VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelper.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
RevLine 
[34098]1/* $Id: VBoxGuestInstallHelper.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxGuestInstallHelper - Various helper routines for Windows guest installer.
[82615]4 * Works with NSIS 3.x.
[34098]5 */
6
7/*
[98103]8 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
[34098]9 *
[96407]10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
[34098]27 */
28
[57358]29
30/*********************************************************************************************************************************
31* Header Files *
32*********************************************************************************************************************************/
[96451]33#ifndef UNICODE
34# define UNICODE
35#endif
[62679]36#include <iprt/win/windows.h>
[96770]37#include <iprt/win/commctrl.h>
[34098]38#include "exdll.h"
39
[96770]40#include <iprt/alloca.h>
[96452]41#include <iprt/errcore.h>
[47212]42#include <iprt/initterm.h>
[68743]43#include <iprt/ldr.h>
[47212]44#include <iprt/localipc.h>
45#include <iprt/mem.h>
[64292]46#include <iprt/process.h>
[47212]47#include <iprt/string.h>
[96451]48#include <iprt/utf16.h>
[47212]49
[34098]50/* Required structures/defines of VBoxTray. */
51#include "../../VBoxTray/VBoxTrayMsg.h"
52
53
[57358]54/*********************************************************************************************************************************
55* Defined Constants And Macros *
56*********************************************************************************************************************************/
[96451]57#define VBOXINSTALLHELPER_EXPORT extern "C" DECLEXPORT(void)
[34098]58
[82616]59
[57358]60/*********************************************************************************************************************************
61* Structures and Typedefs *
62*********************************************************************************************************************************/
[37421]63typedef DWORD (WINAPI *PFNSFCFILEEXCEPTION)(DWORD param1, PWCHAR param2, DWORD param3);
64
65
[57358]66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
[96451]69static HINSTANCE g_hInstance;
70static HWND g_hwndParent;
[37421]71
[96451]72
[47212]73/**
[96451]74 * Frees a popped stack entry after use.
[47212]75 */
[96451]76DECLINLINE(void) vboxFreeStackEntry(stack_t *pEntry)
77{
78 if (pEntry)
79 GlobalFree((HGLOBAL)pEntry);
80}
[37421]81
[96451]82
[34098]83/**
[96451]84 * Allocates a new stack entry for containing a string of the given length
85 * (excluding terminator)
86 */
87DECLINLINE(stack_t *) vboxAllocStackEntry(size_t cwcString)
88{
89 return (stack_t *)GlobalAlloc(GPTR, RT_UOFFSETOF_DYN(stack_t, text[cwcString + 1]));
90}
91
92
93/**
94 * Pops an entry off the stack, return NULL if empty.
[34098]95 *
[96451]96 * Call vboxFreeStackEntry when done.
97 *
[34098]98 */
[96451]99DECLINLINE(stack_t *) vboxPopStack(stack_t **ppTopOfStack)
[34098]100{
[96451]101 stack_t *pEntry = ppTopOfStack ? *ppTopOfStack : NULL;
102 if (pEntry)
103 *ppTopOfStack = pEntry->next;
104 return pEntry;
105}
[82625]106
107
[96451]108/**
109 * Pushes an entry onto the stack.
110 */
111DECLINLINE(void) vboxPushStack(stack_t **ppTopOfStack, stack_t *pEntry)
112{
113 pEntry->next = *ppTopOfStack;
114 *ppTopOfStack = pEntry;
[34098]115}
116
[96451]117
118static void vboxPushUtf16N(stack_t **ppTopOfStack, wchar_t const *pwszString, size_t cwcString)
[34098]119{
[96451]120 stack_t *pEntry = vboxAllocStackEntry(cwcString);
[82625]121
[96451]122 memcpy(pEntry->text, pwszString, cwcString * sizeof(pEntry->text[0]));
123 pEntry->text[cwcString] = '\0';
[34098]124
[96451]125 vboxPushStack(ppTopOfStack, pEntry);
126}
[82625]127
128
[96451]129static void vboxPushUtf16(stack_t **ppTopOfStack, wchar_t const *pwszString)
130{
131 return vboxPushUtf16N(ppTopOfStack, pwszString, RTUtf16Len(pwszString));
[34098]132}
133
[96451]134
135#define VBOX_PUSH_STRING_LITERAL(a_ppTopOfStack, a_szLiteral) \
136 vboxPushUtf16N(a_ppTopOfStack, RT_CONCAT(L, a_szLiteral), sizeof(RT_CONCAT(L, a_szLiteral)) / sizeof(wchar_t) - 1)
137
138
139static void vboxPushUtf8(stack_t **ppTopOfStack, char const *pszString)
[39548]140{
[96451]141 size_t cwcUtf16 = RTStrCalcUtf16Len(pszString);
142 stack_t *pEntry = vboxAllocStackEntry(cwcUtf16);
143
144 PRTUTF16 pwszUtf16 = pEntry->text;
145 int rc = RTStrToUtf16Ex(pszString, RTSTR_MAX, &pwszUtf16, cwcUtf16 + 1, NULL);
146 AssertRC(rc);
147
148 vboxPushStack(ppTopOfStack, pEntry);
[39548]149}
150
[96451]151/**
152 * Pushes a string containing an error message and a VBox status code.
153 */
154static void vboxPushVBoxError(stack_t **ppTopOfStack, char const *pszString, int vrc)
[82625]155{
[96451]156 RTUTF16 wszTmp[128];
157 RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %s! %Rrc", pszString, vrc);
158 vboxPushUtf16(ppTopOfStack, wszTmp);
159}
[82625]160
161
[96451]162static void vboxPushLastError(stack_t **ppTopOfStack, char const *pszString)
163{
164 DWORD const dwErr = GetLastError();
165 RTUTF16 wszTmp[128];
166 RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %s! lasterr=%u (%#x)", pszString, dwErr, dwErr);
167 vboxPushUtf16(ppTopOfStack, wszTmp);
[82625]168}
169
[96451]170
171static void vboxPushLastErrorF(stack_t **ppTopOfStack, const char *pszFormat, ...)
172{
173 DWORD const dwErr = GetLastError();
174 RTUTF16 wszTmp[128];
175 va_list va;
176 va_start(va, pszFormat);
177 RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %N! lasterr=%u (%#x)", pszFormat, &va, dwErr, dwErr);
178 va_end(va);
179 vboxPushUtf16(ppTopOfStack, wszTmp);
180}
181
182
[47232]183/**
[96451]184 * Convers a parameter to uint32_t.
[47232]185 *
[96451]186 * @returns IPRT status code.
187 * @param pwsz Will be trimmed.
188 * @param puValue Where to return the value.
189 */
190static int vboxUtf16ToUInt32(PRTUTF16 pwsz, uint32_t *puValue)
191{
192 *puValue = 0;
193
194 /* Trim the input: */
195 RTUTF16 wc;
196 while ((wc = *pwsz) == ' ' || wc == '\t')
197 pwsz++;
198 size_t cwc = RTUtf16Len(pwsz);
199 while (cwc > 0 && ((wc = pwsz[cwc - 1]) == ' ' || wc == '\t'))
200 pwsz[--cwc] = '\0';
201
202 /* Convert the remains into an UTF-8 string. */
203 char szValue[128];
204 char *pszValue = &szValue[0];
205 int rc = RTUtf16ToUtf8Ex(pwsz, cwc, &pszValue, sizeof(szValue), NULL);
206 if (RT_SUCCESS(rc))
207 rc = RTStrToUInt32Full(pszValue, 0, puValue);
208 return rc;
209}
210
211
212/**
213 * Connects to VBoxTray IPC under the behalf of the user running in the current
214 * thread context.
215 *
[47232]216 * @return IPRT status code.
217 * @param phSession Where to store the IPC session.
218 */
[48030]219static int vboxConnectToVBoxTray(RTLOCALIPCSESSION *phSession)
[47232]220{
[64292]221 char szPipeName[512 + sizeof(VBOXTRAY_IPC_PIPE_PREFIX)];
222 memcpy(szPipeName, VBOXTRAY_IPC_PIPE_PREFIX, sizeof(VBOXTRAY_IPC_PIPE_PREFIX));
223 int rc = RTProcQueryUsername(NIL_RTPROCESS,
224 &szPipeName[sizeof(VBOXTRAY_IPC_PIPE_PREFIX) - 1],
225 sizeof(szPipeName) - sizeof(VBOXTRAY_IPC_PIPE_PREFIX) + 1,
226 NULL /*pcbUser*/);
[47232]227 if (RT_SUCCESS(rc))
[64292]228 rc = RTLocalIpcSessionConnect(phSession, szPipeName, RTLOCALIPC_FLAGS_NATIVE_NAME);
[47232]229 return rc;
230}
231
[36570]232
[34098]233/**
[39548]234 * Retrieves a file's architecture (x86 or amd64).
[96451]235 *
[39548]236 * Outputs "x86", "amd64" or an error message (if not found/invalid) on stack.
237 *
238 * @param hwndParent Window handle of parent.
239 * @param string_size Size of variable string.
240 * @param variables The actual variable string.
241 * @param stacktop Pointer to a pointer to the current stack.
[96451]242 * @param extra Extra parameters.
[39548]243 */
[96451]244VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
[82615]245 extra_parameters *extra)
[39548]246{
[96451]247 RT_NOREF(hwndParent, string_size, variables, extra);
[82615]248
[96451]249 stack_t *pEntry = vboxPopStack(stacktop);
250 if (pEntry)
[39548]251 {
[82625]252 char *pszFileUtf8;
[96451]253 int rc = RTUtf16ToUtf8(pEntry->text, &pszFileUtf8);
[68743]254 if (RT_SUCCESS(rc))
[39548]255 {
[82625]256 RTLDRMOD hLdrMod;
257 rc = RTLdrOpen(pszFileUtf8, RTLDR_O_FOR_VALIDATION, RTLDRARCH_WHATEVER, &hLdrMod);
258 if (RT_SUCCESS(rc))
[39548]259 {
[82625]260 if (RTLdrGetFormat(hLdrMod) == RTLDRFMT_PE)
[39548]261 {
[82625]262 RTLDRARCH enmLdrArch = RTLdrGetArch(hLdrMod);
263 switch (enmLdrArch)
264 {
265 case RTLDRARCH_X86_32:
[96451]266 VBOX_PUSH_STRING_LITERAL(stacktop, "x86");
[82625]267 break;
[39548]268
[82625]269 case RTLDRARCH_AMD64:
[96451]270 VBOX_PUSH_STRING_LITERAL(stacktop, "amd64");
[82625]271 break;
[39548]272
[82625]273 default:
[96451]274 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid architecture");
[82625]275 break;
276 }
[39548]277 }
[82625]278 else
[96451]279 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid PE signature");
[82625]280
281 RTLdrClose(hLdrMod);
[39548]282 }
[68743]283 else
[96451]284 vboxPushVBoxError(stacktop, "RTLdrOpen failed", rc);
[82625]285 RTStrFree(pszFileUtf8);
[39548]286 }
[96451]287 else
288 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8 failed", rc);
[39548]289 }
[68743]290 else
[96451]291 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
292 vboxFreeStackEntry(pEntry);
[39548]293}
294
295/**
296 * Retrieves a file's vendor.
[96451]297 *
[39548]298 * Outputs the vendor's name or an error message (if not found/invalid) on stack.
299 *
300 * @param hwndParent Window handle of parent.
301 * @param string_size Size of variable string.
302 * @param variables The actual variable string.
303 * @param stacktop Pointer to a pointer to the current stack.
[96451]304 * @param extra Extra parameters.
[39548]305 */
[96451]306VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
[82615]307 extra_parameters *extra)
[39548]308{
[96451]309 RT_NOREF(hwndParent, string_size, variables, extra);
[82615]310
[96451]311 stack_t *pEntry = vboxPopStack(stacktop);
312 if (pEntry)
[36464]313 {
[96451]314 DWORD dwInfoSize = GetFileVersionInfoSizeW(pEntry->text, NULL /* lpdwHandle */);
[39548]315 if (dwInfoSize)
316 {
[96451]317 void *pvFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);
318 if (pvFileInfo)
[39548]319 {
[96451]320 if (GetFileVersionInfoW(pEntry->text, 0, dwInfoSize, pvFileInfo))
[39548]321 {
322 LPVOID pvInfo;
[96451]323 UINT cbInfo;
324 if (VerQueryValueW(pvFileInfo, L"\\VarFileInfo\\Translation", &pvInfo, &cbInfo))
[39548]325 {
[96451]326 WORD wCodePage = LOWORD(*(DWORD const *)pvInfo);
327 WORD wLanguageID = HIWORD(*(DWORD const *)pvInfo);
[39548]328
[96451]329 WCHAR wszQuery[80];
330 RTUtf16Printf(wszQuery, RT_ELEMENTS(wszQuery), "StringFileInfo\\%04X%04X\\CompanyName",
331 wCodePage, wLanguageID);
[39548]332
[96451]333 LPCWSTR pwszData;
334 if (VerQueryValueW(pvFileInfo, wszQuery, (void **)&pwszData, &cbInfo))
335 vboxPushUtf16(stacktop, pwszData);
[39548]336 else
[96451]337 vboxPushLastErrorF(stacktop, "VerQueryValueW '%ls' failed", wszQuery);
[39548]338 }
339 else
[96451]340 vboxPushLastError(stacktop, "VerQueryValueW '\\VarFileInfo\\Translation' failed");
[39548]341 }
[96451]342 else
343 vboxPushLastError(stacktop, "GetFileVersionInfo failed");
344 GlobalFree(pvFileInfo);
[39548]345 }
346 else
[96451]347 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: GlobalAlloc failed");
[39548]348 }
[36464]349 else
[96451]350 vboxPushLastError(stacktop, "GetFileVersionInfoSizeW failed");
[36464]351 }
[96451]352 else
353 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
354 vboxFreeStackEntry(pEntry);
[36455]355}
356
[39548]357/**
358 * Shows a balloon message using VBoxTray's notification area in the
359 * Windows task bar.
360 *
361 * @param hwndParent Window handle of parent.
362 * @param string_size Size of variable string.
363 * @param variables The actual variable string.
364 * @param stacktop Pointer to a pointer to the current stack.
[96451]365 * @param extra Extra parameters.
[39548]366 */
[96451]367VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
[82615]368 extra_parameters *extra)
[39548]369{
[96451]370 RT_NOREF(hwndParent, string_size, variables, extra);
[82615]371
[96451]372 /*
373 * Get parameters from the stack.
374 */
375 stack_t * const pMsgEntry = vboxPopStack(stacktop);
376 stack_t * const pTitleEntry = vboxPopStack(stacktop);
377 stack_t * const pTypeEntry = vboxPopStack(stacktop);
378 stack_t * const pTimeoutEntry = vboxPopStack(stacktop);
379 if (pTimeoutEntry)
[39548]380 {
[96451]381 /*
382 * Allocate an IPC message payload structure of the right size.
383 */
384 size_t const cchMsg = RTUtf16CalcUtf8Len(pMsgEntry->text);
385 size_t const cchTitle = RTUtf16CalcUtf8Len(pTitleEntry->text);
386 size_t const cbPayload = RT_UOFFSETOF_DYN(VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T, szzStrings[cchMsg + 1 + cchTitle + 1]);
387 PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T pPayload = (PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T)RTMemAllocZVar(cbPayload);
388 if (pPayload)
[39548]389 {
[96451]390 VBOXTRAYIPCHEADER const MsgHdr =
[82625]391 {
[96451]392 VBOXTRAY_IPC_HDR_MAGIC,
393 VBOXTRAY_IPC_HDR_VERSION,
394 VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG,
395 cbPayload
396 };
[47212]397
[96451]398 /*
399 * Convert the parametes and put them into the payload structure.
400 */
401 pPayload->cchMsg = cchMsg;
402 pPayload->cchTitle = cchTitle;
403 char *psz = &pPayload->szzStrings[0];
404 int rc = RTUtf16ToUtf8Ex(pMsgEntry->text, RTSTR_MAX, &psz, cchMsg + 1, NULL);
405 if (RT_SUCCESS(rc))
406 {
407 psz = &pPayload->szzStrings[cchMsg + 1];
408 rc = RTUtf16ToUtf8Ex(pTitleEntry->text, RTSTR_MAX, &psz, cchTitle + 1, NULL);
[82625]409 if (RT_SUCCESS(rc))
[47212]410 {
[96451]411 rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->uType);
[47212]412 if (RT_SUCCESS(rc))
[82625]413 {
[96451]414 rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->cMsTimeout);
[82625]415 if (RT_SUCCESS(rc))
[96451]416 {
417 /*
418 * Connect to VBoxTray and send the message.
419 */
420 RTLOCALIPCSESSION hSession = 0;
421 rc = vboxConnectToVBoxTray(&hSession);
422 if (RT_SUCCESS(rc))
423 {
424 rc = RTLocalIpcSessionWrite(hSession, &MsgHdr, sizeof(MsgHdr));
425 if (RT_SUCCESS(rc))
426 {
427 rc = RTLocalIpcSessionWrite(hSession, pPayload, cbPayload);
428 if (RT_FAILURE(rc))
429 vboxPushVBoxError(stacktop, "Failed to write message payload", rc);
430 }
431 else
432 vboxPushVBoxError(stacktop, "Failed to write message header", rc);
[82625]433
[96451]434 int rc2 = RTLocalIpcSessionClose(hSession);
435 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
436 {
437 vboxPushVBoxError(stacktop, "RTLocalIpcSessionClose failed", rc);
438 rc = rc2;
439 }
440 }
441 else
442 vboxPushVBoxError(stacktop, "vboxConnectToVBoxTray failed", rc);
443 }
444 else
445 vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the timeout value", rc);
[82625]446 }
[96451]447 else
448 vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the type value", rc);
[47212]449 }
[96451]450 else
451 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the title text", rc);
[47212]452 }
[82625]453 else
[96451]454 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the message text", rc);
[39548]455 }
[96451]456 else
457 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Out of memory!");
[39548]458 }
[96451]459 else
460 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Too few parameters on the stack!");
461 vboxFreeStackEntry(pTimeoutEntry);
462 vboxFreeStackEntry(pTypeEntry);
463 vboxFreeStackEntry(pTitleEntry);
464 vboxFreeStackEntry(pMsgEntry);
[39548]465}
466
[96770]467/**
468 * Dumps the UI log to a file in UTF-8 format.
469 *
470 * Does not return any values on the stack.
471 *
472 * @param hWndParent Window handle of parent.
473 * @param string_size Size of variable string.
474 * @param variables The actual variable string.
475 * @param stacktop Pointer to a pointer to the current stack.
476 * @param extra Extra parameters.
477 */
478VBOXINSTALLHELPER_EXPORT DumpLog(HWND hWndParent, int string_size, WCHAR *variables, stack_t **stacktop,
479 extra_parameters *extra)
480{
481 RT_NOREF(string_size, variables, extra);
482
483 /*
484 * Get parameters from the stack.
485 */
486 stack_t * const pFilename = vboxPopStack(stacktop);
487 if (pFilename)
488 {
489 /*
490 * Open the output file.
491 */
492 HANDLE hFile = CreateFileW(pFilename->text, GENERIC_WRITE, FILE_SHARE_READ, NULL /*pSecAttr*/, CREATE_ALWAYS,
493 FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
494 if (hFile != NULL)
495 {
496 DWORD dwIgn;
497
498 /*
499 * Locate the list view widget.
500 */
501 HWND hWndDialog = FindWindowExW(hWndParent, NULL /*hWndChildAfter*/, L"#32770" /*pwszClass*/, NULL /*pwszTitle*/);
502 if (hWndDialog)
503 {
504 HWND hWndList = FindWindowExW(hWndDialog, NULL /*hWndChildAfter*/, L"SysListView32", NULL /*pwszTitle*/);
505 if (hWndList != NULL)
506 {
507 uint32_t const cLines = (uint32_t)SendMessageW(hWndList, LVM_GETITEMCOUNT, 0, 0);
508 if (cLines > 0)
509 {
510 /* Allocate a buffer for retriving the text. */
511 uint32_t cwcBuf = RT_MAX(string_size + 16, _8K);
512 wchar_t *pwszBuf = (wchar_t *)RTMemTmpAlloc(cwcBuf * sizeof(wchar_t));
513 wchar_t * const pwszBufFree = pwszBuf;
514 if (!pwszBuf)
515 {
516 cwcBuf = _4K;
517 pwszBuf = (wchar_t *)alloca(cwcBuf * sizeof(wchar_t));
518 }
519
520 /*
521 * Retreive the lines and write them to the output file.
522 */
523 for (uint32_t iLine = 0; iLine < cLines; iLine++)
524 {
525 LVITEMW Item =
526 {
527 /* .mask = */ 0,
528 /* .iItem = */ (int)iLine,
529 /* .iSubItem = */ 0,
530 /* .state = */ 0,
531 /* .stateMask = */ 0,
532 /* .pszText = */ pwszBuf,
533 /* .cchTextMax = */ (int)cwcBuf,
534 };
535 uint32_t const cwcRet = (uint32_t)SendMessageW(hWndList, LVM_GETITEMTEXT, iLine, (LPARAM)&Item);
536 if (cwcRet < cwcBuf)
537 {
538 pwszBuf[cwcRet] = '\0';
539 bool fNeedsNewline = cwcRet + 2 >= cwcBuf;
540 if (!fNeedsNewline)
541 {
542 pwszBuf[cwcRet + 0] = '\r';
543 pwszBuf[cwcRet + 1] = '\n';
544 pwszBuf[cwcRet + 2] = '\0';
545 }
546
547 char *pszUtf8;
548 int rc = RTUtf16ToUtf8(pwszBuf, &pszUtf8);
549 if (RT_SUCCESS(rc))
550 {
551 WriteFile(hFile, pszUtf8, strlen(pszUtf8), &dwIgn, NULL);
552 if (fNeedsNewline)
553 WriteFile(hFile, RT_STR_TUPLE("\r\n"), &dwIgn, NULL);
554 RTStrFree(pszUtf8);
555 }
556 else
557 WriteFile(hFile, RT_STR_TUPLE("!RTUtf16ToUtf8 failed!\r\n"), &dwIgn, NULL);
558 }
559 else
560 WriteFile(hFile, RT_STR_TUPLE("!LVM_GETITEMTEXT overflow!\r\n"), &dwIgn, NULL);
561 } /* for loop*/
562
563 RTMemTmpFree(pwszBufFree);
564 }
565 else
566 WriteFile(hFile, RT_STR_TUPLE("Log is empty.\r\n"), &dwIgn, NULL);
567 }
568 else
569 WriteFile(hFile, RT_STR_TUPLE("FindWindowEx failed to locate the log control!\r\n"), &dwIgn, NULL);
570 }
571 else
572 WriteFile(hFile, RT_STR_TUPLE("FindWindowEx failed to locate dialog windows!\r\n"), &dwIgn, NULL);
573 CloseHandle(hFile);
574 }
575 }
576 vboxFreeStackEntry(pFilename);
577}
578
[63089]579BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved)
[39548]580{
[82629]581 RT_NOREF(pReserved);
582
[39548]583 g_hInstance = (HINSTANCE)hInst;
[82629]584
585 switch (uReason)
586 {
587 case DLL_PROCESS_ATTACH:
588 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
589 break;
590
591 case DLL_PROCESS_DETACH:
592 break;
593
594 case DLL_THREAD_ATTACH:
595 break;
596
597 case DLL_THREAD_DETACH:
598 break;
599
600 default:
601 break;
602 }
603
[39548]604 return TRUE;
605}
606
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use