Index: trunk/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c	(revision 40388)
+++ trunk/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c	(revision 40483)
@@ -596,8 +596,14 @@
  */
 /** @todo use vbglR3DoIOCtl here instead */
-static int crVBoxHGCMCall(void *pvData, unsigned cbData)
+static int crVBoxHGCMCall(CRConnection *conn, void *pvData, unsigned cbData)
 {
 #ifdef IN_GUEST
-
+    PCRVBOXHGSMI_CLIENT pClient = _crVBoxHGSMIClientGet(conn);
+    if (pClient)
+    {
+        return VBoxCrHgsmiCtlConCall(pClient->pHgsmi, (struct VBoxGuestHGCMCallInfo *)pvData, cbData);
+    }
+    else
+    {
 # ifdef RT_OS_WINDOWS
     DWORD cbReturned, lerr;
@@ -683,5 +689,5 @@
     return VERR_NOT_SUPPORTED;
 # endif /*#ifdef RT_OS_WINDOWS*/
-
+    }
 #else /*#ifdef IN_GUEST*/
     crError("crVBoxHGCMCall called on host side!");
@@ -853,5 +859,5 @@
         parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
-        rc = crVBoxHGCMCall(&parms, sizeof(parms));
+        rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
         callRes = parms.hdr.result;
     }
@@ -870,5 +876,5 @@
         parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
-        rc = crVBoxHGCMCall(&parms, sizeof(parms));
+        rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
         callRes = parms.hdr.result;
     }
@@ -911,5 +917,5 @@
     parms.cbBuffer.u.value32 = 0;
 
-    rc = crVBoxHGCMCall(&parms, sizeof(parms));
+    rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
 
     if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
@@ -967,5 +973,5 @@
     parms.cbWriteback.u.value32 = 0;
 
-    rc = crVBoxHGCMCall(&parms, sizeof(parms));
+    rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
 
 #if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS)
@@ -1003,5 +1009,5 @@
             crDebug("SHCRGL_GUEST_FN_WRITE_BUFFER, offset=%u, size=%u", wbParms.ui32Offset.u.value32, wbParms.pBuffer.u.Pointer.size);
 
-            rc = crVBoxHGCMCall(&wbParms, sizeof(wbParms));
+            rc = crVBoxHGCMCall(conn, &wbParms, sizeof(wbParms));
             if (RT_FAILURE(rc) || RT_FAILURE(wbParms.hdr.result))
             {
@@ -1028,5 +1034,5 @@
             crMemcpy(&wrbParms.cbWriteback, &parms.cbWriteback, sizeof(HGCMFunctionParameter));
 
-            rc = crVBoxHGCMCall(&wrbParms, sizeof(wrbParms));
+            rc = crVBoxHGCMCall(conn, &wrbParms, sizeof(wrbParms));
 
             /*bit of hack to reuse code below*/
@@ -1164,5 +1170,5 @@
     parms.cbBuffer.u.value32 = 0;
 
-    rc = crVBoxHGCMCall(&parms, sizeof(parms));
+    rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
 
     if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
@@ -1372,5 +1378,5 @@
     parms.vMinor.u.value32 = CR_PROTOCOL_VERSION_MINOR;
 
-    rc = crVBoxHGCMCall(&parms, sizeof(parms));
+    rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
 
     if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
@@ -1400,5 +1406,5 @@
     parms.u64PID.u.value64 = pid;
 
-    rc = crVBoxHGCMCall(&parms, sizeof(parms));
+    rc = crVBoxHGCMCall(conn, &parms, sizeof(parms));
 
     if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
@@ -1442,4 +1448,5 @@
         {
             crDebug("could not open VBox Guest Additions driver! rc = %d\n", GetLastError());
+            CRASSERT(0);
             VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
             return FALSE;
@@ -1533,4 +1540,38 @@
 }
 
+static bool _crVBoxCommonDoDisconnectLocked( CRConnection *conn )
+{
+    int i;
+    if (conn->pHostBuffer)
+    {
+        crFree(conn->pHostBuffer);
+        conn->pHostBuffer = NULL;
+        conn->cbHostBuffer = 0;
+        conn->cbHostBufferAllocated = 0;
+    }
+
+    conn->pBuffer = NULL;
+    conn->cbBuffer = 0;
+
+    if (conn->type == CR_VBOXHGCM)
+    {
+        --g_crvboxhgcm.num_conns;
+
+        if (conn->index < g_crvboxhgcm.num_conns)
+        {
+            g_crvboxhgcm.conns[conn->index] = g_crvboxhgcm.conns[g_crvboxhgcm.num_conns];
+            g_crvboxhgcm.conns[conn->index]->index = conn->index;
+        }
+        else g_crvboxhgcm.conns[conn->index] = NULL;
+
+        conn->type = CR_NO_CONNECTION;
+    }
+
+    for (i = 0; i < g_crvboxhgcm.num_conns; i++)
+        if (g_crvboxhgcm.conns[i] && g_crvboxhgcm.conns[i]->type != CR_NO_CONNECTION)
+            return true;
+    return false;
+}
+
 /*@todo same, replace DeviceIoControl with vbglR3DoIOCtl */
 static void crVBoxHGCMDoDisconnect( CRConnection *conn )
@@ -1541,6 +1582,6 @@
     DWORD cbReturned;
 # endif
-    int i;
-#endif
+#endif
+    bool fHasActiveCons = false;
 
     if (!g_crvboxhgcm.initialized) return;
@@ -1552,28 +1593,5 @@
     VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
-    if (conn->pHostBuffer)
-    {
-        crFree(conn->pHostBuffer);
-        conn->pHostBuffer = NULL;
-        conn->cbHostBuffer = 0;
-        conn->cbHostBufferAllocated = 0;
-    }
-
-    conn->pBuffer = NULL;
-    conn->cbBuffer = 0;
-
-    if (conn->type == CR_VBOXHGCM)
-    {
-        --g_crvboxhgcm.num_conns;
-
-        if (conn->index < g_crvboxhgcm.num_conns)
-        {
-            g_crvboxhgcm.conns[conn->index] = g_crvboxhgcm.conns[g_crvboxhgcm.num_conns];
-            g_crvboxhgcm.conns[conn->index]->index = conn->index;
-        }
-        else g_crvboxhgcm.conns[conn->index] = NULL;
-
-        conn->type = CR_NO_CONNECTION;
-    }
+    fHasActiveCons = _crVBoxCommonDoDisconnectLocked(conn);
 
 #ifndef IN_GUEST
@@ -1613,11 +1631,6 @@
     }
 
-    /* see if any connections remain */
-    for (i = 0; i < g_crvboxhgcm.num_conns; i++)
-        if (g_crvboxhgcm.conns[i] && g_crvboxhgcm.conns[i]->type != CR_NO_CONNECTION)
-            break;
-
     /* close guest additions driver*/
-    if (i>=g_crvboxhgcm.num_conns)
+    if (!fHasActiveCons)
     {
 # ifdef RT_OS_WINDOWS
@@ -1672,5 +1685,5 @@
         int rc;
 #ifndef VBOX_CRHGSMI_WITH_D3DDEV
-        rc = VBoxCrHgsmiInit();
+        rc = VBoxCrHgsmiInit(CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR);
 #else
         VBOXCRHGSMI_CALLBACKS Callbacks;
@@ -2305,12 +2318,43 @@
 static int crVBoxHGSMIDoConnect( CRConnection *conn )
 {
-    return crVBoxHGCMDoConnect(conn);
+    PCRVBOXHGSMI_CLIENT pClient;
+    int rc = VINF_SUCCESS;
+
+#ifdef CHROMIUM_THREADSAFE
+    crLockMutex(&g_crvboxhgcm.mutex);
+#endif
+
+    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
+
+    pClient = _crVBoxHGSMIClientGet(conn);
+    CRASSERT(pClient);
+    if (pClient)
+    {
+        rc = VBoxCrHgsmiCtlConGetClientID(pClient->pHgsmi, &conn->u32ClientID);
+        CRASSERT(RT_SUCCESS(rc));
+    }
+
+    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
+
+#ifdef CHROMIUM_THREADSAFE
+    crUnlockMutex(&g_crvboxhgcm.mutex);
+#endif
+    return RT_SUCCESS(rc);
 }
 
 static void crVBoxHGSMIDoDisconnect( CRConnection *conn )
 {
+    bool fHasActiveCons = false;
+
+    if (!g_crvboxhgcm.initialized) return;
+
+    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
+
 #ifdef CHROMIUM_THREADSAFE
     crLockMutex(&g_crvboxhgcm.mutex);
 #endif
+
+    fHasActiveCons = _crVBoxCommonDoDisconnectLocked(conn);
+
 #ifndef VBOX_CRHGSMI_WITH_D3DDEV
     if (conn->HgsmiClient.pHgsmi)
@@ -2321,6 +2365,10 @@
         VBoxCrHgsmiDestroy(pHgsmi);
     }
-#endif
-    crVBoxHGCMDoDisconnect(conn);
+#else
+# error "port me!"
+#endif
+
+    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
+
 #ifdef CHROMIUM_THREADSAFE
     crUnlockMutex(&g_crvboxhgcm.mutex);
