Changeset 26136 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Feb 1, 2010 5:45:40 PM (15 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
r25959 r26136 117 117 118 118 119 /** Reports our current status to the SCM. */ 119 120 BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint) 120 121 { … … 140 141 int VBoxServiceWinSetDesc(SC_HANDLE hService) 141 142 { 142 /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields 143 /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields 143 144 like a longer service description. */ 144 145 #ifndef TARGET_NT4 … … 146 147 /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */ 147 148 desc. lpDescription = VBOXSERVICE_DESCRIPTION; 148 if (FALSE == ChangeServiceConfig2(hService, 149 SERVICE_CONFIG_DESCRIPTION, /* Service info level */ 149 if (FALSE == ChangeServiceConfig2(hService, 150 SERVICE_CONFIG_DESCRIPTION, /* Service info level */ 150 151 &desc)) 151 152 { … … 158 159 159 160 161 /** Installs the service into the registry. */ 160 162 int VBoxServiceWinInstall(void) 161 163 { … … 181 183 imagePath, NULL, NULL, NULL, NULL, NULL); 182 184 int rc = VINF_SUCCESS; 183 if (NULL == hService) 185 if (NULL == hService) 184 186 { 185 187 DWORD dwErr = GetLastError(); … … 242 244 } 243 245 246 /** Uninstalls the service from the registry. */ 244 247 int VBoxServiceWinUninstall(void) 245 248 { -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r26061 r26136 363 363 int rc; 364 364 VBoxServiceVerbose(2, "Waiting for service '%s' to stop ...\n", g_aServices[j].pDesc->pszName); 365 for (int i =0; i<30; i++) /* Wait 30 seconds in total */365 for (int i = 0; i < 30; i++) /* Wait 30 seconds in total */ 366 366 { 367 367 rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL); -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r26083 r26136 106 106 typedef struct 107 107 { 108 WCHAR szUser[_MAX_PATH];109 WCHAR szAuthenticationPackage[_MAX_PATH];110 WCHAR szLogonDomain[_MAX_PATH];108 WCHAR wszUser[_MAX_PATH]; 109 WCHAR wszAuthenticationPackage[_MAX_PATH]; 110 WCHAR wszLogonDomain[_MAX_PATH]; 111 111 } VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER; 112 112 /** Structure for the file information lookup. */ … … 119 119 typedef struct 120 120 { 121 DWORD id; 121 DWORD id; 122 122 LUID luid; 123 123 } VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC; 124 124 /** Function prototypes for dynamic loading. */ 125 typedef DWORD (WINAPI * fnWTSGetActiveConsoleSessionId)();125 typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void); 126 126 #endif /* RT_OS_WINDOWS */ 127 127 … … 151 151 extern SERVICE_STATUS_HANDLE g_hWinServiceStatus; 152 152 extern SERVICE_TABLE_ENTRY const g_aServiceTable[]; /** @todo generate on the fly, see comment in main() from the enabled sub services. */ 153 extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */ 153 154 154 /** Installs the service into the registry. */ 155 extern int VBoxServiceWinInstall(void); 156 /** Uninstalls the service from the registry. */ 157 extern int VBoxServiceWinUninstall(void); 158 /** Reports our current status to the SCM. */ 155 extern int VBoxServiceWinInstall(void); 156 extern int VBoxServiceWinUninstall(void); 159 157 extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint); 160 158 # ifdef VBOX_WITH_GUEST_PROPS 161 /** Determines the total count of processes attach to a logon session. */ 162 extern DWORD VBoxServiceVMInfoWinSessionGetProcessCount(PLUID pSession, 163 PVBOXSERVICEVMINFOPROC pProc, DWORD dwProcCount); 164 /** Detects wheter a user is logged on based on the enumerated processes. */ 165 extern BOOL VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, 166 PLUID a_pSession); 167 /** Gets logon user IDs from enumerated processes. ppProc needs to be freed with VBoxServiceVMInfoWinProcessesFree() afterwards. */ 168 extern int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount); 169 /** Frees the process structure allocated by VBoxServiceVMInfoWinProcessesEnumerate() before. */ 170 extern void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC pProc); 159 extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs); 160 extern bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession); 161 extern int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount); 162 extern void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs); 163 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID); 171 164 # endif /* VBOX_WITH_GUEST_PROPS */ 172 165 #endif /* RT_OS_WINDOWS */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceUtils.cpp
r25802 r26136 5 5 6 6 /* 7 * Copyright (C) 2009 Sun Microsystems, Inc.7 * Copyright (C) 2009-2010 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 26 26 #ifdef RT_OS_WINDOWS 27 27 # include <Windows.h> 28 # include <iprt/param.h> 29 # include <iprt/path.h> 28 30 #endif 29 30 31 #include <iprt/assert.h> 31 32 #include <iprt/mem.h> … … 35 36 #include "VBoxServiceInternal.h" 36 37 37 38 38 #ifdef VBOX_WITH_GUEST_PROPS 39 39 40 /** 40 41 * Reads a guest property. … … 53 54 int VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp) 54 55 { 55 size_tcbBuf = _1K;56 void *pvBuf = NULL;57 int rc;56 uint32_t cbBuf = _1K; 57 void *pvBuf = NULL; 58 int rc; 58 59 59 60 *ppszValue = NULL; … … 186 187 return rc; 187 188 } 189 188 190 #endif /* VBOX_WITH_GUEST_PROPS */ 189 190 191 191 #ifdef RT_OS_WINDOWS 192 /** @todo return an iprt status code instead of BOOL */ 193 BOOL VBoxServiceGetFileString(const char* pszFileName, 194 char* pszBlock, 195 char* pszString, 196 PUINT puiSize) 197 { 198 DWORD dwHandle, dwLen = 0; 199 UINT uiDataLen = 0; 200 char* lpData = NULL; 201 UINT uiValueLen = 0; 202 LPTSTR lpValue = NULL; 203 BOOL bRet = FALSE; 204 205 Assert(pszFileName); 206 Assert(pszBlock); 207 Assert(pszString); 208 Assert(puiSize > 0); 209 210 /* The VS_FIXEDFILEINFO structure contains version information about a file. 211 This information is language and code page independent. */ 212 VS_FIXEDFILEINFO *pFileInfo = NULL; 213 dwLen = GetFileVersionInfoSize(pszFileName, &dwHandle); 214 215 if (!dwLen) 216 { 217 /* Don't print this to release log -- this confuses people if a file 218 * isn't present because it's optional / was not installed intentionally. */ 219 VBoxServiceVerbose(3, "No file information found! File = %s, Error: %Rrc\n", 220 pszFileName, RTErrConvertFromWin32(GetLastError())); 221 return FALSE; 222 } 223 224 lpData = (LPTSTR) RTMemTmpAlloc(dwLen); 225 if (!lpData) 226 { 227 VBoxServiceError("Could not allocate temp buffer for file string lookup!\n"); 228 return FALSE; 229 } 230 231 if (GetFileVersionInfo(pszFileName, dwHandle, dwLen, lpData)) 232 { 233 if((bRet = VerQueryValue(lpData, pszBlock, (LPVOID*)&lpValue, (PUINT)&uiValueLen))) 234 { 235 UINT uiSize = uiValueLen * sizeof(char); 236 237 if(uiSize > *puiSize) 238 uiSize = *puiSize; 239 240 ZeroMemory(pszString, *puiSize); 241 memcpy(pszString, lpValue, uiSize); 242 } 243 else VBoxServiceVerbose(3, "No file string value for \"%s\" in file \"%s\" available!\n", pszBlock, pszFileName); 244 } 245 else VBoxServiceVerbose(3, "No file version table for file \"%s\" available!\n", pszFileName); 246 247 RTMemFree(lpData); 248 return bRet; 249 } 250 251 252 /** @todo return an iprt status code instead of BOOL */ 253 BOOL VBoxServiceGetFileVersion(const char* pszFileName, 254 DWORD* pdwMajor, 255 DWORD* pdwMinor, 256 DWORD* pdwBuildNumber, 257 DWORD* pdwRevisionNumber) 258 { 259 DWORD dwHandle, dwLen = 0; 260 UINT BufLen = 0; 261 LPTSTR lpData = NULL; 262 BOOL bRet = FALSE; 263 264 Assert(pszFileName); 265 Assert(pdwMajor); 266 Assert(pdwMinor); 267 Assert(pdwBuildNumber); 268 Assert(pdwRevisionNumber); 269 270 /* The VS_FIXEDFILEINFO structure contains version information about a file. 271 This information is language and code page independent. */ 272 VS_FIXEDFILEINFO *pFileInfo = NULL; 273 dwLen = GetFileVersionInfoSize(pszFileName, &dwHandle); 274 275 /* Try own fields defined in block "\\StringFileInfo\\040904b0\\FileVersion". */ 276 char szValue[_MAX_PATH] = {0}; 277 char *pszValue = szValue; 278 UINT uiSize = _MAX_PATH; 279 int r = 0; 280 281 bRet = VBoxServiceGetFileString(pszFileName, "\\StringFileInfo\\040904b0\\FileVersion", szValue, &uiSize); 282 if (bRet) 283 { 284 sscanf(pszValue, "%ld.%ld.%ld.%ld", pdwMajor, pdwMinor, pdwBuildNumber, pdwRevisionNumber); 285 } 286 else if (dwLen > 0) 287 { 288 /* Try regular fields - this maybe is not file provided by VBox! */ 289 lpData = (LPTSTR) RTMemTmpAlloc(dwLen); 290 if (!lpData) 291 { 292 VBoxServiceError("Could not allocate temp buffer for file version string!\n"); 293 return FALSE; 294 } 295 296 if (GetFileVersionInfo(pszFileName, dwHandle, dwLen, lpData)) 297 { 298 if((bRet = VerQueryValue(lpData, "\\", (LPVOID*)&pFileInfo, (PUINT)&BufLen))) 192 193 /** 194 * Helper for VBoxServiceGetFileVersion and attemps to read and parse 195 * FileVersion. 196 * 197 * @returns Success indicator. 198 */ 199 static bool VBoxServiceGetFileVersionOwn(LPSTR pVerData, 200 PDWORD pdwMajor, 201 PDWORD pdwMinor, 202 PDWORD pdwBuildNumber, 203 PDWORD pdwRevisionNumber) 204 { 205 UINT cchStrValue = 0; 206 LPTSTR pStrValue = NULL; 207 if (!VerQueryValueA(pVerData, "\\StringFileInfo\\040904b0\\FileVersion", (LPVOID *)&pStrValue, &cchStrValue)) 208 return false; 209 210 /** @todo r=bird: get rid of this. Avoid sscanf like the plague! */ 211 if (sscanf(pStrValue, "%ld.%ld.%ld.%ld", pdwMajor, pdwMinor, pdwBuildNumber, pdwRevisionNumber) != 4) 212 return false; 213 214 return true; 215 } 216 217 218 /** 219 * Worker for VBoxServiceGetFileVersionString. 220 * 221 * @returns VBox status code. 222 * @param pszFilename ASCII & ANSI & UTF-8 compliant name. 223 */ 224 static int VBoxServiceGetFileVersion(const char *pszFilename, 225 PDWORD pdwMajor, 226 PDWORD pdwMinor, 227 PDWORD pdwBuildNumber, 228 PDWORD pdwRevisionNumber) 229 { 230 int rc; 231 232 *pdwMajor = *pdwMinor = *pdwBuildNumber = *pdwRevisionNumber = 0; 233 234 /* 235 * Get the file version info. 236 */ 237 DWORD dwHandleIgnored; 238 DWORD cbVerData = GetFileVersionInfoSizeA(pszFilename, &dwHandleIgnored); 239 if (cbVerData) 240 { 241 LPTSTR pVerData = (LPTSTR)RTMemTmpAllocZ(cbVerData); 242 if (pVerData) 243 { 244 if (GetFileVersionInfoA(pszFilename, dwHandleIgnored, cbVerData, pVerData)) 299 245 { 300 *pdwMajor = HIWORD(pFileInfo->dwFileVersionMS); 301 *pdwMinor = LOWORD(pFileInfo->dwFileVersionMS); 302 *pdwBuildNumber = HIWORD(pFileInfo->dwFileVersionLS); 303 *pdwRevisionNumber = LOWORD(pFileInfo->dwFileVersionLS); 304 bRet = TRUE; 246 /* 247 * Try query and parse the FileVersion string our selves first 248 * since this will give us the correct revision number when 249 * it goes beyond the range of an uint16_t / WORD. 250 */ 251 if (VBoxServiceGetFileVersionOwn(pVerData, pdwMajor, pdwMinor, pdwBuildNumber, pdwRevisionNumber)) 252 rc = VINF_SUCCESS; 253 else 254 { 255 /* Fall back on VS_FIXEDFILEINFO */ 256 UINT cbFileInfoIgnored = 0; 257 VS_FIXEDFILEINFO *pFileInfo = NULL; 258 if (VerQueryValue(pVerData, "\\", (LPVOID *)&pFileInfo, &cbFileInfoIgnored)) 259 { 260 *pdwMajor = HIWORD(pFileInfo->dwFileVersionMS); 261 *pdwMinor = LOWORD(pFileInfo->dwFileVersionMS); 262 *pdwBuildNumber = HIWORD(pFileInfo->dwFileVersionLS); 263 *pdwRevisionNumber = LOWORD(pFileInfo->dwFileVersionLS); 264 rc = VINF_SUCCESS; 265 } 266 else 267 { 268 rc = RTErrConvertFromWin32(GetLastError()); 269 VBoxServiceVerbose(3, "No file version value for file \"%s\" available! (%d / rc=%Rrc)\n", 270 pszFilename, GetLastError(), rc); 271 } 272 } 305 273 } 306 else VBoxServiceVerbose(3, "No file version value for file \"%s\" available!\n", pszFileName); 307 } 308 else VBoxServiceVerbose(3, "No file version struct for file \"%s\" available!\n", pszFileName); 309 310 RTMemFree(lpData); 311 } 312 return bRet; 313 } 314 315 316 BOOL VBoxServiceGetFileVersionString(const char* pszPath, const char* pszFileName, char* pszVersion, UINT uiSize) 317 { 318 BOOL bRet = FALSE; 319 char szFullPath[_MAX_PATH] = {0}; 320 char szValue[_MAX_PATH] = {0}; 321 int r = 0; 322 323 RTStrPrintf(szFullPath, 4096, "%s\\%s", pszPath, pszFileName); 324 325 DWORD dwMajor, dwMinor, dwBuild, dwRev; 326 327 bRet = VBoxServiceGetFileVersion(szFullPath, &dwMajor, &dwMinor, &dwBuild, &dwRev); 328 if (bRet) 329 RTStrPrintf(pszVersion, uiSize, "%ld.%ld.%ldr%ld", dwMajor, dwMinor, dwBuild, dwRev); 274 else 275 { 276 rc = RTErrConvertFromWin32(GetLastError()); 277 VBoxServiceVerbose(0, "GetFileVersionInfo(%s) -> %u / %Rrc\n", pszFilename, GetLastError(), rc); 278 } 279 280 RTMemTmpFree(pVerData); 281 } 282 else 283 { 284 VBoxServiceVerbose(0, "Failed to allocate %u byte for file version info for '%s'\n", cbVerData, pszFilename); 285 rc = VERR_NO_TMP_MEMORY; 286 } 287 } 330 288 else 331 RTStrPrintf(pszVersion, uiSize, "-"); 332 333 return bRet; 334 } 335 #endif /* !RT_OS_WINDOWS */ 336 289 { 290 rc = RTErrConvertFromWin32(GetLastError()); 291 VBoxServiceVerbose(3, "GetFileVersionInfoSize(%s) -> %u / %Rrc\n", pszFilename, GetLastError(), rc); 292 } 293 return rc; 294 } 295 296 297 /** 298 * Gets a re-formatted version string from the VS_FIXEDFILEINFO table. 299 * 300 * @returns VBox status code. The output buffer is always valid and the status 301 * code can safely be ignored. 302 * 303 * @param pszPath The base path. 304 * @param pszFilaname The filename. 305 * @param pszVersion Where to return the version string. 306 * @param cbVersion The size of the version string buffer. This MUST be 307 * at least 2 bytes! 308 */ 309 int VBoxServiceGetFileVersionString(const char *pszPath, const char *pszFilename, 310 char *pszVersion, size_t cbVersion) 311 { 312 /* 313 * We will ALWAYS return with a valid output buffer. 314 */ 315 AssertReturn(cbVersion >= 2, VERR_BUFFER_OVERFLOW); 316 pszVersion[0] = '-'; 317 pszVersion[1] = '\0'; 318 319 /* 320 * Create the path and query the bits. 321 */ 322 char szFullPath[RTPATH_MAX]; 323 int rc = RTPathJoin(szFullPath, sizeof(szFullPath), pszPath, pszFilename); 324 if (RT_SUCCESS(rc)) 325 { 326 DWORD dwMajor, dwMinor, dwBuild, dwRev; 327 rc = VBoxServiceGetFileVersion(szFullPath, &dwMajor, &dwMinor, &dwBuild, &dwRev); 328 if (RT_SUCCESS(rc)) 329 RTStrPrintf(pszVersion, cbVersion, "%ld.%ld.%ldr%ld", dwMajor, dwMinor, dwBuild, dwRev); 330 } 331 return rc; 332 } 333 334 #endif /* RT_OS_WINDOWS */ 335 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceUtils.h
r25390 r26136 26 26 27 27 #ifdef VBOX_WITH_GUEST_PROPS 28 /** Reads a guest property. */29 28 int VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp); 30 /** Reads a guest property as a 32-bit value. */31 29 int VBoxServiceReadPropUInt32(uint32_t u32ClientId, const char *pszPropName, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max); 32 /** Wrapper around VbglR3GuestPropWriteValue that does value formatting and logging. */33 30 int VBoxServiceWritePropF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...); 34 31 #endif 32 35 33 #ifdef RT_OS_WINDOWS 36 /** Gets a pre-formatted version string from the VS_FIXEDFILEINFO table. */ 37 BOOL VBoxServiceGetFileVersionString(const char* pszPath, const char* pszFileName, char* pszVersion, UINT uiSize); 34 int VBoxServiceGetFileVersionString(const char *pszPath, const char *pszFileName, char *pszVersion, size_t cbVersion); 38 35 #endif 39 36 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
r26092 r26136 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox VMInfo-win - Virtual machine (guest) information for the host.3 * VBoxService - Virtual Machine Information for the Host, Windows specifics. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2009 Sun Microsystems, Inc.7 * Copyright (C) 2009-2010 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 43 43 * Global Variables * 44 44 *******************************************************************************/ 45 /** Function prototypes for dynamic loading. */ 46 PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId = NULL; 47 48 45 49 #ifndef TARGET_NT4 46 /** Function prototypes for dynamic loading. */ 47 extern fnWTSGetActiveConsoleSessionId g_pfnWTSGetActiveConsoleSessionId; 48 /** The vminfo interval (millseconds). */49 uint32_t g_VMInfoLoggedInUsersCount = 0;50 #endif 51 52 53 #ifndef TARGET_NT4 54 int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pProc, 55 TOKEN_INFORMATION_CLASS tkClass)50 51 /** 52 * Fills in more data for a process. 53 * 54 * @returns VBox status code. 55 * @param pProc The process structure to fill data into. 56 * @param tkClass The kind of token information to get. 57 */ 58 static int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pProc, 59 TOKEN_INFORMATION_CLASS tkClass) 56 60 { 57 61 AssertPtr(pProc); … … 60 64 return RTErrConvertFromWin32(GetLastError()); 61 65 66 int rc = VERR_NO_MEMORY; 62 67 HANDLE hToken; 63 int rc; 64 if (FALSE == OpenProcessToken(h, TOKEN_QUERY, &hToken)) 65 { 66 rc = RTErrConvertFromWin32(GetLastError()); 67 } 68 else 68 if (OpenProcessToken(h, TOKEN_QUERY, &hToken)) 69 69 { 70 70 void *pvTokenInfo = NULL; … … 72 72 switch (tkClass) 73 73 { 74 case TokenStatistics: 75 dwTokenInfoSize = sizeof(TOKEN_STATISTICS); 76 pvTokenInfo = (TOKEN_STATISTICS*)RTMemAlloc(dwTokenInfoSize); 77 AssertPtr(pvTokenInfo); 78 break; 79 80 /** @todo Implement more token classes here. */ 81 82 default: 83 VBoxServiceError("Token class not implemented: %ld", tkClass); 84 rc = VERR_NOT_IMPLEMENTED; 85 break; 74 case TokenStatistics: 75 dwTokenInfoSize = sizeof(TOKEN_STATISTICS); 76 pvTokenInfo = RTMemAlloc(dwTokenInfoSize); 77 break; 78 79 /** @todo Implement more token classes here. */ 80 81 default: 82 VBoxServiceError("Token class not implemented: %ld", tkClass); 83 rc = VERR_NOT_IMPLEMENTED; 84 break; 86 85 } 87 86 88 87 if (pvTokenInfo) 89 { 88 { 90 89 DWORD dwRetLength; 91 if (FALSE == GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength)) 92 { 93 rc = RTErrConvertFromWin32(GetLastError()); 94 } 95 else 90 if (GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength)) 96 91 { 97 92 switch (tkClass) 98 93 { 99 case TokenStatistics:94 case TokenStatistics: 100 95 { 101 96 TOKEN_STATISTICS *pStats = (TOKEN_STATISTICS*)pvTokenInfo; 102 AssertPtr(pStats);103 97 pProc->luid = pStats->AuthenticationId; 104 /* @todo Add more information of TOKEN_STATISTICS as needed. */98 /** @todo Add more information of TOKEN_STATISTICS as needed. */ 105 99 break; 106 100 } 107 101 108 default:109 /* Should never get here! */110 break;102 default: 103 /* Should never get here! */ 104 break; 111 105 } 112 106 rc = VINF_SUCCESS; 113 107 } 108 else 109 rc = RTErrConvertFromWin32(GetLastError()); 114 110 RTMemFree(pvTokenInfo); 115 111 } 116 112 CloseHandle(hToken); 117 } 113 } 114 else 115 rc = RTErrConvertFromWin32(GetLastError()); 118 116 CloseHandle(h); 119 117 return rc; 120 118 } 121 119 122 int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount) 123 { 124 AssertPtr(ppProc); 125 AssertPtr(pdwCount); 126 127 DWORD dwNumProcs = 128; /* Number of processes our array can hold */ 128 DWORD *pdwProcIDs = (DWORD*)RTMemAlloc(dwNumProcs * sizeof(DWORD)); 129 if (pdwProcIDs == NULL) 130 return VERR_NO_MEMORY; 131 132 int rc; 133 DWORD cbRet; /* Returned size in bytes */ 120 121 /** 122 * Enumerate all the processes in the system and get the logon user IDs for 123 * them. 124 * 125 * @returns VBox status code. 126 * @param ppaProcs Where to return the process snapshot. This must be 127 * freed by calling VBoxServiceVMInfoWinProcessesFree. 128 * 129 * @param pcProcs Where to store the returned process count. 130 */ 131 int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppaProcs, PDWORD pcProcs) 132 { 133 AssertPtr(ppaProcs); 134 AssertPtr(pcProcs); 135 136 /* 137 * Call EnumProcesses with an increasingly larger buffer until it all fits 138 * or we think something is screwed up. 139 */ 140 DWORD cProcesses = 64; 141 PDWORD paPids = NULL; 142 int rc = VINF_SUCCESS; 134 143 do 135 144 { 136 if (FALSE == EnumProcesses(pdwProcIDs, dwNumProcs * sizeof(DWORD), &cbRet)) 145 /* Allocate / grow the buffer first. */ 146 cProcesses *= 2; 147 void *pvNew = RTMemRealloc(paPids, cProcesses * sizeof(DWORD)); 148 if (!pvNew) 149 { 150 rc = VERR_NO_MEMORY; 151 break; 152 } 153 paPids = (PDWORD)pvNew; 154 155 /* Query the processes. Not the cbRet == buffer size means there could be more work to be done. */ 156 DWORD cbRet; 157 if (!EnumProcesses(paPids, cProcesses * sizeof(DWORD), &cbRet)) 137 158 { 138 159 rc = RTErrConvertFromWin32(GetLastError()); 139 160 break; 140 161 } 141 142 /* Was our array big enough? Or do we need more space? */ 143 if (cbRet >= dwNumProcs * sizeof(DWORD)) 162 if (cbRet < cProcesses * sizeof(DWORD)) 144 163 { 145 /* Apparently not, so try next bigger size */ 146 dwNumProcs += 128; 147 pdwProcIDs = (DWORD*)RTMemRealloc(pdwProcIDs, dwNumProcs * sizeof(DWORD)); 148 if (pdwProcIDs == NULL) 164 cProcesses = cbRet / sizeof(DWORD); 165 break; 166 } 167 } while (cProcesses <= 32768); /* Should be enough; see: http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx */ 168 if (RT_SUCCESS(rc)) 169 { 170 /* 171 * Allocate out process structures and fill data into them. 172 * We currently only try lookup their LUID's. 173 */ 174 PVBOXSERVICEVMINFOPROC paProcs; 175 paProcs = (PVBOXSERVICEVMINFOPROC)RTMemAllocZ(cProcesses * sizeof(VBOXSERVICEVMINFOPROC)); 176 if (paProcs) 177 { 178 for (DWORD i = 0; i < cProcesses; i++) 149 179 { 150 rc = VERR_NO_MEMORY; 151 break; 180 paProcs[i].id = paPids[i]; 181 rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(&paProcs[i], TokenStatistics); 182 if (RT_FAILURE(rc)) 183 { 184 /* Because some processes cannot be opened/parsed on 185 Windows, we should not consider to be this an error here. */ 186 rc = VINF_SUCCESS; 187 } 152 188 } 189 190 /* Save number of processes */ 191 if (RT_SUCCESS(rc)) 192 { 193 *pcProcs = cProcesses; 194 *ppaProcs = paProcs; 195 } 196 else 197 RTMemFree(paProcs); 153 198 } 154 199 else 155 {156 rc = VINF_SUCCESS;157 dwNumProcs = cbRet / sizeof(DWORD); /* Set the current, real size of the number of processes we retrieved */158 break;159 }160 } while(dwNumProcs < 32768); /* Should be enough; see: http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx */161 162 if (RT_SUCCESS(rc))163 {164 /* Allocate our process structure */165 *ppProc = (PVBOXSERVICEVMINFOPROC)RTMemAlloc(dwNumProcs * sizeof(VBOXSERVICEVMINFOPROC));166 if (ppProc == NULL)167 200 rc = VERR_NO_MEMORY; 168 169 if (RT_SUCCESS(rc)) 170 { 171 /* We now have the PIDs, fill them into the struct and lookup their LUID's */ 172 PVBOXSERVICEVMINFOPROC pCur = *ppProc; 173 DWORD *pCurProcID = pdwProcIDs; 174 for (DWORD i=0; i<dwNumProcs; i++) 175 { 176 RT_BZERO(pCur, sizeof(VBOXSERVICEVMINFOPROC)); 177 pCur->id = *pCurProcID; 178 rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(pCur, TokenStatistics); 179 if (RT_FAILURE(rc)) 180 { 181 /* Because some processes cannot be opened/parsed on Windows, we should not consider to 182 be this an error here. */ 183 rc = VINF_SUCCESS; 184 } 185 pCur++; 186 pCurProcID++; 187 } 188 /* Save number of processes */ 189 *pdwCount = dwNumProcs; 190 } 191 } 192 193 RTMemFree(pdwProcIDs); 194 if (RT_FAILURE(rc)) 195 VBoxServiceVMInfoWinProcessesFree(*ppProc); 201 } 202 203 RTMemFree(paPids); 196 204 return rc; 197 205 } 198 206 199 void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC pProc) 200 { 201 if (pProc != NULL) 202 { 203 RTMemFree(pProc); 204 pProc = NULL; 205 } 206 } 207 208 DWORD VBoxServiceVMInfoWinSessionGetProcessCount(PLUID pSession, 209 PVBOXSERVICEVMINFOPROC pProc, DWORD dwProcCount) 207 /** 208 * Frees the process structures returned by 209 * VBoxServiceVMInfoWinProcessesEnumerate() before. 210 * 211 * @param paProcs What 212 */ 213 void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs) 214 { 215 RTMemFree(paProcs); 216 } 217 218 /** 219 * Determins whether the specified session has processes on the system. 220 * 221 * @returns true if it has, false if it doesn't. 222 * @param pSession The session. 223 * @param paProcs The process snapshot. 224 * @param cProcs The number of processes in the snaphot. 225 */ 226 bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs) 210 227 { 211 228 AssertPtr(pSession); 212 229 213 if ( dwProcCount <= 0) /* To be on the safe side. */214 return 0;215 AssertPtr(p Proc);230 if (!cProcs) /* To be on the safe side. */ 231 return false; 232 AssertPtr(paProcs); 216 233 217 234 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; 218 if (STATUS_SUCCESS != LsaGetLogonSessionData (pSession, &pSessionData)) 219 { 220 VBoxServiceError("Could not get logon session data! rc=%Rrc", RTErrConvertFromWin32(GetLastError())); 221 return 0; 222 } 223 AssertPtr(pSessionData); 224 225 /* Even if a user seems to be logged in, it could be a stale/orphaned logon session. 226 * So check if we have some processes bound to it by comparing the session <-> process LUIDs. */ 227 PVBOXSERVICEVMINFOPROC pCur = pProc; 228 for (DWORD i=0; i<dwProcCount; i++) 235 NTSTATUS rcNt = LsaGetLogonSessionData(pSession, &pSessionData); 236 if (rcNt != STATUS_SUCCESS) 237 { 238 VBoxServiceError("Could not get logon session data! rcNt=%#x", rcNt); 239 return false; 240 } 241 AssertPtrReturn(pSessionData, false); 242 243 /* 244 * Even if a user seems to be logged in, it could be a stale/orphaned logon 245 * session. So check if we have some processes bound to it by comparing the 246 * session <-> process LUIDs. 247 */ 248 for (DWORD i = 0; i < cProcs; i++) 229 249 { 230 250 /*VBoxServiceVerbose(3, "%ld:%ld <-> %ld:%ld\n", 231 p Cur->luid.HighPart, pCur->luid.LowPart,251 paProcs[i].luid.HighPart, paProcs[i].luid.LowPart, 232 252 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);*/ 233 if ( p Cur->luid.HighPart == pSessionData->LogonId.HighPart234 && p Cur->luid.LowPart == pSessionData->LogonId.LowPart)253 if ( paProcs[i].luid.HighPart == pSessionData->LogonId.HighPart 254 && paProcs[i].luid.LowPart == pSessionData->LogonId.LowPart) 235 255 { 236 256 VBoxServiceVerbose(3, "Users: Session %ld:%ld has active processes\n", 237 257 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart); 238 258 LsaFreeReturnBuffer(pSessionData); 239 return 1; 240 } 241 pCur++; 259 return true; 260 } 242 261 } 243 262 LsaFreeReturnBuffer(pSessionData); 244 return 0; 245 } 246 247 BOOL VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, 248 PLUID a_pSession) 249 { 250 BOOL bFoundUser = FALSE; 251 PSECURITY_LOGON_SESSION_DATA sessionData = NULL; 252 NTSTATUS r = 0; 253 WCHAR *usBuffer = NULL; 254 int iLength = 0; 255 263 return false; 264 } 265 266 267 /** 268 * Save and noisy string copy. 269 * 270 * @param pwszDst Destination buffer. 271 * @param cbDst Size in bytes - not WCHAR count! 272 * @param pSrc Source string. 273 * @param pszWhat What this is. For the log. 274 */ 275 static void VBoxServiceVMInfoWinSafeCopy(PWCHAR pwszDst, size_t cbDst, LSA_UNICODE_STRING const *pSrc, const char *pszWhat) 276 { 277 Assert(RT_ALIGN(cbDst, sizeof(WCHAR)) == cbDst); 278 279 size_t cbCopy = pSrc->Length; 280 if (cbCopy + sizeof(WCHAR) > cbDst) 281 { 282 VBoxServiceVerbose(0, "%s is too long - %u bytes, buffer %u bytes! It will be truncated.\n", 283 pszWhat, cbCopy, cbDst); 284 cbCopy = cbDst - sizeof(WCHAR); 285 } 286 if (cbCopy) 287 memcpy(pwszDst, pSrc->Buffer, cbCopy); 288 pwszDst[cbCopy / sizeof(WCHAR)] = '\0'; 289 } 290 291 292 /** 293 * Detects whether a user is logged on based on the enumerated processes. 294 * 295 * @returns true if logged in, false if not (or error). 296 * @param a_pUserInfo Where to return the user information. 297 * @param a_pSession The session to check. 298 */ 299 bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession) 300 { 256 301 if (!a_pSession) 257 return FALSE; 258 259 r = LsaGetLogonSessionData(a_pSession, &sessionData); 260 if (r != STATUS_SUCCESS) 261 { 262 VBoxServiceError("LsaGetLogonSessionData failed, LSA error %lu\n", LsaNtStatusToWinError(r)); 263 264 if (sessionData) 265 LsaFreeReturnBuffer(sessionData); 266 267 return FALSE; 268 } 269 270 if (!sessionData) 302 return false; 303 304 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; 305 NTSTATUS rcNt = LsaGetLogonSessionData(a_pSession, &pSessionData); 306 if (rcNt != STATUS_SUCCESS) 307 { 308 VBoxServiceError("LsaGetLogonSessionData failed, LSA error %#x\n", LsaNtStatusToWinError(rcNt)); 309 if (pSessionData) 310 LsaFreeReturnBuffer(pSessionData); 311 return false; 312 } 313 if (!pSessionData) 271 314 { 272 315 VBoxServiceError("Invalid logon session data.\n"); 273 return FALSE; 274 } 275 316 return false; 317 } 276 318 VBoxServiceVerbose(3, "Users: Session data: Name = %ls, Len = %d, SID = %s, LogonID = %d,%d\n", 277 (sessionData->UserName).Buffer, 278 (sessionData->UserName).Length, 279 (sessionData->Sid != NULL) ? "1" : "0", sessionData->LogonId.HighPart, sessionData->LogonId.LowPart); 280 281 if ((sessionData->UserName.Buffer != NULL) && 282 (sessionData->Sid != NULL) && 283 (sessionData->LogonId.LowPart != 0)) 284 { 285 /* Get the user name. */ 286 usBuffer = (sessionData->UserName).Buffer; 287 iLength = (sessionData->UserName).Length; 288 if (iLength > sizeof(a_pUserInfo->szUser) - sizeof(WCHAR)) /* -sizeof(WCHAR) because we have to add the terminating null char at the end later. */ 319 pSessionData->UserName.Buffer, 320 pSessionData->UserName.Length, 321 pSessionData->Sid != NULL ? "1" : "0", 322 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart); 323 324 bool fFoundUser = false; 325 if ( pSessionData->UserName.Buffer != NULL 326 && pSessionData->Sid != NULL 327 && pSessionData->LogonId.LowPart != 0) 328 { 329 /* 330 * Copy out the data. 331 */ 332 VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszUser, sizeof(a_pUserInfo->wszUser), 333 &pSessionData->UserName, "User name"); 334 VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszAuthenticationPackage, sizeof(a_pUserInfo->wszAuthenticationPackage), 335 &pSessionData->AuthenticationPackage, "Authentication pkg name"); 336 VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszLogonDomain, sizeof(a_pUserInfo->wszLogonDomain), 337 &pSessionData->LogonDomain, "Logon domain name"); 338 339 340 /* 341 * Only handle users which can login interactively or logged in 342 * remotely over native RDP. 343 */ 344 /** @todo r=bird: Whey don't we check this before copying the data? */ 345 if ( ( (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive 346 || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive) 347 && pSessionData->Sid != NULL) 289 348 { 290 VBoxServiceVerbose(0, "User name too long (%d bytes) for buffer! Name will be truncated.\n", iLength); 291 iLength = sizeof(a_pUserInfo->szUser) - sizeof(WCHAR); 292 } 293 wcsncpy (a_pUserInfo->szUser, usBuffer, iLength); 294 295 /* Get authentication package. */ 296 usBuffer = (sessionData->AuthenticationPackage).Buffer; 297 iLength = (sessionData->AuthenticationPackage).Length; 298 if (iLength > sizeof(a_pUserInfo->szAuthenticationPackage) - sizeof(WCHAR)) /* -sizeof(WCHAR) because we have to add the terminating null char at the end later. */ 299 { 300 VBoxServiceVerbose(0, "Authentication pkg name too long (%d bytes) for buffer! Name will be truncated.\n", iLength); 301 iLength = sizeof(a_pUserInfo->szAuthenticationPackage) - sizeof(WCHAR); 302 } 303 if (iLength) 304 wcsncpy (a_pUserInfo->szAuthenticationPackage, usBuffer, iLength); 305 306 /* Get logon domain. */ 307 usBuffer = (sessionData->LogonDomain).Buffer; 308 iLength = (sessionData->LogonDomain).Length; 309 if (iLength > sizeof(a_pUserInfo->szLogonDomain) - sizeof(WCHAR)) /* -sizeof(WCHAR) because we have to add the terminating null char at the end later. */ 310 { 311 VBoxServiceVerbose(0, "Logon domain name too long (%d bytes) for buffer! Name will be truncated.\n", iLength); 312 iLength = sizeof(a_pUserInfo->szLogonDomain) - sizeof(WCHAR); 313 } 314 if (iLength) 315 wcsncpy (a_pUserInfo->szLogonDomain, usBuffer, iLength); 316 317 /* Only handle users which can login interactively or logged in remotely over native RDP. */ 318 if ( (((SECURITY_LOGON_TYPE)sessionData->LogonType == Interactive) 319 || ((SECURITY_LOGON_TYPE)sessionData->LogonType == RemoteInteractive)) 320 && (sessionData->Sid != NULL)) 321 { 322 TCHAR szOwnerName [_MAX_PATH] = { 0 }; 323 DWORD dwOwnerNameSize = _MAX_PATH; 324 325 TCHAR szDomainName [_MAX_PATH] = { 0 }; 326 DWORD dwDomainNameSize = _MAX_PATH; 327 328 SID_NAME_USE ownerType; 329 349 TCHAR szOwnerName[_MAX_PATH] = { 0 }; 350 DWORD dwOwnerNameSize = sizeof(szOwnerName); 351 TCHAR szDomainName[_MAX_PATH] = { 0 }; 352 DWORD dwDomainNameSize = sizeof(szDomainName); 353 SID_NAME_USE enmOwnerType = SidTypeInvalid; 330 354 if (LookupAccountSid(NULL, 331 sessionData->Sid,355 pSessionData->Sid, 332 356 szOwnerName, 333 357 &dwOwnerNameSize, 334 358 szDomainName, 335 359 &dwDomainNameSize, 336 & ownerType))360 &enmOwnerType)) 337 361 { 338 362 VBoxServiceVerbose(3, "Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n", 339 a_pUserInfo->szUser, sessionData->Session, sessionData->LogonId.HighPart, sessionData->LogonId.LowPart, a_pUserInfo->szAuthenticationPackage, a_pUserInfo->szLogonDomain); 340 363 a_pUserInfo->wszUser, pSessionData->Session, pSessionData->LogonId.HighPart, 364 pSessionData->LogonId.LowPart, a_pUserInfo->wszAuthenticationPackage, 365 a_pUserInfo->wszLogonDomain); 366 367 #if 1 /** @todo If we don't use this, drop it? */ 341 368 /* The session ID increments/decrements on Vista often! So don't compare 342 369 the session data SID with the current SID here. */ … … 344 371 if (g_pfnWTSGetActiveConsoleSessionId != NULL) /* Check terminal session ID. */ 345 372 dwActiveSession = g_pfnWTSGetActiveConsoleSessionId(); 346 347 373 /*VBoxServiceVerbose(3, ("Users: Current active session ID: %ld\n", dwActiveSession));*/ 348 349 if (SidTypeUser == ownerType) 374 #endif 375 376 if (enmOwnerType == SidTypeUser) 350 377 { 351 char* pBuffer = NULL; 352 DWORD dwBytesRet = 0; 353 int iState = 0; 354 355 if (WTSQuerySessionInformation( /* Detect RDP sessions as well. */ 356 WTS_CURRENT_SERVER_HANDLE, 357 WTS_CURRENT_SESSION, 358 WTSConnectState, 359 &pBuffer, 360 &dwBytesRet)) 378 /* Detect RDP sessions as well. */ 379 LPTSTR pBuffer = NULL; 380 DWORD cbRet = 0; 381 int iState = 0; 382 if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 383 WTS_CURRENT_SESSION, 384 WTSConnectState, 385 &pBuffer, 386 &cbRet)) 361 387 { 362 /*VBoxServiceVerbose(3, ("Users: WTSQuerySessionInformation returned %ld bytes, p=%p, state=%d\n", dwBytesRet, pBuffer, pBuffer != NULL ? (INT)*pBuffer : -1));*/363 if( dwBytesRet)388 /*VBoxServiceVerbose(3, ("Users: WTSQuerySessionInformation returned %ld bytes, p=%p, state=%d\n", cbRet, pBuffer, pBuffer != NULL ? (INT)*pBuffer : -1));*/ 389 if(cbRet) 364 390 iState = *pBuffer; 365 391 366 if ( (iState == WTSActive)/* User logged on to WinStation. */367 || (iState == WTSShadow)/* Shadowing another WinStation. */368 || (iState == WTSDisconnected)) /* WinStation logged on without client. */392 if ( iState == WTSActive /* User logged on to WinStation. */ 393 || iState == WTSShadow /* Shadowing another WinStation. */ 394 || iState == WTSDisconnected) /* WinStation logged on without client. */ 369 395 { 370 396 /** @todo On Vista and W2K, always "old" user name are still 371 397 * there. Filter out the old one! */ 372 VBoxServiceVerbose(3, "Users: Account User=%ls is logged in via TCS/RDP. State=%d\n", a_pUserInfo->szUser, iState); 373 bFoundUser = TRUE; 398 VBoxServiceVerbose(3, "Users: Account User=%ls is logged in via TCS/RDP. State=%d\n", 399 a_pUserInfo->wszUser, iState); 400 fFoundUser = true; 374 401 } 402 403 if (pBuffer) 404 WTSFreeMemory(pBuffer); 375 405 } 376 406 else 377 407 { 378 /* Terminal services don't run (for example in W2K, nothing to worry about ...). */ 379 /* ... or is on Vista fast user switching page! */ 380 bFoundUser = TRUE; 408 /* 409 * Terminal services don't run (for example in W2K, 410 * nothing to worry about ...). ... or is on the Vista 411 * fast user switching page! 412 */ 413 fFoundUser = true; 381 414 } 382 383 if (pBuffer)384 WTSFreeMemory(pBuffer);385 415 } 386 416 } … … 388 418 } 389 419 390 LsaFreeReturnBuffer(sessionData); 391 return bFoundUser; 392 } 420 LsaFreeReturnBuffer(pSessionData); 421 return fFoundUser; 422 } 423 393 424 #endif /* TARGET_NT4 */ 394 425 395 int VBoxServiceWinGetComponentVersions(uint32_t u iClientID)426 int VBoxServiceWinGetComponentVersions(uint32_t uClientID) 396 427 { 397 428 int rc; 398 char szVer[_MAX_PATH] = {0};399 char szPropPath[_MAX_PATH] = {0};400 429 char szSysDir[_MAX_PATH] = {0}; 401 430 char szWinDir[_MAX_PATH] = {0}; 402 431 char szDriversDir[_MAX_PATH + 32] = {0}; 403 432 433 /* ASSUME: szSysDir and szWinDir and derivatives are always ASCII compatible. */ 404 434 GetSystemDirectory(szSysDir, _MAX_PATH); 405 435 GetWindowsDirectory(szWinDir, _MAX_PATH); 406 RTStrPrintf(szDriversDir, (_MAX_PATH + 32), "%s\\drivers", szSysDir);436 RTStrPrintf(szDriversDir, sizeof(szDriversDir), "%s\\drivers", szSysDir); 407 437 #ifdef RT_ARCH_AMD64 408 438 char szSysWowDir[_MAX_PATH + 32] = {0}; 409 RTStrPrintf(szSysWowDir, (_MAX_PATH + 32), "%s\\SysWow64", szWinDir);439 RTStrPrintf(szSysWowDir, sizeof(szSysWowDir), "%s\\SysWow64", szWinDir); 410 440 #endif 411 441 412 442 /* The file information table. */ 413 443 #ifndef TARGET_NT4 414 VBOXSERVICEVMINFOFILE vboxFileInfoTable[] =415 { 416 { szSysDir, "VBoxControl.exe" ,},417 { szSysDir, "VBoxHook.dll" ,},418 { szSysDir, "VBoxDisp.dll" ,},419 { szSysDir, "VBoxMRXNP.dll" ,},420 { szSysDir, "VBoxService.exe" ,},421 { szSysDir, "VBoxTray.exe" ,},422 { szSysDir, "VBoxGINA.dll" ,},423 { szSysDir, "VBoxCredProv.dll" ,},444 const VBOXSERVICEVMINFOFILE aVBoxFiles[] = 445 { 446 { szSysDir, "VBoxControl.exe" }, 447 { szSysDir, "VBoxHook.dll" }, 448 { szSysDir, "VBoxDisp.dll" }, 449 { szSysDir, "VBoxMRXNP.dll" }, 450 { szSysDir, "VBoxService.exe" }, 451 { szSysDir, "VBoxTray.exe" }, 452 { szSysDir, "VBoxGINA.dll" }, 453 { szSysDir, "VBoxCredProv.dll" }, 424 454 425 455 /* On 64-bit we don't yet have the OpenGL DLLs in native format. 426 456 So just enumerate the 32-bit files in the SYSWOW directory. */ 427 #ifdef RT_ARCH_AMD64 428 { szSysWowDir, "VBoxOGLarrayspu.dll", }, 429 { szSysWowDir, "VBoxOGLcrutil.dll", }, 430 { szSysWowDir, "VBoxOGLerrorspu.dll", }, 431 { szSysWowDir, "VBoxOGLpackspu.dll", }, 432 { szSysWowDir, "VBoxOGLpassthroughspu.dll", }, 433 { szSysWowDir, "VBoxOGLfeedbackspu.dll", }, 434 { szSysWowDir, "VBoxOGL.dll", }, 435 #else 436 { szSysDir, "VBoxOGLarrayspu.dll", }, 437 { szSysDir, "VBoxOGLcrutil.dll", }, 438 { szSysDir, "VBoxOGLerrorspu.dll", }, 439 { szSysDir, "VBoxOGLpackspu.dll", }, 440 { szSysDir, "VBoxOGLpassthroughspu.dll", }, 441 { szSysDir, "VBoxOGLfeedbackspu.dll", }, 442 { szSysDir, "VBoxOGL.dll", }, 443 #endif 444 445 { szDriversDir, "VBoxGuest.sys", }, 446 { szDriversDir, "VBoxMouse.sys", }, 447 { szDriversDir, "VBoxSF.sys", }, 448 { szDriversDir, "VBoxVideo.sys", }, 449 450 { 451 NULL 452 } 457 # ifdef RT_ARCH_AMD64 458 { szSysWowDir, "VBoxOGLarrayspu.dll" }, 459 { szSysWowDir, "VBoxOGLcrutil.dll" }, 460 { szSysWowDir, "VBoxOGLerrorspu.dll" }, 461 { szSysWowDir, "VBoxOGLpackspu.dll" }, 462 { szSysWowDir, "VBoxOGLpassthroughspu.dll" }, 463 { szSysWowDir, "VBoxOGLfeedbackspu.dll" }, 464 { szSysWowDir, "VBoxOGL.dll" }, 465 # else /* !RT_ARCH_AMD64 */ 466 { szSysDir, "VBoxOGLarrayspu.dll" }, 467 { szSysDir, "VBoxOGLcrutil.dll" }, 468 { szSysDir, "VBoxOGLerrorspu.dll" }, 469 { szSysDir, "VBoxOGLpackspu.dll" }, 470 { szSysDir, "VBoxOGLpassthroughspu.dll" }, 471 { szSysDir, "VBoxOGLfeedbackspu.dll" }, 472 { szSysDir, "VBoxOGL.dll" }, 473 # endif /* !RT_ARCH_AMD64 */ 474 475 { szDriversDir, "VBoxGuest.sys" }, 476 { szDriversDir, "VBoxMouse.sys" }, 477 { szDriversDir, "VBoxSF.sys" }, 478 { szDriversDir, "VBoxVideo.sys" }, 453 479 }; 454 #else /* File lookup for NT4. */ 455 VBOXSERVICEVMINFOFILE vboxFileInfoTable[] = 456 { 457 { szSysDir, "VBoxControl.exe", }, 458 { szSysDir, "VBoxHook.dll", }, 459 { szSysDir, "VBoxDisp.dll", }, 460 { szSysDir, "VBoxService.exe", }, 461 { szSysDir, "VBoxTray.exe", }, 462 463 { szDriversDir, "VBoxGuestNT.sys", }, 464 { szDriversDir, "VBoxMouseNT.sys", }, 465 { szDriversDir, "VBoxVideo.sys", }, 466 467 { 468 NULL 469 } 480 481 #else /* TARGET_NT4 */ 482 const VBOXSERVICEVMINFOFILE aVBoxFiles[] = 483 { 484 { szSysDir, "VBoxControl.exe" }, 485 { szSysDir, "VBoxHook.dll" }, 486 { szSysDir, "VBoxDisp.dll" }, 487 { szSysDir, "VBoxService.exe" }, 488 { szSysDir, "VBoxTray.exe" }, 489 490 { szDriversDir, "VBoxGuestNT.sys" }, 491 { szDriversDir, "VBoxMouseNT.sys" }, 492 { szDriversDir, "VBoxVideo.sys" }, 470 493 }; 471 #endif 472 473 PVBOXSERVICEVMINFOFILE pTable = vboxFileInfoTable; 474 Assert(pTable); 475 while (pTable->pszFileName) 476 { 477 rc = VBoxServiceGetFileVersionString(pTable->pszFilePath, pTable->pszFileName, szVer, sizeof(szVer)); 478 RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestAdd/Components/%s", pTable->pszFileName); 479 rc = VBoxServiceWritePropF(uiClientID, szPropPath, "%s", szVer); 480 pTable++; 494 #endif /* TARGET_NT4 */ 495 496 for (unsigned i = 0; i < RT_ELEMENTS(aVBoxFiles); i++) 497 { 498 char szVer[128]; 499 VBoxServiceGetFileVersionString(aVBoxFiles[i].pszFilePath, aVBoxFiles[i].pszFileName, szVer, sizeof(szVer)); 500 char szPropPath[256]; 501 RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestAdd/Components/%s", aVBoxFiles[i].pszFileName); 502 rc = VBoxServiceWritePropF(uClientID, szPropPath, "%s", szVer); 481 503 } 482 504 483 505 return VINF_SUCCESS; 484 506 } 507 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
r26087 r26136 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox VMInfo - Virtual machine (guest) information for the host.3 * VBoxService - Virtual Machine Information for the Host. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2009 Sun Microsystems, Inc.7 * Copyright (C) 2009-2010 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 64 64 *******************************************************************************/ 65 65 /** The vminfo interval (millseconds). */ 66 uint32_t g_VMInfoInterval = 0;66 uint32_t g_VMInfoInterval = 0; 67 67 /** The semaphore we're blocking on. */ 68 static RTSEMEVENTMULTI g_VMInfoEvent = NIL_RTSEMEVENTMULTI;68 static RTSEMEVENTMULTI g_VMInfoEvent = NIL_RTSEMEVENTMULTI; 69 69 /** The guest property service client ID. */ 70 static uint32_t g_VMInfoGuestPropSvcClientID = 0;70 static uint32_t g_VMInfoGuestPropSvcClientID = 0; 71 71 /** Number of logged in users in OS. */ 72 static uint32_t g_VMInfoLoggedInUsers = UINT32_MAX; 73 #ifdef RT_OS_WINDOWS 74 /** Function prototypes for dynamic loading. */ 75 fnWTSGetActiveConsoleSessionId g_pfnWTSGetActiveConsoleSessionId = NULL; 76 /** External functions. */ 77 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID); 78 #endif 72 static uint32_t g_cVMInfoLoggedInUsers = UINT32_MAX; 79 73 80 74 … … 117 111 /* Get function pointers. */ 118 112 HMODULE hKernel32 = LoadLibrary("kernel32"); 119 if ( NULL != hKernel32)113 if (hKernel32 != NULL) 120 114 { 121 g_pfnWTSGetActiveConsoleSessionId = ( fnWTSGetActiveConsoleSessionId)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");115 g_pfnWTSGetActiveConsoleSessionId = (PFNWTSGETACTIVECONSOLESESSIONID)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId"); 122 116 FreeLibrary(hKernel32); 123 117 } … … 138 132 139 133 140 /** @copydoc VBOXSERVICE::pfnWorker */ 141 DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown) 142 { 143 int rc = VINF_SUCCESS; 144 145 /* 146 * Tell the control thread that it can continue 147 * spawning services. 148 */ 149 RTThreadUserSignal(RTThreadSelf()); 150 151 #ifdef RT_OS_WINDOWS 152 /* Required for network information (must be called per thread). */ 153 WSADATA wsaData; 154 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { 155 VBoxServiceError("WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError())); 156 } 157 #endif /* !RT_OS_WINDOWS */ 158 159 /* First get information that won't change while the OS is running. */ 160 char szInfo[256] = {0}; 161 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szInfo, sizeof(szInfo)); 162 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Product", "%s", szInfo); 134 /** 135 * Writes the properties that won't change while the service is running. 136 * 137 * Errors are ignored. 138 */ 139 static void VBoxServiceVMInfoWriteFixedProperties(void) 140 { 141 /* 142 * First get OS information that won't change. 143 */ 144 char szInfo[256]; 145 int rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szInfo, sizeof(szInfo)); 146 if (RT_SUCCESS(rc)) 147 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Product", "%s", szInfo); 148 else 149 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Product", ""); 163 150 164 151 rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szInfo, sizeof(szInfo)); 165 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Release", "%s", szInfo); 152 if (RT_SUCCESS(rc)) 153 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Release", "%s", szInfo); 154 else 155 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Release", ""); 166 156 167 157 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szInfo, sizeof(szInfo)); 168 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Version", "%s", szInfo); 158 if (RT_SUCCESS(rc)) 159 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Version", "%s", szInfo); 160 else 161 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Version", ""); 169 162 170 163 rc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szInfo, sizeof(szInfo)); 171 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/ServicePack", "%s", szInfo); 172 173 /* Retrieve version information about Guest Additions and installed files (components). */ 174 char *pszAddVer, *pszAddRev; 164 if (RT_SUCCESS(rc)) 165 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/ServicePack", "%s", szInfo); 166 else 167 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/ServicePack", ""); 168 169 /* 170 * Retrieve version information about Guest Additions and installed files (components). 171 */ 172 char *pszAddVer; 173 char *pszAddRev; 175 174 rc = VbglR3GetAdditionsVersion(&pszAddVer, &pszAddRev); 176 175 if (RT_SUCCESS(rc)) 177 176 { 178 177 /* Write information to host. */ 179 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/ Revision","%s", pszAddVer);180 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/ Version", "%s", pszAddRev);178 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Version", "%s", pszAddVer); 179 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Revision", "%s", pszAddRev); 181 180 RTStrFree(pszAddVer); 182 181 RTStrFree(pszAddRev); … … 184 183 185 184 #ifdef RT_OS_WINDOWS 185 /* 186 * Do windows specific properties. 187 */ 186 188 char *pszInstDir; 187 189 rc = VbglR3GetAdditionsInstallationPath(&pszInstDir); … … 191 193 RTStrFree(pszInstDir); 192 194 } 193 rc = VBoxServiceWinGetComponentVersions(g_VMInfoGuestPropSvcClientID); 194 #endif 195 196 /* Now enter the loop retrieving runtime data continuously. */ 195 VBoxServiceWinGetComponentVersions(g_VMInfoGuestPropSvcClientID); 196 #endif 197 } 198 199 200 /** @copydoc VBOXSERVICE::pfnWorker */ 201 DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown) 202 { 203 int rc = VINF_SUCCESS; 204 205 /* 206 * Tell the control thread that it can continue 207 * spawning services. 208 */ 209 RTThreadUserSignal(RTThreadSelf()); 210 211 #ifdef RT_OS_WINDOWS 212 /* Required for network information (must be called per thread). */ 213 WSADATA wsaData; 214 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) 215 VBoxServiceError("WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError())); 216 #endif /* RT_OS_WINDOWS */ 217 218 /* 219 * Write the fixed properties first. 220 */ 221 VBoxServiceVMInfoWriteFixedProperties(); 222 223 /* 224 * Now enter the loop retrieving runtime data continuously. 225 */ 197 226 unsigned cErrors = 0; 198 227 for (;;) 199 228 { 229 /** @todo r=bird: split this code up into functions!! */ 200 230 /* Enumerate logged in users. */ 201 uint32_t uiUserCount = 0;231 uint32_t cUsersInList = 0; 202 232 char szUserList[4096] = {0}; 203 233 204 234 #ifdef RT_OS_WINDOWS 205 235 # ifndef TARGET_NT4 206 PLUID pSessions = NULL; 207 ULONG ulCount = 0; 208 NTSTATUS r = 0; 209 210 char* pszTemp = NULL; 211 212 /* This function can report stale or orphaned interactive logon sessions of already logged 213 off users (especially in Windows 2000). */ 214 r = ::LsaEnumerateLogonSessions(&ulCount, &pSessions); 215 VBoxServiceVerbose(3, "Users: Found %ld users.\n", ulCount); 216 236 PLUID paSessions = NULL; 237 ULONG cSession = 0; 238 NTSTATUS r = 0; 239 240 /* This function can report stale or orphaned interactive logon sessions 241 of already logged off users (especially in Windows 2000). */ 242 r = ::LsaEnumerateLogonSessions(&cSession, &paSessions); 243 VBoxServiceVerbose(3, "Users: Found %ld users.\n", cSession); 217 244 if (r != STATUS_SUCCESS) 218 245 { … … 221 248 } 222 249 223 PVBOXSERVICEVMINFOPROC pProcs; 224 DWORD dwNumProcs; 225 rc = VBoxServiceVMInfoWinProcessesEnumerate(&pProcs, &dwNumProcs); 226 227 for (ULONG i=0; i<ulCount; i++) 228 { 229 VBOXSERVICEVMINFOUSER userInfo; 230 /* Leave the memory clearing *inside* the loop as VBoxServiceVMInfoWinIsLoggedIn 231 * assumes the memory reserved for strings is zeroed. 232 */ 233 ZeroMemory (&userInfo, sizeof(VBOXSERVICEVMINFOUSER)); 234 235 if ( VBoxServiceVMInfoWinIsLoggedIn(&userInfo, &pSessions[i]) 236 && VBoxServiceVMInfoWinSessionGetProcessCount(&pSessions[i], pProcs, dwNumProcs) > 0) 250 PVBOXSERVICEVMINFOPROC paProcs; 251 DWORD cProcs; 252 rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); 253 if (RT_SUCCESS(rc)) 254 { 255 for (ULONG i = 0; i < cSession; i++) 237 256 { 238 if (uiUserCount > 0) 239 strcat (szUserList, ","); 240 241 uiUserCount++; 242 243 RTUtf16ToUtf8(userInfo.szUser, &pszTemp); 244 strcat(szUserList, pszTemp); 245 RTMemFree(pszTemp); 257 VBOXSERVICEVMINFOUSER UserInfo; 258 if ( VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i]) 259 && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs) > 0) 260 { 261 if (cUsersInList > 0) 262 strcat(szUserList, ","); 263 264 cUsersInList++; 265 266 char *pszTemp; 267 int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp); 268 if (RT_SUCCESS(rc2)) 269 { 270 strcat(szUserList, pszTemp); 271 RTMemFree(pszTemp); 272 } 273 else 274 strcat(szUserList, "<string-convertion-error>"); 275 } 246 276 } 247 }248 249 VBoxServiceVMInfoWinProcessesFree(pProcs); 250 ::LsaFreeReturnBuffer(p Sessions);277 VBoxServiceVMInfoWinProcessesFree(paProcs); 278 } 279 280 ::LsaFreeReturnBuffer(paSessions); 251 281 # endif /* TARGET_NT4 */ 252 282 #elif defined(RT_OS_FREEBSD) … … 277 307 /** @todo r=bird: strstr will filtering out users with similar names. For 278 308 * example: smith, smithson, joesmith and bobsmith */ 279 if ( uiUserCount > 0)309 if (cUsersInList > 0) 280 310 strcat(szUserList, ","); 281 311 strcat(szUserList, ut_user->ut_user); 282 uiUserCount++;312 cUsersInList++; 283 313 } 284 314 } … … 286 316 #endif /* !RT_OS_WINDOWS */ 287 317 288 if ( uiUserCount > 0)318 if (cUsersInList > 0) 289 319 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList); 290 320 else 291 321 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL); 292 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", uiUserCount); 293 if (g_VMInfoLoggedInUsers != uiUserCount || g_VMInfoLoggedInUsers == UINT32_MAX) 322 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList); 323 if ( g_cVMInfoLoggedInUsers != cUsersInList 324 || g_cVMInfoLoggedInUsers == UINT32_MAX) 294 325 { 295 326 /* Update this property ONLY if there is a real change from no users to … … 297 328 * forces an update, but only once. This ensures consistent property 298 329 * settings even if the VM aborted previously. */ 299 if ( uiUserCount == 0)330 if (cUsersInList == 0) 300 331 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true"); 301 else if (g_ VMInfoLoggedInUsers == 0)332 else if (g_cVMInfoLoggedInUsers == 0) 302 333 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false"); 303 334 } 304 g_VMInfoLoggedInUsers = uiUserCount; 305 306 /* Get network configuration. */ 335 g_cVMInfoLoggedInUsers = cUsersInList; 336 337 /* 338 * Get network configuration. 339 */ 307 340 /** @todo Throw this code into a separate function/module? */ 308 341 int nNumInterfaces = 0; … … 421 454 iCurIface++; 422 455 } 423 #ifdef RT_OS_WINDOWS 424 if (sd) closesocket(sd); 425 #else 426 if (sd) close(sd); 427 #endif /* !RT_OS_WINDOWS */ 456 if (sd >= 0) 457 #ifdef RT_OS_WINDOWS 458 closesocket(sd); 459 #else 460 close(sd); 461 #endif 428 462 429 463 /* … … 479 513 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL); 480 514 rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%d", 0); 481 if (g_ VMInfoLoggedInUsers > 0)515 if (g_cVMInfoLoggedInUsers > 0) 482 516 VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true"); 483 517
Note:
See TracChangeset
for help on using the changeset viewer.