Index: trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMF.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMF.h	(revision 37221)
+++ trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMF.h	(revision 37225)
@@ -47,4 +47,5 @@
 typedef struct _VBOXMOUSE_DEVEXT
 {
+    LIST_ENTRY ListEntry;
     PDEVICE_OBJECT pdoMain;           /* PDO passed to VBoxDrvAddDevice */
     PDEVICE_OBJECT pdoSelf;           /* our PDO created in VBoxDrvAddDevice*/
@@ -77,4 +78,7 @@
 VOID VBoxDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt);
 
+NTSTATUS VBoxNewProtInit();
+NTSTATUS VBoxNewProtTerm();
+
 VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG  InputDataConsumed);
 
Index: trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFDriver.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFDriver.cpp	(revision 37221)
+++ trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFDriver.cpp	(revision 37225)
@@ -51,4 +51,10 @@
     DriverObject->MajorFunction[IRP_MJ_PNP] = VBoxIrpPnP;
 
+    NTSTATUS tmpStatus = VBoxNewProtInit();
+    if (!NT_SUCCESS(tmpStatus))
+    {
+        WARN(("VBoxNewProtInit failed Status (0x%x)", tmpStatus));
+    }
+
     LOGF_LEAVE();
     return STATUS_SUCCESS;
@@ -60,4 +66,11 @@
     PAGED_CODE();
     LOGF_ENTER();
+
+    NTSTATUS tmpStatus = VBoxNewProtTerm();
+    if (!NT_SUCCESS(tmpStatus))
+    {
+        WARN(("VBoxNewProtTerm failed Status (0x%x)", tmpStatus));
+    }
+
 
     RTR0Term();
Index: trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp	(revision 37221)
+++ trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp	(revision 37225)
@@ -43,4 +43,5 @@
     volatile PVBOXMOUSE_DEVEXT pCurrentDevExt;
     LIST_ENTRY DevExtList;
+    volatile bool fIsNewProtEnabled;
     MOUSE_INPUT_DATA LastReportedData;
 } VBoxGlobalContext;
@@ -48,4 +49,5 @@
 static VBoxGlobalContext g_ctx = {};
 
+/* Guest Device Communication API */
 NTSTATUS VBoxGdcInit()
 {
@@ -207,5 +209,15 @@
 }
 
-static NTSTATUS vboxNewProtInit(PVBOXMOUSE_DEVEXT pCurrentDevExt)
+static BOOLEAN vboxNewProtIsInitialized()
+{
+    return !!g_ctx.pThread;
+}
+
+static BOOLEAN vboxNewProtIsStarted()
+{
+    return (BOOLEAN)ASMAtomicReadBool(&g_ctx.fIsNewProtEnabled);
+}
+
+NTSTATUS VBoxNewProtInit()
 {
     NTSTATUS Status = VBoxGdcInit();
@@ -215,30 +227,25 @@
         KeInitializeEvent(&g_ctx.TerminateEvent, NotificationEvent, FALSE);
         KeInitializeEvent(&g_ctx.MouseEvent, SynchronizationEvent, FALSE);
-
-        Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent);
+        InitializeListHead(&g_ctx.DevExtList);
+        /* we assume the new prot data in g_ctx is zero-initialized (see g_ctx definition) */
+
+        Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);
         if (NT_SUCCESS(Status))
         {
-            Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);
-            if (NT_SUCCESS(Status))
-            {
-                g_ctx.pCurrentDevExt = pCurrentDevExt;
-                return STATUS_SUCCESS;
-            }
-            g_ctx.pThread = NULL;
-            NTSTATUS tmpStatus = VBoxGdcSetMouseNotifyEvent(NULL);
-            Assert(NT_SUCCESS(tmpStatus));
-        }
-    }
-
-    return Status;
-}
-
-static BOOLEAN vboxNewProtIsSupported()
-{
-    return !!g_ctx.pThread;
-}
-
-static NTSTATUS vboxNewProtTerm()
-{
+            return STATUS_SUCCESS;
+        }
+        g_ctx.pThread = NULL;
+    }
+
+    return Status;
+}
+
+NTSTATUS VBoxNewProtTerm()
+{
+    Assert(IsListEmpty(&g_ctx.DevExtList));
+    Assert(!vboxNewProtIsStarted());
+    if (!vboxNewProtIsInitialized())
+        return STATUS_SUCCESS;
+
     KeSetEvent(&g_ctx.TerminateEvent, 0, FALSE);
     NTSTATUS Status = KeWaitForSingleObject(g_ctx.pThread, Executive, KernelMode, FALSE, NULL);
@@ -249,11 +256,4 @@
     }
 
-    Status = VBoxGdcSetMouseNotifyEvent(NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
-        return Status;
-    }
-
     ObDereferenceObject(g_ctx.pThread);
     g_ctx.pThread = NULL;
@@ -262,8 +262,99 @@
 }
 
-static NTSTATUS vboxNewProtSetCurrentDevExt(PVBOXMOUSE_DEVEXT pCurrentDevExt)
-{
-    ASMAtomicWritePtrVoid((void * volatile *)&g_ctx.pCurrentDevExt, pCurrentDevExt);
-    return STATUS_SUCCESS;
+static NTSTATUS vboxNewProtDeviceAdded(PVBOXMOUSE_DEVEXT pDevExt)
+{
+    if (!vboxNewProtIsInitialized())
+        return STATUS_UNSUCCESSFUL;
+
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL Irql;
+    BOOLEAN fDoEventRegister = FALSE;
+    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
+    InsertHeadList(&g_ctx.DevExtList, &pDevExt->ListEntry);
+    if (!g_ctx.pCurrentDevExt)
+    {
+        ASMAtomicWritePtr(&g_ctx.pCurrentDevExt, pDevExt);
+        /* ensure the object is not deleted while it is being used by a poller thread */
+        ObReferenceObject(pDevExt->pdoSelf);
+        fDoEventRegister = TRUE;
+    }
+    KeReleaseSpinLock(&g_ctx.SyncLock, Irql);
+
+    if (fDoEventRegister)
+    {
+        /* to ensure we do not concur with vboxNewProtDeviceRemoved cleaning the event,
+         * do it in a loop until the cauuent state of fIsNewProtEnabled is false,
+         * setting one and the same event multiple times will not hutr  */
+        do
+        {
+            Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent);
+            if (!NT_SUCCESS(Status))
+            {
+                WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
+                break;
+            }
+        } while (ASMAtomicCmpXchgBool(&g_ctx.fIsNewProtEnabled, true, false));
+
+        if (NT_SUCCESS(Status))
+        {
+            /* signal the event to ensure we did not miss anything */
+            KeSetEvent(&g_ctx.MouseEvent, 0, FALSE);
+            Status = STATUS_SUCCESS;
+        }
+    }
+#ifdef DEBUG_misha
+    else
+    {
+        Assert(g_ctx.fIsNewProtEnabled);
+    }
+#endif
+
+    return Status;
+}
+
+#define PVBOXMOUSE_DEVEXT_FROM_LE(_pLe) ( (PVBOXMOUSE_DEVEXT)(((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXMOUSE_DEVEXT, ListEntry)) )
+
+static NTSTATUS vboxNewProtDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt)
+{
+    if (!vboxNewProtIsInitialized())
+        return STATUS_UNSUCCESSFUL;
+
+    KIRQL Irql;
+    NTSTATUS Status = STATUS_SUCCESS;
+    BOOLEAN fDoEventUnregister = FALSE;
+    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
+    RemoveEntryList(&pDevExt->ListEntry);
+    if (g_ctx.pCurrentDevExt == pDevExt)
+    {
+        ObDereferenceObject(pDevExt->pdoSelf);
+        g_ctx.pCurrentDevExt = NULL;
+        for (PLIST_ENTRY pCur = g_ctx.DevExtList.Flink; pCur != &g_ctx.DevExtList; pCur = pCur->Flink)
+        {
+            PVBOXMOUSE_DEVEXT pNewCurDevExt = PVBOXMOUSE_DEVEXT_FROM_LE(pCur);
+            ASMAtomicWritePtr(&g_ctx.pCurrentDevExt, pNewCurDevExt);
+            /* ensure the object is not deleted while it is being used by a poller thread */
+            ObReferenceObject(pNewCurDevExt->pdoSelf);
+            break;
+        }
+    }
+
+    fDoEventUnregister = IsListEmpty(&g_ctx.DevExtList);
+    KeReleaseSpinLock(&g_ctx.SyncLock, Irql);
+
+    if (fDoEventUnregister)
+    {
+        if (vboxNewProtIsStarted())
+        {
+            Status = VBoxGdcSetMouseNotifyEvent(NULL);
+            if (!NT_SUCCESS(Status))
+            {
+                WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
+            }
+
+            ASMAtomicWriteBool(&g_ctx.fIsNewProtEnabled, false);
+        }
+    }
+
+    return Status;
 }
 
@@ -289,5 +380,5 @@
                     pData->LastY = pDevExt->pSCReq->pointerYPos;
                     pData->Flags = MOUSE_MOVE_ABSOLUTE;
-                    if (vboxNewProtIsSupported())
+                    if (vboxNewProtIsStarted())
                         pData->Flags |= MOUSE_VIRTUAL_DESKTOP;
                     pData++;
@@ -353,8 +444,8 @@
                 WARN(("VBGL init failed with rc=%#x", rc));
             }
-
-            vboxNewProtInit(pDevExt);
-        }
-    }
+        }
+    }
+
+    vboxNewProtDeviceAdded(pDevExt);
 
     if (!vboxIsHostMouseFound())
@@ -454,5 +545,5 @@
         {
             req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
-            if (vboxNewProtIsSupported())
+            if (vboxNewProtIsStarted())
                 req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL;
 
@@ -543,8 +634,8 @@
     LONG callCnt = InterlockedDecrement(&g_ctx.cDevicesStarted);
 
+    vboxNewProtDeviceRemoved(pDevExt);
+
     if (callCnt == 0)
     {
-        vboxNewProtTerm();
-
         if (vboxIsVBGLInited())
         {
