Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 57920)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 57921)
@@ -20,7 +20,7 @@
 *   Header Files                                                                                                                 *
 *********************************************************************************************************************************/
-#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502
+#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
 # undef  _WIN32_WINNT
-# define _WIN32_WINNT 0x0502 /* CachedRemoteInteractive in recent SDKs. */
+# define _WIN32_WINNT 0x0600 /* QueryFullProcessImageNameW in recent SDKs. */
 #endif
 #include <Windows.h>
@@ -33,9 +33,11 @@
 #include <iprt/localipc.h>
 #include <iprt/mem.h>
-#include <iprt/thread.h>
+#include <iprt/once.h>
 #include <iprt/string.h>
 #include <iprt/semaphore.h>
 #include <iprt/system.h>
 #include <iprt/time.h>
+#include <iprt/thread.h>
+
 #include <VBox/VBoxGuestLib.h>
 #include "VBoxServiceInternal.h"
@@ -90,40 +92,145 @@
 
 
-/*******************************************************************************
-*   Prototypes
-*******************************************************************************/
-uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs);
-bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession);
-int  VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
-void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paProcs);
-int vboxServiceVMInfoWinWriteLastInput(PVBOXSERVICEVEPROPCACHE pCache, const char *pszUser, const char *pszDomain);
-
-typedef BOOL WINAPI FNQUERYFULLPROCESSIMAGENAME(HANDLE,  DWORD, LPWSTR, PDWORD);
-typedef FNQUERYFULLPROCESSIMAGENAME *PFNQUERYFULLPROCESSIMAGENAME;
-
-
-#ifndef TARGET_NT4
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+static uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs);
+static bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession);
+static int  VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
+static void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paProcs);
+static int  vboxServiceVMInfoWinWriteLastInput(PVBOXSERVICEVEPROPCACHE pCache, const char *pszUser, const char *pszDomain);
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+static RTONCE                                   g_vgsvcWinVmInitOnce = RTONCE_INITIALIZER;
+
+/** @name Secur32.dll imports are dynamically resolved because of NT4.
+ * @{ */
+static decltype(LsaGetLogonSessionData)        *g_pfnLsaGetLogonSessionData = NULL;
+static decltype(LsaEnumerateLogonSessions)     *g_pfnLsaEnumerateLogonSessions = NULL;
+static decltype(LsaFreeReturnBuffer)           *g_pfnLsaFreeReturnBuffer = NULL;
+/** @} */
+
+/** @name WtsApi32.dll imports are dynamically resolved because of NT4.
+ * @{ */
+static decltype(WTSFreeMemory)                 *g_pfnWTSFreeMemory = NULL;
+static decltype(WTSQuerySessionInformationA)   *g_pfnWTSQuerySessionInformationA = NULL;
+/** @} */
+
+/** @name PsApi.dll imports are dynamically resolved because of NT4.
+ * @{ */
+static decltype(EnumProcesses)                 *g_pfnEnumProcesses = NULL;
+static decltype(GetModuleFileNameExW)          *g_pfnGetModuleFileNameExW = NULL;
+/** @} */
+
+/** @name New Kernel32.dll APIs we may use when present.
+ * @{  */
+static decltype(QueryFullProcessImageNameW)    *g_pfnQueryFullProcessImageNameW = NULL;
+
+/** @} */
+
+/** Windows version.  */
+static OSVERSIONINFOEXA                         g_WinVersion;
+
+
+/**
+ * An RTOnce callback function.
+ */
+static DECLCALLBACK(int) vgsvcWinVmInfoInitOnce(void *pvIgnored)
+{
+    /* SECUR32 */
+    RTLDRMOD hLdrMod;
+    int rc = RTLdrLoadSystem("secur32.dll", true, &hLdrMod);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hLdrMod, "LsaGetLogonSessionData", (void **)&g_pfnLsaGetLogonSessionData);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "LsaEnumerateLogonSessions", (void **)&g_pfnLsaEnumerateLogonSessions);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "LsaFreeReturnBuffer", (void **)&g_pfnLsaFreeReturnBuffer);
+        AssertRC(rc);
+        RTLdrClose(hLdrMod);
+    }
+    if (RT_FAILURE(rc))
+    {
+        VBoxServiceVerbose(1, "Secur32.dll APIs are not availble (%Rrc)\n", rc);
+        g_pfnLsaGetLogonSessionData = NULL;
+        g_pfnLsaEnumerateLogonSessions = NULL;
+        g_pfnLsaFreeReturnBuffer = NULL;
+        Assert(g_WinVersion.dwMajorVersion < 5);
+    }
+
+    /* WTSAPI32 */
+    rc = RTLdrLoadSystem("wtsapi32.dll", true, &hLdrMod);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hLdrMod, "WTSFreeMemory", (void **)&g_pfnWTSFreeMemory);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "WTSQuerySessionInformationA", (void **)&g_pfnWTSQuerySessionInformationA);
+        AssertRC(rc);
+        RTLdrClose(hLdrMod);
+    }
+    if (RT_FAILURE(rc))
+    {
+        VBoxServiceVerbose(1, "WtsApi32.dll APIs are not availble (%Rrc)\n", rc);
+        g_pfnWTSFreeMemory = NULL;
+        g_pfnWTSQuerySessionInformationA = NULL;
+        Assert(g_WinVersion.dwMajorVersion < 5);
+    }
+
+    /* PSAPI */
+    rc = RTLdrLoadSystem("psapi.dll", true, &hLdrMod);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hLdrMod, "EnumProcesses", (void **)&g_pfnEnumProcesses);
+        if (RT_SUCCESS(rc))
+            rc = RTLdrGetSymbol(hLdrMod, "GetModuleFileNameExW", (void **)&g_pfnGetModuleFileNameExW);
+        AssertRC(rc);
+        RTLdrClose(hLdrMod);
+    }
+    if (RT_FAILURE(rc))
+    {
+        VBoxServiceVerbose(1, "psapi.dll APIs are not availble (%Rrc)\n", rc);
+        g_pfnEnumProcesses = NULL;
+        g_pfnGetModuleFileNameExW = NULL;
+        Assert(g_WinVersion.dwMajorVersion < 5);
+    }
+
+    /* Kernel32: */
+    rc = RTLdrLoadSystem("kerne32.dll", true, &hLdrMod);
+    AssertRCReturn(rc, rc);
+    rc = RTLdrGetSymbol(hLdrMod, "QueryFullProcessImageNameW", (void **)&g_pfnQueryFullProcessImageNameW);
+    if (RT_FAILURE(rc))
+    {
+        Assert(g_WinVersion.dwMajorVersion < 6);
+        g_pfnQueryFullProcessImageNameW = NULL;
+    }
+    RTLdrClose(hLdrMod);
+
+    /*
+     * Get the extended windows version once and for all.
+     */
+    g_WinVersion.dwOSVersionInfoSize = sizeof(g_WinVersion);
+    if (!GetVersionExA((OSVERSIONINFO *)&g_WinVersion))
+    {
+        AssertFailed();
+        RT_ZERO(g_WinVersion);
+        g_WinVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+        if (!GetVersionExA((OSVERSIONINFO *)&g_WinVersion))
+            RT_ZERO(g_WinVersion);
+    }
+
+    return VINF_SUCCESS;
+}
+
 
 static bool vboxServiceVMInfoSession0Separation(void)
 {
-    /** @todo Only do this once. Later. */
-    OSVERSIONINFOEX OSInfoEx;
-    RT_ZERO(OSInfoEx);
-    OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-    if (   !GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
-        || OSInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT)
-    {
-        /* Platform other than NT (e.g. Win9x) not supported. */
-        return false;
-    }
-
-    if (   OSInfoEx.dwMajorVersion >= 6
-        && OSInfoEx.dwMinorVersion >= 0)
-    {
-        return true;
-    }
-
-    return false;
+    return g_WinVersion.dwPlatformId == VER_PLATFORM_WIN32_NT
+        && g_WinVersion.dwMajorVersion >= 6; /* Vista = 6.0 */
 }
+
 
 /**
@@ -139,19 +246,13 @@
 
     /** @todo Only do this once. Later. */
-    OSVERSIONINFOEX OSInfoEx;
-    RT_ZERO(OSInfoEx);
-    OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-    if (   !GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
-        || OSInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT)
-    {
-        /* Platform other than NT (e.g. Win9x) not supported. */
+    /* Platform other than NT (e.g. Win9x) not supported. */
+    if (g_WinVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)
         return VERR_NOT_SUPPORTED;
-    }
 
     int rc = VINF_SUCCESS;
 
     DWORD dwFlags = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
-    if (OSInfoEx.dwMajorVersion >= 6 /* Vista or later */)
-        dwFlags = 0x1000; /* = PROCESS_QUERY_LIMITED_INFORMATION; less privileges needed. */
+    if (g_WinVersion.dwMajorVersion >= 6 /* Vista or later */)
+        dwFlags = PROCESS_QUERY_LIMITED_INFORMATION; /* possible to do on more processes */
 
     HANDLE h = OpenProcess(dwFlags, FALSE, pProc->id);
@@ -169,25 +270,14 @@
            apps and vice verse) we have to use a different code path for Vista and up. */
         WCHAR wszName[_1K];
-        DWORD dwLen = sizeof(wszName);
-
-        /* Note: For 2000 + NT4 we might just use GetModuleFileNameW() instead. */
-        if (OSInfoEx.dwMajorVersion >= 6 /* Vista or later */)
-        {
-            /* Loading the module and getting the symbol for each and every process is expensive
-             * -- since this function (at the moment) only is used for debugging purposes it's okay. */
-            PFNQUERYFULLPROCESSIMAGENAME pfnQueryFullProcessImageName;
-            pfnQueryFullProcessImageName = (PFNQUERYFULLPROCESSIMAGENAME)
-                RTLdrGetSystemSymbol("kernel32.dll", "QueryFullProcessImageNameW");
-            if (pfnQueryFullProcessImageName)
-            {
-                if (!pfnQueryFullProcessImageName(h, 0 /*PROCESS_NAME_NATIVE*/, wszName, &dwLen))
-                    rc = VERR_ACCESS_DENIED;
-            }
-        }
-        else
-        {
-            if (!GetModuleFileNameExW(h, NULL /* Get main executable */, wszName, dwLen))
+        DWORD dwLen = sizeof(wszName); /** @todo r=bird: wrong? */
+
+        /* Use QueryFullProcessImageNameW if available (Vista+). */
+        if (g_pfnQueryFullProcessImageNameW)
+        {
+            if (!g_pfnQueryFullProcessImageNameW(h, 0 /*PROCESS_NAME_NATIVE*/, wszName, &dwLen))
                 rc = VERR_ACCESS_DENIED;
         }
+        else if (!g_pfnGetModuleFileNameExW(h, NULL /* Get main executable */, wszName, dwLen))
+            rc = VERR_ACCESS_DENIED;
 
         if (   RT_FAILURE(rc)
@@ -436,8 +526,11 @@
  * @param   pcProcs     Where to store the returned process count.
  */
-int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppaProcs, PDWORD pcProcs)
+static int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppaProcs, PDWORD pcProcs)
 {
     AssertPtr(ppaProcs);
     AssertPtr(pcProcs);
+
+    if (!g_pfnEnumProcesses)
+        return VERR_NOT_SUPPORTED;
 
     /*
@@ -462,5 +555,5 @@
         /* Query the processes. Not the cbRet == buffer size means there could be more work to be done. */
         DWORD cbRet;
-        if (!EnumProcesses(paPID, cProcesses * sizeof(DWORD), &cbRet))
+        if (!g_pfnEnumProcesses(paPID, cProcesses * sizeof(DWORD), &cbRet))
         {
             rc = RTErrConvertFromWin32(GetLastError());
@@ -528,5 +621,5 @@
  * @param   paProcs     What
  */
-void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paProcs)
+static void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paProcs)
 {
     for (DWORD i = 0; i < cProcs; i++)
@@ -551,7 +644,7 @@
  * @param   puSession       Looked up session number.  Optional.
  */
-uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession,
-                                                 PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs,
-                                                 PULONG puTerminalSession)
+static uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession,
+                                                        PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs,
+                                                        PULONG puTerminalSession)
 {
     if (!pSession)
@@ -560,7 +653,9 @@
         return 0;
     }
+    if (!g_pfnLsaGetLogonSessionData)
+        return VERR_NOT_SUPPORTED;
 
     PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
-    NTSTATUS rcNt = LsaGetLogonSessionData(pSession, &pSessionData);
+    NTSTATUS rcNt = g_pfnLsaGetLogonSessionData(pSession, &pSessionData);
     if (rcNt != STATUS_SUCCESS)
     {
@@ -573,9 +668,8 @@
        VBoxServiceError("User SID=%p is not valid\n", pSessionData->Sid);
        if (pSessionData)
-           LsaFreeReturnBuffer(pSessionData);
+           g_pfnLsaFreeReturnBuffer(pSessionData);
        return 0;
     }
 
-    int rc = VINF_SUCCESS;
 
     /*
@@ -584,6 +678,6 @@
      * session <-> process LUIDs.
      */
-    uint32_t cNumProcs = 0;
-
+    int rc = VINF_SUCCESS;
+    uint32_t cProcessesFound = 0;
     for (DWORD i = 0; i < cProcs; i++)
     {
@@ -608,5 +702,5 @@
                 if (paProcs[i].fInteractive)
                 {
-                    cNumProcs++;
+                    cProcessesFound++;
                     if (!g_cVerbosity) /* We want a bit more info on higher verbosity. */
                         break;
@@ -619,7 +713,7 @@
         *puTerminalSession = pSessionData->Session;
 
-    LsaFreeReturnBuffer(pSessionData);
-
-    return cNumProcs;
+    g_pfnLsaFreeReturnBuffer(pSessionData);
+
+    return cProcessesFound;
 }
 
@@ -657,12 +751,14 @@
  * @param   pSession            The session to check.
  */
-bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER pUserInfo, PLUID pSession)
+static bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER pUserInfo, PLUID pSession)
 {
     AssertPtrReturn(pUserInfo, false);
     if (!pSession)
         return false;
+    if (!g_pfnLsaGetLogonSessionData)
+        return false;
 
     PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
-    NTSTATUS rcNt = LsaGetLogonSessionData(pSession, &pSessionData);
+    NTSTATUS rcNt = g_pfnLsaGetLogonSessionData(pSession, &pSessionData);
     if (rcNt != STATUS_SUCCESS)
     {
@@ -686,5 +782,5 @@
         }
         if (pSessionData)
-            LsaFreeReturnBuffer(pSessionData);
+            g_pfnLsaFreeReturnBuffer(pSessionData);
         return false;
     }
@@ -709,5 +805,5 @@
             || pSessionData->LogonTime.QuadPart == 0)
         {
-            LsaFreeReturnBuffer(pSessionData);
+            g_pfnLsaFreeReturnBuffer(pSessionData);
             return false;
         }
@@ -781,23 +877,18 @@
                 if (!s_fSkipRDPDetection)
                 {
-                    /** @todo Only do this once. Later. */
-                    OSVERSIONINFOEX OSInfoEx;
-                    RT_ZERO(OSInfoEx);
-                    OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
                     /* Skip RDP detection on non-NT systems. */
-                    if (   !GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
-                        || OSInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT)
-                    {
+                    if (g_WinVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)
                         s_fSkipRDPDetection = true;
-                    }
+
                     /* Skip RDP detection on Windows 2000.
                      * For Windows 2000 however we don't have any hotfixes, so just skip the
                      * RDP detection in any case. */
-                    if (   OSInfoEx.dwMajorVersion == 5
-                        && OSInfoEx.dwMinorVersion == 0)
-                    {
+                    if (   g_WinVersion.dwMajorVersion == 5
+                        && g_WinVersion.dwMinorVersion == 0)
                         s_fSkipRDPDetection = true;
-                    }
+
+                    /* Skip if we don't have the WTS API. */
+                    if (!g_pfnWTSQuerySessionInformationA)
+                        s_fSkipRDPDetection = true;
 
                     if (s_fSkipRDPDetection)
@@ -807,13 +898,16 @@
                 if (!s_fSkipRDPDetection)
                 {
+                    Assert(g_pfnWTSQuerySessionInformationA);
+                    Assert(g_pfnWTSFreeMemory);
+
                     /* Detect RDP sessions as well. */
                     LPTSTR  pBuffer = NULL;
                     DWORD   cbRet   = 0;
                     int     iState  = -1;
-                    if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
-                                                   pSessionData->Session,
-                                                   WTSConnectState,
-                                                   &pBuffer,
-                                                   &cbRet))
+                    if (g_pfnWTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE,
+                                                         pSessionData->Session,
+                                                         WTSConnectState,
+                                                         &pBuffer,
+                                                         &cbRet))
                     {
                         if (cbRet)
@@ -832,5 +926,5 @@
                         }
                         if (pBuffer)
-                            WTSFreeMemory(pBuffer);
+                            g_pfnWTSFreeMemory(pBuffer);
                     }
                     else
@@ -871,5 +965,5 @@
         pUserInfo->ulLastSession = pSessionData->Session;
 
-    LsaFreeReturnBuffer(pSessionData);
+    g_pfnLsaFreeReturnBuffer(pSessionData);
     return fFoundUser;
 }
@@ -1015,6 +1109,12 @@
     AssertPtrReturn(pcUsersInList, VERR_INVALID_POINTER);
 
-    int rc2 = VbglR3GuestPropConnect(&s_uDebugGuestPropClientID);
-    AssertRC(rc2);
+    int rc = RTOnce(&g_vgsvcWinVmInitOnce, vgsvcWinVmInfoInitOnce, NULL);
+    if (RT_FAILURE(rc))
+        return rc;
+    if (!g_pfnLsaEnumerateLogonSessions || !g_pfnEnumProcesses)
+        return VERR_NOT_SUPPORTED;
+
+    rc = VbglR3GuestPropConnect(&s_uDebugGuestPropClientID);
+    AssertRC(rc);
 
     char *pszUserList = NULL;
@@ -1025,5 +1125,5 @@
     PLUID    paSessions = NULL;
     ULONG    cSessions = 0;
-    NTSTATUS rcNt = LsaEnumerateLogonSessions(&cSessions, &paSessions);
+    NTSTATUS rcNt = g_pfnLsaEnumerateLogonSessions(&cSessions, &paSessions);
     if (rcNt != STATUS_SUCCESS)
     {
@@ -1048,5 +1148,5 @@
 
         if (paSessions)
-            LsaFreeReturnBuffer(paSessions);
+            g_pfnLsaFreeReturnBuffer(paSessions);
 
         return RTErrConvertFromWin32(ulError);
@@ -1056,5 +1156,5 @@
     PVBOXSERVICEVMINFOPROC  paProcs;
     DWORD                   cProcs;
-    int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
+    rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
     if (RT_FAILURE(rc))
     {
@@ -1074,5 +1174,5 @@
             ULONG cUniqueUsers = 0;
 
-            /**
+            /*
              * Note: The cSessions loop variable does *not* correlate with
              *       the Windows session ID!
@@ -1098,6 +1198,7 @@
                     if (g_cVerbosity > 3)
                     {
-                        char szDebugSessionPath[255]; RTStrPrintf(szDebugSessionPath,  sizeof(szDebugSessionPath), "/VirtualBox/GuestInfo/Debug/LSA/Session/%RU32",
-                                                                  userSession.ulLastSession);
+                        char szDebugSessionPath[255];
+                        RTStrPrintf(szDebugSessionPath,  sizeof(szDebugSessionPath),
+                                    "/VirtualBox/GuestInfo/Debug/LSA/Session/%RU32", userSession.ulLastSession);
                         VBoxServiceWritePropF(s_uDebugGuestPropClientID, szDebugSessionPath,
                                               "#%RU32: cSessionProcs=%RU32 (of %RU32 procs total)", s_uDebugIter, cCurSessionProcs, cProcs);
@@ -1225,5 +1326,5 @@
     }
     if (paSessions)
-        LsaFreeReturnBuffer(paSessions);
+        g_pfnLsaFreeReturnBuffer(paSessions);
 
     if (RT_SUCCESS(rc))
@@ -1239,5 +1340,4 @@
 }
 
-#endif /* TARGET_NT4 */
 
 int VBoxServiceWinGetComponentVersions(uint32_t uClientID)
@@ -1258,5 +1358,4 @@
 
     /* The file information table. */
-#ifndef TARGET_NT4
     const VBOXSERVICEVMINFOFILE aVBoxFiles[] =
     {
@@ -1264,13 +1363,17 @@
         { szSysDir, "VBoxHook.dll" },
         { szSysDir, "VBoxDisp.dll" },
+        { szSysDir, "VBoxTray.exe" },
+#ifdef TARGET_NT4
+        { szSysDir, "VBoxServiceNT.exe" },
+#else
+        { szSysDir, "VBoxService.exe" },
         { szSysDir, "VBoxMRXNP.dll" },
-        { szSysDir, "VBoxService.exe" },
-        { szSysDir, "VBoxTray.exe" },
         { szSysDir, "VBoxGINA.dll" },
         { szSysDir, "VBoxCredProv.dll" },
+#endif
 
  /* On 64-bit we don't yet have the OpenGL DLLs in native format.
     So just enumerate the 32-bit files in the SYSWOW directory. */
-# ifdef RT_ARCH_AMD64
+#ifdef RT_ARCH_AMD64
         { szSysWowDir, "VBoxOGLarrayspu.dll" },
         { szSysWowDir, "VBoxOGLcrutil.dll" },
@@ -1280,5 +1383,6 @@
         { szSysWowDir, "VBoxOGLfeedbackspu.dll" },
         { szSysWowDir, "VBoxOGL.dll" },
-# else  /* !RT_ARCH_AMD64 */
+#else  /* !RT_ARCH_AMD64 */
+# ifdef TARGET_NT4
         { szSysDir, "VBoxOGLarrayspu.dll" },
         { szSysDir, "VBoxOGLcrutil.dll" },
@@ -1288,26 +1392,17 @@
         { szSysDir, "VBoxOGLfeedbackspu.dll" },
         { szSysDir, "VBoxOGL.dll" },
-# endif /* !RT_ARCH_AMD64 */
-
+# endif
+#endif /* !RT_ARCH_AMD64 */
+
+#ifdef TARGET_NT4
+        { szDriversDir, "VBoxGuestNT.sys" },
+        { szDriversDir, "VBoxMouseNT.sys" },
+#else
         { szDriversDir, "VBoxGuest.sys" },
         { szDriversDir, "VBoxMouse.sys" },
         { szDriversDir, "VBoxSF.sys"    },
+#endif
         { szDriversDir, "VBoxVideo.sys" },
     };
-
-#else  /* TARGET_NT4 */
-    const VBOXSERVICEVMINFOFILE aVBoxFiles[] =
-    {
-        { szSysDir, "VBoxControl.exe" },
-        { szSysDir, "VBoxHook.dll" },
-        { szSysDir, "VBoxDisp.dll" },
-        { szSysDir, "VBoxServiceNT.exe" },
-        { szSysDir, "VBoxTray.exe" },
-
-        { szDriversDir, "VBoxGuestNT.sys" },
-        { szDriversDir, "VBoxMouseNT.sys" },
-        { szDriversDir, "VBoxVideo.sys" },
-    };
-#endif /* TARGET_NT4 */
 
     for (unsigned i = 0; i < RT_ELEMENTS(aVBoxFiles); i++)
