Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 45761)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 45763)
@@ -81,4 +81,37 @@
 static HANDLE vboxDtGetNotifyEvent();
 
+/* caps API */
+#define VBOXCAPS_ENTRY_IDX_SEAMLESS  0
+#define VBOXCAPS_ENTRY_IDX_GRAPHICS  1
+#define VBOXCAPS_ENTRY_IDX_COUNT     2
+
+typedef enum VBOXCAPS_ENTRY_FUNCSTATE
+{
+    /* the cap is unsupported */
+    VBOXCAPS_ENTRY_FUNCSTATE_UNSUPPORTED = 0,
+    /* the cap is supported */
+    VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED,
+    /* the cap functionality is started, it can be disabled however if its AcState is not ACQUIRED */
+    VBOXCAPS_ENTRY_FUNCSTATE_STARTED,
+} VBOXCAPS_ENTRY_FUNCSTATE;
+
+
+static void VBoxCapsEntryFuncStateSet(uint32_t iCup, VBOXCAPS_ENTRY_FUNCSTATE enmFuncState);
+static int VBoxCapsInit();
+static int VBoxCapsReleaseAll();
+static void VBoxCapsTerm();
+static BOOL VBoxCapsEntryIsAcquired(uint32_t iCap);
+static BOOL VBoxCapsEntryIsEnabled(uint32_t iCap);
+static BOOL VBoxCapsCheckTimer(WPARAM wParam);
+static int VBoxCapsEntryRelease(uint32_t iCap);
+static int VBoxCapsEntryAcquire(uint32_t iCap);
+static int VBoxCapsAcquireAllSupported();
+
+/* console-related caps API */
+static BOOL VBoxConsoleIsAllowed();
+static void VBoxConsoleEnable(BOOL fEnable);
+static void VBoxConsoleCapSetSupported(uint32_t iCap, BOOL fSupported);
+
+static void VBoxGrapicsSetSupported(BOOL fSupported);
 
 /*******************************************************************************
@@ -105,5 +138,4 @@
 NOTIFYICONDATA        gNotifyIconData;
 DWORD                 gMajorVersion;
-BOOL                  gfIsSeamlessOn = FALSE;
 
 
@@ -657,9 +689,19 @@
                  */
 
-                HANDLE hWaitEvent[3] = { ghStopSem, ghSeamlessWtNotifyEvent, vboxDtGetNotifyEvent() };
-                DWORD dwEventCount = RT_ELEMENTS(hWaitEvent);
-
-                if (0 == ghSeamlessWtNotifyEvent) /* If seamless mode is not active / supported, reduce event array count. */
-                    dwEventCount = 1;
+                HANDLE hWaitEvent[3] = {0};
+                DWORD dwEventCount = 0;
+
+                hWaitEvent[dwEventCount++] = ghStopSem;
+
+                /* Check if seamless mode is not active and add seamless event to the list */
+                if (0 != ghSeamlessWtNotifyEvent)
+                {
+                    hWaitEvent[dwEventCount++] = ghSeamlessWtNotifyEvent;
+                }
+
+                if (0 != vboxDtGetNotifyEvent())
+                {
+                    hWaitEvent[dwEventCount++] = vboxDtGetNotifyEvent();
+                }
 
                 Log(("VBoxTray: Number of events to wait in main loop: %ld\n", dwEventCount));
@@ -678,41 +720,48 @@
                         break;
                     }
-                    else if (   waitResult == 1
-                             && ghSeamlessWtNotifyEvent != 0) /* Only jump in, if seamless is active! */
+                    else
                     {
-                        Log(("VBoxTray: Event 'Seamless' triggered\n"));
-
-                        /* seamless window notification */
-                        VBoxSeamlessCheckWindows();
-                    }
-                    else if (   waitResult == 2
-                             && vboxDtGetNotifyEvent() != 0) /* Only jump in, if Dt is active! */
-                    {
-                        BOOL fOldSeamlessAllowedState = VBoxSeamlessIsAllowed();
-                        if (vboxDtHandleEvent())
+                        BOOL fHandled = FALSE;
+                        if (waitResult < RT_ELEMENTS(hWaitEvent))
                         {
-                            if (!VBoxSeamlessIsAllowed() != !fOldSeamlessAllowedState)
+                            if (hWaitEvent[waitResult])
                             {
-                                rc = VBoxSeamlessOnAllowChange(!fOldSeamlessAllowedState);
-                                if (!RT_SUCCESS(rc))
-                                    Log(("VBoxTray: WndProc: Failed to set seamless capability\n"));
+                                if (hWaitEvent[waitResult] == ghSeamlessWtNotifyEvent)
+                                {
+                                    Log(("VBoxTray: Event 'Seamless' triggered\n"));
+
+                                    /* seamless window notification */
+                                    VBoxSeamlessCheckWindows();
+                                    fHandled = TRUE;
+                                }
+                                else if (hWaitEvent[waitResult] == vboxDtGetNotifyEvent())
+                                {
+                                    Log(("VBoxTray: Event 'Dt' triggered\n"));
+                                    BOOL fOldAllowedState = VBoxConsoleIsAllowed();
+                                    if (vboxDtHandleEvent())
+                                    {
+                                        if (!VBoxConsoleIsAllowed() != !fOldAllowedState)
+                                            VBoxConsoleEnable(!fOldAllowedState);
+                                    }
+                                    fHandled = TRUE;
+                                }
                             }
                         }
-                    }
-                    else
-                    {
-                        /* timeout or a window message, handle it */
-                        MSG msg;
-                        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+
+                        if (!fHandled)
                         {
-                            Log(("VBoxTray: msg %p\n", msg.message));
-                            if (msg.message == WM_QUIT)
+                            /* timeout or a window message, handle it */
+                            MSG msg;
+                            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                             {
-                                Log(("VBoxTray: WM_QUIT!\n"));
-                                SetEvent(ghStopSem);
-                                continue;
+                                Log(("VBoxTray: msg %p\n", msg.message));
+                                if (msg.message == WM_QUIT)
+                                {
+                                    Log(("VBoxTray: WM_QUIT!\n"));
+                                    SetEvent(ghStopSem);
+                                }
+                                TranslateMessage(&msg);
+                                DispatchMessage(&msg);
                             }
-                            TranslateMessage(&msg);
-                            DispatchMessage(&msg);
                         }
                     }
@@ -767,4 +816,6 @@
         if (RT_SUCCESS(rc))
         {
+            VBoxCapsInit();
+
             rc = vboxStInit(ghwndToolWindow);
             if (!RT_SUCCESS(rc))
@@ -803,4 +854,6 @@
             vboxStTerm();
 
+            VBoxCapsTerm();
+
             vboxTrayDestroyToolWindow();
         }
@@ -854,4 +907,7 @@
 
         case WM_TIMER:
+            if (VBoxCapsCheckTimer(wParam))
+                return 0;
+
             switch (wParam)
             {
@@ -881,18 +937,22 @@
 
         case WM_VBOX_SEAMLESS_ENABLE:
-            gfIsSeamlessOn = TRUE;
-            if (VBoxSeamlessIsAllowed())
-                VBoxSeamlessInstallHook();
+            VBoxCapsEntryFuncStateSet(VBOXCAPS_ENTRY_IDX_SEAMLESS, VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
             return 0;
 
         case WM_VBOX_SEAMLESS_DISABLE:
-            gfIsSeamlessOn = FALSE;
-            if (VBoxSeamlessIsAllowed())
-                VBoxSeamlessRemoveHook();
+            VBoxCapsEntryFuncStateSet(VBOXCAPS_ENTRY_IDX_SEAMLESS, VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED);
             return 0;
 
         case WM_VBOX_SEAMLESS_UPDATE:
-            if (gfIsSeamlessOn && VBoxSeamlessIsAllowed())
+            if (VBoxCapsEntryIsEnabled(VBOXCAPS_ENTRY_IDX_SEAMLESS))
                 VBoxSeamlessCheckWindows();
+            return 0;
+
+        case WM_VBOX_GRAPHICS_SUPPORTED:
+            VBoxGrapicsSetSupported(TRUE);
+            return 0;
+
+        case WM_VBOX_GRAPHICS_UNSUPPORTED:
+            VBoxGrapicsSetSupported(FALSE);
             return 0;
 
@@ -907,13 +967,9 @@
         case WM_WTSSESSION_CHANGE:
         {
-            BOOL fOldSeamlessAllowedState = VBoxSeamlessIsAllowed();
+            BOOL fOldAllowedState = VBoxConsoleIsAllowed();
             if (vboxStHandleEvent(wParam, lParam))
             {
-                if (!VBoxSeamlessIsAllowed() != !fOldSeamlessAllowedState)
-                {
-                    int rc = VBoxSeamlessOnAllowChange(!fOldSeamlessAllowedState);
-                    if (!RT_SUCCESS(rc))
-                        Log(("VBoxTray: WndProc: Failed to set seamless capability\n"));
-                }
+                if (!VBoxConsoleIsAllowed() != !fOldAllowedState)
+                    VBoxConsoleEnable(!fOldAllowedState);
             }
             return 0;
@@ -1302,28 +1358,347 @@
 
 
-/* helper state tracking API */
-BOOL VBoxSeamlessIsAllowed()
+/* we need to perform Acquire/Release using the file handled we use for rewuesting events from VBoxGuest
+ * otherwise Acquisition mechanism will treat us as different client and will not propagate necessary requests
+ * */
+static int VBoxAcquireGuestCaps(uint32_t fOr, uint32_t fNot)
+{
+    DWORD cbReturned = 0;
+    VBoxGuestCapsAquire Info;
+    Info.rc = VERR_NOT_IMPLEMENTED;
+    Info.u32OrMask = fOr;
+    Info.u32NotMask = fNot;
+    if (!DeviceIoControl(ghVBoxDriver, VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE, &Info, sizeof(Info), &Info, sizeof(Info), &cbReturned, NULL))
+    {
+        DWORD LastErr = GetLastError();
+        WARN(("DeviceIoControl VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE failed LastErr %d", LastErr));
+        return RTErrConvertFromWin32(LastErr);
+    }
+
+    int rc = Info.rc;
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE failed rc %d", rc));
+        return rc;
+    }
+
+    return rc;
+}
+
+typedef enum VBOXCAPS_ENTRY_ACSTATE
+{
+    /* the given cap is released */
+    VBOXCAPS_ENTRY_ACSTATE_RELEASED = 0,
+    /* the given cap acquisition is in progress */
+    VBOXCAPS_ENTRY_ACSTATE_ACQUIRING,
+    /* the given cap is acquired */
+    VBOXCAPS_ENTRY_ACSTATE_ACQUIRED
+} VBOXCAPS_ENTRY_ACSTATE;
+
+
+struct VBOXCAPS_ENTRY;
+struct VBOXCAPS;
+
+typedef DECLCALLBACKPTR(void, PFNVBOXCAPS_ENTRY_ON_ENABLE)(struct VBOXCAPS *pConsole, struct VBOXCAPS_ENTRY *pCap, BOOL fEnabled);
+
+typedef struct VBOXCAPS_ENTRY
+{
+    uint32_t fCap;
+    uint32_t iCap;
+    /* the functionality is supported by the guest */
+    BOOL fIsSupported;
+    /* */
+    BOOL fIsOn;
+    VBOXCAPS_ENTRY_FUNCSTATE enmFuncState;
+    VBOXCAPS_ENTRY_ACSTATE enmAcState;
+    PFNVBOXCAPS_ENTRY_ON_ENABLE pfnOnEnable;
+} VBOXCAPS_ENTRY;
+
+
+typedef struct VBOXCAPS
+{
+    UINT_PTR idTimer;
+    VBOXCAPS_ENTRY aCaps[VBOXCAPS_ENTRY_IDX_COUNT];
+} VBOXCAPS;
+
+static VBOXCAPS gVBoxCaps;
+
+static DECLCALLBACK(void) vboxCapsOnEnableSeamles(struct VBOXCAPS *pConsole, struct VBOXCAPS_ENTRY *pCap, BOOL fEnabled)
+{
+    if (fEnabled)
+    {
+        Assert(pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
+        Assert(pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
+        VBoxSeamlessInstallHook();
+    }
+    else
+    {
+        Assert(pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_ACQUIRED || pCap->enmFuncState != VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
+        VBoxSeamlessRemoveHook();
+    }
+}
+
+static void vboxCapsEntryAcStateSet(VBOXCAPS_ENTRY *pCap, VBOXCAPS_ENTRY_ACSTATE enmAcState)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    if (pCap->enmAcState == enmAcState)
+        return;
+
+    VBOXCAPS_ENTRY_ACSTATE enmOldAcState = pCap->enmAcState;
+    pCap->enmAcState = enmAcState;
+
+    if (enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED)
+    {
+        if (pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED)
+        {
+            if (pCap->pfnOnEnable)
+                pCap->pfnOnEnable(pConsole, pCap, TRUE);
+        }
+    }
+    else if (enmOldAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED && pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED)
+    {
+        if (pCap->pfnOnEnable)
+            pCap->pfnOnEnable(pConsole, pCap, FALSE);
+    }
+}
+
+static void vboxCapsEntryFuncStateSet(VBOXCAPS_ENTRY *pCap, VBOXCAPS_ENTRY_FUNCSTATE enmFuncState)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    if (pCap->enmFuncState == enmFuncState)
+        return;
+
+    VBOXCAPS_ENTRY_FUNCSTATE enmOldFuncState = pCap->enmFuncState;
+
+    pCap->enmFuncState = enmFuncState;
+
+    if (enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED)
+    {
+        Assert(enmOldFuncState == VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED);
+        if (pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED)
+        {
+            if (pCap->pfnOnEnable)
+                pCap->pfnOnEnable(pConsole, pCap, TRUE);
+        }
+    }
+    else if (pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED && enmOldFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED)
+    {
+        if (pCap->pfnOnEnable)
+            pCap->pfnOnEnable(pConsole, pCap, FALSE);
+    }
+}
+
+static void VBoxCapsEntryFuncStateSet(uint32_t iCup, VBOXCAPS_ENTRY_FUNCSTATE enmFuncState)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCup];
+    vboxCapsEntryFuncStateSet(pCap, enmFuncState);
+}
+
+static int VBoxCapsInit()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    memset(pConsole, 0, sizeof (*pConsole));
+    pConsole->aCaps[VBOXCAPS_ENTRY_IDX_SEAMLESS].fCap = VMMDEV_GUEST_SUPPORTS_SEAMLESS;
+    pConsole->aCaps[VBOXCAPS_ENTRY_IDX_SEAMLESS].iCap = VBOXCAPS_ENTRY_IDX_SEAMLESS;
+    pConsole->aCaps[VBOXCAPS_ENTRY_IDX_SEAMLESS].pfnOnEnable = vboxCapsOnEnableSeamles;
+    pConsole->aCaps[VBOXCAPS_ENTRY_IDX_GRAPHICS].fCap = VMMDEV_GUEST_SUPPORTS_GRAPHICS;
+    pConsole->aCaps[VBOXCAPS_ENTRY_IDX_GRAPHICS].iCap = VBOXCAPS_ENTRY_IDX_GRAPHICS;
+    return VINF_SUCCESS;
+}
+
+static int VBoxCapsReleaseAll()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    int rc = VBoxAcquireGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS | VMMDEV_GUEST_SUPPORTS_GRAPHICS);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("VBoxTray: vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
+        return rc;
+    }
+
+    if (pConsole->idTimer)
+    {
+        KillTimer(ghwndToolWindow, pConsole->idTimer);
+        pConsole->idTimer = 0;
+    }
+
+    for (int i = 0; i < RT_ELEMENTS(pConsole->aCaps); ++i)
+    {
+        vboxCapsEntryAcStateSet(&pConsole->aCaps[i], VBOXCAPS_ENTRY_ACSTATE_RELEASED);
+    }
+
+    return rc;
+}
+
+static void VBoxCapsTerm()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBoxCapsReleaseAll();
+    memset(pConsole, 0, sizeof (*pConsole));
+}
+
+static BOOL VBoxCapsEntryIsAcquired(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    return pConsole->aCaps[iCap].enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED;
+}
+
+static BOOL VBoxCapsEntryIsEnabled(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    return pConsole->aCaps[iCap].enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED
+            && pConsole->aCaps[iCap].enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED;
+}
+
+static BOOL VBoxCapsCheckTimer(WPARAM wParam)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    if (wParam != pConsole->idTimer)
+        return FALSE;
+
+    uint32_t u32AcquiredCaps = 0;
+    BOOL fNeedNewTimer = FALSE;
+
+    for (int i = 0; i < RT_ELEMENTS(pConsole->aCaps); ++i)
+    {
+        VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[i];
+        if (pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_ACQUIRING)
+            continue;
+
+        int rc = VBoxAcquireGuestCaps(pCap->fCap, 0);
+        if (RT_SUCCESS(rc))
+        {
+            vboxCapsEntryAcStateSet(&pConsole->aCaps[i], VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
+            u32AcquiredCaps |= pCap->fCap;
+        }
+        else
+        {
+            Assert(rc == VERR_RESOURCE_BUSY);
+            fNeedNewTimer = TRUE;
+        }
+    }
+
+    if (!fNeedNewTimer)
+    {
+        KillTimer(ghwndToolWindow, pConsole->idTimer);
+        /* cleanup timer data */
+        pConsole->idTimer = 0;
+    }
+
+    return TRUE;
+}
+
+static int VBoxCapsEntryRelease(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCap];
+    if (pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_RELEASED)
+    {
+        WARN(("invalid cap[%d] state[%d] on release\n", iCap, pCap->enmAcState));
+        return VERR_INVALID_STATE;
+    }
+
+    if (pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED)
+    {
+        int rc = VBoxAcquireGuestCaps(0, pCap->fCap);
+        AssertRC(rc);
+    }
+
+    vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_RELEASED);
+
+    return VINF_SUCCESS;
+}
+
+static int VBoxCapsEntryAcquire(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    Assert(VBoxConsoleIsAllowed());
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCap];
+    if (pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_RELEASED)
+    {
+        WARN(("invalid cap[%d] state[%d] on acquire\n", iCap, pCap->enmAcState));
+        return VERR_INVALID_STATE;
+    }
+
+    vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_ACQUIRING);
+    int rc = VBoxAcquireGuestCaps(pCap->fCap, 0);
+    if (RT_SUCCESS(rc))
+    {
+        vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
+        return VINF_SUCCESS;
+    }
+
+    if (rc != VERR_RESOURCE_BUSY)
+    {
+        WARN(("VBoxTray: vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
+        return rc;
+    }
+
+    WARN(("VBoxTray: iCap %d is busy!\n", iCap));
+
+    /* the cap was busy, most likely it is still used by other VBoxTray instance running in another session,
+     * queue the retry timer */
+    if (!pConsole->idTimer)
+    {
+        pConsole->idTimer = SetTimer(ghwndToolWindow, TIMERID_VBOXTRAY_CAPS_TIMER, 100, (TIMERPROC)NULL);
+        if (!pConsole->idTimer)
+        {
+            DWORD dwErr = GetLastError();
+            WARN(("VBoxTray: SetTimer error %08X\n", dwErr));
+            return RTErrConvertFromWin32(dwErr);
+        }
+    }
+
+    return rc;
+}
+
+static int VBoxCapsAcquireAllSupported()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    for (int i = 0; i < RT_ELEMENTS(pConsole->aCaps); ++i)
+    {
+        if (pConsole->aCaps[i].enmFuncState >= VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED)
+            VBoxCapsEntryAcquire(i);
+    }
+    return VINF_SUCCESS;
+}
+
+static BOOL VBoxConsoleIsAllowed()
 {
     return vboxDtIsInputDesktop() && vboxStIsActiveConsole();
 }
 
-int VBoxSeamlessOnAllowChange(BOOL fAllowed)
-{
-    int rc;
-    if (fAllowed)
-    {
-        rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_SEAMLESS, 0);
-        if (gfIsSeamlessOn)
-            VBoxSeamlessInstallHook();
-    }
+static void VBoxConsoleEnable(BOOL fEnable)
+{
+    if (fEnable)
+        VBoxCapsAcquireAllSupported();
     else
-    {
-        if (gfIsSeamlessOn)
-            VBoxSeamlessRemoveHook();
-        rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS);
-    }
-    if (!RT_SUCCESS(rc))
-        WARN(("VBoxTray: VMMDEV_GUEST_SUPPORTS_SEAMLESS: Failed to %s seamless capability\n", fAllowed ? "set" : "clear" ));
-
-    return rc;
-}
+        VBoxCapsReleaseAll();
+}
+
+static void VBoxConsoleCapSetSupported(uint32_t iCap, BOOL fSupported)
+{
+    if (fSupported)
+    {
+        VBoxCapsEntryFuncStateSet(iCap, VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED);
+
+        if (VBoxConsoleIsAllowed())
+            VBoxCapsEntryAcquire(iCap);
+    }
+    else
+    {
+        VBoxCapsEntryFuncStateSet(iCap, VBOXCAPS_ENTRY_FUNCSTATE_UNSUPPORTED);
+
+        VBoxCapsEntryRelease(iCap);
+    }
+}
+
+void VBoxSeamlessSetSupported(BOOL fSupported)
+{
+    VBoxConsoleCapSetSupported(VBOXCAPS_ENTRY_IDX_SEAMLESS, fSupported);
+}
+
+static void VBoxGrapicsSetSupported(BOOL fSupported)
+{
+    VBoxConsoleCapSetSupported(VBOXCAPS_ENTRY_IDX_GRAPHICS, fSupported);
+}
