VirtualBox

Changeset 26136 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Feb 1, 2010 5:45:40 PM (15 years ago)
Author:
vboxsync
Message:

VBoxService: a couple of bug fixes together with code review and cleanups.

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  
    117117
    118118
     119/** Reports our current status to the SCM. */
    119120BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
    120121{
     
    140141int VBoxServiceWinSetDesc(SC_HANDLE hService)
    141142{
    142     /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields 
     143    /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields
    143144       like a longer service description. */
    144145#ifndef TARGET_NT4
     
    146147    /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */
    147148    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 */
    150151                                      &desc))
    151152    {
     
    158159
    159160
     161/** Installs the service into the registry. */
    160162int VBoxServiceWinInstall(void)
    161163{
     
    181183                                imagePath, NULL, NULL, NULL, NULL, NULL);
    182184    int rc = VINF_SUCCESS;
    183     if (NULL == hService) 
     185    if (NULL == hService)
    184186    {
    185187        DWORD dwErr = GetLastError();
     
    242244}
    243245
     246/** Uninstalls the service from the registry. */
    244247int VBoxServiceWinUninstall(void)
    245248{
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r26061 r26136  
    363363                int rc;
    364364                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 */
    366366                {
    367367                    rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r26083 r26136  
    106106typedef struct
    107107{
    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];
    111111} VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER;
    112112/** Structure for the file information lookup. */
     
    119119typedef struct
    120120{
    121     DWORD id; 
     121    DWORD id;
    122122    LUID luid;
    123123} VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC;
    124124/** Function prototypes for dynamic loading. */
    125 typedef DWORD (WINAPI* fnWTSGetActiveConsoleSessionId)();
     125typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void);
    126126#endif /* RT_OS_WINDOWS */
    127127
     
    151151extern SERVICE_STATUS_HANDLE g_hWinServiceStatus;
    152152extern SERVICE_TABLE_ENTRY const g_aServiceTable[];     /** @todo generate on the fly, see comment in main() from the enabled sub services. */
     153extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */
    153154
    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. */
     155extern int  VBoxServiceWinInstall(void);
     156extern int  VBoxServiceWinUninstall(void);
    159157extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint);
    160158# 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);
     159extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs);
     160extern bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession);
     161extern int  VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
     162extern void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs);
     163extern int  VBoxServiceWinGetComponentVersions(uint32_t uiClientID);
    171164# endif /* VBOX_WITH_GUEST_PROPS */
    172165#endif /* RT_OS_WINDOWS */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceUtils.cpp

    r25802 r26136  
    55
    66/*
    7  * Copyright (C) 2009 Sun Microsystems, Inc.
     7 * Copyright (C) 2009-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2626#ifdef RT_OS_WINDOWS
    2727# include <Windows.h>
     28# include <iprt/param.h>
     29# include <iprt/path.h>
    2830#endif
    29 
    3031#include <iprt/assert.h>
    3132#include <iprt/mem.h>
     
    3536#include "VBoxServiceInternal.h"
    3637
    37 
    3838#ifdef VBOX_WITH_GUEST_PROPS
     39
    3940/**
    4041 * Reads a guest property.
     
    5354int VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp)
    5455{
    55     size_t  cbBuf = _1K;
    56     void   *pvBuf = NULL;
    57     int     rc;
     56    uint32_t    cbBuf = _1K;
     57    void       *pvBuf = NULL;
     58    int         rc;
    5859
    5960    *ppszValue = NULL;
     
    186187    return rc;
    187188}
     189
    188190#endif /* VBOX_WITH_GUEST_PROPS */
    189 
    190 
    191191#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 */
     199static 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 */
     224static 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))
    299245            {
    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                }
    305273            }
    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    }
    330288    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 */
     309int 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  
    2626
    2727#ifdef VBOX_WITH_GUEST_PROPS
    28 /** Reads a guest property. */
    2928int VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp);
    30 /** Reads a guest property as a 32-bit value. */
    3129int 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. */
    3330int VBoxServiceWritePropF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...);
    3431#endif
     32
    3533#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);
     34int VBoxServiceGetFileVersionString(const char *pszPath, const char *pszFileName, char *pszVersion, size_t cbVersion);
    3835#endif
    3936
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp

    r26092 r26136  
    11/* $Id$ */
    22/** @file
    3  * VBoxVMInfo-win - Virtual machine (guest) information for the host.
     3 * VBoxService - Virtual Machine Information for the Host, Windows specifics.
    44 */
    55
    66/*
    7  * Copyright (C) 2009 Sun Microsystems, Inc.
     7 * Copyright (C) 2009-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4343*   Global Variables                                                           *
    4444*******************************************************************************/
     45/** Function prototypes for dynamic loading. */
     46PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId = NULL;
     47
     48
    4549#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 */
     58static int VBoxServiceVMInfoWinProcessesGetTokenInfo(PVBOXSERVICEVMINFOPROC pProc,
     59                                                     TOKEN_INFORMATION_CLASS tkClass)
    5660{
    5761    AssertPtr(pProc);
     
    6064        return RTErrConvertFromWin32(GetLastError());
    6165
     66     int    rc = VERR_NO_MEMORY;
    6267     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))
    6969     {
    7070         void *pvTokenInfo = NULL;
     
    7272         switch (tkClass)
    7373         {
    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;
    8685         }
    8786
    8887         if (pvTokenInfo)
    89          {     
     88         {
    9089             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))
    9691             {
    9792                 switch (tkClass)
    9893                 {
    99                  case TokenStatistics:
     94                     case TokenStatistics:
    10095                     {
    10196                         TOKEN_STATISTICS *pStats = (TOKEN_STATISTICS*)pvTokenInfo;
    102                          AssertPtr(pStats);
    10397                         pProc->luid = pStats->AuthenticationId;
    104                          /* @todo Add more information of TOKEN_STATISTICS as needed. */
     98                         /** @todo Add more information of TOKEN_STATISTICS as needed. */
    10599                         break;
    106100                     }
    107101
    108                  default:
    109                      /* Should never get here! */
    110                      break;               
     102                     default:
     103                         /* Should never get here! */
     104                         break;
    111105                 }
    112106                 rc = VINF_SUCCESS;
    113107             }
     108             else
     109                 rc = RTErrConvertFromWin32(GetLastError());
    114110             RTMemFree(pvTokenInfo);
    115111         }
    116112         CloseHandle(hToken);
    117     }   
     113    }
     114    else
     115        rc = RTErrConvertFromWin32(GetLastError());
    118116    CloseHandle(h);
    119117    return rc;
    120118}
    121119
    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 */
     131int 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;
    134143    do
    135144    {
    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))
    137158        {
    138159            rc = RTErrConvertFromWin32(GetLastError());
    139160            break;
    140161        }
    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))
    144163        {
    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++)
    149179            {
    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                }
    152188            }
     189
     190            /* Save number of processes */
     191            if (RT_SUCCESS(rc))
     192            {
     193                *pcProcs  = cProcesses;
     194                *ppaProcs = paProcs;
     195            }
     196            else
     197                RTMemFree(paProcs);
    153198        }
    154199        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)
    167200            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);
    196204    return rc;
    197205}
    198206
    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 */
     213void 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 */
     226bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs)
    210227{
    211228    AssertPtr(pSession);
    212229
    213     if (dwProcCount <= 0) /* To be on the safe side. */
    214         return 0;
    215     AssertPtr(pProc);
     230    if (!cProcs) /* To be on the safe side. */
     231        return false;
     232    AssertPtr(paProcs);
    216233
    217234    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++)
    229249    {
    230250        /*VBoxServiceVerbose(3, "%ld:%ld <-> %ld:%ld\n",
    231                              pCur->luid.HighPart, pCur->luid.LowPart,
     251                             paProcs[i].luid.HighPart, paProcs[i].luid.LowPart,
    232252                             pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);*/
    233         if (   pCur->luid.HighPart == pSessionData->LogonId.HighPart
    234             && pCur->luid.LowPart  == pSessionData->LogonId.LowPart)
     253        if (   paProcs[i].luid.HighPart == pSessionData->LogonId.HighPart
     254            && paProcs[i].luid.LowPart  == pSessionData->LogonId.LowPart)
    235255        {
    236256            VBoxServiceVerbose(3, "Users: Session %ld:%ld has active processes\n",
    237257                               pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);
    238258            LsaFreeReturnBuffer(pSessionData);
    239             return 1;
    240         }         
    241         pCur++;
     259            return true;
     260        }
    242261    }
    243262    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 */
     275static 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 */
     299bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession)
     300{
    256301    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)
    271314    {
    272315        VBoxServiceError("Invalid logon session data.\n");
    273         return FALSE;
    274     }
    275 
     316        return false;
     317    }
    276318    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)
    289348        {
    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;
    330354            if (LookupAccountSid(NULL,
    331                                  sessionData->Sid,
     355                                 pSessionData->Sid,
    332356                                 szOwnerName,
    333357                                 &dwOwnerNameSize,
    334358                                 szDomainName,
    335359                                 &dwDomainNameSize,
    336                                  &ownerType))
     360                                 &enmOwnerType))
    337361            {
    338362                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? */
    341368                /* The session ID increments/decrements on Vista often! So don't compare
    342369                   the session data SID with the current SID here. */
     
    344371                if (g_pfnWTSGetActiveConsoleSessionId != NULL)            /* Check terminal session ID. */
    345372                    dwActiveSession = g_pfnWTSGetActiveConsoleSessionId();
    346 
    347373                /*VBoxServiceVerbose(3, ("Users: Current active session ID: %ld\n", dwActiveSession));*/
    348 
    349                 if (SidTypeUser == ownerType)
     374#endif
     375
     376                if (enmOwnerType == SidTypeUser)
    350377                {
    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))
    361387                    {
    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)
    364390                            iState = *pBuffer;
    365391
    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. */
    369395                        {
    370396                            /** @todo On Vista and W2K, always "old" user name are still
    371397                             *        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;
    374401                        }
     402
     403                        if (pBuffer)
     404                            WTSFreeMemory(pBuffer);
    375405                    }
    376406                    else
    377407                    {
    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;
    381414                    }
    382 
    383                     if (pBuffer)
    384                         WTSFreeMemory(pBuffer);
    385415                }
    386416            }
     
    388418    }
    389419
    390     LsaFreeReturnBuffer(sessionData);
    391     return bFoundUser;
    392 }
     420    LsaFreeReturnBuffer(pSessionData);
     421    return fFoundUser;
     422}
     423
    393424#endif /* TARGET_NT4 */
    394425
    395 int VBoxServiceWinGetComponentVersions(uint32_t uiClientID)
     426int VBoxServiceWinGetComponentVersions(uint32_t uClientID)
    396427{
    397428    int rc;
    398     char szVer[_MAX_PATH] = {0};
    399     char szPropPath[_MAX_PATH] = {0};
    400429    char szSysDir[_MAX_PATH] = {0};
    401430    char szWinDir[_MAX_PATH] = {0};
    402431    char szDriversDir[_MAX_PATH + 32] = {0};
    403432
     433    /* ASSUME: szSysDir and szWinDir and derivatives are always ASCII compatible. */
    404434    GetSystemDirectory(szSysDir, _MAX_PATH);
    405435    GetWindowsDirectory(szWinDir, _MAX_PATH);
    406     RTStrPrintf(szDriversDir, (_MAX_PATH + 32), "%s\\drivers", szSysDir);
     436    RTStrPrintf(szDriversDir, sizeof(szDriversDir), "%s\\drivers", szSysDir);
    407437#ifdef RT_ARCH_AMD64
    408438    char szSysWowDir[_MAX_PATH + 32] = {0};
    409     RTStrPrintf(szSysWowDir, (_MAX_PATH + 32), "%s\\SysWow64", szWinDir);
     439    RTStrPrintf(szSysWowDir, sizeof(szSysWowDir), "%s\\SysWow64", szWinDir);
    410440#endif
    411441
    412442    /* The file information table. */
    413443#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" },
    424454
    425455 /* On 64-bit we don't yet have the OpenGL DLLs in native format.
    426456    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" },
    453479    };
    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" },
    470493    };
    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);
    481503    }
    482504
    483505    return VINF_SUCCESS;
    484506}
     507
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp

    r26087 r26136  
    11/* $Id$ */
    22/** @file
    3  * VBoxVMInfo - Virtual machine (guest) information for the host.
     3 * VBoxService - Virtual Machine Information for the Host.
    44 */
    55
    66/*
    7  * Copyright (C) 2009 Sun Microsystems, Inc.
     7 * Copyright (C) 2009-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6464*******************************************************************************/
    6565/** The vminfo interval (millseconds). */
    66 uint32_t g_VMInfoInterval = 0;
     66uint32_t                g_VMInfoInterval = 0;
    6767/** The semaphore we're blocking on. */
    68 static RTSEMEVENTMULTI g_VMInfoEvent = NIL_RTSEMEVENTMULTI;
     68static RTSEMEVENTMULTI  g_VMInfoEvent = NIL_RTSEMEVENTMULTI;
    6969/** The guest property service client ID. */
    70 static uint32_t g_VMInfoGuestPropSvcClientID = 0;
     70static uint32_t         g_VMInfoGuestPropSvcClientID = 0;
    7171/** 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
     72static uint32_t         g_cVMInfoLoggedInUsers = UINT32_MAX;
    7973
    8074
     
    117111    /* Get function pointers. */
    118112    HMODULE hKernel32 = LoadLibrary("kernel32");
    119     if (NULL != hKernel32)
     113    if (hKernel32 != NULL)
    120114    {
    121         g_pfnWTSGetActiveConsoleSessionId = (fnWTSGetActiveConsoleSessionId)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");
     115        g_pfnWTSGetActiveConsoleSessionId = (PFNWTSGETACTIVECONSOLESESSIONID)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");
    122116        FreeLibrary(hKernel32);
    123117    }
     
    138132
    139133
    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 */
     139static 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", "");
    163150
    164151    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", "");
    166156
    167157    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", "");
    169162
    170163    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;
    175174    rc = VbglR3GetAdditionsVersion(&pszAddVer, &pszAddRev);
    176175    if (RT_SUCCESS(rc))
    177176    {
    178177        /* 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);
    181180        RTStrFree(pszAddVer);
    182181        RTStrFree(pszAddRev);
     
    184183
    185184#ifdef RT_OS_WINDOWS
     185    /*
     186     * Do windows specific properties.
     187     */
    186188    char *pszInstDir;
    187189    rc = VbglR3GetAdditionsInstallationPath(&pszInstDir);
     
    191193        RTStrFree(pszInstDir);
    192194    }
    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 */
     201DECLCALLBACK(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     */
    197226    unsigned cErrors = 0;
    198227    for (;;)
    199228    {
     229/** @todo r=bird: split this code up into functions!! */
    200230        /* Enumerate logged in users. */
    201         uint32_t uiUserCount = 0;
     231        uint32_t cUsersInList = 0;
    202232        char szUserList[4096] = {0};
    203233
    204234#ifdef RT_OS_WINDOWS
    205235# 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);
    217244        if (r != STATUS_SUCCESS)
    218245        {
     
    221248        }
    222249
    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++)
    237256            {
    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                }
    246276            }
    247         }
    248 
    249         VBoxServiceVMInfoWinProcessesFree(pProcs);
    250         ::LsaFreeReturnBuffer(pSessions);
     277            VBoxServiceVMInfoWinProcessesFree(paProcs);
     278        }
     279
     280        ::LsaFreeReturnBuffer(paSessions);
    251281# endif /* TARGET_NT4 */
    252282#elif defined(RT_OS_FREEBSD)
     
    277307                /** @todo r=bird: strstr will filtering out users with similar names. For
    278308                 *        example: smith, smithson, joesmith and bobsmith */
    279                 if (uiUserCount > 0)
     309                if (cUsersInList > 0)
    280310                    strcat(szUserList, ",");
    281311                strcat(szUserList, ut_user->ut_user);
    282                 uiUserCount++;
     312                cUsersInList++;
    283313            }
    284314        }
     
    286316#endif /* !RT_OS_WINDOWS */
    287317
    288         if (uiUserCount > 0)
     318        if (cUsersInList > 0)
    289319            VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList);
    290320        else
    291321            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)
    294325        {
    295326            /* Update this property ONLY if there is a real change from no users to
     
    297328             * forces an update, but only once. This ensures consistent property
    298329             * settings even if the VM aborted previously. */
    299             if (uiUserCount == 0)
     330            if (cUsersInList == 0)
    300331                VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true");
    301             else if (g_VMInfoLoggedInUsers == 0)
     332            else if (g_cVMInfoLoggedInUsers == 0)
    302333                VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false");
    303334        }
    304         g_VMInfoLoggedInUsers = uiUserCount;
    305 
    306         /* Get network configuration. */
     335        g_cVMInfoLoggedInUsers = cUsersInList;
     336
     337        /*
     338         * Get network configuration.
     339         */
    307340        /** @todo Throw this code into a separate function/module? */
    308341       int nNumInterfaces = 0;
     
    421454            iCurIface++;
    422455        }
    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
    428462
    429463        /*
     
    479513        rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
    480514        rc = VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%d", 0);
    481         if (g_VMInfoLoggedInUsers > 0)
     515        if (g_cVMInfoLoggedInUsers > 0)
    482516            VBoxServiceWritePropF(g_VMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true");
    483517
Note: See TracChangeset for help on using the changeset viewer.

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