VirtualBox

source: vbox/trunk/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp@ 86777

Last change on this file since 86777 was 86777, checked in by vboxsync, 4 years ago

Windows host installer: Rewritten Python installation support to now utilize IPRT for most tasks, also now supporting

  • Python 3 support.
  • Python Core installer support for user-based installs (as fallback only).
  • Automatic (simple) validation of the VBox API after installation.

[Build fix]. bugref:9855

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.9 KB
Line 
1/* $Id: VBoxInstallHelper.cpp 86777 2020-10-30 18:37:15Z vboxsync $ */
2/** @file
3 * VBoxInstallHelper - Various helper routines for Windows host installer.
4 */
5
6/*
7 * Copyright (C) 2008-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#ifdef VBOX_WITH_NETFLT
23# include "VBox/VBoxNetCfg-win.h"
24# include "VBox/VBoxDrvCfg-win.h"
25#endif /* VBOX_WITH_NETFLT */
26
27#include <VBox/version.h>
28
29#include <wchar.h>
30#include <stdio.h>
31
32#include <msi.h>
33#include <msiquery.h>
34
35#define _WIN32_DCOM
36#include <iprt/win/windows.h>
37
38#include <assert.h>
39#include <shellapi.h>
40#define INITGUID
41#include <guiddef.h>
42#include <cfgmgr32.h>
43#include <devguid.h>
44
45#include <iprt/env.h>
46#include <iprt/err.h>
47#include <iprt/initterm.h>
48#include <iprt/path.h>
49#include <iprt/process.h>
50#include <iprt/utf16.h>
51
52#include <iprt/win/objbase.h>
53#include <iprt/win/setupapi.h>
54#include <iprt/win/shlobj.h>
55
56#include "VBoxCommon.h"
57
58#ifndef VBOX_OSE
59# include "internal/VBoxSerial.h"
60#endif
61
62
63/*********************************************************************************************************************************
64* Defined Constants And Macros *
65*********************************************************************************************************************************/
66#ifdef DEBUG
67# define NonStandardAssert(_expr) assert(_expr)
68#else
69# define NonStandardAssert(_expr) do{ }while(0)
70#endif
71
72#define MY_WTEXT_HLP(a_str) L##a_str
73#define MY_WTEXT(a_str) MY_WTEXT_HLP(a_str)
74
75
76BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved)
77{
78 RT_NOREF(hInst, pReserved);
79
80 switch (uReason)
81 {
82 case DLL_PROCESS_ATTACH:
83 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
84 break;
85
86 case DLL_PROCESS_DETACH:
87 break;
88
89 case DLL_THREAD_ATTACH:
90 break;
91
92 case DLL_THREAD_DETACH:
93 break;
94
95 default:
96 break;
97 }
98
99 return TRUE;
100}
101
102static int logStringF(MSIHANDLE hInstall, const char *pcszFmt, ...)
103{
104 PMSIHANDLE hMSI = MsiCreateRecord(2 /* cParms */);
105 if (!hMSI)
106 return VERR_ACCESS_DENIED;
107
108 RTUTF16 wszBuf[_1K] = { 0 };
109
110 va_list va;
111 va_start(va, pcszFmt);
112 ssize_t cwch = RTUtf16PrintfV(wszBuf, RT_ELEMENTS(wszBuf), pcszFmt, va);
113 va_end(va);
114
115 if (cwch <= 0)
116 return VERR_BUFFER_OVERFLOW;
117
118 MsiRecordSetStringW(hMSI, 0, wszBuf);
119 MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), hMSI);
120 MsiCloseHandle(hMSI);
121
122 return VINF_SUCCESS;
123}
124
125UINT __stdcall IsSerialCheckNeeded(MSIHANDLE hModule)
126{
127#ifndef VBOX_OSE
128 /*BOOL fRet =*/ serialCheckNeeded(hModule);
129#else
130 RT_NOREF(hModule);
131#endif
132 return ERROR_SUCCESS;
133}
134
135UINT __stdcall CheckSerial(MSIHANDLE hModule)
136{
137#ifndef VBOX_OSE
138 /*BOOL bRet =*/ serialIsValid(hModule);
139#else
140 RT_NOREF(hModule);
141#endif
142 return ERROR_SUCCESS;
143}
144
145/**
146 * Tries to retrieve the Python installation path on the system.
147 *
148 * @returns VBox status code.
149 * @param hModule Windows installer module handle.
150 * @param hKeyRoot Registry root key to use, e.g. HKEY_LOCAL_MACHINE.
151 * @param ppszPath Where to store the allocated Python path on success.
152 * Must be free'd by the caller using RTStrFree().
153 */
154static int getPythonPath(MSIHANDLE hModule, HKEY hKeyRoot, char **ppszPath)
155{
156 HKEY hkPythonCore = NULL;
157 LSTATUS dwErr = RegOpenKeyExW(hKeyRoot, L"SOFTWARE\\Python\\PythonCore", 0, KEY_READ, &hkPythonCore);
158 if (dwErr != ERROR_SUCCESS)
159 return RTErrConvertFromWin32(dwErr);
160
161 char *pszPythonPath = NULL;
162
163 RTUTF16 wszKey [RTPATH_MAX] = { 0 };
164 RTUTF16 wszKey2[RTPATH_MAX] = { 0 };
165 RTUTF16 wszVal [RTPATH_MAX] = { 0 };
166
167 int rc = VINF_SUCCESS;
168
169 /* Note: The loop ASSUMES that later found versions are higher, e.g. newer Python versions.
170 * For now we always go by the newest version. */
171 for (int i = 0;; ++i)
172 {
173 DWORD dwKey = sizeof(wszKey);
174 DWORD dwKeyType = REG_SZ;
175
176 dwErr = RegEnumKeyExW(hkPythonCore, i, wszKey, &dwKey, NULL, NULL, NULL, NULL);
177 if (dwErr != ERROR_SUCCESS || dwKey <= 0)
178 break;
179 AssertBreakStmt(dwKey <= sizeof(wszKey), VERR_BUFFER_OVERFLOW);
180
181 if (RTUtf16Printf(wszKey2, sizeof(wszKey2), "%ls\\InstallPath", wszKey) <= 0)
182 {
183 rc = VERR_BUFFER_OVERFLOW;
184 break;
185 }
186
187 dwKey = sizeof(wszKey2); /* Re-initialize length. */
188
189 HKEY hkPythonInstPath = NULL;
190 dwErr = RegOpenKeyExW(hkPythonCore, wszKey2, 0, KEY_READ, &hkPythonInstPath);
191 if (dwErr != ERROR_SUCCESS)
192 continue;
193
194 dwErr = RegQueryValueExW(hkPythonInstPath, L"", NULL, &dwKeyType, (LPBYTE)wszVal, &dwKey);
195 if (dwErr == ERROR_SUCCESS)
196 logStringF(hModule, "InstallPythonAPI: Path \"%ls\" found.", wszVal);
197
198 if (pszPythonPath) /* Free former path, if any. */
199 {
200 RTStrFree(pszPythonPath);
201 pszPythonPath = NULL;
202 }
203
204 rc = RTUtf16ToUtf8(wszVal, &pszPythonPath);
205 AssertRCBreak(rc);
206
207 if (!RTPathExists(pszPythonPath))
208 {
209 logStringF(hModule, "InstallPythonAPI: Warning: Path \"%s\" does not exist, skipping.", wszVal);
210 rc = VERR_PATH_NOT_FOUND;
211 }
212
213 RegCloseKey(hkPythonInstPath);
214 }
215
216 RegCloseKey(hkPythonCore);
217
218 if (RT_FAILURE(rc))
219 {
220 RTStrFree(pszPythonPath);
221 }
222 else
223 *ppszPath = pszPythonPath;
224
225 return rc;
226}
227
228/**
229 * Waits for a started process to terminate.
230 *
231 * @returns VBox status code.
232 * @param Process Handle of process to wait for.
233 * @param msTimeout Timeout (in ms) to wait for process to terminate.
234 * @param pProcSts Pointer to process status on return.
235 */
236int procWait(RTPROCESS Process, RTMSINTERVAL msTimeout, PRTPROCSTATUS pProcSts)
237{
238 uint64_t tsStartMs = RTTimeMilliTS();
239
240 while (RTTimeMilliTS() - tsStartMs <= msTimeout)
241 {
242 int rc = RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, pProcSts);
243 if (rc == VERR_PROCESS_RUNNING)
244 continue;
245 else if (RT_FAILURE(rc))
246 return rc;
247
248 if ( pProcSts->iStatus != 0
249 || pProcSts->enmReason != RTPROCEXITREASON_NORMAL)
250 {
251 rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
252 }
253
254 return VINF_SUCCESS;
255 }
256
257 return VERR_TIMEOUT;
258}
259
260/**
261 * Checks for a valid Python installation on the system.
262 *
263 * Called from the MSI installer as custom action.
264 *
265 * @returns Always ERROR_SUCCESS.
266 * Sets public property VBOX_PYTHON_INSTALLED to "0" (false) or "1" (success).
267 * Sets public property VBOX_PYTHON_PATH to the Python installation path (if found).
268 *
269 * @param hModule Windows installer module handle.
270 */
271UINT __stdcall IsPythonInstalled(MSIHANDLE hModule)
272{
273 char *pszPythonPath;
274 int rc = getPythonPath(hModule, HKEY_LOCAL_MACHINE, &pszPythonPath);
275 if (RT_FAILURE(rc))
276 rc = getPythonPath(hModule, HKEY_CURRENT_USER, &pszPythonPath);
277
278 if (RT_SUCCESS(rc))
279 {
280 logStringF(hModule, "IsPythonInstalled: Python installation found at \"%s\"", pszPythonPath);
281
282 PRTUTF16 pwszPythonPath;
283 rc = RTStrToUtf16(pszPythonPath, &pwszPythonPath);
284 if (RT_SUCCESS(rc))
285 {
286 VBoxSetMsiProp(hModule, L"VBOX_PYTHON_PATH", pwszPythonPath);
287
288 RTUtf16Free(pwszPythonPath);
289 }
290 else
291 logStringF(hModule, "IsPythonInstalled: Error: Unable to convert path, rc=%Rrc", rc);
292
293 RTStrFree(pszPythonPath);
294 }
295 else
296 logStringF(hModule, "IsPythonInstalled: Error: No suitable Python installation found (%Rrc), skipping installation.", rc);
297
298 VBoxSetMsiProp(hModule, L"VBOX_PYTHON_INSTALLED", RT_SUCCESS(rc) ? L"1" : L"0");
299
300 return ERROR_SUCCESS; /* Never return failure. */
301}
302
303/**
304 * Installs and compiles the VBox Python bindings.
305 *
306 * Called from the MSI installer as custom action.
307 *
308 * @returns Always ERROR_SUCCESS.
309 * Sets public property VBOX_API_INSTALLED to "0" (false) or "1" (success).
310 *
311 * @param hModule Windows installer module handle.
312 */
313UINT __stdcall InstallPythonAPI(MSIHANDLE hModule)
314{
315 logStringF(hModule, "InstallPythonAPI: Checking for installed Python environment(s) ...");
316
317 char *pszPythonPath;
318 int rc = getPythonPath(hModule, HKEY_LOCAL_MACHINE, &pszPythonPath);
319 if (RT_FAILURE(rc))
320 rc = getPythonPath(hModule, HKEY_CURRENT_USER, &pszPythonPath);
321
322 if (RT_FAILURE(rc))
323 {
324 VBoxSetMsiProp(hModule, L"VBOX_API_INSTALLED", L"0");
325
326 logStringF(hModule, "InstallPythonAPI: Python seems not to be installed (%Rrc); please download + install the Python Core package.", rc);
327 return ERROR_SUCCESS;
328 }
329
330 logStringF(hModule, "InstallPythonAPI: Python installation found at \"%s\".", pszPythonPath);
331 logStringF(hModule, "InstallPythonAPI: Checking for win32api extensions ...");
332
333 uint32_t fProcess = 0;
334#ifndef DEBUG
335 fProcess |= RTPROC_FLAGS_HIDDEN;
336#endif
337
338 char szPythonPath[RTPATH_MAX] = { 0 };
339 rc = RTPathAppend(szPythonPath, sizeof(szPythonPath), pszPythonPath);
340 if (RT_SUCCESS(rc))
341 {
342 rc = RTPathAppend(szPythonPath, sizeof(szPythonPath), "python.exe");
343 if (RT_SUCCESS(rc))
344 {
345 /*
346 * Check if importing the win32api module works.
347 * This is a prerequisite for setting up the VBox API.
348 */
349 RTPROCESS Process;
350 RT_ZERO(Process);
351 const char *papszArgs[4] = { szPythonPath, "-c", "import win32api", NULL};
352 rc = RTProcCreate(szPythonPath, papszArgs, RTENV_DEFAULT, fProcess, &Process);
353 if (RT_SUCCESS(rc))
354 {
355 RTPROCSTATUS ProcSts;
356 rc = procWait(Process, RT_MS_30SEC, &ProcSts);
357 if (RT_FAILURE(rc))
358 logStringF(hModule, "InstallPythonAPI: Importing the win32api failed with %d (exit reason: %d)\n",
359 ProcSts.iStatus, ProcSts.enmReason);
360 }
361 }
362 }
363
364 /*
365 * Set up the VBox API.
366 */
367 if (RT_SUCCESS(rc))
368 {
369 /* Get the VBox API setup string. */
370 char *pszVBoxSDKPath;
371 rc = VBoxGetMsiPropUtf8(hModule, "CustomActionData", &pszVBoxSDKPath);
372 if (RT_SUCCESS(rc))
373 {
374 /* Make sure our current working directory is the VBox installation path. */
375 rc = RTPathSetCurrent(pszVBoxSDKPath);
376 if (RT_SUCCESS(rc))
377 {
378 /* Set required environment variables. */
379 rc = RTEnvSet("VBOX_INSTALL_PATH", pszVBoxSDKPath);
380 if (RT_SUCCESS(rc))
381 {
382 RTPROCSTATUS ProcSts;
383 RT_ZERO(ProcSts);
384
385 logStringF(hModule, "InstallPythonAPI: Invoking vboxapisetup.py in \"%s\" ...\n", pszVBoxSDKPath);
386
387 RTPROCESS Process;
388 RT_ZERO(Process);
389 const char *papszArgs[4] = { szPythonPath, "vboxapisetup.py", "install", NULL};
390 rc = RTProcCreate(szPythonPath, papszArgs, RTENV_DEFAULT, fProcess, &Process);
391 if (RT_SUCCESS(rc))
392 {
393 rc = procWait(Process, RT_MS_30SEC, &ProcSts);
394 if (RT_SUCCESS(rc))
395 logStringF(hModule, "InstallPythonAPI: Installation of vboxapisetup.py successful\n");
396 }
397
398 if (RT_FAILURE(rc))
399 logStringF(hModule, "InstallPythonAPI: Calling vboxapisetup.py failed with %Rrc (process status: %d, exit reason: %d)\n",
400 rc, ProcSts.iStatus, ProcSts.enmReason);
401 }
402 else
403 logStringF(hModule, "InstallPythonAPI: Could set environment variable VBOX_INSTALL_PATH, rc=%Rrc\n", rc);
404 }
405 else
406 logStringF(hModule, "InstallPythonAPI: Could set working directory to \"%s\", rc=%Rrc\n", pszVBoxSDKPath, rc);
407
408 RTStrFree(pszVBoxSDKPath);
409 }
410 else
411 logStringF(hModule, "InstallPythonAPI: Unable to retrieve VBox installation directory, rc=%Rrc\n", rc);
412 }
413
414 /*
415 * Do some sanity checking if the VBox API works.
416 */
417 if (RT_SUCCESS(rc))
418 {
419 logStringF(hModule, "InstallPythonAPI: Validating VBox API ...\n");
420
421 RTPROCSTATUS ProcSts;
422 RT_ZERO(ProcSts);
423
424 RTPROCESS Process;
425 RT_ZERO(Process);
426 const char *papszArgs[4] = { szPythonPath, "-c", "from vboxapi import VirtualBoxManager", NULL};
427 rc = RTProcCreate(szPythonPath, papszArgs, RTENV_DEFAULT, fProcess, &Process);
428 if (RT_SUCCESS(rc))
429 {
430 rc = procWait(Process, RT_MS_30SEC, &ProcSts);
431 if (RT_SUCCESS(rc))
432 logStringF(hModule, "InstallPythonAPI: VBox API looks good.\n");
433 }
434
435 if (RT_FAILURE(rc))
436 logStringF(hModule, "InstallPythonAPI: Validating VBox API failed with %Rrc (process status: %d, exit reason: %d)\n",
437 rc, ProcSts.iStatus, ProcSts.enmReason);
438 }
439
440 RTStrFree(pszPythonPath);
441
442 VBoxSetMsiProp(hModule, L"VBOX_API_INSTALLED", RT_SUCCESS(rc) ? L"1" : L"0");
443
444 if (RT_FAILURE(rc))
445 logStringF(hModule, "InstallPythonAPI: Installation failed with %Rrc\n", rc);
446
447 return ERROR_SUCCESS; /* Do not fail here. */
448}
449
450static LONG installBrandingValue(MSIHANDLE hModule,
451 const WCHAR *pwszFileName,
452 const WCHAR *pwszSection,
453 const WCHAR *pwszValue)
454{
455 LONG rc;
456 WCHAR wszValue[_MAX_PATH];
457 if (GetPrivateProfileStringW(pwszSection, pwszValue, NULL,
458 wszValue, sizeof(wszValue), pwszFileName) > 0)
459 {
460 HKEY hkBranding;
461 WCHAR wszKey[_MAX_PATH];
462
463 if (wcsicmp(L"General", pwszSection) != 0)
464 swprintf_s(wszKey, RT_ELEMENTS(wszKey), L"SOFTWARE\\%S\\VirtualBox\\Branding\\%s", VBOX_VENDOR_SHORT, pwszSection);
465 else
466 swprintf_s(wszKey, RT_ELEMENTS(wszKey), L"SOFTWARE\\%S\\VirtualBox\\Branding", VBOX_VENDOR_SHORT);
467
468 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszKey, 0, KEY_WRITE, &hkBranding);
469 if (rc == ERROR_SUCCESS)
470 {
471 rc = RegSetValueExW(hkBranding,
472 pwszValue,
473 NULL,
474 REG_SZ,
475 (BYTE *)wszValue,
476 (DWORD)wcslen(wszValue));
477 if (rc != ERROR_SUCCESS)
478 logStringF(hModule, "InstallBranding: Could not write value %s! Error %ld", pwszValue, rc);
479 RegCloseKey (hkBranding);
480 }
481 }
482 else
483 rc = ERROR_NOT_FOUND;
484 return rc;
485}
486
487UINT CopyDir(MSIHANDLE hModule, const WCHAR *pwszDestDir, const WCHAR *pwszSourceDir)
488{
489 UINT rc;
490 WCHAR wszDest[_MAX_PATH + 1];
491 WCHAR wszSource[_MAX_PATH + 1];
492
493 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, L'\0');
494 swprintf_s(wszSource, RT_ELEMENTS(wszSource), L"%s%c", pwszSourceDir, L'\0');
495
496 SHFILEOPSTRUCTW s = {0};
497 s.hwnd = NULL;
498 s.wFunc = FO_COPY;
499 s.pTo = wszDest;
500 s.pFrom = wszSource;
501 s.fFlags = FOF_SILENT |
502 FOF_NOCONFIRMATION |
503 FOF_NOCONFIRMMKDIR |
504 FOF_NOERRORUI;
505
506 logStringF(hModule, "CopyDir: DestDir=%s, SourceDir=%s", wszDest, wszSource);
507 int r = SHFileOperationW(&s);
508 if (r != 0)
509 {
510 logStringF(hModule, "CopyDir: Copy operation returned status 0x%x", r);
511 rc = ERROR_GEN_FAILURE;
512 }
513 else
514 rc = ERROR_SUCCESS;
515 return rc;
516}
517
518UINT RemoveDir(MSIHANDLE hModule, const WCHAR *pwszDestDir)
519{
520 UINT rc;
521 WCHAR wszDest[_MAX_PATH + 1];
522
523 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, L'\0');
524
525 SHFILEOPSTRUCTW s = {0};
526 s.hwnd = NULL;
527 s.wFunc = FO_DELETE;
528 s.pFrom = wszDest;
529 s.fFlags = FOF_SILENT
530 | FOF_NOCONFIRMATION
531 | FOF_NOCONFIRMMKDIR
532 | FOF_NOERRORUI;
533
534 logStringF(hModule, "RemoveDir: DestDir=%s", wszDest);
535 int r = SHFileOperationW(&s);
536 if (r != 0)
537 {
538 logStringF(hModule, "RemoveDir: Remove operation returned status 0x%x", r);
539 rc = ERROR_GEN_FAILURE;
540 }
541 else
542 rc = ERROR_SUCCESS;
543 return rc;
544}
545
546UINT RenameDir(MSIHANDLE hModule, const WCHAR *pwszDestDir, const WCHAR *pwszSourceDir)
547{
548 UINT rc;
549 WCHAR wszDest[_MAX_PATH + 1];
550 WCHAR wszSource[_MAX_PATH + 1];
551
552 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, L'\0');
553 swprintf_s(wszSource, RT_ELEMENTS(wszSource), L"%s%c", pwszSourceDir, L'\0');
554
555 SHFILEOPSTRUCTW s = {0};
556 s.hwnd = NULL;
557 s.wFunc = FO_RENAME;
558 s.pTo = wszDest;
559 s.pFrom = wszSource;
560 s.fFlags = FOF_SILENT
561 | FOF_NOCONFIRMATION
562 | FOF_NOCONFIRMMKDIR
563 | FOF_NOERRORUI;
564
565 logStringF(hModule, "RenameDir: DestDir=%s, SourceDir=%s", wszDest, wszSource);
566 int r = SHFileOperationW(&s);
567 if (r != 0)
568 {
569 logStringF(hModule, "RenameDir: Rename operation returned status 0x%x", r);
570 rc = ERROR_GEN_FAILURE;
571 }
572 else
573 rc = ERROR_SUCCESS;
574 return rc;
575}
576
577UINT __stdcall UninstallBranding(MSIHANDLE hModule)
578{
579 UINT rc;
580 logStringF(hModule, "UninstallBranding: Handling branding file ...");
581
582 WCHAR wszPathTargetDir[_MAX_PATH];
583 WCHAR wszPathDest[_MAX_PATH];
584
585 rc = VBoxGetMsiProp(hModule, L"CustomActionData", wszPathTargetDir, sizeof(wszPathTargetDir));
586 if (rc == ERROR_SUCCESS)
587 {
588 /** @todo Check trailing slash after %s. */
589/** @todo r=bird: using swprintf_s for formatting paths without checking for
590 * overflow not good. You're dodging the buffer overflow issue only to end up
591 * with incorrect behavior! (Truncated file/dir names)
592 *
593 * This applies almost to all swprintf_s calls in this file!!
594 */
595 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%scustom", wszPathTargetDir);
596 rc = RemoveDir(hModule, wszPathDest);
597 if (rc != ERROR_SUCCESS)
598 {
599 /* Check for hidden .custom directory and remove it. */
600 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%s.custom", wszPathTargetDir);
601 rc = RemoveDir(hModule, wszPathDest);
602 }
603 }
604
605 logStringF(hModule, "UninstallBranding: Handling done. (rc=%u (ignored))", rc);
606 return ERROR_SUCCESS; /* Do not fail here. */
607}
608
609UINT __stdcall InstallBranding(MSIHANDLE hModule)
610{
611 UINT rc;
612 logStringF(hModule, "InstallBranding: Handling branding file ...");
613
614 WCHAR wszPathMSI[_MAX_PATH];
615 rc = VBoxGetMsiProp(hModule, L"SOURCEDIR", wszPathMSI, sizeof(wszPathMSI));
616 if (rc == ERROR_SUCCESS)
617 {
618 WCHAR wszPathTargetDir[_MAX_PATH];
619 rc = VBoxGetMsiProp(hModule, L"CustomActionData", wszPathTargetDir, sizeof(wszPathTargetDir));
620 if (rc == ERROR_SUCCESS)
621 {
622 /** @todo Check for trailing slash after %s. */
623 WCHAR wszPathDest[_MAX_PATH];
624 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%s", wszPathTargetDir);
625
626 WCHAR wszPathSource[_MAX_PATH];
627 swprintf_s(wszPathSource, RT_ELEMENTS(wszPathSource), L"%s.custom", wszPathMSI);
628 rc = CopyDir(hModule, wszPathDest, wszPathSource);
629 if (rc == ERROR_SUCCESS)
630 {
631 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%scustom", wszPathTargetDir);
632 swprintf_s(wszPathSource, RT_ELEMENTS(wszPathSource), L"%s.custom", wszPathTargetDir);
633 rc = RenameDir(hModule, wszPathDest, wszPathSource);
634 }
635 }
636 }
637
638 logStringF(hModule, "InstallBranding: Handling done. (rc=%u (ignored))", rc);
639 return ERROR_SUCCESS; /* Do not fail here. */
640}
641
642#ifdef VBOX_WITH_NETFLT
643
644/** @todo should use some real VBox app name */
645#define VBOX_NETCFG_APP_NAME L"VirtualBox Installer"
646#define VBOX_NETCFG_MAX_RETRIES 10
647#define NETFLT_PT_INF_REL_PATH L"VBoxNetFlt.inf"
648#define NETFLT_MP_INF_REL_PATH L"VBoxNetFltM.inf"
649#define NETFLT_ID L"sun_VBoxNetFlt" /** @todo Needs to be changed (?). */
650#define NETADP_ID L"sun_VBoxNetAdp" /** @todo Needs to be changed (?). */
651
652#define NETLWF_INF_NAME L"VBoxNetLwf.inf"
653
654static MSIHANDLE g_hCurrentModule = NULL;
655
656static UINT _uninstallNetFlt(MSIHANDLE hModule);
657static UINT _uninstallNetLwf(MSIHANDLE hModule);
658
659static VOID vboxDrvLoggerCallback(VBOXDRVCFG_LOG_SEVERITY enmSeverity, char *pszMsg, void *pvContext)
660{
661 RT_NOREF1(pvContext);
662 switch (enmSeverity)
663 {
664 case VBOXDRVCFG_LOG_SEVERITY_FLOW:
665 case VBOXDRVCFG_LOG_SEVERITY_REGULAR:
666 break;
667 case VBOXDRVCFG_LOG_SEVERITY_REL:
668 if (g_hCurrentModule)
669 logStringF(g_hCurrentModule, pszMsg);
670 break;
671 default:
672 break;
673 }
674}
675
676static DECLCALLBACK(void) netCfgLoggerCallback(const char *pszString)
677{
678 if (g_hCurrentModule)
679 logStringF(g_hCurrentModule, pszString);
680}
681
682static VOID netCfgLoggerDisable()
683{
684 if (g_hCurrentModule)
685 {
686 VBoxNetCfgWinSetLogging(NULL);
687 g_hCurrentModule = NULL;
688 }
689}
690
691static VOID netCfgLoggerEnable(MSIHANDLE hModule)
692{
693 NonStandardAssert(hModule);
694
695 if (g_hCurrentModule)
696 netCfgLoggerDisable();
697
698 g_hCurrentModule = hModule;
699
700 VBoxNetCfgWinSetLogging(netCfgLoggerCallback);
701 /* uncomment next line if you want to add logging information from VBoxDrvCfg.cpp */
702// VBoxDrvCfgLoggerSet(vboxDrvLoggerCallback, NULL);
703}
704
705static UINT errorConvertFromHResult(MSIHANDLE hModule, HRESULT hr)
706{
707 UINT uRet;
708 switch (hr)
709 {
710 case S_OK:
711 uRet = ERROR_SUCCESS;
712 break;
713
714 case NETCFG_S_REBOOT:
715 {
716 logStringF(hModule, "Reboot required, setting REBOOT property to \"force\"");
717 HRESULT hr2 = MsiSetPropertyW(hModule, L"REBOOT", L"Force");
718 if (hr2 != ERROR_SUCCESS)
719 logStringF(hModule, "Failed to set REBOOT property, error = 0x%x", hr2);
720 uRet = ERROR_SUCCESS; /* Never fail here. */
721 break;
722 }
723
724 default:
725 logStringF(hModule, "Converting unhandled HRESULT (0x%x) to ERROR_GEN_FAILURE", hr);
726 uRet = ERROR_GEN_FAILURE;
727 }
728 return uRet;
729}
730
731static MSIHANDLE createNetCfgLockedMsgRecord(MSIHANDLE hModule)
732{
733 MSIHANDLE hRecord = MsiCreateRecord(2);
734 if (hRecord)
735 {
736 UINT uErr = MsiRecordSetInteger(hRecord, 1, 25001);
737 if (uErr != ERROR_SUCCESS)
738 {
739 logStringF(hModule, "createNetCfgLockedMsgRecord: MsiRecordSetInteger failed, error = 0x%x", uErr);
740 MsiCloseHandle(hRecord);
741 hRecord = NULL;
742 }
743 }
744 else
745 logStringF(hModule, "createNetCfgLockedMsgRecord: Failed to create a record");
746
747 return hRecord;
748}
749
750static UINT doNetCfgInit(MSIHANDLE hModule, INetCfg **ppnc, BOOL bWrite)
751{
752 MSIHANDLE hMsg = NULL;
753 UINT uErr = ERROR_GEN_FAILURE;
754 int MsgResult;
755 int cRetries = 0;
756
757 do
758 {
759 LPWSTR lpszLockedBy;
760 HRESULT hr = VBoxNetCfgWinQueryINetCfg(ppnc, bWrite, VBOX_NETCFG_APP_NAME, 10000, &lpszLockedBy);
761 if (hr != NETCFG_E_NO_WRITE_LOCK)
762 {
763 if (FAILED(hr))
764 logStringF(hModule, "doNetCfgInit: VBoxNetCfgWinQueryINetCfg failed, error = 0x%x", hr);
765 uErr = errorConvertFromHResult(hModule, hr);
766 break;
767 }
768
769 /* hr == NETCFG_E_NO_WRITE_LOCK */
770
771 if (!lpszLockedBy)
772 {
773 logStringF(hModule, "doNetCfgInit: lpszLockedBy == NULL, breaking");
774 break;
775 }
776
777 /* on vista the 6to4svc.dll periodically maintains the lock for some reason,
778 * if this is the case, increase the wait period by retrying multiple times
779 * NOTE: we could alternatively increase the wait timeout,
780 * however it seems unneeded for most cases, e.g. in case some network connection property
781 * dialog is opened, it would be better to post a notification to the user as soon as possible
782 * rather than waiting for a longer period of time before displaying it */
783 if ( cRetries < VBOX_NETCFG_MAX_RETRIES
784 && !wcscmp(lpszLockedBy, L"6to4svc.dll"))
785 {
786 cRetries++;
787 logStringF(hModule, "doNetCfgInit: lpszLockedBy is 6to4svc.dll, retrying %d out of %d", cRetries, VBOX_NETCFG_MAX_RETRIES);
788 MsgResult = IDRETRY;
789 }
790 else
791 {
792 if (!hMsg)
793 {
794 hMsg = createNetCfgLockedMsgRecord(hModule);
795 if (!hMsg)
796 {
797 logStringF(hModule, "doNetCfgInit: Failed to create a message record, breaking");
798 CoTaskMemFree(lpszLockedBy);
799 break;
800 }
801 }
802
803 UINT rTmp = MsiRecordSetStringW(hMsg, 2, lpszLockedBy);
804 NonStandardAssert(rTmp == ERROR_SUCCESS);
805 if (rTmp != ERROR_SUCCESS)
806 {
807 logStringF(hModule, "doNetCfgInit: MsiRecordSetStringW failed, error = 0x%x", rTmp);
808 CoTaskMemFree(lpszLockedBy);
809 break;
810 }
811
812 MsgResult = MsiProcessMessage(hModule, (INSTALLMESSAGE)(INSTALLMESSAGE_USER | MB_RETRYCANCEL), hMsg);
813 NonStandardAssert(MsgResult == IDRETRY || MsgResult == IDCANCEL);
814 logStringF(hModule, "doNetCfgInit: MsiProcessMessage returned (0x%x)", MsgResult);
815 }
816 CoTaskMemFree(lpszLockedBy);
817 } while(MsgResult == IDRETRY);
818
819 if (hMsg)
820 MsiCloseHandle(hMsg);
821
822 return uErr;
823}
824
825static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, OUT LPWSTR pwszMpInf, DWORD dwSize)
826{
827 DWORD dwBuf = dwSize - RT_MAX(sizeof(NETFLT_PT_INF_REL_PATH), sizeof(NETFLT_MP_INF_REL_PATH));
828 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", pwszPtInf, &dwBuf);
829 if ( uErr == ERROR_SUCCESS
830 && dwBuf)
831 {
832 wcscpy(pwszMpInf, pwszPtInf);
833
834 wcsncat(pwszPtInf, NETFLT_PT_INF_REL_PATH, sizeof(NETFLT_PT_INF_REL_PATH));
835 logStringF(hModule, "vboxNetFltQueryInfArray: INF 1: %s", pwszPtInf);
836
837 wcsncat(pwszMpInf, NETFLT_MP_INF_REL_PATH, sizeof(NETFLT_MP_INF_REL_PATH));
838 logStringF(hModule, "vboxNetFltQueryInfArray: INF 2: %s", pwszMpInf);
839 }
840 else if (uErr != ERROR_SUCCESS)
841 logStringF(hModule, "vboxNetFltQueryInfArray: MsiGetPropertyW failed, error = 0x%x", uErr);
842 else
843 {
844 logStringF(hModule, "vboxNetFltQueryInfArray: Empty installation directory");
845 uErr = ERROR_GEN_FAILURE;
846 }
847
848 return uErr;
849}
850
851#endif /*VBOX_WITH_NETFLT*/
852
853/*static*/ UINT _uninstallNetFlt(MSIHANDLE hModule)
854{
855#ifdef VBOX_WITH_NETFLT
856 INetCfg *pNetCfg;
857 UINT uErr;
858
859 netCfgLoggerEnable(hModule);
860
861 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
862
863 __try
864 {
865 logStringF(hModule, "Uninstalling NetFlt");
866
867 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
868 if (uErr == ERROR_SUCCESS)
869 {
870 HRESULT hr = VBoxNetCfgWinNetFltUninstall(pNetCfg);
871 if (hr != S_OK)
872 logStringF(hModule, "UninstallNetFlt: VBoxNetCfgWinUninstallComponent failed, error = 0x%x", hr);
873
874 uErr = errorConvertFromHResult(hModule, hr);
875
876 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
877
878 logStringF(hModule, "Uninstalling NetFlt done, error = 0x%x", uErr);
879 }
880 else
881 logStringF(hModule, "UninstallNetFlt: doNetCfgInit failed, error = 0x%x", uErr);
882 }
883 __finally
884 {
885 if (bOldIntMode)
886 {
887 /* The prev mode != FALSE, i.e. non-interactive. */
888 SetupSetNonInteractiveMode(bOldIntMode);
889 }
890 netCfgLoggerDisable();
891 }
892#endif /* VBOX_WITH_NETFLT */
893
894 /* Never fail the uninstall even if we did not succeed. */
895 return ERROR_SUCCESS;
896}
897
898UINT __stdcall UninstallNetFlt(MSIHANDLE hModule)
899{
900 (void)_uninstallNetLwf(hModule);
901 return _uninstallNetFlt(hModule);
902}
903
904static UINT _installNetFlt(MSIHANDLE hModule)
905{
906#ifdef VBOX_WITH_NETFLT
907 UINT uErr;
908 INetCfg *pNetCfg;
909
910 netCfgLoggerEnable(hModule);
911
912 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
913
914 __try
915 {
916
917 logStringF(hModule, "InstallNetFlt: Installing NetFlt");
918
919 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
920 if (uErr == ERROR_SUCCESS)
921 {
922 WCHAR wszPtInf[MAX_PATH];
923 WCHAR wszMpInf[MAX_PATH];
924 uErr = vboxNetFltQueryInfArray(hModule, wszPtInf, wszMpInf, sizeof(wszMpInf));
925 if (uErr == ERROR_SUCCESS)
926 {
927 LPCWSTR const apwszInfs[] = { wszPtInf, wszMpInf };
928 HRESULT hr = VBoxNetCfgWinNetFltInstall(pNetCfg, &apwszInfs[0], RT_ELEMENTS(apwszInfs));
929 if (FAILED(hr))
930 logStringF(hModule, "InstallNetFlt: VBoxNetCfgWinNetFltInstall failed, error = 0x%x", hr);
931
932 uErr = errorConvertFromHResult(hModule, hr);
933 }
934 else
935 logStringF(hModule, "InstallNetFlt: vboxNetFltQueryInfArray failed, error = 0x%x", uErr);
936
937 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
938
939 logStringF(hModule, "InstallNetFlt: Done");
940 }
941 else
942 logStringF(hModule, "InstallNetFlt: doNetCfgInit failed, error = 0x%x", uErr);
943 }
944 __finally
945 {
946 if (bOldIntMode)
947 {
948 /* The prev mode != FALSE, i.e. non-interactive. */
949 SetupSetNonInteractiveMode(bOldIntMode);
950 }
951 netCfgLoggerDisable();
952 }
953#endif /* VBOX_WITH_NETFLT */
954
955 /* Never fail the install even if we did not succeed. */
956 return ERROR_SUCCESS;
957}
958
959UINT __stdcall InstallNetFlt(MSIHANDLE hModule)
960{
961 (void)_uninstallNetLwf(hModule);
962 return _installNetFlt(hModule);
963}
964
965
966/*static*/ UINT _uninstallNetLwf(MSIHANDLE hModule)
967{
968#ifdef VBOX_WITH_NETFLT
969 INetCfg *pNetCfg;
970 UINT uErr;
971
972 netCfgLoggerEnable(hModule);
973
974 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
975
976 __try
977 {
978 logStringF(hModule, "Uninstalling NetLwf");
979
980 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
981 if (uErr == ERROR_SUCCESS)
982 {
983 HRESULT hr = VBoxNetCfgWinNetLwfUninstall(pNetCfg);
984 if (hr != S_OK)
985 logStringF(hModule, "UninstallNetLwf: VBoxNetCfgWinUninstallComponent failed, error = 0x%x", hr);
986
987 uErr = errorConvertFromHResult(hModule, hr);
988
989 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
990
991 logStringF(hModule, "Uninstalling NetLwf done, error = 0x%x", uErr);
992 }
993 else
994 logStringF(hModule, "UninstallNetLwf: doNetCfgInit failed, error = 0x%x", uErr);
995 }
996 __finally
997 {
998 if (bOldIntMode)
999 {
1000 /* The prev mode != FALSE, i.e. non-interactive. */
1001 SetupSetNonInteractiveMode(bOldIntMode);
1002 }
1003 netCfgLoggerDisable();
1004 }
1005#endif /* VBOX_WITH_NETFLT */
1006
1007 /* Never fail the uninstall even if we did not succeed. */
1008 return ERROR_SUCCESS;
1009}
1010
1011UINT __stdcall UninstallNetLwf(MSIHANDLE hModule)
1012{
1013 (void)_uninstallNetFlt(hModule);
1014 return _uninstallNetLwf(hModule);
1015}
1016
1017static UINT _installNetLwf(MSIHANDLE hModule)
1018{
1019#ifdef VBOX_WITH_NETFLT
1020 UINT uErr;
1021 INetCfg *pNetCfg;
1022
1023 netCfgLoggerEnable(hModule);
1024
1025 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
1026
1027 __try
1028 {
1029
1030 logStringF(hModule, "InstallNetLwf: Installing NetLwf");
1031
1032 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
1033 if (uErr == ERROR_SUCCESS)
1034 {
1035 WCHAR wszInf[MAX_PATH];
1036 DWORD cwcInf = RT_ELEMENTS(wszInf) - sizeof(NETLWF_INF_NAME) - 1;
1037 uErr = MsiGetPropertyW(hModule, L"CustomActionData", wszInf, &cwcInf);
1038 if (uErr == ERROR_SUCCESS)
1039 {
1040 if (cwcInf)
1041 {
1042 if (wszInf[cwcInf - 1] != L'\\')
1043 {
1044 wszInf[cwcInf++] = L'\\';
1045 wszInf[cwcInf] = L'\0';
1046 }
1047
1048 wcscat(wszInf, NETLWF_INF_NAME);
1049
1050 HRESULT hr = VBoxNetCfgWinNetLwfInstall(pNetCfg, wszInf);
1051 if (FAILED(hr))
1052 logStringF(hModule, "InstallNetLwf: VBoxNetCfgWinNetLwfInstall failed, error = 0x%x", hr);
1053
1054 uErr = errorConvertFromHResult(hModule, hr);
1055 }
1056 else
1057 {
1058 logStringF(hModule, "vboxNetFltQueryInfArray: Empty installation directory");
1059 uErr = ERROR_GEN_FAILURE;
1060 }
1061 }
1062 else
1063 logStringF(hModule, "vboxNetFltQueryInfArray: MsiGetPropertyW failed, error = 0x%x", uErr);
1064
1065 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
1066
1067 logStringF(hModule, "InstallNetLwf: Done");
1068 }
1069 else
1070 logStringF(hModule, "InstallNetLwf: doNetCfgInit failed, error = 0x%x", uErr);
1071 }
1072 __finally
1073 {
1074 if (bOldIntMode)
1075 {
1076 /* The prev mode != FALSE, i.e. non-interactive. */
1077 SetupSetNonInteractiveMode(bOldIntMode);
1078 }
1079 netCfgLoggerDisable();
1080 }
1081#endif /* VBOX_WITH_NETFLT */
1082
1083 /* Never fail the install even if we did not succeed. */
1084 return ERROR_SUCCESS;
1085}
1086
1087UINT __stdcall InstallNetLwf(MSIHANDLE hModule)
1088{
1089 (void)_uninstallNetFlt(hModule);
1090 return _installNetLwf(hModule);
1091}
1092
1093
1094#if 0
1095static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
1096{
1097 WCHAR DevName[256];
1098 DWORD winEr;
1099
1100 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDev,
1101 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
1102 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
1103 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
1104 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
1105 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
1106 ))
1107 {
1108 HKEY hKey = SetupDiOpenDevRegKey(hDevInfo, pDev,
1109 DICS_FLAG_GLOBAL, /* IN DWORD Scope,*/
1110 0, /*IN DWORD HwProfile, */
1111 DIREG_DRV, /* IN DWORD KeyType, */
1112 KEY_READ /*IN REGSAM samDesired*/
1113 );
1114 NonStandardAssert(hKey != INVALID_HANDLE_VALUE);
1115 if (hKey != INVALID_HANDLE_VALUE)
1116 {
1117 WCHAR guid[50];
1118 DWORD cbGuid=sizeof(guid);
1119 winEr = RegQueryValueExW(hKey,
1120 L"NetCfgInstanceId", /*__in_opt LPCTSTR lpValueName,*/
1121 NULL, /*__reserved LPDWORD lpReserved,*/
1122 NULL, /*__out_opt LPDWORD lpType,*/
1123 (LPBYTE)guid, /*__out_opt LPBYTE lpData,*/
1124 &cbGuid /*guid__inout_opt LPDWORD lpcbData*/
1125 );
1126 NonStandardAssert(winEr == ERROR_SUCCESS);
1127 if (winEr == ERROR_SUCCESS)
1128 {
1129 WCHAR ConnectoinName[128];
1130 ULONG cbName = sizeof(ConnectoinName);
1131
1132 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName (DevName, ConnectoinName, &cbName);
1133 NonStandardAssert(hr == S_OK);
1134 if (SUCCEEDED(hr))
1135 {
1136 hr = VBoxNetCfgWinRenameConnection(guid, ConnectoinName);
1137 NonStandardAssert(hr == S_OK);
1138 }
1139 }
1140 }
1141 RegCloseKey(hKey);
1142 }
1143 else
1144 {
1145 NonStandardAssert(0);
1146 }
1147
1148 return TRUE;
1149}
1150#endif
1151
1152static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR pwszInfName)
1153{
1154#ifdef VBOX_WITH_NETFLT
1155 netCfgLoggerEnable(hModule);
1156
1157 BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
1158
1159 logStringF(hModule, "CreateHostOnlyInterface: Creating host-only interface");
1160
1161 HRESULT hr = E_FAIL;
1162 GUID guid;
1163 WCHAR wszMpInf[MAX_PATH];
1164 DWORD cchMpInf = RT_ELEMENTS(wszMpInf) - (DWORD)wcslen(pwszInfName) - 1 - 1;
1165 LPCWSTR pwszInfPath = NULL;
1166 bool fIsFile = false;
1167 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", wszMpInf, &cchMpInf);
1168 if (uErr == ERROR_SUCCESS)
1169 {
1170 if (cchMpInf)
1171 {
1172 logStringF(hModule, "CreateHostOnlyInterface: NetAdpDir property = %s", wszMpInf);
1173 if (wszMpInf[cchMpInf - 1] != L'\\')
1174 {
1175 wszMpInf[cchMpInf++] = L'\\';
1176 wszMpInf[cchMpInf] = L'\0';
1177 }
1178
1179 wcscat(wszMpInf, pwszInfName);
1180 pwszInfPath = wszMpInf;
1181 fIsFile = true;
1182
1183 logStringF(hModule, "CreateHostOnlyInterface: Resulting INF path = %s", pwszInfPath);
1184 }
1185 else
1186 logStringF(hModule, "CreateHostOnlyInterface: VBox installation path is empty");
1187 }
1188 else
1189 logStringF(hModule, "CreateHostOnlyInterface: Unable to retrieve VBox installation path, error = 0x%x", uErr);
1190
1191 /* Make sure the inf file is installed. */
1192 if (pwszInfPath != NULL && fIsFile)
1193 {
1194 logStringF(hModule, "CreateHostOnlyInterface: Calling VBoxDrvCfgInfInstall(%s)", pwszInfPath);
1195 hr = VBoxDrvCfgInfInstall(pwszInfPath);
1196 logStringF(hModule, "CreateHostOnlyInterface: VBoxDrvCfgInfInstall returns 0x%x", hr);
1197 if (FAILED(hr))
1198 logStringF(hModule, "CreateHostOnlyInterface: Failed to install INF file, error = 0x%x", hr);
1199 }
1200
1201 if (SUCCEEDED(hr))
1202 {
1203 //first, try to update Host Only Network Interface
1204 BOOL fRebootRequired = FALSE;
1205 hr = VBoxNetCfgWinUpdateHostOnlyNetworkInterface(pwszInfPath, &fRebootRequired, pwszId);
1206 if (SUCCEEDED(hr))
1207 {
1208 if (fRebootRequired)
1209 {
1210 logStringF(hModule, "CreateHostOnlyInterface: Reboot required for update, setting REBOOT property to force");
1211 HRESULT hr2 = MsiSetPropertyW(hModule, L"REBOOT", L"Force");
1212 if (hr2 != ERROR_SUCCESS)
1213 logStringF(hModule, "CreateHostOnlyInterface: Failed to set REBOOT property for update, error = 0x%x", hr2);
1214 }
1215 }
1216 else
1217 {
1218 //in fail case call CreateHostOnlyInterface
1219 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinUpdateHostOnlyNetworkInterface failed, hr = 0x%x", hr);
1220 logStringF(hModule, "CreateHostOnlyInterface: calling VBoxNetCfgWinCreateHostOnlyNetworkInterface");
1221#ifdef VBOXNETCFG_DELAYEDRENAME
1222 BSTR devId;
1223 hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, &devId, NULL);
1224#else /* !VBOXNETCFG_DELAYEDRENAME */
1225 hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, NULL, NULL);
1226#endif /* !VBOXNETCFG_DELAYEDRENAME */
1227 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface returns 0x%x", hr);
1228 if (SUCCEEDED(hr))
1229 {
1230 ULONG ip = inet_addr("192.168.56.1");
1231 ULONG mask = inet_addr("255.255.255.0");
1232 logStringF(hModule, "CreateHostOnlyInterface: calling VBoxNetCfgWinEnableStaticIpConfig");
1233 hr = VBoxNetCfgWinEnableStaticIpConfig(&guid, ip, mask);
1234 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig returns 0x%x", hr);
1235 if (FAILED(hr))
1236 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, error = 0x%x", hr);
1237#ifdef VBOXNETCFG_DELAYEDRENAME
1238 hr = VBoxNetCfgWinRenameHostOnlyConnection(&guid, devId, NULL);
1239 if (FAILED(hr))
1240 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinRenameHostOnlyConnection failed, error = 0x%x", hr);
1241 SysFreeString(devId);
1242#endif /* VBOXNETCFG_DELAYEDRENAME */
1243 }
1244 else
1245 logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, error = 0x%x", hr);
1246 }
1247 }
1248
1249 if (SUCCEEDED(hr))
1250 logStringF(hModule, "CreateHostOnlyInterface: Creating host-only interface done");
1251
1252 /* Restore original setup mode. */
1253 logStringF(hModule, "CreateHostOnlyInterface: Almost done...");
1254 if (fSetupModeInteractive)
1255 SetupSetNonInteractiveMode(fSetupModeInteractive);
1256
1257 netCfgLoggerDisable();
1258
1259#endif /* VBOX_WITH_NETFLT */
1260
1261 logStringF(hModule, "CreateHostOnlyInterface: Returns success (ignoring all failures)");
1262 /* Never fail the install even if we did not succeed. */
1263 return ERROR_SUCCESS;
1264}
1265
1266UINT __stdcall CreateHostOnlyInterface(MSIHANDLE hModule)
1267{
1268 return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp.inf");
1269}
1270
1271UINT __stdcall Ndis6CreateHostOnlyInterface(MSIHANDLE hModule)
1272{
1273 return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp6.inf");
1274}
1275
1276static UINT _removeHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId)
1277{
1278#ifdef VBOX_WITH_NETFLT
1279 netCfgLoggerEnable(hModule);
1280
1281 logStringF(hModule, "RemoveHostOnlyInterfaces: Removing all host-only interfaces");
1282
1283 BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
1284
1285 HRESULT hr = VBoxNetCfgWinRemoveAllNetDevicesOfId(pwszId);
1286 if (SUCCEEDED(hr))
1287 {
1288 hr = VBoxDrvCfgInfUninstallAllSetupDi(&GUID_DEVCLASS_NET, L"Net", pwszId, SUOI_FORCEDELETE/* could be SUOI_FORCEDELETE */);
1289 if (FAILED(hr))
1290 {
1291 logStringF(hModule, "RemoveHostOnlyInterfaces: NetAdp uninstalled successfully, but failed to remove INF files");
1292 }
1293 else
1294 logStringF(hModule, "RemoveHostOnlyInterfaces: NetAdp uninstalled successfully");
1295
1296 }
1297 else
1298 logStringF(hModule, "RemoveHostOnlyInterfaces: NetAdp uninstall failed, hr = 0x%x", hr);
1299
1300 /* Restore original setup mode. */
1301 if (fSetupModeInteractive)
1302 SetupSetNonInteractiveMode(fSetupModeInteractive);
1303
1304 netCfgLoggerDisable();
1305#endif /* VBOX_WITH_NETFLT */
1306
1307 /* Never fail the uninstall even if we did not succeed. */
1308 return ERROR_SUCCESS;
1309}
1310
1311UINT __stdcall RemoveHostOnlyInterfaces(MSIHANDLE hModule)
1312{
1313 return _removeHostOnlyInterfaces(hModule, NETADP_ID);
1314}
1315
1316static UINT _stopHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId)
1317{
1318#ifdef VBOX_WITH_NETFLT
1319 netCfgLoggerEnable(hModule);
1320
1321 logStringF(hModule, "StopHostOnlyInterfaces: Stopping all host-only interfaces");
1322
1323 BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
1324
1325 HRESULT hr = VBoxNetCfgWinPropChangeAllNetDevicesOfId(pwszId, VBOXNECTFGWINPROPCHANGE_TYPE_DISABLE);
1326 if (SUCCEEDED(hr))
1327 {
1328 logStringF(hModule, "StopHostOnlyInterfaces: Disabling host interfaces was successful, hr = 0x%x", hr);
1329 }
1330 else
1331 logStringF(hModule, "StopHostOnlyInterfaces: Disabling host interfaces failed, hr = 0x%x", hr);
1332
1333 /* Restore original setup mode. */
1334 if (fSetupModeInteractive)
1335 SetupSetNonInteractiveMode(fSetupModeInteractive);
1336
1337 netCfgLoggerDisable();
1338#endif /* VBOX_WITH_NETFLT */
1339
1340 /* Never fail the uninstall even if we did not succeed. */
1341 return ERROR_SUCCESS;
1342}
1343
1344UINT __stdcall StopHostOnlyInterfaces(MSIHANDLE hModule)
1345{
1346 return _stopHostOnlyInterfaces(hModule, NETADP_ID);
1347}
1348
1349static UINT _updateHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszInfName, LPCWSTR pwszId)
1350{
1351#ifdef VBOX_WITH_NETFLT
1352 netCfgLoggerEnable(hModule);
1353
1354 logStringF(hModule, "UpdateHostOnlyInterfaces: Updating all host-only interfaces");
1355
1356 BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
1357
1358 WCHAR wszMpInf[MAX_PATH];
1359 DWORD cchMpInf = RT_ELEMENTS(wszMpInf) - (DWORD)wcslen(pwszInfName) - 1 - 1;
1360 LPCWSTR pwszInfPath = NULL;
1361 bool fIsFile = false;
1362 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", wszMpInf, &cchMpInf);
1363 if (uErr == ERROR_SUCCESS)
1364 {
1365 if (cchMpInf)
1366 {
1367 logStringF(hModule, "UpdateHostOnlyInterfaces: NetAdpDir property = %s", wszMpInf);
1368 if (wszMpInf[cchMpInf - 1] != L'\\')
1369 {
1370 wszMpInf[cchMpInf++] = L'\\';
1371 wszMpInf[cchMpInf] = L'\0';
1372 }
1373
1374 wcscat(wszMpInf, pwszInfName);
1375 pwszInfPath = wszMpInf;
1376 fIsFile = true;
1377
1378 logStringF(hModule, "UpdateHostOnlyInterfaces: Resulting INF path = %s", pwszInfPath);
1379
1380 DWORD attrFile = GetFileAttributesW(pwszInfPath);
1381 if (attrFile == INVALID_FILE_ATTRIBUTES)
1382 {
1383 DWORD dwErr = GetLastError();
1384 logStringF(hModule, "UpdateHostOnlyInterfaces: File \"%s\" not found, dwErr=%ld",
1385 pwszInfPath, dwErr);
1386 }
1387 else
1388 {
1389 logStringF(hModule, "UpdateHostOnlyInterfaces: File \"%s\" exists",
1390 pwszInfPath);
1391
1392 BOOL fRebootRequired = FALSE;
1393 HRESULT hr = VBoxNetCfgWinUpdateHostOnlyNetworkInterface(pwszInfPath, &fRebootRequired, pwszId);
1394 if (SUCCEEDED(hr))
1395 {
1396 if (fRebootRequired)
1397 {
1398 logStringF(hModule, "UpdateHostOnlyInterfaces: Reboot required, setting REBOOT property to force");
1399 HRESULT hr2 = MsiSetPropertyW(hModule, L"REBOOT", L"Force");
1400 if (hr2 != ERROR_SUCCESS)
1401 logStringF(hModule, "UpdateHostOnlyInterfaces: Failed to set REBOOT property, error = 0x%x", hr2);
1402 }
1403 }
1404 else
1405 logStringF(hModule, "UpdateHostOnlyInterfaces: VBoxNetCfgWinUpdateHostOnlyNetworkInterface failed, hr = 0x%x", hr);
1406 }
1407 }
1408 else
1409 logStringF(hModule, "UpdateHostOnlyInterfaces: VBox installation path is empty");
1410 }
1411 else
1412 logStringF(hModule, "UpdateHostOnlyInterfaces: Unable to retrieve VBox installation path, error = 0x%x", uErr);
1413
1414 /* Restore original setup mode. */
1415 if (fSetupModeInteractive)
1416 SetupSetNonInteractiveMode(fSetupModeInteractive);
1417
1418 netCfgLoggerDisable();
1419#endif /* VBOX_WITH_NETFLT */
1420
1421 /* Never fail the update even if we did not succeed. */
1422 return ERROR_SUCCESS;
1423}
1424
1425UINT __stdcall UpdateHostOnlyInterfaces(MSIHANDLE hModule)
1426{
1427 return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp.inf", NETADP_ID);
1428}
1429
1430UINT __stdcall Ndis6UpdateHostOnlyInterfaces(MSIHANDLE hModule)
1431{
1432 return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp6.inf", NETADP_ID);
1433}
1434
1435static UINT _uninstallNetAdp(MSIHANDLE hModule, LPCWSTR pwszId)
1436{
1437#ifdef VBOX_WITH_NETFLT
1438 INetCfg *pNetCfg;
1439 UINT uErr;
1440
1441 netCfgLoggerEnable(hModule);
1442
1443 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
1444
1445 __try
1446 {
1447 logStringF(hModule, "Uninstalling NetAdp");
1448
1449 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
1450 if (uErr == ERROR_SUCCESS)
1451 {
1452 HRESULT hr = VBoxNetCfgWinNetAdpUninstall(pNetCfg, pwszId);
1453 if (hr != S_OK)
1454 logStringF(hModule, "UninstallNetAdp: VBoxNetCfgWinUninstallComponent failed, error = 0x%x", hr);
1455
1456 uErr = errorConvertFromHResult(hModule, hr);
1457
1458 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
1459
1460 logStringF(hModule, "Uninstalling NetAdp done, error = 0x%x", uErr);
1461 }
1462 else
1463 logStringF(hModule, "UninstallNetAdp: doNetCfgInit failed, error = 0x%x", uErr);
1464 }
1465 __finally
1466 {
1467 if (bOldIntMode)
1468 {
1469 /* The prev mode != FALSE, i.e. non-interactive. */
1470 SetupSetNonInteractiveMode(bOldIntMode);
1471 }
1472 netCfgLoggerDisable();
1473 }
1474#endif /* VBOX_WITH_NETFLT */
1475
1476 /* Never fail the uninstall even if we did not succeed. */
1477 return ERROR_SUCCESS;
1478}
1479
1480UINT __stdcall UninstallNetAdp(MSIHANDLE hModule)
1481{
1482 return _uninstallNetAdp(hModule, NETADP_ID);
1483}
1484
1485static bool isTAPDevice(const WCHAR *pwszGUID)
1486{
1487 HKEY hNetcard;
1488 bool bIsTapDevice = false;
1489 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1490 L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
1491 0, KEY_READ, &hNetcard);
1492 if (lStatus != ERROR_SUCCESS)
1493 return false;
1494
1495 int i = 0;
1496 for (;;)
1497 {
1498 WCHAR wszEnumName[256];
1499 WCHAR wszNetCfgInstanceId[256];
1500 DWORD dwKeyType;
1501 HKEY hNetCardGUID;
1502
1503 DWORD dwLen = sizeof(wszEnumName);
1504 lStatus = RegEnumKeyExW(hNetcard, i, wszEnumName, &dwLen, NULL, NULL, NULL, NULL);
1505 if (lStatus != ERROR_SUCCESS)
1506 break;
1507
1508 lStatus = RegOpenKeyExW(hNetcard, wszEnumName, 0, KEY_READ, &hNetCardGUID);
1509 if (lStatus == ERROR_SUCCESS)
1510 {
1511 dwLen = sizeof(wszNetCfgInstanceId);
1512 lStatus = RegQueryValueExW(hNetCardGUID, L"NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)wszNetCfgInstanceId, &dwLen);
1513 if ( lStatus == ERROR_SUCCESS
1514 && dwKeyType == REG_SZ)
1515 {
1516 WCHAR wszNetProductName[256];
1517 WCHAR wszNetProviderName[256];
1518
1519 wszNetProductName[0] = 0;
1520 dwLen = sizeof(wszNetProductName);
1521 lStatus = RegQueryValueExW(hNetCardGUID, L"ProductName", NULL, &dwKeyType, (LPBYTE)wszNetProductName, &dwLen);
1522
1523 wszNetProviderName[0] = 0;
1524 dwLen = sizeof(wszNetProviderName);
1525 lStatus = RegQueryValueExW(hNetCardGUID, L"ProviderName", NULL, &dwKeyType, (LPBYTE)wszNetProviderName, &dwLen);
1526
1527 if ( !wcscmp(wszNetCfgInstanceId, pwszGUID)
1528 && !wcscmp(wszNetProductName, L"VirtualBox TAP Adapter")
1529 && ( (!wcscmp(wszNetProviderName, L"innotek GmbH")) /* Legacy stuff. */
1530 || (!wcscmp(wszNetProviderName, L"Sun Microsystems, Inc.")) /* Legacy stuff. */
1531 || (!wcscmp(wszNetProviderName, MY_WTEXT(VBOX_VENDOR))) /* Reflects current vendor string. */
1532 )
1533 )
1534 {
1535 bIsTapDevice = true;
1536 RegCloseKey(hNetCardGUID);
1537 break;
1538 }
1539 }
1540 RegCloseKey(hNetCardGUID);
1541 }
1542 ++i;
1543 }
1544
1545 RegCloseKey(hNetcard);
1546 return bIsTapDevice;
1547}
1548
1549/** @todo r=andy BUGBUG WTF! Why do we a) set the rc to 0 (success), and b) need this macro at all!? */
1550#define SetErrBreak(args) \
1551 if (1) { \
1552 rc = 0; \
1553 logStringF args; \
1554 break; \
1555 } else do {} while (0)
1556
1557int removeNetworkInterface(MSIHANDLE hModule, const WCHAR *pwszGUID)
1558{
1559 int rc = 1;
1560 do
1561 {
1562 WCHAR wszPnPInstanceId[512] = {0};
1563
1564 /* We have to find the device instance ID through a registry search */
1565
1566 HKEY hkeyNetwork = 0;
1567 HKEY hkeyConnection = 0;
1568
1569 do /* break-loop */
1570 {
1571 WCHAR wszRegLocation[256];
1572 swprintf(wszRegLocation,
1573 L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
1574 pwszGUID);
1575 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegLocation, 0, KEY_READ, &hkeyNetwork);
1576 if ((lStatus != ERROR_SUCCESS) || !hkeyNetwork)
1577 SetErrBreak((hModule, "VBox HostInterfaces: Host interface network was not found in registry (%s)! [1]",
1578 wszRegLocation));
1579
1580 lStatus = RegOpenKeyExW(hkeyNetwork, L"Connection", 0, KEY_READ, &hkeyConnection);
1581 if ((lStatus != ERROR_SUCCESS) || !hkeyConnection)
1582 SetErrBreak((hModule, "VBox HostInterfaces: Host interface network was not found in registry (%s)! [2]",
1583 wszRegLocation));
1584
1585 DWORD len = sizeof(wszPnPInstanceId);
1586 DWORD dwKeyType;
1587 lStatus = RegQueryValueExW(hkeyConnection, L"PnPInstanceID", NULL,
1588 &dwKeyType, (LPBYTE)&wszPnPInstanceId[0], &len);
1589 if ((lStatus != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
1590 SetErrBreak((hModule, "VBox HostInterfaces: Host interface network was not found in registry (%s)! [3]",
1591 wszRegLocation));
1592 }
1593 while (0);
1594
1595 if (hkeyConnection)
1596 RegCloseKey(hkeyConnection);
1597 if (hkeyNetwork)
1598 RegCloseKey(hkeyNetwork);
1599
1600 /*
1601 * Now we are going to enumerate all network devices and
1602 * wait until we encounter the right device instance ID
1603 */
1604
1605 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1606 BOOL fResult;
1607
1608 do
1609 {
1610 GUID netGuid;
1611 SP_DEVINFO_DATA DeviceInfoData;
1612 DWORD index = 0;
1613 DWORD size = 0;
1614
1615 /* initialize the structure size */
1616 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1617
1618 /* copy the net class GUID */
1619 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
1620
1621 /* return a device info set contains all installed devices of the Net class */
1622 hDeviceInfo = SetupDiGetClassDevs(&netGuid, NULL, NULL, DIGCF_PRESENT);
1623 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1624 {
1625 logStringF(hModule, "VBox HostInterfaces: SetupDiGetClassDevs failed (0x%08X)!", GetLastError());
1626 SetErrBreak((hModule, "VBox HostInterfaces: Uninstallation failed!"));
1627 }
1628
1629 BOOL fFoundDevice = FALSE;
1630
1631 /* enumerate the driver info list */
1632 while (TRUE)
1633 {
1634 WCHAR *pwszDeviceHwid;
1635
1636 fResult = SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData);
1637 if (!fResult)
1638 {
1639 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1640 break;
1641 else
1642 {
1643 index++;
1644 continue;
1645 }
1646 }
1647
1648 /* try to get the hardware ID registry property */
1649 fResult = SetupDiGetDeviceRegistryProperty(hDeviceInfo,
1650 &DeviceInfoData,
1651 SPDRP_HARDWAREID,
1652 NULL,
1653 NULL,
1654 0,
1655 &size);
1656 if (!fResult)
1657 {
1658 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1659 {
1660 index++;
1661 continue;
1662 }
1663
1664 pwszDeviceHwid = (WCHAR *)malloc(size);
1665 if (pwszDeviceHwid)
1666 {
1667 fResult = SetupDiGetDeviceRegistryProperty(hDeviceInfo,
1668 &DeviceInfoData,
1669 SPDRP_HARDWAREID,
1670 NULL,
1671 (PBYTE)pwszDeviceHwid,
1672 size,
1673 NULL);
1674 if (!fResult)
1675 {
1676 free(pwszDeviceHwid);
1677 pwszDeviceHwid = NULL;
1678 index++;
1679 continue;
1680 }
1681 }
1682 }
1683 else
1684 {
1685 /* something is wrong. This shouldn't have worked with a NULL buffer */
1686 index++;
1687 continue;
1688 }
1689
1690 for (WCHAR *t = pwszDeviceHwid;
1691 t && *t && t < &pwszDeviceHwid[size / sizeof(WCHAR)];
1692 t += wcslen(t) + 1)
1693 {
1694 if (!_wcsicmp(L"vboxtap", t))
1695 {
1696 /* get the device instance ID */
1697 WCHAR wszDevID[MAX_DEVICE_ID_LEN];
1698 if (CM_Get_Device_IDW(DeviceInfoData.DevInst,
1699 wszDevID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
1700 {
1701 /* compare to what we determined before */
1702 if (!wcscmp(wszDevID, wszPnPInstanceId))
1703 {
1704 fFoundDevice = TRUE;
1705 break;
1706 }
1707 }
1708 }
1709 }
1710
1711 if (pwszDeviceHwid)
1712 {
1713 free(pwszDeviceHwid);
1714 pwszDeviceHwid = NULL;
1715 }
1716
1717 if (fFoundDevice)
1718 break;
1719
1720 index++;
1721 }
1722
1723 if (fFoundDevice)
1724 {
1725 fResult = SetupDiSetSelectedDevice(hDeviceInfo, &DeviceInfoData);
1726 if (!fResult)
1727 {
1728 logStringF(hModule, "VBox HostInterfaces: SetupDiSetSelectedDevice failed (0x%08X)!", GetLastError());
1729 SetErrBreak((hModule, "VBox HostInterfaces: Uninstallation failed!"));
1730 }
1731
1732 fResult = SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
1733 if (!fResult)
1734 {
1735 logStringF(hModule, "VBox HostInterfaces: SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)!", GetLastError());
1736 SetErrBreak((hModule, "VBox HostInterfaces: Uninstallation failed!"));
1737 }
1738 }
1739 else
1740 SetErrBreak((hModule, "VBox HostInterfaces: Host interface network device not found!"));
1741 } while (0);
1742
1743 /* clean up the device info set */
1744 if (hDeviceInfo != INVALID_HANDLE_VALUE)
1745 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1746 } while (0);
1747 return rc;
1748}
1749
1750UINT __stdcall UninstallTAPInstances(MSIHANDLE hModule)
1751{
1752 static const WCHAR *s_wszNetworkKey = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
1753 HKEY hCtrlNet;
1754
1755 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_wszNetworkKey, 0, KEY_READ, &hCtrlNet);
1756 if (lStatus == ERROR_SUCCESS)
1757 {
1758 logStringF(hModule, "VBox HostInterfaces: Enumerating interfaces ...");
1759 for (int i = 0; ; ++i)
1760 {
1761 WCHAR wszNetworkGUID[256] = { 0 };
1762 DWORD dwLen = (DWORD)sizeof(wszNetworkGUID);
1763 lStatus = RegEnumKeyExW(hCtrlNet, i, wszNetworkGUID, &dwLen, NULL, NULL, NULL, NULL);
1764 if (lStatus != ERROR_SUCCESS)
1765 {
1766 switch (lStatus)
1767 {
1768 case ERROR_NO_MORE_ITEMS:
1769 logStringF(hModule, "VBox HostInterfaces: No interfaces found.");
1770 break;
1771 default:
1772 logStringF(hModule, "VBox HostInterfaces: Enumeration failed: %ld", lStatus);
1773 break;
1774 }
1775 break;
1776 }
1777
1778 if (isTAPDevice(wszNetworkGUID))
1779 {
1780 logStringF(hModule, "VBox HostInterfaces: Removing interface \"%s\" ...", wszNetworkGUID);
1781 removeNetworkInterface(hModule, wszNetworkGUID);
1782 lStatus = RegDeleteKeyW(hCtrlNet, wszNetworkGUID);
1783 }
1784 }
1785 RegCloseKey(hCtrlNet);
1786 logStringF(hModule, "VBox HostInterfaces: Removing interfaces done.");
1787 }
1788 return ERROR_SUCCESS;
1789}
1790
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