Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 39759)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 39760)
@@ -30,4 +30,5 @@
 
 #include <iprt/assert.h>
+#include <iprt/ldr.h>
 #include <iprt/mem.h>
 #include <iprt/thread.h>
@@ -72,12 +73,102 @@
 *   Prototypes
 *******************************************************************************/
-uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs);
+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(PVBOXSERVICEVMINFOPROC paProcs);
 
+typedef BOOL WINAPI FNQUERYFULLPROCESSIMAGENAME(HANDLE,  DWORD, LPTSTR, PDWORD);
+typedef FNQUERYFULLPROCESSIMAGENAME *PFNQUERYFULLPROCESSIMAGENAME;
 
 
 #ifndef TARGET_NT4
+
+/**
+ * Retrieves the module name of a given process.
+ *
+ * @return  IPRT status code.
+ * @param   pProc
+ * @param   pszBuf
+ * @param   cbBuf
+ */
+static int VBoxServiceVMInfoWinProcessesGetModuleName(PVBOXSERVICEVMINFOPROC const pProc,
+                                                      TCHAR *pszName, size_t cbName)
+{
+    AssertPtrReturn(pProc, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+    AssertReturn(cbName, VERR_INVALID_PARAMETER);
+
+    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 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. */
+
+    HANDLE h = OpenProcess(dwFlags, FALSE, pProc->id);
+    if (h == NULL)
+    {
+        DWORD dwErr = GetLastError();
+        if (g_cVerbosity)
+            VBoxServiceError("VMInfo/Users: Unable to open process with PID=%ld, error=%ld",
+                             pProc->id, dwErr);
+        rc = RTErrConvertFromWin32(dwErr);
+    }
+    else
+    {
+        /* Since GetModuleFileNameEx has trouble with cross-bitness stuff (32-bit apps cannot query 64-bit
+           apps and vice verse) we have to use a different code path for Vista and up. */
+
+        /* Note: For 2000 + NT4 we might just use GetModuleFileName() 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. */
+            RTLDRMOD hMod;
+            rc = RTLdrLoad("kernel32.dll", &hMod);
+            if (RT_SUCCESS(rc))
+            {
+                PFNQUERYFULLPROCESSIMAGENAME pfnQueryFullProcessImageName;
+                rc = RTLdrGetSymbol(hMod, "QueryFullProcessImageNameA", (void **)&pfnQueryFullProcessImageName);
+                if (RT_SUCCESS(rc))
+                {
+                    DWORD dwLen = sizeof(pszName);
+                    if (!pfnQueryFullProcessImageName(h, 0 /*PROCESS_NAME_NATIVE*/, pszName, &dwLen))
+                        rc = VERR_ACCESS_DENIED;
+                }
+
+                RTLdrClose(hMod);
+            }
+        }
+        else
+        {
+            if (!GetModuleFileNameEx(h, NULL /* Get main executable */, pszName, cbName / sizeof(TCHAR)))
+                rc = VERR_ACCESS_DENIED;
+        }
+
+        if (VERR_ACCESS_DENIED == rc)
+        {
+            DWORD dwErr = GetLastError();
+            if (g_cVerbosity)
+                VBoxServiceError("VMInfo/Users: Unable to retrieve module name for PID=%ld, error=%ld",
+                                 pProc->id, dwErr);
+            rc = RTErrConvertFromWin32(dwErr);
+        }
+
+        CloseHandle(h);
+    }
+
+    return rc;
+}
+
 
 /**
@@ -91,8 +182,14 @@
                                                      TOKEN_INFORMATION_CLASS tkClass)
 {
-    AssertPtr(pProc);
+    AssertPtrReturn(pProc, VERR_INVALID_POINTER);
     HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pProc->id);
     if (h == NULL)
-        return RTErrConvertFromWin32(GetLastError());
+    {
+        DWORD dwErr = GetLastError();
+        if (g_cVerbosity)
+            VBoxServiceError("VMInfo/Users: Unable to open process with PID=%ld, error=%ld",
+                             pProc->id, dwErr);
+        return RTErrConvertFromWin32(dwErr);
+    }
 
      int    rc = VERR_NO_MEMORY;
@@ -145,5 +242,11 @@
     }
     else
-        rc = RTErrConvertFromWin32(GetLastError());
+    {
+        DWORD dwErr = GetLastError();
+        if (g_cVerbosity)
+            VBoxServiceError("VMInfo/Users: Unable to query process token for PID=%ld, error=%ld\n",
+                             pProc->id, dwErr);
+        rc = RTErrConvertFromWin32(dwErr);
+    }
     CloseHandle(h);
     return rc;
@@ -171,5 +274,5 @@
      */
     DWORD   cProcesses  = 64;
-    PDWORD  paPids      = NULL;
+    PDWORD  paPID       = NULL;
     int     rc          = VINF_SUCCESS;
     do
@@ -177,5 +280,5 @@
         /* Allocate / grow the buffer first. */
         cProcesses *= 2;
-        void *pvNew = RTMemRealloc(paPids, cProcesses * sizeof(DWORD));
+        void *pvNew = RTMemRealloc(paPID, cProcesses * sizeof(DWORD));
         if (!pvNew)
         {
@@ -183,9 +286,9 @@
             break;
         }
-        paPids = (PDWORD)pvNew;
+        paPID = (PDWORD)pvNew;
 
         /* Query the processes. Not the cbRet == buffer size means there could be more work to be done. */
         DWORD cbRet;
-        if (!EnumProcesses(paPids, cProcesses * sizeof(DWORD), &cbRet))
+        if (!EnumProcesses(paPID, cProcesses * sizeof(DWORD), &cbRet))
         {
             rc = RTErrConvertFromWin32(GetLastError());
@@ -197,5 +300,5 @@
             break;
         }
-    } while (cProcesses <= 32768); /* Should be enough; see: http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx */
+    } while (cProcesses <= _32K); /* Should be enough; see: http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx */
     if (RT_SUCCESS(rc))
     {
@@ -210,5 +313,5 @@
             for (DWORD i = 0; i < cProcesses; i++)
             {
-                paProcs[i].id = paPids[i];
+                paProcs[i].id = paPID[i];
                 rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(&paProcs[i], TokenStatistics);
                 if (RT_FAILURE(rc))
@@ -233,5 +336,5 @@
     }
 
-    RTMemFree(paPids);
+    RTMemFree(paPID);
     return rc;
 }
@@ -256,5 +359,5 @@
  * @param   cProcs          The number of processes in the snaphot.
  */
-uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs)
+uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs)
 {
     if (!pSession)
@@ -287,10 +390,16 @@
         {
             cNumProcs++;
-            if (g_cVerbosity < 4) /* We want a bit more info on high verbosity. */
+            if (!g_cVerbosity) /* We want a bit more info on higher verbosity. */
                 break;
-        }
-    }
-
-    if (g_cVerbosity >= 4)
+
+            TCHAR szModule[_1K];
+            int rc2 = VBoxServiceVMInfoWinProcessesGetModuleName(&paProcs[i], szModule, sizeof(szModule));
+            if (RT_SUCCESS(rc2))
+                VBoxServiceVerbose(4, "VMInfo/Users: PID=%ld: %s\n",
+                                   paProcs[i].id, szModule);
+        }
+    }
+
+    if (g_cVerbosity)
         VBoxServiceVerbose(3, "VMInfo/Users: Session %u has %u processes\n",
                            pSessionData->Session, cNumProcs);
