Changeset 70103 in vbox for trunk/src/VBox/Additions/common/VBoxGuest
- Timestamp:
- Dec 13, 2017 10:09:27 AM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119651
- Location:
- trunk/src/VBox/Additions/common/VBoxGuest
- Files:
-
- 2 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
r70101 r70103 105 105 ifeq ($(KBUILD_TARGET), win) 106 106 VBoxGuest_SOURCES += \ 107 VBoxGuest-$(KBUILD_TARGET)-pnp.cpp \108 107 win/VBoxGuest.rc 109 108 endif -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp
r70101 r70103 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP LOG_GROUP_SUP_DRV 32 #include "VBoxGuest-win.h" 32 #include <iprt/nt/ntddk.h> 33 33 34 #include "VBoxGuestInternal.h" 35 #include <VBox/VBoxGuestLib.h> 36 #include <VBox/log.h> 34 37 35 38 #include <iprt/asm.h> 36 39 #include <iprt/asm-amd64-x86.h> 37 38 #include <VBox/log.h> 39 #include <VBox/VBoxGuestLib.h> 40 #include <iprt/memobj.h> 41 #include <iprt/spinlock.h> 40 42 #include <iprt/string.h> 43 41 44 42 45 … … 47 50 # define PCI_MAX_BUSES 256 48 51 #endif 52 53 /** CM_RESOURCE_MEMORY_* flags which were used on XP or earlier. */ 54 #define VBOX_CM_PRE_VISTA_MASK (0x3f) 55 56 57 #define VBOXGUEST_UPDATE_DEVSTATE(a_pDevExt, a_enmNewDevState) \ 58 do { \ 59 (a_pDevExt)->enmPrevDevState = (a_pDevExt)->enmDevState; \ 60 (a_pDevExt)->enmDevState = (a_enmNewDevState); \ 61 } while (0) 62 63 64 /********************************************************************************************************************************* 65 * Structures and Typedefs * 66 *********************************************************************************************************************************/ 67 /** Possible device states for our state machine. */ 68 typedef enum VGDRVNTDEVSTATE 69 { 70 VGDRVNTDEVSTATE_STOPPED, 71 VGDRVNTDEVSTATE_WORKING, 72 VGDRVNTDEVSTATE_PENDINGSTOP, 73 VGDRVNTDEVSTATE_PENDINGREMOVE, 74 VGDRVNTDEVSTATE_SURPRISEREMOVED, 75 VGDRVNTDEVSTATE_REMOVED 76 } VGDRVNTDEVSTATE; 77 78 typedef struct VBOXGUESTWINBASEADDRESS 79 { 80 /** Original device physical address. */ 81 PHYSICAL_ADDRESS RangeStart; 82 /** Length of I/O or memory range. */ 83 ULONG RangeLength; 84 /** Flag: Unmapped range is I/O or memory range. */ 85 BOOLEAN RangeInMemory; 86 /** Mapped I/O or memory range. */ 87 PVOID MappedRangeStart; 88 /** Flag: mapped range is I/O or memory range. */ 89 BOOLEAN MappedRangeInMemory; 90 /** Flag: resource is mapped (i.e. MmMapIoSpace called). */ 91 BOOLEAN ResourceMapped; 92 } VBOXGUESTWINBASEADDRESS, *PVBOXGUESTWINBASEADDRESS; 93 94 95 /** Windows-specific device extension bits. */ 96 typedef struct VBOXGUESTDEVEXTWIN 97 { 98 VBOXGUESTDEVEXT Core; 99 100 /** Our functional driver object. */ 101 PDEVICE_OBJECT pDeviceObject; 102 /** Top of the stack. */ 103 PDEVICE_OBJECT pNextLowerDriver; 104 /** Currently active Irp. */ 105 IRP *pCurrentIrp; 106 /** Interrupt object pointer. */ 107 PKINTERRUPT pInterruptObject; 108 109 /** Bus number where the device is located. */ 110 ULONG busNumber; 111 /** Slot number where the device is located. */ 112 ULONG slotNumber; 113 /** Device interrupt level. */ 114 ULONG interruptLevel; 115 /** Device interrupt vector. */ 116 ULONG interruptVector; 117 /** Affinity mask. */ 118 KAFFINITY interruptAffinity; 119 /** LevelSensitive or Latched. */ 120 KINTERRUPT_MODE interruptMode; 121 122 /** PCI base address information. */ 123 ULONG pciAddressCount; 124 VBOXGUESTWINBASEADDRESS pciBaseAddress[PCI_TYPE0_ADDRESSES]; 125 126 /** Physical address and length of VMMDev memory. */ 127 PHYSICAL_ADDRESS vmmDevPhysMemoryAddress; 128 ULONG vmmDevPhysMemoryLength; 129 130 /** Device state. */ 131 VGDRVNTDEVSTATE enmDevState; 132 /** The previous device state. */ 133 VGDRVNTDEVSTATE enmPrevDevState; 134 135 /** Last system power action set (see VBoxGuestPower). */ 136 POWER_ACTION LastSystemPowerAction; 137 /** Preallocated generic request for shutdown. */ 138 VMMDevPowerStateRequest *pPowerStateRequest; 139 /** Preallocated VMMDevEvents for IRQ handler. */ 140 VMMDevEvents *pIrqAckEvents; 141 142 /** Pre-allocated kernel session data. This is needed 143 * for handling kernel IOCtls. */ 144 struct VBOXGUESTSESSION *pKernelSession; 145 146 /** Spinlock protecting MouseNotifyCallback. Required since the consumer is 147 * in a DPC callback and not the ISR. */ 148 KSPIN_LOCK MouseEventAccessLock; 149 } VBOXGUESTDEVEXTWIN, *PVBOXGUESTDEVEXTWIN; 150 151 152 /** NT (windows) version identifier. */ 153 typedef enum VGDRVNTVER 154 { 155 VGDRVNTVER_INVALID = 0, 156 VGDRVNTVER_WINNT4, 157 VGDRVNTVER_WIN2K, 158 VGDRVNTVER_WINXP, 159 VGDRVNTVER_WIN2K3, 160 VGDRVNTVER_WINVISTA, 161 VGDRVNTVER_WIN7, 162 VGDRVNTVER_WIN8, 163 VGDRVNTVER_WIN81, 164 VGDRVNTVER_WIN10 165 } VGDRVNTVER; 166 extern VGDRVNTVER g_enmVGDrvNtVer; 49 167 50 168 … … 57 175 static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath); 58 176 #else 59 static NTSTATUS vgdrvNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj); 60 #endif 177 static NTSTATUS vgdrvNtNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj); 178 static NTSTATUS vgdrvNtNt5PlusPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp); 179 static NTSTATUS vgdrvNtNt5PlusPower(PDEVICE_OBJECT pDevObj, PIRP pIrp); 180 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); 181 #endif 182 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt); 183 static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj); 61 184 static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj); 62 185 static NTSTATUS vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); … … 66 189 static NTSTATUS vgdrvNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp); 67 190 static void vgdrvNtReadConfiguration(PVBOXGUESTDEVEXTWIN pDevExt); 68 #ifndef TARGET_NT469 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);70 #endif71 191 static NTSTATUS vgdrvNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp); 72 192 static NTSTATUS vgdrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp); … … 224 344 rc = vgdrvNt4CreateDevice(pDrvObj, pRegPath); 225 345 #else 226 pDrvObj->MajorFunction[IRP_MJ_PNP] = vgdrvNt PnP;227 pDrvObj->MajorFunction[IRP_MJ_POWER] = vgdrvNt Power;346 pDrvObj->MajorFunction[IRP_MJ_PNP] = vgdrvNtNt5PlusPnP; 347 pDrvObj->MajorFunction[IRP_MJ_POWER] = vgdrvNtNt5PlusPower; 228 348 pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vgdrvNtNt5PlusSystemControl; 229 pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vgdrvNt 5PlusAddDevice;349 pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vgdrvNtNt5PlusAddDevice; 230 350 #endif 231 351 } … … 236 356 237 357 238 #ifdef TARGET_NT4 239 240 /** 241 * Legacy helper function to create the device object. 242 * 243 * @returns NT status code. 244 * 245 * @param pDrvObj The driver object. 246 * @param pRegPath The driver registry path. 247 */ 248 static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) 249 { 250 Log(("vgdrvNt4CreateDevice: pDrvObj=%p, pRegPath=%p\n", pDrvObj, pRegPath)); 251 252 /* 253 * Find our virtual PCI device 254 */ 255 ULONG uBusNumber; 256 PCI_SLOT_NUMBER SlotNumber; 257 NTSTATUS rc = vgdrvNt4FindPciDevice(&uBusNumber, &SlotNumber); 258 if (NT_ERROR(rc)) 259 { 260 Log(("vgdrvNt4CreateDevice: Device not found!\n")); 261 return rc; 262 } 263 264 /* 265 * Create device. 266 */ 267 UNICODE_STRING szDevName; 268 RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT); 269 PDEVICE_OBJECT pDeviceObject = NULL; 270 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); 271 if (NT_SUCCESS(rc)) 272 { 273 Log(("vgdrvNt4CreateDevice: Device created\n")); 274 275 UNICODE_STRING DosName; 276 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 277 rc = IoCreateSymbolicLink(&DosName, &szDevName); 278 if (NT_SUCCESS(rc)) 279 { 280 Log(("vgdrvNt4CreateDevice: Symlink created\n")); 281 282 /* 283 * Setup the device extension. 284 */ 285 Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n")); 286 287 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; 288 RT_ZERO(*pDevExt); 289 290 Log(("vgdrvNt4CreateDevice: Device extension created\n")); 291 292 /* Store a reference to ourself. */ 293 pDevExt->pDeviceObject = pDeviceObject; 294 295 /* Store bus and slot number we've queried before. */ 296 pDevExt->busNumber = uBusNumber; 297 pDevExt->slotNumber = SlotNumber.u.AsULONG; 298 299 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 300 rc = hlpRegisterBugCheckCallback(pDevExt); 301 #endif 302 303 /* Do the actual VBox init ... */ 304 if (NT_SUCCESS(rc)) 305 { 306 rc = vgdrvNtInit(pDrvObj, pDeviceObject, pRegPath); 307 if (NT_SUCCESS(rc)) 308 { 309 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); 310 return rc; 311 } 312 313 /* bail out */ 314 } 315 IoDeleteSymbolicLink(&DosName); 316 } 317 else 318 Log(("vgdrvNt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc)); 319 IoDeleteDevice(pDeviceObject); 320 } 321 else 322 Log(("vgdrvNt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc)); 323 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x\n", rc)); 324 return rc; 325 } 326 327 328 /** 329 * Helper function to handle the PCI device lookup. 330 * 331 * @returns NT status code. 332 * 333 * @param pulBusNumber Where to return the bus number on success. 334 * @param pSlotNumber Where to return the slot number on success. 335 */ 336 static NTSTATUS vgdrvNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber) 337 { 338 Log(("vgdrvNt4FindPciDevice\n")); 339 340 PCI_SLOT_NUMBER SlotNumber; 341 SlotNumber.u.AsULONG = 0; 342 343 /* Scan each bus. */ 344 for (ULONG ulBusNumber = 0; ulBusNumber < PCI_MAX_BUSES; ulBusNumber++) 345 { 346 /* Scan each device. */ 347 for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++) 348 { 349 SlotNumber.u.bits.DeviceNumber = deviceNumber; 350 351 /* Scan each function (not really required...). */ 352 for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++) 353 { 354 SlotNumber.u.bits.FunctionNumber = functionNumber; 355 356 /* Have a look at what's in this slot. */ 357 PCI_COMMON_CONFIG PciData; 358 if (!HalGetBusData(PCIConfiguration, ulBusNumber, SlotNumber.u.AsULONG, &PciData, sizeof(ULONG))) 359 { 360 /* No such bus, we're done with it. */ 361 deviceNumber = PCI_MAX_DEVICES; 362 break; 363 } 364 365 if (PciData.VendorID == PCI_INVALID_VENDORID) 366 /* We have to proceed to the next function. */ 367 continue; 368 369 /* Check if it's another device. */ 370 if ( PciData.VendorID != VMMDEV_VENDORID 371 || PciData.DeviceID != VMMDEV_DEVICEID) 372 continue; 373 374 /* Hooray, we've found it! */ 375 Log(("vgdrvNt4FindPciDevice: Device found!\n")); 376 377 *pulBusNumber = ulBusNumber; 378 *pSlotNumber = SlotNumber; 379 return STATUS_SUCCESS; 380 } 381 } 382 } 383 384 return STATUS_DEVICE_DOES_NOT_EXIST; 385 } 386 387 #else /* !TARGET_NT4 */ 388 389 /** 390 * Handle request from the Plug & Play subsystem. 391 * 392 * @returns NT status code 393 * @param pDrvObj Driver object 394 * @param pDevObj Device object 395 * 396 * @remarks Parts of this is duplicated in VBoxGuest-win-legacy.cpp. 397 */ 398 static NTSTATUS vgdrvNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj) 399 { 400 NTSTATUS rc; 401 LogFlowFuncEnter(); 402 403 /* 404 * Create device. 405 */ 406 UNICODE_STRING DevName; 407 RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT); 408 PDEVICE_OBJECT pDeviceObject = NULL; 409 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); 410 if (NT_SUCCESS(rc)) 411 { 412 /* 413 * Create symbolic link (DOS devices). 414 */ 415 UNICODE_STRING DosName; 416 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 417 rc = IoCreateSymbolicLink(&DosName, &DevName); 418 if (NT_SUCCESS(rc)) 419 { 420 /* 421 * Setup the device extension. 422 */ 423 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; 424 RT_ZERO(*pDevExt); 425 426 KeInitializeSpinLock(&pDevExt->MouseEventAccessLock); 427 428 pDevExt->pDeviceObject = pDeviceObject; 429 pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED; 430 pDevExt->enmDevState = VGDRVNTDEVSTATE_STOPPED; 431 432 pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); 433 if (pDevExt->pNextLowerDriver != NULL) 434 { 435 /* 436 * If we reached this point we're fine with the basic driver setup, 437 * so continue to init our own things. 438 */ 439 # ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 440 vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */ 441 # endif 442 if (NT_SUCCESS(rc)) 443 { 444 /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */ 445 pDeviceObject->Flags |= DO_POWER_PAGABLE; 446 447 /* Driver is ready now. */ 448 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 449 LogFlowFunc(("Returning with rc=%#x (success)\n", rc)); 450 return rc; 451 } 452 453 IoDetachDevice(pDevExt->pNextLowerDriver); 454 } 455 else 456 { 457 LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); 458 rc = STATUS_DEVICE_NOT_CONNECTED; 459 } 460 461 /* bail out */ 462 IoDeleteSymbolicLink(&DosName); 463 } 464 else 465 LogFunc(("IoCreateSymbolicLink failed with rc=%#x!\n", rc)); 466 IoDeleteDevice(pDeviceObject); 467 } 468 else 469 LogFunc(("IoCreateDevice failed with rc=%#x!\n", rc)); 470 471 LogFunc(("Returning with rc=%#x\n", rc)); 472 return rc; 473 } 474 475 #endif /* !TARGET_NT4 */ 358 /** 359 * Translates NT version to VBox OS. 360 * 361 * @returns VBox OS type. 362 * @param enmNtVer The NT version. 363 */ 364 static VBOXOSTYPE vgdrvNtVersionToOSType(VGDRVNTVER enmNtVer) 365 { 366 VBOXOSTYPE enmOsType; 367 switch (enmNtVer) 368 { 369 case VGDRVNTVER_WINNT4: 370 enmOsType = VBOXOSTYPE_WinNT4; 371 break; 372 373 case VGDRVNTVER_WIN2K: 374 enmOsType = VBOXOSTYPE_Win2k; 375 break; 376 377 case VGDRVNTVER_WINXP: 378 #if ARCH_BITS == 64 379 enmOsType = VBOXOSTYPE_WinXP_x64; 380 #else 381 enmOsType = VBOXOSTYPE_WinXP; 382 #endif 383 break; 384 385 case VGDRVNTVER_WIN2K3: 386 #if ARCH_BITS == 64 387 enmOsType = VBOXOSTYPE_Win2k3_x64; 388 #else 389 enmOsType = VBOXOSTYPE_Win2k3; 390 #endif 391 break; 392 393 case VGDRVNTVER_WINVISTA: 394 #if ARCH_BITS == 64 395 enmOsType = VBOXOSTYPE_WinVista_x64; 396 #else 397 enmOsType = VBOXOSTYPE_WinVista; 398 #endif 399 break; 400 401 case VGDRVNTVER_WIN7: 402 #if ARCH_BITS == 64 403 enmOsType = VBOXOSTYPE_Win7_x64; 404 #else 405 enmOsType = VBOXOSTYPE_Win7; 406 #endif 407 break; 408 409 case VGDRVNTVER_WIN8: 410 #if ARCH_BITS == 64 411 enmOsType = VBOXOSTYPE_Win8_x64; 412 #else 413 enmOsType = VBOXOSTYPE_Win8; 414 #endif 415 break; 416 417 case VGDRVNTVER_WIN81: 418 #if ARCH_BITS == 64 419 enmOsType = VBOXOSTYPE_Win81_x64; 420 #else 421 enmOsType = VBOXOSTYPE_Win81; 422 #endif 423 break; 424 425 case VGDRVNTVER_WIN10: 426 #if ARCH_BITS == 64 427 enmOsType = VBOXOSTYPE_Win10_x64; 428 #else 429 enmOsType = VBOXOSTYPE_Win10; 430 #endif 431 break; 432 433 default: 434 /* We don't know, therefore NT family. */ 435 enmOsType = VBOXOSTYPE_WinNT; 436 break; 437 } 438 return enmOsType; 439 } 476 440 477 441 … … 539 503 */ 540 504 #ifndef TARGET_NT4 541 NTSTATUS vgdrvNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)505 static NTSTATUS vgdrvNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp) 542 506 #else 543 NTSTATUS vgdrvNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)507 static NTSTATUS vgdrvNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) 544 508 #endif 545 509 { … … 711 675 712 676 677 678 679 #ifdef TARGET_NT4 680 681 /** 682 * Legacy helper function to create the device object. 683 * 684 * @returns NT status code. 685 * 686 * @param pDrvObj The driver object. 687 * @param pRegPath The driver registry path. 688 */ 689 static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) 690 { 691 Log(("vgdrvNt4CreateDevice: pDrvObj=%p, pRegPath=%p\n", pDrvObj, pRegPath)); 692 693 /* 694 * Find our virtual PCI device 695 */ 696 ULONG uBusNumber; 697 PCI_SLOT_NUMBER SlotNumber; 698 NTSTATUS rc = vgdrvNt4FindPciDevice(&uBusNumber, &SlotNumber); 699 if (NT_ERROR(rc)) 700 { 701 Log(("vgdrvNt4CreateDevice: Device not found!\n")); 702 return rc; 703 } 704 705 /* 706 * Create device. 707 */ 708 UNICODE_STRING szDevName; 709 RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT); 710 PDEVICE_OBJECT pDeviceObject = NULL; 711 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); 712 if (NT_SUCCESS(rc)) 713 { 714 Log(("vgdrvNt4CreateDevice: Device created\n")); 715 716 UNICODE_STRING DosName; 717 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 718 rc = IoCreateSymbolicLink(&DosName, &szDevName); 719 if (NT_SUCCESS(rc)) 720 { 721 Log(("vgdrvNt4CreateDevice: Symlink created\n")); 722 723 /* 724 * Setup the device extension. 725 */ 726 Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n")); 727 728 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; 729 RT_ZERO(*pDevExt); 730 731 Log(("vgdrvNt4CreateDevice: Device extension created\n")); 732 733 /* Store a reference to ourself. */ 734 pDevExt->pDeviceObject = pDeviceObject; 735 736 /* Store bus and slot number we've queried before. */ 737 pDevExt->busNumber = uBusNumber; 738 pDevExt->slotNumber = SlotNumber.u.AsULONG; 739 740 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 741 rc = hlpRegisterBugCheckCallback(pDevExt); 742 #endif 743 744 /* Do the actual VBox init ... */ 745 if (NT_SUCCESS(rc)) 746 { 747 rc = vgdrvNtInit(pDrvObj, pDeviceObject, pRegPath); 748 if (NT_SUCCESS(rc)) 749 { 750 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); 751 return rc; 752 } 753 754 /* bail out */ 755 } 756 IoDeleteSymbolicLink(&DosName); 757 } 758 else 759 Log(("vgdrvNt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc)); 760 IoDeleteDevice(pDeviceObject); 761 } 762 else 763 Log(("vgdrvNt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc)); 764 Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x\n", rc)); 765 return rc; 766 } 767 768 769 /** 770 * Helper function to handle the PCI device lookup. 771 * 772 * @returns NT status code. 773 * 774 * @param pulBusNumber Where to return the bus number on success. 775 * @param pSlotNumber Where to return the slot number on success. 776 */ 777 static NTSTATUS vgdrvNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber) 778 { 779 Log(("vgdrvNt4FindPciDevice\n")); 780 781 PCI_SLOT_NUMBER SlotNumber; 782 SlotNumber.u.AsULONG = 0; 783 784 /* Scan each bus. */ 785 for (ULONG ulBusNumber = 0; ulBusNumber < PCI_MAX_BUSES; ulBusNumber++) 786 { 787 /* Scan each device. */ 788 for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++) 789 { 790 SlotNumber.u.bits.DeviceNumber = deviceNumber; 791 792 /* Scan each function (not really required...). */ 793 for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++) 794 { 795 SlotNumber.u.bits.FunctionNumber = functionNumber; 796 797 /* Have a look at what's in this slot. */ 798 PCI_COMMON_CONFIG PciData; 799 if (!HalGetBusData(PCIConfiguration, ulBusNumber, SlotNumber.u.AsULONG, &PciData, sizeof(ULONG))) 800 { 801 /* No such bus, we're done with it. */ 802 deviceNumber = PCI_MAX_DEVICES; 803 break; 804 } 805 806 if (PciData.VendorID == PCI_INVALID_VENDORID) 807 /* We have to proceed to the next function. */ 808 continue; 809 810 /* Check if it's another device. */ 811 if ( PciData.VendorID != VMMDEV_VENDORID 812 || PciData.DeviceID != VMMDEV_DEVICEID) 813 continue; 814 815 /* Hooray, we've found it! */ 816 Log(("vgdrvNt4FindPciDevice: Device found!\n")); 817 818 *pulBusNumber = ulBusNumber; 819 *pSlotNumber = SlotNumber; 820 return STATUS_SUCCESS; 821 } 822 } 823 } 824 825 return STATUS_DEVICE_DOES_NOT_EXIST; 826 } 827 828 #else /* !TARGET_NT4 */ 829 830 /** 831 * Handle request from the Plug & Play subsystem. 832 * 833 * @returns NT status code 834 * @param pDrvObj Driver object 835 * @param pDevObj Device object 836 * 837 * @remarks Parts of this is duplicated in VBoxGuest-win-legacy.cpp. 838 */ 839 static NTSTATUS vgdrvNtNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj) 840 { 841 NTSTATUS rc; 842 LogFlowFuncEnter(); 843 844 /* 845 * Create device. 846 */ 847 UNICODE_STRING DevName; 848 RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT); 849 PDEVICE_OBJECT pDeviceObject = NULL; 850 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); 851 if (NT_SUCCESS(rc)) 852 { 853 /* 854 * Create symbolic link (DOS devices). 855 */ 856 UNICODE_STRING DosName; 857 RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); 858 rc = IoCreateSymbolicLink(&DosName, &DevName); 859 if (NT_SUCCESS(rc)) 860 { 861 /* 862 * Setup the device extension. 863 */ 864 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; 865 RT_ZERO(*pDevExt); 866 867 KeInitializeSpinLock(&pDevExt->MouseEventAccessLock); 868 869 pDevExt->pDeviceObject = pDeviceObject; 870 pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED; 871 pDevExt->enmDevState = VGDRVNTDEVSTATE_STOPPED; 872 873 pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); 874 if (pDevExt->pNextLowerDriver != NULL) 875 { 876 /* 877 * If we reached this point we're fine with the basic driver setup, 878 * so continue to init our own things. 879 */ 880 # ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION 881 vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */ 882 # endif 883 if (NT_SUCCESS(rc)) 884 { 885 /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */ 886 pDeviceObject->Flags |= DO_POWER_PAGABLE; 887 888 /* Driver is ready now. */ 889 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 890 LogFlowFunc(("Returning with rc=%#x (success)\n", rc)); 891 return rc; 892 } 893 894 IoDetachDevice(pDevExt->pNextLowerDriver); 895 } 896 else 897 { 898 LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); 899 rc = STATUS_DEVICE_NOT_CONNECTED; 900 } 901 902 /* bail out */ 903 IoDeleteSymbolicLink(&DosName); 904 } 905 else 906 LogFunc(("IoCreateSymbolicLink failed with rc=%#x!\n", rc)); 907 IoDeleteDevice(pDeviceObject); 908 } 909 else 910 LogFunc(("IoCreateDevice failed with rc=%#x!\n", rc)); 911 912 LogFunc(("Returning with rc=%#x\n", rc)); 913 return rc; 914 } 915 916 /** 917 * Irp completion routine for PnP Irps we send. 918 * 919 * @returns NT status code. 920 * @param pDevObj Device object. 921 * @param pIrp Request packet. 922 * @param pEvent Semaphore. 923 */ 924 static NTSTATUS vgdrvNt5PlusPnpIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent) 925 { 926 RT_NOREF2(pDevObj, pIrp); 927 KeSetEvent(pEvent, 0, FALSE); 928 return STATUS_MORE_PROCESSING_REQUIRED; 929 } 930 931 932 /** 933 * Helper to send a PnP IRP and wait until it's done. 934 * 935 * @returns NT status code. 936 * @param pDevObj Device object. 937 * @param pIrp Request packet. 938 * @param fStrict When set, returns an error if the IRP gives an error. 939 */ 940 static NTSTATUS vgdrvNt5PlusPnPSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict) 941 { 942 KEVENT Event; 943 944 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 945 946 IoCopyCurrentIrpStackLocationToNext(pIrp); 947 IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)vgdrvNt5PlusPnpIrpComplete, &Event, TRUE, TRUE, TRUE); 948 949 NTSTATUS rc = IoCallDriver(pDevObj, pIrp); 950 951 if (rc == STATUS_PENDING) 952 { 953 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 954 rc = pIrp->IoStatus.Status; 955 } 956 957 if ( !fStrict 958 && (rc == STATUS_NOT_SUPPORTED || rc == STATUS_INVALID_DEVICE_REQUEST)) 959 { 960 rc = STATUS_SUCCESS; 961 } 962 963 Log(("vgdrvNt5PlusPnPSendIrpSynchronously: Returning 0x%x\n", rc)); 964 return rc; 965 } 966 967 968 /** 969 * PnP Request handler. 970 * 971 * @param pDevObj Device object. 972 * @param pIrp Request packet. 973 */ 974 static NTSTATUS vgdrvNtNt5PlusPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) 975 { 976 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; 977 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); 978 979 # ifdef LOG_ENABLED 980 static char const * const s_apszFnctName[] = 981 { 982 "IRP_MN_START_DEVICE", 983 "IRP_MN_QUERY_REMOVE_DEVICE", 984 "IRP_MN_REMOVE_DEVICE", 985 "IRP_MN_CANCEL_REMOVE_DEVICE", 986 "IRP_MN_STOP_DEVICE", 987 "IRP_MN_QUERY_STOP_DEVICE", 988 "IRP_MN_CANCEL_STOP_DEVICE", 989 "IRP_MN_QUERY_DEVICE_RELATIONS", 990 "IRP_MN_QUERY_INTERFACE", 991 "IRP_MN_QUERY_CAPABILITIES", 992 "IRP_MN_QUERY_RESOURCES", 993 "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", 994 "IRP_MN_QUERY_DEVICE_TEXT", 995 "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", 996 "IRP_MN_0xE", 997 "IRP_MN_READ_CONFIG", 998 "IRP_MN_WRITE_CONFIG", 999 "IRP_MN_EJECT", 1000 "IRP_MN_SET_LOCK", 1001 "IRP_MN_QUERY_ID", 1002 "IRP_MN_QUERY_PNP_DEVICE_STATE", 1003 "IRP_MN_QUERY_BUS_INFORMATION", 1004 "IRP_MN_DEVICE_USAGE_NOTIFICATION", 1005 "IRP_MN_SURPRISE_REMOVAL", 1006 }; 1007 Log(("vgdrvNtNt5PlusPnP: MinorFunction: %s\n", 1008 pStack->MinorFunction < RT_ELEMENTS(s_apszFnctName) ? s_apszFnctName[pStack->MinorFunction] : "Unknown")); 1009 # endif 1010 1011 NTSTATUS rc = STATUS_SUCCESS; 1012 switch (pStack->MinorFunction) 1013 { 1014 case IRP_MN_START_DEVICE: 1015 { 1016 Log(("vgdrvNtNt5PlusPnP: START_DEVICE\n")); 1017 1018 /* This must be handled first by the lower driver. */ 1019 rc = vgdrvNt5PlusPnPSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); 1020 if ( NT_SUCCESS(rc) 1021 && NT_SUCCESS(pIrp->IoStatus.Status)) 1022 { 1023 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n", 1024 pStack->Parameters.StartDevice.AllocatedResources)); 1025 1026 if (pStack->Parameters.StartDevice.AllocatedResources) 1027 rc = vgdrvNtInit(pDevObj, pIrp); 1028 else 1029 { 1030 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: No resources, pDevExt = %p, nextLowerDriver = %p!\n", 1031 pDevExt, pDevExt ? pDevExt->pNextLowerDriver : NULL)); 1032 rc = STATUS_UNSUCCESSFUL; 1033 } 1034 } 1035 1036 if (NT_ERROR(rc)) 1037 { 1038 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: Error: rc = 0x%x\n", rc)); 1039 1040 /* Need to unmap memory in case of errors ... */ 1041 /** @todo r=bird: vgdrvNtInit maps it and is responsible for cleaning up its own friggin mess... 1042 * Fix it instead of kind of working around things there!! */ 1043 vgdrvNtUnmapVMMDevMemory(pDevExt); 1044 } 1045 break; 1046 } 1047 1048 case IRP_MN_CANCEL_REMOVE_DEVICE: 1049 { 1050 Log(("vgdrvNtNt5PlusPnP: CANCEL_REMOVE_DEVICE\n")); 1051 1052 /* This must be handled first by the lower driver. */ 1053 rc = vgdrvNt5PlusPnPSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); 1054 if ( NT_SUCCESS(rc) 1055 && pDevExt->enmDevState == VGDRVNTDEVSTATE_PENDINGREMOVE) 1056 { 1057 /* Return to the state prior to receiving the IRP_MN_QUERY_REMOVE_DEVICE request. */ 1058 pDevExt->enmDevState = pDevExt->enmPrevDevState; 1059 } 1060 1061 /* Complete the IRP. */ 1062 break; 1063 } 1064 1065 case IRP_MN_SURPRISE_REMOVAL: 1066 { 1067 Log(("vgdrvNtNt5PlusPnP: IRP_MN_SURPRISE_REMOVAL\n")); 1068 1069 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_SURPRISEREMOVED); 1070 1071 /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE. 1072 * This request is not expected for VBoxGuest. 1073 */ 1074 LogRel(("VBoxGuest: unexpected device removal\n")); 1075 1076 /* Pass to the lower driver. */ 1077 pIrp->IoStatus.Status = STATUS_SUCCESS; 1078 1079 IoSkipCurrentIrpStackLocation(pIrp); 1080 1081 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1082 1083 /* Do not complete the IRP. */ 1084 return rc; 1085 } 1086 1087 case IRP_MN_QUERY_REMOVE_DEVICE: 1088 { 1089 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n")); 1090 1091 # ifdef VBOX_REBOOT_ON_UNINSTALL 1092 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); 1093 rc = STATUS_UNSUCCESSFUL; 1094 # endif 1095 1096 if (NT_SUCCESS(rc)) 1097 { 1098 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGREMOVE); 1099 1100 /* This IRP passed down to lower driver. */ 1101 pIrp->IoStatus.Status = STATUS_SUCCESS; 1102 1103 IoSkipCurrentIrpStackLocation(pIrp); 1104 1105 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1106 Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1107 1108 /* we must not do anything the IRP after doing IoSkip & CallDriver 1109 * since the driver below us will complete (or already have completed) the IRP. 1110 * I.e. just return the status we got from IoCallDriver */ 1111 return rc; 1112 } 1113 1114 /* Complete the IRP on failure. */ 1115 break; 1116 } 1117 1118 case IRP_MN_REMOVE_DEVICE: 1119 { 1120 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE\n")); 1121 1122 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_REMOVED); 1123 1124 /* Free hardware resources. */ 1125 /** @todo this should actually free I/O ports, interrupts, etc. 1126 * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do? */ 1127 rc = vgdrvNtCleanup(pDevObj); 1128 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: vgdrvNtCleanup rc = 0x%08X\n", rc)); 1129 1130 /* 1131 * We need to send the remove down the stack before we detach, 1132 * but we don't need to wait for the completion of this operation 1133 * (and to register a completion routine). 1134 */ 1135 pIrp->IoStatus.Status = STATUS_SUCCESS; 1136 1137 IoSkipCurrentIrpStackLocation(pIrp); 1138 1139 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1140 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1141 1142 IoDetachDevice(pDevExt->pNextLowerDriver); 1143 1144 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Removing device ...\n")); 1145 1146 /* Destroy device extension and clean up everything else. */ 1147 VGDrvCommonDeleteDevExt(&pDevExt->Core); 1148 1149 /* Remove DOS device + symbolic link. */ 1150 UNICODE_STRING win32Name; 1151 RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); 1152 IoDeleteSymbolicLink(&win32Name); 1153 1154 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Deleting device ...\n")); 1155 1156 /* Last action: Delete our device! pDevObj is *not* failed 1157 * anymore after this call! */ 1158 IoDeleteDevice(pDevObj); 1159 1160 Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Device removed!\n")); 1161 1162 /* Propagating rc from IoCallDriver. */ 1163 return rc; /* Make sure that we don't do anything below here anymore! */ 1164 } 1165 1166 case IRP_MN_CANCEL_STOP_DEVICE: 1167 { 1168 Log(("vgdrvNtNt5PlusPnP: CANCEL_STOP_DEVICE\n")); 1169 1170 /* This must be handled first by the lower driver. */ 1171 rc = vgdrvNt5PlusPnPSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); 1172 if ( NT_SUCCESS(rc) 1173 && pDevExt->enmDevState == VGDRVNTDEVSTATE_PENDINGSTOP) 1174 { 1175 /* Return to the state prior to receiving the IRP_MN_QUERY_STOP_DEVICE request. */ 1176 pDevExt->enmDevState = pDevExt->enmPrevDevState; 1177 } 1178 1179 /* Complete the IRP. */ 1180 break; 1181 } 1182 1183 case IRP_MN_QUERY_STOP_DEVICE: 1184 { 1185 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n")); 1186 1187 # ifdef VBOX_REBOOT_ON_UNINSTALL 1188 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n")); 1189 pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; 1190 # endif 1191 1192 if (NT_SUCCESS(rc)) 1193 { 1194 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGSTOP); 1195 1196 /* This IRP passed down to lower driver. */ 1197 pIrp->IoStatus.Status = STATUS_SUCCESS; 1198 1199 IoSkipCurrentIrpStackLocation(pIrp); 1200 1201 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1202 Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1203 1204 /* we must not do anything with the IRP after doing IoSkip & CallDriver 1205 * since the driver below us will complete (or already have completed) the IRP. 1206 * I.e. just return the status we got from IoCallDriver */ 1207 return rc; 1208 } 1209 1210 /* Complete the IRP on failure. */ 1211 break; 1212 } 1213 1214 case IRP_MN_STOP_DEVICE: 1215 { 1216 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE\n")); 1217 1218 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_STOPPED); 1219 1220 /* Free hardware resources. */ 1221 /** @todo this should actually free I/O ports, interrupts, etc. 1222 * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do? */ 1223 rc = vgdrvNtCleanup(pDevObj); 1224 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc)); 1225 1226 /* Pass to the lower driver. */ 1227 pIrp->IoStatus.Status = STATUS_SUCCESS; 1228 1229 IoSkipCurrentIrpStackLocation(pIrp); 1230 1231 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1232 Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); 1233 1234 return rc; 1235 } 1236 1237 default: 1238 { 1239 IoSkipCurrentIrpStackLocation(pIrp); 1240 rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1241 return rc; 1242 } 1243 } 1244 1245 pIrp->IoStatus.Status = rc; 1246 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 1247 1248 Log(("vgdrvNtNt5PlusPnP: Returning with rc = 0x%x\n", rc)); 1249 return rc; 1250 } 1251 1252 1253 /** 1254 * Handle the power completion event. 1255 * 1256 * @returns NT status code. 1257 * @param pDevObj Targetted device object. 1258 * @param pIrp IO request packet. 1259 * @param pContext Context value passed to IoSetCompletionRoutine in VBoxGuestPower. 1260 */ 1261 static NTSTATUS vgdrvNtNt5PlusPowerComplete(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pContext) 1262 { 1263 # ifdef VBOX_STRICT 1264 RT_NOREF1(pDevObj); 1265 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pContext; 1266 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp); 1267 1268 Assert(pDevExt); 1269 1270 if (pIrpSp) 1271 { 1272 Assert(pIrpSp->MajorFunction == IRP_MJ_POWER); 1273 if (NT_SUCCESS(pIrp->IoStatus.Status)) 1274 { 1275 switch (pIrpSp->MinorFunction) 1276 { 1277 case IRP_MN_SET_POWER: 1278 switch (pIrpSp->Parameters.Power.Type) 1279 { 1280 case DevicePowerState: 1281 switch (pIrpSp->Parameters.Power.State.DeviceState) 1282 { 1283 case PowerDeviceD0: 1284 break; 1285 default: /* Shut up MSC */ break; 1286 } 1287 break; 1288 default: /* Shut up MSC */ break; 1289 } 1290 break; 1291 } 1292 } 1293 } 1294 # else 1295 RT_NOREF3(pDevObj, pIrp, pContext); 1296 # endif 1297 1298 return STATUS_SUCCESS; 1299 } 1300 1301 1302 /** 1303 * Handle the Power requests. 1304 * 1305 * @returns NT status code 1306 * @param pDevObj device object 1307 * @param pIrp IRP 1308 */ 1309 static NTSTATUS vgdrvNtNt5PlusPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) 1310 { 1311 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); 1312 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; 1313 POWER_STATE_TYPE enmPowerType = pStack->Parameters.Power.Type; 1314 POWER_STATE PowerState = pStack->Parameters.Power.State; 1315 POWER_ACTION enmPowerAction = pStack->Parameters.Power.ShutdownType; 1316 1317 Log(("vgdrvNtNt5PlusPower:\n")); 1318 1319 switch (pStack->MinorFunction) 1320 { 1321 case IRP_MN_SET_POWER: 1322 { 1323 Log(("vgdrvNtNt5PlusPower: IRP_MN_SET_POWER, type= %d\n", enmPowerType)); 1324 switch (enmPowerType) 1325 { 1326 case SystemPowerState: 1327 { 1328 Log(("vgdrvNtNt5PlusPower: SystemPowerState, action = %d, state = %d/%d\n", 1329 enmPowerAction, PowerState.SystemState, PowerState.DeviceState)); 1330 1331 switch (enmPowerAction) 1332 { 1333 case PowerActionSleep: 1334 1335 /* System now is in a working state. */ 1336 if (PowerState.SystemState == PowerSystemWorking) 1337 { 1338 if ( pDevExt 1339 && pDevExt->LastSystemPowerAction == PowerActionHibernate) 1340 { 1341 Log(("vgdrvNtNt5PlusPower: Returning from hibernation!\n")); 1342 int rc = VGDrvCommonReinitDevExtAfterHibernation(&pDevExt->Core, 1343 vgdrvNtVersionToOSType(g_enmVGDrvNtVer)); 1344 if (RT_FAILURE(rc)) 1345 Log(("vgdrvNtNt5PlusPower: Cannot re-init VMMDev chain, rc = %d!\n", rc)); 1346 } 1347 } 1348 break; 1349 1350 case PowerActionShutdownReset: 1351 { 1352 Log(("vgdrvNtNt5PlusPower: Power action reset!\n")); 1353 1354 /* Tell the VMM that we no longer support mouse pointer integration. */ 1355 VMMDevReqMouseStatus *pReq = NULL; 1356 int vrc = VbglR0GRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), 1357 VMMDevReq_SetMouseStatus); 1358 if (RT_SUCCESS(vrc)) 1359 { 1360 pReq->mouseFeatures = 0; 1361 pReq->pointerXPos = 0; 1362 pReq->pointerYPos = 0; 1363 1364 vrc = VbglR0GRPerform(&pReq->header); 1365 if (RT_FAILURE(vrc)) 1366 { 1367 Log(("vgdrvNtNt5PlusPower: error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); 1368 } 1369 1370 VbglR0GRFree(&pReq->header); 1371 } 1372 1373 /* Don't do any cleanup here; there might be still coming in some IOCtls after we got this 1374 * power action and would assert/crash when we already cleaned up all the stuff! */ 1375 break; 1376 } 1377 1378 case PowerActionShutdown: 1379 case PowerActionShutdownOff: 1380 { 1381 Log(("vgdrvNtNt5PlusPower: Power action shutdown!\n")); 1382 if (PowerState.SystemState >= PowerSystemShutdown) 1383 { 1384 Log(("vgdrvNtNt5PlusPower: Telling the VMMDev to close the VM ...\n")); 1385 1386 VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest; 1387 int vrc = VERR_NOT_IMPLEMENTED; 1388 if (pReq) 1389 { 1390 pReq->header.requestType = VMMDevReq_SetPowerStatus; 1391 pReq->powerState = VMMDevPowerState_PowerOff; 1392 1393 vrc = VbglR0GRPerform(&pReq->header); 1394 } 1395 if (RT_FAILURE(vrc)) 1396 Log(("vgdrvNtNt5PlusPower: Error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); 1397 1398 /* No need to do cleanup here; at this point we should've been 1399 * turned off by VMMDev already! */ 1400 } 1401 break; 1402 } 1403 1404 case PowerActionHibernate: 1405 1406 Log(("vgdrvNtNt5PlusPower: Power action hibernate!\n")); 1407 break; 1408 1409 case PowerActionWarmEject: 1410 Log(("vgdrvNtNt5PlusPower: PowerActionWarmEject!\n")); 1411 break; 1412 1413 default: 1414 Log(("vgdrvNtNt5PlusPower: %d\n", enmPowerAction)); 1415 break; 1416 } 1417 1418 /* 1419 * Save the current system power action for later use. 1420 * This becomes handy when we return from hibernation for example. 1421 */ 1422 if (pDevExt) 1423 pDevExt->LastSystemPowerAction = enmPowerAction; 1424 1425 break; 1426 } 1427 default: 1428 break; 1429 } 1430 break; 1431 } 1432 default: 1433 break; 1434 } 1435 1436 /* 1437 * Whether we are completing or relaying this power IRP, 1438 * we must call PoStartNextPowerIrp. 1439 */ 1440 PoStartNextPowerIrp(pIrp); 1441 1442 /* 1443 * Send the IRP down the driver stack, using PoCallDriver 1444 * (not IoCallDriver, as for non-power irps). 1445 */ 1446 IoCopyCurrentIrpStackLocationToNext(pIrp); 1447 IoSetCompletionRoutine(pIrp, 1448 vgdrvNtNt5PlusPowerComplete, 1449 (PVOID)pDevExt, 1450 TRUE, 1451 TRUE, 1452 TRUE); 1453 return PoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1454 } 1455 1456 1457 /** 1458 * IRP_MJ_SYSTEM_CONTROL handler. 1459 * 1460 * @returns NT status code 1461 * @param pDevObj Device object. 1462 * @param pIrp IRP. 1463 */ 1464 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp) 1465 { 1466 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; 1467 1468 LogFlowFuncEnter(); 1469 1470 /* Always pass it on to the next driver. */ 1471 IoSkipCurrentIrpStackLocation(pIrp); 1472 1473 return IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1474 } 1475 1476 #endif /* !TARGET_NT4 */ 1477 1478 1479 /** 1480 * Unmaps the VMMDev I/O range from kernel space. 1481 * 1482 * @param pDevExt The device extension. 1483 */ 1484 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt) 1485 { 1486 LogFlowFunc(("pVMMDevMemory = %#x\n", pDevExt->Core.pVMMDevMemory)); 1487 if (pDevExt->Core.pVMMDevMemory) 1488 { 1489 MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->vmmDevPhysMemoryLength); 1490 pDevExt->Core.pVMMDevMemory = NULL; 1491 } 1492 1493 pDevExt->vmmDevPhysMemoryAddress.QuadPart = 0; 1494 pDevExt->vmmDevPhysMemoryLength = 0; 1495 } 1496 1497 713 1498 /** 714 1499 * Cleans up hardware resources. … … 724 1509 * @param pDevObj Device object. 725 1510 */ 726 NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj)1511 static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj) 727 1512 { 728 1513 LogFlowFuncEnter(); … … 788 1573 IoDeleteDevice(pDrvObj->DeviceObject); 789 1574 #else /* !TARGET_NT4 */ 790 /* On a PnP driver this routine will be called after 791 * IRP_MN_REMOVE_DEVICE (where we already did the cleanup), 792 * so don't do anything here (yet). */ 1575 /* 1576 * On a PnP driver this routine will be called after IRP_MN_REMOVE_DEVICE 1577 * where we already did the cleanup, so don't do anything here (yet). 1578 */ 793 1579 RT_NOREF1(pDrvObj); 794 1580 #endif /* !TARGET_NT4 */ … … 1063 1849 return vgdrvNtDeviceControl(pDevObj, pIrp); 1064 1850 } 1065 1066 1067 #ifndef TARGET_NT41068 /**1069 * IRP_MJ_SYSTEM_CONTROL handler.1070 *1071 * @returns NT status code1072 * @param pDevObj Device object.1073 * @param pIrp IRP.1074 */1075 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)1076 {1077 PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;1078 1079 LogFlowFuncEnter();1080 1081 /* Always pass it on to the next driver. */1082 IoSkipCurrentIrpStackLocation(pIrp);1083 1084 return IoCallDriver(pDevExt->pNextLowerDriver, pIrp);1085 }1086 #endif /* TARGET_NT4 */1087 1851 1088 1852 … … 1618 2382 } 1619 2383 1620 1621 /**1622 * Unmaps the VMMDev I/O range from kernel space.1623 *1624 * @param pDevExt The device extension.1625 */1626 void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt)1627 {1628 LogFlowFunc(("pVMMDevMemory = %#x\n", pDevExt->Core.pVMMDevMemory));1629 if (pDevExt->Core.pVMMDevMemory)1630 {1631 MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->vmmDevPhysMemoryLength);1632 pDevExt->Core.pVMMDevMemory = NULL;1633 }1634 1635 pDevExt->vmmDevPhysMemoryAddress.QuadPart = 0;1636 pDevExt->vmmDevPhysMemoryLength = 0;1637 }1638 1639 1640 /**1641 * Translates NT version to VBox OS.1642 *1643 * @returns VBox OS type.1644 * @param enmNtVer The NT version.1645 */1646 VBOXOSTYPE vgdrvNtVersionToOSType(VGDRVNTVER enmNtVer)1647 {1648 VBOXOSTYPE enmOsType;1649 switch (enmNtVer)1650 {1651 case VGDRVNTVER_WINNT4:1652 enmOsType = VBOXOSTYPE_WinNT4;1653 break;1654 1655 case VGDRVNTVER_WIN2K:1656 enmOsType = VBOXOSTYPE_Win2k;1657 break;1658 1659 case VGDRVNTVER_WINXP:1660 #if ARCH_BITS == 641661 enmOsType = VBOXOSTYPE_WinXP_x64;1662 #else1663 enmOsType = VBOXOSTYPE_WinXP;1664 #endif1665 break;1666 1667 case VGDRVNTVER_WIN2K3:1668 #if ARCH_BITS == 641669 enmOsType = VBOXOSTYPE_Win2k3_x64;1670 #else1671 enmOsType = VBOXOSTYPE_Win2k3;1672 #endif1673 break;1674 1675 case VGDRVNTVER_WINVISTA:1676 #if ARCH_BITS == 641677 enmOsType = VBOXOSTYPE_WinVista_x64;1678 #else1679 enmOsType = VBOXOSTYPE_WinVista;1680 #endif1681 break;1682 1683 case VGDRVNTVER_WIN7:1684 #if ARCH_BITS == 641685 enmOsType = VBOXOSTYPE_Win7_x64;1686 #else1687 enmOsType = VBOXOSTYPE_Win7;1688 #endif1689 break;1690 1691 case VGDRVNTVER_WIN8:1692 #if ARCH_BITS == 641693 enmOsType = VBOXOSTYPE_Win8_x64;1694 #else1695 enmOsType = VBOXOSTYPE_Win8;1696 #endif1697 break;1698 1699 case VGDRVNTVER_WIN81:1700 #if ARCH_BITS == 641701 enmOsType = VBOXOSTYPE_Win81_x64;1702 #else1703 enmOsType = VBOXOSTYPE_Win81;1704 #endif1705 break;1706 1707 case VGDRVNTVER_WIN10:1708 #if ARCH_BITS == 641709 enmOsType = VBOXOSTYPE_Win10_x64;1710 #else1711 enmOsType = VBOXOSTYPE_Win10;1712 #endif1713 break;1714 1715 default:1716 /* We don't know, therefore NT family. */1717 enmOsType = VBOXOSTYPE_WinNT;1718 break;1719 }1720 return enmOsType;1721 }1722 1723 2384 #ifdef VBOX_STRICT 1724 2385
Note:
See TracChangeset
for help on using the changeset viewer.