Changeset 26083 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Jan 28, 2010 1:53:51 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 57036
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r26061 r26083 27 27 # include <Windows.h> 28 28 # include <process.h> /* Needed for file version information. */ 29 # include <Ntsecapi.h> /* Needed for process security information. */ 29 30 #endif 30 31 … … 115 116 char *pszFileName; 116 117 } VBOXSERVICEVMINFOFILE, *PVBOXSERVICEVMINFOFILE; 118 /** Structure for process information lookup. */ 119 typedef struct 120 { 121 DWORD id; 122 LUID luid; 123 } VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC; 117 124 /** Function prototypes for dynamic loading. */ 118 125 typedef DWORD (WINAPI* fnWTSGetActiveConsoleSessionId)(); … … 152 159 extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint); 153 160 # 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); 154 164 /** Detects wheter a user is logged on based on the enumerated processes. */ 155 extern BOOL VBoxServiceVMInfoWinIsLoggedIn( VBOXSERVICEVMINFOUSER *a_pUserInfo,156 PLUID a_pSession ,157 PLUID a_pLuid, 158 DWORD a_dwNumOfProcLUIDs);159 /** Gets logon user IDs from enumerated processes. */160 extern DWORD VBoxServiceVMInfoWinGetLUIDsFromProcesses(PLUID *ppLuid);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); 161 171 # endif /* VBOX_WITH_GUEST_PROPS */ 162 172 #endif /* RT_OS_WINDOWS */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
r26073 r26083 25 25 *******************************************************************************/ 26 26 #include <windows.h> 27 #include <Ntsecapi.h>28 27 #include <wtsapi32.h> /* For WTS* calls. */ 29 28 #include <psapi.h> /* EnumProcesses. */ … … 53 52 54 53 #ifndef TARGET_NT4 55 /* Function GetLUIDsFromProcesses() written by Stefan Kuhr. */ 56 DWORD VBoxServiceVMInfoWinGetLUIDsFromProcesses(PLUID *ppLuid) 57 { 58 DWORD dwSize, dwSize2, dwIndex ; 59 LPDWORD lpdwPIDs ; 60 DWORD dwLastError = ERROR_SUCCESS; 61 62 if (!ppLuid) 63 { 64 SetLastError(ERROR_INVALID_PARAMETER); 65 return 0L; 66 } 67 68 /* Call the PSAPI function EnumProcesses to get all of the 69 ProcID's currently in the system. 70 NOTE: In the documentation, the third parameter of 71 EnumProcesses is named cbNeeded, which implies that you 72 can call the function once to find out how much space to 73 allocate for a buffer and again to fill the buffer. 74 This is not the case. The cbNeeded parameter returns 75 the number of PIDs returned, so if your buffer size is 76 zero cbNeeded returns zero. 77 NOTE: The "HeapAlloc" loop here ensures that we 78 actually allocate a buffer large enough for all the 79 PIDs in the system. */ 80 dwSize2 = 256 * sizeof(DWORD); 81 82 lpdwPIDs = NULL; 54 int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pProc, 55 TOKEN_INFORMATION_CLASS tkClass) 56 { 57 AssertPtr(pProc); 58 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pProc->id); 59 if (h == NULL) 60 return RTErrConvertFromWin32(GetLastError()); 61 62 HANDLE hToken; 63 int rc; 64 if (FALSE == OpenProcessToken(h, TOKEN_QUERY, &hToken)) 65 { 66 rc = RTErrConvertFromWin32(GetLastError()); 67 } 68 else 69 { 70 void *pvTokenInfo = NULL; 71 DWORD dwTokenInfoSize; 72 switch (tkClass) 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 break; 85 } 86 87 if (pvTokenInfo) 88 { 89 DWORD dwRetLength; 90 if (FALSE == GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength)) 91 { 92 rc = RTErrConvertFromWin32(GetLastError()); 93 } 94 else 95 { 96 switch (tkClass) 97 { 98 case TokenStatistics: 99 { 100 TOKEN_STATISTICS *pStats = (TOKEN_STATISTICS*)pvTokenInfo; 101 AssertPtr(pStats); 102 pProc->luid = pStats->AuthenticationId; 103 /* @todo Add more information of TOKEN_STATISTICS as needed. */ 104 break; 105 } 106 107 default: 108 /* Should never get here! */ 109 break; 110 } 111 rc = VINF_SUCCESS; 112 } 113 RTMemFree(pvTokenInfo); 114 } 115 CloseHandle(hToken); 116 } 117 CloseHandle(h); 118 return rc; 119 } 120 121 int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount) 122 { 123 AssertPtr(ppProc); 124 AssertPtr(pdwCount); 125 126 DWORD dwSize = 256; /* Number of processes our array can hold */ 127 DWORD *pdwProcIDs = (DWORD*)RTMemAlloc(dwSize * sizeof(DWORD)); 128 if (pdwProcIDs == NULL) 129 return VERR_NO_MEMORY; 130 131 int rc; 132 DWORD dwNeeded; 83 133 do 84 134 { 85 if (lpdwPIDs) 86 { 87 HeapFree(GetProcessHeap(), 0, lpdwPIDs) ; 88 dwSize2 *= 2; 89 } 90 lpdwPIDs = (unsigned long *)HeapAlloc(GetProcessHeap(), 0, dwSize2); 91 if (lpdwPIDs == NULL) 92 return 0L; // Last error will be that of HeapAlloc 93 94 if (!EnumProcesses( lpdwPIDs, dwSize2, &dwSize)) 95 { 96 DWORD dw = GetLastError(); 97 HeapFree(GetProcessHeap(), 0, lpdwPIDs); 98 SetLastError(dw); 99 return 0L; 100 } 101 } 102 while (dwSize == dwSize2); 103 104 /* At this point we have an array of the PIDs at the 105 time of the last EnumProcesses invocation. We will 106 allocate an array of LUIDs passed back via the out 107 param ppLuid of exactly the number of PIDs. We will 108 only fill the first n values of this array, with n 109 being the number of unique LUIDs found in these PIDs. */ 110 111 /* How many ProcIDs did we get? */ 112 dwSize /= sizeof(DWORD); 113 dwSize2 = 0L; /* Our return value of found luids. */ 114 115 *ppLuid = (LUID *)LocalAlloc(LPTR, dwSize*sizeof(LUID)); 116 if (!(*ppLuid)) 117 { 118 dwLastError = GetLastError(); 119 goto CLEANUP; 120 } 121 for (dwIndex = 0; dwIndex < dwSize; dwIndex++) 122 { 123 (*ppLuid)[dwIndex].LowPart =0L; 124 (*ppLuid)[dwIndex].HighPart=0; 125 126 /* Open the process (if we can... security does not 127 permit every process in the system). */ 128 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE, lpdwPIDs[dwIndex]); 129 if ( hProcess != NULL ) 130 { 131 HANDLE hAccessToken; 132 if (OpenProcessToken(hProcess, TOKEN_QUERY, &hAccessToken)) 135 if (FALSE == EnumProcesses(pdwProcIDs, dwSize * sizeof(DWORD), &dwNeeded)) 136 { 137 rc = RTErrConvertFromWin32(GetLastError()); 138 break; 139 } 140 141 /* Was our array big enough? Or do we need more space? */ 142 if (dwNeeded >= dwSize) 143 { 144 /* Apparently not, so try next bigger size */ 145 dwSize += 256; 146 pdwProcIDs = (DWORD*)RTMemRealloc(pdwProcIDs, dwSize * sizeof(DWORD)); 147 if (pdwProcIDs == NULL) 133 148 { 134 TOKEN_STATISTICS ts; 135 DWORD dwSize; 136 if (GetTokenInformation(hAccessToken, TokenStatistics, &ts, sizeof ts, &dwSize)) 149 rc = VERR_NO_MEMORY; 150 break; 151 } 152 } 153 else 154 { 155 rc = VINF_SUCCESS; 156 break; 157 } 158 } while(dwNeeded >= dwSize); 159 160 if (RT_SUCCESS(rc)) 161 { 162 /* Allocate our process structure */ 163 *ppProc = (PVBOXSERVICEVMINFOPROC)RTMemAlloc(dwNeeded * sizeof(VBOXSERVICEVMINFOPROC)); 164 if (ppProc == NULL) 165 rc = VERR_NO_MEMORY; 166 167 if (RT_SUCCESS(rc)) 168 { 169 /* We now have the PIDs, fill them into the struct and lookup their LUID's */ 170 PVBOXSERVICEVMINFOPROC pCur = *ppProc; 171 DWORD *pCurProcID = pdwProcIDs; 172 for (DWORD i=0; i<dwNeeded; i++) 173 { 174 RT_BZERO(pCur, sizeof(VBOXSERVICEVMINFOPROC)); 175 pCur->id = *pCurProcID; 176 rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(pCur, TokenStatistics); 177 if (RT_FAILURE(rc)) 137 178 { 138 DWORD dwTmp = 0L; 139 BOOL bFound = FALSE; 140 for (;dwTmp<dwSize2 && !bFound;dwTmp++) 141 bFound = (*ppLuid)[dwTmp].HighPart == ts.AuthenticationId.HighPart && 142 (*ppLuid)[dwTmp].LowPart == ts.AuthenticationId.LowPart; 143 144 if (!bFound) 145 (*ppLuid)[dwSize2++] = ts.AuthenticationId; 179 /* Because some processes cannot be opened/parsed on Windows, we should not consider to 180 be this an error here. */ 181 rc = VINF_SUCCESS; 146 182 } 147 CloseHandle(hAccessToken); 183 pCur++; 184 pCurProcID++; 148 185 } 149 150 CloseHandle(hProcess); 151 } 152 153 /* We don't really care if OpenProcess or OpenProcessToken fail or succeed, because 154 there are quite a number of system processes we cannot open anyway, not even as SYSTEM. */ 155 } 156 157 CLEANUP: 158 159 if (lpdwPIDs) 160 HeapFree(GetProcessHeap(), 0, lpdwPIDs); 161 162 if (ERROR_SUCCESS !=dwLastError) 163 SetLastError(dwLastError); 164 165 return dwSize2; 166 } 167 168 BOOL VBoxServiceVMInfoWinIsLoggedIn(VBOXSERVICEVMINFOUSER* a_pUserInfo, 169 PLUID a_pSession, 170 PLUID a_pLuid, 171 DWORD a_dwNumOfProcLUIDs) 172 { 173 BOOL bLoggedIn = FALSE; 186 /* Save number of processes */ 187 *pdwCount = dwNeeded; 188 } 189 } 190 191 RTMemFree(pdwProcIDs); 192 if (RT_FAILURE(rc)) 193 VBoxServiceVMInfoWinProcessesFree(*ppProc); 194 return rc; 195 } 196 197 void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC pProc) 198 { 199 if (pProc != NULL) 200 { 201 RTMemFree(pProc); 202 pProc = NULL; 203 } 204 } 205 206 DWORD VBoxServiceVMInfoWinSessionGetProcessCount(PLUID pSession, 207 PVBOXSERVICEVMINFOPROC pProc, DWORD dwProcCount) 208 { 209 AssertPtr(pSession); 210 211 if (dwProcCount <= 0) /* To be on the safe side. */ 212 return 0; 213 AssertPtr(pProc); 214 215 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; 216 if (STATUS_SUCCESS != LsaGetLogonSessionData (pSession, &pSessionData)) 217 { 218 VBoxServiceError("Could not get logon session data! rc=%Rrc", RTErrConvertFromWin32(GetLastError())); 219 return 0; 220 } 221 AssertPtr(pSessionData); 222 223 /* Even if a user seems to be logged in, it could be a stale/orphaned logon session. 224 * So check if we have some processes bound to it by comparing the session <-> process LUIDs. */ 225 PVBOXSERVICEVMINFOPROC pCur = pProc; 226 for (DWORD i=0; i<dwProcCount; i++) 227 { 228 /*VBoxServiceVerbose(3, "%ld:%ld <-> %ld:%ld\n", 229 pCur->luid.HighPart, pCur->luid.LowPart, 230 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);*/ 231 if ( pCur->luid.HighPart == pSessionData->LogonId.HighPart 232 && pCur->luid.LowPart == pSessionData->LogonId.LowPart) 233 { 234 VBoxServiceVerbose(3, "Users: Session %ld:%ld has active processes\n", 235 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart); 236 LsaFreeReturnBuffer(pSessionData); 237 return 1; 238 } 239 pCur++; 240 } 241 LsaFreeReturnBuffer(pSessionData); 242 return 0; 243 } 244 245 BOOL VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, 246 PLUID a_pSession) 247 { 174 248 BOOL bFoundUser = FALSE; 175 249 PSECURITY_LOGON_SESSION_DATA sessionData = NULL; … … 181 255 return FALSE; 182 256 183 r = LsaGetLogonSessionData 257 r = LsaGetLogonSessionData(a_pSession, &sessionData); 184 258 if (r != STATUS_SUCCESS) 185 259 { … … 199 273 200 274 VBoxServiceVerbose(3, "Users: Session data: Name = %ls, Len = %d, SID = %s, LogonID = %d,%d\n", 201 (sessionData->UserName).Buffer, (sessionData->UserName).Length, (sessionData->Sid != NULL) ? "1" : "0", sessionData->LogonId.HighPart, sessionData->LogonId.LowPart); 275 (sessionData->UserName).Buffer, 276 (sessionData->UserName).Length, 277 (sessionData->Sid != NULL) ? "1" : "0", sessionData->LogonId.HighPart, sessionData->LogonId.LowPart); 202 278 203 279 if ((sessionData->UserName.Buffer != NULL) && … … 305 381 if (pBuffer) 306 382 WTSFreeMemory(pBuffer); 307 308 /* A user logged in, but it could be a stale/orphaned logon session. */309 BOOL bFoundInLUIDs = FALSE;310 for (DWORD dwIndex = 0; dwIndex < a_dwNumOfProcLUIDs; dwIndex++)311 {312 if ( (a_pLuid[dwIndex].HighPart == sessionData->LogonId.HighPart)313 && (a_pLuid[dwIndex].LowPart == sessionData->LogonId.LowPart))314 {315 bLoggedIn = TRUE;316 VBoxServiceVerbose(3, "User \"%ls\" is logged in!\n", a_pUserInfo->szUser);317 break;318 }319 }320 383 } 321 384 } … … 324 387 325 388 LsaFreeReturnBuffer(sessionData); 326 return bLoggedIn; 327 } 328 389 return bFoundUser; 390 } 329 391 #endif /* TARGET_NT4 */ 330 392 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
r26070 r26083 221 221 } 222 222 223 PLUID pLuid = NULL; 224 DWORD dwNumOfProcLUIDs = VBoxServiceVMInfoWinGetLUIDsFromProcesses(&pLuid); 225 226 for (int i = 0; i<(int)ulCount; i++) 227 { 228 VBOXSERVICEVMINFOUSER userInfo; 229 ZeroMemory (&userInfo, sizeof(VBOXSERVICEVMINFOUSER)); 230 231 if (VBoxServiceVMInfoWinIsLoggedIn(&userInfo, &pSessions[i], pLuid, dwNumOfProcLUIDs)) 223 PVBOXSERVICEVMINFOPROC pProcs; 224 DWORD dwNumProcs; 225 rc = VBoxServiceVMInfoWinProcessesEnumerate(&pProcs, &dwNumProcs); 226 227 VBOXSERVICEVMINFOUSER userInfo; 228 ZeroMemory (&userInfo, sizeof(VBOXSERVICEVMINFOUSER)); 229 230 for (ULONG i=0; i<ulCount; i++) 231 { 232 if ( VBoxServiceVMInfoWinIsLoggedIn(&userInfo, &pSessions[i]) 233 && VBoxServiceVMInfoWinSessionGetProcessCount(&pSessions[i], pProcs, dwNumProcs) > 0) 232 234 { 233 235 if (uiUserCount > 0) … … 242 244 } 243 245 244 if (NULL != pLuid) 245 ::LocalFree (pLuid); 246 246 VBoxServiceVMInfoWinProcessesFree(pProcs); 247 247 ::LsaFreeReturnBuffer(pSessions); 248 248 # endif /* TARGET_NT4 */
Note:
See TracChangeset
for help on using the changeset viewer.