- Timestamp:
- May 28, 2010 12:54:03 PM (15 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r29817 r29858 102 102 /** The following constant may be defined by including NtStatus.h. */ 103 103 # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 104 105 /** @todo Move these Windows stuff into VBoxServiceVMInfo-win.cpp and hide all106 * the windows details using behind function calls!107 * @{ */108 /** Structure for storing the looked up user information. */109 typedef struct110 {111 WCHAR wszUser[_MAX_PATH];112 WCHAR wszAuthenticationPackage[_MAX_PATH];113 WCHAR wszLogonDomain[_MAX_PATH];114 } VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER;115 /** Structure for the file information lookup. */116 typedef struct117 {118 char *pszFilePath;119 char *pszFileName;120 } VBOXSERVICEVMINFOFILE, *PVBOXSERVICEVMINFOFILE;121 /** Structure for process information lookup. */122 typedef struct123 {124 DWORD id;125 LUID luid;126 } VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC;127 /** Function prototypes for dynamic loading. */128 typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void);129 /** @} */130 104 131 105 #endif /* RT_OS_WINDOWS */ … … 290 264 291 265 #ifdef RT_OS_WINDOWS 292 extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */293 266 # ifdef VBOX_WITH_GUEST_PROPS 294 extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs); 295 extern bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession); 296 extern int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount); 297 extern void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs); 298 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID); 267 extern int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList); 268 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID); 299 269 # endif /* VBOX_WITH_GUEST_PROPS */ 300 270 #endif /* RT_OS_WINDOWS */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
r28800 r29858 37 37 38 38 39 /** Structure for storing the looked up user information. */ 40 typedef struct 41 { 42 WCHAR wszUser[_MAX_PATH]; 43 WCHAR wszAuthenticationPackage[_MAX_PATH]; 44 WCHAR wszLogonDomain[_MAX_PATH]; 45 } VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER; 46 /** Structure for the file information lookup. */ 47 typedef struct 48 { 49 char *pszFilePath; 50 char *pszFileName; 51 } VBOXSERVICEVMINFOFILE, *PVBOXSERVICEVMINFOFILE; 52 /** Structure for process information lookup. */ 53 typedef struct 54 { 55 DWORD id; 56 LUID luid; 57 } VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC; 58 59 60 /******************************************************************************* 61 * Prototypes 62 *******************************************************************************/ 63 bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs); 64 bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession); 65 int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount); 66 void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs); 67 68 39 69 /******************************************************************************* 40 70 * Global Variables * 41 71 *******************************************************************************/ 42 /** Function prototypes for dynamic loading. */43 PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId = NULL;44 72 45 73 … … 288 316 289 317 /** 290 * Detects whether a user is logged on based on the enumerated processes.318 * Detects whether a user is logged on. 291 319 * 292 320 * @returns true if logged in, false if not (or error). … … 296 324 bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession) 297 325 { 326 AssertPtr(a_pUserInfo); 298 327 if (!a_pSession) 299 328 return false; … … 303 332 if (rcNt != STATUS_SUCCESS) 304 333 { 305 VBoxServiceError(" LsaGetLogonSessionData failed, LSA error %#x\n", LsaNtStatusToWinError(rcNt));334 VBoxServiceError("VMInfo/Users: LsaGetLogonSessionData failed, LSA error %#x\n", LsaNtStatusToWinError(rcNt)); 306 335 if (pSessionData) 307 336 LsaFreeReturnBuffer(pSessionData); … … 310 339 if (!pSessionData) 311 340 { 312 VBoxServiceError(" Invalid logon session data.\n");341 VBoxServiceError("VMInfo/Users: Invalid logon session data!\n"); 313 342 return false; 314 343 } 315 VBoxServiceVerbose(3, "Users: Session data: Name = %ls, Len = %d, SID = %s, LogonID = %d,%d\n", 316 pSessionData->UserName.Buffer, 317 pSessionData->UserName.Length, 318 pSessionData->Sid != NULL ? "1" : "0", 319 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart); 320 344 345 /* 346 * Only handle users which can login interactively or logged in 347 * remotely over native RDP. 348 */ 321 349 bool fFoundUser = false; 322 if ( pSessionData->UserName.Buffer != NULL 323 && pSessionData->Sid != NULL 324 && pSessionData->LogonId.LowPart != 0) 325 { 350 DWORD dwErr = NO_ERROR; 351 if ( IsValidSid(pSessionData->Sid) 352 && ( (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive 353 || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive 354 || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedInteractive 355 || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedRemoteInteractive)) 356 { 357 VBoxServiceVerbose(3, "VMInfo/Users: Session data: Name=%ls, Len=%d, SID=%s, LogonID=%ld,%ld\n", 358 pSessionData->UserName.Buffer, 359 pSessionData->UserName.Length, 360 pSessionData->Sid != NULL ? "1" : "0", 361 pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart); 362 326 363 /* 327 * Copy out thedata.364 * Copy out relevant data. 328 365 */ 329 366 VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszUser, sizeof(a_pUserInfo->wszUser), … … 334 371 &pSessionData->LogonDomain, "Logon domain name"); 335 372 336 337 /* 338 * Only handle users which can login interactively or logged in 339 * remotely over native RDP. 340 */ 341 /** @todo r=bird: Whey don't we check this before copying the data? */ 342 if ( ( (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive 343 || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive) 344 && pSessionData->Sid != NULL) 345 { 346 TCHAR szOwnerName[_MAX_PATH] = { 0 }; 347 DWORD dwOwnerNameSize = sizeof(szOwnerName); 348 TCHAR szDomainName[_MAX_PATH] = { 0 }; 349 DWORD dwDomainNameSize = sizeof(szDomainName); 350 SID_NAME_USE enmOwnerType = SidTypeInvalid; 351 if (LookupAccountSid(NULL, 352 pSessionData->Sid, 353 szOwnerName, 354 &dwOwnerNameSize, 355 szDomainName, 356 &dwDomainNameSize, 357 &enmOwnerType)) 373 TCHAR szOwnerName[_MAX_PATH] = { 0 }; 374 DWORD dwOwnerNameSize = sizeof(szOwnerName); 375 TCHAR szDomainName[_MAX_PATH] = { 0 }; 376 DWORD dwDomainNameSize = sizeof(szDomainName); 377 SID_NAME_USE enmOwnerType = SidTypeInvalid; 378 if (!LookupAccountSid(NULL, 379 pSessionData->Sid, 380 szOwnerName, 381 &dwOwnerNameSize, 382 szDomainName, 383 &dwDomainNameSize, 384 &enmOwnerType)) 385 { 386 VBoxServiceError("VMInfo/Users: Failed looking up account info for user '%ls': %ld!\n", 387 a_pUserInfo->wszUser, GetLastError()); 388 } 389 else 390 { 391 if (enmOwnerType == SidTypeUser) /* Only recognize users; we don't care about the rest! */ 358 392 { 359 VBoxServiceVerbose(3, " Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",393 VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n", 360 394 a_pUserInfo->wszUser, pSessionData->Session, pSessionData->LogonId.HighPart, 361 395 pSessionData->LogonId.LowPart, a_pUserInfo->wszAuthenticationPackage, 362 396 a_pUserInfo->wszLogonDomain); 363 397 364 #if 1 /** @todo If we don't use this, drop it? */ 365 /* The session ID increments/decrements on Vista often! So don't compare 366 the session data SID with the current SID here. */ 367 DWORD dwActiveSession = 0; 368 if (g_pfnWTSGetActiveConsoleSessionId != NULL) /* Check terminal session ID. */ 369 dwActiveSession = g_pfnWTSGetActiveConsoleSessionId(); 370 /*VBoxServiceVerbose(3, ("Users: Current active session ID: %ld\n", dwActiveSession));*/ 371 #endif 372 373 if (enmOwnerType == SidTypeUser) 398 /* Detect RDP sessions as well. */ 399 LPTSTR pBuffer = NULL; 400 DWORD cbRet = 0; 401 int iState = 0; 402 if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 403 pSessionData->Session, 404 WTSConnectState, 405 &pBuffer, 406 &cbRet)) 374 407 { 375 /* Detect RDP sessions as well. */ 376 LPTSTR pBuffer = NULL; 377 DWORD cbRet = 0; 378 int iState = 0; 379 if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 380 WTS_CURRENT_SESSION, 381 WTSConnectState, 382 &pBuffer, 383 &cbRet)) 408 if(cbRet) 409 iState = *pBuffer; 410 VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, WTSConnectState=%d\n", 411 a_pUserInfo->wszUser, iState); 412 if ( iState == WTSActive /* User logged on to WinStation. */ 413 || iState == WTSShadow /* Shadowing another WinStation. */ 414 || iState == WTSDisconnected) /* WinStation logged on without client. */ 384 415 { 385 /*VBoxServiceVerbose(3, ("Users: WTSQuerySessionInformation returned %ld bytes, p=%p, state=%d\n", cbRet, pBuffer, pBuffer != NULL ? (INT)*pBuffer : -1));*/ 386 if(cbRet) 387 iState = *pBuffer; 388 389 if ( iState == WTSActive /* User logged on to WinStation. */ 390 || iState == WTSShadow /* Shadowing another WinStation. */ 391 || iState == WTSDisconnected) /* WinStation logged on without client. */ 392 { 393 /** @todo On Vista and W2K, always "old" user name are still 394 * there. Filter out the old one! */ 395 VBoxServiceVerbose(3, "Users: Account User=%ls is logged in via TCS/RDP. State=%d\n", 396 a_pUserInfo->wszUser, iState); 397 fFoundUser = true; 398 } 399 400 if (pBuffer) 401 WTSFreeMemory(pBuffer); 402 } 403 else 404 { 405 /* 406 * Terminal services don't run (for example in W2K, 407 * nothing to worry about ...). ... or is on the Vista 408 * fast user switching page! 409 */ 416 /** @todo On Vista and W2K, always "old" user name are still 417 * there. Filter out the old one! */ 418 VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls is logged in via TCS/RDP. State=%d\n", 419 a_pUserInfo->wszUser, iState); 410 420 fFoundUser = true; 411 421 } 422 if (pBuffer) 423 WTSFreeMemory(pBuffer); 424 } 425 else 426 { 427 VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, WTSConnectState returnd %ld\n", 428 a_pUserInfo->wszUser, GetLastError()); 429 430 /* 431 * Terminal services don't run (for example in W2K, 432 * nothing to worry about ...). ... or is on the Vista 433 * fast user switching page! 434 */ 435 fFoundUser = true; 412 436 } 413 437 } 414 438 } 415 } 439 } 416 440 417 441 LsaFreeReturnBuffer(pSessionData); 418 442 return fFoundUser; 443 } 444 445 446 /** 447 * Retrieves the currently logged in users and stores their names along with the 448 * user count. 449 * 450 * @returns VBox status code. 451 * @param ppszUserList Where to store the user list (separated by commas). Must be 452 * freed with RTStrFree(). 453 * @param pcUsersInList Where to store the number of users in the list. 454 */ 455 int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList) 456 { 457 PLUID paSessions = NULL; 458 ULONG cSession = 0; 459 NTSTATUS r = 0; 460 461 /* This function can report stale or orphaned interactive logon sessions 462 of already logged off users (especially in Windows 2000). */ 463 r = LsaEnumerateLogonSessions(&cSession, &paSessions); 464 VBoxServiceVerbose(3, "VMInfo/Users: Found %ld users\n", cSession); 465 if (r != STATUS_SUCCESS) 466 { 467 VBoxServiceError("VMInfo/Users: LsaEnumerate failed with %lu\n", LsaNtStatusToWinError(r)); 468 return RTErrConvertFromWin32(LsaNtStatusToWinError(r)); 469 } 470 471 PVBOXSERVICEVMINFOPROC paProcs; 472 DWORD cProcs; 473 int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); 474 if (RT_SUCCESS(rc)) 475 { 476 *pcUsersInList = 0; 477 for (ULONG i = 0; i < cSession; i++) 478 { 479 VBOXSERVICEVMINFOUSER UserInfo; 480 if ( VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i]) 481 && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs)) 482 { 483 if (*pcUsersInList > 0) 484 { 485 rc = RTStrAAppend(ppszUserList, ","); 486 AssertRCReturn(rc, rc); 487 } 488 489 *pcUsersInList += 1; 490 491 char *pszTemp; 492 int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp); 493 if (RT_SUCCESS(rc2)) 494 { 495 rc = RTStrAAppend(ppszUserList, pszTemp); 496 RTMemFree(pszTemp); 497 AssertRCReturn(rc, rc); 498 } 499 else 500 RTStrAAppend(ppszUserList, "<string-convertion-error>"); 501 } 502 } 503 VBoxServiceVMInfoWinProcessesFree(paProcs); 504 } 505 LsaFreeReturnBuffer(paSessions); 419 506 } 420 507 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
r29852 r29858 113 113 AssertRCReturn(rc, rc); 114 114 115 #ifdef RT_OS_WINDOWS116 /** @todo r=bird: call a windows specific init function and move117 * g_pfnWTSGetActiveConsoleSessionId out of the global scope. */118 /* Get function pointers. */119 HMODULE hKernel32 = LoadLibrary("kernel32");120 if (hKernel32 != NULL)121 {122 g_pfnWTSGetActiveConsoleSessionId = (PFNWTSGETACTIVECONSOLESESSIONID)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");123 FreeLibrary(hKernel32);124 }125 #endif126 127 115 rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID); 128 116 if (RT_SUCCESS(rc)) … … 228 216 { 229 217 int rc; 230 char szUserList[4096] = {0};218 char *pszUserList = NULL; 231 219 uint32_t cUsersInList = 0; 232 220 233 221 #ifdef RT_OS_WINDOWS 234 222 # ifndef TARGET_NT4 235 PLUID paSessions = NULL; 236 ULONG cSession = 0; 237 NTSTATUS r = 0; 238 239 /* This function can report stale or orphaned interactive logon sessions 240 of already logged off users (especially in Windows 2000). */ 241 r = ::LsaEnumerateLogonSessions(&cSession, &paSessions); 242 VBoxServiceVerbose(3, "Users: Found %ld users.\n", cSession); 243 if (r != STATUS_SUCCESS) 244 { 245 VBoxServiceError("VMInfo/Users: LsaEnumerate failed %lu\n", LsaNtStatusToWinError(r)); 246 return RTErrConvertFromWin32(LsaNtStatusToWinError(r)); 247 } 248 249 PVBOXSERVICEVMINFOPROC paProcs; 250 DWORD cProcs; 251 rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); 252 if (RT_SUCCESS(rc)) 253 { 254 for (ULONG i = 0; i < cSession; i++) 255 { 256 VBOXSERVICEVMINFOUSER UserInfo; 257 if ( VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i]) 258 && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs)) 259 { 260 if (cUsersInList > 0) 261 strcat(szUserList, ","); 262 263 cUsersInList++; 264 265 char *pszTemp; 266 int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp); 267 if (RT_SUCCESS(rc2)) 268 { 269 strcat(szUserList, pszTemp); 270 RTMemFree(pszTemp); 271 } 272 else 273 strcat(szUserList, "<string-convertion-error>"); 274 } 275 } 276 VBoxServiceVMInfoWinProcessesFree(paProcs); 277 } 278 279 ::LsaFreeReturnBuffer(paSessions); 223 rc = VBoxServiceVMInfoWinWriteUsers(&pszUserList, &cUsersInList); 280 224 # endif /* TARGET_NT4 */ 281 225 #elif defined(RT_OS_FREEBSD) … … 298 242 { 299 243 /* Make sure we don't add user names which are not 300 * part of type USER_PROCESS and don't add same users twice. */ 301 if ( ut_user->ut_type == USER_PROCESS 302 && strstr(szUserList, ut_user->ut_user) == NULL) 303 { 304 /** @todo Do we really want to filter out double user names? (Same user logged in twice) 305 * bird: If we do, then we must add checks for buffer overflows here! */ 306 /** @todo r=bird: strstr will filtering out users with similar names. For 307 * example: smith, smithson, joesmith and bobsmith */ 244 * part of type USER_PROCESS. */ 245 246 /** @todo Do we want to filter out user names? What if a user is logged in twice? */ 247 if (ut_user->ut_type == USER_PROCESS) 248 { 308 249 if (cUsersInList > 0) 309 strcat(szUserList, ","); 310 strcat(szUserList, ut_user->ut_user); 250 { 251 rc = RTStrAAppend(pszUserList, ","); 252 AssertRCReturn(rc, rc); 253 } 254 rc = RTStrAAppend(pszUserList, ut_user->ut_user); 255 AssertRCReturn(rc, rc); 311 256 cUsersInList++; 312 257 } … … 315 260 #endif /* !RT_OS_WINDOWS */ 316 261 317 if ( cUsersInList > 0)318 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList);262 if (pszUserList && cUsersInList > 0) 263 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", pszUserList); 319 264 else 320 265 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL); 321 266 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList); 322 if ( g_cVMInfoLoggedInUsers != cUsersInList 323 || g_cVMInfoLoggedInUsers == UINT32_MAX) 324 { 325 /* 326 * Update this property ONLY if there is a real change from no users to 327 * users or vice versa. The only exception is that the initialization 328 * forces an update, but only once. This ensures consistent property 329 * settings even if the VM aborted previously. 330 */ 331 if (cUsersInList == 0) 332 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true"); 333 else if (g_cVMInfoLoggedInUsers == 0) 334 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false"); 335 } 336 g_cVMInfoLoggedInUsers = cUsersInList; 337 267 if (g_cVMInfoLoggedInUsers != cUsersInList) 268 { 269 VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", cUsersInList == 0 ? "true" : "false"); 270 g_cVMInfoLoggedInUsers = cUsersInList; 271 } 272 if (pszUserList) 273 RTStrFree(pszUserList); 338 274 return VINF_SUCCESS; 339 275 } … … 655 591 WSADATA wsaData; 656 592 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) 657 VBoxServiceError("VMInfo : WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));593 VBoxServiceError("VMInfo/Users: WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError())); 658 594 #endif /* RT_OS_WINDOWS */ 659 595
Note:
See TracChangeset
for help on using the changeset viewer.