VirtualBox

Changeset 96451 in vbox


Ignore:
Timestamp:
Aug 24, 2022 9:56:54 AM (2 years ago)
Author:
vboxsync
Message:

Add/NT/Inst,Add/NT/VBoxTray,Add/VBoxService: Cleaned up VBoxGuestInstallHelper.cpp (tested) and the VBoxTray IPC interface (not tested). The motivation for the former was to make it compile in no-CRT mode, the latter was buggy code. The IPC interface is not backwards compatible, this is intentional to avoid buggy code. bugref:10261

Location:
trunk/src/VBox/Additions
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/Makefile.kmk

    r96407 r96451  
    3535# NSIS plugins always have to be compiled in 32-bit!
    3636#
     37# Note! Installation is required for repacking Guest Additions
     38#
    3739## @todo kBuild: This needs the WINPSDK fix to work for cross building.
    3840DLLS.x86 += VBoxGuestInstallHelper
    39 VBoxGuestInstallHelper_TEMPLATE = VBoxGuestR3Dll
    40 #Installation is required for repacking Guest Additions
    41 VBoxGuestInstallHelper_INST     = repackadd/resources/VBoxGuestInstallHelper/
     41VBoxGuestInstallHelper_TEMPLATE        := VBoxGuestR3Dll
     42VBoxGuestInstallHelper_INST             := repackadd/resources/VBoxGuestInstallHelper/
    4243ifdef VBOX_SIGN_ADDITIONS # (See the parent makefile.)
    43  VBoxGuestInstallHelper_INSTTYPE       = stage
    44  VBoxGuestInstallHelper_DEBUG_INSTTYPE = both
     44 VBoxGuestInstallHelper_INSTTYPE       := stage
     45 VBoxGuestInstallHelper_DEBUG_INSTTYPE := both
    4546endif
    46 VBoxGuestInstallHelper_DEFS         = _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1 UNICODE _UNICODE
    47 VBoxGuestInstallHelper_BLD_TRG_ARCH = x86
    48 VBoxGuestInstallHelper_SOURCES  = \
     47VBoxGuestInstallHelper_DEFS             := _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1 UNICODE _UNICODE
     48VBoxGuestInstallHelper_BLD_TRG_ARCH    := x86
     49VBoxGuestInstallHelper_SOURCES         := \
    4950        VBoxGuestInstallHelper.cpp \
    5051        VBoxGuestInstallHelper.rc
  • trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp

    r96407 r96451  
    3131*   Header Files                                                                                                                 *
    3232*********************************************************************************************************************************/
     33#ifndef UNICODE
     34# define UNICODE
     35#endif
    3336#include <iprt/win/windows.h>
    34 #include <stdlib.h>
    35 #include <tchar.h>
    36 #include <strsafe.h>
    37 #pragma warning(push)
    38 #pragma warning(disable: 4995) /* warning C4995: 'lstrcpyA': name was marked as #pragma deprecated */
    3937#include "exdll.h"
    40 #pragma warning(pop)
    4138
    4239#include <iprt/err.h>
     
    4744#include <iprt/process.h>
    4845#include <iprt/string.h>
    49 #ifdef UNICODE
    50 # include <iprt/utf16.h>
    51 #endif
     46#include <iprt/utf16.h>
    5247
    5348/* Required structures/defines of VBoxTray. */
     
    5853*   Defined Constants And Macros                                                                                                 *
    5954*********************************************************************************************************************************/
    60 #define VBOXINSTALLHELPER_EXPORT extern "C" void __declspec(dllexport)
     55#define VBOXINSTALLHELPER_EXPORT extern "C" DECLEXPORT(void)
    6156
    6257
     
    7065*   Global Variables                                                                                                             *
    7166*********************************************************************************************************************************/
    72 HINSTANCE               g_hInstance;
    73 HWND                    g_hwndParent;
    74 
    75 /**
    76  * @todo Clean up this DLL, use more IPRT in here!
    77  */
    78 
    79 /**
    80  * Pops (gets) a value from the internal NSIS stack.
    81  * Since the supplied popstring() method easily can cause buffer
    82  * overflows, use vboxPopString() instead!
    83  *
    84  * @return  VBox status code.
    85  * @param   pszDest     Pointer to pre-allocated string to store result.
    86  * @param   cchDest     Size (in characters) of pre-allocated string.
    87  */
    88 static int vboxPopString(TCHAR *pszDest, size_t cchDest)
    89 {
    90     int rc = VINF_SUCCESS;
    91 
    92     if (!g_stacktop || !*g_stacktop)
    93     {
    94         rc = VERR_NO_DATA;
    95     }
    96     else
    97     {
    98         stack_t *pStack = (*g_stacktop);
    99         AssertPtr(pStack);
    100 
    101         HRESULT hr = StringCchCopy(pszDest, cchDest, pStack->text);
    102         if (SUCCEEDED(hr))
    103         {
    104             *g_stacktop = pStack->next;
    105             GlobalFree((HGLOBAL)pStack);
    106         }
    107         else
    108             rc = VERR_INVALID_PARAMETER;
    109     }
     67static HINSTANCE    g_hInstance;
     68static HWND         g_hwndParent;
     69
     70
     71/**
     72 * Frees a popped stack entry after use.
     73 */
     74DECLINLINE(void) vboxFreeStackEntry(stack_t *pEntry)
     75{
     76    if (pEntry)
     77        GlobalFree((HGLOBAL)pEntry);
     78}
     79
     80
     81/**
     82 * Allocates a new stack entry for containing a string of the given length
     83 * (excluding terminator)
     84 */
     85DECLINLINE(stack_t *) vboxAllocStackEntry(size_t cwcString)
     86{
     87    return (stack_t *)GlobalAlloc(GPTR, RT_UOFFSETOF_DYN(stack_t, text[cwcString + 1]));
     88}
     89
     90
     91/**
     92 * Pops an entry off the stack, return NULL if empty.
     93 *
     94 * Call vboxFreeStackEntry when done.
     95 *
     96 */
     97DECLINLINE(stack_t *) vboxPopStack(stack_t **ppTopOfStack)
     98{
     99    stack_t *pEntry = ppTopOfStack ? *ppTopOfStack : NULL;
     100    if (pEntry)
     101        *ppTopOfStack = pEntry->next;
     102    return pEntry;
     103}
     104
     105
     106/**
     107 * Pushes an entry onto the stack.
     108 */
     109DECLINLINE(void) vboxPushStack(stack_t **ppTopOfStack, stack_t *pEntry)
     110{
     111    pEntry->next = *ppTopOfStack;
     112    *ppTopOfStack = pEntry;
     113}
     114
     115
     116static void vboxPushUtf16N(stack_t **ppTopOfStack, wchar_t const *pwszString, size_t cwcString)
     117{
     118    stack_t *pEntry = vboxAllocStackEntry(cwcString);
     119
     120    memcpy(pEntry->text, pwszString, cwcString * sizeof(pEntry->text[0]));
     121    pEntry->text[cwcString] = '\0';
     122
     123    vboxPushStack(ppTopOfStack, pEntry);
     124}
     125
     126
     127static void vboxPushUtf16(stack_t **ppTopOfStack, wchar_t const *pwszString)
     128{
     129    return vboxPushUtf16N(ppTopOfStack, pwszString, RTUtf16Len(pwszString));
     130}
     131
     132
     133#define VBOX_PUSH_STRING_LITERAL(a_ppTopOfStack, a_szLiteral) \
     134    vboxPushUtf16N(a_ppTopOfStack, RT_CONCAT(L, a_szLiteral), sizeof(RT_CONCAT(L, a_szLiteral)) / sizeof(wchar_t) - 1)
     135
     136
     137static void vboxPushUtf8(stack_t **ppTopOfStack, char const *pszString)
     138{
     139    size_t cwcUtf16 = RTStrCalcUtf16Len(pszString);
     140    stack_t *pEntry = vboxAllocStackEntry(cwcUtf16);
     141
     142    PRTUTF16 pwszUtf16 = pEntry->text;
     143    int rc = RTStrToUtf16Ex(pszString, RTSTR_MAX, &pwszUtf16, cwcUtf16 + 1, NULL);
     144    AssertRC(rc);
     145
     146    vboxPushStack(ppTopOfStack, pEntry);
     147}
     148
     149/**
     150 * Pushes a string containing an error message and a VBox status code.
     151 */
     152static void vboxPushVBoxError(stack_t **ppTopOfStack, char const *pszString, int vrc)
     153{
     154    RTUTF16 wszTmp[128];
     155    RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %s! %Rrc", pszString, vrc);
     156    vboxPushUtf16(ppTopOfStack, wszTmp);
     157}
     158
     159
     160static void vboxPushLastError(stack_t **ppTopOfStack, char const *pszString)
     161{
     162    DWORD const dwErr = GetLastError();
     163    RTUTF16 wszTmp[128];
     164    RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %s! lasterr=%u (%#x)", pszString, dwErr, dwErr);
     165    vboxPushUtf16(ppTopOfStack, wszTmp);
     166}
     167
     168
     169static void vboxPushLastErrorF(stack_t **ppTopOfStack, const char *pszFormat, ...)
     170{
     171    DWORD const dwErr = GetLastError();
     172    RTUTF16 wszTmp[128];
     173    va_list va;
     174    va_start(va, pszFormat);
     175    RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %N! lasterr=%u (%#x)", pszFormat, &va, dwErr, dwErr);
     176    va_end(va);
     177    vboxPushUtf16(ppTopOfStack, wszTmp);
     178}
     179
     180
     181/**
     182 * Convers a parameter to uint32_t.
     183 *
     184 * @returns IPRT status code.
     185 * @param   pwsz                Will be trimmed.
     186 * @param   puValue             Where to return the value.
     187 */
     188static int vboxUtf16ToUInt32(PRTUTF16 pwsz, uint32_t *puValue)
     189{
     190    *puValue = 0;
     191
     192    /* Trim the input: */
     193    RTUTF16 wc;
     194    while ((wc = *pwsz) == ' ' || wc == '\t')
     195        pwsz++;
     196    size_t cwc = RTUtf16Len(pwsz);
     197    while (cwc > 0 && ((wc = pwsz[cwc - 1]) == ' ' || wc == '\t'))
     198        pwsz[--cwc] = '\0';
     199
     200    /* Convert the remains into an UTF-8 string. */
     201    char szValue[128];
     202    char *pszValue = &szValue[0];
     203    int rc = RTUtf16ToUtf8Ex(pwsz, cwc, &pszValue, sizeof(szValue), NULL);
     204    if (RT_SUCCESS(rc))
     205        rc = RTStrToUInt32Full(pszValue, 0, puValue);
    110206    return rc;
    111207}
    112208
    113 static int vboxPopULong(PULONG pulValue)
    114 {
    115     int rc = VINF_SUCCESS;
    116 
    117     if (!g_stacktop || !*g_stacktop)
    118     {
    119         rc = VERR_NO_DATA;
    120     }
    121     else
    122     {
    123         stack_t *pStack = (*g_stacktop);
    124         AssertPtr(pStack);
    125 
    126         *pulValue = _tcstoul(pStack->text, NULL, 10 /* Base */);
    127 
    128         *g_stacktop = pStack->next;
    129         GlobalFree((HGLOBAL)pStack);
    130     }
    131 
    132     return rc;
    133 }
    134 
    135 static void vboxPushHResultAsString(HRESULT hr)
    136 {
    137     TCHAR szErr[NSIS_MAX_STRLEN];
    138     if (FAILED(hr))
    139     {
    140         if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szErr, MAX_PATH, NULL))
    141             szErr[MAX_PATH] = '\0';
    142         else
    143             StringCchPrintf(szErr, sizeof(szErr),
    144                             _T("FormatMessage failed! Error = %ld"), GetLastError());
    145     }
    146     else
    147         StringCchPrintf(szErr, sizeof(szErr), _T("0"));
    148     pushstring(szErr);
    149 }
    150 
    151 static void vboxPushRcAsString(int rc)
    152 {
    153     TCHAR szErr[NSIS_MAX_STRLEN];
    154     if (RT_FAILURE(rc))
    155     {
    156         static const char s_szPrefix[] = "Error: ";
    157         AssertCompile(NSIS_MAX_STRLEN > sizeof(s_szPrefix) + 32);
    158 #ifdef UNICODE
    159         char szTmp[80];
    160         memcpy(szTmp, s_szPrefix, sizeof(s_szPrefix));
    161         RTErrQueryDefine(rc, &szTmp[sizeof(s_szPrefix) - 1], sizeof(szTmp) - sizeof(s_szPrefix) - 1, false);
    162 
    163         RT_ZERO(szErr);
    164         PRTUTF16 pwszDst = szErr;
    165         RTStrToUtf16Ex(szTmp, RTSTR_MAX, &pwszDst, RT_ELEMENTS(szErr), NULL);
    166 #else
    167         memcpy(szErr, s_szPrefix, sizeof(s_szPrefix));
    168         RTErrQueryDefine(rc, &szErr[sizeof(s_szPrefix) - 1], sizeof(szErr) - sizeof(s_szPrefix) - 1, false);
    169 #endif
    170     }
    171     else
    172     {
    173         szErr[0] = '0';
    174         szErr[1] = '\0';
    175     }
    176 
    177     pushstring(szErr);
    178 }
    179 
    180 /**
    181  * Connects to VBoxTray IPC under the behalf of the user running
    182  * in the current thread context.
     209
     210/**
     211 * Connects to VBoxTray IPC under the behalf of the user running in the current
     212 * thread context.
    183213 *
    184214 * @return  IPRT status code.
     
    201231/**
    202232 * Retrieves a file's architecture (x86 or amd64).
     233 *
    203234 * Outputs "x86", "amd64" or an error message (if not found/invalid) on stack.
    204235 *
     
    207238 * @param   variables           The actual variable string.
    208239 * @param   stacktop            Pointer to a pointer to the current stack.
    209  * @param   extra               Extra parameters. Currently unused.
    210  */
    211 VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
     240 * @param   extra               Extra parameters.
     241 */
     242VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
    212243                                             extra_parameters *extra)
    213244{
    214     RT_NOREF(hwndParent, extra);
    215 
    216     EXDLL_INIT();
    217 
    218     TCHAR szFile[MAX_PATH + 1];
    219     int rc = vboxPopString(szFile, sizeof(szFile) / sizeof(TCHAR));
    220     if (RT_SUCCESS(rc))
     245    RT_NOREF(hwndParent, string_size, variables, extra);
     246
     247    stack_t *pEntry = vboxPopStack(stacktop);
     248    if (pEntry)
    221249    {
    222 #ifdef UNICODE
    223250        char *pszFileUtf8;
    224         rc = RTUtf16ToUtf8(szFile, &pszFileUtf8);
     251        int rc = RTUtf16ToUtf8(pEntry->text, &pszFileUtf8);
    225252        if (RT_SUCCESS(rc))
    226253        {
    227 #else
    228             char *pszFileUtf8 = szFile;
    229 #endif
    230254            RTLDRMOD hLdrMod;
    231255            rc = RTLdrOpen(pszFileUtf8, RTLDR_O_FOR_VALIDATION, RTLDRARCH_WHATEVER, &hLdrMod);
     
    238262                    {
    239263                        case RTLDRARCH_X86_32:
    240                             pushstring(_T("x86"));
     264                            VBOX_PUSH_STRING_LITERAL(stacktop, "x86");
    241265                            break;
    242266
    243267                        case RTLDRARCH_AMD64:
    244                             pushstring(_T("amd64"));
     268                            VBOX_PUSH_STRING_LITERAL(stacktop, "amd64");
    245269                            break;
    246270
    247271                        default:
    248                             pushstring(_T("Error: Unknown / invalid architecture"));
     272                            VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid architecture");
    249273                            break;
    250274                    }
    251275                }
    252276                else
    253                     pushstring(_T("Error: Unknown / invalid PE signature"));
     277                    VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid PE signature");
    254278
    255279                RTLdrClose(hLdrMod);
    256280            }
    257281            else
    258                 pushstring(_T("Error: Could not open file"));
    259 #ifdef UNICODE
     282                vboxPushVBoxError(stacktop, "RTLdrOpen failed", rc);
    260283            RTStrFree(pszFileUtf8);
    261284        }
    262 #endif
     285        else
     286            vboxPushVBoxError(stacktop, "RTUtf16ToUtf8 failed", rc);
    263287    }
    264288    else
    265         pushstring(_T("Error: Could not retrieve file name"));
     289        VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
     290    vboxFreeStackEntry(pEntry);
    266291}
    267292
    268293/**
    269294 * Retrieves a file's vendor.
     295 *
    270296 * Outputs the vendor's name or an error message (if not found/invalid) on stack.
    271297 *
     
    274300 * @param   variables           The actual variable string.
    275301 * @param   stacktop            Pointer to a pointer to the current stack.
    276  * @param   extra               Extra parameters. Currently unused.
    277  */
    278 VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
     302 * @param   extra               Extra parameters.
     303 */
     304VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
    279305                                       extra_parameters *extra)
    280306{
    281     RT_NOREF(hwndParent, extra);
    282 
    283     EXDLL_INIT();
    284 
    285     TCHAR szFile[MAX_PATH + 1];
    286     int rc = vboxPopString(szFile, sizeof(szFile) / sizeof(TCHAR));
    287     if (RT_SUCCESS(rc))
     307    RT_NOREF(hwndParent, string_size, variables, extra);
     308
     309    stack_t *pEntry = vboxPopStack(stacktop);
     310    if (pEntry)
    288311    {
    289         DWORD dwInfoSize = GetFileVersionInfoSize(szFile, NULL /* lpdwHandle */);
     312        DWORD dwInfoSize = GetFileVersionInfoSizeW(pEntry->text, NULL /* lpdwHandle */);
    290313        if (dwInfoSize)
    291314        {
    292             void *pFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);
    293             if (pFileInfo)
     315            void *pvFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);
     316            if (pvFileInfo)
    294317            {
    295                 if (GetFileVersionInfo(szFile, 0, dwInfoSize, pFileInfo))
     318                if (GetFileVersionInfoW(pEntry->text, 0, dwInfoSize, pvFileInfo))
    296319                {
    297320                    LPVOID pvInfo;
    298                     UINT puInfoLen;
    299                     if (VerQueryValue(pFileInfo, _T("\\VarFileInfo\\Translation"),
    300                                       &pvInfo, &puInfoLen))
     321                    UINT   cbInfo;
     322                    if (VerQueryValueW(pvFileInfo, L"\\VarFileInfo\\Translation", &pvInfo, &cbInfo))
    301323                    {
    302                         WORD wCodePage = LOWORD(*(DWORD*)pvInfo);
    303                         WORD wLanguageID = HIWORD(*(DWORD*)pvInfo);
    304 
    305                         TCHAR szQuery[MAX_PATH];
    306                         StringCchPrintf(szQuery, sizeof(szQuery), _T("StringFileInfo\\%04X%04X\\CompanyName"),
    307                                         wCodePage, wLanguageID);
    308 
    309                         LPCTSTR pcData;
    310                         if (VerQueryValue(pFileInfo, szQuery, (void**)&pcData, &puInfoLen))
    311                         {
    312                             pushstring(pcData);
    313                         }
     324                        WORD wCodePage   = LOWORD(*(DWORD const *)pvInfo);
     325                        WORD wLanguageID = HIWORD(*(DWORD const *)pvInfo);
     326
     327                        WCHAR wszQuery[80];
     328                        RTUtf16Printf(wszQuery, RT_ELEMENTS(wszQuery), "StringFileInfo\\%04X%04X\\CompanyName",
     329                                      wCodePage, wLanguageID);
     330
     331                        LPCWSTR pwszData;
     332                        if (VerQueryValueW(pvFileInfo, wszQuery, (void **)&pwszData, &cbInfo))
     333                            vboxPushUtf16(stacktop, pwszData);
    314334                        else
    315                             rc = VERR_NOT_FOUND;
     335                            vboxPushLastErrorF(stacktop, "VerQueryValueW '%ls' failed", wszQuery);
    316336                    }
    317337                    else
    318                         rc = VERR_NOT_FOUND;
     338                        vboxPushLastError(stacktop, "VerQueryValueW '\\VarFileInfo\\Translation' failed");
    319339                }
    320                 GlobalFree(pFileInfo);
     340                else
     341                    vboxPushLastError(stacktop, "GetFileVersionInfo failed");
     342                GlobalFree(pvFileInfo);
    321343            }
    322344            else
    323                 rc = VERR_NO_MEMORY;
     345                VBOX_PUSH_STRING_LITERAL(stacktop, "Error: GlobalAlloc failed");
    324346        }
    325347        else
    326             rc = VERR_NOT_FOUND;
     348            vboxPushLastError(stacktop, "GetFileVersionInfoSizeW failed");
    327349    }
    328 
    329     if (RT_FAILURE(rc))
    330         vboxPushRcAsString(rc);
     350    else
     351        VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
     352    vboxFreeStackEntry(pEntry);
    331353}
    332354
     
    339361 * @param   variables           The actual variable string.
    340362 * @param   stacktop            Pointer to a pointer to the current stack.
    341  * @param   extra               Extra parameters. Currently unused.
    342  */
    343 VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
     363 * @param   extra               Extra parameters.
     364 */
     365VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
    344366                                               extra_parameters *extra)
    345367{
    346     RT_NOREF(hwndParent, extra);
    347 
    348     EXDLL_INIT();
    349 
    350     TCHAR szMsg[256];
    351     TCHAR szTitle[128];
    352     int rc = vboxPopString(szMsg, sizeof(szMsg) / sizeof(TCHAR));
    353     if (RT_SUCCESS(rc))
    354         rc = vboxPopString(szTitle, sizeof(szTitle) / sizeof(TCHAR));
    355 
    356     /** @todo Do we need to restore the stack on failure? */
    357 
    358     if (RT_SUCCESS(rc))
     368    RT_NOREF(hwndParent, string_size, variables, extra);
     369
     370    /*
     371     * Get parameters from the stack.
     372     */
     373    stack_t * const pMsgEntry     = vboxPopStack(stacktop);
     374    stack_t * const pTitleEntry   = vboxPopStack(stacktop);
     375    stack_t * const pTypeEntry    = vboxPopStack(stacktop);
     376    stack_t * const pTimeoutEntry = vboxPopStack(stacktop);
     377    if (pTimeoutEntry)
    359378    {
    360         RTR3InitDll(0);
    361 
    362 #ifdef UNICODE
    363         char *pszMsgUtf8   = NULL;
    364         char *pszTitleUtf8 = NULL;
    365         rc = RTUtf16ToUtf8(szMsg, &pszMsgUtf8);
    366         if (RT_SUCCESS(rc))
    367             rc = RTUtf16ToUtf8(szTitle, &pszTitleUtf8);
    368 #else
    369         char *pszMsgUtf8   = szMsg;
    370         char *pszTitleUtf8 = szTitle;
    371 #endif
    372         if (RT_SUCCESS(rc))
     379        /*
     380         * Allocate an IPC message payload structure of the right size.
     381         */
     382        size_t const cchMsg     = RTUtf16CalcUtf8Len(pMsgEntry->text);
     383        size_t const cchTitle   = RTUtf16CalcUtf8Len(pTitleEntry->text);
     384        size_t const cbPayload  = RT_UOFFSETOF_DYN(VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T, szzStrings[cchMsg + 1 + cchTitle + 1]);
     385        PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T pPayload = (PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T)RTMemAllocZVar(cbPayload);
     386        if (pPayload)
    373387        {
    374             /* We use UTF-8 for the IPC data. */
    375             uint32_t cbMsg = sizeof(VBOXTRAYIPCMSG_SHOWBALLOONMSG)
    376                            + (uint32_t)strlen(pszMsgUtf8)   + 1  /* Include terminating zero */
    377                            + (uint32_t)strlen(pszTitleUtf8) + 1; /* Ditto. */
    378             Assert(cbMsg);
    379             PVBOXTRAYIPCMSG_SHOWBALLOONMSG pIpcMsg = (PVBOXTRAYIPCMSG_SHOWBALLOONMSG)RTMemAlloc(cbMsg);
    380             if (pIpcMsg)
     388            VBOXTRAYIPCHEADER const MsgHdr =
    381389            {
    382                 /* Stuff in the strings. */
    383                 memcpy(pIpcMsg->szMsgContent, pszMsgUtf8,   strlen(pszMsgUtf8)   + 1);
    384                 memcpy(pIpcMsg->szMsgTitle,   pszTitleUtf8, strlen(pszTitleUtf8) + 1);
    385 
    386                 /* Pop off the values in reverse order from the stack. */
    387                 rc = vboxPopULong((ULONG *)&pIpcMsg->uType);
    388                 if (RT_SUCCESS(rc))
    389                     rc = vboxPopULong((ULONG *)&pIpcMsg->uShowMS);
    390 
     390                VBOXTRAY_IPC_HDR_MAGIC,
     391                VBOXTRAY_IPC_HDR_VERSION,
     392                VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG,
     393                cbPayload
     394            };
     395
     396            /*
     397             * Convert the parametes and put them into the payload structure.
     398             */
     399            pPayload->cchMsg   = cchMsg;
     400            pPayload->cchTitle = cchTitle;
     401            char *psz = &pPayload->szzStrings[0];
     402            int rc = RTUtf16ToUtf8Ex(pMsgEntry->text, RTSTR_MAX, &psz, cchMsg + 1, NULL);
     403            if (RT_SUCCESS(rc))
     404            {
     405                psz = &pPayload->szzStrings[cchMsg + 1];
     406                rc = RTUtf16ToUtf8Ex(pTitleEntry->text, RTSTR_MAX, &psz, cchTitle + 1, NULL);
    391407                if (RT_SUCCESS(rc))
    392408                {
    393                     RTLOCALIPCSESSION hSession = 0;
    394                     rc = vboxConnectToVBoxTray(&hSession);
     409                    rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->uType);
    395410                    if (RT_SUCCESS(rc))
    396411                    {
    397                         VBOXTRAYIPCHEADER ipcHdr = { VBOXTRAY_IPC_HDR_MAGIC, 0 /* Header version */,
    398                                                      VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG, cbMsg };
    399 
    400                         rc = RTLocalIpcSessionWrite(hSession, &ipcHdr, sizeof(ipcHdr));
     412                        rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->cMsTimeout);
    401413                        if (RT_SUCCESS(rc))
    402                             rc = RTLocalIpcSessionWrite(hSession, pIpcMsg, cbMsg);
    403 
    404                         int rc2 = RTLocalIpcSessionClose(hSession);
    405                         if (RT_SUCCESS(rc))
    406                             rc = rc2;
     414                        {
     415                            /*
     416                             * Connect to VBoxTray and send the message.
     417                             */
     418                            RTLOCALIPCSESSION hSession = 0;
     419                            rc = vboxConnectToVBoxTray(&hSession);
     420                            if (RT_SUCCESS(rc))
     421                            {
     422                                rc = RTLocalIpcSessionWrite(hSession, &MsgHdr, sizeof(MsgHdr));
     423                                if (RT_SUCCESS(rc))
     424                                {
     425                                    rc = RTLocalIpcSessionWrite(hSession, pPayload, cbPayload);
     426                                    if (RT_FAILURE(rc))
     427                                        vboxPushVBoxError(stacktop, "Failed to write message payload", rc);
     428                                }
     429                                else
     430                                    vboxPushVBoxError(stacktop, "Failed to write message header", rc);
     431
     432                                int rc2 = RTLocalIpcSessionClose(hSession);
     433                                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     434                                {
     435                                    vboxPushVBoxError(stacktop, "RTLocalIpcSessionClose failed", rc);
     436                                    rc = rc2;
     437                                }
     438                            }
     439                            else
     440                                vboxPushVBoxError(stacktop, "vboxConnectToVBoxTray failed", rc);
     441                        }
     442                        else
     443                            vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the timeout value", rc);
    407444                    }
     445                    else
     446                        vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the type value", rc);
    408447                }
    409 
    410                 RTMemFree(pIpcMsg);
     448                else
     449                    vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the title text", rc);
    411450            }
    412451            else
    413                 rc = VERR_NO_MEMORY;
    414 #ifdef UNICODE
    415             RTStrFree(pszMsgUtf8);
    416             RTStrFree(pszTitleUtf8);
    417 #endif
     452                vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the message text", rc);
    418453        }
     454        else
     455            VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Out of memory!");
    419456    }
    420 
    421     vboxPushRcAsString(rc);
     457    else
     458        VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Too few parameters on the stack!");
     459    vboxFreeStackEntry(pTimeoutEntry);
     460    vboxFreeStackEntry(pTypeEntry);
     461    vboxFreeStackEntry(pTitleEntry);
     462    vboxFreeStackEntry(pMsgEntry);
    422463}
    423464
  • trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/exdll.h

    r82625 r96451  
    6161#endif
    6262
     63#ifndef VBOX
    6364// only include this file from one place in your DLL.
    6465// (it is all static, if you use it in two places it will fail)
     
    6869        g_stacktop=stacktop;      \
    6970        g_variables=variables; }
     71#endif /* !VBOX */
    7072
    7173typedef struct _stack_t
     
    104106} extra_parameters;
    105107
     108#ifndef VBOX
    106109static unsigned int g_stringsize;
    107110static stack_t **g_stacktop;
    108111static TCHAR *g_variables;
     112#endif
    109113
    110114enum
     
    137141__INST_LAST
    138142};
     143
     144#ifndef VBOX
    139145
    140146// utility functions (not required but often useful)
     
    173179        lstrcpy(g_variables + varnum*g_stringsize, var);
    174180}
     181
     182#endif /* ! VBOX */
     183
    175184#endif /* !GA_INCLUDED_SRC_WINNT_Installer_InstallHelper_exdll_h */
  • trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/testcase/tstWinAdditionsInstallHelper.cpp

    r96407 r96451  
    3131*********************************************************************************************************************************/
    3232#include <iprt/win/windows.h>
    33 
    34 #include <tchar.h>
    35 
    36 #pragma warning(push)
    37 #pragma warning(disable: 4995) /* warning C4995: 'lstrcpyA': name was marked as #pragma deprecated */
    3833#include "../exdll.h"
    39 #pragma warning(pop)
    4034
    4135#include <iprt/assert.h>
     
    4943
    5044
    51 RT_C_DECLS_BEGIN
    52 
    53 /** A generic NSIS plugin function. */
    54 typedef void __cdecl NSIS_PLUGIN_FUNC(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra);
    55 /** Pointer to a generic NSIS plugin function. */
    56 typedef NSIS_PLUGIN_FUNC *PNSIS_PLUGIN_FUNC;
    57 
    58 RT_C_DECLS_END
    59 
     45/*********************************************************************************************************************************
     46*   Defined Constants And Macros                                                                                                 *
     47*********************************************************************************************************************************/
    6048/** Symbol names to test. */
    6149#define TST_FILEGETARCHITECTURE_NAME   "FileGetArchitecture"
     
    6452
    6553
     54/*********************************************************************************************************************************
     55*   Structures and Typedefs                                                                                                      *
     56*********************************************************************************************************************************/
     57/** A generic NSIS plugin function. */
     58typedef void __cdecl NSIS_PLUGIN_FUNC(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop, extra_parameters *extra);
     59/** Pointer to a generic NSIS plugin function. */
     60typedef NSIS_PLUGIN_FUNC *PNSIS_PLUGIN_FUNC;
     61
     62
     63
    6664/**
    6765 * Destroys a stack.
     
    8482 * @returns VBox status code.
    8583 * @param   ppStackTop          Stack to push string to.
    86  * @param   pcszString          String to push to the stack.
    87  */
    88 static int tstStackPushString(stack_t **ppStackTop, const TCHAR *pcszString)
    89 {
    90     int rc = VINF_SUCCESS;
    91 
    92     /* Termination space is part of stack_t. */
    93     stack_t *pStack = (stack_t *)GlobalAlloc(GPTR, sizeof(stack_t) + g_stringsize);
     84 * @param   pwszString          String to push to the stack.
     85 */
     86static int tstStackPushString(stack_t **ppStackTop, const WCHAR *pwszString)
     87{
     88    size_t cwcString = RTUtf16Len(pwszString);
     89    stack_t *pStack = (stack_t *)GlobalAlloc(GPTR, RT_UOFFSETOF_DYN(stack_t, text[cwcString + 1]));
    9490    if (pStack)
    9591    {
    96         lstrcpyn(pStack->text, pcszString, (int)g_stringsize);
     92        AssertCompile(sizeof(pStack->text[0]) == sizeof(*pwszString));
     93        memcpy(pStack->text, pwszString, (cwcString + 1) * sizeof(pStack->text[0]));
    9794        pStack->next = ppStackTop ? *ppStackTop : NULL;
    9895
    9996        *ppStackTop = pStack;
    100     }
    101     else
    102         rc = VERR_NO_MEMORY;
    103 
    104     return rc;
     97        return VINF_SUCCESS;
     98    }
     99    return VERR_NO_MEMORY;
    105100}
    106101
     
    108103 * Pops a string off a stack.
    109104 *
    110  * @returns Allocated string popped off the stack, or NULL on error / empty stack.
    111  * @param   ppStackTop          Stack to pop off string from.
    112  */
    113 static int tstStackPopString(stack_t **ppStackTop, TCHAR *pszStr, size_t cchStr)
     105 * @returns IPRT status code.
     106 * @param   ppStackTop      Stack to pop off string from.
     107 * @param   pwszDst         Where to return the string.
     108 * @param   cwcDst          The size of the destination buffer.
     109 */
     110static int tstStackPopString(stack_t **ppStackTop, WCHAR *pwszDst, size_t cwcDst)
    114111{
    115112    stack_t *pStack = *ppStackTop;
    116     lstrcpyn(pszStr, pStack->text, cchStr);
    117     *ppStackTop = pStack->next;
    118     GlobalFree((HGLOBAL)pStack);
    119 
    120     return VINF_SUCCESS;
    121 }
    122 
    123 int main()
     113    if (pStack)
     114    {
     115        int rc = RTUtf16Copy(pwszDst, cwcDst, pStack->text);
     116
     117        *ppStackTop = pStack->next;
     118        GlobalFree((HGLOBAL)pStack);
     119
     120        return rc;
     121    }
     122    return VERR_NOT_FOUND;
     123}
     124
     125int main(int argc, char **argv)
    124126{
    125127    RTTEST hTest;
    126     RTEXITCODE rcExit = RTTestInitAndCreate("tstWinAdditionsInstallHelper", &hTest);
     128    RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0, "tstWinAdditionsInstallHelper", &hTest);
    127129    if (rcExit != RTEXITCODE_SUCCESS)
    128130        return rcExit;
     
    130132
    131133    char szGuestInstallHelperDll[RTPATH_MAX];
    132     RTProcGetExecutablePath(szGuestInstallHelperDll, sizeof(szGuestInstallHelperDll));
    133 
    134     /* Set the default string size. */
    135     g_stringsize = NSIS_MAX_STRLEN;
     134    RTPathExecDir(szGuestInstallHelperDll, sizeof(szGuestInstallHelperDll));
    136135
    137136    /** @todo This ASSUMES that this testcase always is located in the separate "bin/additions" sub directory
     
    139138     *        Might need some more tweaking ... */
    140139    int rc = RTPathAppend(szGuestInstallHelperDll, sizeof(szGuestInstallHelperDll),
    141                           "../../../repack/resources/VBoxGuestInstallHelper/VBoxGuestInstallHelper.dll");
     140                          "..\\..\\repackadd\\resources\\VBoxGuestInstallHelper\\VBoxGuestInstallHelper.dll");
    142141    if (RT_SUCCESS(rc))
    143142    {
    144143        RTTestIPrintf(RTTESTLVL_ALWAYS, "Using DLL: %s\n", szGuestInstallHelperDll);
    145 
    146 #ifdef UNICODE
    147         const bool fUnicode = true;
    148 #else
    149         const bool fUnicode = false;
    150 #endif
    151         RTTestIPrintf(RTTESTLVL_ALWAYS, "Running %s build\n", fUnicode ? "UNICODE" : "ANSI");
    152144
    153145        RTLDRMOD hLdrMod;
     
    155147        if (RT_SUCCESS(rc))
    156148        {
    157             TCHAR szVars[NSIS_MAX_STRLEN * sizeof(TCHAR)] = { 0 };
     149            WCHAR wszVars[NSIS_MAX_STRLEN * sizeof(WCHAR)] = { 0 };
     150            WCHAR wszResult[NSIS_MAX_STRLEN];
    158151
    159152            /*
     
    165158            {
    166159                stack_t *pStack = NULL;
    167                 tstStackPushString(&pStack, _T("c:\\windows\\system32\\kernel32.dll"));
    168 
    169                 pfnFileGetArchitecture(NULL /* hWnd */, NSIS_MAX_STRLEN, szVars, &pStack, NULL /* extra */);
    170 
    171                 TCHAR szStack[NSIS_MAX_STRLEN];
    172                 rc = tstStackPopString(&pStack, szStack, sizeof(szStack));
     160                tstStackPushString(&pStack, L"c:\\windows\\system32\\kernel32.dll");
     161
     162                pfnFileGetArchitecture(NULL /* hWnd */, NSIS_MAX_STRLEN, wszVars, &pStack, NULL /* extra */);
     163
     164                rc = tstStackPopString(&pStack, wszResult, sizeof(wszResult));
    173165                if (   RT_SUCCESS(rc)
    174                     && (   !_tcscmp(szStack, _T("x86"))
    175                         || !_tcscmp(szStack, _T("amd64"))))
    176                 {
    177                     if (fUnicode)
    178                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Arch: %ls\n", szStack);
    179                     else
    180                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Arch: %s\n", szStack);
    181                 }
     166                    && (   RTUtf16CmpAscii(wszResult, "x86") == 0
     167                        || RTUtf16CmpAscii(wszResult, "amd64") == 0))
     168                    RTTestIPrintf(RTTESTLVL_ALWAYS, "Arch: %ls\n", wszResult);
    182169                else
    183                     RTTestIFailed("Getting file arch failed (NSIS API changed?)\n");
     170                    RTTestIFailed("Getting file arch on kernel32 failed: %Rrc - '%ls', expected 'x86' or 'amd64'", rc, wszResult);
     171
     172                if (pStack)
     173                    RTTestIFailed("Too many items on the stack!");
    184174                tstStackDestroy(pStack);
    185175            }
     
    191181             */
    192182            PNSIS_PLUGIN_FUNC pfnFileGetVendor;
    193             rc = RTLdrGetSymbol(hLdrMod, TST_FILEGETVENDOR_NAME, (void**)&pfnFileGetVendor);
     183            rc = RTLdrGetSymbol(hLdrMod, TST_FILEGETVENDOR_NAME, (void **)&pfnFileGetVendor);
    194184            if (RT_SUCCESS(rc))
    195185            {
    196186                stack_t *pStack = NULL;
    197                 tstStackPushString(&pStack, _T("c:\\windows\\system32\\kernel32.dll"));
    198 
    199                 pfnFileGetVendor(NULL /* hWnd */, NSIS_MAX_STRLEN, szVars, &pStack, NULL /* extra */);
    200 
    201                 TCHAR szStack[NSIS_MAX_STRLEN];
    202                 rc = tstStackPopString(&pStack, szStack, RT_ELEMENTS(szStack));
     187                tstStackPushString(&pStack, L"c:\\windows\\system32\\kernel32.dll");
     188
     189                pfnFileGetVendor(NULL /* hWnd */, NSIS_MAX_STRLEN, wszVars, &pStack, NULL /* extra */);
     190
     191                rc = tstStackPopString(&pStack, wszResult, RT_ELEMENTS(wszResult));
    203192                if (   RT_SUCCESS(rc)
    204                     && !_tcscmp(szStack, _T("Microsoft Corporation")))
    205                 {
    206                     if (fUnicode)
    207                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Vendor: %ls\n", szStack);
    208                     else
    209                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Vendor: %s\n", szStack);
    210                 }
     193                    && RTUtf16CmpAscii(wszResult, "Microsoft Corporation") == 0)
     194                    RTTestIPrintf(RTTESTLVL_ALWAYS, "Vendor: %ls\n", wszResult);
    211195                else
    212                     RTTestIFailed("Getting file vendor failed (NSIS API changed?)\n");
     196                    RTTestIFailed("Getting file vendor failed: %Rrc - '%ls', expected 'Microsoft Corporation'\n", rc, wszResult);
     197
     198                if (pStack)
     199                    RTTestIFailed("Too many items on the stack!");
    213200                tstStackDestroy(pStack);
    214201            }
     
    225212                stack_t *pStack = NULL;
    226213                /* Push stuff in reverse order to the stack. */
    227                 tstStackPushString(&pStack, _T("5000") /* Time to show in ms */);
    228                 tstStackPushString(&pStack, _T("1") /* Type */);
    229                 tstStackPushString(&pStack, _T("This is a message from tstWinAdditionsInstallHelper!"));
    230                 tstStackPushString(&pStack, _T("This is a title from tstWinAdditionsInstallHelper!"));
    231 
    232                 pfnVBoxTrayShowBallonMsg(NULL /* hWnd */, NSIS_MAX_STRLEN, szVars, &pStack, NULL /* extra */);
    233 
    234                 TCHAR szStack[NSIS_MAX_STRLEN];
    235                 rc = tstStackPopString(&pStack, szStack, RT_ELEMENTS(szStack));
     214                tstStackPushString(&pStack, L"5000" /* Time to show in ms */);
     215                tstStackPushString(&pStack, L"1" /* Type - info */);
     216                tstStackPushString(&pStack, L"This is a message from tstWinAdditionsInstallHelper!");
     217                tstStackPushString(&pStack, L"This is a title from tstWinAdditionsInstallHelper!");
     218
     219                pfnVBoxTrayShowBallonMsg(NULL /* hWnd */, NSIS_MAX_STRLEN, wszVars, &pStack, NULL /* extra */);
     220
     221                rc = tstStackPopString(&pStack, wszResult, RT_ELEMENTS(wszResult));
    236222                if (RT_SUCCESS(rc))
    237                 {
    238                     if (fUnicode)
    239                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Reply: %ls\n", szStack);
    240                     else
    241                         RTTestIPrintf(RTTESTLVL_ALWAYS, "Reply: %s\n", szStack);
    242                 }
     223                    RTTestIPrintf(RTTESTLVL_ALWAYS, "Reply: '%ls'\n", wszResult);
    243224                else
    244                     RTTestIFailed("Sending message to VBoxTray failed (NSIS API changed?)\n");
     225                    RTTestIFailed("Sending message to VBoxTray failed: stack pop error - %Rrc", rc);
     226
     227                if (pStack)
     228                    RTTestIFailed("Too many items on the stack!");
    245229                tstStackDestroy(pStack);
    246230            }
  • trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsLog.nsh

    r96407 r96451  
    7373    ; - String: Description / Body
    7474    ; - String: Title / Name of application
    75     ; - Integer: Type of message: 0 (Info), 1 (Warning), 2 (Error)
     75    ; - Integer: Type of message: 1 (Info), 2 (Warning), 3 (Error)
    7676    ; - Integer: Time (in msec) to show the notification
    7777    VBoxGuestInstallHelper::VBoxTrayShowBallonMsg "${text}" "VirtualBox Guest Additions Setup" ${type} 5000
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp

    r96407 r96451  
    107107
    108108
     109/**
     110 * Handles VBOXTRAYIPCMSGTYPE_RESTART.
     111 */
    109112static int vboxIPCHandleVBoxTrayRestart(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr)
    110113{
    111     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    112     AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
     114    RT_NOREF(pSession, pHdr);
    113115
    114116    /** @todo Not implemented yet; don't return an error here. */
     
    116118}
    117119
     120/**
     121 * Handles VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG.
     122 */
    118123static int vboxIPCHandleShowBalloonMsg(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr)
    119124{
    120     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    121     AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
    122     AssertReturn(pHdr->uMsgLen > 0, VERR_INVALID_PARAMETER);
    123 
    124     VBOXTRAYIPCMSG_SHOWBALLOONMSG ipcMsg;
    125     int rc = RTLocalIpcSessionRead(pSession->hSession, &ipcMsg, pHdr->uMsgLen,
    126                                    NULL /* Exact read, blocking */);
    127     if (RT_SUCCESS(rc))
    128     {
    129         /* Showing the balloon tooltip is not critical. */
    130         int rc2 = hlpShowBalloonTip(g_hInstance, g_hwndToolWindow, ID_TRAYICON,
    131                                     ipcMsg.szMsgContent, ipcMsg.szMsgTitle,
    132                                     ipcMsg.uShowMS, ipcMsg.uType);
    133         LogFlowFunc(("Showing \"%s\" - \"%s\" (type %RU32, %RU32ms), rc=%Rrc\n",
    134                      ipcMsg.szMsgTitle, ipcMsg.szMsgContent,
    135                      ipcMsg.uType, ipcMsg.uShowMS, rc2));
    136         NOREF(rc2);
    137     }
    138 
    139     return rc;
    140 }
    141 
     125    /*
     126     * Unmarshal and validate the data.
     127     */
     128    union
     129    {
     130        uint8_t                             abBuf[_4K];
     131        VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T   s;
     132    } Payload;
     133    AssertReturn(pHdr->cbPayload >= RT_UOFFSETOF_DYN(VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T, szzStrings[2]), VERR_INVALID_PARAMETER);
     134    AssertReturn(pHdr->cbPayload < sizeof(Payload), VERR_BUFFER_OVERFLOW);
     135
     136    int rc = RTLocalIpcSessionRead(pSession->hSession, &Payload, pHdr->cbPayload, NULL /*pcbRead - exact, blocking*/);
     137    if (RT_FAILURE(rc))
     138        return rc;
     139
     140    /* String lengths: */
     141    AssertReturn(   Payload.s.cchMsg + 1 + Payload.s.cchTitle + 1 + RT_UOFFSETOF(VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T, szzStrings)
     142                 <= pHdr->cbPayload, VERR_INVALID_PARAMETER);
     143
     144    /* Message text: */
     145    const char *pszMsg   = Payload.s.szzStrings;
     146    rc = RTStrValidateEncodingEx(pszMsg, Payload.s.cchMsg + 1,
     147                                 RTSTR_VALIDATE_ENCODING_EXACT_LENGTH | RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     148    AssertRCReturn(rc, rc);
     149
     150    /* Title text: */
     151    const char *pszTitle = &Payload.s.szzStrings[Payload.s.cchMsg + 1];
     152    rc = RTStrValidateEncodingEx(pszMsg, Payload.s.cchTitle + 1,
     153                                 RTSTR_VALIDATE_ENCODING_EXACT_LENGTH | RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     154    AssertRCReturn(rc, rc);
     155
     156    /* Type/dwInfoFlags: */
     157    AssertReturn(   Payload.s.uType == NIIF_NONE
     158                 || Payload.s.uType == NIIF_INFO
     159                 || Payload.s.uType == NIIF_WARNING
     160                 || Payload.s.uType == NIIF_ERROR,
     161                 VERR_WRONG_TYPE);
     162
     163    /* Timeout: */
     164    if (!Payload.s.cMsTimeout)
     165        Payload.s.cMsTimeout = RT_MS_5SEC;
     166    AssertStmt(Payload.s.cMsTimeout >= RT_MS_1SEC, Payload.s.cMsTimeout = RT_MS_1SEC);
     167    AssertStmt(Payload.s.cMsTimeout <= RT_MS_1MIN, Payload.s.cMsTimeout = RT_MS_1MIN);
     168
     169    /*
     170     * Showing the balloon tooltip is not critical.
     171     */
     172    int rc2 = hlpShowBalloonTip(g_hInstance, g_hwndToolWindow, ID_TRAYICON,
     173                                pszMsg, pszTitle, Payload.s.cMsTimeout, Payload.s.uType);
     174    LogFlowFunc(("Showing \"%s\" - \"%s\" (type %RU32, %RU32ms), rc=%Rrc\n",
     175                 pszTitle, pszMsg, Payload.s.cMsTimeout, Payload.s.uType, rc2));
     176    RT_NOREF_PV(rc2);
     177
     178    return VINF_SUCCESS;
     179}
     180
     181/**
     182 * Handles VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT.
     183 */
    142184static int vboxIPCHandleUserLastInput(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr)
    143185{
    144     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    145     AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
    146     /* No actual message from client. */
     186    RT_NOREF(pHdr);
    147187
    148188    int rc = VINF_SUCCESS;
    149 
    150     bool fLastInputAvailable = false;
    151     VBOXTRAYIPCRES_USERLASTINPUT ipcRes;
     189    VBOXTRAYIPCREPLY_USER_LAST_INPUT_T Reply = { UINT32_MAX };
    152190    if (g_pfnGetLastInputInfo)
    153191    {
    154         /* Note: This only works up to 49.7 days (= 2^32, 32-bit counter)
    155            since Windows was started. */
    156         LASTINPUTINFO lastInput;
    157         lastInput.cbSize = sizeof(LASTINPUTINFO);
    158         BOOL fRc = g_pfnGetLastInputInfo(&lastInput);
    159         if (fRc)
    160         {
    161             ipcRes.uLastInput = (GetTickCount() - lastInput.dwTime) / 1000;
    162             fLastInputAvailable = true;
    163         }
     192        /* Note: This only works up to 49.7 days (= 2^32, 32-bit counter) since Windows was started. */
     193        LASTINPUTINFO LastInput;
     194        LastInput.cbSize = sizeof(LastInput);
     195        if (g_pfnGetLastInputInfo(&LastInput))
     196            Reply.cSecSinceLastInput = (GetTickCount() - LastInput.dwTime) / 1000;
    164197        else
    165198            rc = RTErrConvertFromWin32(GetLastError());
    166199    }
    167200
    168     if (!fLastInputAvailable)
    169     {
    170         /* No last input available. */
    171         ipcRes.uLastInput = UINT32_MAX;
    172     }
    173 
    174     int rc2 = RTLocalIpcSessionWrite(pSession->hSession, &ipcRes, sizeof(ipcRes));
     201    int rc2 = RTLocalIpcSessionWrite(pSession->hSession, &Reply, sizeof(Reply));
    175202    if (RT_SUCCESS(rc))
    176203        rc = rc2;
     
    355382        /* The next call will be cancelled via VBoxIPCStop if needed. */
    356383        rc = RTLocalIpcSessionWaitForData(hSession, RT_INDEFINITE_WAIT);
    357         if (RT_FAILURE(rc))
    358         {
    359             if (rc == VERR_CANCELLED)
    360             {
    361                 LogFlowFunc(("Session %p: Waiting for data cancelled\n", pThis));
    362                 rc = VINF_SUCCESS;
     384        if (RT_SUCCESS(rc))
     385        {
     386            /*
     387             * Read the message header.
     388             */
     389            VBOXTRAYIPCHEADER Hdr = {0};
     390            rc = RTLocalIpcSessionRead(hSession, &Hdr, sizeof(Hdr), NULL /*pcbRead - exact, blocking*/);
     391            if (RT_FAILURE(rc))
    363392                break;
    364             }
    365             else
    366                 LogFlowFunc(("Session %p: Waiting for session data failed with rc=%Rrc\n",
    367                          pThis, rc));
     393
     394            /*
     395             * Validate the message header.
     396             *
     397             * Disconnecting the client if invalid or something we don't grok.
     398             * Currently all clients are one-shots, so there is no need to get
     399             * in complicated recovery code if we don't understand one another.
     400             */
     401            if (   Hdr.uMagic   != VBOXTRAY_IPC_HDR_MAGIC
     402                || Hdr.uVersion != VBOXTRAY_IPC_HDR_VERSION)
     403            {
     404                LogRelFunc(("Session %p: Invalid header magic/version: %#x, %#x, %#x, %#x\n",
     405                            Hdr.uMagic, Hdr.uVersion, Hdr.enmMsgType, Hdr.cbPayload));
     406                rc = VERR_INVALID_MAGIC;
     407                break;
     408            }
     409            if (Hdr.cbPayload > VBOXTRAY_IPC_MAX_PAYLOAD)
     410            {
     411                LogRelFunc(("Session %p: Payload to big: %#x, %#x, %#x, %#x - max %#x\n",
     412                            Hdr.uMagic, Hdr.uVersion, Hdr.enmMsgType, Hdr.cbPayload, VBOXTRAY_IPC_MAX_PAYLOAD));
     413                rc = VERR_TOO_MUCH_DATA;
     414                break;
     415            }
     416            if (   Hdr.enmMsgType > VBOXTRAYIPCMSGTYPE_INVALID
     417                && Hdr.enmMsgType < VBOXTRAYIPCMSGTYPE_END)
     418            {
     419                LogRelFunc(("Session %p: Unknown message: %#x, %#x, %#x, %#x\n",
     420                            Hdr.uMagic, Hdr.uVersion, Hdr.enmMsgType, Hdr.cbPayload));
     421                rc = VERR_INVALID_FUNCTION;
     422                break;
     423            }
     424
     425            /*
     426             * Handle the message.
     427             */
     428            switch (Hdr.enmMsgType)
     429            {
     430                case VBOXTRAYIPCMSGTYPE_RESTART:
     431                    rc = vboxIPCHandleVBoxTrayRestart(pThis, &Hdr);
     432                    break;
     433
     434                case VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG:
     435                    rc = vboxIPCHandleShowBalloonMsg(pThis, &Hdr);
     436                    break;
     437
     438                case VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT:
     439                    rc = vboxIPCHandleUserLastInput(pThis, &Hdr);
     440                    break;
     441
     442                default:
     443                    AssertFailedBreakStmt(rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE);
     444            }
     445            if (RT_FAILURE(rc))
     446                LogFlowFunc(("Session %p: Handling command %RU32 failed with rc=%Rrc\n", pThis, Hdr.enmMsgType, rc));
     447        }
     448        else if (rc == VERR_CANCELLED)
     449        {
     450            LogFlowFunc(("Session %p: Waiting for data cancelled\n", pThis));
     451            rc = VINF_SUCCESS;
     452            break;
    368453        }
    369454        else
    370         {
    371             VBOXTRAYIPCHEADER ipcHdr;
    372             rc = RTLocalIpcSessionRead(hSession, &ipcHdr, sizeof(ipcHdr),
    373                                        NULL /* Exact read, blocking */);
    374             bool fRejected = false; /* Reject current command? */
    375             if (RT_SUCCESS(rc))
    376                 fRejected =    ipcHdr.uMagic != VBOXTRAY_IPC_HDR_MAGIC
    377                             || ipcHdr.uHdrVersion != 0; /* We only know version 0 commands for now. */
    378 
    379             if (   !fRejected
    380                 && RT_SUCCESS(rc))
    381             {
    382                 switch (ipcHdr.uMsgType)
    383                 {
    384                     case VBOXTRAYIPCMSGTYPE_RESTART:
    385                         rc = vboxIPCHandleVBoxTrayRestart(pThis, &ipcHdr);
    386                         break;
    387 
    388                     case VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG:
    389                         rc = vboxIPCHandleShowBalloonMsg(pThis, &ipcHdr);
    390                         break;
    391 
    392                     case VBOXTRAYIPCMSGTYPE_USERLASTINPUT:
    393                         rc = vboxIPCHandleUserLastInput(pThis, &ipcHdr);
    394                         break;
    395 
    396                     default:
    397                     {
    398                         /* Unknown command, reject. */
    399                         fRejected = true;
    400                         break;
    401                     }
    402                 }
    403 
    404                 if (RT_FAILURE(rc))
    405                     LogFlowFunc(("Session %p: Handling command %RU32 failed with rc=%Rrc\n",
    406                              pThis, ipcHdr.uMsgType, rc));
    407             }
    408 
    409             if (fRejected)
    410             {
    411                 static int s_cRejectedCmds = 0;
    412                 if (++s_cRejectedCmds <= 3)
    413                 {
    414                     LogRelFunc(("Session %p: Received invalid/unknown command %RU32 (%RU32 bytes), rejecting (%RU32/3)\n",
    415                                 pThis, ipcHdr.uMsgType, ipcHdr.uMsgLen, s_cRejectedCmds + 1));
    416                     if (ipcHdr.uMsgLen)
    417                     {
    418                         /* Get and discard payload data. */
    419                         size_t cbRead;
    420                         uint8_t devNull[_1K];
    421                         while (ipcHdr.uMsgLen)
    422                         {
    423                             rc = RTLocalIpcSessionRead(hSession, &devNull, sizeof(devNull), &cbRead);
    424                             if (RT_FAILURE(rc))
    425                                 break;
    426                             AssertRelease(cbRead <= ipcHdr.uMsgLen);
    427                             ipcHdr.uMsgLen -= (uint32_t)cbRead;
    428                         }
    429                     }
    430                 }
    431                 else
    432                     rc = VERR_INVALID_PARAMETER; /* Enough fun, bail out. */
    433             }
    434         }
    435     }
    436 
    437     LogFlowFunc(("Session %p: Handler ended with rc=%Rrc\n",
    438              pThis, rc));
     455            LogFlowFunc(("Session %p: Waiting for session data failed with rc=%Rrc\n", pThis, rc));
     456    }
     457
     458    LogFlowFunc(("Session %p: Handler ended with rc=%Rrc\n", pThis, rc));
    439459
    440460    /*
     
    461481    }
    462482
    463     LogFlowFunc(("Session %p: Terminated with rc=%Rrc, freeing ...\n",
    464              pThis, rc));
     483    LogFlowFunc(("Session %p: Terminated with rc=%Rrc, freeing ...\n", pThis, rc));
    465484
    466485    RTMemFree(pThis);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTrayMsg.h

    r96407 r96451  
    3434/** The IPC pipe's prefix (native).
    3535 * Will be followed by the username VBoxTray runs under. */
    36 #define VBOXTRAY_IPC_PIPE_PREFIX      "\\\\.\\pipe\\VBoxTrayIPC-"
     36#define VBOXTRAY_IPC_PIPE_PREFIX        "\\\\.\\pipe\\VBoxTrayIPC-"
    3737/** The IPC header's magic. */
    38 #define VBOXTRAY_IPC_HDR_MAGIC        0x19840804
     38#define VBOXTRAY_IPC_HDR_MAGIC          0x19840804
     39/** IPC header version number. */
     40#define VBOXTRAY_IPC_HDR_VERSION        1
     41/** The max payload size accepted by VBoxTray.  Clients trying to send more
     42 *  will be disconnected. */
     43#define VBOXTRAY_IPC_MAX_PAYLOAD        _16K
    3944
    40 enum VBOXTRAYIPCMSGTYPE
     45
     46/**
     47 * VBoxTray IPC message types.
     48 */
     49typedef enum VBOXTRAYIPCMSGTYPE
    4150{
    42     /** Restarts VBoxTray. */
    43     VBOXTRAYIPCMSGTYPE_RESTART        = 10,
    44     /** Shows a balloon message in the tray area. */
    45     VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG = 100,
    46     /** Retrieves the current user's last input
    47      *  time. This will be the user VBoxTray is running
    48      *  under. No actual message for this command
    49      *  required. */
    50     VBOXTRAYIPCMSGTYPE_USERLASTINPUT  = 120
    51 };
     51    /** Customary invalid zero value. */
     52    VBOXTRAYIPCMSGTYPE_INVALID = 0,
     53    /** Restarts VBoxTray - not implemented.
     54     * Payload: None.
     55     * Reply: None. */
     56    VBOXTRAYIPCMSGTYPE_RESTART,
     57    /** Shows a balloon message in the tray area.
     58     * Payload: VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T
     59     * Reply: None */
     60    VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG,
     61    /** Time since the last user input for the user VBoxTray is running as.
     62     * Payload: None.
     63     * Reply: VBOXTRAYIPCREPLY_USER_LAST_INPUT_T. */
     64    VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT,
     65    /** End of valid types. */
     66    VBOXTRAYIPCMSGTYPE_END,
     67    /* Make sure the type is 32-bit wide. */
     68    VBOXTRAYIPCMSGTYPE_32BIT_HACK = 0x7fffffff
     69} VBOXTRAYIPCMSGTYPE;
    5270
    53 /* VBoxTray's IPC header. */
     71/**
     72 * VBoxTray's IPC header.
     73 *
     74 * All messages have one of these.  The payload following it is optional and
     75 * specific to each individual message type.
     76 */
    5477typedef struct VBOXTRAYIPCHEADER
    5578{
    56     /** The header's magic. */
    57     uint32_t uMagic;
     79    /** The header's magic (VBOXTRAY_IPC_HDR_MAGIC). */
     80    uint32_t            uMagic;
    5881    /** Header version, must be 0 by now. */
    59     uint32_t uHdrVersion;
    60     /** Message type. Specifies a message
    61      *  of VBOXTRAYIPCMSGTYPE. */
    62     uint32_t uMsgType;
    63     /** Message length (in bytes). This must
    64      *  include the overall message length, including
    65      *  (eventual) dynamically allocated areas which
    66      *  are passed into the message structure.
    67      */
    68     uint32_t uMsgLen;
    69 
    70 } VBOXTRAYIPCHEADER, *PVBOXTRAYIPCHEADER;
     82    uint32_t            uVersion;
     83    /** Message type, a VBOXTRAYIPCMSGTYPE value. */
     84    VBOXTRAYIPCMSGTYPE  enmMsgType;
     85    /** Payload length in bytes.
     86     * When present, the payload follows this header. */
     87    uint32_t            cbPayload;
     88} VBOXTRAYIPCHEADER;
     89/** Pointer to a VBoxTray IPC header. */
     90typedef VBOXTRAYIPCHEADER *PVBOXTRAYIPCHEADER;
    7191
    7292/**
    73  * Tells VBoxTray to show a balloon message in Windows'
    74  * tray area. This may or may not work depending on the
    75  * system's configuration / set user preference.
     93 * Tells VBoxTray to show a balloon message in Windows' tray area.
     94 *
     95 * This may or may not work depending on the system's configuration / set user
     96 * preference.
    7697 */
    77 typedef struct VBOXTRAYIPCMSG_SHOWBALLOONMSG
     98typedef struct VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T
    7899{
    79     /** Length of message body (in bytes). */
    80     uint32_t cbMsgContent;
    81     /** Length of message title (in bytes). */
    82     uint32_t cbMsgTitle;
     100    /** Length of the message string (no terminator). */
     101    uint32_t    cchMsg;
     102    /** Length of the title string (no terminator). */
     103    uint32_t    cchTitle;
    83104    /** Message type. */
    84     uint32_t uType;
     105    uint32_t    uType;
    85106    /** Time to show the message (in ms). */
    86     uint32_t uShowMS;
    87     /** Dynamically allocated stuff.
    88      *
    89      *  Note: These must come at the end of the
    90      *  structure to not overwrite any important
    91      *  stuff above.
    92      */
    93     /** Message body. Can be up to 256 chars
    94      *  long. */
    95     char     szMsgContent[1];
    96         /** Message title. Can be up to 73 chars
    97      *  long. */
    98     char     szMsgTitle[1];
    99 } VBOXTRAYIPCMSG_SHOWBALLOONMSG, *PVBOXTRAYIPCMSG_SHOWBALLOONMSG;
     107    uint32_t    cMsTimeout;
     108    /** Variable length buffer containing two szero terminated strings, first is  */
     109    char        szzStrings[RT_FLEXIBLE_ARRAY];
     110} VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T;
     111typedef VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T *PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T;
    100112
    101113/**
    102  * Response telling the last input of the current user.
     114 * Reply to VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT
    103115 */
    104 typedef struct VBOXTRAYIPCRES_USERLASTINPUT
     116typedef struct VBOXTRAYIPCREPLY_USER_LAST_INPUT_T
    105117{
    106     /** Last occurred user input event (in seconds). */
    107     uint32_t uLastInput;
    108 } VBOXTRAYIPCRES_USERLASTINPUT, *PVBOXTRAYIPCRES_USERLASTINPUT;
     118    /** How many seconds since the last user input event.
     119     * Set to UINT32_MAX if we don't know. */
     120    uint32_t    cSecSinceLastInput;
     121} VBOXTRAYIPCREPLY_USER_LAST_INPUT_T;
     122typedef VBOXTRAYIPCREPLY_USER_LAST_INPUT_T *PVBOXTRAYIPCREPLY_USER_LAST_INPUT_T;
    109123
    110124#endif /* !GA_INCLUDED_SRC_WINNT_VBoxTray_VBoxTrayMsg_h */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp

    r96407 r96451  
    5858#include "../../WINNT/VBoxTray/VBoxTrayMsg.h" /* For IPC. */
    5959
    60 static uint32_t s_uDebugGuestPropClientID = 0;
    61 static uint32_t s_uDebugIter = 0;
    62 /** Whether to skip the logged-in user detection over RDP or not.
    63  *  See notes in this section why we might want to skip this. */
    64 static bool s_fSkipRDPDetection = false;
    65 
    6660
    6761/*********************************************************************************************************************************
     
    117111*   Global Variables                                                                                                             *
    118112*********************************************************************************************************************************/
     113static uint32_t s_uDebugGuestPropClientID = 0;
     114static uint32_t s_uDebugIter = 0;
     115/** Whether to skip the logged-in user detection over RDP or not.
     116 *  See notes in this section why we might want to skip this. */
     117static bool s_fSkipRDPDetection = false;
     118
    119119static RTONCE                                   g_vgsvcWinVmInitOnce = RTONCE_INITIALIZER;
    120120
     
    984984            {
    985985                /* .uMagic      = */ VBOXTRAY_IPC_HDR_MAGIC,
    986                 /* .uHdrVersion = */ 0,
    987                 /* .uMsgType    = */ VBOXTRAYIPCMSGTYPE_USERLASTINPUT,
    988                 /* .cbMsgData   = */ 0 /* No msg */
     986                /* .uVersion    = */ VBOXTRAY_IPC_HDR_VERSION,
     987                /* .enmMsgType  = */ VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT,
     988                /* .cbPayload   = */ 0 /* No payload */
    989989            };
    990990
    991991            rc = RTLocalIpcSessionWrite(hSession, &ipcHdr, sizeof(ipcHdr));
    992 
    993992            if (RT_SUCCESS(rc))
    994993            {
    995                 VBOXTRAYIPCRES_USERLASTINPUT ipcRes;
    996                 rc = RTLocalIpcSessionRead(hSession, &ipcRes, sizeof(ipcRes), NULL /* Exact read */);
     994                VBOXTRAYIPCREPLY_USER_LAST_INPUT_T ipcReply;
     995                rc = RTLocalIpcSessionRead(hSession, &ipcReply, sizeof(ipcReply), NULL /* Exact read */);
    997996                if (   RT_SUCCESS(rc)
    998997                    /* If uLastInput is set to UINT32_MAX VBoxTray was not able to retrieve the
    999998                     * user's last input time. This might happen when running on Windows NT4 or older. */
    1000                     && ipcRes.uLastInput != UINT32_MAX)
     999                    && ipcReply.cSecSinceLastInput != UINT32_MAX)
    10011000                {
    1002                     userState = (ipcRes.uLastInput * 1000) < g_uVMInfoUserIdleThresholdMS
     1001                    userState = ipcReply.cSecSinceLastInput * 1000 < g_uVMInfoUserIdleThresholdMS
    10031002                              ? VBoxGuestUserState_InUse
    10041003                              : VBoxGuestUserState_Idle;
     
    10141013                    fReportToHost = rc == VINF_SUCCESS;
    10151014                    VGSvcVerbose(4, "User '%s' (domain '%s') is idle for %RU32, fReportToHost=%RTbool\n",
    1016                                  pszUser, pszDomain ? pszDomain : "<None>", ipcRes.uLastInput, fReportToHost);
     1015                                 pszUser, pszDomain ? pszDomain : "<None>", ipcReply.cSecSinceLastInput, fReportToHost);
    10171016
    10181017#if 0 /* Do we want to write the idle time as well? */
    10191018                        /* Also write the user's current idle time, if there is any. */
    10201019                        if (userState == VBoxGuestUserState_Idle)
    1021                             rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", "%RU32", ipcRes.uLastInputMs);
     1020                            rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", "%RU32", ipcReply.cSecSinceLastInput);
    10221021                        else
    10231022                            rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", NULL /* Delete property */);
     
    10271026                }
    10281027#ifdef DEBUG
    1029                 else if (RT_SUCCESS(rc) && ipcRes.uLastInput == UINT32_MAX)
     1028                else if (RT_SUCCESS(rc) && ipcReply.cSecSinceLastInput == UINT32_MAX)
    10301029                    VGSvcVerbose(4, "Last input for user '%s' is not supported, skipping\n", pszUser, rc);
    10311030#endif
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