Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 95965)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 95966)
@@ -39,4 +39,7 @@
 VBoxTray_SOURCES  = \
 	VBoxTray.cpp \
+	VBoxCaps.cpp \
+	VBoxConsole.cpp \
+	VBoxDesktopTracking.cpp \
 	VBoxDispIf.cpp \
 	VBoxSeamless.cpp \
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxCaps.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxCaps.cpp	(revision 95966)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxCaps.cpp	(revision 95966)
@@ -0,0 +1,334 @@
+/* $Id$ */
+/** @file
+ * VBoxCaps.cpp - Capability APIs.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/log.h>
+
+#include "VBoxTray.h"
+#include "VBoxTrayInternal.h"
+#include "VBoxSeamless.h"
+
+
+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;
+    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;
+
+
+/* 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
+ * */
+int VBoxAcquireGuestCaps(uint32_t fOr, uint32_t fNot, bool fCfg)
+{
+    Log(("VBoxAcquireGuestCaps or(0x%x), not(0x%x), cfx(%d)\n", fOr, fNot, fCfg));
+    int rc = VbglR3AcquireGuestCaps(fOr, fNot, fCfg);
+    if (RT_FAILURE(rc))
+        LogFlowFunc(("VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE failed: %Rrc\n", rc));
+    return rc;
+}
+
+static DECLCALLBACK(void) vboxCapsOnEnableSeamless(struct VBOXCAPS *pConsole, struct VBOXCAPS_ENTRY *pCap, BOOL fEnabled)
+{
+    RT_NOREF(pConsole, pCap);
+    if (fEnabled)
+    {
+        Log(("vboxCapsOnEnableSeamless: ENABLED\n"));
+        Assert(pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
+        Assert(pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
+        VBoxSeamlessEnable();
+    }
+    else
+    {
+        Log(("vboxCapsOnEnableSeamless: DISABLED\n"));
+        Assert(pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_ACQUIRED || pCap->enmFuncState != VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
+        VBoxSeamlessDisable();
+    }
+}
+
+static void vboxCapsEntryAcStateSet(VBOXCAPS_ENTRY *pCap, VBOXCAPS_ENTRY_ACSTATE enmAcState)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+
+    Log(("vboxCapsEntryAcStateSet: new state enmAcState(%d); pCap: fCap(%d), iCap(%d), enmFuncState(%d), enmAcState(%d)\n",
+            enmAcState, pCap->fCap, pCap->iCap, pCap->enmFuncState, pCap->enmAcState));
+
+    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;
+
+    Log(("vboxCapsEntryFuncStateSet: new state enmAcState(%d); pCap: fCap(%d), iCap(%d), enmFuncState(%d), enmAcState(%d)\n",
+            enmFuncState, pCap->fCap, pCap->iCap, pCap->enmFuncState, pCap->enmAcState));
+
+    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);
+    }
+}
+
+void VBoxCapsEntryFuncStateSet(uint32_t iCup, VBOXCAPS_ENTRY_FUNCSTATE enmFuncState)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCup];
+    vboxCapsEntryFuncStateSet(pCap, enmFuncState);
+}
+
+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 = vboxCapsOnEnableSeamless;
+    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;
+}
+
+int VBoxCapsReleaseAll()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    Log(("VBoxCapsReleaseAll\n"));
+    int rc = VBoxAcquireGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS | VMMDEV_GUEST_SUPPORTS_GRAPHICS, false);
+    if (!RT_SUCCESS(rc))
+    {
+        LogFlowFunc(("vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
+        return rc;
+    }
+
+    if (pConsole->idTimer)
+    {
+        Log(("killing console timer\n"));
+        KillTimer(g_hwndToolWindow, 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;
+}
+
+void VBoxCapsTerm()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBoxCapsReleaseAll();
+    memset(pConsole, 0, sizeof (*pConsole));
+}
+
+BOOL VBoxCapsEntryIsAcquired(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    return pConsole->aCaps[iCap].enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED;
+}
+
+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;
+}
+
+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, false);
+        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(g_hwndToolWindow, pConsole->idTimer);
+        /* cleanup timer data */
+        pConsole->idTimer = 0;
+    }
+
+    return TRUE;
+}
+
+int VBoxCapsEntryRelease(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCap];
+    if (pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_RELEASED)
+    {
+        LogFlowFunc(("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, false);
+        AssertRC(rc);
+    }
+
+    vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_RELEASED);
+
+    return VINF_SUCCESS;
+}
+
+int VBoxCapsEntryAcquire(uint32_t iCap)
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    Assert(VBoxConsoleIsAllowed());
+    VBOXCAPS_ENTRY *pCap = &pConsole->aCaps[iCap];
+    Log(("VBoxCapsEntryAcquire %d\n", iCap));
+    if (pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_RELEASED)
+    {
+        LogFlowFunc(("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, false);
+    if (RT_SUCCESS(rc))
+    {
+        vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
+        return VINF_SUCCESS;
+    }
+
+    if (rc != VERR_RESOURCE_BUSY)
+    {
+        LogFlowFunc(("vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
+        return rc;
+    }
+
+    LogFlowFunc(("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(g_hwndToolWindow, TIMERID_VBOXTRAY_CAPS_TIMER, 100, (TIMERPROC)NULL);
+        if (!pConsole->idTimer)
+        {
+            DWORD dwErr = GetLastError();
+            LogFlowFunc(("SetTimer error %08X\n", dwErr));
+            return RTErrConvertFromWin32(dwErr);
+        }
+    }
+
+    return rc;
+}
+
+int VBoxCapsAcquireAllSupported()
+{
+    VBOXCAPS *pConsole = &gVBoxCaps;
+    Log(("VBoxCapsAcquireAllSupported\n"));
+    for (int i = 0; i < RT_ELEMENTS(pConsole->aCaps); ++i)
+    {
+        if (pConsole->aCaps[i].enmFuncState >= VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED)
+        {
+            Log(("VBoxCapsAcquireAllSupported acquiring cap %d, state %d\n", i, pConsole->aCaps[i].enmFuncState));
+            VBoxCapsEntryAcquire(i);
+        }
+        else
+        {
+            LogFlowFunc(("VBoxCapsAcquireAllSupported: WARN: cap %d not supported, state %d\n", i, pConsole->aCaps[i].enmFuncState));
+        }
+    }
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxConsole.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxConsole.cpp	(revision 95966)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxConsole.cpp	(revision 95966)
@@ -0,0 +1,53 @@
+/* $Id$ */
+/** @file
+ * VBoxConsole.cpp - Console APIs.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "VBoxTray.h"
+#include "VBoxTrayInternal.h"
+
+
+/** @todo r=andy Lacks documentation / Doxygen headers. What does this, and why? */
+
+BOOL VBoxConsoleIsAllowed()
+{
+    return vboxDtIsInputDesktop() && vboxStIsActiveConsole();
+}
+
+void VBoxConsoleEnable(BOOL fEnable)
+{
+    if (fEnable)
+        VBoxCapsAcquireAllSupported();
+    else
+        VBoxCapsReleaseAll();
+}
+
+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);
+    }
+}
+
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDesktopTracking.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDesktopTracking.cpp	(revision 95966)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDesktopTracking.cpp	(revision 95966)
@@ -0,0 +1,242 @@
+/* $Id$ */
+/** @file
+ * VBoxDesktopTracking.cpp - Desktop tracking.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+#include <iprt/errcore.h>
+#include <iprt/ldr.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/system.h>
+#include <iprt/win/windows.h>
+
+#include <VBoxHook.h>
+
+#include "VBoxTray.h"
+#include "VBoxTrayInternal.h"
+
+/* Default desktop state tracking */
+#include <Wtsapi32.h>
+
+
+/** @todo r=andy Lacks documentation / Doxygen headers. What does this, and why? */
+
+/*
+ * Dt (desktop [state] tracking) functionality API impl
+ *
+ * !!!NOTE: this API is NOT thread-safe!!!
+ * */
+
+typedef struct VBOXDT
+{
+    HANDLE hNotifyEvent;
+    BOOL fIsInputDesktop;
+    UINT_PTR idTimer;
+    RTLDRMOD hLdrModHook;
+    BOOL (* pfnVBoxHookInstallActiveDesktopTracker)(HMODULE hDll);
+    BOOL (* pfnVBoxHookRemoveActiveDesktopTracker)();
+    HDESK (WINAPI * pfnGetThreadDesktop)(DWORD dwThreadId);
+    HDESK (WINAPI * pfnOpenInputDesktop)(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
+    BOOL (WINAPI * pfnCloseDesktop)(HDESK hDesktop);
+} VBOXDT;
+
+static VBOXDT gVBoxDt;
+
+BOOL vboxDtCalculateIsInputDesktop()
+{
+    BOOL fIsInputDt = FALSE;
+    HDESK hInput = gVBoxDt.pfnOpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
+    if (hInput)
+    {
+//        DWORD dwThreadId = GetCurrentThreadId();
+//        HDESK hThreadDt = gVBoxDt.pfnGetThreadDesktop(dwThreadId);
+//        if (hThreadDt)
+//        {
+            fIsInputDt = TRUE;
+//        }
+//        else
+//        {
+//            DWORD dwErr = GetLastError();
+//            LogFlowFunc(("pfnGetThreadDesktop for Seamless failed, last error = %08X\n", dwErr));
+//        }
+
+        gVBoxDt.pfnCloseDesktop(hInput);
+    }
+    else
+    {
+//        DWORD dwErr = GetLastError();
+//        LogFlowFunc(("pfnOpenInputDesktop for Seamless failed, last error = %08X\n", dwErr));
+    }
+    return fIsInputDt;
+}
+
+void VBoxTrayCheckDt()
+{
+    BOOL fOldAllowedState = VBoxConsoleIsAllowed();
+    if (vboxDtHandleEvent())
+    {
+        if (!VBoxConsoleIsAllowed() != !fOldAllowedState)
+            VBoxConsoleEnable(!fOldAllowedState);
+    }
+}
+
+BOOL vboxDtCheckTimer(WPARAM wParam)
+{
+    if (wParam != gVBoxDt.idTimer)
+        return FALSE;
+
+    VBoxTrayCheckDt();
+
+    return TRUE;
+}
+
+int vboxDtInit()
+{
+    RT_ZERO(gVBoxDt);
+
+    int rc;
+    gVBoxDt.hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
+    if (gVBoxDt.hNotifyEvent != NULL)
+    {
+        /* Load the hook dll and resolve the necessary entry points. */
+        rc = RTLdrLoadAppPriv(VBOXHOOK_DLL_NAME, &gVBoxDt.hLdrModHook);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookInstallActiveDesktopTracker",
+                                (void **)&gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker);
+            if (RT_SUCCESS(rc))
+            {
+                rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookRemoveActiveDesktopTracker",
+                                    (void **)&gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker);
+                if (RT_FAILURE(rc))
+                    LogFlowFunc(("VBoxHookRemoveActiveDesktopTracker not found\n"));
+            }
+            else
+                LogFlowFunc(("VBoxHookInstallActiveDesktopTracker not found\n"));
+            if (RT_SUCCESS(rc))
+            {
+                /* Try get the system APIs we need. */
+                *(void **)&gVBoxDt.pfnGetThreadDesktop = RTLdrGetSystemSymbol("user32.dll", "GetThreadDesktop");
+                if (!gVBoxDt.pfnGetThreadDesktop)
+                {
+                    LogFlowFunc(("GetThreadDesktop not found\n"));
+                    rc = VERR_NOT_SUPPORTED;
+                }
+
+                *(void **)&gVBoxDt.pfnOpenInputDesktop = RTLdrGetSystemSymbol("user32.dll", "OpenInputDesktop");
+                if (!gVBoxDt.pfnOpenInputDesktop)
+                {
+                    LogFlowFunc(("OpenInputDesktop not found\n"));
+                    rc = VERR_NOT_SUPPORTED;
+                }
+
+                *(void **)&gVBoxDt.pfnCloseDesktop = RTLdrGetSystemSymbol("user32.dll", "CloseDesktop");
+                if (!gVBoxDt.pfnCloseDesktop)
+                {
+                    LogFlowFunc(("CloseDesktop not found\n"));
+                    rc = VERR_NOT_SUPPORTED;
+                }
+
+                if (RT_SUCCESS(rc))
+                {
+                    BOOL fRc = FALSE;
+                    /* For Vista and up we need to change the integrity of the security descriptor, too. */
+                    uint64_t const uNtVersion = RTSystemGetNtVersion();
+                    if (uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0))
+                    {
+                        HMODULE hModHook = (HMODULE)RTLdrGetNativeHandle(gVBoxDt.hLdrModHook);
+                        Assert((uintptr_t)hModHook != ~(uintptr_t)0);
+                        fRc = gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker(hModHook);
+                        if (!fRc)
+                            LogFlowFunc(("pfnVBoxHookInstallActiveDesktopTracker failed, last error = %08X\n", GetLastError()));
+                    }
+
+                    if (!fRc)
+                    {
+                        gVBoxDt.idTimer = SetTimer(g_hwndToolWindow, TIMERID_VBOXTRAY_DT_TIMER, 500, (TIMERPROC)NULL);
+                        if (!gVBoxDt.idTimer)
+                        {
+                            DWORD dwErr = GetLastError();
+                            LogFlowFunc(("SetTimer error %08X\n", dwErr));
+                            rc = RTErrConvertFromWin32(dwErr);
+                        }
+                    }
+
+                    if (RT_SUCCESS(rc))
+                    {
+                        gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
+                        return VINF_SUCCESS;
+                    }
+                }
+            }
+
+            RTLdrClose(gVBoxDt.hLdrModHook);
+        }
+        else
+        {
+            DWORD dwErr = GetLastError();
+            LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
+            rc = RTErrConvertFromWin32(dwErr);
+        }
+
+        CloseHandle(gVBoxDt.hNotifyEvent);
+    }
+    else
+    {
+        DWORD dwErr = GetLastError();
+        LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
+        rc = RTErrConvertFromWin32(dwErr);
+    }
+
+
+    RT_ZERO(gVBoxDt);
+    gVBoxDt.fIsInputDesktop = TRUE;
+
+    return rc;
+}
+
+void vboxDtTerm()
+{
+    if (!gVBoxDt.hLdrModHook)
+        return;
+
+    gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker();
+
+    RTLdrClose(gVBoxDt.hLdrModHook);
+    CloseHandle(gVBoxDt.hNotifyEvent);
+
+    RT_ZERO(gVBoxDt);
+}
+
+/* @returns true on "IsInputDesktop" state change */
+BOOL vboxDtHandleEvent()
+{
+    BOOL fIsInputDesktop = gVBoxDt.fIsInputDesktop;
+    gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
+    return !fIsInputDesktop != !gVBoxDt.fIsInputDesktop;
+}
+
+HANDLE vboxDtGetNotifyEvent()
+{
+    return gVBoxDt.hNotifyEvent;
+}
+
+/* @returns true iff the application (VBoxTray) desktop is input */
+BOOL vboxDtIsInputDesktop()
+{
+    return gVBoxDt.fIsInputDesktop;
+}
+
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp	(revision 95965)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp	(revision 95966)
@@ -29,11 +29,10 @@
 #include <iprt/win/windows.h>
 
-#include <VBoxDisplay.h> /** @todo r=bird: Presumably the ../include/VBoxDisplay.h file rather than ./VBoxDisplay.h. WTF???  */
 #include <VBoxHook.h> /* from ../include/ */
 
 #include "VBoxTray.h"
+#include "VBoxTrayInternal.h"
 #include "VBoxHelpers.h"
 #include "VBoxSeamless.h"
-
 
 
@@ -70,5 +69,5 @@
 *********************************************************************************************************************************/
 void VBoxLogString(HANDLE hDriver, char *pszStr);
-
+static void vboxSeamlessSetSupported(BOOL fSupported);
 
 
@@ -105,5 +104,5 @@
                 && pCtx->pfnVBoxHookRemoveWindowTracker)
             {
-                VBoxSeamlessSetSupported(TRUE);
+                vboxSeamlessSetSupported(TRUE);
 
                 *ppInstance = pCtx;
@@ -136,5 +135,5 @@
     AssertPtr(pCtx);
 
-    VBoxSeamlessSetSupported(FALSE);
+    vboxSeamlessSetSupported(FALSE);
 
     /* Inform the host that we no longer support the seamless window mode. */
@@ -206,4 +205,9 @@
 
     VBoxDispIfSeamlessTerm(&gVBoxDispIfSeamless);
+}
+
+void vboxSeamlessSetSupported(BOOL fSupported)
+{
+    VBoxConsoleCapSetSupported(VBOXCAPS_ENTRY_IDX_SEAMLESS, fSupported);
 }
 
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h	(revision 95965)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h	(revision 95966)
@@ -22,9 +22,7 @@
 #endif
 
-void VBoxSeamlessEnable();
-void VBoxSeamlessDisable();
+void VBoxSeamlessEnable(void);
+void VBoxSeamlessDisable(void);
 void VBoxSeamlessCheckWindows(bool fForce);
-
-void VBoxSeamlessSetSupported(BOOL fSupported);
 
 #endif /* !GA_INCLUDED_SRC_WINNT_VBoxTray_VBoxSeamless_h */
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 95965)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp	(revision 95966)
@@ -56,52 +56,4 @@
 
 
-
-
-/*
- * Dt (desktop [state] tracking) functionality API
- *
- * !!!NOTE: this API is NOT thread-safe!!!
- * */
-static int vboxDtInit();
-static void vboxDtTerm();
-/* @returns true on "IsInputDesktop" state change */
-static BOOL vboxDtHandleEvent();
-/* @returns true iff the application (VBoxTray) desktop is input */
-static BOOL vboxDtIsInputDesktop();
-static HANDLE vboxDtGetNotifyEvent();
-static BOOL vboxDtCheckTimer(WPARAM wParam);
-
-/* 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);
 
@@ -115,7 +67,4 @@
 /* Global message handler prototypes. */
 static int vboxTrayGlMsgTaskbarCreated(WPARAM lParam, LPARAM wParam);
-/*static int vboxTrayGlMsgShowBalloonMsg(WPARAM lParam, LPARAM wParam);*/
-
-static int VBoxAcquireGuestCaps(uint32_t fOr, uint32_t fNot, bool fCfg);
 
 
@@ -828,14 +777,4 @@
 }
 
-static void VBoxTrayCheckDt()
-{
-    BOOL fOldAllowedState = VBoxConsoleIsAllowed();
-    if (vboxDtHandleEvent())
-    {
-        if (!VBoxConsoleIsAllowed() != !fOldAllowedState)
-            VBoxConsoleEnable(!fOldAllowedState);
-    }
-}
-
 static int vboxTrayServiceMain(void)
 {
@@ -1378,545 +1317,7 @@
 }
 
-/*
- * Dt (desktop [state] tracking) functionality API impl
- *
- * !!!NOTE: this API is NOT thread-safe!!!
- * */
-
-typedef struct VBOXDT
-{
-    HANDLE hNotifyEvent;
-    BOOL fIsInputDesktop;
-    UINT_PTR idTimer;
-    RTLDRMOD hLdrModHook;
-    BOOL (* pfnVBoxHookInstallActiveDesktopTracker)(HMODULE hDll);
-    BOOL (* pfnVBoxHookRemoveActiveDesktopTracker)();
-    HDESK (WINAPI * pfnGetThreadDesktop)(DWORD dwThreadId);
-    HDESK (WINAPI * pfnOpenInputDesktop)(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
-    BOOL (WINAPI * pfnCloseDesktop)(HDESK hDesktop);
-} VBOXDT;
-
-static VBOXDT gVBoxDt;
-
-static BOOL vboxDtCalculateIsInputDesktop()
-{
-    BOOL fIsInputDt = FALSE;
-    HDESK hInput = gVBoxDt.pfnOpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
-    if (hInput)
-    {
-//        DWORD dwThreadId = GetCurrentThreadId();
-//        HDESK hThreadDt = gVBoxDt.pfnGetThreadDesktop(dwThreadId);
-//        if (hThreadDt)
-//        {
-            fIsInputDt = TRUE;
-//        }
-//        else
-//        {
-//            DWORD dwErr = GetLastError();
-//            LogFlowFunc(("pfnGetThreadDesktop for Seamless failed, last error = %08X\n", dwErr));
-//        }
-
-        gVBoxDt.pfnCloseDesktop(hInput);
-    }
-    else
-    {
-//        DWORD dwErr = GetLastError();
-//        LogFlowFunc(("pfnOpenInputDesktop for Seamless failed, last error = %08X\n", dwErr));
-    }
-    return fIsInputDt;
-}
-
-static BOOL vboxDtCheckTimer(WPARAM wParam)
-{
-    if (wParam != gVBoxDt.idTimer)
-        return FALSE;
-
-    VBoxTrayCheckDt();
-
-    return TRUE;
-}
-
-static int vboxDtInit()
-{
-    RT_ZERO(gVBoxDt);
-
-    int rc;
-    gVBoxDt.hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
-    if (gVBoxDt.hNotifyEvent != NULL)
-    {
-        /* Load the hook dll and resolve the necessary entry points. */
-        rc = RTLdrLoadAppPriv(VBOXHOOK_DLL_NAME, &gVBoxDt.hLdrModHook);
-        if (RT_SUCCESS(rc))
-        {
-            rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookInstallActiveDesktopTracker",
-                                (void **)&gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker);
-            if (RT_SUCCESS(rc))
-            {
-                rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookRemoveActiveDesktopTracker",
-                                    (void **)&gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker);
-                if (RT_FAILURE(rc))
-                    LogFlowFunc(("VBoxHookRemoveActiveDesktopTracker not found\n"));
-            }
-            else
-                LogFlowFunc(("VBoxHookInstallActiveDesktopTracker not found\n"));
-            if (RT_SUCCESS(rc))
-            {
-                /* Try get the system APIs we need. */
-                *(void **)&gVBoxDt.pfnGetThreadDesktop = RTLdrGetSystemSymbol("user32.dll", "GetThreadDesktop");
-                if (!gVBoxDt.pfnGetThreadDesktop)
-                {
-                    LogFlowFunc(("GetThreadDesktop not found\n"));
-                    rc = VERR_NOT_SUPPORTED;
-                }
-
-                *(void **)&gVBoxDt.pfnOpenInputDesktop = RTLdrGetSystemSymbol("user32.dll", "OpenInputDesktop");
-                if (!gVBoxDt.pfnOpenInputDesktop)
-                {
-                    LogFlowFunc(("OpenInputDesktop not found\n"));
-                    rc = VERR_NOT_SUPPORTED;
-                }
-
-                *(void **)&gVBoxDt.pfnCloseDesktop = RTLdrGetSystemSymbol("user32.dll", "CloseDesktop");
-                if (!gVBoxDt.pfnCloseDesktop)
-                {
-                    LogFlowFunc(("CloseDesktop not found\n"));
-                    rc = VERR_NOT_SUPPORTED;
-                }
-
-                if (RT_SUCCESS(rc))
-                {
-                    BOOL fRc = FALSE;
-                    /* For Vista and up we need to change the integrity of the security descriptor, too. */
-                    uint64_t const uNtVersion = RTSystemGetNtVersion();
-                    if (uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0))
-                    {
-                        HMODULE hModHook = (HMODULE)RTLdrGetNativeHandle(gVBoxDt.hLdrModHook);
-                        Assert((uintptr_t)hModHook != ~(uintptr_t)0);
-                        fRc = gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker(hModHook);
-                        if (!fRc)
-                            LogFlowFunc(("pfnVBoxHookInstallActiveDesktopTracker failed, last error = %08X\n", GetLastError()));
-                    }
-
-                    if (!fRc)
-                    {
-                        gVBoxDt.idTimer = SetTimer(g_hwndToolWindow, TIMERID_VBOXTRAY_DT_TIMER, 500, (TIMERPROC)NULL);
-                        if (!gVBoxDt.idTimer)
-                        {
-                            DWORD dwErr = GetLastError();
-                            LogFlowFunc(("SetTimer error %08X\n", dwErr));
-                            rc = RTErrConvertFromWin32(dwErr);
-                        }
-                    }
-
-                    if (RT_SUCCESS(rc))
-                    {
-                        gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
-                        return VINF_SUCCESS;
-                    }
-                }
-            }
-
-            RTLdrClose(gVBoxDt.hLdrModHook);
-        }
-        else
-        {
-            DWORD dwErr = GetLastError();
-            LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
-            rc = RTErrConvertFromWin32(dwErr);
-        }
-
-        CloseHandle(gVBoxDt.hNotifyEvent);
-    }
-    else
-    {
-        DWORD dwErr = GetLastError();
-        LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
-        rc = RTErrConvertFromWin32(dwErr);
-    }
-
-
-    RT_ZERO(gVBoxDt);
-    gVBoxDt.fIsInputDesktop = TRUE;
-
-    return rc;
-}
-
-static void vboxDtTerm()
-{
-    if (!gVBoxDt.hLdrModHook)
-        return;
-
-    gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker();
-
-    RTLdrClose(gVBoxDt.hLdrModHook);
-    CloseHandle(gVBoxDt.hNotifyEvent);
-
-    RT_ZERO(gVBoxDt);
-}
-/* @returns true on "IsInputDesktop" state change */
-static BOOL vboxDtHandleEvent()
-{
-    BOOL fIsInputDesktop = gVBoxDt.fIsInputDesktop;
-    gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
-    return !fIsInputDesktop != !gVBoxDt.fIsInputDesktop;
-}
-
-static HANDLE vboxDtGetNotifyEvent()
-{
-    return gVBoxDt.hNotifyEvent;
-}
-
-/* @returns true iff the application (VBoxTray) desktop is input */
-static BOOL vboxDtIsInputDesktop()
-{
-    return gVBoxDt.fIsInputDesktop;
-}
-
-/* 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, bool fCfg)
-{
-    Log(("VBoxAcquireGuestCaps or(0x%x), not(0x%x), cfx(%d)\n", fOr, fNot, fCfg));
-    int rc = VbglR3AcquireGuestCaps(fOr, fNot, fCfg);
-    if (RT_FAILURE(rc))
-        LogFlowFunc(("VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE failed: %Rrc\n", 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;
-    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) vboxCapsOnEnableSeamless(struct VBOXCAPS *pConsole, struct VBOXCAPS_ENTRY *pCap, BOOL fEnabled)
-{
-    RT_NOREF(pConsole, pCap);
-    if (fEnabled)
-    {
-        Log(("vboxCapsOnEnableSeamless: ENABLED\n"));
-        Assert(pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
-        Assert(pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
-        VBoxSeamlessEnable();
-    }
-    else
-    {
-        Log(("vboxCapsOnEnableSeamless: DISABLED\n"));
-        Assert(pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_ACQUIRED || pCap->enmFuncState != VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
-        VBoxSeamlessDisable();
-    }
-}
-
-static void vboxCapsEntryAcStateSet(VBOXCAPS_ENTRY *pCap, VBOXCAPS_ENTRY_ACSTATE enmAcState)
-{
-    VBOXCAPS *pConsole = &gVBoxCaps;
-
-    Log(("vboxCapsEntryAcStateSet: new state enmAcState(%d); pCap: fCap(%d), iCap(%d), enmFuncState(%d), enmAcState(%d)\n",
-            enmAcState, pCap->fCap, pCap->iCap, pCap->enmFuncState, pCap->enmAcState));
-
-    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;
-
-    Log(("vboxCapsEntryFuncStateSet: new state enmAcState(%d); pCap: fCap(%d), iCap(%d), enmFuncState(%d), enmAcState(%d)\n",
-            enmFuncState, pCap->fCap, pCap->iCap, pCap->enmFuncState, pCap->enmAcState));
-
-    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 = vboxCapsOnEnableSeamless;
-    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;
-    Log(("VBoxCapsReleaseAll\n"));
-    int rc = VBoxAcquireGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS | VMMDEV_GUEST_SUPPORTS_GRAPHICS, false);
-    if (!RT_SUCCESS(rc))
-    {
-        LogFlowFunc(("vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
-        return rc;
-    }
-
-    if (pConsole->idTimer)
-    {
-        Log(("killing console timer\n"));
-        KillTimer(g_hwndToolWindow, 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, false);
-        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(g_hwndToolWindow, 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)
-    {
-        LogFlowFunc(("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, false);
-        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];
-    Log(("VBoxCapsEntryAcquire %d\n", iCap));
-    if (pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_RELEASED)
-    {
-        LogFlowFunc(("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, false);
-    if (RT_SUCCESS(rc))
-    {
-        vboxCapsEntryAcStateSet(pCap, VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
-        return VINF_SUCCESS;
-    }
-
-    if (rc != VERR_RESOURCE_BUSY)
-    {
-        LogFlowFunc(("vboxCapsEntryReleaseAll VBoxAcquireGuestCaps failed rc %d\n", rc));
-        return rc;
-    }
-
-    LogFlowFunc(("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(g_hwndToolWindow, TIMERID_VBOXTRAY_CAPS_TIMER, 100, (TIMERPROC)NULL);
-        if (!pConsole->idTimer)
-        {
-            DWORD dwErr = GetLastError();
-            LogFlowFunc(("SetTimer error %08X\n", dwErr));
-            return RTErrConvertFromWin32(dwErr);
-        }
-    }
-
-    return rc;
-}
-
-static int VBoxCapsAcquireAllSupported()
-{
-    VBOXCAPS *pConsole = &gVBoxCaps;
-    Log(("VBoxCapsAcquireAllSupported\n"));
-    for (int i = 0; i < RT_ELEMENTS(pConsole->aCaps); ++i)
-    {
-        if (pConsole->aCaps[i].enmFuncState >= VBOXCAPS_ENTRY_FUNCSTATE_SUPPORTED)
-        {
-            Log(("VBoxCapsAcquireAllSupported acquiring cap %d, state %d\n", i, pConsole->aCaps[i].enmFuncState));
-            VBoxCapsEntryAcquire(i);
-        }
-        else
-        {
-            LogFlowFunc(("VBoxCapsAcquireAllSupported: WARN: cap %d not supported, state %d\n", i, pConsole->aCaps[i].enmFuncState));
-        }
-    }
-    return VINF_SUCCESS;
-}
-
-static BOOL VBoxConsoleIsAllowed()
-{
-    return vboxDtIsInputDesktop() && vboxStIsActiveConsole();
-}
-
-static void VBoxConsoleEnable(BOOL fEnable)
-{
-    if (fEnable)
-        VBoxCapsAcquireAllSupported();
-    else
-        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);
 }
+
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTrayInternal.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTrayInternal.h	(revision 95965)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTrayInternal.h	(revision 95966)
@@ -21,4 +21,57 @@
 # pragma once
 #endif
+
+
+/* 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;
+
+
+int VBoxAcquireGuestCaps(uint32_t fOr, uint32_t fNot, bool fCfg);
+void VBoxCapsEntryFuncStateSet(uint32_t iCup, VBOXCAPS_ENTRY_FUNCSTATE enmFuncState);
+int VBoxCapsInit();
+int VBoxCapsReleaseAll();
+void VBoxCapsTerm();
+BOOL VBoxCapsEntryIsAcquired(uint32_t iCap);
+BOOL VBoxCapsEntryIsEnabled(uint32_t iCap);
+BOOL VBoxCapsCheckTimer(WPARAM wParam);
+int VBoxCapsEntryRelease(uint32_t iCap);
+int VBoxCapsEntryAcquire(uint32_t iCap);
+int VBoxCapsAcquireAllSupported();
+
+
+/* console-related caps API */
+BOOL VBoxConsoleIsAllowed();
+void VBoxConsoleEnable(BOOL fEnable);
+void VBoxConsoleCapSetSupported(uint32_t iCap, BOOL fSupported);
+
+
+/*
+ * Dt (desktop [state] tracking) functionality API
+ *
+ * !!!NOTE: this API is NOT thread-safe!!!
+ * */
+int vboxDtInit();
+void vboxDtTerm();
+/* @returns true on "IsInputDesktop" state change */
+BOOL vboxDtHandleEvent();
+/* @returns true iff the application (VBoxTray) desktop is input */
+BOOL vboxDtIsInputDesktop();
+HANDLE vboxDtGetNotifyEvent();
+BOOL vboxDtCheckTimer(WPARAM wParam);
+void VBoxTrayCheckDt();
+
+
 /*
  * St (session [state] tracking) functionality API
@@ -34,4 +87,5 @@
 BOOL vboxStCheckTimer(WPARAM wEvent);
 
+
 DWORD VBoxDisplayGetCount();
 DWORD VBoxDisplayGetConfig(const DWORD NumDevices, DWORD *pDevPrimaryNum, DWORD *pNumDevices, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes);
