VirtualBox

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

Last change on this file since 91669 was 84735, checked in by vboxsync, 5 years ago

Add/NT/Installer: WRP workaround is not needed any more, bugref:9725

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
Line 
1/* $Id: VBoxGuestInstallHelper.cpp 84735 2020-06-09 10:47:05Z 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-2020 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23#include <iprt/win/windows.h>
24#include <stdlib.h>
25#include <tchar.h>
26#include <strsafe.h>
27#pragma warning(push)
28#pragma warning(disable: 4995) /* warning C4995: 'lstrcpyA': name was marked as #pragma deprecated */
29#include "exdll.h"
30#pragma warning(pop)
31
32#include <iprt/err.h>
33#include <iprt/initterm.h>
34#include <iprt/ldr.h>
35#include <iprt/localipc.h>
36#include <iprt/mem.h>
37#include <iprt/process.h>
38#include <iprt/string.h>
39#ifdef UNICODE
40# include <iprt/utf16.h>
41#endif
42
43/* Required structures/defines of VBoxTray. */
44#include "../../VBoxTray/VBoxTrayMsg.h"
45
46
47/*********************************************************************************************************************************
48* Defined Constants And Macros *
49*********************************************************************************************************************************/
50#define VBOXINSTALLHELPER_EXPORT extern "C" void __declspec(dllexport)
51
52
53/*********************************************************************************************************************************
54* Structures and Typedefs *
55*********************************************************************************************************************************/
56typedef DWORD (WINAPI *PFNSFCFILEEXCEPTION)(DWORD param1, PWCHAR param2, DWORD param3);
57
58
59/*********************************************************************************************************************************
60* Global Variables *
61*********************************************************************************************************************************/
62HINSTANCE g_hInstance;
63HWND g_hwndParent;
64
65/**
66 * @todo Clean up this DLL, use more IPRT in here!
67 */
68
69/**
70 * Pops (gets) a value from the internal NSIS stack.
71 * Since the supplied popstring() method easily can cause buffer
72 * overflows, use vboxPopString() instead!
73 *
74 * @return VBox status code.
75 * @param pszDest Pointer to pre-allocated string to store result.
76 * @param cchDest Size (in characters) of pre-allocated string.
77 */
78static int vboxPopString(TCHAR *pszDest, size_t cchDest)
79{
80 int rc = VINF_SUCCESS;
81
82 if (!g_stacktop || !*g_stacktop)
83 {
84 rc = VERR_NO_DATA;
85 }
86 else
87 {
88 stack_t *pStack = (*g_stacktop);
89 AssertPtr(pStack);
90
91 HRESULT hr = StringCchCopy(pszDest, cchDest, pStack->text);
92 if (SUCCEEDED(hr))
93 {
94 *g_stacktop = pStack->next;
95 GlobalFree((HGLOBAL)pStack);
96 }
97 else
98 rc = VERR_INVALID_PARAMETER;
99 }
100 return rc;
101}
102
103static int vboxPopULong(PULONG pulValue)
104{
105 int rc = VINF_SUCCESS;
106
107 if (!g_stacktop || !*g_stacktop)
108 {
109 rc = VERR_NO_DATA;
110 }
111 else
112 {
113 stack_t *pStack = (*g_stacktop);
114 AssertPtr(pStack);
115
116 *pulValue = _tcstoul(pStack->text, NULL, 10 /* Base */);
117
118 *g_stacktop = pStack->next;
119 GlobalFree((HGLOBAL)pStack);
120 }
121
122 return rc;
123}
124
125static void vboxPushHResultAsString(HRESULT hr)
126{
127 TCHAR szErr[NSIS_MAX_STRLEN];
128 if (FAILED(hr))
129 {
130 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szErr, MAX_PATH, NULL))
131 szErr[MAX_PATH] = '\0';
132 else
133 StringCchPrintf(szErr, sizeof(szErr),
134 _T("FormatMessage failed! Error = %ld"), GetLastError());
135 }
136 else
137 StringCchPrintf(szErr, sizeof(szErr), _T("0"));
138 pushstring(szErr);
139}
140
141static void vboxPushRcAsString(int rc)
142{
143 TCHAR szErr[NSIS_MAX_STRLEN];
144 if (RT_FAILURE(rc))
145 {
146 static const char s_szPrefix[] = "Error: ";
147 AssertCompile(NSIS_MAX_STRLEN > sizeof(s_szPrefix) + 32);
148#ifdef UNICODE
149 char szTmp[80];
150 memcpy(szTmp, s_szPrefix, sizeof(s_szPrefix));
151 RTErrQueryDefine(rc, &szTmp[sizeof(s_szPrefix) - 1], sizeof(szTmp) - sizeof(s_szPrefix) - 1, false);
152
153 RT_ZERO(szErr);
154 PRTUTF16 pwszDst = szErr;
155 RTStrToUtf16Ex(szTmp, RTSTR_MAX, &pwszDst, RT_ELEMENTS(szErr), NULL);
156#else
157 memcpy(szErr, s_szPrefix, sizeof(s_szPrefix));
158 RTErrQueryDefine(rc, &szErr[sizeof(s_szPrefix) - 1], sizeof(szErr) - sizeof(s_szPrefix) - 1, false);
159#endif
160 }
161 else
162 {
163 szErr[0] = '0';
164 szErr[1] = '\0';
165 }
166
167 pushstring(szErr);
168}
169
170/**
171 * Connects to VBoxTray IPC under the behalf of the user running
172 * in the current thread context.
173 *
174 * @return IPRT status code.
175 * @param phSession Where to store the IPC session.
176 */
177static int vboxConnectToVBoxTray(RTLOCALIPCSESSION *phSession)
178{
179 char szPipeName[512 + sizeof(VBOXTRAY_IPC_PIPE_PREFIX)];
180 memcpy(szPipeName, VBOXTRAY_IPC_PIPE_PREFIX, sizeof(VBOXTRAY_IPC_PIPE_PREFIX));
181 int rc = RTProcQueryUsername(NIL_RTPROCESS,
182 &szPipeName[sizeof(VBOXTRAY_IPC_PIPE_PREFIX) - 1],
183 sizeof(szPipeName) - sizeof(VBOXTRAY_IPC_PIPE_PREFIX) + 1,
184 NULL /*pcbUser*/);
185 if (RT_SUCCESS(rc))
186 rc = RTLocalIpcSessionConnect(phSession, szPipeName, RTLOCALIPC_FLAGS_NATIVE_NAME);
187 return rc;
188}
189
190
191/**
192 * Retrieves a file's architecture (x86 or amd64).
193 * Outputs "x86", "amd64" or an error message (if not found/invalid) on stack.
194 *
195 * @param hwndParent Window handle of parent.
196 * @param string_size Size of variable string.
197 * @param variables The actual variable string.
198 * @param stacktop Pointer to a pointer to the current stack.
199 * @param extra Extra parameters. Currently unused.
200 */
201VBOXINSTALLHELPER_EXPORT FileGetArchitecture(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
202 extra_parameters *extra)
203{
204 RT_NOREF(hwndParent, extra);
205
206 EXDLL_INIT();
207
208 TCHAR szFile[MAX_PATH + 1];
209 int rc = vboxPopString(szFile, sizeof(szFile) / sizeof(TCHAR));
210 if (RT_SUCCESS(rc))
211 {
212#ifdef UNICODE
213 char *pszFileUtf8;
214 rc = RTUtf16ToUtf8(szFile, &pszFileUtf8);
215 if (RT_SUCCESS(rc))
216 {
217#else
218 char *pszFileUtf8 = szFile;
219#endif
220 RTLDRMOD hLdrMod;
221 rc = RTLdrOpen(pszFileUtf8, RTLDR_O_FOR_VALIDATION, RTLDRARCH_WHATEVER, &hLdrMod);
222 if (RT_SUCCESS(rc))
223 {
224 if (RTLdrGetFormat(hLdrMod) == RTLDRFMT_PE)
225 {
226 RTLDRARCH enmLdrArch = RTLdrGetArch(hLdrMod);
227 switch (enmLdrArch)
228 {
229 case RTLDRARCH_X86_32:
230 pushstring(_T("x86"));
231 break;
232
233 case RTLDRARCH_AMD64:
234 pushstring(_T("amd64"));
235 break;
236
237 default:
238 pushstring(_T("Error: Unknown / invalid architecture"));
239 break;
240 }
241 }
242 else
243 pushstring(_T("Error: Unknown / invalid PE signature"));
244
245 RTLdrClose(hLdrMod);
246 }
247 else
248 pushstring(_T("Error: Could not open file"));
249#ifdef UNICODE
250 RTStrFree(pszFileUtf8);
251 }
252#endif
253 }
254 else
255 pushstring(_T("Error: Could not retrieve file name"));
256}
257
258/**
259 * Retrieves a file's vendor.
260 * Outputs the vendor's name or an error message (if not found/invalid) on stack.
261 *
262 * @param hwndParent Window handle of parent.
263 * @param string_size Size of variable string.
264 * @param variables The actual variable string.
265 * @param stacktop Pointer to a pointer to the current stack.
266 * @param extra Extra parameters. Currently unused.
267 */
268VBOXINSTALLHELPER_EXPORT FileGetVendor(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
269 extra_parameters *extra)
270{
271 RT_NOREF(hwndParent, extra);
272
273 EXDLL_INIT();
274
275 TCHAR szFile[MAX_PATH + 1];
276 int rc = vboxPopString(szFile, sizeof(szFile) / sizeof(TCHAR));
277 if (RT_SUCCESS(rc))
278 {
279 DWORD dwInfoSize = GetFileVersionInfoSize(szFile, NULL /* lpdwHandle */);
280 if (dwInfoSize)
281 {
282 void *pFileInfo = GlobalAlloc(GMEM_FIXED, dwInfoSize);
283 if (pFileInfo)
284 {
285 if (GetFileVersionInfo(szFile, 0, dwInfoSize, pFileInfo))
286 {
287 LPVOID pvInfo;
288 UINT puInfoLen;
289 if (VerQueryValue(pFileInfo, _T("\\VarFileInfo\\Translation"),
290 &pvInfo, &puInfoLen))
291 {
292 WORD wCodePage = LOWORD(*(DWORD*)pvInfo);
293 WORD wLanguageID = HIWORD(*(DWORD*)pvInfo);
294
295 TCHAR szQuery[MAX_PATH];
296 StringCchPrintf(szQuery, sizeof(szQuery), _T("StringFileInfo\\%04X%04X\\CompanyName"),
297 wCodePage, wLanguageID);
298
299 LPCTSTR pcData;
300 if (VerQueryValue(pFileInfo, szQuery, (void**)&pcData, &puInfoLen))
301 {
302 pushstring(pcData);
303 }
304 else
305 rc = VERR_NOT_FOUND;
306 }
307 else
308 rc = VERR_NOT_FOUND;
309 }
310 GlobalFree(pFileInfo);
311 }
312 else
313 rc = VERR_NO_MEMORY;
314 }
315 else
316 rc = VERR_NOT_FOUND;
317 }
318
319 if (RT_FAILURE(rc))
320 vboxPushRcAsString(rc);
321}
322
323/**
324 * Shows a balloon message using VBoxTray's notification area in the
325 * Windows task bar.
326 *
327 * @param hwndParent Window handle of parent.
328 * @param string_size Size of variable string.
329 * @param variables The actual variable string.
330 * @param stacktop Pointer to a pointer to the current stack.
331 * @param extra Extra parameters. Currently unused.
332 */
333VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop,
334 extra_parameters *extra)
335{
336 RT_NOREF(hwndParent, extra);
337
338 EXDLL_INIT();
339
340 TCHAR szMsg[256];
341 TCHAR szTitle[128];
342 int rc = vboxPopString(szMsg, sizeof(szMsg) / sizeof(TCHAR));
343 if (RT_SUCCESS(rc))
344 rc = vboxPopString(szTitle, sizeof(szTitle) / sizeof(TCHAR));
345
346 /** @todo Do we need to restore the stack on failure? */
347
348 if (RT_SUCCESS(rc))
349 {
350 RTR3InitDll(0);
351
352#ifdef UNICODE
353 char *pszMsgUtf8 = NULL;
354 char *pszTitleUtf8 = NULL;
355 rc = RTUtf16ToUtf8(szMsg, &pszMsgUtf8);
356 if (RT_SUCCESS(rc))
357 rc = RTUtf16ToUtf8(szTitle, &pszTitleUtf8);
358#else
359 char *pszMsgUtf8 = szMsg;
360 char *pszTitleUtf8 = szTitle;
361#endif
362 if (RT_SUCCESS(rc))
363 {
364 /* We use UTF-8 for the IPC data. */
365 uint32_t cbMsg = sizeof(VBOXTRAYIPCMSG_SHOWBALLOONMSG)
366 + (uint32_t)strlen(pszMsgUtf8) + 1 /* Include terminating zero */
367 + (uint32_t)strlen(pszTitleUtf8) + 1; /* Ditto. */
368 Assert(cbMsg);
369 PVBOXTRAYIPCMSG_SHOWBALLOONMSG pIpcMsg = (PVBOXTRAYIPCMSG_SHOWBALLOONMSG)RTMemAlloc(cbMsg);
370 if (pIpcMsg)
371 {
372 /* Stuff in the strings. */
373 memcpy(pIpcMsg->szMsgContent, pszMsgUtf8, strlen(pszMsgUtf8) + 1);
374 memcpy(pIpcMsg->szMsgTitle, pszTitleUtf8, strlen(pszTitleUtf8) + 1);
375
376 /* Pop off the values in reverse order from the stack. */
377 rc = vboxPopULong((ULONG *)&pIpcMsg->uType);
378 if (RT_SUCCESS(rc))
379 rc = vboxPopULong((ULONG *)&pIpcMsg->uShowMS);
380
381 if (RT_SUCCESS(rc))
382 {
383 RTLOCALIPCSESSION hSession = 0;
384 rc = vboxConnectToVBoxTray(&hSession);
385 if (RT_SUCCESS(rc))
386 {
387 VBOXTRAYIPCHEADER ipcHdr = { VBOXTRAY_IPC_HDR_MAGIC, 0 /* Header version */,
388 VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG, cbMsg };
389
390 rc = RTLocalIpcSessionWrite(hSession, &ipcHdr, sizeof(ipcHdr));
391 if (RT_SUCCESS(rc))
392 rc = RTLocalIpcSessionWrite(hSession, pIpcMsg, cbMsg);
393
394 int rc2 = RTLocalIpcSessionClose(hSession);
395 if (RT_SUCCESS(rc))
396 rc = rc2;
397 }
398 }
399
400 RTMemFree(pIpcMsg);
401 }
402 else
403 rc = VERR_NO_MEMORY;
404#ifdef UNICODE
405 RTStrFree(pszMsgUtf8);
406 RTStrFree(pszTitleUtf8);
407#endif
408 }
409 }
410
411 vboxPushRcAsString(rc);
412}
413
414BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved)
415{
416 RT_NOREF(pReserved);
417
418 g_hInstance = (HINSTANCE)hInst;
419
420 switch (uReason)
421 {
422 case DLL_PROCESS_ATTACH:
423 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
424 break;
425
426 case DLL_PROCESS_DETACH:
427 break;
428
429 case DLL_THREAD_ATTACH:
430 break;
431
432 case DLL_THREAD_DETACH:
433 break;
434
435 default:
436 break;
437 }
438
439 return TRUE;
440}
441
Note: See TracBrowser for help on using the repository browser.

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