VirtualBox

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

Last change on this file since 34684 was 34547, checked in by vboxsync, 14 years ago

Windows installer: fixed misinterpretation of the sizeOfBuffer parameter of _stprintf_s => swprintf_s

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