VirtualBox

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

Last change on this file since 38465 was 37765, checked in by vboxsync, 14 years ago

Windows host installer: Fixed automated VBox Python API installation.

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