VirtualBox

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

Last change on this file since 78425 was 77804, checked in by vboxsync, 6 years ago

NetAdp/Win: (bugref:9409) Store host-only adapter configuration in extra data. Create missing adapters when listing/creating/removing adapters.

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