Changeset 96451 in vbox
- Timestamp:
- Aug 24, 2022 9:56:54 AM (2 years ago)
- Location:
- trunk/src/VBox/Additions
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/Makefile.kmk
r96407 r96451 35 35 # NSIS plugins always have to be compiled in 32-bit! 36 36 # 37 # Note! Installation is required for repacking Guest Additions 38 # 37 39 ## @todo kBuild: This needs the WINPSDK fix to work for cross building. 38 40 DLLS.x86 += VBoxGuestInstallHelper 39 VBoxGuestInstallHelper_TEMPLATE = VBoxGuestR3Dll 40 #Installation is required for repacking Guest Additions 41 VBoxGuestInstallHelper_INST = repackadd/resources/VBoxGuestInstallHelper/ 41 VBoxGuestInstallHelper_TEMPLATE := VBoxGuestR3Dll 42 VBoxGuestInstallHelper_INST := repackadd/resources/VBoxGuestInstallHelper/ 42 43 ifdef VBOX_SIGN_ADDITIONS # (See the parent makefile.) 43 VBoxGuestInstallHelper_INSTTYPE = stage44 VBoxGuestInstallHelper_DEBUG_INSTTYPE = both44 VBoxGuestInstallHelper_INSTTYPE := stage 45 VBoxGuestInstallHelper_DEBUG_INSTTYPE := both 45 46 endif 46 VBoxGuestInstallHelper_DEFS = _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1 UNICODE _UNICODE47 VBoxGuestInstallHelper_BLD_TRG_ARCH = x8648 VBoxGuestInstallHelper_SOURCES = \47 VBoxGuestInstallHelper_DEFS := _WIN32_WINNT=0x0400 WIN32_LEAN_AND_MEAN=1 UNICODE _UNICODE 48 VBoxGuestInstallHelper_BLD_TRG_ARCH := x86 49 VBoxGuestInstallHelper_SOURCES := \ 49 50 VBoxGuestInstallHelper.cpp \ 50 51 VBoxGuestInstallHelper.rc -
trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp
r96407 r96451 31 31 * Header Files * 32 32 *********************************************************************************************************************************/ 33 #ifndef UNICODE 34 # define UNICODE 35 #endif 33 36 #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 */39 37 #include "exdll.h" 40 #pragma warning(pop)41 38 42 39 #include <iprt/err.h> … … 47 44 #include <iprt/process.h> 48 45 #include <iprt/string.h> 49 #ifdef UNICODE 50 # include <iprt/utf16.h> 51 #endif 46 #include <iprt/utf16.h> 52 47 53 48 /* Required structures/defines of VBoxTray. */ … … 58 53 * Defined Constants And Macros * 59 54 *********************************************************************************************************************************/ 60 #define VBOXINSTALLHELPER_EXPORT extern "C" void __declspec(dllexport)55 #define VBOXINSTALLHELPER_EXPORT extern "C" DECLEXPORT(void) 61 56 62 57 … … 70 65 * Global Variables * 71 66 *********************************************************************************************************************************/ 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 } 67 static HINSTANCE g_hInstance; 68 static HWND g_hwndParent; 69 70 71 /** 72 * Frees a popped stack entry after use. 73 */ 74 DECLINLINE(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 */ 85 DECLINLINE(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 */ 97 DECLINLINE(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 */ 109 DECLINLINE(void) vboxPushStack(stack_t **ppTopOfStack, stack_t *pEntry) 110 { 111 pEntry->next = *ppTopOfStack; 112 *ppTopOfStack = pEntry; 113 } 114 115 116 static 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 127 static 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 137 static 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 */ 152 static 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 160 static 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 169 static 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 */ 188 static 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); 110 206 return rc; 111 207 } 112 208 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. 183 213 * 184 214 * @return IPRT status code. … … 201 231 /** 202 232 * Retrieves a file's architecture (x86 or amd64). 233 * 203 234 * Outputs "x86", "amd64" or an error message (if not found/invalid) on stack. 204 235 * … … 207 238 * @param variables The actual variable string. 208 239 * @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 */ 242 VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop, 212 243 extra_parameters *extra) 213 244 { 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) 221 249 { 222 #ifdef UNICODE223 250 char *pszFileUtf8; 224 rc = RTUtf16ToUtf8(szFile, &pszFileUtf8);251 int rc = RTUtf16ToUtf8(pEntry->text, &pszFileUtf8); 225 252 if (RT_SUCCESS(rc)) 226 253 { 227 #else228 char *pszFileUtf8 = szFile;229 #endif230 254 RTLDRMOD hLdrMod; 231 255 rc = RTLdrOpen(pszFileUtf8, RTLDR_O_FOR_VALIDATION, RTLDRARCH_WHATEVER, &hLdrMod); … … 238 262 { 239 263 case RTLDRARCH_X86_32: 240 pushstring(_T("x86"));264 VBOX_PUSH_STRING_LITERAL(stacktop, "x86"); 241 265 break; 242 266 243 267 case RTLDRARCH_AMD64: 244 pushstring(_T("amd64"));268 VBOX_PUSH_STRING_LITERAL(stacktop, "amd64"); 245 269 break; 246 270 247 271 default: 248 pushstring(_T("Error: Unknown / invalid architecture"));272 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid architecture"); 249 273 break; 250 274 } 251 275 } 252 276 else 253 pushstring(_T("Error: Unknown / invalid PE signature"));277 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid PE signature"); 254 278 255 279 RTLdrClose(hLdrMod); 256 280 } 257 281 else 258 pushstring(_T("Error: Could not open file")); 259 #ifdef UNICODE 282 vboxPushVBoxError(stacktop, "RTLdrOpen failed", rc); 260 283 RTStrFree(pszFileUtf8); 261 284 } 262 #endif 285 else 286 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8 failed", rc); 263 287 } 264 288 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); 266 291 } 267 292 268 293 /** 269 294 * Retrieves a file's vendor. 295 * 270 296 * Outputs the vendor's name or an error message (if not found/invalid) on stack. 271 297 * … … 274 300 * @param variables The actual variable string. 275 301 * @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 */ 304 VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop, 279 305 extra_parameters *extra) 280 306 { 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) 288 311 { 289 DWORD dwInfoSize = GetFileVersionInfoSize (szFile, NULL /* lpdwHandle */);312 DWORD dwInfoSize = GetFileVersionInfoSizeW(pEntry->text, NULL /* lpdwHandle */); 290 313 if (dwInfoSize) 291 314 { 292 void *p FileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);293 if (p FileInfo)315 void *pvFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize); 316 if (pvFileInfo) 294 317 { 295 if (GetFileVersionInfo (szFile, 0, dwInfoSize, pFileInfo))318 if (GetFileVersionInfoW(pEntry->text, 0, dwInfoSize, pvFileInfo)) 296 319 { 297 320 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)) 301 323 { 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); 314 334 else 315 rc = VERR_NOT_FOUND;335 vboxPushLastErrorF(stacktop, "VerQueryValueW '%ls' failed", wszQuery); 316 336 } 317 337 else 318 rc = VERR_NOT_FOUND;338 vboxPushLastError(stacktop, "VerQueryValueW '\\VarFileInfo\\Translation' failed"); 319 339 } 320 GlobalFree(pFileInfo); 340 else 341 vboxPushLastError(stacktop, "GetFileVersionInfo failed"); 342 GlobalFree(pvFileInfo); 321 343 } 322 344 else 323 rc = VERR_NO_MEMORY;345 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: GlobalAlloc failed"); 324 346 } 325 347 else 326 rc = VERR_NOT_FOUND;348 vboxPushLastError(stacktop, "GetFileVersionInfoSizeW failed"); 327 349 } 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); 331 353 } 332 354 … … 339 361 * @param variables The actual variable string. 340 362 * @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 */ 365 VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop, 344 366 extra_parameters *extra) 345 367 { 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) 359 378 { 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) 373 387 { 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 = 381 389 { 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); 391 407 if (RT_SUCCESS(rc)) 392 408 { 393 RTLOCALIPCSESSION hSession = 0; 394 rc = vboxConnectToVBoxTray(&hSession); 409 rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->uType); 395 410 if (RT_SUCCESS(rc)) 396 411 { 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); 401 413 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); 407 444 } 445 else 446 vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the type value", rc); 408 447 } 409 410 RTMemFree(pIpcMsg);448 else 449 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the title text", rc); 411 450 } 412 451 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); 418 453 } 454 else 455 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Out of memory!"); 419 456 } 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); 422 463 } 423 464 -
trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/exdll.h
r82625 r96451 61 61 #endif 62 62 63 #ifndef VBOX 63 64 // only include this file from one place in your DLL. 64 65 // (it is all static, if you use it in two places it will fail) … … 68 69 g_stacktop=stacktop; \ 69 70 g_variables=variables; } 71 #endif /* !VBOX */ 70 72 71 73 typedef struct _stack_t … … 104 106 } extra_parameters; 105 107 108 #ifndef VBOX 106 109 static unsigned int g_stringsize; 107 110 static stack_t **g_stacktop; 108 111 static TCHAR *g_variables; 112 #endif 109 113 110 114 enum … … 137 141 __INST_LAST 138 142 }; 143 144 #ifndef VBOX 139 145 140 146 // utility functions (not required but often useful) … … 173 179 lstrcpy(g_variables + varnum*g_stringsize, var); 174 180 } 181 182 #endif /* ! VBOX */ 183 175 184 #endif /* !GA_INCLUDED_SRC_WINNT_Installer_InstallHelper_exdll_h */ -
trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/testcase/tstWinAdditionsInstallHelper.cpp
r96407 r96451 31 31 *********************************************************************************************************************************/ 32 32 #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 */38 33 #include "../exdll.h" 39 #pragma warning(pop)40 34 41 35 #include <iprt/assert.h> … … 49 43 50 44 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 *********************************************************************************************************************************/ 60 48 /** Symbol names to test. */ 61 49 #define TST_FILEGETARCHITECTURE_NAME "FileGetArchitecture" … … 64 52 65 53 54 /********************************************************************************************************************************* 55 * Structures and Typedefs * 56 *********************************************************************************************************************************/ 57 /** A generic NSIS plugin function. */ 58 typedef 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. */ 60 typedef NSIS_PLUGIN_FUNC *PNSIS_PLUGIN_FUNC; 61 62 63 66 64 /** 67 65 * Destroys a stack. … … 84 82 * @returns VBox status code. 85 83 * @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 */ 86 static 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])); 94 90 if (pStack) 95 91 { 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])); 97 94 pStack->next = ppStackTop ? *ppStackTop : NULL; 98 95 99 96 *ppStackTop = pStack; 100 } 101 else 102 rc = VERR_NO_MEMORY; 103 104 return rc; 97 return VINF_SUCCESS; 98 } 99 return VERR_NO_MEMORY; 105 100 } 106 101 … … 108 103 * Pops a string off a stack. 109 104 * 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 */ 110 static int tstStackPopString(stack_t **ppStackTop, WCHAR *pwszDst, size_t cwcDst) 114 111 { 115 112 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 125 int main(int argc, char **argv) 124 126 { 125 127 RTTEST hTest; 126 RTEXITCODE rcExit = RTTestInit AndCreate("tstWinAdditionsInstallHelper", &hTest);128 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0, "tstWinAdditionsInstallHelper", &hTest); 127 129 if (rcExit != RTEXITCODE_SUCCESS) 128 130 return rcExit; … … 130 132 131 133 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)); 136 135 137 136 /** @todo This ASSUMES that this testcase always is located in the separate "bin/additions" sub directory … … 139 138 * Might need some more tweaking ... */ 140 139 int rc = RTPathAppend(szGuestInstallHelperDll, sizeof(szGuestInstallHelperDll), 141 ".. /../../repack/resources/VBoxGuestInstallHelper/VBoxGuestInstallHelper.dll");140 "..\\..\\repackadd\\resources\\VBoxGuestInstallHelper\\VBoxGuestInstallHelper.dll"); 142 141 if (RT_SUCCESS(rc)) 143 142 { 144 143 RTTestIPrintf(RTTESTLVL_ALWAYS, "Using DLL: %s\n", szGuestInstallHelperDll); 145 146 #ifdef UNICODE147 const bool fUnicode = true;148 #else149 const bool fUnicode = false;150 #endif151 RTTestIPrintf(RTTESTLVL_ALWAYS, "Running %s build\n", fUnicode ? "UNICODE" : "ANSI");152 144 153 145 RTLDRMOD hLdrMod; … … 155 147 if (RT_SUCCESS(rc)) 156 148 { 157 TCHAR szVars[NSIS_MAX_STRLEN * sizeof(TCHAR)] = { 0 }; 149 WCHAR wszVars[NSIS_MAX_STRLEN * sizeof(WCHAR)] = { 0 }; 150 WCHAR wszResult[NSIS_MAX_STRLEN]; 158 151 159 152 /* … … 165 158 { 166 159 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)); 173 165 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); 182 169 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!"); 184 174 tstStackDestroy(pStack); 185 175 } … … 191 181 */ 192 182 PNSIS_PLUGIN_FUNC pfnFileGetVendor; 193 rc = RTLdrGetSymbol(hLdrMod, TST_FILEGETVENDOR_NAME, (void **)&pfnFileGetVendor);183 rc = RTLdrGetSymbol(hLdrMod, TST_FILEGETVENDOR_NAME, (void **)&pfnFileGetVendor); 194 184 if (RT_SUCCESS(rc)) 195 185 { 196 186 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)); 203 192 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); 211 195 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!"); 213 200 tstStackDestroy(pStack); 214 201 } … … 225 212 stack_t *pStack = NULL; 226 213 /* 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)); 236 222 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); 243 224 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!"); 245 229 tstStackDestroy(pStack); 246 230 } -
trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestAdditionsLog.nsh
r96407 r96451 73 73 ; - String: Description / Body 74 74 ; - 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) 76 76 ; - Integer: Time (in msec) to show the notification 77 77 VBoxGuestInstallHelper::VBoxTrayShowBallonMsg "${text}" "VirtualBox Guest Additions Setup" ${type} 5000 -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp
r96407 r96451 107 107 108 108 109 /** 110 * Handles VBOXTRAYIPCMSGTYPE_RESTART. 111 */ 109 112 static int vboxIPCHandleVBoxTrayRestart(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr) 110 113 { 111 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 112 AssertPtrReturn(pHdr, VERR_INVALID_POINTER); 114 RT_NOREF(pSession, pHdr); 113 115 114 116 /** @todo Not implemented yet; don't return an error here. */ … … 116 118 } 117 119 120 /** 121 * Handles VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG. 122 */ 118 123 static int vboxIPCHandleShowBalloonMsg(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr) 119 124 { 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 */ 142 184 static int vboxIPCHandleUserLastInput(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr) 143 185 { 144 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 145 AssertPtrReturn(pHdr, VERR_INVALID_POINTER); 146 /* No actual message from client. */ 186 RT_NOREF(pHdr); 147 187 148 188 int rc = VINF_SUCCESS; 149 150 bool fLastInputAvailable = false; 151 VBOXTRAYIPCRES_USERLASTINPUT ipcRes; 189 VBOXTRAYIPCREPLY_USER_LAST_INPUT_T Reply = { UINT32_MAX }; 152 190 if (g_pfnGetLastInputInfo) 153 191 { 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; 164 197 else 165 198 rc = RTErrConvertFromWin32(GetLastError()); 166 199 } 167 200 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)); 175 202 if (RT_SUCCESS(rc)) 176 203 rc = rc2; … … 355 382 /* The next call will be cancelled via VBoxIPCStop if needed. */ 356 383 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)) 363 392 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; 368 453 } 369 454 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)); 439 459 440 460 /* … … 461 481 } 462 482 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)); 465 484 466 485 RTMemFree(pThis); -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTrayMsg.h
r96407 r96451 34 34 /** The IPC pipe's prefix (native). 35 35 * 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-" 37 37 /** 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 39 44 40 enum VBOXTRAYIPCMSGTYPE 45 46 /** 47 * VBoxTray IPC message types. 48 */ 49 typedef enum VBOXTRAYIPCMSGTYPE 41 50 { 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; 52 70 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 */ 54 77 typedef struct VBOXTRAYIPCHEADER 55 78 { 56 /** The header's magic . */57 uint32_t uMagic;79 /** The header's magic (VBOXTRAY_IPC_HDR_MAGIC). */ 80 uint32_t uMagic; 58 81 /** 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. */ 90 typedef VBOXTRAYIPCHEADER *PVBOXTRAYIPCHEADER; 71 91 72 92 /** 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. 76 97 */ 77 typedef struct VBOXTRAYIPCMSG_SHOW BALLOONMSG98 typedef struct VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T 78 99 { 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; 83 104 /** Message type. */ 84 uint32_t uType;105 uint32_t uType; 85 106 /** 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; 111 typedef VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T *PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T; 100 112 101 113 /** 102 * Re sponse telling the last input of the current user.114 * Reply to VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT 103 115 */ 104 typedef struct VBOXTRAYIPCRE S_USERLASTINPUT116 typedef struct VBOXTRAYIPCREPLY_USER_LAST_INPUT_T 105 117 { 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; 122 typedef VBOXTRAYIPCREPLY_USER_LAST_INPUT_T *PVBOXTRAYIPCREPLY_USER_LAST_INPUT_T; 109 123 110 124 #endif /* !GA_INCLUDED_SRC_WINNT_VBoxTray_VBoxTrayMsg_h */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
r96407 r96451 58 58 #include "../../WINNT/VBoxTray/VBoxTrayMsg.h" /* For IPC. */ 59 59 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 66 60 67 61 /********************************************************************************************************************************* … … 117 111 * Global Variables * 118 112 *********************************************************************************************************************************/ 113 static uint32_t s_uDebugGuestPropClientID = 0; 114 static 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. */ 117 static bool s_fSkipRDPDetection = false; 118 119 119 static RTONCE g_vgsvcWinVmInitOnce = RTONCE_INITIALIZER; 120 120 … … 984 984 { 985 985 /* .uMagic = */ VBOXTRAY_IPC_HDR_MAGIC, 986 /* .u HdrVersion = */ 0,987 /* . uMsgType = */ VBOXTRAYIPCMSGTYPE_USERLASTINPUT,988 /* .cb MsgData = */ 0 /* No msg*/986 /* .uVersion = */ VBOXTRAY_IPC_HDR_VERSION, 987 /* .enmMsgType = */ VBOXTRAYIPCMSGTYPE_USER_LAST_INPUT, 988 /* .cbPayload = */ 0 /* No payload */ 989 989 }; 990 990 991 991 rc = RTLocalIpcSessionWrite(hSession, &ipcHdr, sizeof(ipcHdr)); 992 993 992 if (RT_SUCCESS(rc)) 994 993 { 995 VBOXTRAYIPCRE S_USERLASTINPUT ipcRes;996 rc = RTLocalIpcSessionRead(hSession, &ipcRe s, sizeof(ipcRes), NULL /* Exact read */);994 VBOXTRAYIPCREPLY_USER_LAST_INPUT_T ipcReply; 995 rc = RTLocalIpcSessionRead(hSession, &ipcReply, sizeof(ipcReply), NULL /* Exact read */); 997 996 if ( RT_SUCCESS(rc) 998 997 /* If uLastInput is set to UINT32_MAX VBoxTray was not able to retrieve the 999 998 * user's last input time. This might happen when running on Windows NT4 or older. */ 1000 && ipcRe s.uLastInput != UINT32_MAX)999 && ipcReply.cSecSinceLastInput != UINT32_MAX) 1001 1000 { 1002 userState = (ipcRes.uLastInput * 1000)< g_uVMInfoUserIdleThresholdMS1001 userState = ipcReply.cSecSinceLastInput * 1000 < g_uVMInfoUserIdleThresholdMS 1003 1002 ? VBoxGuestUserState_InUse 1004 1003 : VBoxGuestUserState_Idle; … … 1014 1013 fReportToHost = rc == VINF_SUCCESS; 1015 1014 VGSvcVerbose(4, "User '%s' (domain '%s') is idle for %RU32, fReportToHost=%RTbool\n", 1016 pszUser, pszDomain ? pszDomain : "<None>", ipcRe s.uLastInput, fReportToHost);1015 pszUser, pszDomain ? pszDomain : "<None>", ipcReply.cSecSinceLastInput, fReportToHost); 1017 1016 1018 1017 #if 0 /* Do we want to write the idle time as well? */ 1019 1018 /* Also write the user's current idle time, if there is any. */ 1020 1019 if (userState == VBoxGuestUserState_Idle) 1021 rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", "%RU32", ipcRe s.uLastInputMs);1020 rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", "%RU32", ipcReply.cSecSinceLastInput); 1022 1021 else 1023 1022 rc = vgsvcUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs", NULL /* Delete property */); … … 1027 1026 } 1028 1027 #ifdef DEBUG 1029 else if (RT_SUCCESS(rc) && ipcRe s.uLastInput == UINT32_MAX)1028 else if (RT_SUCCESS(rc) && ipcReply.cSecSinceLastInput == UINT32_MAX) 1030 1029 VGSvcVerbose(4, "Last input for user '%s' is not supported, skipping\n", pszUser, rc); 1031 1030 #endif
Note:
See TracChangeset
for help on using the changeset viewer.