3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* $Id$ */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** @file
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * NetFltInstall - VBoxNetFlt installer command line tool
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2011 Oracle Corporation
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync *
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * available from http://www.virtualbox.org. This file is free software;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * General Public License (GPL) as published by the Free Software
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#include <VBox/VBoxNetCfg-win.h>
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#include <devguid.h>
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#include <stdio.h>
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define NETFLT_ID L"sun_VBoxNetFlt"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define VBOX_NETCFG_APP_NAME L"NetFltInstall"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define VBOX_NETFLT_PT_INF L".\\VBoxNetFlt.inf"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define VBOX_NETFLT_MP_INF L".\\VBoxNetFltM.inf"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define VBOX_NETFLT_RETRIES 10
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID winNetCfgLogger (LPCSTR szString)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync{
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync printf("%s", szString);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync}
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** Wrapper around GetfullPathNameW that will try an alternative INF location.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync *
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * The default location is the current directory. If not found there, the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * alternative location is the executable directory. If not found there either,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the first alternative is present to the caller.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic DWORD MyGetfullPathNameW(LPCWSTR pwszName, size_t cchFull, LPWSTR pwszFull)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync{
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LPWSTR pwszFilePart;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync DWORD dwSize = GetFullPathNameW(pwszName, (DWORD)cchFull, pwszFull, &pwszFilePart);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(dwSize <= 0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return dwSize;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* if it doesn't exist, see if the file exists in the same directory as the executable. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (GetFileAttributesW(pwszFull) == INVALID_FILE_ATTRIBUTES)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync WCHAR wsz[512];
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync DWORD cch = GetModuleFileNameW(GetModuleHandle(NULL), &wsz[0], sizeof(wsz) / sizeof(wsz[0]));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(cch > 0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync while(cch > 0 && wsz[cch - 1] != '/' && wsz[cch - 1] != '\\' && wsz[cch - 1] != ':')
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync cch--;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync unsigned i = 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync while(cch < sizeof(wsz) / sizeof(wsz[0]))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wsz[cch] = pwszFilePart[i++];
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(!wsz[cch])
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync dwSize = GetFullPathNameW(wsz, (DWORD)cchFull, pwszFull, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(dwSize > 0 && GetFileAttributesW(pwszFull) != INVALID_FILE_ATTRIBUTES)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return dwSize;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync break;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync cch++;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* fallback */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return GetFullPathNameW(pwszName, (DWORD)cchFull, pwszFull, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync}
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int VBoxNetFltInstall()
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync{
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync WCHAR PtInf[MAX_PATH];
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync WCHAR MpInf[MAX_PATH];
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync INetCfg *pnc;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LPWSTR lpszLockedBy = NULL;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync int r = 1;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync VBoxNetCfgWinSetLogging(winNetCfgLogger);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync HRESULT hr = CoInitialize(NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(hr == S_OK)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync int i = 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync do
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync hr = VBoxNetCfgWinQueryINetCfg(&pnc, TRUE, VBOX_NETCFG_APP_NAME, 10000, &lpszLockedBy);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(hr == S_OK)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync DWORD dwSize;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync dwSize = MyGetfullPathNameW(VBOX_NETFLT_PT_INF, sizeof(PtInf)/sizeof(PtInf[0]), PtInf);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(dwSize > 0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** @todo add size check for (sizeof(PtInf)/sizeof(PtInf[0])) == dwSize (string length in sizeof(PtInf[0])) */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync dwSize = MyGetfullPathNameW(VBOX_NETFLT_MP_INF, sizeof(MpInf)/sizeof(MpInf[0]), MpInf);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(dwSize > 0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** @todo add size check for (sizeof(MpInf)/sizeof(MpInf[0])) == dwSize (string length in sizeof(MpInf[0])) */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LPCWSTR aInfs[] = {PtInf, MpInf};
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync hr = VBoxNetCfgWinNetFltInstall(pnc, aInfs, 2);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(hr == S_OK)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"installed successfully\n");
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync r = 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"error installing VBoxNetFlt (0x%x)\n", hr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync hr = HRESULT_FROM_WIN32(GetLastError());
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"error getting full inf path for VBoxNetFltM.inf (0x%x)\n", hr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync hr = HRESULT_FROM_WIN32(GetLastError());
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"error getting full inf path for VBoxNetFlt.inf (0x%x)\n", hr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync VBoxNetCfgWinReleaseINetCfg(pnc, TRUE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync break;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else if(hr == NETCFG_E_NO_WRITE_LOCK && lpszLockedBy)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if(i < VBOX_NETFLT_RETRIES && !wcscmp(lpszLockedBy, L"6to4svc.dll"))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"6to4svc.dll is holding the lock, retrying %d out of %d\n", ++i, VBOX_NETFLT_RETRIES);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync CoTaskMemFree(lpszLockedBy);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"Error: write lock is owned by another application (%s), close the application and retry installing\n", lpszLockedBy);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync r = 1;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync CoTaskMemFree(lpszLockedBy);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync break;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"Error getting the INetCfg interface (0x%x)\n", hr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync r = 1;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync break;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while(true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync CoUninitialize();
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync else
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync wprintf(L"Error initializing COM (0x%x)\n", hr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync r = 1;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync VBoxNetCfgWinSetLogging(NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return r;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync}
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint __cdecl main(int argc, char **argv)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync{
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return VBoxNetFltInstall();
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync}