VirtualBox

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

Last change on this file since 62779 was 62779, checked in by vboxsync, 9 years ago

Installer: warnings

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

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