Index: /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp	(revision 70222)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp	(revision 70223)
@@ -149,6 +149,4 @@
     /** Preallocated generic request for shutdown. */
     VMMDevPowerStateRequest *pPowerStateRequest;
-    /** Preallocated VMMDevEvents for IRQ handler. */
-    VMMDevEvents           *pIrqAckEvents;
 
     /** Spinlock protecting MouseNotifyCallback. Required since the consumer is
@@ -191,5 +189,4 @@
 static NTSTATUS vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
 static void     vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt);
-static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj);
 static void     vgdrvNtUnload(PDRIVER_OBJECT pDrvObj);
 static NTSTATUS vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
@@ -263,4 +260,5 @@
         return STATUS_UNSUCCESSFUL;
     }
+    VGDrvCommonInitLoggers();
 
     LogFunc(("Driver built: %s %s\n", __DATE__, __TIME__));
@@ -400,5 +398,4 @@
                 return rcNt;
             }
-
         }
     }
@@ -408,4 +405,5 @@
      */
     LogRelFunc(("Failed! rcNt=%#x\n", rcNt));
+    VGDrvCommonDestroyLoggers();
     RTR0Term();
     return rcNt;
@@ -513,5 +511,5 @@
 
 /**
- * Global initialization stuff.
+ * Sets up the device and its resources.
  *
  * @param   pDevExt     Our device extension data.
@@ -521,6 +519,6 @@
  * @param   pRegPath    The registry path for NT4, NULL for NT5+.
  */
-static NTSTATUS vgdrvNtInit(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj,
-                            PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
+static NTSTATUS vgdrvNtSetupDevice(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj,
+                                   PIRP pIrp, PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
 {
     LogFlowFunc(("ENTER: pDevExt=%p pDevObj=%p pIrq=%p pDrvObj=%p pRegPath=%p\n", pDevExt, pDevObj, pIrp, pDrvObj, pRegPath));
@@ -588,11 +586,12 @@
                      pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL));
 
-            int vrc = VGDrvCommonInitDevExt(&pDevExt->Core,
-                                            pDevExt->Core.IOPortBase,
-                                            pvMMIOBase, cbMMIO,
-                                            vgdrvNtVersionToOSType(g_enmVGDrvNtVer),
-                                            VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
+            int vrc = VGDrvCommonInitDevExtResources(&pDevExt->Core,
+                                                     pDevExt->Core.IOPortBase,
+                                                     pvMMIOBase, cbMMIO,
+                                                     vgdrvNtVersionToOSType(g_enmVGDrvNtVer),
+                                                     VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
             if (RT_SUCCESS(vrc))
             {
+
                 vrc = VbglR0GRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest,
                                     sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
@@ -674,9 +673,9 @@
                 }
 
-                VGDrvCommonDeleteDevExt(&pDevExt->Core);
+                VGDrvCommonDeleteDevExtResources(&pDevExt->Core);
             }
             else
             {
-                LogFunc(("Could not init device extension, vrc=%Rrc\n", vrc));
+                LogFunc(("Could not init device extension resources: vrc=%Rrc\n", vrc));
                 rcNt = STATUS_DEVICE_CONFIGURATION_ERROR;
             }
@@ -695,4 +694,65 @@
 
 #ifdef TARGET_NT4
+
+/**
+ * Helper function to handle the PCI device lookup.
+ *
+ * @returns NT status code.
+ *
+ * @param   puBus           Where to return the bus number on success.
+ * @param   pSlot           Where to return the slot number on success.
+ */
+static NTSTATUS vgdrvNt4FindPciDevice(PULONG puBus, PPCI_SLOT_NUMBER pSlot)
+{
+    Log(("vgdrvNt4FindPciDevice\n"));
+
+    PCI_SLOT_NUMBER Slot;
+    Slot.u.AsULONG = 0;
+
+    /* Scan each bus. */
+    for (ULONG uBus = 0; uBus < PCI_MAX_BUSES; uBus++)
+    {
+        /* Scan each device. */
+        for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
+        {
+            Slot.u.bits.DeviceNumber = deviceNumber;
+
+            /* Scan each function (not really required...). */
+            for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
+            {
+                Slot.u.bits.FunctionNumber = functionNumber;
+
+                /* Have a look at what's in this slot. */
+                PCI_COMMON_CONFIG PciData;
+                if (!HalGetBusData(PCIConfiguration, uBus, Slot.u.AsULONG, &PciData, sizeof(ULONG)))
+                {
+                    /* No such bus, we're done with it. */
+                    deviceNumber = PCI_MAX_DEVICES;
+                    break;
+                }
+
+                if (PciData.VendorID == PCI_INVALID_VENDORID)
+                    /* We have to proceed to the next function. */
+                    continue;
+
+                /* Check if it's another device. */
+                if (   PciData.VendorID != VMMDEV_VENDORID
+                    || PciData.DeviceID != VMMDEV_DEVICEID)
+                    continue;
+
+                /* Hooray, we've found it! */
+                Log(("vgdrvNt4FindPciDevice: Device found! Bus=%#x Slot=%#u (dev %#x, fun %#x, rvd %#x)\n",
+                     uBus, Slot.u.AsULONG, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, Slot.u.bits.Reserved));
+
+                *puBus  = uBus;
+                *pSlot  = Slot;
+                return STATUS_SUCCESS;
+            }
+        }
+    }
+
+    return STATUS_DEVICE_DOES_NOT_EXIST;
+}
+
 
 /**
@@ -742,9 +802,6 @@
              */
             Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n"));
-
             PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
             RT_ZERO(*pDevExt);
-
-            Log(("vgdrvNt4CreateDevice: Device extension created\n"));
 
             /* Store a reference to ourself. */
@@ -755,18 +812,25 @@
             pDevExt->uSlot = uSlot.u.AsULONG;
 
+            /* Initialize common bits. */
+            int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
+            if (RT_SUCCESS(vrc))
+            {
+                Log(("vgdrvNt4CreateDevice: Device extension created\n"));
 # ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
-            rc = hlpRegisterBugCheckCallback(pDevExt);
+                rc = hlpRegisterBugCheckCallback(pDevExt);
 # endif
-            if (NT_SUCCESS(rc))
-            {
-                /* Do the actual VBox init ... */
-                rc = vgdrvNtInit(pDevExt, pDeviceObject, NULL /*pIrp*/, pDrvObj, pRegPath);
                 if (NT_SUCCESS(rc))
                 {
-                    Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc));
-                    return rc;
+                    /* Do the actual VBox init ... */
+                    rc = vgdrvNtSetupDevice(pDevExt, pDeviceObject, NULL /*pIrp*/, pDrvObj, pRegPath);
+                    if (NT_SUCCESS(rc))
+                    {
+                        Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc));
+                        return rc;
+                    }
+
+                    /* bail out */
                 }
-
-                /* bail out */
+                VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
             }
             IoDeleteSymbolicLink(&DosName);
@@ -780,65 +844,4 @@
     Log(("vgdrvNt4CreateDevice: Returning rc = 0x%x\n", rc));
     return rc;
-}
-
-
-/**
- * Helper function to handle the PCI device lookup.
- *
- * @returns NT status code.
- *
- * @param   puBus           Where to return the bus number on success.
- * @param   pSlot           Where to return the slot number on success.
- */
-static NTSTATUS vgdrvNt4FindPciDevice(PULONG puBus, PPCI_SLOT_NUMBER pSlot)
-{
-    Log(("vgdrvNt4FindPciDevice\n"));
-
-    PCI_SLOT_NUMBER Slot;
-    Slot.u.AsULONG = 0;
-
-    /* Scan each bus. */
-    for (ULONG uBus = 0; uBus < PCI_MAX_BUSES; uBus++)
-    {
-        /* Scan each device. */
-        for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
-        {
-            Slot.u.bits.DeviceNumber = deviceNumber;
-
-            /* Scan each function (not really required...). */
-            for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
-            {
-                Slot.u.bits.FunctionNumber = functionNumber;
-
-                /* Have a look at what's in this slot. */
-                PCI_COMMON_CONFIG PciData;
-                if (!HalGetBusData(PCIConfiguration, uBus, Slot.u.AsULONG, &PciData, sizeof(ULONG)))
-                {
-                    /* No such bus, we're done with it. */
-                    deviceNumber = PCI_MAX_DEVICES;
-                    break;
-                }
-
-                if (PciData.VendorID == PCI_INVALID_VENDORID)
-                    /* We have to proceed to the next function. */
-                    continue;
-
-                /* Check if it's another device. */
-                if (   PciData.VendorID != VMMDEV_VENDORID
-                    || PciData.DeviceID != VMMDEV_DEVICEID)
-                    continue;
-
-                /* Hooray, we've found it! */
-                Log(("vgdrvNt4FindPciDevice: Device found! Bus=%#x Slot=%#u (dev %#x, fun %#x, rvd %#x)\n",
-                     uBus, Slot.u.AsULONG, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, Slot.u.bits.Reserved));
-
-                *puBus  = uBus;
-                *pSlot  = Slot;
-                return STATUS_SUCCESS;
-            }
-        }
-    }
-
-    return STATUS_DEVICE_DOES_NOT_EXIST;
 }
 
@@ -882,37 +885,43 @@
 
             KeInitializeSpinLock(&pDevExt->MouseEventAccessSpinLock);
-
             pDevExt->pDeviceObject   = pDeviceObject;
             pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED;
             pDevExt->enmDevState     = VGDRVNTDEVSTATE_STOPPED;
 
-            pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
-            if (pDevExt->pNextLowerDriver != NULL)
-            {
-                /*
-                 * If we reached this point we're fine with the basic driver setup,
-                 * so continue to init our own things.
-                 */
+            int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
+            if (RT_SUCCESS(vrc))
+            {
+                pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
+                if (pDevExt->pNextLowerDriver != NULL)
+                {
+                    /*
+                     * If we reached this point we're fine with the basic driver setup,
+                     * so continue to init our own things.
+                     */
 #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
-                vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */
+                    vgdrvNtBugCheckCallback(pDevExt); /* Ignore failure! */
 #endif
-                if (NT_SUCCESS(rcNt))
+                    if (NT_SUCCESS(rcNt))
+                    {
+                        /* Ensure we are not called at elevated IRQL, even if our code isn't pagable any more. */
+                        pDeviceObject->Flags |= DO_POWER_PAGABLE;
+
+                        /* Driver is ready now. */
+                        pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+                        LogFlowFunc(("Returning with rcNt=%#x (success)\n", rcNt));
+                        return rcNt;
+                    }
+
+                    IoDetachDevice(pDevExt->pNextLowerDriver);
+                }
+                else
                 {
-                    /* Ensure we are not called at elevated IRQL, even if our code isn't pagable any more. */
-                    pDeviceObject->Flags |= DO_POWER_PAGABLE;
-
-                    /* Driver is ready now. */
-                    pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-                    LogFlowFunc(("Returning with rcNt=%#x (success)\n", rcNt));
-                    return rcNt;
+                    LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
+                    rcNt = STATUS_DEVICE_NOT_CONNECTED;
                 }
-
-                IoDetachDevice(pDevExt->pNextLowerDriver);
+                VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
             }
             else
-            {
-                LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
-                rcNt = STATUS_DEVICE_NOT_CONNECTED;
-            }
+                rcNt = STATUS_UNSUCCESSFUL;
 
             /* bail out */
@@ -979,4 +988,56 @@
     Log(("vgdrvNt5PlusPnPSendIrpSynchronously: Returning %#x\n", rcNt));
     return rcNt;
+}
+
+
+/**
+ * Deletes the device hardware resources.
+ *
+ * Used during removal, stopping and legacy module unloading.
+ *
+ * @param   pDevExt         The device extension.
+ */
+static void vgdrvNtDeleteDeviceResources(PVBOXGUESTDEVEXTWIN pDevExt)
+{
+    if (pDevExt->pInterruptObject)
+    {
+        IoDisconnectInterrupt(pDevExt->pInterruptObject);
+        pDevExt->pInterruptObject = NULL;
+    }
+    if (pDevExt->Core.uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES)
+        VGDrvCommonDeleteDevExtResources(&pDevExt->Core);
+    vgdrvNtUnmapVMMDevMemory(pDevExt);
+}
+
+
+/**
+ * Deletes the device extension fundament and unlinks the device
+ *
+ * Used during removal and legacy module unloading.  Must have called
+ * vgdrvNtDeleteDeviceResources.
+ *
+ * @param   pDevExt         The device extension.
+ */
+static void vgdrvNtDeleteDeviceFundamentAndUnlink(PDEVICE_OBJECT pDevObj, PVBOXGUESTDEVEXTWIN pDevExt)
+{
+    /*
+     * Delete the remainder of the device extension.
+     */
+    pDevExt->pPowerStateRequest = NULL; /* Will be deleted by the following call. */
+    VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
+
+#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
+    hlpDeregisterBugCheckCallback(pDevExt);
+#endif
+
+    /*
+     * Delete the DOS symlink to the device and finally the device itself.
+     */
+    UNICODE_STRING DosName;
+    RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
+    IoDeleteSymbolicLink(&DosName);
+
+    Log(("vgdrvNtDeleteDeviceFundamentAndUnlink: Deleting device ...\n"));
+    IoDeleteDevice(pDevObj);
 }
 
@@ -1039,7 +1100,10 @@
                 Log(("vgdrvNtNt5PlusPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n",
                      pStack->Parameters.StartDevice.AllocatedResources));
-
                 if (pStack->Parameters.StartDevice.AllocatedResources)
-                    rc = vgdrvNtInit(pDevExt, pDevObj, pIrp, NULL, NULL);
+                {
+                    rc = vgdrvNtSetupDevice(pDevExt, pDevObj, pIrp, NULL, NULL);
+                    if (!NT_SUCCESS(rc))
+                        Log(("vgdrvNtNt5PlusPnP: START_DEVICE: vgdrvNtSetupDevice failed: %#x\n", rc));
+                }
                 else
                 {
@@ -1049,9 +1113,57 @@
                 }
             }
-            if (NT_ERROR(rc))
-                Log(("vgdrvNtNt5PlusPnP: START_DEVICE: Error: rc = 0x%x\n", rc));
-            break;
+            else
+                Log(("vgdrvNtNt5PlusPnP: START_DEVICE: vgdrvNt5PlusPnPSendIrpSynchronously failed: %#x + %#x\n",
+                     rc, pIrp->IoStatus.Status));
+
+            pIrp->IoStatus.Status = rc;
+            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+            return rc;
         }
 
+
+        /*
+         * Sent before removing the device and/or driver.
+         */
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+        {
+            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n"));
+
+#ifdef VBOX_REBOOT_ON_UNINSTALL
+            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n"));
+            rc = STATUS_UNSUCCESSFUL;
+#endif
+            /** @todo refuse to remove ourselves when we've got client
+             *        sessions attached...  */
+
+            if (NT_SUCCESS(rc))
+            {
+                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGREMOVE);
+
+                /* This IRP passed down to lower driver. */
+                pIrp->IoStatus.Status = STATUS_SUCCESS;
+
+                IoSkipCurrentIrpStackLocation(pIrp);
+                rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
+                Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
+
+                /* We must not do anything the IRP after doing IoSkip & CallDriver
+                   since the driver below us will complete (or already have completed) the IRP.
+                   I.e. just return the status we got from IoCallDriver */
+            }
+            else
+            {
+                pIrp->IoStatus.Status = rc;
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+            }
+
+            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Returning with rc = 0x%x\n", rc));
+            return rc;
+        }
+
+        /*
+         * Cancels a pending remove, IRP_MN_QUERY_REMOVE_DEVICE.
+         * We only have to revert the state.
+         */
         case IRP_MN_CANCEL_REMOVE_DEVICE:
         {
@@ -1068,16 +1180,17 @@
 
             /* Complete the IRP. */
-            break;
+            pIrp->IoStatus.Status = rc;
+            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+            return rc;
         }
 
+        /*
+         * We do nothing here actually, esp. since this request is not expected for VBoxGuest.
+         * The cleanup will be done in IRP_MN_REMOVE_DEVICE, which follows this call.
+         */
         case IRP_MN_SURPRISE_REMOVAL:
         {
             Log(("vgdrvNtNt5PlusPnP: IRP_MN_SURPRISE_REMOVAL\n"));
-
             VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_SURPRISEREMOVED);
-
-            /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE.
-             * This request is not expected for VBoxGuest.
-             */
             LogRel(("VBoxGuest: unexpected device removal\n"));
 
@@ -1086,5 +1199,4 @@
 
             IoSkipCurrentIrpStackLocation(pIrp);
-
             rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
 
@@ -1093,83 +1205,84 @@
         }
 
-        case IRP_MN_QUERY_REMOVE_DEVICE:
-        {
-            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n"));
-
-#ifdef VBOX_REBOOT_ON_UNINSTALL
-            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n"));
-            rc = STATUS_UNSUCCESSFUL;
-#endif
-
-            if (NT_SUCCESS(rc))
-            {
-                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGREMOVE);
-
-                /* This IRP passed down to lower driver. */
-                pIrp->IoStatus.Status = STATUS_SUCCESS;
-
-                IoSkipCurrentIrpStackLocation(pIrp);
-
-                rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
-                Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
-
-                /* we must not do anything the IRP after doing IoSkip & CallDriver
-                 * since the driver below us will complete (or already have completed) the IRP.
-                 * I.e. just return the status we got from IoCallDriver */
-                return rc;
-            }
-
-            /* Complete the IRP on failure. */
-            break;
-        }
-
+        /*
+         * Device and/or driver removal.  Destroy everything.
+         */
         case IRP_MN_REMOVE_DEVICE:
         {
             Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE\n"));
-
             VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_REMOVED);
 
-            /* Free hardware resources. */
-            /** @todo this should actually free I/O ports, interrupts, etc.
-             * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do?  */
-            rc = vgdrvNtCleanup(pDevObj);
-            Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: vgdrvNtCleanup rc = 0x%08X\n", rc));
-
             /*
-             * We need to send the remove down the stack before we detach,
-             * but we don't need to wait for the completion of this operation
-             * (and to register a completion routine).
+             * Disconnect interrupts and delete all hardware resources.
+             * Note! This may already have been done if we're STOPPED already, if that's a possibility.
+             */
+            vgdrvNtDeleteDeviceResources(pDevExt);
+
+            /*
+             * We need to send the remove down the stack before we detach, but we don't need
+             * to wait for the completion of this operation (nor register a completion routine).
              */
             pIrp->IoStatus.Status = STATUS_SUCCESS;
 
             IoSkipCurrentIrpStackLocation(pIrp);
-
             rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
             Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
 
             IoDetachDevice(pDevExt->pNextLowerDriver);
-
             Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Removing device ...\n"));
 
-            /* Destroy device extension and clean up everything else. */
-            VGDrvCommonDeleteDevExt(&pDevExt->Core);
-
-            /* Remove DOS device + symbolic link. */
-            UNICODE_STRING win32Name;
-            RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
-            IoDeleteSymbolicLink(&win32Name);
-
-            Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Deleting device ...\n"));
-
-            /* Last action: Delete our device! pDevObj is *not* failed
-             * anymore after this call! */
-            IoDeleteDevice(pDevObj);
+            /*
+             * Delete the remainder of the device extension data, unlink it from the namespace and delete it.
+             */
+            vgdrvNtDeleteDeviceFundamentAndUnlink(pDevObj, pDevExt);
+
+            pDevObj = NULL; /* invalid */
+            pDevExt = NULL; /* invalid */
 
             Log(("vgdrvNtNt5PlusPnP: REMOVE_DEVICE: Device removed!\n"));
-
-            /* Propagating rc from IoCallDriver. */
-            return rc; /* Make sure that we don't do anything below here anymore! */
+            return rc; /* Propagating rc from IoCallDriver. */
         }
 
+
+        /*
+         * Sent before stopping the device/driver to check whether it is okay to do so.
+         */
+        case IRP_MN_QUERY_STOP_DEVICE:
+        {
+            Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n"));
+
+            /** @todo Check whether we can stop the device.  Similar to
+             *        removal above */
+            rc = STATUS_SUCCESS;
+            if (NT_SUCCESS(rc))
+            {
+                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGSTOP);
+
+                /* This IRP passed down to lower driver. */
+                pIrp->IoStatus.Status = STATUS_SUCCESS;
+
+                IoSkipCurrentIrpStackLocation(pIrp);
+
+                rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
+                Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
+
+                /* we must not do anything with the IRP after doing IoSkip & CallDriver since the
+                   driver below us will complete (or already have completed) the IRP.  I.e. just
+                   return the status we got from IoCallDriver. */
+            }
+            else
+            {
+                pIrp->IoStatus.Status = rc;
+                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+            }
+
+            Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Returning with rc = 0x%x\n", rc));
+            return rc;
+        }
+
+        /*
+         * Cancels a pending remove, IRP_MN_QUERY_STOP_DEVICE.
+         * We only have to revert the state.
+         */
         case IRP_MN_CANCEL_STOP_DEVICE:
         {
@@ -1186,58 +1299,29 @@
 
             /* Complete the IRP. */
-            break;
+            pIrp->IoStatus.Status = rc;
+            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+            return rc;
         }
 
-        case IRP_MN_QUERY_STOP_DEVICE:
-        {
-            Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n"));
-
-#ifdef VBOX_REBOOT_ON_UNINSTALL /** @todo  r=bird: this code and log msg is pointless as rc = success and status will be overwritten below. */
-            Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n"));
-            pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-#endif
-
-            if (NT_SUCCESS(rc))
-            {
-                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_PENDINGSTOP);
-
-                /* This IRP passed down to lower driver. */
-                pIrp->IoStatus.Status = STATUS_SUCCESS;
-
-                IoSkipCurrentIrpStackLocation(pIrp);
-
-                rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
-                Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
-
-                /* we must not do anything with the IRP after doing IoSkip & CallDriver
-                 * since the driver below us will complete (or already have completed) the IRP.
-                 * I.e. just return the status we got from IoCallDriver */
-                return rc;
-            }
-
-            /* Complete the IRP on failure. */
-            break;
-        }
-
+        /*
+         * Stop the device.
+         */
         case IRP_MN_STOP_DEVICE:
         {
             Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE\n"));
-
             VBOXGUEST_UPDATE_DEVSTATE(pDevExt, VGDRVNTDEVSTATE_STOPPED);
 
-            /* Free hardware resources. */
-            /** @todo this should actually free I/O ports, interrupts, etc.
-             * Update/bird: vgdrvNtCleanup actually does that... So, what's there to do?  */
-            rc = vgdrvNtCleanup(pDevObj);
-            Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc));
-
-            /* Pass to the lower driver. */
+            /*
+             * Release the hardware resources.
+             */
+            vgdrvNtDeleteDeviceResources(pDevExt);
+
+            /*
+             * Pass the request to the lower driver.
+             */
             pIrp->IoStatus.Status = STATUS_SUCCESS;
-
             IoSkipCurrentIrpStackLocation(pIrp);
-
             rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
             Log(("vgdrvNtNt5PlusPnP: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
-
             return rc;
         }
@@ -1247,13 +1331,8 @@
             IoSkipCurrentIrpStackLocation(pIrp);
             rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp);
+            Log(("vgdrvNtNt5PlusPnP: Unknown request %#x: Lower driver replied: %x\n", pStack->MinorFunction, rc));
             return rc;
         }
     }
-
-    pIrp->IoStatus.Status = rc;
-    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
-
-    Log(("vgdrvNtNt5PlusPnP: Returning with rc = 0x%x\n", rc));
-    return rc;
 }
 
@@ -1505,68 +1584,30 @@
 
 /**
- * Cleans up hardware resources.
- * Do not delete DevExt here.
- *
- * @todo r=bird: HC SVNT DRACONES!
- *
- *       This code leaves clients hung when vgdrvNtInit is called afterwards.
- *       This happens when for instance hotplugging a CPU.  Problem is
- *       vgdrvNtInit doing a full VGDrvCommonInitDevExt, orphaning all pDevExt
- *       members, like session lists and stuff.
- *
- * @param   pDevObj     Device object.
- */
-static NTSTATUS vgdrvNtCleanup(PDEVICE_OBJECT pDevObj)
+ * Unload the driver.
+ *
+ * @param   pDrvObj     Driver object.
+ */
+static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj)
 {
     LogFlowFuncEnter();
 
-    PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
-    if (pDevExt)
-    {
-        if (pDevExt->pInterruptObject)
+#ifdef TARGET_NT4
+    /*
+     * We need to destroy the device object here on NT4 and earlier.
+     */
+    PDEVICE_OBJECT pDevObj = pDrvObj->DeviceObject;
+    if (pDevObj)
+    {
+        if (g_enmVGDrvNtVer <= VGDRVNTVER_WINNT4)
         {
-            IoDisconnectInterrupt(pDevExt->pInterruptObject);
-            pDevExt->pInterruptObject = NULL;
+            PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
+            AssertPtr(pDevExt);
+            AssertMsg(pDevExt->Core.uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES,
+                      ("uInitState=%#x\n", pDevExt->Core.uInitState));
+
+            vgdrvNtDeleteDeviceResources(pDevExt);
+            vgdrvNtDeleteDeviceFundamentAndUnlink(pDevObj, pDevExt);
         }
-
-        /** @todo cleanup the rest stuff */
-
-
-#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
-        hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */
-#endif
-        /* According to MSDN we have to unmap previously mapped memory. */
-        vgdrvNtUnmapVMMDevMemory(pDevExt);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-
-/**
- * Unload the driver.
- *
- * @param   pDrvObj     Driver object.
- */
-static void vgdrvNtUnload(PDRIVER_OBJECT pDrvObj)
-{
-    LogFlowFuncEnter();
-
-#ifdef TARGET_NT4
-    vgdrvNtCleanup(pDrvObj->DeviceObject);
-
-    /* Destroy device extension and clean up everything else. */
-    if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension)
-        VGDrvCommonDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension);
-
-    /*
-     * I don't think it's possible to unload a driver which processes have
-     * opened, at least we'll blindly assume that here.
-     */
-    UNICODE_STRING DosName;
-    RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
-    IoDeleteSymbolicLink(&DosName);
-
-    IoDeleteDevice(pDrvObj->DeviceObject);
+    }
 #else  /* !TARGET_NT4 */
     /*
@@ -1577,4 +1618,5 @@
 #endif /* !TARGET_NT4 */
 
+    VGDrvCommonDestroyLoggers();
     RTR0Term();
     LogFlowFunc(("Returning\n"));
@@ -1982,5 +2024,5 @@
         {
             Log3Func(("Requesting DPC ...\n"));
-            IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL);
+            IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL); /** @todo r=bird: pCurrentIrp is not set anywhere. sigh. */
         }
     }
Index: /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp	(revision 70222)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp	(revision 70223)
@@ -924,29 +924,10 @@
 
 /**
- * Initializes the VBoxGuest device extension when the
- * device driver is loaded.
- *
- * The native code locates the VMMDev on the PCI bus and retrieve
- * the MMIO and I/O port ranges, this function will take care of
- * mapping the MMIO memory (if present). Upon successful return
- * the native code should set up the interrupt handler.
- *
- * @returns VBox status code.
- *
- * @param   pDevExt         The device extension. Allocated by the native code.
- * @param   IOPortBase      The base of the I/O port range.
- * @param   pvMMIOBase      The base of the MMIO memory mapping.
- *                          This is optional, pass NULL if not present.
- * @param   cbMMIO          The size of the MMIO memory mapping.
- *                          This is optional, pass 0 if not present.
- * @param   enmOSType       The guest OS type to report to the VMMDev.
- * @param   fFixedEvents    Events that will be enabled upon init and no client
- *                          will ever be allowed to mask.
- */
-int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
-                          void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents)
-{
-    int rc, rc2;
-
+ * Initializes the release logger (debug is implicit), if configured.
+ *
+ * @returns IPRT status code.
+ */
+int VGDrvCommonInitLoggers(void)
+{
 #ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
     /*
@@ -955,23 +936,48 @@
     static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
     PRTLOGGER pRelLogger;
-    rc = RTLogCreate(&pRelLogger, 0 /*fFlags*/, "all", "VBOXGUEST_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
-                     RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL);
+    int rc = RTLogCreate(&pRelLogger, 0 /*fFlags*/, "all", "VBOXGUEST_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
+                         RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL);
     if (RT_SUCCESS(rc))
         RTLogRelSetDefaultInstance(pRelLogger);
     /** @todo Add native hook for getting logger config parameters and setting
      *        them.  On linux we should use the module parameter stuff... */
+    return rc;
+#else
+    return VINF_SUCCESS;
 #endif
-
-    /*
-     * Adjust fFixedEvents.
-     */
-#ifdef VBOX_WITH_HGCM
-    fFixedEvents |= VMMDEV_EVENT_HGCM;
+}
+
+
+/**
+ * Destroys the loggers.
+ */
+void VGDrvCommonDestroyLoggers(void)
+{
+#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
+    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
+    RTLogDestroy(RTLogSetDefaultInstance(NULL));
 #endif
+}
+
+
+/**
+ * Initialize the device extension fundament.
+ *
+ * There are no device resources at this point, VGDrvCommonInitDevExtResources
+ * should be called when they are available.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt         The device extension to init.
+ */
+int VGDrvCommonInitDevExtFundament(PVBOXGUESTDEVEXT pDevExt)
+{
+    int rc;
+    AssertMsg(   pDevExt->uInitState != VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT
+              && pDevExt->uInitState != VBOXGUESTDEVEXT_INIT_STATE_RESOURCES, ("uInitState=%#x\n", pDevExt->uInitState));
 
     /*
      * Initialize the data.
      */
-    pDevExt->IOPortBase = IOPortBase;
+    pDevExt->IOPortBase = UINT16_MAX;
     pDevExt->pVMMDevMemory = NULL;
     pDevExt->hGuestMappings = NIL_RTR0MEMOBJ;
@@ -1004,5 +1010,5 @@
     pDevExt->pReqGuestHeartbeat = NULL;
 
-    pDevExt->fFixedEvents = fFixedEvents;
+    pDevExt->fFixedEvents = 0;
     vgdrvBitUsageTrackerClear(&pDevExt->EventFilterTracker);
     pDevExt->fEventFilterHost = UINT32_MAX;  /* forces a report */
@@ -1018,4 +1024,79 @@
 
     /*
+     * Create the wait and session spinlocks as well as the ballooning mutex.
+     */
+    rc = RTSpinlockCreate(&pDevExt->EventSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestEvent");
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTSpinlockCreate(&pDevExt->SessionSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestSession");
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTSemFastMutexCreate(&pDevExt->MemBalloon.hMtx);
+            if (RT_SUCCESS(rc))
+            {
+                pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT;
+                return VINF_SUCCESS;
+            }
+
+            LogRel(("VGDrvCommonInitDevExt: failed to create mutex, rc=%Rrc!\n", rc));
+            RTSpinlockDestroy(pDevExt->SessionSpinlock);
+        }
+        else
+            LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc));
+        RTSpinlockDestroy(pDevExt->EventSpinlock);
+    }
+    else
+        LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc));
+
+    pDevExt->uInitState = 0;
+    return rc;
+}
+
+
+/**
+ * Counter to VGDrvCommonInitDevExtFundament.
+ *
+ * @param   pDevExt         The device extension.
+ */
+void VGDrvCommonDeleteDevExtFundament(PVBOXGUESTDEVEXT pDevExt)
+{
+    int rc2;
+    AssertMsgReturnVoid(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT, ("uInitState=%#x\n", pDevExt->uInitState));
+    pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_DELETED;
+
+    rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2);
+    rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2);
+    rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2);
+}
+
+
+/**
+ * Initializes the VBoxGuest device extension resource parts.
+ *
+ * The native code locates the VMMDev on the PCI bus and retrieve the MMIO and
+ * I/O port ranges, this function will take care of mapping the MMIO memory (if
+ * present).  Upon successful return the native code should set up the interrupt
+ * handler.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt         The device extension. Allocated by the native code.
+ * @param   IOPortBase      The base of the I/O port range.
+ * @param   pvMMIOBase      The base of the MMIO memory mapping.
+ *                          This is optional, pass NULL if not present.
+ * @param   cbMMIO          The size of the MMIO memory mapping.
+ *                          This is optional, pass 0 if not present.
+ * @param   enmOSType       The guest OS type to report to the VMMDev.
+ * @param   fFixedEvents    Events that will be enabled upon init and no client
+ *                          will ever be allowed to mask.
+ */
+int VGDrvCommonInitDevExtResources(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
+                                   void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents)
+{
+    int rc;
+    AssertMsgReturn(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT, ("uInitState=%#x\n", pDevExt->uInitState),
+                    VERR_INVALID_STATE);
+
+    /*
      * If there is an MMIO region validate the version and size.
      */
@@ -1029,33 +1110,10 @@
         {
             pDevExt->pVMMDevMemory = pVMMDev;
-            Log(("VGDrvCommonInitDevExt: VMMDevMemory: mapping=%p size=%#RX32 (%#RX32) version=%#RX32\n",
+            Log(("VGDrvCommonInitDevExtResources: VMMDevMemory: mapping=%p size=%#RX32 (%#RX32) version=%#RX32\n",
                  pVMMDev, pVMMDev->u32Size, cbMMIO, pVMMDev->u32Version));
         }
         else /* try live without it. */
-            LogRel(("VGDrvCommonInitDevExt: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32 (expected <= %RX32)\n",
+            LogRel(("VGDrvCommonInitDevExtResources: Bogus VMMDev memory; u32Version=%RX32 (expected %RX32) u32Size=%RX32 (expected <= %RX32)\n",
                     pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size, cbMMIO));
-    }
-
-    /*
-     * Create the wait and session spinlocks as well as the ballooning mutex.
-     */
-    rc = RTSpinlockCreate(&pDevExt->EventSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestEvent");
-    if (RT_SUCCESS(rc))
-        rc = RTSpinlockCreate(&pDevExt->SessionSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestSession");
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("VGDrvCommonInitDevExt: failed to create spinlock, rc=%Rrc!\n", rc));
-        if (pDevExt->EventSpinlock != NIL_RTSPINLOCK)
-            RTSpinlockDestroy(pDevExt->EventSpinlock);
-        return rc;
-    }
-
-    rc = RTSemFastMutexCreate(&pDevExt->MemBalloon.hMtx);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("VGDrvCommonInitDevExt: failed to create mutex, rc=%Rrc!\n", rc));
-        RTSpinlockDestroy(pDevExt->SessionSpinlock);
-        RTSpinlockDestroy(pDevExt->EventSpinlock);
-        return rc;
     }
 
@@ -1065,4 +1123,5 @@
      * made by the VMM.
      */
+    pDevExt->IOPortBase = IOPortBase;
     rc = VbglR0InitPrimary(pDevExt->IOPortBase, (VMMDevMemory *)pDevExt->pVMMDevMemory);
     if (RT_SUCCESS(rc))
@@ -1081,5 +1140,9 @@
                  * the guest capabilities or mouse status bits set.
                  */
-                rc = vgdrvResetEventFilterOnHost(pDevExt, pDevExt->fFixedEvents);
+#ifdef VBOX_WITH_HGCM
+                fFixedEvents |= VMMDEV_EVENT_HGCM;
+#endif
+                pDevExt->fFixedEvents = fFixedEvents;
+                rc = vgdrvResetEventFilterOnHost(pDevExt, fFixedEvents);
                 if (RT_SUCCESS(rc))
                 {
@@ -1101,37 +1164,162 @@
                             rc = vgdrvReportDriverStatus(true /* Driver is active */);
                             if (RT_FAILURE(rc))
-                                LogRel(("VGDrvCommonInitDevExt: VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc));
-
-                            LogFlowFunc(("VGDrvCommonInitDevExt: returns success\n"));
+                                LogRel(("VGDrvCommonInitDevExtResources: VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc));
+
+                            pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_RESOURCES;
+                            LogFlowFunc(("VGDrvCommonInitDevExtResources: returns success\n"));
                             return VINF_SUCCESS;
                         }
-                        LogRel(("VGDrvCommonInitDevExt: failed to clear mouse status: rc=%Rrc\n", rc));
+                        LogRel(("VGDrvCommonInitDevExtResources: failed to clear mouse status: rc=%Rrc\n", rc));
                     }
                     else
-                        LogRel(("VGDrvCommonInitDevExt: failed to clear guest capabilities: rc=%Rrc\n", rc));
+                        LogRel(("VGDrvCommonInitDevExtResources: failed to clear guest capabilities: rc=%Rrc\n", rc));
                 }
                 else
-                    LogRel(("VGDrvCommonInitDevExt: failed to set fixed event filter: rc=%Rrc\n", rc));
+                    LogRel(("VGDrvCommonInitDevExtResources: failed to set fixed event filter: rc=%Rrc\n", rc));
+                pDevExt->fFixedEvents = 0;
             }
             else
-                LogRel(("VGDrvCommonInitDevExt: vgdrvReportGuestInfo failed: rc=%Rrc\n", rc));
+                LogRel(("VGDrvCommonInitDevExtResources: vgdrvReportGuestInfo failed: rc=%Rrc\n", rc));
             VbglR0GRFree((VMMDevRequestHeader *)pDevExt->pIrqAckEvents);
         }
         else
-            LogRel(("VGDrvCommonInitDevExt: VbglR0GRAlloc failed: rc=%Rrc\n", rc));
+            LogRel(("VGDrvCommonInitDevExtResources: VbglR0GRAlloc failed: rc=%Rrc\n", rc));
 
         VbglR0TerminatePrimary();
     }
     else
-        LogRel(("VGDrvCommonInitDevExt: VbglR0InitPrimary failed: rc=%Rrc\n", rc));
-
-    rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2);
-    rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2);
-    rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2);
-
-#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
-    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
-    RTLogDestroy(RTLogSetDefaultInstance(NULL));
+        LogRel(("VGDrvCommonInitDevExtResources: VbglR0InitPrimary failed: rc=%Rrc\n", rc));
+    pDevExt->IOPortBase = UINT16_MAX;
+    return rc;
+}
+
+
+/**
+ * Deletes all the items in a wait chain.
+ * @param   pList       The head of the chain.
+ */
+static void vgdrvDeleteWaitList(PRTLISTNODE pList)
+{
+    while (!RTListIsEmpty(pList))
+    {
+        int             rc2;
+        PVBOXGUESTWAIT  pWait = RTListGetFirst(pList, VBOXGUESTWAIT, ListNode);
+        RTListNodeRemove(&pWait->ListNode);
+
+        rc2 = RTSemEventMultiDestroy(pWait->Event); AssertRC(rc2);
+        pWait->Event = NIL_RTSEMEVENTMULTI;
+        pWait->pSession = NULL;
+        RTMemFree(pWait);
+    }
+}
+
+
+/**
+ * Counter to VGDrvCommonInitDevExtResources.
+ *
+ * @param   pDevExt         The device extension.
+ */
+void VGDrvCommonDeleteDevExtResources(PVBOXGUESTDEVEXT pDevExt)
+{
+    Log(("VGDrvCommonDeleteDevExtResources:\n"));
+    AssertMsgReturnVoid(pDevExt->uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES, ("uInitState=%#x\n", pDevExt->uInitState));
+    pDevExt->uInitState = VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT;
+
+    /*
+     * Stop and destroy HB timer and disable host heartbeat checking.
+     */
+    if (pDevExt->pHeartbeatTimer)
+    {
+        RTTimerDestroy(pDevExt->pHeartbeatTimer);
+        vgdrvHeartbeatHostConfigure(pDevExt, false);
+    }
+
+    VbglR0GRFree(pDevExt->pReqGuestHeartbeat);
+    pDevExt->pReqGuestHeartbeat = NULL;
+
+    /*
+     * Clean up the bits that involves the host first.
+     */
+    vgdrvTermUnfixGuestMappings(pDevExt);
+    if (!RTListIsEmpty(&pDevExt->SessionList))
+    {
+        LogRelFunc(("session list not empty!\n"));
+        RTListInit(&pDevExt->SessionList);
+    }
+
+    /*
+     * Update the host flags (mouse status etc) not to reflect this session.
+     */
+    pDevExt->fFixedEvents = 0;
+    vgdrvResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/);
+    vgdrvResetCapabilitiesOnHost(pDevExt);
+    vgdrvResetMouseStatusOnHost(pDevExt);
+
+    vgdrvCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL);
+
+    /*
+     * Cleanup all the other resources.
+     */
+    vgdrvDeleteWaitList(&pDevExt->WaitList);
+#ifdef VBOX_WITH_HGCM
+    vgdrvDeleteWaitList(&pDevExt->HGCMWaitList);
 #endif
+#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
+    vgdrvDeleteWaitList(&pDevExt->WakeUpList);
+#endif
+    vgdrvDeleteWaitList(&pDevExt->WokenUpList);
+    vgdrvDeleteWaitList(&pDevExt->FreeList);
+
+    VbglR0TerminatePrimary();
+
+
+    pDevExt->pVMMDevMemory = NULL;
+    pDevExt->IOPortBase = 0;
+    pDevExt->pIrqAckEvents = NULL; /* Freed by VbglR0TerminatePrimary. */
+}
+
+
+/**
+ * Initializes the VBoxGuest device extension when the device driver is loaded.
+ *
+ * The native code locates the VMMDev on the PCI bus and retrieve the MMIO and
+ * I/O port ranges, this function will take care of mapping the MMIO memory (if
+ * present). Upon successful return the native code should set up the interrupt
+ * handler.
+ *
+ * Instead of calling this method, the host specific code choose to perform a
+ * more granular initialization using:
+ *      1. VGDrvCommonInitLoggers
+ *      2. VGDrvCommonInitDevExtFundament
+ *      3. VGDrvCommonInitDevExtResources
+ *
+ * @returns VBox status code.
+ *
+ * @param   pDevExt         The device extension. Allocated by the native code.
+ * @param   IOPortBase      The base of the I/O port range.
+ * @param   pvMMIOBase      The base of the MMIO memory mapping.
+ *                          This is optional, pass NULL if not present.
+ * @param   cbMMIO          The size of the MMIO memory mapping.
+ *                          This is optional, pass 0 if not present.
+ * @param   enmOSType       The guest OS type to report to the VMMDev.
+ * @param   fFixedEvents    Events that will be enabled upon init and no client
+ *                          will ever be allowed to mask.
+ */
+int VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
+                          void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents)
+{
+    int rc;
+    VGDrvCommonInitLoggers();
+
+    rc = VGDrvCommonInitDevExtFundament(pDevExt);
+    if (RT_SUCCESS(rc))
+    {
+        rc = VGDrvCommonInitDevExtResources(pDevExt, IOPortBase, pvMMIOBase, cbMMIO, enmOSType, fFixedEvents);
+        if (RT_SUCCESS(rc))
+            return rc;
+
+        VGDrvCommonDeleteDevExtFundament(pDevExt);
+    }
+    VGDrvCommonDestroyLoggers();
     return rc; /* (failed) */
 }
@@ -1390,24 +1578,4 @@
 
 /**
- * Deletes all the items in a wait chain.
- * @param   pList       The head of the chain.
- */
-static void vgdrvDeleteWaitList(PRTLISTNODE pList)
-{
-    while (!RTListIsEmpty(pList))
-    {
-        int             rc2;
-        PVBOXGUESTWAIT  pWait = RTListGetFirst(pList, VBOXGUESTWAIT, ListNode);
-        RTListNodeRemove(&pWait->ListNode);
-
-        rc2 = RTSemEventMultiDestroy(pWait->Event); AssertRC(rc2);
-        pWait->Event = NIL_RTSEMEVENTMULTI;
-        pWait->pSession = NULL;
-        RTMemFree(pWait);
-    }
-}
-
-
-/**
  * Destroys the VBoxGuest device extension.
  *
@@ -1419,67 +1587,9 @@
 void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt)
 {
-    int rc2;
     Log(("VGDrvCommonDeleteDevExt:\n"));
     Log(("VBoxGuest: The additions driver is terminating.\n"));
-
-    /*
-     * Stop and destroy HB timer and
-     * disable host heartbeat checking.
-     */
-    if (pDevExt->pHeartbeatTimer)
-    {
-        RTTimerDestroy(pDevExt->pHeartbeatTimer);
-        vgdrvHeartbeatHostConfigure(pDevExt, false);
-    }
-
-    VbglR0GRFree(pDevExt->pReqGuestHeartbeat);
-    pDevExt->pReqGuestHeartbeat = NULL;
-
-    /*
-     * Clean up the bits that involves the host first.
-     */
-    vgdrvTermUnfixGuestMappings(pDevExt);
-    if (!RTListIsEmpty(&pDevExt->SessionList))
-    {
-        LogRelFunc(("session list not empty!\n"));
-        RTListInit(&pDevExt->SessionList);
-    }
-    /* Update the host flags (mouse status etc) not to reflect this session. */
-    pDevExt->fFixedEvents = 0;
-    vgdrvResetEventFilterOnHost(pDevExt, 0 /*fFixedEvents*/);
-    vgdrvResetCapabilitiesOnHost(pDevExt);
-    vgdrvResetMouseStatusOnHost(pDevExt);
-
-    vgdrvCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL);
-
-    /*
-     * Cleanup all the other resources.
-     */
-    rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2);
-    rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2);
-    rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2);
-
-    vgdrvDeleteWaitList(&pDevExt->WaitList);
-#ifdef VBOX_WITH_HGCM
-    vgdrvDeleteWaitList(&pDevExt->HGCMWaitList);
-#endif
-#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
-    vgdrvDeleteWaitList(&pDevExt->WakeUpList);
-#endif
-    vgdrvDeleteWaitList(&pDevExt->WokenUpList);
-    vgdrvDeleteWaitList(&pDevExt->FreeList);
-
-    VbglR0TerminatePrimary();
-
-    pDevExt->pVMMDevMemory = NULL;
-
-    pDevExt->IOPortBase = 0;
-    pDevExt->pIrqAckEvents = NULL;
-
-#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER
-    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
-    RTLogDestroy(RTLogSetDefaultInstance(NULL));
-#endif
-
+    VGDrvCommonDeleteDevExtResources(pDevExt);
+    VGDrvCommonDeleteDevExtFundament(pDevExt);
+    VGDrvCommonDestroyLoggers();
 }
 
Index: /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h	(revision 70222)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h	(revision 70223)
@@ -140,4 +140,6 @@
 typedef struct VBOXGUESTDEVEXT
 {
+    /** VBOXGUESTDEVEXT_INIT_STATE_XXX.   */
+    uint32_t                    uInitState;
     /** The base of the adapter I/O ports. */
     RTIOPORT                    IOPortBase;
@@ -251,4 +253,11 @@
 typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT;
 
+/** @name VBOXGUESTDEVEXT_INIT_STATE_XXX - magic values for validating init
+ *        state of the device extension structur.
+ * @{ */
+#define VBOXGUESTDEVEXT_INIT_STATE_FUNDAMENT        UINT32_C(0x0badcafe)
+#define VBOXGUESTDEVEXT_INIT_STATE_RESOURCES        UINT32_C(0xcafebabe)
+#define VBOXGUESTDEVEXT_INIT_STATE_DELETED          UINT32_C(0xdeadd0d0)
+/** @} */
 
 /**
@@ -325,4 +334,15 @@
 int  VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO,
                            VBOXOSTYPE enmOSType, uint32_t fEvents);
+void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
+
+int  VGDrvCommonInitLoggers(void);
+void VGDrvCommonDestroyLoggers(void);
+int  VGDrvCommonInitDevExtFundament(PVBOXGUESTDEVEXT pDevExt);
+void VGDrvCommonDeleteDevExtFundament(PVBOXGUESTDEVEXT pDevExt);
+int  VGDrvCommonInitDevExtResources(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase,
+                                    void *pvMMIOBase, uint32_t cbMMIO, VBOXOSTYPE enmOSType, uint32_t fFixedEvents);
+void VGDrvCommonDeleteDevExtResources(PVBOXGUESTDEVEXT pDevExt);
+int  VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType);
+
 bool VBDrvCommonIsOptionValueTrue(const char *pszValue);
 void VGDrvCommonProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue);
@@ -330,6 +350,5 @@
 bool VGDrvCommonIsOurIRQ(PVBOXGUESTDEVEXT pDevExt);
 bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt);
-void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
-int  VGDrvCommonReinitDevExtAfterHibernation(PVBOXGUESTDEVEXT pDevExt, VBOXOSTYPE enmOSType);
+
 #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP
 void VGDrvCommonWaitDoWakeUps(PVBOXGUESTDEVEXT pDevExt);
