VirtualBox

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

Last change on this file since 37195 was 36487, checked in by vboxsync, 14 years ago

netflt/adp/win: switch to new VBoxDrvCfg lib

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.9 KB
Line 
1/* $Id: VBoxInstallHelper.cpp 36487 2011-04-01 08:21:30Z vboxsync $ */
2/** @file
3 * VBoxInstallHelper - Various helper routines for Windows host installer.
4 */
5
6/*
7 * Copyright (C) 2008-2010 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#ifdef VBOX_WITH_NETFLT
19# include "VBox/VBoxNetCfg-win.h"
20# include "VBox/VBoxDrvCfg-win.h"
21#endif /* VBOX_WITH_NETFLT */
22
23#include <VBox/version.h>
24
25#include <windows.h>
26#include <tchar.h>
27#include <stdio.h>
28
29#include <msi.h>
30#include <msiquery.h>
31
32#define _WIN32_DCOM
33#include <windows.h>
34#include <assert.h>
35#include <shellapi.h>
36#define INITGUID
37#include <guiddef.h>
38#include <devguid.h>
39#include <objbase.h>
40#include <setupapi.h>
41#include <shlobj.h>
42#include <cfgmgr32.h>
43
44#include "VBoxCommon.h"
45
46#ifndef VBOX_OSE
47# include "internal/VBoxSerial.h"
48#endif
49
50#ifdef DEBUG
51# define Assert(_expr) assert(_expr)
52#else
53# define Assert(_expr) do{ }while(0)
54#endif
55
56BOOL APIENTRY DllMain(HANDLE hModule,
57 DWORD ul_reason_for_call,
58 LPVOID lpReserved)
59{
60 return TRUE;
61}
62
63void LogString(MSIHANDLE hInstall, TCHAR* szString, ...)
64{
65 PMSIHANDLE newHandle = ::MsiCreateRecord(2);
66
67 TCHAR szBuffer[1024] = {0};
68 va_list pArgList;
69 va_start(pArgList, szString);
70 _vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szString, pArgList);
71 va_end(pArgList);
72
73 MsiRecordSetString(newHandle, 0, szBuffer);
74 MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), newHandle);
75 MsiCloseHandle(newHandle);
76
77#ifdef DEBUG
78 _tprintf(_T("Debug: %s\n"), szBuffer);
79#endif
80}
81
82static void LogStringW(MSIHANDLE hInstall, LPCWSTR szString, ...)
83{
84 PMSIHANDLE newHandle = ::MsiCreateRecord(2);
85
86 TCHAR szBuffer[1024] = {0};
87 va_list pArgList;
88 va_start(pArgList, szString);
89 _vsnwprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szString, pArgList);
90 va_end(pArgList);
91
92 MsiRecordSetStringW(newHandle, 0, szBuffer);
93 MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), newHandle);
94 MsiCloseHandle(newHandle);
95}
96
97UINT __stdcall IsSerialCheckNeeded(MSIHANDLE a_hModule)
98{
99#ifndef VBOX_OSE
100 /*BOOL bRet =*/ serialCheckNeeded(a_hModule);
101#endif
102 return ERROR_SUCCESS;
103}
104
105UINT __stdcall CheckSerial(MSIHANDLE a_hModule)
106{
107#ifndef VBOX_OSE
108 /*BOOL bRet =*/ serialIsValid(a_hModule);
109#endif
110 return ERROR_SUCCESS;
111}
112
113DWORD Exec(MSIHANDLE hModule, TCHAR* szAppName, TCHAR* szCmdLine, TCHAR* szWorkDir, DWORD* dwExitCode)
114{
115 STARTUPINFO si;
116 PROCESS_INFORMATION pi;
117 DWORD rc = ERROR_SUCCESS;
118
119 ::ZeroMemory(&si, sizeof(si));
120 si.dwFlags = STARTF_USESHOWWINDOW;
121#ifdef UNICODE
122 si.dwFlags |= CREATE_UNICODE_ENVIRONMENT;
123#endif
124 si.wShowWindow = SW_HIDE; /* For debugging: SW_SHOW; */
125 si.cb = sizeof(si);
126 ::ZeroMemory(&pi, sizeof(pi));
127
128 LogString(hModule, TEXT("Executing command line: %s %s (Working Dir: %s)"), szAppName, szCmdLine, szWorkDir == NULL ? L"Current" : szWorkDir);
129
130 ::SetLastError(0);
131 if (!::CreateProcess(szAppName, /* Module name. */
132 szCmdLine, /* Command line. */
133 NULL, /* Process handle not inheritable. */
134 NULL, /* Thread handle not inheritable. */
135 FALSE, /* Set handle inheritance to FALSE .*/
136 0, /* No creation flags. */
137 NULL, /* Use parent's environment block. */
138 szWorkDir, /* Use parent's starting directory. */
139 &si, /* Pointer to STARTUPINFO structure. */
140 &pi)) /* Pointer to PROCESS_INFORMATION structure. */
141 {
142 rc = ::GetLastError();
143 LogString(hModule, TEXT("Executing command line: CreateProcess() failed! Error: %ld"), rc);
144 return rc;
145 }
146
147 /* Wait until child process exits. */
148 if (WAIT_FAILED == ::WaitForSingleObject(pi.hProcess, 30 * 1000 /* Wait 30 secs max. */))
149 {
150 rc = ::GetLastError();
151 LogString(hModule, TEXT("Executing command line: WaitForSingleObject() failed! Error: %ld"), rc);
152 }
153 else
154 {
155 if (0 == ::GetExitCodeProcess(pi.hProcess, dwExitCode))
156 {
157 rc = ::GetLastError();
158 LogString(hModule, TEXT("Executing command line: GetExitCodeProcess() failed! Error: %ld"), rc);
159 }
160 }
161
162 /* Close process and thread handles. */
163 ::CloseHandle(pi.hProcess);
164 ::CloseHandle(pi.hThread);
165
166 LogString(hModule, TEXT("Executing command returned: %ld (exit code %ld)"), rc, *dwExitCode);
167 return rc;
168}
169
170UINT __stdcall InstallPythonAPI(MSIHANDLE hModule)
171{
172 LogString(hModule, TEXT("InstallPythonAPI: Checking for installed Python environment ..."));
173
174 HKEY hkPythonCore = NULL;
175 BOOL bInstalled = FALSE;
176 LONG rc = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Python\\PythonCore", 0, KEY_READ, &hkPythonCore);
177 if (rc != ERROR_SUCCESS)
178 {
179 LogString(hModule, TEXT("InstallPythonAPI: No environment seems to be installed."));
180 return ERROR_SUCCESS;
181 }
182
183 TCHAR szPath[MAX_PATH] = { 0 };
184 TCHAR szVal[MAX_PATH] = { 0 };
185
186 for (int i = 0;; ++i)
187 {
188 TCHAR szRoot[MAX_PATH] = { 0 };
189 DWORD dwLen = sizeof (szPath);
190 DWORD dwKeyType = REG_SZ;
191
192 rc = ::RegEnumKeyEx(hkPythonCore, i, szRoot, &dwLen, NULL, NULL, NULL, NULL);
193 if (rc != ERROR_SUCCESS || dwLen <= 0)
194 break;
195
196 _stprintf_s(szPath, sizeof(szPath) / sizeof(TCHAR), L"%s\\InstallPath", szRoot);
197 dwLen = sizeof(szVal);
198
199 HKEY hkPythonInstPath = NULL;
200 rc = ::RegOpenKeyEx(hkPythonCore, szPath, 0, KEY_READ, &hkPythonInstPath);
201 if (rc != ERROR_SUCCESS)
202 continue;
203
204 rc = ::RegQueryValueEx(hkPythonInstPath, L"", NULL, &dwKeyType, (LPBYTE)szVal, &dwLen);
205 if(rc == ERROR_SUCCESS)
206 LogString(hModule, TEXT("InstallPythonAPI: Path \"%s\" detected."), szVal);
207
208 ::RegCloseKey(hkPythonInstPath);
209 }
210 ::RegCloseKey(hkPythonCore);
211
212 /* Python path found? */
213 TCHAR szExec[MAX_PATH] = { 0 };
214 TCHAR szCmdLine[MAX_PATH] = { 0 };
215 DWORD dwExitCode = 0;
216 if (::_tcslen(szVal) > 0)
217 {
218 /* Cool, check for installed Win32 extensions. */
219 LogString(hModule, TEXT("InstallPythonAPI: Python installed. Checking for Win32 extensions ..."));
220 _stprintf_s(szExec, sizeof(szExec) / sizeof(TCHAR), L"%s\\python.exe", szVal);
221 _stprintf_s(szCmdLine, sizeof(szCmdLine) / sizeof(TCHAR), L"%s\\python.exe -c \"import win32api\"", szVal);
222
223 if ( (0 == Exec(hModule, szExec, szCmdLine, NULL, &dwExitCode))
224 && (0 == dwExitCode))
225 {
226 /* Did we get the correct error level (=0)? */
227 LogString(hModule, TEXT("InstallPythonAPI: Win32 extensions installed."));
228 bInstalled = TRUE;
229 }
230 else LogString(hModule, TEXT("InstallPythonAPI: Win32 extensions not found."));
231 }
232
233 if (bInstalled) /* Is Python and all required stuff installed? */
234 {
235 /* Get the VBoxAPI setup string. */
236 TCHAR szVBoxAPISetupPath[MAX_PATH] = {0};
237 VBoxGetProperty(hModule, L"INSTALLDIR", szVBoxAPISetupPath, sizeof(szVBoxAPISetupPath));
238
239 /* Set final path. */
240 _stprintf_s(szPath, sizeof(szPath) / sizeof(TCHAR), L"%s\\sdk\\install", szVBoxAPISetupPath);
241
242 /* Install our API module. */
243 _stprintf_s(szCmdLine, sizeof(szCmdLine) / sizeof(TCHAR), L"%s\\python.exe vboxapisetup.py install", szVal);
244
245 /* Set required environment variables. */
246 if (!SetEnvironmentVariable(L"VBOX_INSTALL_PATH", szVBoxAPISetupPath))
247 {
248 LogString(hModule, TEXT("InstallPythonAPI: Cannot set environment variable VBOX_INSTALL_PATH!"));
249 return FALSE;
250 }
251 else
252 {
253 if ( (0 == Exec(hModule, szExec, szCmdLine, szPath, &dwExitCode))
254 && (0 == dwExitCode))
255 {
256 /* All done! */
257 LogString(hModule, TEXT("InstallPythonAPI: VBoxAPI for Python successfully installed."));
258 return ERROR_SUCCESS;
259 }
260 else LogString(hModule, TEXT("InstallPythonAPI: Error while installing VBoxAPI: %ld"), dwExitCode);
261 }
262 }
263
264 LogString(hModule, TEXT("InstallPythonAPI: VBoxAPI not installed."));
265 return ERROR_SUCCESS; /* Do not fail here. */
266}
267
268static LONG InstallBrandingValue(MSIHANDLE hModule,
269 const TCHAR* pszFileName,
270 const TCHAR* pszSection,
271 const TCHAR* pszValue)
272{
273 LONG rc;
274 TCHAR szValue[_MAX_PATH];
275 if (GetPrivateProfileString(pszSection, pszValue, NULL,
276 szValue, sizeof(szValue), pszFileName) > 0)
277 {
278 HKEY hkBranding;
279 TCHAR szKey[_MAX_PATH];
280
281 if (wcsicmp(L"General", pszSection) != 0)
282 _stprintf_s(szKey, sizeof(szKey) / sizeof(TCHAR), L"SOFTWARE\\%s\\VirtualBox\\Branding\\", VBOX_VENDOR_SHORT, pszSection);
283 else
284 _stprintf_s(szKey, sizeof(szKey) / sizeof(TCHAR), L"SOFTWARE\\%s\\VirtualBox\\Branding", VBOX_VENDOR_SHORT);
285
286 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey,
287 0, KEY_WRITE, &hkBranding);
288 if (rc == ERROR_SUCCESS)
289 {
290 rc = RegSetValueEx(hkBranding,
291 pszValue,
292 NULL,
293 REG_SZ,
294 (BYTE*)szValue,
295 (DWORD)wcslen(szValue));
296 if (rc != ERROR_SUCCESS)
297 LogString(hModule, TEXT("InstallBranding: Could not write value %s! Error %ld"), pszValue, rc);
298 RegCloseKey (hkBranding);
299 }
300 }
301 else
302 rc = ERROR_NOT_FOUND;
303 return rc;
304}
305
306UINT CopyDir(MSIHANDLE hModule, const TCHAR *pszDestDir, const TCHAR *pszSourceDir)
307{
308 UINT rc;
309 TCHAR szDest[_MAX_PATH + 1];
310 TCHAR szSource[_MAX_PATH + 1];
311
312 _stprintf_s(szDest, sizeof(szDest) / sizeof(TCHAR), L"%s%c", pszDestDir, '\0');
313 _stprintf_s(szSource, sizeof(szSource) / sizeof(TCHAR), L"%s%c", pszSourceDir, '\0');
314
315 SHFILEOPSTRUCT s = {0};
316 s.hwnd = NULL;
317 s.wFunc = FO_COPY;
318 s.pTo = szDest;
319 s.pFrom = szSource;
320 s.fFlags = FOF_SILENT |
321 FOF_NOCONFIRMATION |
322 FOF_NOCONFIRMMKDIR |
323 FOF_NOERRORUI;
324
325 LogString(hModule, TEXT("CopyDir: DestDir=%s, SourceDir=%s"),
326 szDest, szSource);
327 int r = SHFileOperation(&s);
328 if (r != 0)
329 {
330 LogString(hModule, TEXT("CopyDir: Copy operation returned status 0x%x"), r);
331 rc = ERROR_GEN_FAILURE;
332 }
333 else
334 rc = ERROR_SUCCESS;
335 return rc;
336}
337
338UINT RemoveDir(MSIHANDLE hModule, const TCHAR *pszDestDir)
339{
340 UINT rc;
341 TCHAR szDest[_MAX_PATH + 1];
342
343 _stprintf_s(szDest, sizeof(szDest) / sizeof(TCHAR), L"%s%c", pszDestDir, '\0');
344
345 SHFILEOPSTRUCT s = {0};
346 s.hwnd = NULL;
347 s.wFunc = FO_DELETE;
348 s.pFrom = szDest;
349 s.fFlags = FOF_SILENT |
350 FOF_NOCONFIRMATION |
351 FOF_NOCONFIRMMKDIR |
352 FOF_NOERRORUI;
353
354 LogString(hModule, TEXT("RemoveDir: DestDir=%s"), szDest);
355 int r = SHFileOperation(&s);
356 if (r != 0)
357 {
358 LogString(hModule, TEXT("RemoveDir: Remove operation returned status 0x%x"), r);
359 rc = ERROR_GEN_FAILURE;
360 }
361 else
362 rc = ERROR_SUCCESS;
363 return rc;
364}
365
366UINT RenameDir(MSIHANDLE hModule, const TCHAR *pszDestDir, const TCHAR *pszSourceDir)
367{
368 UINT rc;
369 TCHAR szDest[_MAX_PATH + 1];
370 TCHAR szSource[_MAX_PATH + 1];
371
372 _stprintf_s(szDest, sizeof(szDest) / sizeof(TCHAR), L"%s%c", pszDestDir, '\0');
373 _stprintf_s(szSource, sizeof(szSource) / sizeof(TCHAR), L"%s%c", pszSourceDir, '\0');
374
375 SHFILEOPSTRUCT s = {0};
376 s.hwnd = NULL;
377 s.wFunc = FO_RENAME;
378 s.pTo = szDest;
379 s.pFrom = szSource;
380 s.fFlags = FOF_SILENT |
381 FOF_NOCONFIRMATION |
382 FOF_NOCONFIRMMKDIR |
383 FOF_NOERRORUI;
384
385 LogString(hModule, TEXT("RenameDir: DestDir=%s, SourceDir=%s"),
386 szDest, szSource);
387 int r = SHFileOperation(&s);
388 if (r != 0)
389 {
390 LogString(hModule, TEXT("RenameDir: Rename operation returned status 0x%x"), r);
391 rc = ERROR_GEN_FAILURE;
392 }
393 else
394 rc = ERROR_SUCCESS;
395 return rc;
396}
397
398UINT __stdcall UninstallBranding(MSIHANDLE hModule)
399{
400 UINT rc;
401 LogString(hModule, TEXT("UninstallBranding: Handling branding file ..."));
402
403 TCHAR szPathTargetDir[_MAX_PATH];
404 TCHAR szPathDest[_MAX_PATH];
405
406 rc = VBoxGetProperty(hModule, L"INSTALLDIR", szPathTargetDir, sizeof(szPathTargetDir));
407 if (rc == ERROR_SUCCESS)
408 {
409 /** @todo Check trailing slash after %s. */
410 _stprintf_s(szPathDest, sizeof(szPathDest) / sizeof(TCHAR), L"%scustom", szPathTargetDir);
411 rc = RemoveDir(hModule, szPathDest);
412 if (rc != ERROR_SUCCESS)
413 {
414 /* Check for hidden .custom directory and remove it. */
415 _stprintf_s(szPathDest, sizeof(szPathDest) / sizeof(TCHAR), L"%s.custom", szPathTargetDir);
416 rc = RemoveDir(hModule, szPathDest);
417 }
418 }
419
420 LogString(hModule, TEXT("UninstallBranding: Handling done."));
421 return ERROR_SUCCESS; /* Do not fail here. */
422}
423
424UINT __stdcall InstallBranding(MSIHANDLE hModule)
425{
426 UINT rc;
427 LogString(hModule, TEXT("InstallBranding: Handling branding file ..."));
428
429 TCHAR szPathMSI[_MAX_PATH];
430 TCHAR szPathTargetDir[_MAX_PATH];
431
432 TCHAR szPathSource[_MAX_PATH];
433 TCHAR szPathDest[_MAX_PATH];
434
435 rc = VBoxGetProperty(hModule, L"SOURCEDIR", szPathMSI, sizeof(szPathMSI));
436 rc = VBoxGetProperty(hModule, L"INSTALLDIR", szPathTargetDir, sizeof(szPathTargetDir));
437 if (rc == ERROR_SUCCESS)
438 {
439 /** @todo Check for trailing slash after %s. */
440 _stprintf_s(szPathDest, sizeof(szPathDest) / sizeof(TCHAR), L"%s", szPathTargetDir);
441 _stprintf_s(szPathSource, sizeof(szPathSource) / sizeof(TCHAR), L"%s.custom", szPathMSI);
442 rc = CopyDir(hModule, szPathDest, szPathSource);
443 if (rc == ERROR_SUCCESS)
444 {
445 _stprintf_s(szPathDest, sizeof(szPathDest) / sizeof(TCHAR), L"%scustom", szPathTargetDir);
446 _stprintf_s(szPathSource, sizeof(szPathSource) / sizeof(TCHAR), L"%s.custom", szPathTargetDir);
447 rc = RenameDir(hModule, szPathDest, szPathSource);
448 }
449 }
450
451 LogString(hModule, TEXT("InstallBranding: Handling done."));
452 return ERROR_SUCCESS; /* Do not fail here. */
453}
454
455#ifdef VBOX_WITH_NETFLT
456
457/** @todo should use some real VBox app name */
458#define VBOX_NETCFG_APP_NAME L"VirtualBox Installer"
459#define VBOX_NETCFG_MAX_RETRIES 10
460#define NETFLT_PT_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFlt.inf"
461#define NETFLT_MP_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFltM.inf"
462#define NETFLT_ID L"sun_VBoxNetFlt" /** @todo Needs to be changed (?). */
463#define NETADP_ID L"sun_VBoxNetAdp" /** @todo Needs to be changed (?). */
464
465static MSIHANDLE g_hCurrentModule = NULL;
466static VOID winNetCfgLogger(LPCWSTR szString)
467{
468 Assert(g_hCurrentModule);
469 if(g_hCurrentModule)
470 {
471 LogStringW(g_hCurrentModule, szString);
472 }
473}
474
475static VOID inintWinNetCfgLogger(MSIHANDLE hModule)
476{
477 Assert(!g_hCurrentModule);
478 Assert(hModule);
479
480 g_hCurrentModule = hModule;
481
482 VBoxNetCfgWinSetLogging((LOG_ROUTINE)winNetCfgLogger);
483}
484
485static VOID finiWinNetCfgLogger()
486{
487 Assert(g_hCurrentModule);
488
489 VBoxNetCfgWinSetLogging((LOG_ROUTINE)NULL);
490
491 g_hCurrentModule = NULL;
492}
493
494static UINT Hresult2Error(MSIHANDLE hModule, HRESULT hr)
495{
496 switch(hr)
497 {
498 case S_OK:
499 return ERROR_SUCCESS;
500 case NETCFG_S_REBOOT:
501 LogString(hModule, TEXT("Reboot required, setting REBOOT property to Force"));
502 if(MsiSetProperty(hModule, TEXT("REBOOT"), TEXT("Force")) != ERROR_SUCCESS)
503 {
504 LogString(hModule, TEXT("Failed to set REBOOT property"));
505 return ERROR_GEN_FAILURE;
506 }
507 return ERROR_SUCCESS;
508 default:
509 LogString(hModule, TEXT("converting hresult (0x%x) to ERROR_GEN_FAILURE"), hr);
510 return ERROR_GEN_FAILURE;
511 }
512}
513
514static MSIHANDLE createNetCfgLockedMsgRecord(MSIHANDLE hModule)
515{
516 MSIHANDLE hRecord = MsiCreateRecord(2);
517 Assert(hRecord);
518 if(hRecord)
519 {
520 do
521 {
522 UINT r = MsiRecordSetInteger(hRecord, 1, 25001);
523 Assert(r == ERROR_SUCCESS);
524 if(r != ERROR_SUCCESS)
525 {
526 LogString(hModule, TEXT("createNetCfgLockedMsgRecord: MsiRecordSetInteger failed, r (0x%x)"), r);
527 MsiCloseHandle(hRecord);
528 hRecord = NULL;
529 break;
530 }
531 }while(0);
532 }
533 else
534 {
535 LogString(hModule, TEXT("createNetCfgLockedMsgRecord: failed to create a record"));
536 }
537
538 return hRecord;
539}
540
541static UINT doNetCfgInit(MSIHANDLE hModule, INetCfg **ppnc, BOOL bWrite)
542{
543 MSIHANDLE hMsg = NULL;
544 UINT r = ERROR_GEN_FAILURE;
545 int MsgResult;
546 int cRetries = 0;
547
548 do
549 {
550 LPWSTR lpszLockedBy;
551 HRESULT hr = VBoxNetCfgWinQueryINetCfg(ppnc, bWrite, VBOX_NETCFG_APP_NAME, 10000, &lpszLockedBy);
552 if(hr != NETCFG_E_NO_WRITE_LOCK)
553 {
554 Assert(hr == S_OK);
555 if(hr != S_OK)
556 {
557 LogString(hModule, TEXT("doNetCfgInit: VBoxNetCfgWinQueryINetCfg failed, hr (0x%x)"), hr);
558 }
559 r = Hresult2Error(hModule, hr);
560 break;
561 }
562
563 /* hr == NETCFG_E_NO_WRITE_LOCK */
564
565 Assert(lpszLockedBy);
566 if(!lpszLockedBy)
567 {
568 LogString(hModule, TEXT("doNetCfgInit: lpszLockedBy == NULL, breaking"));
569 break;
570 }
571
572 /* on vista the 6to4svc.dll periodically maintains the lock for some reason,
573 * if this is the case, increase the wait period by retrying multiple times
574 * NOTE: we could alternatively increase the wait timeout,
575 * however it seems unneeded for most cases, e.g. in case some network connection property
576 * dialog is opened, it would be better to post a notification to the user as soon as possible
577 * rather than waiting for a longer period of time before displaying it */
578 if(cRetries < VBOX_NETCFG_MAX_RETRIES
579 && !wcscmp(lpszLockedBy, L"6to4svc.dll"))
580 {
581 cRetries++;
582 LogString(hModule, TEXT("doNetCfgInit: lpszLockedBy is 6to4svc.dll, retrying %d out of %d"), cRetries, VBOX_NETCFG_MAX_RETRIES);
583 MsgResult = IDRETRY;
584 }
585 else
586 {
587 if(!hMsg)
588 {
589 hMsg = createNetCfgLockedMsgRecord(hModule);
590 if(!hMsg)
591 {
592 LogString(hModule, TEXT("doNetCfgInit: failed to create a message record, breaking"));
593 CoTaskMemFree(lpszLockedBy);
594 break;
595 }
596 }
597
598 UINT rTmp = MsiRecordSetStringW(hMsg, 2, lpszLockedBy);
599 Assert(rTmp == ERROR_SUCCESS);
600 if(rTmp != ERROR_SUCCESS)
601 {
602 LogString(hModule, TEXT("doNetCfgInit: MsiRecordSetStringW failed, r (0x%x)"), rTmp);
603 CoTaskMemFree(lpszLockedBy);
604 break;
605 }
606
607 MsgResult = MsiProcessMessage(hModule, (INSTALLMESSAGE)(INSTALLMESSAGE_USER | MB_RETRYCANCEL), hMsg);
608 Assert(MsgResult == IDRETRY || MsgResult == IDCANCEL);
609 LogString(hModule, TEXT("doNetCfgInit: MsiProcessMessage returned (0x%x)"), MsgResult);
610 }
611 CoTaskMemFree(lpszLockedBy);
612 } while(MsgResult == IDRETRY);
613
614 if(hMsg)
615 {
616 MsiCloseHandle(hMsg);
617 }
618
619 return r;
620}
621
622static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR *apInfFullPaths, PUINT pcInfs, DWORD cSize)
623{
624 UINT r;
625 Assert(*pcInfs >= 2);
626 if(*pcInfs >= 2)
627 {
628 *pcInfs = 2;
629 r = MsiGetPropertyW(hModule, L"CustomActionData", apInfFullPaths[0], &cSize);
630 Assert(r == ERROR_SUCCESS);
631 if(r == ERROR_SUCCESS)
632 {
633 wcscpy(apInfFullPaths[1], apInfFullPaths[0]);
634
635 wcsncat(apInfFullPaths[0], NETFLT_PT_INF_REL_PATH, sizeof(NETFLT_PT_INF_REL_PATH));
636 wcsncat(apInfFullPaths[1], NETFLT_MP_INF_REL_PATH, sizeof(NETFLT_MP_INF_REL_PATH));
637 }
638 else
639 {
640 LogString(hModule, TEXT("vboxNetFltQueryInfArray: MsiGetPropertyW failes, r (%d)"), r);
641 }
642 }
643 else
644 {
645 r = ERROR_GEN_FAILURE;
646 LogString(hModule, TEXT("vboxNetFltQueryInfArray: buffer array size is < 2 : (%d)"), *pcInfs);
647 *pcInfs = 2;
648 }
649
650 return r;
651}
652
653#endif /*VBOX_WITH_NETFLT*/
654
655UINT __stdcall UninstallNetFlt(MSIHANDLE hModule)
656{
657#ifdef VBOX_WITH_NETFLT
658 INetCfg *pnc;
659 UINT r;
660
661 inintWinNetCfgLogger(hModule);
662
663 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
664
665 __try
666 {
667 LogString(hModule, TEXT("Uninstalling NetFlt"));
668
669 r = doNetCfgInit(hModule, &pnc, TRUE);
670 Assert(r == ERROR_SUCCESS);
671 if(r == ERROR_SUCCESS)
672 {
673 HRESULT hr = VBoxNetCfgWinNetFltUninstall(pnc);
674 Assert(hr == S_OK);
675 if(hr != S_OK)
676 {
677 LogString(hModule, TEXT("UninstallNetFlt: VBoxNetCfgWinUninstallComponent failed, hr (0x%x)"), hr);
678 }
679
680 r = Hresult2Error(hModule, hr);
681
682 VBoxNetCfgWinReleaseINetCfg(pnc, TRUE);
683
684 /* Never fail the uninstall */
685 r = ERROR_SUCCESS;
686 }
687 else
688 {
689 LogString(hModule, TEXT("UninstallNetFlt: doNetCfgInit failed, r (0x%x)"), r);
690 }
691
692 LogString(hModule, TEXT("Uninstalling NetFlt done, r (0x%x)"), r);
693 }
694 __finally
695 {
696 if(bOldIntMode)
697 {
698 /* the prev mode != FALSE, i.e. non-interactive */
699 SetupSetNonInteractiveMode(bOldIntMode);
700 }
701 finiWinNetCfgLogger();
702 }
703
704 return ERROR_SUCCESS;
705#else /* not defined VBOX_WITH_NETFLT */
706 return ERROR_SUCCESS;
707#endif /* VBOX_WITH_NETFLT */
708}
709
710UINT __stdcall InstallNetFlt(MSIHANDLE hModule)
711{
712#ifdef VBOX_WITH_NETFLT
713 UINT r;
714 INetCfg *pnc;
715
716 inintWinNetCfgLogger(hModule);
717
718 BOOL bOldIntMode = SetupSetNonInteractiveMode(FALSE);
719
720 __try
721 {
722
723 LogString(hModule, TEXT("Installing NetFlt"));
724
725 r = doNetCfgInit(hModule, &pnc, TRUE);
726 Assert(r == ERROR_SUCCESS);
727 if(r == ERROR_SUCCESS)
728 {
729 WCHAR PtInf[MAX_PATH];
730 WCHAR MpInf[MAX_PATH];
731 DWORD sz = sizeof(PtInf);
732 LPWSTR aInfs[] = {PtInf, MpInf};
733 UINT cInfs = 2;
734
735 r = vboxNetFltQueryInfArray(hModule, aInfs, &cInfs, sz);
736 Assert(r == ERROR_SUCCESS);
737 Assert(cInfs == 2);
738 if(r == ERROR_SUCCESS)
739 {
740 // HRESULT hr = VBoxNetCfgWinInstallSpecifiedComponent (
741 // pnc,
742 // (LPCWSTR*)aInfs,
743 // cInfs,
744 // NETFLT_ID,
745 // &GUID_DEVCLASS_NETSERVICE,
746 // true);
747 HRESULT hr = VBoxNetCfgWinNetFltInstall(pnc, (LPCWSTR*)aInfs, cInfs);
748 Assert(hr == S_OK);
749 if(hr != S_OK)
750 {
751 LogString(hModule, TEXT("InstallNetFlt: VBoxNetCfgWinInstallSpecifiedComponent failed, hr (0x%x)"), hr);
752 }
753
754 r = Hresult2Error(hModule, hr);
755 }
756 else
757 {
758 LogString(hModule, TEXT("InstallNetFlt: vboxNetFltQueryInfArray failed, r (0x%x)"), r);
759 }
760
761 VBoxNetCfgWinReleaseINetCfg(pnc, TRUE);
762
763 /* Never fail the uninstall */
764 r = ERROR_SUCCESS;
765 }
766 else
767 {
768 LogString(hModule, TEXT("InstallNetFlt: doNetCfgInit failed, r (0x%x)"), r);
769 }
770
771 LogString(hModule, TEXT("Installing NetFlt done, r (0x%x)"), r);
772 }
773 __finally
774 {
775 if(bOldIntMode)
776 {
777 /* the prev mode != FALSE, i.e. non-interactive */
778 SetupSetNonInteractiveMode(bOldIntMode);
779 }
780 finiWinNetCfgLogger();
781 }
782
783 return ERROR_SUCCESS;
784#else /* not defined VBOX_WITH_NETFLT */
785 return ERROR_SUCCESS;
786#endif /* VBOX_WITH_NETFLT */
787}
788
789#if 0
790static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
791{
792 WCHAR DevName[256];
793 DWORD winEr;
794
795 if(SetupDiGetDeviceRegistryPropertyW(hDevInfo, pDev,
796 SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
797 NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
798 (PBYTE)DevName, /*OUT PBYTE PropertyBuffer,*/
799 sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
800 NULL /*OUT PDWORD RequiredSize OPTIONAL*/
801 ))
802 {
803 HKEY hKey = SetupDiOpenDevRegKey(hDevInfo, pDev,
804 DICS_FLAG_GLOBAL, /* IN DWORD Scope,*/
805 0, /*IN DWORD HwProfile, */
806 DIREG_DRV, /* IN DWORD KeyType, */
807 KEY_READ /*IN REGSAM samDesired*/
808 );
809 Assert(hKey != INVALID_HANDLE_VALUE);
810 if (hKey != INVALID_HANDLE_VALUE)
811 {
812 WCHAR guid[50];
813 DWORD cbGuid=sizeof(guid);
814 winEr = RegQueryValueExW(hKey,
815 L"NetCfgInstanceId", /*__in_opt LPCTSTR lpValueName,*/
816 NULL, /*__reserved LPDWORD lpReserved,*/
817 NULL, /*__out_opt LPDWORD lpType,*/
818 (LPBYTE)guid, /*__out_opt LPBYTE lpData,*/
819 &cbGuid /*guid__inout_opt LPDWORD lpcbData*/
820 );
821 Assert(winEr == ERROR_SUCCESS);
822 if(winEr == ERROR_SUCCESS)
823 {
824 WCHAR ConnectoinName[128];
825 ULONG cbName = sizeof(ConnectoinName);
826
827 HRESULT hr = VBoxNetCfgWinGenHostonlyConnectionName (DevName, ConnectoinName, &cbName);
828 Assert(hr == S_OK);
829 if(hr == S_OK)
830 {
831 hr = VBoxNetCfgWinRenameConnection (guid, ConnectoinName);
832 Assert(hr == S_OK);
833 }
834 }
835 }
836 RegCloseKey(hKey);
837 }
838 else
839 {
840 Assert(0);
841 }
842
843 return TRUE;
844}
845#endif
846
847UINT __stdcall CreateHostOnlyInterface(MSIHANDLE hModule)
848{
849#ifdef VBOX_WITH_NETFLT
850 inintWinNetCfgLogger(hModule);
851
852 BOOL bPrevMode = SetupSetNonInteractiveMode(FALSE);
853 bool bSetStaticIp = true;
854
855 LogString(hModule, TEXT("Creating Host-Only Interface"));
856
857 HRESULT hr = VBoxNetCfgWinRemoveAllNetDevicesOfId(NETADP_ID);
858 Assert(hr == S_OK);
859 if(hr != S_OK)
860 {
861 LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinRemoveAllNetDevicesOfId failed, hr (0x%x)"), hr);
862 bSetStaticIp = false;
863 }
864
865 GUID guid;
866 WCHAR MpInf[MAX_PATH];
867 DWORD cSize = sizeof(MpInf)/sizeof(MpInf[0]);
868 LPCWSTR pInfPath = NULL;
869 bool bIsFile = false;
870 UINT r = MsiGetPropertyW(hModule, L"CustomActionData", MpInf, &cSize);
871 Assert(r == ERROR_SUCCESS);
872 if(r == ERROR_SUCCESS)
873 {
874 LogString(hModule, TEXT("NetAdpDir property: (%s)"), MpInf);
875 if(cSize)
876 {
877 if(MpInf[cSize-1] != L'\\')
878 {
879 MpInf[cSize] = L'\\';
880 ++cSize;
881 MpInf[cSize] = L'\0';
882 }
883// wcscat(MpInf, L"VBoxNetFlt.inf");
884 wcscat(MpInf, L"drivers\\network\\netadp\\VBoxNetAdp.inf");
885 pInfPath = MpInf;
886 bIsFile = true;
887 LogString(hModule, TEXT("Resulting inf path is: (%s)"), pInfPath);
888 }
889 else
890 {
891 LogString(hModule, TEXT("CreateHostOnlyInterface: NetAdpDir property value is empty"));
892 }
893 }
894 else
895 {
896 LogString(hModule, TEXT("CreateHostOnlyInterface: failed to get NetAdpDir property, r(%d)"), r);
897 }
898
899 /* make sure the inf file is installed */
900 if(!!pInfPath && bIsFile)
901 {
902 HRESULT tmpHr = VBoxDrvCfgInfInstall(pInfPath);
903 Assert(tmpHr == S_OK);
904 }
905
906 hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface (pInfPath, bIsFile, &guid, NULL, NULL);
907 Assert(hr == S_OK);
908 if(hr == S_OK)
909 {
910 ULONG ip = inet_addr("192.168.56.1");
911 ULONG mask = inet_addr("255.255.255.0");
912
913 hr = VBoxNetCfgWinEnableStaticIpConfig(&guid, ip, mask);
914 Assert(hr == S_OK);
915 if(hr != S_OK)
916 {
917 LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, hr (0x%x)"), hr);
918 }
919 }
920 else
921 {
922 LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, hr (0x%x)"), hr);
923 }
924
925 if(bPrevMode)
926 {
927 /* the prev mode != FALSE, i.e. non-interactive */
928 SetupSetNonInteractiveMode(bPrevMode);
929 }
930
931 finiWinNetCfgLogger();
932
933 /* never fail the install even if we are not succeeded */
934 return ERROR_SUCCESS;
935#else /* not defined VBOX_WITH_NETFLT */
936 return ERROR_SUCCESS;
937#endif /* VBOX_WITH_NETFLT */
938}
939
940UINT __stdcall RemoveHostOnlyInterfaces(MSIHANDLE hModule)
941{
942#ifdef VBOX_WITH_NETFLT
943 inintWinNetCfgLogger(hModule);
944
945 LogString(hModule, TEXT("Removing All Host-Only Interface"));
946
947 BOOL bPrevMode = SetupSetNonInteractiveMode(FALSE);
948
949 HRESULT hr = VBoxNetCfgWinRemoveAllNetDevicesOfId(NETADP_ID);
950 if(hr == S_OK)
951 {
952 hr = VBoxDrvCfgInfUninstallAllSetupDi(&GUID_DEVCLASS_NET, NETADP_ID, L"Net", 0/* could be SUOI_FORCEDELETE */);
953 if(hr != S_OK)
954 {
955 LogString(hModule, TEXT("NetAdp uninstalled successfully, but failed to remove infs\n"));
956 }
957 }
958 else
959 {
960 LogString(hModule, TEXT("NetAdp uninstall failed, hr = 0x%x\n"), hr);
961 }
962
963 if(bPrevMode)
964 {
965 /* the prev mode != FALSE, i.e. non-interactive */
966 SetupSetNonInteractiveMode(bPrevMode);
967 }
968
969 finiWinNetCfgLogger();
970
971 return ERROR_SUCCESS;
972#else /* not defined VBOX_WITH_NETFLT */
973 return ERROR_SUCCESS;
974#endif /* VBOX_WITH_NETFLT */
975}
976
977static bool IsTAPDevice (const TCHAR *a_pcGUID)
978{
979 HKEY hNetcard;
980 LONG status;
981 DWORD len;
982 int i = 0;
983 bool ret = false;
984
985 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
986 TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
987 0, KEY_READ, &hNetcard);
988
989 if (status != ERROR_SUCCESS)
990 return false;
991
992 while(true)
993 {
994 TCHAR szEnumName[256];
995 TCHAR szNetCfgInstanceId[256];
996 DWORD dwKeyType;
997 HKEY hNetCardGUID;
998
999 len = sizeof(szEnumName);
1000 status = RegEnumKeyEx (hNetcard, i, szEnumName, &len, NULL, NULL, NULL, NULL);
1001 if (status != ERROR_SUCCESS)
1002 break;
1003
1004 status = RegOpenKeyEx (hNetcard, szEnumName, 0, KEY_READ, &hNetCardGUID);
1005 if (status == ERROR_SUCCESS)
1006 {
1007 len = sizeof (szNetCfgInstanceId);
1008 status = RegQueryValueEx (hNetCardGUID, TEXT("NetCfgInstanceId"), NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
1009 if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
1010 {
1011 TCHAR szNetProductName[256];
1012 TCHAR szNetProviderName[256];
1013
1014 szNetProductName[0] = 0;
1015 len = sizeof(szNetProductName);
1016 status = RegQueryValueEx (hNetCardGUID, TEXT("ProductName"), NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
1017
1018 szNetProviderName[0] = 0;
1019 len = sizeof(szNetProviderName);
1020 status = RegQueryValueEx (hNetCardGUID, TEXT("ProviderName"), NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
1021
1022 if ( !wcscmp(szNetCfgInstanceId, a_pcGUID)
1023 && !wcscmp(szNetProductName, TEXT("VirtualBox TAP Adapter"))
1024 && ( (!wcscmp(szNetProviderName, TEXT("innotek GmbH"))) /* Legacy stuff. */
1025 || (!wcscmp(szNetProviderName, TEXT("Sun Microsystems, Inc."))) /* Legacy stuff. */
1026 || (!wcscmp(szNetProviderName, TEXT(VBOX_VENDOR))) /* Reflects current vendor string. */
1027 )
1028 )
1029 {
1030 ret = true;
1031 RegCloseKey(hNetCardGUID);
1032 break;
1033 }
1034 }
1035 RegCloseKey(hNetCardGUID);
1036 }
1037 ++i;
1038 }
1039
1040 RegCloseKey (hNetcard);
1041 return ret;
1042}
1043
1044#define VBOX_TAP_HWID _T("vboxtap")
1045
1046#define SetErrBreak(strAndArgs) \
1047 if (1) { \
1048 rc = 0; \
1049 LogString (a_hModule, strAndArgs); \
1050 break; \
1051 } else do {} while (0)
1052
1053int removeNetworkInterface (MSIHANDLE a_hModule, const TCHAR* pcGUID)
1054{
1055 int rc = 1;
1056 do
1057 {
1058 TCHAR lszPnPInstanceId [512] = {0};
1059
1060 /* We have to find the device instance ID through a registry search */
1061
1062 HKEY hkeyNetwork = 0;
1063 HKEY hkeyConnection = 0;
1064
1065 do
1066 {
1067 TCHAR strRegLocation [256];
1068 swprintf (strRegLocation,
1069 TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")
1070 TEXT("{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s"),
1071 pcGUID);
1072 LONG status;
1073 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, strRegLocation, 0,
1074 KEY_READ, &hkeyNetwork);
1075 if ((status != ERROR_SUCCESS) || !hkeyNetwork)
1076 SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [1]"), strRegLocation));
1077
1078 status = RegOpenKeyExA (hkeyNetwork, "Connection", 0,
1079 KEY_READ, &hkeyConnection);
1080 if ((status != ERROR_SUCCESS) || !hkeyConnection)
1081 SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [2]"), strRegLocation));
1082
1083 DWORD len = sizeof (lszPnPInstanceId);
1084 DWORD dwKeyType;
1085 status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
1086 &dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
1087 if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
1088 SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [3]"), strRegLocation));
1089 }
1090 while (0);
1091
1092 if (hkeyConnection)
1093 RegCloseKey (hkeyConnection);
1094 if (hkeyNetwork)
1095 RegCloseKey (hkeyNetwork);
1096
1097 /*
1098 * Now we are going to enumerate all network devices and
1099 * wait until we encounter the right device instance ID
1100 */
1101
1102 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
1103
1104 do
1105 {
1106 BOOL ok;
1107 DWORD ret = 0;
1108 GUID netGuid;
1109 SP_DEVINFO_DATA DeviceInfoData;
1110 DWORD index = 0;
1111 BOOL found = FALSE;
1112 DWORD size = 0;
1113
1114 /* initialize the structure size */
1115 DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
1116
1117 /* copy the net class GUID */
1118 memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
1119
1120 /* return a device info set contains all installed devices of the Net class */
1121 hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
1122
1123 if (hDeviceInfo == INVALID_HANDLE_VALUE)
1124 {
1125 LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiGetClassDevs failed (0x%08X)!"), GetLastError());
1126 SetErrBreak (TEXT("VBox HostInterfaces: Uninstallation failed!"));
1127 }
1128
1129 /* enumerate the driver info list */
1130 while (TRUE)
1131 {
1132 TCHAR *deviceHwid;
1133
1134 ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
1135
1136 if (!ok)
1137 {
1138 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1139 break;
1140 else
1141 {
1142 index++;
1143 continue;
1144 }
1145 }
1146
1147 /* try to get the hardware ID registry property */
1148 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1149 &DeviceInfoData,
1150 SPDRP_HARDWAREID,
1151 NULL,
1152 NULL,
1153 0,
1154 &size);
1155 if (!ok)
1156 {
1157 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1158 {
1159 index++;
1160 continue;
1161 }
1162
1163 deviceHwid = (TCHAR *) malloc (size);
1164 ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
1165 &DeviceInfoData,
1166 SPDRP_HARDWAREID,
1167 NULL,
1168 (PBYTE)deviceHwid,
1169 size,
1170 NULL);
1171 if (!ok)
1172 {
1173 free (deviceHwid);
1174 deviceHwid = NULL;
1175 index++;
1176 continue;
1177 }
1178 }
1179 else
1180 {
1181 /* something is wrong. This shouldn't have worked with a NULL buffer */
1182 index++;
1183 continue;
1184 }
1185
1186 for (TCHAR *t = deviceHwid;
1187 t && *t && t < &deviceHwid[size / sizeof(TCHAR)];
1188 t += _tcslen (t) + 1)
1189 {
1190 if (!_tcsicmp (VBOX_TAP_HWID, t))
1191 {
1192 /* get the device instance ID */
1193 TCHAR devID [MAX_DEVICE_ID_LEN];
1194 if (CM_Get_Device_ID(DeviceInfoData.DevInst,
1195 devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
1196 {
1197 /* compare to what we determined before */
1198 if (wcscmp(devID, lszPnPInstanceId) == 0)
1199 {
1200 found = TRUE;
1201 break;
1202 }
1203 }
1204 }
1205 }
1206
1207 if (deviceHwid)
1208 {
1209 free (deviceHwid);
1210 deviceHwid = NULL;
1211 }
1212
1213 if (found)
1214 break;
1215
1216 index++;
1217 }
1218
1219 if (found == FALSE)
1220 SetErrBreak (TEXT("VBox HostInterfaces: Host Interface Network driver not found!"));
1221
1222 ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
1223 if (!ok)
1224 {
1225 LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiSetSelectedDevice failed (0x%08X)!"), GetLastError());
1226 SetErrBreak (TEXT("VBox HostInterfaces: Uninstallation failed!"));
1227 }
1228
1229 ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
1230 if (!ok)
1231 {
1232 LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)!"), GetLastError());
1233 SetErrBreak (TEXT("VBox HostInterfaces: Uninstallation failed!"));
1234 }
1235 }
1236 while (0);
1237
1238 /* clean up the device info set */
1239 if (hDeviceInfo != INVALID_HANDLE_VALUE)
1240 SetupDiDestroyDeviceInfoList (hDeviceInfo);
1241 }
1242 while (0);
1243 return rc;
1244}
1245
1246UINT __stdcall UninstallTAPInstances (MSIHANDLE a_hModule)
1247{
1248 static const TCHAR *NetworkKey = TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")
1249 TEXT("{4D36E972-E325-11CE-BFC1-08002BE10318}");
1250 HKEY hCtrlNet;
1251 LONG status = 0;
1252 DWORD len = 0;
1253 LONG cnt = 0;
1254
1255 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, NetworkKey, 0, KEY_READ, &hCtrlNet);
1256 if (status == ERROR_SUCCESS)
1257 {
1258 LogString(a_hModule, TEXT("VBox HostInterfaces: Enumerating interfaces ..."));
1259 for (int i = 0;; ++ i)
1260 {
1261 TCHAR szNetworkGUID [256] = { 0 };
1262 TCHAR szNetworkConnection [256] = { 0 };
1263
1264 len = sizeof (szNetworkGUID);
1265 status = RegEnumKeyEx (hCtrlNet, i, szNetworkGUID, &len, NULL, NULL, NULL, NULL);
1266 if (status != ERROR_SUCCESS)
1267 {
1268 switch (status)
1269 {
1270 case ERROR_NO_MORE_ITEMS:
1271 LogString(a_hModule, TEXT("VBox HostInterfaces: No interfaces found."));
1272 break;
1273 default:
1274 LogString(a_hModule, TEXT("VBox HostInterfaces: Enumeration failed: %ld"), status);
1275 break;
1276 };
1277 break;
1278 }
1279
1280 if (IsTAPDevice(szNetworkGUID))
1281 {
1282 LogString(a_hModule, TEXT("VBox HostInterfaces: Removing interface \"%s\" ..."), szNetworkGUID);
1283 removeNetworkInterface (a_hModule, szNetworkGUID);
1284 status = RegDeleteKey (hCtrlNet, szNetworkGUID);
1285 }
1286 }
1287 RegCloseKey (hCtrlNet);
1288 LogString(a_hModule, TEXT("VBox HostInterfaces: Removing interfaces done."));
1289 }
1290 return ERROR_SUCCESS;
1291}
1292
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