VirtualBox

Ignore:
Timestamp:
Dec 13, 2017 10:09:27 AM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119651
Message:

VBoxGuest-win*: Folded VBoxGuest-win-pnp.cpp and VBoxGuest-win.h into VBoxGuest-win.cpp.

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  
    105105  ifeq ($(KBUILD_TARGET), win)
    106106   VBoxGuest_SOURCES += \
    107         VBoxGuest-$(KBUILD_TARGET)-pnp.cpp \
    108107        win/VBoxGuest.rc
    109108  endif
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp

    r70101 r70103  
    3030*********************************************************************************************************************************/
    3131#define LOG_GROUP LOG_GROUP_SUP_DRV
    32 #include "VBoxGuest-win.h"
     32#include <iprt/nt/ntddk.h>
     33
    3334#include "VBoxGuestInternal.h"
     35#include <VBox/VBoxGuestLib.h>
     36#include <VBox/log.h>
    3437
    3538#include <iprt/asm.h>
    3639#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>
    4042#include <iprt/string.h>
     43
    4144
    4245
     
    4750# define PCI_MAX_BUSES 256
    4851#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. */
     68typedef enum VGDRVNTDEVSTATE
     69{
     70    VGDRVNTDEVSTATE_STOPPED,
     71    VGDRVNTDEVSTATE_WORKING,
     72    VGDRVNTDEVSTATE_PENDINGSTOP,
     73    VGDRVNTDEVSTATE_PENDINGREMOVE,
     74    VGDRVNTDEVSTATE_SURPRISEREMOVED,
     75    VGDRVNTDEVSTATE_REMOVED
     76} VGDRVNTDEVSTATE;
     77
     78typedef 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. */
     96typedef 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. */
     153typedef 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;
     166extern VGDRVNTVER g_enmVGDrvNtVer;
    49167
    50168
     
    57175static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
    58176#else
    59 static NTSTATUS vgdrvNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
    60 #endif
     177static NTSTATUS vgdrvNtNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
     178static NTSTATUS vgdrvNtNt5PlusPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     179static NTSTATUS vgdrvNtNt5PlusPower(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     180static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     181#endif
     182static void     vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt);
     183static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj);
    61184static void     vgdrvNtUnload(PDRIVER_OBJECT pDrvObj);
    62185static NTSTATUS vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     
    66189static NTSTATUS vgdrvNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    67190static void     vgdrvNtReadConfiguration(PVBOXGUESTDEVEXTWIN pDevExt);
    68 #ifndef TARGET_NT4
    69 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    70 #endif
    71191static NTSTATUS vgdrvNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    72192static NTSTATUS vgdrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
     
    224344        rc = vgdrvNt4CreateDevice(pDrvObj, pRegPath);
    225345#else
    226         pDrvObj->MajorFunction[IRP_MJ_PNP]                     = vgdrvNtPnP;
    227         pDrvObj->MajorFunction[IRP_MJ_POWER]                   = vgdrvNtPower;
     346        pDrvObj->MajorFunction[IRP_MJ_PNP]                     = vgdrvNtNt5PlusPnP;
     347        pDrvObj->MajorFunction[IRP_MJ_POWER]                   = vgdrvNtNt5PlusPower;
    228348        pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL]          = vgdrvNtNt5PlusSystemControl;
    229         pDrvObj->DriverExtension->AddDevice                    = (PDRIVER_ADD_DEVICE)vgdrvNt5PlusAddDevice;
     349        pDrvObj->DriverExtension->AddDevice                    = (PDRIVER_ADD_DEVICE)vgdrvNtNt5PlusAddDevice;
    230350#endif
    231351    }
     
    236356
    237357
    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 */
     364static 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}
    476440
    477441
     
    539503 */
    540504#ifndef TARGET_NT4
    541 NTSTATUS vgdrvNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
     505static NTSTATUS vgdrvNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    542506#else
    543 NTSTATUS vgdrvNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
     507static NTSTATUS vgdrvNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
    544508#endif
    545509{
     
    711675
    712676
     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 */
     689static 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 */
     777static 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 */
     839static 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 */
     924static 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 */
     940static 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 */
     974static 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 */
     1261static 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 */
     1309static 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 */
     1464static 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 */
     1484static 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
    7131498/**
    7141499 * Cleans up hardware resources.
     
    7241509 * @param   pDevObj     Device object.
    7251510 */
    726 NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj)
     1511static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj)
    7271512{
    7281513    LogFlowFuncEnter();
     
    7881573    IoDeleteDevice(pDrvObj->DeviceObject);
    7891574#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     */
    7931579    RT_NOREF1(pDrvObj);
    7941580#endif /* !TARGET_NT4 */
     
    10631849    return vgdrvNtDeviceControl(pDevObj, pIrp);
    10641850}
    1065 
    1066 
    1067 #ifndef TARGET_NT4
    1068 /**
    1069  * IRP_MJ_SYSTEM_CONTROL handler.
    1070  *
    1071  * @returns NT status code
    1072  * @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 */
    10871851
    10881852
     
    16182382}
    16192383
    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 == 64
    1661             enmOsType = VBOXOSTYPE_WinXP_x64;
    1662 #else
    1663             enmOsType = VBOXOSTYPE_WinXP;
    1664 #endif
    1665             break;
    1666 
    1667         case VGDRVNTVER_WIN2K3:
    1668 #if ARCH_BITS == 64
    1669             enmOsType = VBOXOSTYPE_Win2k3_x64;
    1670 #else
    1671             enmOsType = VBOXOSTYPE_Win2k3;
    1672 #endif
    1673             break;
    1674 
    1675         case VGDRVNTVER_WINVISTA:
    1676 #if ARCH_BITS == 64
    1677             enmOsType = VBOXOSTYPE_WinVista_x64;
    1678 #else
    1679             enmOsType = VBOXOSTYPE_WinVista;
    1680 #endif
    1681             break;
    1682 
    1683         case VGDRVNTVER_WIN7:
    1684 #if ARCH_BITS == 64
    1685             enmOsType = VBOXOSTYPE_Win7_x64;
    1686 #else
    1687             enmOsType = VBOXOSTYPE_Win7;
    1688 #endif
    1689             break;
    1690 
    1691         case VGDRVNTVER_WIN8:
    1692 #if ARCH_BITS == 64
    1693             enmOsType = VBOXOSTYPE_Win8_x64;
    1694 #else
    1695             enmOsType = VBOXOSTYPE_Win8;
    1696 #endif
    1697             break;
    1698 
    1699         case VGDRVNTVER_WIN81:
    1700 #if ARCH_BITS == 64
    1701             enmOsType = VBOXOSTYPE_Win81_x64;
    1702 #else
    1703             enmOsType = VBOXOSTYPE_Win81;
    1704 #endif
    1705             break;
    1706 
    1707         case VGDRVNTVER_WIN10:
    1708 #if ARCH_BITS == 64
    1709             enmOsType = VBOXOSTYPE_Win10_x64;
    1710 #else
    1711             enmOsType = VBOXOSTYPE_Win10;
    1712 #endif
    1713             break;
    1714 
    1715         default:
    1716             /* We don't know, therefore NT family. */
    1717             enmOsType = VBOXOSTYPE_WinNT;
    1718             break;
    1719     }
    1720     return enmOsType;
    1721 }
    1722 
    17232384#ifdef VBOX_STRICT
    17242385
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette