VirtualBox

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

Last change on this file since 37515 was 37289, checked in by vboxsync, 14 years ago

Windows host installaer/VBoxNetCfg: Major overhaul for supporting Windows Installer XML 3.5, fixed VBoxInstallHelper logging, coding style, added missing installer icons.

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