VBoxInstallHelper.cpp revision be6a7ee8f237a71cf075c128e8e391e6c3654687
/* $Id$ */
/** @file
* VBoxInstallHelper - Various helper routines for Windows host installer.
*/
/*
* Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifdef VBOX_WITH_NETFLT
# include "VBox/VBoxNetCfg-win.h"
#endif /* VBOX_WITH_NETFLT */
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <msi.h>
#include <msiquery.h>
#define _WIN32_DCOM
#include <windows.h>
#include <assert.h>
#include <shellapi.h>
#define INITGUID
#include <guiddef.h>
#include <devguid.h>
#include <objbase.h>
#include <setupapi.h>
#include <shlobj.h>
#include <cfgmgr32.h>
#include "VBoxCommon.h"
#ifndef VBOX_OSE
# include "internal/VBoxSerial.h"
#endif
#ifdef DEBUG
#else
#endif
{
return TRUE;
}
{
#ifdef DEBUG
#endif
}
{
}
{
#ifndef VBOX_OSE
#endif
return ERROR_SUCCESS;
}
{
#ifndef VBOX_OSE
#endif
return ERROR_SUCCESS;
}
DWORD Exec(MSIHANDLE hModule, TCHAR* szAppName, TCHAR* szCmdLine, TCHAR* szWorkDir, DWORD* dwExitCode)
{
#ifdef UNICODE
#endif
LogString(hModule, TEXT("Executing command line: %s %s (Working Dir: %s)"), szAppName, szCmdLine, szWorkDir == NULL ? L"Current" : szWorkDir);
::SetLastError(0);
szCmdLine, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
FALSE, /* Set handle inheritance to FALSE .*/
0, /* No creation flags. */
NULL, /* Use parent's environment block. */
szWorkDir, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi)) /* Pointer to PROCESS_INFORMATION structure. */
{
rc = ::GetLastError();
return rc;
}
/* Wait until child process exits. */
{
rc = ::GetLastError();
}
else
{
{
rc = ::GetLastError();
}
}
/* Close process and thread handles. */
return rc;
}
{
LONG rc = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Python\\PythonCore", 0, KEY_READ, &hkPythonCore);
if (rc != ERROR_SUCCESS)
{
return ERROR_SUCCESS;
}
for (int i = 0;; ++i)
{
break;
if (rc != ERROR_SUCCESS)
continue;
if(rc == ERROR_SUCCESS)
}
::RegCloseKey (hkPythonCore);
/* Python path found? */
DWORD dwExitCode = 0;
{
/* Cool, check for installed Win32 extensions. */
_stprintf_s(szCmdLine, sizeof(szCmdLine) / sizeof(TCHAR), L"%s\\python.exe -c \"import win32api\"", szVal);
&& (0 == dwExitCode))
{
/* Did we get the correct error level (=0)? */
bInstalled = TRUE;
}
}
if (bInstalled) /* Is Python and all required stuff installed? */
{
/* Get the VBoxAPI setup string. */
/* Set final path. */
/* Install our API module. */
_stprintf_s(szCmdLine, sizeof(szCmdLine) / sizeof(TCHAR), L"%s\\python.exe vboxapisetup.py install", szVal);
/* Set required environment variables. */
{
return FALSE;
}
else
{
&& (0 == dwExitCode))
{
/* All done! */
return ERROR_SUCCESS;
}
}
}
return ERROR_SUCCESS; /* Do not fail here. */
}
const TCHAR* pszFileName,
const TCHAR* pszSection,
{
{
_stprintf_s(szKey, sizeof(szKey) / sizeof(TCHAR), L"SOFTWARE\\%s\\VirtualBox\\Branding\\", VBOX_VENDOR_SHORT, pszSection);
else
_stprintf_s(szKey, sizeof(szKey) / sizeof(TCHAR), L"SOFTWARE\\%s\\VirtualBox\\Branding", VBOX_VENDOR_SHORT);
0, KEY_WRITE, &hkBranding);
if (rc == ERROR_SUCCESS)
{
NULL,
if (rc != ERROR_SUCCESS)
}
}
else
return rc;
}
{
SHFILEOPSTRUCT s = {0};
s.fFlags = FOF_SILENT |
int r = SHFileOperation(&s);
if (r != 0)
{
}
else
rc = ERROR_SUCCESS;
return rc;
}
{
SHFILEOPSTRUCT s = {0};
s.fFlags = FOF_SILENT |
int r = SHFileOperation(&s);
if (r != 0)
{
}
else
rc = ERROR_SUCCESS;
return rc;
}
{
SHFILEOPSTRUCT s = {0};
s.fFlags = FOF_SILENT |
int r = SHFileOperation(&s);
if (r != 0)
{
}
else
rc = ERROR_SUCCESS;
return rc;
}
{
if (rc == ERROR_SUCCESS)
{
/** @todo Check trailing slash after %s. */
if (rc != ERROR_SUCCESS)
{
/* Check for hidden .custom directory and remove it. */
}
}
return ERROR_SUCCESS; /* Do not fail here. */
}
{
if (rc == ERROR_SUCCESS)
{
/** @todo Check for trailing slash after %s. */
if (rc == ERROR_SUCCESS)
{
}
}
return ERROR_SUCCESS; /* Do not fail here. */
}
#ifdef VBOX_WITH_NETFLT
/** @todo should use some real VBox app name */
#define VBOX_NETCFG_APP_NAME L"VirtualBox Installer"
#define VBOX_NETCFG_MAX_RETRIES 10
#define NETFLT_PT_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFlt.inf"
#define NETFLT_MP_INF_REL_PATH L"drivers\\network\\netflt\\VBoxNetFltM.inf"
{
if(g_hCurrentModule)
{
}
}
{
}
static VOID finiWinNetCfgLogger()
{
}
{
switch(hr)
{
case S_OK:
return ERROR_SUCCESS;
case NETCFG_S_REBOOT:
{
return ERROR_GEN_FAILURE;
}
return ERROR_SUCCESS;
default:
return ERROR_GEN_FAILURE;
}
}
{
if(hRecord)
{
do
{
Assert(r == ERROR_SUCCESS);
if(r != ERROR_SUCCESS)
{
break;
}
}while(0);
}
else
{
}
return hRecord;
}
{
UINT r = ERROR_GEN_FAILURE;
int MsgResult;
int cRetries = 0;
do
{
if(hr != NETCFG_E_NO_WRITE_LOCK)
{
{
}
break;
}
/* hr == NETCFG_E_NO_WRITE_LOCK */
if(!lpszLockedBy)
{
break;
}
/* on vista the 6to4svc.dll periodically maintains the lock for some reason,
* if this is the case, increase the wait period by retrying multiple times
* NOTE: we could alternatively increase the wait timeout,
* however it seems unneeded for most cases, e.g. in case some network connection property
* dialog is opened, it would be better to post a notification to the user as soon as possible
* rather than waiting for a longer period of time before displaying it */
{
cRetries++;
LogString(hModule, TEXT("doNetCfgInit: lpszLockedBy is 6to4svc.dll, retrying %d out of %d"), cRetries, VBOX_NETCFG_MAX_RETRIES);
}
else
{
if(!hMsg)
{
if(!hMsg)
{
break;
}
}
if(rTmp != ERROR_SUCCESS)
{
break;
}
MsgResult = MsiProcessMessage(hModule, (INSTALLMESSAGE)(INSTALLMESSAGE_USER | MB_RETRYCANCEL), hMsg);
}
if(hMsg)
{
}
return r;
}
static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR *apInfFullPaths, PUINT pcInfs, DWORD cSize)
{
UINT r;
if(*pcInfs >= 2)
{
*pcInfs = 2;
Assert(r == ERROR_SUCCESS);
if(r == ERROR_SUCCESS)
{
}
else
{
}
}
else
{
r = ERROR_GEN_FAILURE;
*pcInfs = 2;
}
return r;
}
#endif /*VBOX_WITH_NETFLT*/
{
#ifdef VBOX_WITH_NETFLT
UINT r;
{
Assert(r == ERROR_SUCCESS);
if(r == ERROR_SUCCESS)
{
{
}
/* Never fail the uninstall */
r = ERROR_SUCCESS;
}
else
{
}
}
{
if(bOldIntMode)
{
/* the prev mode != FALSE, i.e. non-interactive */
}
}
return ERROR_SUCCESS;
#else /* not defined VBOX_WITH_NETFLT */
return ERROR_SUCCESS;
#endif /* VBOX_WITH_NETFLT */
}
{
#ifdef VBOX_WITH_NETFLT
UINT r;
{
Assert(r == ERROR_SUCCESS);
if(r == ERROR_SUCCESS)
{
Assert(r == ERROR_SUCCESS);
if(r == ERROR_SUCCESS)
{
// HRESULT hr = VBoxNetCfgWinInstallSpecifiedComponent (
// pnc,
// (LPCWSTR*)aInfs,
// cInfs,
// NETFLT_ID,
// &GUID_DEVCLASS_NETSERVICE,
// true);
{
LogString(hModule, TEXT("InstallNetFlt: VBoxNetCfgWinInstallSpecifiedComponent failed, hr (0x%x)"), hr);
}
}
else
{
}
/* Never fail the uninstall */
r = ERROR_SUCCESS;
}
else
{
}
}
{
if(bOldIntMode)
{
/* the prev mode != FALSE, i.e. non-interactive */
}
}
return ERROR_SUCCESS;
#else /* not defined VBOX_WITH_NETFLT */
return ERROR_SUCCESS;
#endif /* VBOX_WITH_NETFLT */
}
#if 0
static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext)
{
SPDRP_FRIENDLYNAME , /* IN DWORD Property,*/
NULL, /*OUT PDWORD PropertyRegDataType, OPTIONAL*/
sizeof(DevName), /* IN DWORD PropertyBufferSize,*/
NULL /*OUT PDWORD RequiredSize OPTIONAL*/
))
{
DICS_FLAG_GLOBAL, /* IN DWORD Scope,*/
0, /*IN DWORD HwProfile, */
DIREG_DRV, /* IN DWORD KeyType, */
KEY_READ /*IN REGSAM samDesired*/
);
if (hKey != INVALID_HANDLE_VALUE)
{
L"NetCfgInstanceId", /*__in_opt LPCTSTR lpValueName,*/
NULL, /*__reserved LPDWORD lpReserved,*/
NULL, /*__out_opt LPDWORD lpType,*/
&cbGuid /*guid__inout_opt LPDWORD lpcbData*/
);
if(winEr == ERROR_SUCCESS)
{
{
}
}
}
}
else
{
Assert(0);
}
return TRUE;
}
#endif
{
#ifdef VBOX_WITH_NETFLT
bool bSetStaticIp = true;
{
LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinRemoveAllNetDevicesOfId failed, hr (0x%x)"), hr);
bSetStaticIp = false;
}
bool bIsFile = false;
Assert(r == ERROR_SUCCESS);
if(r == ERROR_SUCCESS)
{
if(cSize)
{
{
++cSize;
}
// wcscat(MpInf, L"VBoxNetFlt.inf");
bIsFile = true;
}
else
{
}
}
else
{
}
/* make sure the inf file is installed */
{
}
{
{
LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, hr (0x%x)"), hr);
}
}
else
{
LogString(hModule, TEXT("CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, hr (0x%x)"), hr);
}
if(bPrevMode)
{
/* the prev mode != FALSE, i.e. non-interactive */
}
/* never fail the install even if we are not succeeded */
return ERROR_SUCCESS;
#else /* not defined VBOX_WITH_NETFLT */
return ERROR_SUCCESS;
#endif /* VBOX_WITH_NETFLT */
}
{
#ifdef VBOX_WITH_NETFLT
{
hr = VBoxNetCfgWinInfUninstallAll(&GUID_DEVCLASS_NET, NETADP_ID, L"Net", 0/* could be SUOI_FORCEDELETE */);
{
}
}
else
{
}
if(bPrevMode)
{
/* the prev mode != FALSE, i.e. non-interactive */
}
return ERROR_SUCCESS;
#else /* not defined VBOX_WITH_NETFLT */
return ERROR_SUCCESS;
#endif /* VBOX_WITH_NETFLT */
}
{
int i = 0;
bool ret = false;
TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
if (status != ERROR_SUCCESS)
return false;
while(true)
{
len = sizeof(szEnumName);
if (status != ERROR_SUCCESS)
break;
if (status == ERROR_SUCCESS)
{
len = sizeof (szNetCfgInstanceId);
status = RegQueryValueEx (hNetCardGUID, TEXT("NetCfgInstanceId"), NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
{
szNetProductName[0] = 0;
len = sizeof(szNetProductName);
status = RegQueryValueEx (hNetCardGUID, TEXT("ProductName"), NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
szNetProviderName[0] = 0;
len = sizeof(szNetProviderName);
status = RegQueryValueEx (hNetCardGUID, TEXT("ProviderName"), NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
)
)
{
ret = true;
break;
}
}
}
++i;
}
return ret;
}
#define SetErrBreak(strAndArgs) \
if (1) { \
rc = 0; \
break; \
} else do {} while (0)
{
int rc = 1;
do
{
/* We have to find the device instance ID through a registry search */
HKEY hkeyNetwork = 0;
HKEY hkeyConnection = 0;
do
{
TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")
TEXT("{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s"),
pcGUID);
KEY_READ, &hkeyNetwork);
SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [1]"), strRegLocation));
SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [2]"), strRegLocation));
SetErrBreak ((TEXT("VBox HostInterfaces: Host interface network was not found in registry (%s)! [3]"), strRegLocation));
}
while (0);
if (hkeyConnection)
if (hkeyNetwork)
/*
* Now we are going to enumerate all network devices and
* wait until we encounter the right device instance ID
*/
do
{
/* initialize the structure size */
/* copy the net class GUID */
/* return a device info set contains all installed devices of the Net class */
if (hDeviceInfo == INVALID_HANDLE_VALUE)
{
LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiGetClassDevs failed (0x%08X)!"), GetLastError());
}
/* enumerate the driver info list */
while (TRUE)
{
if (!ok)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
break;
else
{
index++;
continue;
}
}
/* try to get the hardware ID registry property */
NULL,
NULL,
0,
&size);
if (!ok)
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
index++;
continue;
}
NULL,
size,
NULL);
if (!ok)
{
free (deviceHwid);
deviceHwid = NULL;
index++;
continue;
}
}
else
{
/* something is wrong. This shouldn't have worked with a NULL buffer */
index++;
continue;
}
for (TCHAR *t = deviceHwid;
t += _tcslen (t) + 1)
{
if (!_tcsicmp (VBOX_TAP_HWID, t))
{
/* get the device instance ID */
{
/* compare to what we determined before */
{
break;
}
}
}
}
if (deviceHwid)
{
free (deviceHwid);
deviceHwid = NULL;
}
if (found)
break;
index++;
}
if (!ok)
{
LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiSetSelectedDevice failed (0x%08X)!"), GetLastError());
}
if (!ok)
{
LogString (a_hModule, TEXT("VBox HostInterfaces: SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)!"), GetLastError());
}
}
while (0);
/* clean up the device info set */
if (hDeviceInfo != INVALID_HANDLE_VALUE)
}
while (0);
return rc;
}
{
TEXT("{4D36E972-E325-11CE-BFC1-08002BE10318}");
if (status == ERROR_SUCCESS)
{
for (int i = 0;; ++ i)
{
len = sizeof (szNetworkGUID);
if (status != ERROR_SUCCESS)
{
switch (status)
{
case ERROR_NO_MORE_ITEMS:
break;
default:
break;
};
break;
}
if (IsTAPDevice(szNetworkGUID))
{
}
}
}
return ERROR_SUCCESS;
}