VBoxGuest-win.cpp revision cba644d3694119a648f130178a8d84d70ba3f88d
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VBoxGuest - Windows specifics.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Copyright (C) 2010-2013 Oracle Corporation
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * available from http://www.virtualbox.org. This file is free software;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * General Public License (GPL) as published by the Free Software
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Header Files *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * on NT4, so... The same for ExAllocatePool.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync* Internal Functions *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtDoTests(void);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Exported Functions *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtScanPCIResourceList)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync/*******************************************************************************
8ad79874169cc981a694a15e8a806b9a39133673vboxsync* Global Variables *
8ad79874169cc981a694a15e8a806b9a39133673vboxsync*******************************************************************************/
8ad79874169cc981a694a15e8a806b9a39133673vboxsync/** The detected NT (windows) version. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Driver entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns appropriate status code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Pointer to driver object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pRegPath Registry base path.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry. Driver built: %s %s\n", __DATE__, __TIME__));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Check if the the NT version is supported and initializing
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * g_enmVbgdNtVer in the process.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync BOOLEAN fCheckedBuild = PsGetVersion(&ulMajorVer, &ulMinorVer, &ulBuildNo, NULL);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::DriverEntry: Running on Windows NT version %u.%u, build %u\n", ulMajorVer, ulMinorVer, ulBuildNo));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: Running on a Windows checked build (debug)!\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 6: /* Windows Vista or Windows 7 (based on minor ver) */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0: /* Note: Also could be Windows 2008 Server! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 1: /* Note: Also could be Windows 2008 Server R2! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", ulMajorVer, ulMinorVer));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", ulMajorVer, ulMinorVer));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::DriverEntry: At least Windows NT4 required! (%u.%u)\n", ulMajorVer, ulMinorVer));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::DriverEntry: Too new version %u.%u!\n", ulMajorVer, ulMinorVer));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the driver entry points in pDrvObj.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = vbgdNtCreate;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vbgdNtClose;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vbgdNtIOCtl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vbgdNtInternalIOCtl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vbgdNtShutdown;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = vbgdNtNotSupportedStub;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = vbgdNtNotSupportedStub;
91fdb167bd5c9417d9507c1317ae121864fdc9cbvboxsync rc = vbgdNt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_POWER] = vbgdNtPower;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vbgdNtSystemControl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vbgdNtAddDevice;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry returning %#x\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Handle request from the Plug & Play subsystem.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Driver object
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create device.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create symbolic link (DOS devices).
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the device extension.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeInitializeSpinLock(&pDevExt->MouseEventAccessLock);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * If we reached this point we're fine with the basic driver setup,
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * so continue to init our own things.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync vbgdNtBugCheckCallback(pDevExt); /* Ignore failure! */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* Driver is ready now. */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync Log(("VBoxGuest::vbgdNtGuestAddDevice: returning with rc = 0x%x (success)\n", rc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* bail out */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestAddDevice: returning with rc = 0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Debug helper to dump a device resource list.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pResourceList list of device resources.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList)
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource = pResourceList->PartialDescriptors;
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync for (ULONG i = 0; i < cResources; ++i, ++pResource)
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync static char const * const s_apszName[] =
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeNull",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypePort",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeInterrupt",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeMemory",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDma",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDeviceSpecific",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeBusNumber",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDevicePrivate",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeAssignedResource",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeSubAllocateFrom",
2b9f3669ba8ae44c1791107537a3b5995aee29a3vboxsync Log(("VBoxGuest::vbgdNtShowDeviceResources: Type %s",
2b9f3669ba8ae44c1791107537a3b5995aee29a3vboxsync uType < RT_ELEMENTS(s_apszName) ? s_apszName[uType] : "Unknown"));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtShowDeviceResources: Start %8X%8.8lX length %X\n",
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync pResource->u.Port.Start.HighPart, pResource->u.Port.Start.LowPart,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtShowDeviceResources: Level %X, Vector %X, Affinity %X\n",
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync pResource->u.Interrupt.Level, pResource->u.Interrupt.Vector,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtShowDeviceResources: Channel %d, Port %X\n",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Global initialisation stuff (PnP + NT4 legacy).
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pDevObj Device object.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pIrp Request packet.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Let's have a look at what our PCI adapter offers.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Starting to scan PCI resources of VBoxGuest ...\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Assign the PCI resources. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter");
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = HalAssignSlotResources(pRegPath, &classNameString,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtShowDeviceResources(&pResourceList->List[0].PartialResourceList);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync rc = vbgdNtScanPCIResourceList(pResourceList, pDevExt);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync rc = vbgdNtScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated, pDevExt);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Map physical address of VMMDev memory into MMIO region
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * and init the common device extension bits.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.pVMMDevMemory = (VMMDevMemory *)pvMMIOBase;
2b9f3669ba8ae44c1791107537a3b5995aee29a3vboxsync Log(("VBoxGuest::vbgdNtInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->Core.pVMMDevMemory = 0x%p\n",
2b9f3669ba8ae44c1791107537a3b5995aee29a3vboxsync pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Could not init device extension, rc = %Rrc!\n", vrc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Register DPC and ISR.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Initializing DPC/ISR ...\n"));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync IoInitializeDpcRequest(pDevExt->pDeviceObject, vbgdNtDpcHandler);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Get an interrupt vector. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Only proceed if the device provides an interrupt. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Getting interrupt vector (HAL): Bus: %u, IRQL: %u, Vector: %u\n",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->busNumber, pDevExt->interruptLevel, pDevExt->interruptVector));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: HalGetInterruptVector returns vector %u\n", uInterruptVector));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: No interrupt vector found!\n"));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Device does not provide an interrupt!\n"));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Connecting interrupt ...\n"));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync rc = IoConnectInterrupt(&pDevExt->pInterruptObject, /* Out: interrupt object. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (PKSERVICE_ROUTINE)vbgdNtIsrHandler, /* Our ISR handler. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptMode, /* LevelSensitive or Latched. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Could not connect interrupt, rc = 0x%x\n", rc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: No interrupt vector found!\n"));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Allocating kernel session data ...\n"));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync int vrc = VBoxGuestCreateKernelSession(&pDevExt->Core, &pDevExt->pKernelSession);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Failed to allocated kernel session data! rc = %Rrc\n", rc));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync NTSTATUS rcNt = vbgdNtRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled", &ulValue);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync Log(("Logging to release log enabled (0x%x)", ulValue));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Ready to rumble! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Device is ready!\n"));
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /** @todo r=bird: The error cleanup here is completely missing. We'll leak a
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * whole bunch of things... */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtInit: Returned with rc = 0x%x\n", rc));
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Cleans up hardware resources.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Do not delete DevExt here.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * @param pDrvObj Driver object.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
92de700c41f3803fd020736400a84b4105590eb6vboxsync#if 0 /* @todo: test & enable cleaning global session data */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync VBoxGuestCloseSession(pDevExt, pDevExt->pKernelSession);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync /** @todo: cleanup the rest stuff */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* According to MSDN we have to unmap previously mapped memory. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Unload the driver.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Driver object.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync /* Destroy device extension and clean up everything else. */
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync VBoxGuestDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * I don't think it's possible to unload a driver which processes have
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * opened, at least we'll blindly assume that here.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync#else /* !TARGET_NT4 */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* On a PnP driver this routine will be called after
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * IRP_MN_REMOVE_DEVICE (where we already did the cleanup),
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * so don't do anything here (yet). */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync#endif /* !TARGET_NT4 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestUnload: returning\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create (i.e. Open) file entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pIrp); */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pStack); */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Log(("VBoxGuest::vbgdNtGuestCreate: device is not working currently: %d!\n", pDevExt->devState));
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync else if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * We are not remotely similar to a directory...
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * (But this is possible.)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestCreate: Uhm, we're not a directory!\n"));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestCreate: File object type = %d\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create a session object if we have a valid file object. This session object
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * exists for every R3 process.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync vrc = VBoxGuestCreateUserSession(&pDevExt->Core, &pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* ... otherwise we've been called from R0! */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync vrc = VBoxGuestCreateKernelSession(&pDevExt->Core, &pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Complete the request! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestCreate: Returning 0x%x\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Close file entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestClose: pDevExt=0x%p pFileObj=0x%p FsContext=0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Close both, R0 and R3 sessions. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Device I/O Control entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* All requests are buffered. */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync size_t cbData = pStack->Parameters.DeviceIoControl.InputBufferLength;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Do we have a file object associated?*/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pFileObj) /* ... then we might have a session object as well! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtIOCtl: uCmd=%u, pDevExt=0x%p, pSession=0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* We don't have a session associated with the file object? So this seems
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * to be a kernel call then. */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync /** @todo r=bird: What on earth is this supposed to be? Each kernel session
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * shall have its own context of course, no hacks, pleeease. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtIOCtl: Using kernel session data ...\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * First process Windows specific stuff which cannot be handled
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * by the common code used on all other platforms. In the default case
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * we then finally handle the common cases.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync LogRel(("VBoxGuest::vbgdNtIOCtl: ENABLE_VRDP_SESSION: Currently: %sabled\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync LogRel(("VBoxGuest::vbgdNtIOCtl: ENABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->ulOldActiveConsoleId = pSharedUserData->ActiveConsoleId;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync LogRel(("VBoxGuest::vbgdNtIOCtl: DISABLE_VRDP_SESSION: Currently: %sabled\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtIOCtl: DISABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSharedUserData->ActiveConsoleId = pDevExt->ulOldActiveConsoleId;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Add at least one (bogus) fall through case to shut up MSVC! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Process the common IOCtls.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync int vrc = VBoxGuestCommonIOCtl(uCmd, &pDevExt->Core, pSession, pBuf, cbData, &cbDataReturned);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestDeviceControl: rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestDeviceControl: Too much output data %u - expected %u!\n", cbDataReturned, cbData));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync //Log(("VBoxGuest::vbgdNtGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status));
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * Internal Device I/O Control entry point.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pDevObj Device object.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pIrp Request packet.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync bool fProcessed = false;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned Info = 0;
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync * Override common behavior of some operations.
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync /** @todo r=bird: Better to add dedicated worker functions for this! */
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync size_t cbData = (size_t)pStack->Parameters.Others.Argument2;
2906c2554adf12dac04c4bdd7e44ec9f960f0390vboxsync if (cbData != sizeof(VBoxGuestMouseSetNotifyCallback))
2906c2554adf12dac04c4bdd7e44ec9f960f0390vboxsync VBoxGuestMouseSetNotifyCallback *pInfo = (VBoxGuestMouseSetNotifyCallback*)pvBuf;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* we need a lock here to avoid concurrency with the set event functionality */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeAcquireSpinLock(&pDevExt->MouseEventAccessLock, &OldIrql);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeReleaseSpinLock(&pDevExt->MouseEventAccessLock, OldIrql);
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync * No override, go to common code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IRP_MJ_SYSTEM_CONTROL handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Always pass it on to the next driver. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync return IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IRP_MJ_SHUTDOWN handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pReq->header.requestType = VMMDevReq_SetPowerStatus;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestShutdown: Error performing request to VMMDev! "
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Stub function for functions we don't implemented.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns STATUS_NOT_SUPPORTED
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ce95f18112057771f68abe58df709edd7c467db1vboxsync * DPC handler.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDPC DPC descriptor.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pIrp Interrupt request packet.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pContext Context specific pointer.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncvoid vbgdNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestDpcHandler: pDevExt=0x%p\n", pDevExt));
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* test & reset the counter */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (ASMAtomicXchgU32(&pDevExt->Core.u32MousePosChangedSeq, 0))
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* we need a lock here to avoid concurrency with the set event ioctl handler thread,
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * i.e. to prevent the event from destroyed while we're using it */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeAcquireSpinLockAtDpcLevel(&pDevExt->MouseEventAccessLock);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.MouseNotifyCallback.pfnNotify(pDevExt->Core.MouseNotifyCallback.pvUser);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeReleaseSpinLockFromDpcLevel(&pDevExt->MouseEventAccessLock);
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* Process the wake-up list we were asked by the scheduling a DPC
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * in vbgdNtIsrHandler(). */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * ISR handler.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @return BOOLEAN Indicates whether the IRQ came from us (TRUE) or not (FALSE).
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pInterrupt Interrupt that was triggered.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pServiceContext Context specific pointer.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncBOOLEAN vbgdNtIsrHandler(PKINTERRUPT pInterrupt, PVOID pServiceContext)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pServiceContext;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync /*Log(("VBoxGuest::vbgdNtGuestIsrHandler: pDevExt = 0x%p, pVMMDevMemory = 0x%p\n",
5ea88591f1ca09476c7e97c758f9c52e1dbb6626vboxsync pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));*/
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* Enter the common ISR routine and do the actual work. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync BOOLEAN fIRQTaken = VBoxGuestCommonISR(&pDevExt->Core);
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* If we need to wake up some events we do that in a DPC to make
ce95f18112057771f68abe58df709edd7c467db1vboxsync * sure we're called at the right IRQL. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestIsrHandler: IRQ was taken! pInterrupt = 0x%p, pDevExt = 0x%p\n",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (ASMAtomicUoReadU32(&pDevExt->Core.u32MousePosChangedSeq) || !RTListIsEmpty(&pDevExt->Core.WakeUpList))
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtGuestIsrHandler: Requesting DPC ...\n"));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * Overridden routine for mouse polling events.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension structure.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncvoid VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* nothing to do here - i.e. since we can not KeSetEvent from ISR level,
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * we rely on the pDevExt->u32MousePosChangedSeq to be set to a non-zero value on a mouse event
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * and queue the DPC in our ISR routine in that case doing KeSetEvent from the DPC routine */
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * Queries (gets) a DWORD value from the registry.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @return NTSTATUS
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param ulRoot Relative path root. See RTL_REGISTRY_SERVICES or RTL_REGISTRY_ABSOLUTE.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param pwszPath Path inside path root.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param pwszName Actual value name to look up.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param puValue On input this can specify the default value (if RTL_REGISTRY_OPTIONAL is
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * not specified in ulRoot), on output this will retrieve the looked up
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * registry value if found.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue)
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync /** @todo Add RTL_QUERY_REGISTRY_TYPECHECK! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Helper to scan the PCI resource list and remember stuff.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pResList Resource list
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncNTSTATUS vbgdNtScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXTWIN pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Enumerate the resource list. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Found %d resources\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->pciBaseAddress;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Overflow protection. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: I/O range: Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save the IO port base. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /** @todo Not so good.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * Update/bird: What is not so good? That we just consider the last range? */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save resource information. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeStart = pPartialData->u.Port.Start;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeLength = pPartialData->u.Port.Length;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: I/O range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Interrupt: Level = %x, Vector = %x, Mode = %x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save information. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptLevel = pPartialData->u.Interrupt.Level;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptVector = pPartialData->u.Interrupt.Vector;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptAffinity = pPartialData->u.Interrupt.Affinity;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check interrupt mode. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Overflow protection. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Memory range: Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* We only care about read/write memory. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo Reconsider memory type. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if ( cMMIORange == 0 /* Only care about the first MMIO range (!!!). */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync && (pPartialData->Flags & VBOX_CM_PRE_VISTA_MASK) == CM_RESOURCE_MEMORY_READ_WRITE)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save physical MMIO base + length for VMMDev. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryLength = (ULONG)pPartialData->u.Memory.Length;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save resource information. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeStart = pPartialData->u.Memory.Start;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeLength = pPartialData->u.Memory.Length;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Ignoring memory: Flags = %08x\n",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtScanPCIResourceList: Unhandled resource found, type = %d\n", pPartialData->Type));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Memorize the number of resources found. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Maps the I/O space from VMMDev to virtual kernel address space.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @return NTSTATUS
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDevExt The device extension.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param PhysAddr Physical address to map.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param cbToMap Number of bytes to map.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param ppvMMIOBase Pointer of mapped I/O base.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pcbMMIO Length of mapped I/O base.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsyncNTSTATUS vbgdNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* pcbMMIO is optional. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync if (PhysAddr.LowPart > 0) /* We're mapping below 4GB. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(PhysAddr, cbToMap, MmNonCached);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtMapVMMDevMemory: pVMMDevMemory = 0x%x\n", pVMMDevMemory));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtMapVMMDevMemory: VMMDevMemory: Version = 0x%x, Size = %d\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pVMMDevMemory->u32Version, pVMMDevMemory->u32Size));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check version of the structure; do we have the right memory version? */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync if (pVMMDevMemory->u32Version == VMMDEV_MEMORY_VERSION)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save results. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Log(("VBoxGuest::vbgdNtMapVMMDevMemory: VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n",
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /* Not our version, refuse operation and unmap the memory. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync Log(("VBoxGuest::vbgdNtMapVMMDevMemory: Wrong version (%u), refusing operation!\n", pVMMDevMemory->u32Version));
ce95f18112057771f68abe58df709edd7c467db1vboxsync * Unmaps the VMMDev I/O range from kernel space.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDevExt The device extension.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncvoid vbgdNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Log(("VBoxGuest::vbgdNtUnmapVMMDevMemory: pVMMDevMemory = 0x%x\n", pDevExt->Core.pVMMDevMemory));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->vmmDevPhysMemoryLength);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncVBOXOSTYPE vbgdNtVersionToOSType(VBGDNTVER enmNtVer)
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync /* We don't know, therefore NT family. */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * A quick implementation of AtomicTestAndClear for uint32_t and multiple bits.
ce95f18112057771f68abe58df709edd7c467db1vboxsyncstatic uint32_t vboxugestwinAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32Mask)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(uint32_t *)pu32Bits, u32Mask));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync int iBitOffset = ASMBitFirstSetU32 (u32WorkingMask);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync bool fSet = ASMAtomicBitTestAndClear(pu32Bits, iBitOffset - 1);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits, uint32_t u32Exp)
ce95f18112057771f68abe58df709edd7c467db1vboxsync uint32_t u32Result = vboxugestwinAtomicBitsTestAndClear(&u32Bits2, u32Mask);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync AssertLogRelMsgFailed(("%s: TEST FAILED: u32Mask=0x%x, u32Bits (before)=0x%x, u32Bits (after)=0x%x, u32Result=0x%x, u32Exp=ox%x\n",
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtDoTests(void)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x00, 0x23, 0);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x22, 0);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync#endif /* DEBUG */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * DPC latency checker.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * One DPC latency sample.
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsynctypedef struct DPCSAMPLE
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * The DPC latency measurement workset.
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsynctypedef struct DPCDATA
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync bool volatile fFinished;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /** The timer interval (relative). */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /** Align the sample array on a 64 byte boundrary just for the off chance
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * that we'll get cache line aligned memory backing this structure. */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncAssertCompileMemberAlignment(DPCDATA, aSamples, 64);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * DPC callback routine for the DPC latency measurement code.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param pDpc The DPC, not used.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param pvDeferredContext Pointer to the DPCDATA.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param SystemArgument1 System use, ignored.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param SystemArgument2 System use, ignored.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncstatic VOID vbgdNtDpcLatencyCallback(PKDPC pDpc, PVOID pvDeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pData->cSamples >= RT_ELEMENTS(pData->aSamples))
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync DPCSAMPLE *pSample = &pData->aSamples[pData->cSamples++];
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pSample->PerfCounter = KeQueryPerformanceCounter(&pSample->PerfFrequency);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pSample->PerfDelta.QuadPart = pSample->PerfCounter.QuadPart - pData->PerfCounterPrev.QuadPart;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pData->PerfCounterPrev.QuadPart = pSample->PerfCounter.QuadPart;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Handles the DPC latency checker request.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @returns VBox status code.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Allocate a block of non paged memory for samples and related data.
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync DPCDATA *pData = (DPCDATA *)ExAllocatePoolWithTag(NonPagedPool, sizeof(DPCDATA), VBOXGUEST_DPC_TAG);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("VBoxGuest: DPC: DPCDATA allocation failed.\n");
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Initialize the data.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync KeInitializeDpc(&pData->Dpc, vbgdNtDpcLatencyCallback, pData);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync pData->ulTimerRes = ExSetTimerResolution(1000 * 10, 1);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync pData->DueTime.QuadPart = -(int64_t)pData->ulTimerRes / 10;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Start the DPC measurements and wait for a full set.
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeDelayExecutionThread(KernelMode, TRUE, &Interval);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Log everything to the host.
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("DPC: ulTimerRes = %d\n", pData->ulTimerRes);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("[%d] pd %lld pc %lld pf %lld t %lld\n",
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */