Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceDisplayConfig.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceDisplayConfig.cpp	(revision 105527)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceDisplayConfig.cpp	(revision 105641)
@@ -25,4 +25,8 @@
  */
 
+#include <iprt/win/windows.h>
+#include <wtsapi32.h>
+#include <ntsecapi.h>
+
 #include <iprt/errcore.h>
 
@@ -48,4 +52,8 @@
 static PFND3DKMT_ESCAPE g_pfnD3DKMTEscape;
 
+static decltype(WTSFreeMemory)                 *g_pfnWTSFreeMemory = NULL;
+static decltype(WTSQuerySessionInformationA)   *g_pfnWTSQuerySessionInformationA = NULL;
+static decltype(WTSEnumerateSessionsA)         *g_pfnWTSEnumerateSessionsA = NULL;
+
 /**
  * @interface_method_impl{VBOXSERVICE,pfnInit}
@@ -68,5 +76,26 @@
     }
 
-    VGSvcVerbose(2, "DXGK d3dkmthk callbacks are %s\n", RT_SUCCESS(rc) ? "Ok" : "Fail");
+    VGSvcVerbose(3, "DXGK d3dkmthk callbacks are %s\n", RT_SUCCESS(rc) ? "Ok" : "Fail");
+
+    rc = RTLdrLoadSystem("wtsapi32.dll", true /*fNoUnload*/, &hLdrMod);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hLdrMod, "WTSFreeMemory", (void **)&g_pfnWTSFreeMemory);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "WTSQuerySessionInformationA", (void **)&g_pfnWTSQuerySessionInformationA);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "WTSEnumerateSessionsA", (void **)&g_pfnWTSEnumerateSessionsA);
+        AssertRC(rc);
+        RTLdrClose(hLdrMod);
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        VGSvcVerbose(1, "WtsApi32.dll APIs are not available (%Rrc)\n", rc);
+        g_pfnWTSFreeMemory = NULL;
+        g_pfnWTSQuerySessionInformationA = NULL;
+        g_pfnWTSEnumerateSessionsA = NULL;
+        // Assert(RTSystemGetNtVersion() < RTSYSTEM_MAKE_NT_VERSION(5, 0, 0));
+    }
 
     return VINF_SUCCESS;
@@ -85,15 +114,15 @@
     }
 
-    VGSvcVerbose(2, "ReconnectDisplays u32Mask 0x%x\n", u32Mask);
+    VGSvcVerbose(3, "ReconnectDisplays u32Mask 0x%x\n", u32Mask);
 
     EnumAdapters.NumAdapters = RT_ELEMENTS(EnumAdapters.Adapters);
     rcNt = g_pfnD3DKMTEnumAdapters(&EnumAdapters);
 
-    VGSvcVerbose(2, "D3DKMTEnumAdapters  rcNt=%#x NumAdapters=%d\n", rcNt, EnumAdapters.NumAdapters);
+    VGSvcVerbose(3, "D3DKMTEnumAdapters  rcNt=%#x NumAdapters=%d\n", rcNt, EnumAdapters.NumAdapters);
 
     for(ULONG id = 0; id < EnumAdapters.NumAdapters; id++)
     {
         D3DKMT_ADAPTERINFO *pAdapterInfo = &EnumAdapters.Adapters[id];
-        VGSvcVerbose(2, "#%d: NumOfSources=%d hAdapter=0x%p Luid(%u, %u)\n", id,
+        VGSvcVerbose(3, "#%d: NumOfSources=%d hAdapter=0x%p Luid(%u, %u)\n", id,
             pAdapterInfo->NumOfSources, pAdapterInfo->hAdapter, pAdapterInfo->AdapterLuid.HighPart, pAdapterInfo->AdapterLuid.LowPart);
     }
@@ -103,5 +132,5 @@
     OpenAdapterData.AdapterLuid = EnumAdapters.Adapters[0].AdapterLuid;
     rcNt = g_pfnD3DKMTOpenAdapterFromLuid(&OpenAdapterData);
-    VGSvcVerbose(2, "D3DKMTOpenAdapterFromLuid  rcNt=%#x hAdapter=0x%p\n", rcNt, OpenAdapterData.hAdapter);
+    VGSvcVerbose(3, "D3DKMTOpenAdapterFromLuid  rcNt=%#x hAdapter=0x%p\n", rcNt, OpenAdapterData.hAdapter);
 
     hAdapter = OpenAdapterData.hAdapter;
@@ -121,5 +150,5 @@
 
         rcNt = g_pfnD3DKMTEscape(&EscapeData);
-        VGSvcVerbose(2, "D3DKMTEscape rcNt=%#x\n", rcNt);
+        VGSvcVerbose(3, "D3DKMTEscape rcNt=%#x\n", rcNt);
 
         D3DKMT_CLOSEADAPTER CloseAdapter;
@@ -127,6 +156,59 @@
 
         rcNt = g_pfnD3DKMTCloseAdapter(&CloseAdapter);
-        VGSvcVerbose(2, "D3DKMTCloseAdapter rcNt=%#x\n", rcNt);
-    }
+        VGSvcVerbose(3, "D3DKMTCloseAdapter rcNt=%#x\n", rcNt);
+    }
+}
+
+static char* WTSSessionState2Str(WTS_CONNECTSTATE_CLASS State)
+{
+    switch(State)
+    {
+        RT_CASE_RET_STR(WTSActive);
+        RT_CASE_RET_STR(WTSConnected);
+        RT_CASE_RET_STR(WTSConnectQuery);
+        RT_CASE_RET_STR(WTSShadow);
+        RT_CASE_RET_STR(WTSDisconnected);
+        RT_CASE_RET_STR(WTSIdle);
+        RT_CASE_RET_STR(WTSListen);
+        RT_CASE_RET_STR(WTSReset);
+        RT_CASE_RET_STR(WTSDown);
+        RT_CASE_RET_STR(WTSInit);
+        default:
+            return "Unknown";
+    }
+}
+
+bool HasActiveLocalUser(void)
+{
+    WTS_SESSION_INFO *paSessionInfos = NULL;
+    DWORD cSessionInfos = 0;
+    bool fRet = false;
+
+    if (g_pfnWTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &paSessionInfos, &cSessionInfos))
+    {
+        VGSvcVerbose(3, "WTSEnumerateSessionsA got %u sessions\n", cSessionInfos);
+
+        for(DWORD i = 0; i < cSessionInfos; i++)
+        {
+            VGSvcVerbose(3, "WTS session[%u] SessionId (%u) pWinStationName (%s) State (%s %u)\n", i,
+                paSessionInfos[i].SessionId, paSessionInfos[i].pWinStationName,
+                WTSSessionState2Str(paSessionInfos[i].State), paSessionInfos[i].State);
+
+            if (paSessionInfos[i].State == WTSActive && RTStrNICmpAscii(paSessionInfos[i].pWinStationName, RT_STR_TUPLE("Console")) == 0)
+            {
+                VGSvcVerbose(2, "Found active WTS session %u connected to Console\n", paSessionInfos[i].SessionId);
+                fRet = true;
+            }
+        }
+    }
+    else
+    {
+        VGSvcError("WTSEnumerateSessionsA failed %#x\n", GetLastError());
+    }
+
+    if (paSessionInfos)
+        g_pfnWTSFreeMemory(paSessionInfos);
+
+    return fRet;
 }
 
@@ -147,5 +229,5 @@
 
     rc = VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
-    VGSvcVerbose(2, "VbglR3CtlFilterMask set rc=%Rrc\n", rc);
+    VGSvcVerbose(3, "VbglR3CtlFilterMask set rc=%Rrc\n", rc);
 
     for (;;)
@@ -153,34 +235,39 @@
         uint32_t fEvents = 0;
 
-        rc = VbglR3AcquireGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0, false);
-        VGSvcVerbose(2, "VbglR3AcquireGuestCaps acquire VMMDEV_GUEST_SUPPORTS_GRAPHICS rc=%Rrc\n", rc);
-
-        rc = VbglR3WaitEvent(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 1000 /*ms*/, &fEvents);
-        VGSvcVerbose(2, "VbglR3WaitEvent rc=%Rrc\n", rc);
-
-        if (RT_SUCCESS(rc))
+        if (HasActiveLocalUser())
         {
-            VMMDevDisplayDef aDisplays[64];
-            uint32_t cDisplays = RT_ELEMENTS(aDisplays);
-
-            rc = VbglR3GetDisplayChangeRequestMulti(cDisplays, &cDisplays, &aDisplays[0], true);
-            VGSvcVerbose(2, "VbglR3GetDisplayChangeRequestMulti rc=%Rrc cDisplays=%d\n", rc, cDisplays);
-            if (cDisplays > 0)
+            RTThreadSleep(1000);
+        }
+        else
+        {
+            rc = VbglR3AcquireGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0, false);
+            VGSvcVerbose(3, "VbglR3AcquireGuestCaps acquire VMMDEV_GUEST_SUPPORTS_GRAPHICS rc=%Rrc\n", rc);
+
+            rc = VbglR3WaitEvent(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 2000 /*ms*/, &fEvents);
+            VGSvcVerbose(3, "VbglR3WaitEvent rc=%Rrc\n", rc);
+
+            if (RT_SUCCESS(rc))
             {
-                for(uint32_t i = 0; i < cDisplays; i++)
+                VMMDevDisplayDef aDisplays[64];
+                uint32_t cDisplays = RT_ELEMENTS(aDisplays);
+
+                rc = VbglR3GetDisplayChangeRequestMulti(cDisplays, &cDisplays, &aDisplays[0], true);
+                VGSvcVerbose(3, "VbglR3GetDisplayChangeRequestMulti rc=%Rrc cDisplays=%d\n", rc, cDisplays);
+                if (cDisplays > 0)
                 {
-                    VGSvcVerbose(2, "Display[%i] flags=%#x (%dx%d)\n", i,
-                        aDisplays[i].fDisplayFlags,
-                        aDisplays[i].cx, aDisplays[i].cy);
+                    for(uint32_t i = 0; i < cDisplays; i++)
+                    {
+                        VGSvcVerbose(2, "Display[%i] flags=%#x (%dx%d)\n", i,
+                            aDisplays[i].fDisplayFlags,
+                            aDisplays[i].cx, aDisplays[i].cy);
+                    }
+
+                    ReconnectDisplays(cDisplays, &aDisplays[0]);
                 }
-
-                ReconnectDisplays(cDisplays, &aDisplays[0]);
             }
+
+            rc = VbglR3AcquireGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS, false);
+            VGSvcVerbose(3, "VbglR3AcquireGuestCaps release VMMDEV_GUEST_SUPPORTS_GRAPHICS rc=%Rrc\n", rc);
         }
-
-        rc = VbglR3AcquireGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS, false);
-        VGSvcVerbose(2, "VbglR3AcquireGuestCaps release VMMDEV_GUEST_SUPPORTS_GRAPHICS rc=%Rrc\n", rc);
-
-        RTThreadSleep(1000);
 
         if (*pfShutdown)
@@ -189,5 +276,5 @@
 
     rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
-    VGSvcVerbose(2, "VbglR3CtlFilterMask cleared rc=%Rrc\n", rc);
+    VGSvcVerbose(3, "VbglR3CtlFilterMask cleared rc=%Rrc\n", rc);
 
     return rc;
