VirtualBox

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

Last change on this file was 107942, checked in by vboxsync, 2 months ago

Additions/WINNT/Installer/InstallHelper/VBoxGuestInstallHelperDll.cpp: Added ARM64 to FileGetArchitecture().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.9 KB
Line 
1/* $Id: VBoxGuestInstallHelperDll.cpp 107942 2025-01-27 14:57:22Z vboxsync $ */
2/** @file
3 * VBoxGuestInstallHelper - Various helper routines for Windows guest installer.
4 * Works with NSIS 3.x.
5 */
6
7/*
8 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
9 *
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
27 */
28
29
30/*********************************************************************************************************************************
31* Header Files *
32*********************************************************************************************************************************/
33#ifndef UNICODE
34# define UNICODE
35#endif
36#include <iprt/win/windows.h>
37#include <iprt/win/commctrl.h>
38#include "exdll.h"
39
40#include <iprt/alloca.h>
41#include <iprt/errcore.h>
42#include <iprt/initterm.h>
43#include <iprt/ldr.h>
44#include <iprt/localipc.h>
45#include <iprt/mem.h>
46#include <iprt/process.h>
47#include <iprt/string.h>
48#include <iprt/utf16.h>
49
50/* Required structures/defines of VBoxTray. */
51#include "../../VBoxTray/VBoxTrayMsg.h"
52
53
54/*********************************************************************************************************************************
55* Defined Constants And Macros *
56*********************************************************************************************************************************/
57#define VBOXINSTALLHELPER_EXPORT extern "C" DECLEXPORT(void)
58
59
60/*********************************************************************************************************************************
61* Structures and Typedefs *
62*********************************************************************************************************************************/
63typedef DWORD (WINAPI *PFNSFCFILEEXCEPTION)(DWORD param1, PWCHAR param2, DWORD param3);
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69static HINSTANCE g_hInstance;
70static HWND g_hwndParent;
71
72
73/**
74 * Frees a popped stack entry after use.
75 */
76DECLINLINE(void) vboxFreeStackEntry(stack_t *pEntry)
77{
78 if (pEntry)
79 GlobalFree((HGLOBAL)pEntry);
80}
81
82
83/**
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.
95 *
96 * Call vboxFreeStackEntry when done.
97 *
98 */
99DECLINLINE(stack_t *) vboxPopStack(stack_t **ppTopOfStack)
100{
101 stack_t *pEntry = ppTopOfStack ? *ppTopOfStack : NULL;
102 if (pEntry)
103 *ppTopOfStack = pEntry->next;
104 return pEntry;
105}
106
107
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;
115}
116
117
118static void vboxPushUtf16N(stack_t **ppTopOfStack, wchar_t const *pwszString, size_t cwcString)
119{
120 stack_t *pEntry = vboxAllocStackEntry(cwcString);
121
122 memcpy(pEntry->text, pwszString, cwcString * sizeof(pEntry->text[0]));
123 pEntry->text[cwcString] = '\0';
124
125 vboxPushStack(ppTopOfStack, pEntry);
126}
127
128
129static void vboxPushUtf16(stack_t **ppTopOfStack, wchar_t const *pwszString)
130{
131 return vboxPushUtf16N(ppTopOfStack, pwszString, RTUtf16Len(pwszString));
132}
133
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)
140{
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);
149}
150
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)
155{
156 RTUTF16 wszTmp[128];
157 RTUtf16Printf(wszTmp, RT_ELEMENTS(wszTmp), "Error: %s! %Rrc", pszString, vrc);
158 vboxPushUtf16(ppTopOfStack, wszTmp);
159}
160
161
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);
168}
169
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
183/**
184 * Convers a parameter to uint32_t.
185 *
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 *
216 * @return IPRT status code.
217 * @param phSession Where to store the IPC session.
218 */
219static int vboxConnectToVBoxTray(RTLOCALIPCSESSION *phSession)
220{
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*/);
227 if (RT_SUCCESS(rc))
228 rc = RTLocalIpcSessionConnect(phSession, szPipeName, RTLOCALIPC_FLAGS_NATIVE_NAME);
229 return rc;
230}
231
232
233/**
234 * Retrieves a file's architecture.
235 *
236 * @retval "x86" on the stack for a 32-bit x86 file.
237 * @retval "amd64" on the stack for a 64-bit x86_64 file.
238 * @retval "arm64" on the stack for a 64-bit ARM file.
239 * @param hwndParent Window handle of parent.
240 * @param string_size Size of variable string.
241 * @param variables The actual variable string.
242 * @param stacktop Pointer to a pointer to the current stack.
243 * @param extra Extra parameters.
244 */
245VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
246 extra_parameters *extra)
247{
248 RT_NOREF(hwndParent, string_size, variables, extra);
249
250 stack_t *pEntry = vboxPopStack(stacktop);
251 if (pEntry)
252 {
253 char *pszFileUtf8;
254 int rc = RTUtf16ToUtf8(pEntry->text, &pszFileUtf8);
255 if (RT_SUCCESS(rc))
256 {
257 RTLDRMOD hLdrMod;
258 rc = RTLdrOpen(pszFileUtf8, RTLDR_O_FOR_VALIDATION, RTLDRARCH_WHATEVER, &hLdrMod);
259 if (RT_SUCCESS(rc))
260 {
261 if (RTLdrGetFormat(hLdrMod) == RTLDRFMT_PE)
262 {
263 RTLDRARCH enmLdrArch = RTLdrGetArch(hLdrMod);
264 switch (enmLdrArch)
265 {
266 case RTLDRARCH_X86_32:
267 VBOX_PUSH_STRING_LITERAL(stacktop, "x86");
268 break;
269
270 case RTLDRARCH_AMD64:
271 VBOX_PUSH_STRING_LITERAL(stacktop, "amd64");
272 break;
273
274 case RTLDRARCH_ARM64:
275 VBOX_PUSH_STRING_LITERAL(stacktop, "arm64");
276 break;
277
278 default:
279 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid architecture");
280 break;
281 }
282 }
283 else
284 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Unknown / invalid PE signature");
285
286 RTLdrClose(hLdrMod);
287 }
288 else
289 vboxPushVBoxError(stacktop, "RTLdrOpen failed", rc);
290 RTStrFree(pszFileUtf8);
291 }
292 else
293 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8 failed", rc);
294 }
295 else
296 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
297 vboxFreeStackEntry(pEntry);
298}
299
300/**
301 * Retrieves a file's vendor.
302 *
303 * Outputs the vendor's name or an error message (if not found/invalid) on stack.
304 *
305 * @param hwndParent Window handle of parent.
306 * @param string_size Size of variable string.
307 * @param variables The actual variable string.
308 * @param stacktop Pointer to a pointer to the current stack.
309 * @param extra Extra parameters.
310 */
311VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
312 extra_parameters *extra)
313{
314 RT_NOREF(hwndParent, string_size, variables, extra);
315
316 stack_t *pEntry = vboxPopStack(stacktop);
317 if (pEntry)
318 {
319 DWORD dwInfoSize = GetFileVersionInfoSizeW(pEntry->text, NULL /* lpdwHandle */);
320 if (dwInfoSize)
321 {
322 void *pvFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);
323 if (pvFileInfo)
324 {
325 if (GetFileVersionInfoW(pEntry->text, 0, dwInfoSize, pvFileInfo))
326 {
327 LPVOID pvInfo;
328 UINT cbInfo;
329 if (VerQueryValueW(pvFileInfo, L"\\VarFileInfo\\Translation", &pvInfo, &cbInfo))
330 {
331 WORD wCodePage = LOWORD(*(DWORD const *)pvInfo);
332 WORD wLanguageID = HIWORD(*(DWORD const *)pvInfo);
333
334 WCHAR wszQuery[80];
335 RTUtf16Printf(wszQuery, RT_ELEMENTS(wszQuery), "StringFileInfo\\%04X%04X\\CompanyName",
336 wCodePage, wLanguageID);
337
338 LPCWSTR pwszData;
339 if (VerQueryValueW(pvFileInfo, wszQuery, (void **)&pwszData, &cbInfo))
340 vboxPushUtf16(stacktop, pwszData);
341 else
342 vboxPushLastErrorF(stacktop, "VerQueryValueW '%ls' failed", wszQuery);
343 }
344 else
345 vboxPushLastError(stacktop, "VerQueryValueW '\\VarFileInfo\\Translation' failed");
346 }
347 else
348 vboxPushLastError(stacktop, "GetFileVersionInfo failed");
349 GlobalFree(pvFileInfo);
350 }
351 else
352 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: GlobalAlloc failed");
353 }
354 else
355 vboxPushLastError(stacktop, "GetFileVersionInfoSizeW failed");
356 }
357 else
358 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Could not retrieve file name");
359 vboxFreeStackEntry(pEntry);
360}
361
362/**
363 * Shows a balloon message using VBoxTray's notification area in the
364 * Windows task bar.
365 *
366 * @param hwndParent Window handle of parent.
367 * @param string_size Size of variable string.
368 * @param variables The actual variable string.
369 * @param stacktop Pointer to a pointer to the current stack.
370 * @param extra Extra parameters.
371 */
372VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, WCHAR *variables, stack_t **stacktop,
373 extra_parameters *extra)
374{
375 RT_NOREF(hwndParent, string_size, variables, extra);
376
377 /*
378 * Get parameters from the stack.
379 */
380 stack_t * const pMsgEntry = vboxPopStack(stacktop);
381 stack_t * const pTitleEntry = vboxPopStack(stacktop);
382 stack_t * const pTypeEntry = vboxPopStack(stacktop);
383 stack_t * const pTimeoutEntry = vboxPopStack(stacktop);
384 if (pTimeoutEntry)
385 {
386 /*
387 * Allocate an IPC message payload structure of the right size.
388 */
389 size_t const cchMsg = RTUtf16CalcUtf8Len(pMsgEntry->text);
390 size_t const cchTitle = RTUtf16CalcUtf8Len(pTitleEntry->text);
391 size_t const cbPayload = RT_UOFFSETOF_DYN(VBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T, szzStrings[cchMsg + 1 + cchTitle + 1]);
392 PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T pPayload = (PVBOXTRAYIPCMSG_SHOW_BALLOON_MSG_T)RTMemAllocZVar(cbPayload);
393 if (pPayload)
394 {
395 VBOXTRAYIPCHEADER const MsgHdr =
396 {
397 VBOXTRAY_IPC_HDR_MAGIC,
398 VBOXTRAY_IPC_HDR_VERSION,
399 VBOXTRAYIPCMSGTYPE_SHOW_BALLOON_MSG,
400 (uint32_t)cbPayload
401 };
402
403 /*
404 * Convert the parametes and put them into the payload structure.
405 */
406 pPayload->cchMsg = (uint32_t)cchMsg;
407 pPayload->cchTitle = (uint32_t)cchTitle;
408 char *psz = &pPayload->szzStrings[0];
409 int rc = RTUtf16ToUtf8Ex(pMsgEntry->text, RTSTR_MAX, &psz, cchMsg + 1, NULL);
410 if (RT_SUCCESS(rc))
411 {
412 psz = &pPayload->szzStrings[cchMsg + 1];
413 rc = RTUtf16ToUtf8Ex(pTitleEntry->text, RTSTR_MAX, &psz, cchTitle + 1, NULL);
414 if (RT_SUCCESS(rc))
415 {
416 rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->uType);
417 if (RT_SUCCESS(rc))
418 {
419 rc = vboxUtf16ToUInt32(pTypeEntry->text, &pPayload->cMsTimeout);
420 if (RT_SUCCESS(rc))
421 {
422 /*
423 * Connect to VBoxTray and send the message.
424 */
425 RTLOCALIPCSESSION hSession = 0;
426 rc = vboxConnectToVBoxTray(&hSession);
427 if (RT_SUCCESS(rc))
428 {
429 rc = RTLocalIpcSessionWrite(hSession, &MsgHdr, sizeof(MsgHdr));
430 if (RT_SUCCESS(rc))
431 {
432 rc = RTLocalIpcSessionWrite(hSession, pPayload, cbPayload);
433 if (RT_FAILURE(rc))
434 vboxPushVBoxError(stacktop, "Failed to write message payload", rc);
435 }
436 else
437 vboxPushVBoxError(stacktop, "Failed to write message header", rc);
438
439 int rc2 = RTLocalIpcSessionClose(hSession);
440 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
441 {
442 vboxPushVBoxError(stacktop, "RTLocalIpcSessionClose failed", rc);
443 rc = rc2;
444 }
445 }
446 else
447 vboxPushVBoxError(stacktop, "vboxConnectToVBoxTray failed", rc);
448 }
449 else
450 vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the timeout value", rc);
451 }
452 else
453 vboxPushVBoxError(stacktop, "MyUtf16ToUInt32 failed on the type value", rc);
454 }
455 else
456 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the title text", rc);
457 }
458 else
459 vboxPushVBoxError(stacktop, "RTUtf16ToUtf8Ex failed on the message text", rc);
460 }
461 else
462 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Out of memory!");
463 }
464 else
465 VBOX_PUSH_STRING_LITERAL(stacktop, "Error: Too few parameters on the stack!");
466 vboxFreeStackEntry(pTimeoutEntry);
467 vboxFreeStackEntry(pTypeEntry);
468 vboxFreeStackEntry(pTitleEntry);
469 vboxFreeStackEntry(pMsgEntry);
470}
471
472/**
473 * Dumps the UI log to a file in UTF-8 format.
474 *
475 * Does not return any values on the stack.
476 *
477 * @param hWndParent Window handle of parent.
478 * @param string_size Size of variable string.
479 * @param variables The actual variable string.
480 * @param stacktop Pointer to a pointer to the current stack.
481 * @param extra Extra parameters.
482 */
483VBOXINSTALLHELPER_EXPORT DumpLog(HWND hWndParent, int string_size, WCHAR *variables, stack_t **stacktop,
484 extra_parameters *extra)
485{
486 RT_NOREF(string_size, variables, extra);
487
488 /*
489 * Get parameters from the stack.
490 */
491 stack_t * const pFilename = vboxPopStack(stacktop);
492 if (pFilename)
493 {
494 /*
495 * Open the output file.
496 */
497 HANDLE hFile = CreateFileW(pFilename->text, GENERIC_WRITE, FILE_SHARE_READ, NULL /*pSecAttr*/, CREATE_ALWAYS,
498 FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
499 if (hFile != NULL)
500 {
501 DWORD dwIgn;
502
503 /*
504 * Locate the list view widget.
505 */
506 HWND hWndDialog = FindWindowExW(hWndParent, NULL /*hWndChildAfter*/, L"#32770" /*pwszClass*/, NULL /*pwszTitle*/);
507 if (hWndDialog)
508 {
509 HWND hWndList = FindWindowExW(hWndDialog, NULL /*hWndChildAfter*/, L"SysListView32", NULL /*pwszTitle*/);
510 if (hWndList != NULL)
511 {
512 uint32_t const cLines = (uint32_t)SendMessageW(hWndList, LVM_GETITEMCOUNT, 0, 0);
513 if (cLines > 0)
514 {
515 /* Allocate a buffer for retriving the text. */
516 uint32_t cwcBuf = RT_MAX(string_size + 16, _8K);
517 wchar_t *pwszBuf = (wchar_t *)RTMemTmpAlloc(cwcBuf * sizeof(wchar_t));
518 wchar_t * const pwszBufFree = pwszBuf;
519 if (!pwszBuf)
520 {
521 cwcBuf = _4K;
522 pwszBuf = (wchar_t *)alloca(cwcBuf * sizeof(wchar_t));
523 }
524
525 /*
526 * Retreive the lines and write them to the output file.
527 */
528 for (uint32_t iLine = 0; iLine < cLines; iLine++)
529 {
530 LVITEMW Item =
531 {
532 /* .mask = */ 0,
533 /* .iItem = */ (int)iLine,
534 /* .iSubItem = */ 0,
535 /* .state = */ 0,
536 /* .stateMask = */ 0,
537 /* .pszText = */ pwszBuf,
538 /* .cchTextMax = */ (int)cwcBuf,
539 };
540 uint32_t const cwcRet = (uint32_t)SendMessageW(hWndList, LVM_GETITEMTEXT, iLine, (LPARAM)&Item);
541 if (cwcRet < cwcBuf)
542 {
543 pwszBuf[cwcRet] = '\0';
544 bool fNeedsNewline = cwcRet + 2 >= cwcBuf;
545 if (!fNeedsNewline)
546 {
547 pwszBuf[cwcRet + 0] = '\r';
548 pwszBuf[cwcRet + 1] = '\n';
549 pwszBuf[cwcRet + 2] = '\0';
550 }
551
552 char *pszUtf8;
553 int rc = RTUtf16ToUtf8(pwszBuf, &pszUtf8);
554 if (RT_SUCCESS(rc))
555 {
556 WriteFile(hFile, pszUtf8, (DWORD)strlen(pszUtf8), &dwIgn, NULL);
557 if (fNeedsNewline)
558 WriteFile(hFile, RT_STR_TUPLE("\r\n"), &dwIgn, NULL);
559 RTStrFree(pszUtf8);
560 }
561 else
562 WriteFile(hFile, RT_STR_TUPLE("!RTUtf16ToUtf8 failed!\r\n"), &dwIgn, NULL);
563 }
564 else
565 WriteFile(hFile, RT_STR_TUPLE("!LVM_GETITEMTEXT overflow!\r\n"), &dwIgn, NULL);
566 } /* for loop*/
567
568 RTMemTmpFree(pwszBufFree);
569 }
570 else
571 WriteFile(hFile, RT_STR_TUPLE("Log is empty.\r\n"), &dwIgn, NULL);
572 }
573 else
574 WriteFile(hFile, RT_STR_TUPLE("FindWindowEx failed to locate the log control!\r\n"), &dwIgn, NULL);
575 }
576 else
577 WriteFile(hFile, RT_STR_TUPLE("FindWindowEx failed to locate dialog windows!\r\n"), &dwIgn, NULL);
578 CloseHandle(hFile);
579 }
580 }
581 vboxFreeStackEntry(pFilename);
582}
583
584BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved)
585{
586 RT_NOREF(pReserved);
587
588 g_hInstance = (HINSTANCE)hInst;
589
590 switch (uReason)
591 {
592 case DLL_PROCESS_ATTACH:
593 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
594 break;
595
596 case DLL_PROCESS_DETACH:
597 break;
598
599 case DLL_THREAD_ATTACH:
600 break;
601
602 case DLL_THREAD_DETACH:
603 break;
604
605 default:
606 break;
607 }
608
609 return TRUE;
610}
611
Note: See TracBrowser for help on using the repository browser.

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