VirtualBox

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

Last change on this file since 46326 was 41024, checked in by vboxsync, 13 years ago

Windows host installer: Fixed deletion of installed host-only adapter on update, fixed allowing features to be installed on demand (advertising), added some more logging to install helper DLL.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.6 KB
Line 
1/* $Id: VBoxInstallHelper.cpp 41024 2012-04-23 12:51:21Z vboxsync $ */
2/** @file
3 * VBoxInstallHelper - Various helper routines for Windows host installer.
4 */
5
6/*
7 * Copyright (C) 2008-2012 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 <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 <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 <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,
69 DWORD ul_reason_for_call,
70 LPVOID lpReserved)
71{
72 return TRUE;
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
259 /* Set final path. */
260 swprintf_s(wszPath, RT_ELEMENTS(wszPath), L"%s\\sdk\\install", wszPathTargetDir);
261
262 /* Install our API module. */
263 swprintf_s(wszCmdLine, RT_ELEMENTS(wszCmdLine), L"%s\\python.exe vboxapisetup.py install", wszVal);
264
265 /* Set required environment variables. */
266 if (!SetEnvironmentVariableW(L"VBOX_INSTALL_PATH", wszPathTargetDir))
267 logStringW(hModule, L"InstallPythonAPI: Could set environment variable VBOX_INSTALL_PATH!");
268 else
269 {
270 DWORD dwRetExec = Exec(hModule, wszExec, wszCmdLine, wszPath, &dwExitCode);
271 if ( (ERROR_SUCCESS == dwRetExec)
272 && ( 0 == dwExitCode))
273 {
274 /* All done! */
275 logStringW(hModule, L"InstallPythonAPI: VBoxAPI for Python successfully installed.");
276 bInstalled = TRUE;
277 }
278 else
279 {
280 if (dwRetExec)
281 logStringW(hModule, L"InstallPythonAPI: Error while executing installation of VBox API: %ld", dwRetExec);
282 else
283 logStringW(hModule, L"InstallPythonAPI: Python reported an error while installing VBox API: %ld", dwExitCode);
284 }
285 }
286 }
287 else
288 logStringW(hModule, L"InstallPythonAPI: Unable to retrieve VBox installation path!");
289 }
290
291 VBoxSetProperty(hModule, L"PYTHON_INSTALLED", bInstalled ? L"1" : L"0");
292
293 if (!bInstalled)
294 logStringW(hModule, L"InstallPythonAPI: VBox API not installed.");
295 return ERROR_SUCCESS; /* Do not fail here. */
296}
297
298static LONG installBrandingValue(MSIHANDLE hModule,
299 const WCHAR *pwszFileName,
300 const WCHAR *pwszSection,
301 const WCHAR *pwszValue)
302{
303 LONG rc;
304 WCHAR wszValue[_MAX_PATH];
305 if (GetPrivateProfileStringW(pwszSection, pwszValue, NULL,
306 wszValue, sizeof(wszValue), pwszFileName) > 0)
307 {
308 HKEY hkBranding;
309 WCHAR wszKey[_MAX_PATH];
310
311 if (wcsicmp(L"General", pwszSection) != 0)
312 swprintf_s(wszKey, RT_ELEMENTS(wszKey), L"SOFTWARE\\%s\\VirtualBox\\Branding\\", VBOX_VENDOR_SHORT, pwszSection);
313 else
314 swprintf_s(wszKey, RT_ELEMENTS(wszKey), L"SOFTWARE\\%s\\VirtualBox\\Branding", VBOX_VENDOR_SHORT);
315
316 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszKey, 0, KEY_WRITE, &hkBranding);
317 if (rc == ERROR_SUCCESS)
318 {
319 rc = RegSetValueExW(hkBranding,
320 pwszValue,
321 NULL,
322 REG_SZ,
323 (BYTE *)wszValue,
324 (DWORD)wcslen(wszValue));
325 if (rc != ERROR_SUCCESS)
326 logStringW(hModule, L"InstallBranding: Could not write value %s! Error %ld", pwszValue, rc);
327 RegCloseKey (hkBranding);
328 }
329 }
330 else
331 rc = ERROR_NOT_FOUND;
332 return rc;
333}
334
335UINT CopyDir(MSIHANDLE hModule, const WCHAR *pwszDestDir, const WCHAR *pwszSourceDir)
336{
337 UINT rc;
338 WCHAR wszDest[_MAX_PATH + 1];
339 WCHAR wszSource[_MAX_PATH + 1];
340
341 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, '\0');
342 swprintf_s(wszSource, RT_ELEMENTS(wszSource), L"%s%c", pwszSourceDir, '\0');
343
344 SHFILEOPSTRUCTW s = {0};
345 s.hwnd = NULL;
346 s.wFunc = FO_COPY;
347 s.pTo = wszDest;
348 s.pFrom = wszSource;
349 s.fFlags = FOF_SILENT |
350 FOF_NOCONFIRMATION |
351 FOF_NOCONFIRMMKDIR |
352 FOF_NOERRORUI;
353
354 logStringW(hModule, L"CopyDir: DestDir=%s, SourceDir=%s", wszDest, wszSource);
355 int r = SHFileOperationW(&s);
356 if (r != 0)
357 {
358 logStringW(hModule, L"CopyDir: Copy operation returned status 0x%x", r);
359 rc = ERROR_GEN_FAILURE;
360 }
361 else
362 rc = ERROR_SUCCESS;
363 return rc;
364}
365
366UINT RemoveDir(MSIHANDLE hModule, const WCHAR *pwszDestDir)
367{
368 UINT rc;
369 WCHAR wszDest[_MAX_PATH + 1];
370
371 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, '\0');
372
373 SHFILEOPSTRUCTW s = {0};
374 s.hwnd = NULL;
375 s.wFunc = FO_DELETE;
376 s.pFrom = wszDest;
377 s.fFlags = FOF_SILENT
378 | FOF_NOCONFIRMATION
379 | FOF_NOCONFIRMMKDIR
380 | FOF_NOERRORUI;
381
382 logStringW(hModule, L"RemoveDir: DestDir=%s", wszDest);
383 int r = SHFileOperationW(&s);
384 if (r != 0)
385 {
386 logStringW(hModule, L"RemoveDir: Remove operation returned status 0x%x", r);
387 rc = ERROR_GEN_FAILURE;
388 }
389 else
390 rc = ERROR_SUCCESS;
391 return rc;
392}
393
394UINT RenameDir(MSIHANDLE hModule, const WCHAR *pwszDestDir, const WCHAR *pwszSourceDir)
395{
396 UINT rc;
397 WCHAR wszDest[_MAX_PATH + 1];
398 WCHAR wszSource[_MAX_PATH + 1];
399
400 swprintf_s(wszDest, RT_ELEMENTS(wszDest), L"%s%c", pwszDestDir, '\0');
401 swprintf_s(wszSource, RT_ELEMENTS(wszSource), L"%s%c", pwszSourceDir, '\0');
402
403 SHFILEOPSTRUCTW s = {0};
404 s.hwnd = NULL;
405 s.wFunc = FO_RENAME;
406 s.pTo = wszDest;
407 s.pFrom = wszSource;
408 s.fFlags = FOF_SILENT
409 | FOF_NOCONFIRMATION
410 | FOF_NOCONFIRMMKDIR
411 | FOF_NOERRORUI;
412
413 logStringW(hModule, L"RenameDir: DestDir=%s, SourceDir=%s", wszDest, wszSource);
414 int r = SHFileOperationW(&s);
415 if (r != 0)
416 {
417 logStringW(hModule, L"RenameDir: Rename operation returned status 0x%x", r);
418 rc = ERROR_GEN_FAILURE;
419 }
420 else
421 rc = ERROR_SUCCESS;
422 return rc;
423}
424
425UINT __stdcall UninstallBranding(MSIHANDLE hModule)
426{
427 UINT rc;
428 logStringW(hModule, L"UninstallBranding: Handling branding file ...");
429
430 WCHAR wszPathTargetDir[_MAX_PATH];
431 WCHAR wszPathDest[_MAX_PATH];
432
433 rc = VBoxGetProperty(hModule, L"CustomActionData", wszPathTargetDir, sizeof(wszPathTargetDir));
434 if (rc == ERROR_SUCCESS)
435 {
436 /** @todo Check trailing slash after %s. */
437/** @todo r=bird: using swprintf_s for formatting paths without checking for
438 * overflow not good. You're dodging the buffer overflow issue only to end up
439 * with incorrect behavior! (Truncated file/dir names)
440 *
441 * This applies almost to all swprintf_s calls in this file!!
442 */
443 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%scustom", wszPathTargetDir);
444 rc = RemoveDir(hModule, wszPathDest);
445 if (rc != ERROR_SUCCESS)
446 {
447 /* Check for hidden .custom directory and remove it. */
448 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%s.custom", wszPathTargetDir);
449 rc = RemoveDir(hModule, wszPathDest);
450 }
451 }
452
453 logStringW(hModule, L"UninstallBranding: Handling done. (rc=%u (ignored))", rc);
454 return ERROR_SUCCESS; /* Do not fail here. */
455}
456
457UINT __stdcall InstallBranding(MSIHANDLE hModule)
458{
459 UINT rc;
460 logStringW(hModule, L"InstallBranding: Handling branding file ...");
461
462 WCHAR wszPathMSI[_MAX_PATH];
463 rc = VBoxGetProperty(hModule, L"SOURCEDIR", wszPathMSI, sizeof(wszPathMSI));
464 if (rc == ERROR_SUCCESS)
465 {
466 WCHAR wszPathTargetDir[_MAX_PATH];
467 rc = VBoxGetProperty(hModule, L"CustomActionData", wszPathTargetDir, sizeof(wszPathTargetDir));
468 if (rc == ERROR_SUCCESS)
469 {
470 /** @todo Check for trailing slash after %s. */
471 WCHAR wszPathDest[_MAX_PATH];
472 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%s", wszPathTargetDir);
473
474 WCHAR wszPathSource[_MAX_PATH];
475 swprintf_s(wszPathSource, RT_ELEMENTS(wszPathSource), L"%s.custom", wszPathMSI);
476 rc = CopyDir(hModule, wszPathDest, wszPathSource);
477 if (rc == ERROR_SUCCESS)
478 {
479 swprintf_s(wszPathDest, RT_ELEMENTS(wszPathDest), L"%scustom", wszPathTargetDir);
480 swprintf_s(wszPathSource, RT_ELEMENTS(wszPathSource), L"%s.custom", wszPathTargetDir);
481 rc = RenameDir(hModule, wszPathDest, wszPathSource);
482 }
483 }
484 }
485
486 logStringW(hModule, L"InstallBranding: Handling done. (rc=%u (ignored))", rc);
487 return ERROR_SUCCESS; /* Do not fail here. */
488}
489
490#ifdef VBOX_WITH_NETFLT
491
492/** @todo should use some real VBox app name */
493#define VBOX_NETCFG_APP_NAME L"VirtualBox Installer"
494#define VBOX_NETCFG_MAX_RETRIES 10
495#define NETFLT_PT_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFlt.inf"
496#define NETFLT_MP_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFltM.inf"
497#define NETFLT_ID L"sun_VBoxNetFlt" /** @todo Needs to be changed (?). */
498#define NETADP_ID L"sun_VBoxNetAdp" /** @todo Needs to be changed (?). */
499
500static MSIHANDLE g_hCurrentModule = NULL;
501
502static VOID netCfgLoggerCallback(LPCSTR szString)
503{
504 if (g_hCurrentModule)
505 logString(g_hCurrentModule, szString);
506}
507
508static VOID netCfgLoggerDisable()
509{
510 if (g_hCurrentModule)
511 {
512 VBoxNetCfgWinSetLogging((LOG_ROUTINE)NULL);
513 g_hCurrentModule = NULL;
514 }
515}
516
517static VOID netCfgLoggerEnable(MSIHANDLE hModule)
518{
519 NonStandardAssert(hModule);
520
521 if (g_hCurrentModule)
522 netCfgLoggerDisable();
523
524 g_hCurrentModule = hModule;
525
526 VBoxNetCfgWinSetLogging((LOG_ROUTINE)netCfgLoggerCallback);
527}
528
529static UINT errorConvertFromHResult(MSIHANDLE hModule, HRESULT hr)
530{
531 UINT uRet;
532 switch (hr)
533 {
534 case S_OK:
535 uRet = ERROR_SUCCESS;
536 break;
537
538 case NETCFG_S_REBOOT:
539 {
540 logStringW(hModule, L"Reboot required, setting REBOOT property to Force");
541 HRESULT hr2 = MsiSetPropertyW(hModule, L"REBOOT", L"Force");
542 if (hr2 != ERROR_SUCCESS)
543 logStringW(hModule, L"Failed to set REBOOT property, error = 0x%x", hr2);
544 uRet = ERROR_SUCCESS; /* Never fail here. */
545 break;
546 }
547
548 default:
549 logStringW(hModule, L"Converting unhandled HRESULT (0x%x) to ERROR_GEN_FAILURE", hr);
550 uRet = ERROR_GEN_FAILURE;
551 }
552 return uRet;
553}
554
555static MSIHANDLE createNetCfgLockedMsgRecord(MSIHANDLE hModule)
556{
557 MSIHANDLE hRecord = MsiCreateRecord(2);
558 if (hRecord)
559 {
560 UINT uErr = MsiRecordSetInteger(hRecord, 1, 25001);
561 if (uErr != ERROR_SUCCESS)
562 {
563 logStringW(hModule, L"createNetCfgLockedMsgRecord: MsiRecordSetInteger failed, error = 0x%x", uErr);
564 MsiCloseHandle(hRecord);
565 hRecord = NULL;
566 }
567 }
568 else
569 logStringW(hModule, L"createNetCfgLockedMsgRecord: Failed to create a record");
570
571 return hRecord;
572}
573
574static UINT doNetCfgInit(MSIHANDLE hModule, INetCfg **ppnc, BOOL bWrite)
575{
576 MSIHANDLE hMsg = NULL;
577 UINT uErr = ERROR_GEN_FAILURE;
578 int MsgResult;
579 int cRetries = 0;
580
581 do
582 {
583 LPWSTR lpszLockedBy;
584 HRESULT hr = VBoxNetCfgWinQueryINetCfg(ppnc, bWrite, VBOX_NETCFG_APP_NAME, 10000, &lpszLockedBy);
585 if (hr != NETCFG_E_NO_WRITE_LOCK)
586 {
587 if (FAILED(hr))
588 logStringW(hModule, L"doNetCfgInit: VBoxNetCfgWinQueryINetCfg failed, error = 0x%x", hr);
589 uErr = errorConvertFromHResult(hModule, hr);
590 break;
591 }
592
593 /* hr == NETCFG_E_NO_WRITE_LOCK */
594
595 if (!lpszLockedBy)
596 {
597 logStringW(hModule, L"doNetCfgInit: lpszLockedBy == NULL, breaking");
598 break;
599 }
600
601 /* on vista the 6to4svc.dll periodically maintains the lock for some reason,
602 * if this is the case, increase the wait period by retrying multiple times
603 * NOTE: we could alternatively increase the wait timeout,
604 * however it seems unneeded for most cases, e.g. in case some network connection property
605 * dialog is opened, it would be better to post a notification to the user as soon as possible
606 * rather than waiting for a longer period of time before displaying it */
607 if ( cRetries < VBOX_NETCFG_MAX_RETRIES
608 && !wcscmp(lpszLockedBy, L"6to4svc.dll"))
609 {
610 cRetries++;
611 logStringW(hModule, L"doNetCfgInit: lpszLockedBy is 6to4svc.dll, retrying %d out of %d", cRetries, VBOX_NETCFG_MAX_RETRIES);
612 MsgResult = IDRETRY;
613 }
614 else
615 {
616 if (!hMsg)
617 {
618 hMsg = createNetCfgLockedMsgRecord(hModule);
619 if (!hMsg)
620 {
621 logStringW(hModule, L"doNetCfgInit: Failed to create a message record, breaking");
622 CoTaskMemFree(lpszLockedBy);
623 break;
624 }
625 }
626
627 UINT rTmp = MsiRecordSetStringW(hMsg, 2, lpszLockedBy);
628 NonStandardAssert(rTmp == ERROR_SUCCESS);
629 if (rTmp != ERROR_SUCCESS)
630 {
631 logStringW(hModule, L"doNetCfgInit: MsiRecordSetStringW failed, error = 0x%x", rTmp);
632 CoTaskMemFree(lpszLockedBy);
633 break;
634 }
635
636 MsgResult = MsiProcessMessage(hModule, (INSTALLMESSAGE)(INSTALLMESSAGE_USER | MB_RETRYCANCEL), hMsg);
637 NonStandardAssert(MsgResult == IDRETRY || MsgResult == IDCANCEL);
638 logStringW(hModule, L"doNetCfgInit: MsiProcessMessage returned (0x%x)", MsgResult);
639 }
640 CoTaskMemFree(lpszLockedBy);
641 } while(MsgResult == IDRETRY);
642
643 if (hMsg)
644 MsiCloseHandle(hMsg);
645
646 return uErr;
647}
648
649static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, OUT LPWSTR pwszMpInf, DWORD dwSize)
650{
651 DWORD dwBuf = dwSize - RT_MAX(sizeof(NETFLT_PT_INF_REL_PATH), sizeof(NETFLT_MP_INF_REL_PATH));
652 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", pwszPtInf, &dwBuf);
653 if ( uErr == ERROR_SUCCESS
654 && dwBuf)
655 {
656 wcscpy(pwszMpInf, pwszPtInf);
657
658 wcsncat(pwszPtInf, NETFLT_PT_INF_REL_PATH, sizeof(NETFLT_PT_INF_REL_PATH));
659 logStringW(hModule, L"vboxNetFltQueryInfArray: INF 1: %s", pwszPtInf);
660
661 wcsncat(pwszMpInf, NETFLT_MP_INF_REL_PATH, sizeof(NETFLT_MP_INF_REL_PATH));
662 logStringW(hModule, L"vboxNetFltQueryInfArray: INF 2: %s", pwszMpInf);
663 }
664 else if (uErr != ERROR_SUCCESS)
665 logStringW(hModule, L"vboxNetFltQueryInfArray: MsiGetPropertyW failed, error = 0x%x", uErr);
666 else
667 {
668 logStringW(hModule, L"vboxNetFltQueryInfArray: Empty installation directory");
669 uErr = ERROR_GEN_FAILURE;
670 }
671
672 return uErr;
673}
674
675#endif /*VBOX_WITH_NETFLT*/
676
677UINT __stdcall UninstallNetFlt(MSIHANDLE hModule)
678{
679#ifdef VBOX_WITH_NETFLT
680 INetCfg *pNetCfg;
681 UINT uErr;
682
683 netCfgLoggerEnable(hModule);
684
685 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
686
687 __try
688 {
689 logStringW(hModule, L"Uninstalling NetFlt");
690
691 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
692 if (uErr == ERROR_SUCCESS)
693 {
694 HRESULT hr = VBoxNetCfgWinNetFltUninstall(pNetCfg);
695 if (hr != S_OK)
696 logStringW(hModule, L"UninstallNetFlt: VBoxNetCfgWinUninstallComponent failed, error = 0x%x", hr);
697
698 uErr = errorConvertFromHResult(hModule, hr);
699
700 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
701
702 logStringW(hModule, L"Uninstalling NetFlt done, error = 0x%x", uErr);
703
704 /* Never fail on uninstall. */
705 uErr = ERROR_SUCCESS;
706 }
707 else
708 logStringW(hModule, L"UninstallNetFlt: doNetCfgInit failed, error = 0x%x", uErr);
709 }
710 __finally
711 {
712 if (bOldIntMode)
713 {
714 /* The prev mode != FALSE, i.e. non-interactive. */
715 SetupSetNonInteractiveMode(bOldIntMode);
716 }
717 netCfgLoggerDisable();
718 }
719#endif /* VBOX_WITH_NETFLT */
720
721 /* Never fail the install even if we did not succeed. */
722 return ERROR_SUCCESS;
723}
724
725UINT __stdcall InstallNetFlt(MSIHANDLE hModule)
726{
727#ifdef VBOX_WITH_NETFLT
728 UINT uErr;
729 INetCfg *pNetCfg;
730
731 netCfgLoggerEnable(hModule);
732
733 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
734
735 __try
736 {
737
738 logStringW(hModule, L"InstallNetFlt: Installing NetFlt");
739
740 uErr = doNetCfgInit(hModule, &pNetCfg, TRUE);
741 if (uErr == ERROR_SUCCESS)
742 {
743 WCHAR wszPtInf[MAX_PATH];
744 WCHAR wszMpInf[MAX_PATH];
745 uErr = vboxNetFltQueryInfArray(hModule, wszPtInf, wszMpInf, sizeof(wszMpInf));
746 if (uErr == ERROR_SUCCESS)
747 {
748 LPCWSTR const apwszInfs[] = { wszPtInf, wszMpInf };
749 HRESULT hr = VBoxNetCfgWinNetFltInstall(pNetCfg, &apwszInfs[0], RT_ELEMENTS(apwszInfs));
750 if (FAILED(hr))
751 logStringW(hModule, L"InstallNetFlt: VBoxNetCfgWinNetFltInstall failed, error = 0x%x", hr);
752
753 uErr = errorConvertFromHResult(hModule, hr);
754 }
755 else
756 logStringW(hModule, L"InstallNetFlt: vboxNetFltQueryInfArray failed, error = 0x%x", uErr);
757
758 VBoxNetCfgWinReleaseINetCfg(pNetCfg, TRUE);
759
760 logStringW(hModule, L"InstallNetFlt: Done");
761 }
762 else
763 logStringW(hModule, L"InstallNetFlt: doNetCfgInit failed, error = 0x%x", uErr);
764 }
765 __finally
766 {
767 if (bOldIntMode)
768 {
769 /* The prev mode != FALSE, i.e. non-interactive. */
770 SetupSetNonInteractiveMode(bOldIntMode);
771 }
772 netCfgLoggerDisable();
773 }
774#endif /* VBOX_WITH_NETFLT */
775
776 /* Never fail the install even if we did not succeed. */
777 return ERROR_SUCCESS;
778}
779
780#if 0
781static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
782{
783 WCHAR DevName[256];
784 DWORD winEr;
785
786 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDev,
787 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
788 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
789 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
790 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
791 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
792 ))
793 {
794 HKEY hKey = SetupDiOpenDevRegKey(hDevInfo, pDev,
795 DICS_FLAG_GLOBAL, /* IN DWORD Scope,*/
796 0, /*IN DWORD HwProfile, */
797 DIREG_DRV, /* IN DWORD KeyType, */
798 KEY_READ /*IN REGSAM samDesired*/
799 );
800 NonStandardAssert(hKey != INVALID_HANDLE_VALUE);
801 if (hKey != INVALID_HANDLE_VALUE)
802 {
803 WCHAR guid[50];
804 DWORD cbGuid=sizeof(guid);
805 winEr = RegQueryValueExW(hKey,
806 L"NetCfgInstanceId", /*__in_opt LPCTSTR lpValueName,*/
807 NULL, /*__reserved LPDWORD lpReserved,*/
808 NULL, /*__out_opt LPDWORD lpType,*/
809 (LPBYTE)guid, /*__out_opt LPBYTE lpData,*/
810 &cbGuid /*guid__inout_opt LPDWORD lpcbData*/
811 );
812 NonStandardAssert(winEr == ERROR_SUCCESS);
813 if (winEr == ERROR_SUCCESS)
814 {
815 WCHAR ConnectoinName[128];
816 ULONG cbName = sizeof(ConnectoinName);
817
818 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName (DevName, ConnectoinName, &cbName);
819 NonStandardAssert(hr == S_OK);
820 if (SUCCEEDED(hr))
821 {
822 hr = VBoxNetCfgWinRenameConnection(guid, ConnectoinName);
823 NonStandardAssert(hr == S_OK);
824 }
825 }
826 }
827 RegCloseKey(hKey);
828 }
829 else
830 {
831 NonStandardAssert(0);
832 }
833
834 return TRUE;
835}
836#endif
837
838UINT __stdcall CreateHostOnlyInterface(MSIHANDLE hModule)
839{
840#ifdef VBOX_WITH_NETFLT
841 netCfgLoggerEnable(hModule);
842
843 BOOL bSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
844 bool bSetStaticIp = true;
845
846 logStringW(hModule, L"CreateHostOnlyInterface: Creating host-only interface");
847
848 HRESULT hr = VBoxNetCfgWinRemoveAllNetDevicesOfId(NETADP_ID);
849 if (FAILED(hr))
850 {
851 logStringW(hModule, L"CreateHostOnlyInterface: VBoxNetCfgWinRemoveAllNetDevicesOfId failed, error = 0x%x", hr);
852 bSetStaticIp = false;
853 }
854
855 GUID guid;
856 WCHAR wszMpInf[MAX_PATH];
857 DWORD cchMpInf = RT_ELEMENTS(wszMpInf) - sizeof("drivers\\network\\netadp\\VBoxNetAdp.inf") - 1;
858 LPCWSTR pwszInfPath = NULL;
859 bool bIsFile = false;
860 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", wszMpInf, &cchMpInf);
861 if (uErr == ERROR_SUCCESS)
862 {
863 if (cchMpInf)
864 {
865 logStringW(hModule, L"CreateHostOnlyInterface: NetAdpDir property = %s", wszMpInf);
866 if (wszMpInf[cchMpInf - 1] != L'\\')
867 {
868 wszMpInf[cchMpInf++] = L'\\';
869 wszMpInf[cchMpInf] = L'\0';
870 }
871
872 wcscat(wszMpInf, L"drivers\\network\\netadp\\VBoxNetAdp.inf");
873 pwszInfPath = wszMpInf;
874 bIsFile = true;
875
876 logStringW(hModule, L"CreateHostOnlyInterface: Resulting INF path = %s", pwszInfPath);
877 }
878 else
879 logStringW(hModule, L"CreateHostOnlyInterface: NetAdpDir property value is empty");
880 }
881 else
882 logStringW(hModule, L"CreateHostOnlyInterface: Failed to get NetAdpDir property, error = 0x%x", uErr);
883
884 /* Make sure the inf file is installed. */
885 if (pwszInfPath != NULL && bIsFile)
886 {
887 logStringW(hModule, L"CreateHostOnlyInterface: Calling VBoxDrvCfgInfInstall(%s)", pwszInfPath);
888 hr = VBoxDrvCfgInfInstall(pwszInfPath);
889 logStringW(hModule, L"CreateHostOnlyInterface: VBoxDrvCfgInfInstall returns 0x%x", hr);
890 if (FAILED(hr))
891 logStringW(hModule, L"CreateHostOnlyInterface: Failed to install INF file, error = 0x%x", hr);
892 }
893
894 if (SUCCEEDED(hr))
895 {
896 logStringW(hModule, L"CreateHostOnlyInterface: calling VBoxNetCfgWinCreateHostOnlyNetworkInterface");
897 hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, bIsFile, &guid, NULL, NULL);
898 logStringW(hModule, L"CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface returns 0x%x", hr);
899 if (SUCCEEDED(hr))
900 {
901 ULONG ip = inet_addr("192.168.56.1");
902 ULONG mask = inet_addr("255.255.255.0");
903 logStringW(hModule, L"CreateHostOnlyInterface: calling VBoxNetCfgWinEnableStaticIpConfig");
904 hr = VBoxNetCfgWinEnableStaticIpConfig(&guid, ip, mask);
905 logStringW(hModule, L"CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig returns 0x%x", hr);
906 if (FAILED(hr))
907 logStringW(hModule, L"CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, error = 0x%x", hr);
908 }
909 else
910 logStringW(hModule, L"CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, error = 0x%x", hr);
911 }
912
913 if (SUCCEEDED(hr))
914 logStringW(hModule, L"CreateHostOnlyInterface: Creating host-only interface done");
915
916 /* Restore original setup mode. */
917 logStringW(hModule, L"CreateHostOnlyInterface: Almost done...");
918 if (bSetupModeInteractive)
919 SetupSetNonInteractiveMode(bSetupModeInteractive);
920
921 netCfgLoggerDisable();
922
923#endif /* VBOX_WITH_NETFLT */
924
925 logStringW(hModule, L"CreateHostOnlyInterface: Returns success (ignoring all failures)");
926 /* Never fail the install even if we did not succeed. */
927 return ERROR_SUCCESS;
928}
929
930UINT __stdcall RemoveHostOnlyInterfaces(MSIHANDLE hModule)
931{
932#ifdef VBOX_WITH_NETFLT
933 netCfgLoggerEnable(hModule);
934
935 logStringW(hModule, L"RemoveHostOnlyInterfaces: Removing all host-only interfaces");
936
937 BOOL bSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
938
939 HRESULT hr = VBoxNetCfgWinRemoveAllNetDevicesOfId(NETADP_ID);
940 if (SUCCEEDED(hr))
941 {
942 hr = VBoxDrvCfgInfUninstallAllSetupDi(&GUID_DEVCLASS_NET, NETADP_ID, L"Net", 0/* could be SUOI_FORCEDELETE */);
943 if (FAILED(hr))
944 {
945 logStringW(hModule, L"RemoveHostOnlyInterfaces: NetAdp uninstalled successfully, but failed to remove infs");
946 }
947 }
948 else
949 logStringW(hModule, L"RemoveHostOnlyInterfaces: NetAdp uninstall failed, hr = 0x%x", hr);
950
951 /* Restore original setup mode. */
952 if (bSetupModeInteractive)
953 SetupSetNonInteractiveMode(bSetupModeInteractive);
954
955 netCfgLoggerDisable();
956#endif /* VBOX_WITH_NETFLT */
957
958 /* Never fail the install even if we did not succeed. */
959 return ERROR_SUCCESS;
960}
961
962UINT __stdcall StopHostOnlyInterfaces(MSIHANDLE hModule)
963{
964#ifdef VBOX_WITH_NETFLT
965 netCfgLoggerEnable(hModule);
966
967 logStringW(hModule, L"StopHostOnlyInterfaces: Stopping all host-only interfaces");
968
969 BOOL bSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
970
971 HRESULT hr = VBoxNetCfgWinPropChangeAllNetDevicesOfId(NETADP_ID, VBOXNECTFGWINPROPCHANGE_TYPE_DISABLE);
972 if (SUCCEEDED(hr))
973 {
974 hr = VBoxDrvCfgInfUninstallAllSetupDi(&GUID_DEVCLASS_NET, NETADP_ID, L"Net", 0/* could be SUOI_FORCEDELETE */);
975 if (FAILED(hr))
976 logStringW(hModule, L"StopHostOnlyInterfaces: VBoxDrvCfgInfUninstallAllSetupDi failed, hr = 0x%x", hr);
977 }
978 else
979 logStringW(hModule, L"StopHostOnlyInterfaces: Disabling host interfaces failed, hr = 0x%x", hr);
980
981 /* Restore original setup mode. */
982 if (bSetupModeInteractive)
983 SetupSetNonInteractiveMode(bSetupModeInteractive);
984
985 netCfgLoggerDisable();
986#endif /* VBOX_WITH_NETFLT */
987
988 /* Never fail the install even if we did not succeed. */
989 return ERROR_SUCCESS;
990}
991
992UINT __stdcall UpdateHostOnlyInterfaces(MSIHANDLE hModule)
993{
994#ifdef VBOX_WITH_NETFLT
995 netCfgLoggerEnable(hModule);
996
997 logStringW(hModule, L"UpdateHostOnlyInterfaces: Updating all host-only interfaces");
998
999 BOOL bSetupModeInteractive = SetupSetNonInteractiveMode(FALSE);
1000
1001 WCHAR wszMpInf[MAX_PATH];
1002 DWORD cchMpInf = RT_ELEMENTS(wszMpInf) - sizeof("drivers\\network\\netadp\\VBoxNetAdp.inf") - 1;
1003 LPCWSTR pwszInfPath = NULL;
1004 bool bIsFile = false;
1005 UINT uErr = MsiGetPropertyW(hModule, L"CustomActionData", wszMpInf, &cchMpInf);
1006 if (uErr == ERROR_SUCCESS)
1007 {
1008 if (cchMpInf)
1009 {
1010 logStringW(hModule, L"UpdateHostOnlyInterfaces: NetAdpDir property = %s", wszMpInf);
1011 if (wszMpInf[cchMpInf - 1] != L'\\')
1012 {
1013 wszMpInf[cchMpInf++] = L'\\';
1014 wszMpInf[cchMpInf] = L'\0';
1015 }
1016
1017 wcscat(wszMpInf, L"drivers\\network\\netadp\\VBoxNetAdp.inf");
1018 pwszInfPath = wszMpInf;
1019 bIsFile = true;
1020
1021 logStringW(hModule, L"UpdateHostOnlyInterfaces: Resulting INF path = %s", pwszInfPath);
1022
1023 DWORD attrFile = GetFileAttributesW(pwszInfPath);
1024 if (attrFile == INVALID_FILE_ATTRIBUTES)
1025 {
1026 DWORD dwErr = GetLastError();
1027 logStringW(hModule, L"UpdateHostOnlyInterfaces: File \"%s\" not found, dwErr=%ld",
1028 pwszInfPath, dwErr);
1029 }
1030 else
1031 {
1032 logStringW(hModule, L"UpdateHostOnlyInterfaces: File \"%s\" exists",
1033 pwszInfPath);
1034
1035 BOOL fRebootRequired = FALSE;
1036 HRESULT hr = VBoxNetCfgWinUpdateHostOnlyNetworkInterface(pwszInfPath, &fRebootRequired);
1037 if (SUCCEEDED(hr))
1038 {
1039 if (fRebootRequired)
1040 {
1041 logStringW(hModule, L"UpdateHostOnlyInterfaces: Reboot required, setting REBOOT property to force");
1042 HRESULT hr2 = MsiSetPropertyW(hModule, L"REBOOT", L"Force");
1043 if (hr2 != ERROR_SUCCESS)
1044 logStringW(hModule, L"UpdateHostOnlyInterfaces: Failed to set REBOOT property, error = 0x%x", hr2);
1045 }
1046 }
1047 else
1048 logStringW(hModule, L"UpdateHostOnlyInterfaces: VBoxNetCfgWinUpdateHostOnlyNetworkInterface failed, hr = 0x%x", hr);
1049 }
1050 }
1051 else
1052 logStringW(hModule, L"UpdateHostOnlyInterfaces: NetAdpDir property value is empty");
1053 }
1054 else
1055 logStringW(hModule, L"UpdateHostOnlyInterfaces: Failed to get NetAdpDir property, error = 0x%x", uErr);
1056
1057 /* Restore original setup mode. */
1058 if (bSetupModeInteractive)
1059 SetupSetNonInteractiveMode(bSetupModeInteractive);
1060
1061 netCfgLoggerDisable();
1062#endif /* VBOX_WITH_NETFLT */
1063
1064 /* Never fail the install even if we did not succeed. */
1065 return ERROR_SUCCESS;
1066}
1067
1068static bool isTAPDevice(const WCHAR *pwszGUID)
1069{
1070 HKEY hNetcard;
1071 bool bIsTapDevice = false;
1072 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1073 L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
1074 0, KEY_READ, &hNetcard);
1075 if (lStatus != ERROR_SUCCESS)
1076 return false;
1077
1078 int i = 0;
1079 for (;;)
1080 {
1081 WCHAR wszEnumName[256];
1082 WCHAR wszNetCfgInstanceId[256];
1083 DWORD dwKeyType;
1084 HKEY hNetCardGUID;
1085
1086 DWORD dwLen = sizeof(wszEnumName);
1087 lStatus = RegEnumKeyExW(hNetcard, i, wszEnumName, &dwLen, NULL, NULL, NULL, NULL);
1088 if (lStatus != ERROR_SUCCESS)
1089 break;
1090
1091 lStatus = RegOpenKeyExW(hNetcard, wszEnumName, 0, KEY_READ, &hNetCardGUID);
1092 if (lStatus == ERROR_SUCCESS)
1093 {
1094 dwLen = sizeof(wszNetCfgInstanceId);
1095 lStatus = RegQueryValueExW(hNetCardGUID, L"NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)wszNetCfgInstanceId, &dwLen);
1096 if ( lStatus == ERROR_SUCCESS
1097 && dwKeyType == REG_SZ)
1098 {
1099 WCHAR wszNetProductName[256];
1100 WCHAR wszNetProviderName[256];
1101
1102 wszNetProductName[0] = 0;
1103 dwLen = sizeof(wszNetProductName);
1104 lStatus = RegQueryValueExW(hNetCardGUID, L"ProductName", NULL, &dwKeyType, (LPBYTE)wszNetProductName, &dwLen);
1105
1106 wszNetProviderName[0] = 0;
1107 dwLen = sizeof(wszNetProviderName);
1108 lStatus = RegQueryValueExW(hNetCardGUID, L"ProviderName", NULL, &dwKeyType, (LPBYTE)wszNetProviderName, &dwLen);
1109
1110 if ( !wcscmp(wszNetCfgInstanceId, pwszGUID)
1111 && !wcscmp(wszNetProductName, L"VirtualBox TAP Adapter")
1112 && ( (!wcscmp(wszNetProviderName, L"innotek GmbH")) /* Legacy stuff. */
1113 || (!wcscmp(wszNetProviderName, L"Sun Microsystems, Inc.")) /* Legacy stuff. */
1114 || (!wcscmp(wszNetProviderName, MY_WTEXT(VBOX_VENDOR))) /* Reflects current vendor string. */
1115 )
1116 )
1117 {
1118 bIsTapDevice = true;
1119 RegCloseKey(hNetCardGUID);
1120 break;
1121 }
1122 }
1123 RegCloseKey(hNetCardGUID);
1124 }
1125 ++i;
1126 }
1127
1128 RegCloseKey(hNetcard);
1129 return bIsTapDevice;
1130}
1131
1132#define SetErrBreak(strAndArgs) \
1133 if (1) { \
1134 rc = 0; \
1135 logStringW(hModule, strAndArgs); \
1136 break; \
1137 } else do {} while (0)
1138
1139int removeNetworkInterface(MSIHANDLE hModule, const WCHAR *pwszGUID)
1140{
1141 int rc = 1;
1142 do
1143 {
1144 WCHAR wszPnPInstanceId[512] = {0};
1145
1146 /* We have to find the device instance ID through a registry search */
1147
1148 HKEY hkeyNetwork = 0;
1149 HKEY hkeyConnection = 0;
1150
1151 do /* break-loop */
1152 {
1153 WCHAR wszRegLocation[256];
1154 swprintf(wszRegLocation,
1155 L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
1156 pwszGUID);
1157 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegLocation, 0, KEY_READ, &hkeyNetwork);
1158 if ((lStatus != ERROR_SUCCESS) || !hkeyNetwork)
1159 SetErrBreak((L"VBox HostInterfaces: Host interface network was not found in registry (%s)! [1]", wszRegLocation));
1160
1161 lStatus = RegOpenKeyExW(hkeyNetwork, L"Connection", 0, KEY_READ, &hkeyConnection);
1162 if ((lStatus != ERROR_SUCCESS) || !hkeyConnection)
1163 SetErrBreak((L"VBox HostInterfaces: Host interface network was not found in registry (%s)! [2]", wszRegLocation));
1164
1165 DWORD len = sizeof(wszPnPInstanceId);
1166 DWORD dwKeyType;
1167 lStatus = RegQueryValueExW(hkeyConnection, L"PnPInstanceID", NULL,
1168 &dwKeyType, (LPBYTE)&wszPnPInstanceId[0], &len);
1169 if ((lStatus != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
1170 SetErrBreak((L"VBox HostInterfaces: Host interface network was not found in registry (%s)! [3]", wszRegLocation));
1171 }
1172 while (0);
1173
1174 if (hkeyConnection)
1175 RegCloseKey(hkeyConnection);
1176 if (hkeyNetwork)
1177 RegCloseKey(hkeyNetwork);
1178
1179 /*
1180 * Now we are going to enumerate all network devices and
1181 * wait until we encounter the right device instance ID
1182 */
1183
1184 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1185 BOOL fResult;
1186
1187 do
1188 {
1189 DWORD ret = 0;
1190 GUID netGuid;
1191 SP_DEVINFO_DATA DeviceInfoData;
1192 DWORD index = 0;
1193 DWORD size = 0;
1194
1195 /* initialize the structure size */
1196 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1197
1198 /* copy the net class GUID */
1199 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
1200
1201 /* return a device info set contains all installed devices of the Net class */
1202 hDeviceInfo = SetupDiGetClassDevs(&netGuid, NULL, NULL, DIGCF_PRESENT);
1203 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1204 {
1205 logStringW(hModule, L"VBox HostInterfaces: SetupDiGetClassDevs failed (0x%08X)!", GetLastError());
1206 SetErrBreak(L"VBox HostInterfaces: Uninstallation failed!");
1207 }
1208
1209 BOOL fFoundDevice = FALSE;
1210
1211 /* enumerate the driver info list */
1212 while (TRUE)
1213 {
1214 WCHAR *pwszDeviceHwid;
1215
1216 fResult = SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData);
1217 if (!fResult)
1218 {
1219 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1220 break;
1221 else
1222 {
1223 index++;
1224 continue;
1225 }
1226 }
1227
1228 /* try to get the hardware ID registry property */
1229 fResult = SetupDiGetDeviceRegistryProperty(hDeviceInfo,
1230 &DeviceInfoData,
1231 SPDRP_HARDWAREID,
1232 NULL,
1233 NULL,
1234 0,
1235 &size);
1236 if (!fResult)
1237 {
1238 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1239 {
1240 index++;
1241 continue;
1242 }
1243
1244 pwszDeviceHwid = (WCHAR *)malloc(size);
1245 if (pwszDeviceHwid)
1246 {
1247 fResult = SetupDiGetDeviceRegistryProperty(hDeviceInfo,
1248 &DeviceInfoData,
1249 SPDRP_HARDWAREID,
1250 NULL,
1251 (PBYTE)pwszDeviceHwid,
1252 size,
1253 NULL);
1254 if (!fResult)
1255 {
1256 free(pwszDeviceHwid);
1257 pwszDeviceHwid = NULL;
1258 index++;
1259 continue;
1260 }
1261 }
1262 }
1263 else
1264 {
1265 /* something is wrong. This shouldn't have worked with a NULL buffer */
1266 index++;
1267 continue;
1268 }
1269
1270 for (WCHAR *t = pwszDeviceHwid;
1271 t && *t && t < &pwszDeviceHwid[size / sizeof(WCHAR)];
1272 t += wcslen(t) + 1)
1273 {
1274 if (!_wcsicmp(L"vboxtap", t))
1275 {
1276 /* get the device instance ID */
1277 WCHAR wszDevID[MAX_DEVICE_ID_LEN];
1278 if (CM_Get_Device_IDW(DeviceInfoData.DevInst,
1279 wszDevID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
1280 {
1281 /* compare to what we determined before */
1282 if (!wcscmp(wszDevID, wszPnPInstanceId))
1283 {
1284 fFoundDevice = TRUE;
1285 break;
1286 }
1287 }
1288 }
1289 }
1290
1291 if (pwszDeviceHwid)
1292 {
1293 free(pwszDeviceHwid);
1294 pwszDeviceHwid = NULL;
1295 }
1296
1297 if (fFoundDevice)
1298 break;
1299
1300 index++;
1301 }
1302
1303 if (fFoundDevice)
1304 {
1305 fResult = SetupDiSetSelectedDevice(hDeviceInfo, &DeviceInfoData);
1306 if (!fResult)
1307 {
1308 logStringW(hModule, L"VBox HostInterfaces: SetupDiSetSelectedDevice failed (0x%08X)!", GetLastError());
1309 SetErrBreak(L"VBox HostInterfaces: Uninstallation failed!");
1310 }
1311
1312 fResult = SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
1313 if (!fResult)
1314 {
1315 logStringW(hModule, L"VBox HostInterfaces: SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)!", GetLastError());
1316 SetErrBreak(L"VBox HostInterfaces: Uninstallation failed!");
1317 }
1318 }
1319 else
1320 SetErrBreak(L"VBox HostInterfaces: Host interface network device not found!");
1321 }
1322 while (0);
1323
1324 /* clean up the device info set */
1325 if (hDeviceInfo != INVALID_HANDLE_VALUE)
1326 SetupDiDestroyDeviceInfoList(hDeviceInfo);
1327 }
1328 while (0);
1329 return rc;
1330}
1331
1332UINT __stdcall UninstallTAPInstances(MSIHANDLE hModule)
1333{
1334 static const WCHAR *s_wszNetworkKey = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
1335 HKEY hCtrlNet;
1336
1337 LONG lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_wszNetworkKey, 0, KEY_READ, &hCtrlNet);
1338 if (lStatus == ERROR_SUCCESS)
1339 {
1340 logStringW(hModule, L"VBox HostInterfaces: Enumerating interfaces ...");
1341 for (int i = 0; ; ++i)
1342 {
1343 WCHAR wszNetworkGUID[256] = { 0 };
1344 DWORD dwLen = (DWORD)sizeof(wszNetworkGUID);
1345 lStatus = RegEnumKeyExW(hCtrlNet, i, wszNetworkGUID, &dwLen, NULL, NULL, NULL, NULL);
1346 if (lStatus != ERROR_SUCCESS)
1347 {
1348 switch (lStatus)
1349 {
1350 case ERROR_NO_MORE_ITEMS:
1351 logStringW(hModule, L"VBox HostInterfaces: No interfaces found.");
1352 break;
1353 default:
1354 logStringW(hModule, L"VBox HostInterfaces: Enumeration failed: %ld", lStatus);
1355 break;
1356 }
1357 break;
1358 }
1359
1360 if (isTAPDevice(wszNetworkGUID))
1361 {
1362 logStringW(hModule, L"VBox HostInterfaces: Removing interface \"%s\" ...", wszNetworkGUID);
1363 removeNetworkInterface(hModule, wszNetworkGUID);
1364 lStatus = RegDeleteKeyW(hCtrlNet, wszNetworkGUID);
1365 }
1366 }
1367 RegCloseKey(hCtrlNet);
1368 logStringW(hModule, L"VBox HostInterfaces: Removing interfaces done.");
1369 }
1370 return ERROR_SUCCESS;
1371}
1372
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