VirtualBox

Changeset 40158 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Feb 16, 2012 5:06:35 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
76311
Message:

VBoxService/users-win: Added session change detection, more fun with logged-in user detection.

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp

    r36338 r40158  
    136136    ss.dwCurrentState             = dwStatus;
    137137    ss.dwControlsAccepted         = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
     138#ifndef TARGET_NT4
     139    ss.dwControlsAccepted        |= SERVICE_ACCEPT_SESSIONCHANGE;
     140#endif
    138141    ss.dwWin32ExitCode            = NO_ERROR;
    139142    ss.dwServiceSpecificExitCode  = 0; /* Not used */
     
    379382
    380383
     384#ifndef TARGET_NT4
     385static const char* vboxServiceWTSStateToString(DWORD dwEvent)
     386{
     387    switch (dwEvent)
     388    {
     389        case WTS_CONSOLE_CONNECT:
     390            return "A session was connected to the console terminal";
     391
     392        case WTS_CONSOLE_DISCONNECT:
     393            return "A session was disconnected from the console terminal";
     394
     395        case WTS_REMOTE_CONNECT:
     396            return "A session connected to the remote terminal";
     397
     398        case WTS_REMOTE_DISCONNECT:
     399            return "A session was disconnected from the remote terminal";
     400
     401        case WTS_SESSION_LOGON:
     402            return "A user has logged on to a session";
     403
     404        case WTS_SESSION_LOGOFF:
     405            return "A user has logged off the session";
     406
     407        case WTS_SESSION_LOCK:
     408            return "A session has been locked";
     409
     410        case WTS_SESSION_UNLOCK:
     411            return "A session has been unlocked";
     412
     413        case WTS_SESSION_REMOTE_CONTROL:
     414            return "A session has changed its remote controlled status";
     415#if 0
     416        case WTS_SESSION_CREATE:
     417            return "A session has been created";
     418
     419        case WTS_SESSION_TERMINATE:
     420            return "The session has been terminated";
     421#endif
     422        default:
     423            break;
     424    }
     425
     426    return "Uknonwn state";
     427}
     428#endif /* !TARGET_NT4 */
     429
     430
    381431#ifdef TARGET_NT4
    382432static VOID WINAPI vboxServiceWinCtrlHandler(DWORD dwControl)
     
    417467        }
    418468
    419         case SERVICE_CONTROL_SESSIONCHANGE:     /* Only Win XP and up. */
    420 #ifndef TARGET_NT4
    421 # if 0
    422             switch (dwEventType)
    423             {
    424                 case WTS_SESSION_LOGON:
    425                     VBoxServiceVerbose(2, "A user has logged on to the session.\n");
    426                     break;
    427 
    428                 case WTS_SESSION_LOGOFF:
    429                     VBoxServiceVerbose(2, "A user has logged off from the session.\n");
    430                     break;
    431                 default:
    432                     break;
    433             }
    434 # endif
    435 #endif /* !TARGET_NT4 */
     469# ifndef TARGET_NT4
     470        case SERVICE_CONTROL_SESSIONCHANGE: /* Only Windows 2000 and up. */
     471        {
     472            AssertPtr(lpEventData);
     473            PWTSSESSION_NOTIFICATION pNotify = (PWTSSESSION_NOTIFICATION)lpEventData;
     474            Assert(pNotify->cbSize == sizeof(WTSSESSION_NOTIFICATION));
     475
     476            VBoxServiceVerbose(1, "Control handler: %s (Session=%ld, Event=%#x)\n",
     477                               vboxServiceWTSStateToString(dwEventType),
     478                               pNotify->dwSessionId, dwEventType);
     479
     480            /* Handle all events, regardless of dwEventType. */
     481            int rc2 = VBoxServiceVMInfoSignal();
     482            AssertRC(rc2);
    436483            break;
     484        }
     485# endif /* !TARGET_NT4 */
    437486
    438487        default:
    439             VBoxServiceVerbose(1, "Service control function not implemented: %#x\n", dwControl);
     488            VBoxServiceVerbose(1, "Control handler: Function not implemented: %#x\n", dwControl);
    440489            rcRet = ERROR_CALL_NOT_IMPLEMENTED;
    441490            break;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r39906 r40158  
    411411
    412412#ifdef VBOXSERVICE_MANAGEMENT
    413 extern uint32_t     VBoxServiceBalloonQueryPages(uint32_t cbPage);
     413extern uint32_t                 VBoxServiceBalloonQueryPages(uint32_t cbPage);
    414414#endif
    415415#if defined(VBOX_WITH_PAGE_SHARING) && defined(RT_OS_WINDOWS)
    416 extern RTEXITCODE   VBoxServicePageSharingInitFork(void);
    417 #endif
     416extern RTEXITCODE               VBoxServicePageSharingInitFork(void);
     417#endif
     418extern int                      VBoxServiceVMInfoSignal(void);
    418419
    419420RT_C_DECLS_END
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp

    r39760 r40158  
    5353    /** Number of assigned user processes. */
    5454    ULONG ulNumProcs;
     55    /** Last (highest) session number. This
     56     *  is needed for distinguishing old session
     57     *  process counts from new (current) session
     58     *  ones. */
     59    ULONG ulSession;
    5560} VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER;
    5661
     
    6570typedef struct
    6671{
     72    /** The PID. */
    6773    DWORD id;
     74    /** The LUID. */
    6875    LUID luid;
     76    /** Interactive process. */
     77    bool fInteractive;
    6978} VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC;
    7079
     
    120129        DWORD dwErr = GetLastError();
    121130        if (g_cVerbosity)
    122             VBoxServiceError("VMInfo/Users: Unable to open process with PID=%ld, error=%ld",
     131            VBoxServiceError("Unable to open process with PID=%ld, error=%ld\n",
    123132                             pProc->id, dwErr);
    124133        rc = RTErrConvertFromWin32(dwErr);
     
    142151                if (RT_SUCCESS(rc))
    143152                {
    144                     DWORD dwLen = sizeof(pszName);
     153                    DWORD dwLen = cbName / sizeof(TCHAR);
    145154                    if (!pfnQueryFullProcessImageName(h, 0 /*PROCESS_NAME_NATIVE*/, pszName, &dwLen))
    146155                        rc = VERR_ACCESS_DENIED;
     
    154163            if (!GetModuleFileNameEx(h, NULL /* Get main executable */, pszName, cbName / sizeof(TCHAR)))
    155164                rc = VERR_ACCESS_DENIED;
    156         }
    157 
    158         if (VERR_ACCESS_DENIED == rc)
    159         {
    160             DWORD dwErr = GetLastError();
    161             if (g_cVerbosity)
    162                 VBoxServiceError("VMInfo/Users: Unable to retrieve module name for PID=%ld, error=%ld",
    163                                  pProc->id, dwErr);
    164             rc = RTErrConvertFromWin32(dwErr);
    165165        }
    166166
     
    183183{
    184184    AssertPtrReturn(pProc, VERR_INVALID_POINTER);
     185
     186    DWORD  dwErr = ERROR_SUCCESS;
    185187    HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pProc->id);
    186188    if (h == NULL)
    187189    {
    188         DWORD dwErr = GetLastError();
    189         if (g_cVerbosity)
    190             VBoxServiceError("VMInfo/Users: Unable to open process with PID=%ld, error=%ld",
     190        dwErr = GetLastError();
     191        if (g_cVerbosity > 4)
     192            VBoxServiceError("Unable to open process with PID=%ld, error=%ld\n",
    191193                             pProc->id, dwErr);
    192194        return RTErrConvertFromWin32(dwErr);
    193195    }
    194196
    195      int    rc = VERR_NO_MEMORY;
    196      HANDLE hToken;
    197      if (OpenProcessToken(h, TOKEN_QUERY, &hToken))
    198      {
    199          void *pvTokenInfo = NULL;
    200          DWORD dwTokenInfoSize;
    201          switch (tkClass)
    202          {
    203              case TokenStatistics:
    204                  dwTokenInfoSize = sizeof(TOKEN_STATISTICS);
    205                  pvTokenInfo = RTMemAlloc(dwTokenInfoSize);
    206                  break;
    207 
    208              /** @todo Implement more token classes here. */
    209 
    210              default:
    211                  VBoxServiceError("Token class not implemented: %ld", tkClass);
    212                  rc = VERR_NOT_IMPLEMENTED;
    213                  break;
    214          }
    215 
    216          if (pvTokenInfo)
    217          {
    218              DWORD dwRetLength;
    219              if (GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength))
    220              {
    221                  switch (tkClass)
    222                  {
    223                      case TokenStatistics:
    224                      {
    225                          TOKEN_STATISTICS *pStats = (TOKEN_STATISTICS*)pvTokenInfo;
    226                          pProc->luid = pStats->AuthenticationId;
    227                          /** @todo Add more information of TOKEN_STATISTICS as needed. */
    228                          break;
    229                      }
    230 
    231                      default:
    232                          /* Should never get here! */
    233                          break;
    234                  }
    235                  rc = VINF_SUCCESS;
    236              }
    237              else
    238                  rc = RTErrConvertFromWin32(GetLastError());
    239              RTMemFree(pvTokenInfo);
    240          }
    241          CloseHandle(hToken);
     197    int    rc = VINF_SUCCESS;
     198    HANDLE hToken;
     199    if (OpenProcessToken(h, TOKEN_QUERY, &hToken))
     200    {
     201        void *pvTokenInfo = NULL;
     202        DWORD dwTokenInfoSize;
     203        switch (tkClass)
     204        {
     205            case TokenStatistics:
     206                dwTokenInfoSize = sizeof(TOKEN_STATISTICS);
     207                pvTokenInfo = HeapAlloc(GetProcessHeap(),
     208                                        HEAP_ZERO_MEMORY, dwTokenInfoSize);
     209                AssertPtr(pvTokenInfo);
     210                break;
     211
     212            case TokenGroups:
     213                dwTokenInfoSize = 0;
     214                /* Allocating will follow in a second step. */
     215                break;
     216
     217            /** @todo Implement more token classes here. */
     218
     219            default:
     220                VBoxServiceError("Token class not implemented: %ld", tkClass);
     221                rc = VERR_NOT_IMPLEMENTED;
     222                break;
     223        }
     224
     225        if (RT_SUCCESS(rc))
     226        {
     227            DWORD dwRetLength;
     228            if (!GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength))
     229            {
     230                dwErr = GetLastError();
     231                if (dwErr == ERROR_INSUFFICIENT_BUFFER)
     232                {
     233                    dwErr = ERROR_SUCCESS;
     234
     235                    switch (tkClass)
     236                    {
     237                        case TokenGroups:
     238                            pvTokenInfo = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
     239                                                                   HEAP_ZERO_MEMORY, dwRetLength);
     240                            if (!pvTokenInfo)
     241                                dwErr = GetLastError();
     242                            dwTokenInfoSize = dwRetLength;
     243                            break;
     244
     245                        default:
     246                            AssertMsgFailed(("Re-allocating of token information for token class not implemented\n"));
     247                            break;
     248                    }
     249
     250                    if (dwErr == ERROR_SUCCESS)
     251                    {
     252                        if (!GetTokenInformation(hToken, tkClass, pvTokenInfo, dwTokenInfoSize, &dwRetLength))
     253                            dwErr = GetLastError();
     254                    }
     255                }
     256            }
     257
     258            if (dwErr == ERROR_SUCCESS)
     259            {
     260                rc = VINF_SUCCESS;
     261
     262                switch (tkClass)
     263                {
     264                    case TokenStatistics:
     265                    {
     266                        PTOKEN_STATISTICS pStats = (PTOKEN_STATISTICS)pvTokenInfo;
     267                        memcpy(&pProc->luid, &pStats->AuthenticationId, sizeof(LUID));
     268                        /** @todo Add more information of TOKEN_STATISTICS as needed. */
     269                        break;
     270                    }
     271
     272                    case TokenGroups:
     273                    {
     274                        pProc->fInteractive = false;
     275
     276                        SID_IDENTIFIER_AUTHORITY sidAuthNT = SECURITY_NT_AUTHORITY;
     277                        PSID pSidInteractive = NULL; /*  S-1-5-4 */
     278                        if (!AllocateAndInitializeSid(&sidAuthNT, 1, 4, 0, 0, 0, 0, 0, 0, 0, &pSidInteractive))
     279                            dwErr = GetLastError();
     280
     281                        PSID pSidLocal = NULL; /*  S-1-2-0 */
     282                        if (dwErr == ERROR_SUCCESS)
     283                        {
     284                            SID_IDENTIFIER_AUTHORITY sidAuthLocal = SECURITY_LOCAL_SID_AUTHORITY;
     285                            if (!AllocateAndInitializeSid(&sidAuthLocal, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSidLocal))
     286                                dwErr = GetLastError();
     287                        }
     288
     289                        if (dwErr == ERROR_SUCCESS)
     290                        {
     291                            PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)pvTokenInfo;
     292                            AssertPtr(pGroups);
     293                            for (DWORD i = 0; i < pGroups->GroupCount; i++)
     294                            {
     295                                if (   EqualSid(pGroups->Groups[i].Sid, pSidInteractive)
     296                                    || EqualSid(pGroups->Groups[i].Sid, pSidLocal)
     297                                    || pGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID)
     298                                {
     299                                    pProc->fInteractive = true;
     300                                    break;
     301                                }
     302                            }
     303                        }
     304
     305                        if (pSidInteractive)
     306                            FreeSid(pSidInteractive);
     307                        if (pSidLocal)
     308                            FreeSid(pSidLocal);
     309                        break;
     310                    }
     311
     312                    default:
     313                        AssertMsgFailed(("Unhandled token information class\n"));
     314                        break;
     315                }
     316            }
     317
     318            if (pvTokenInfo)
     319                HeapFree(GetProcessHeap(), 0 /* Flags */, pvTokenInfo);
     320        }
     321        CloseHandle(hToken);
    242322    }
    243323    else
    244     {
    245         DWORD dwErr = GetLastError();
     324        dwErr = GetLastError();
     325
     326    if (dwErr != ERROR_SUCCESS)
     327    {
    246328        if (g_cVerbosity)
    247             VBoxServiceError("VMInfo/Users: Unable to query process token for PID=%ld, error=%ld\n",
     329            VBoxServiceError("Unable to query token information for PID=%ld, error=%ld\n",
    248330                             pProc->id, dwErr);
    249331        rc = RTErrConvertFromWin32(dwErr);
    250332    }
     333
    251334    CloseHandle(h);
    252335    return rc;
     
    314397            {
    315398                paProcs[i].id = paPID[i];
    316                 rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(&paProcs[i], TokenStatistics);
     399                rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(&paProcs[i], TokenGroups);
    317400                if (RT_FAILURE(rc))
    318401                {
    319402                    /* Because some processes cannot be opened/parsed on
    320                        Windows, we should not consider to be this an error here. */
     403                           Windows, we should not consider to be this an error here. */
    321404                    rc = VINF_SUCCESS;
     405                }
     406                else
     407                {
     408                    rc = VBoxServiceVMInfoWinProcessesGetTokenInfo(&paProcs[i], TokenStatistics);
     409                    if (RT_FAILURE(rc))
     410                    {
     411                        /* Because some processes cannot be opened/parsed on
     412                           Windows, we should not consider to be this an error here. */
     413                        rc = VINF_SUCCESS;
     414                    }
    322415                }
    323416            }
     
    358451 * @param   paProcs         The process snapshot.
    359452 * @param   cProcs          The number of processes in the snaphot.
     453 * @param   puSession       Looked up session number.  Optional.
    360454 */
    361 uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs)
     455uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession,
     456                                                 PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs,
     457                                                 PULONG puSession)
    362458{
    363459    if (!pSession)
    364460    {
    365         VBoxServiceVerbose(1, "VMInfo/Users: Session became invalid while enumerating!\n");
     461        VBoxServiceVerbose(1, "Session became invalid while enumerating!\n");
    366462        return 0;
    367463    }
     
    371467    if (rcNt != STATUS_SUCCESS)
    372468    {
    373         VBoxServiceError("VMInfo/Users: Could not get logon session data! rcNt=%#x", rcNt);
     469        VBoxServiceError("Could not get logon session data! rcNt=%#x", rcNt);
    374470        return 0;
    375471    }
     
    383479    for (DWORD i = 0; i < cProcs; i++)
    384480    {
    385         /*VBoxServiceVerbose(3, "%ld:%ld <-> %ld:%ld\n",
    386                              paProcs[i].luid.HighPart, paProcs[i].luid.LowPart,
    387                              pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);*/
    388         if (   paProcs[i].luid.HighPart == pSessionData->LogonId.HighPart
    389             && paProcs[i].luid.LowPart  == pSessionData->LogonId.LowPart)
     481        VBoxServiceVerbose(4, "PID=%ld: (Interactive: %RTbool) %ld:%ld <-> %ld:%ld\n",
     482                           paProcs[i].id,                  paProcs[i].fInteractive,
     483                           paProcs[i].luid.HighPart,       paProcs[i].luid.LowPart,
     484                           pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);
     485        if (g_cVerbosity)
     486        {
     487            TCHAR szModule[_1K];
     488            int rc2 = VBoxServiceVMInfoWinProcessesGetModuleName(&paProcs[i], szModule, sizeof(szModule));
     489            if (RT_SUCCESS(rc2))
     490                VBoxServiceVerbose(4, "PID=%ld: %s\n",
     491                                   paProcs[i].id, szModule);
     492        }
     493
     494        if (   paProcs[i].fInteractive
     495            && (   paProcs[i].luid.HighPart == pSessionData->LogonId.HighPart
     496                && paProcs[i].luid.LowPart  == pSessionData->LogonId.LowPart))
    390497        {
    391498            cNumProcs++;
    392499            if (!g_cVerbosity) /* We want a bit more info on higher verbosity. */
    393500                break;
    394 
    395             TCHAR szModule[_1K];
    396             int rc2 = VBoxServiceVMInfoWinProcessesGetModuleName(&paProcs[i], szModule, sizeof(szModule));
    397             if (RT_SUCCESS(rc2))
    398                 VBoxServiceVerbose(4, "VMInfo/Users: PID=%ld: %s\n",
    399                                    paProcs[i].id, szModule);
    400501        }
    401502    }
    402503
    403504    if (g_cVerbosity)
    404         VBoxServiceVerbose(3, "VMInfo/Users: Session %u has %u processes\n",
     505        VBoxServiceVerbose(3, "Session %u has %u processes total\n",
    405506                           pSessionData->Session, cNumProcs);
    406507    else
    407         VBoxServiceVerbose(3, "VMInfo/Users: Session %u has at least one process\n",
     508        VBoxServiceVerbose(3, "Session %u has at least one process\n",
    408509                           pSessionData->Session);
     510
     511    if (puSession)
     512        *puSession = pSessionData->Session;
    409513
    410514    LsaFreeReturnBuffer(pSessionData);
     
    447551bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER pUserInfo, PLUID pSession)
    448552{
    449     AssertPtr(pUserInfo);
     553    AssertPtrReturn(pUserInfo, false);
    450554    if (!pSession)
    451555        return false;
     
    461565                /* If we don't have enough memory it's hard to judge whether the specified user
    462566                 * is logged in or not, so just assume he/she's not. */
    463                 VBoxServiceVerbose(3, "VMInfo/Users: Not enough memory to retrieve logon session data!\n");
     567                VBoxServiceVerbose(3, "Not enough memory to retrieve logon session data!\n");
    464568                break;
    465569
     
    470574
    471575            default:
    472                 VBoxServiceError("VMInfo/Users: LsaGetLogonSessionData failed with error %ul\n", ulError);
     576                VBoxServiceError("LsaGetLogonSessionData failed with error %u\n", ulError);
    473577                break;
    474578        }
     
    479583    if (!pSessionData)
    480584    {
    481         VBoxServiceError("VMInfo/Users: Invalid logon session data!\n");
     585        VBoxServiceError("Invalid logon session data!\n");
    482586        return false;
    483587    }
     
    491595    if (   IsValidSid(pSessionData->Sid)
    492596        && (   (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive
    493             || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive
    494             || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedInteractive
    495             || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedRemoteInteractive))
    496     {
    497         VBoxServiceVerbose(3, "VMInfo/Users: Session data: Name=%ls, Len=%d, SID=%s, LogonID=%ld,%ld, LogonType=%ld\n",
     597            || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive))
     598    {
     599        VBoxServiceVerbose(3, "Session data: Name=%ls, Session=%u, LogonID=%ld,%ld, LogonType=%ld\n",
    498600                           pSessionData->UserName.Buffer,
    499                            pSessionData->UserName.Length,
    500                            pSessionData->Sid != NULL ? "1" : "0",
     601                           pSessionData->Session,
    501602                           pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart,
    502603                           pSessionData->LogonType);
     
    533634             */
    534635            if (dwErr != ERROR_NONE_MAPPED)
    535                 VBoxServiceError("VMInfo/Users: Failed looking up account info for user=%ls, error=$ld!\n",
     636                VBoxServiceError("Failed looking up account info for user=%ls, error=$ld!\n",
    536637                                 pUserInfo->wszUser, dwErr);
    537638        }
     
    540641            if (enmOwnerType == SidTypeUser) /* Only recognize users; we don't care about the rest! */
    541642            {
    542                 VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",
     643                VBoxServiceVerbose(3, "Account User=%ls, Session=%ld, LogonID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",
    543644                                   pUserInfo->wszUser, pSessionData->Session, pSessionData->LogonId.HighPart,
    544645                                   pSessionData->LogonId.LowPart, pUserInfo->wszAuthenticationPackage,
     
    548649                LPTSTR  pBuffer = NULL;
    549650                DWORD   cbRet   = 0;
    550                 int     iState  = 0;
     651                int     iState  = -1;
    551652                if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
    552653                                               pSessionData->Session,
     
    557658                    if (cbRet)
    558659                        iState = *pBuffer;
    559                     VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, WTSConnectState=%d\n",
    560                                        pUserInfo->wszUser, iState);
     660                    VBoxServiceVerbose(3, "Account User=%ls, WTSConnectState=%d (%ld)\n",
     661                                       pUserInfo->wszUser, iState, cbRet);
    561662                    if (    iState == WTSActive           /* User logged on to WinStation. */
    562663                         || iState == WTSShadow           /* Shadowing another WinStation. */
     
    565666                        /** @todo On Vista and W2K, always "old" user name are still
    566667                         *        there. Filter out the old one! */
    567                         VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls using TCS/RDP, state=%d\n",
     668                        VBoxServiceVerbose(3, "Account User=%ls using TCS/RDP, state=%d \n",
    568669                                           pUserInfo->wszUser, iState);
    569670                        fFoundUser = true;
     
    583684                         */
    584685                        case ERROR_CTX_WINSTATION_NOT_FOUND:
    585                             VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, no WinSta found\n",
     686                            VBoxServiceVerbose(3, "No WinStation found for user=%ls\n",
    586687                                               pUserInfo->wszUser);
    587688                            break;
    588689
    589690                        default:
    590                             VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, error=%ld\n",
     691                            VBoxServiceVerbose(3, "Cannot query WTS connection state for user=%ls, error=%ld\n",
    591692                                               pUserInfo->wszUser, dwLastErr);
    592693                            break;
     
    598699        }
    599700
    600         VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls %s logged in\n",
     701        VBoxServiceVerbose(3, "Account User=%ls %s logged in\n",
    601702                           pUserInfo->wszUser, fFoundUser ? "is" : "is not");
    602703    }
     
    630731        {
    631732            case ERROR_NOT_ENOUGH_MEMORY:
    632                 VBoxServiceError("VMInfo/Users: Not enough memory to enumerate logon sessions!\n");
     733                VBoxServiceError("Not enough memory to enumerate logon sessions!\n");
    633734                break;
    634735
     
    636737                /* If we're about to shutdown when we were in the middle of enumerating the logon
    637738                 * sessions, skip the error to not confuse the user with an unnecessary log message. */
    638                 VBoxServiceVerbose(3, "VMInfo/Users: Shutdown in progress ...\n");
     739                VBoxServiceVerbose(3, "Shutdown in progress ...\n");
    639740                ulError = ERROR_SUCCESS;
    640741                break;
    641742
    642743            default:
    643                 VBoxServiceError("VMInfo/Users: LsaEnumerate failed with error %ul\n", ulError);
     744                VBoxServiceError("LsaEnumerate failed with error %u\n", ulError);
    644745                break;
    645746        }
     
    647748        return RTErrConvertFromWin32(ulError);
    648749    }
    649     VBoxServiceVerbose(3, "VMInfo/Users: Found %ld sessions\n", cSessions);
     750    VBoxServiceVerbose(3, "Found %ld sessions\n", cSessions);
    650751
    651752    PVBOXSERVICEVMINFOPROC  paProcs;
     
    655756    {
    656757        if (rc == VERR_NO_MEMORY)
    657             VBoxServiceError("VMInfo/Users: Not enough memory to enumerate processes for a session!\n");
     758            VBoxServiceError("Not enough memory to enumerate processes\n");
    658759        else
    659             VBoxServiceError("VMInfo/Users: Failed to enumerate processes for a session, rc=%Rrc\n", rc);
     760            VBoxServiceError("Failed to enumerate processes, rc=%Rrc\n", rc);
    660761    }
    661762    else
     
    664765        pUserInfo = (PVBOXSERVICEVMINFOUSER)RTMemAllocZ(cSessions * sizeof(VBOXSERVICEVMINFOUSER) + 1);
    665766        if (!pUserInfo)
    666             VBoxServiceError("VMInfo/Users: Not enough memory to store enumerated users!\n");
     767            VBoxServiceError("Not enough memory to store enumerated users!\n");
    667768        else
    668769        {
     
    673774                if (VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i]))
    674775                {
    675                     VBoxServiceVerbose(4, "VMInfo/Users: Handling user=%ls, domain=%ls, package=%ls\n",
    676                                        pUserInfo[i].wszUser, pUserInfo[i].wszLogonDomain, pUserInfo[i].wszAuthenticationPackage);
     776                    VBoxServiceVerbose(4, "Handling user=%ls, domain=%ls, package=%ls\n",
     777                                       UserInfo.wszUser, UserInfo.wszLogonDomain, UserInfo.wszAuthenticationPackage);
    677778
    678779                    /* Retrieve assigned processes of current session. */
    679                     uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs);
     780                    ULONG ulSession;
     781                    uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs, &ulSession);
    680782                    /* Don't return here when current session does not have assigned processes
    681783                     * anymore -- in that case we have to search through the unique users list below
     
    687789                        if (   !wcscmp(UserInfo.wszUser, pUserInfo[i].wszUser)
    688790                            && !wcscmp(UserInfo.wszLogonDomain, pUserInfo[i].wszLogonDomain)
    689                             && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage))
     791                            && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage)
     792                            && cSessionProcs)
    690793                        {
    691                             /* If the process-per-user count was higher than 0 before but another session was
    692                              * was detected which also belongs to this user but has no assigned processes anymore,
    693                              * we detected a stale session. */
    694                             if (   pUserInfo[i].ulNumProcs > 0
    695                                 && !cSessionProcs)
     794                            /*
     795                             * Only respect the highest session for the current user.
     796                             */
     797                            if (ulSession > pUserInfo[i].ulSession)
    696798                            {
    697                                 VBoxServiceVerbose(3, "VMInfo/Users: Stale session for user=%ls detected! Old processes: %u, new: %u\n",
    698                                                    pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs);
     799                                VBoxServiceVerbose(4, "Updating user=%ls to %u processes (last session: %u)\n",
     800                                                   UserInfo.wszUser, cSessionProcs, ulSession);
     801
     802                                pUserInfo[i].ulNumProcs = cSessionProcs;
     803                                pUserInfo[i].ulSession  = ulSession;
     804
     805                                if (!cSessionProcs)
     806                                    VBoxServiceVerbose(3, "Stale session for user=%ls detected! Old processes: %u, new: %u\n",
     807                                                       pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs);
    699808                            }
    700 
    701                             VBoxServiceVerbose(4, "VMInfo/Users: Updating user=%ls to %u processes\n",
    702                                                UserInfo.wszUser, cSessionProcs);
    703 
    704                             pUserInfo[i].ulNumProcs = cSessionProcs;
     809                            /* There can be multiple session objects using the same session ID for the
     810                             * current user -- so when we got the same session again just add the found
     811                             * processes to it. */
     812                            else if (pUserInfo[i].ulSession == ulSession)
     813                            {
     814                                VBoxServiceVerbose(4, "Adding %u processes to user=%ls (session %u)\n",
     815                                                   cSessionProcs, UserInfo.wszUser, ulSession);
     816
     817                                pUserInfo[i].ulNumProcs += cSessionProcs;
     818                                pUserInfo[i].ulSession   = ulSession;
     819                            }
     820
    705821                            fFoundUser = true;
    706822                            break;
     
    710826                    if (!fFoundUser)
    711827                    {
    712                         VBoxServiceVerbose(4, "VMInfo/Users: Adding new user=%ls with %u processes\n",
    713                                            UserInfo.wszUser, cSessionProcs);
     828                        VBoxServiceVerbose(4, "Adding new user=%ls (session %u) with %u processes\n",
     829                                           UserInfo.wszUser, ulSession, cSessionProcs);
    714830
    715831                        memcpy(&pUserInfo[cUniqueUsers], &UserInfo, sizeof(VBOXSERVICEVMINFOUSER));
    716                         pUserInfo[cUniqueUsers++].ulNumProcs = cSessionProcs;
     832                        pUserInfo[cUniqueUsers].ulNumProcs = cSessionProcs;
     833                        pUserInfo[cUniqueUsers].ulSession  = ulSession;
     834                        cUniqueUsers++;
    717835                        Assert(cUniqueUsers <= cSessions);
    718836                    }
     
    720838            }
    721839
    722             VBoxServiceVerbose(3, "VMInfo/Users: Found %u unique logged-in user(s)\n",
     840            VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n",
    723841                               cUniqueUsers);
    724842
     
    728846                if (pUserInfo[i].ulNumProcs)
    729847                {
     848                    VBoxServiceVerbose(3, "User %ls has %ld processes (session %u)\n",
     849                                       pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulSession);
     850
    730851                    if (*pcUsersInList > 0)
    731852                    {
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp

    r39129 r40158  
    8383
    8484
    85 #ifdef RT_OS_WINDOWS
    86 static BOOL WINAPI VBoxServiceVMInfoConsoleControlHandler(DWORD dwCtrlType)
    87 {
    88     int rc = VINF_SUCCESS;
    89     bool fEventHandled = FALSE;
    90     switch (dwCtrlType)
    91     {
    92         case CTRL_LOGOFF_EVENT:
    93             VBoxServiceVerbose(2, "VMInfo: Received logged-off event\n");
    94             /* Trigger a re-enumeration of all logged-in users by unblocking
    95              * the multi event semaphore of the VMInfo thread. */
    96             if (g_hVMInfoEvent)
    97                 rc = RTSemEventMultiSignal(g_hVMInfoEvent);
    98             fEventHandled = TRUE;
    99             break;
    100         default:
    101             break;
    102         /** @todo Add other events here. */
    103     }
    104 
    105     if (RT_FAILURE(rc))
    106         VBoxServiceError("VMInfo: Event %ld handled with error rc=%Rrc\n",
    107                          dwCtrlType, rc);
    108     return fEventHandled;
     85
     86/**
     87 * Signals the event so that a re-enumeration of VM-specific
     88 * information (like logged in users) can happen.
     89 *
     90 * @return  IPRT status code.
     91 */
     92int VBoxServiceVMInfoSignal(void)
     93{
     94    /* Trigger a re-enumeration of all logged-in users by unblocking
     95     * the multi event semaphore of the VMInfo thread. */
     96    if (g_hVMInfoEvent)
     97        return RTSemEventMultiSignal(g_hVMInfoEvent);
     98
     99    return VINF_SUCCESS;
    109100}
    110 #endif /* RT_OS_WINDOWS */
    111101
    112102
     
    182172        VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count",
    183173                                        VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE, NULL /* Delete on exit */);
    184 
    185 #ifdef RT_OS_WINDOWS
    186 # ifndef RT_OS_NT4
    187     /* Install console control handler. */
    188     if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)VBoxServiceVMInfoConsoleControlHandler, TRUE /* Add handler */))
    189     {
    190         VBoxServiceError("VMInfo: Unable to add console control handler, error=%ld\n", GetLastError());
    191         /* Just skip this error, not critical. */
    192     }
    193 # endif /* !RT_OS_NT4 */
    194 #endif /* RT_OS_WINDOWS */
    195174    }
    196175    return rc;
     
    301280           && RT_SUCCESS(rc))
    302281    {
    303         VBoxServiceVerbose(4, "VMInfo/Users: Found logged in user \"%s\"\n",
     282        VBoxServiceVerbose(4, "Found logged in user \"%s\"\n",
    304283                           ut_user->ut_user);
    305284        if (cUsersInList > cListSize)
     
    369348            static int s_iVMInfoBitchedOOM = 0;
    370349            if (s_iVMInfoBitchedOOM++ < 3)
    371                 VBoxServiceVerbose(0, "VMInfo/Users: Warning: Not enough memory available to enumerate users! Keeping old value (%u)\n",
     350                VBoxServiceVerbose(0, "Warning: Not enough memory available to enumerate users! Keeping old value (%u)\n",
    372351                                   g_cVMInfoLoggedInUsers);
    373352            cUsersInList = g_cVMInfoLoggedInUsers;
     
    377356    }
    378357
    379     VBoxServiceVerbose(4, "VMInfo/Users: cUsersInList: %u, pszUserList: %s, rc=%Rrc\n",
     358    VBoxServiceVerbose(4, "cUsersInList: %u, pszUserList: %s, rc=%Rrc\n",
    380359                       cUsersInList, pszUserList ? pszUserList : "<NULL>", rc);
    381360
     
    878857static DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
    879858{
    880     int rc;
    881 
    882 #ifdef RT_OS_WINDOWS
    883 # ifndef RT_OS_NT4
    884     /* Uninstall console control handler. */
    885     if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)NULL, FALSE /* Remove handler */))
    886     {
    887         VBoxServiceError("VMInfo: Unable to remove console control handler, error=%ld\n", GetLastError());
    888         /* Just skip this error, not critical. */
    889     }
    890 # endif /* !RT_OS_NT4 */
    891 #endif
    892 
    893859    if (g_hVMInfoEvent != NIL_RTSEMEVENTMULTI)
    894860    {
     
    906872        /* Delete the "../Net" branch. */
    907873        const char *apszPat[1] = { "/VirtualBox/GuestInfo/Net/*" };
    908         rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));
     874        int rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));
    909875
    910876        /* Destroy property cache. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette