NetIf-win.cpp revision 01ec18b1f9e7637bee5cf993d0622ac9e8011d9b
/* $Id$ */
/** @file
* Main - NetIfList, Windows implementation.
*/
/*
* Copyright (C) 2008-2012 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_MAIN
#include <list>
#define _WIN32_DCOM
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#ifdef VBOX_WITH_NETFLT
# include "VBox/VBoxNetCfg-win.h"
# include "devguid.h"
#endif
#include <iphlpapi.h>
#include "Logging.h"
#include "HostNetworkInterfaceImpl.h"
#include "ProgressImpl.h"
#include "VirtualBoxImpl.h"
#include "netif.h"
#ifdef VBOX_WITH_NETFLT
#include <Wbemidl.h>
#include <comdef.h>
#include "svchlp.h"
#include <shellapi.h>
#define INITGUID
#include <guiddef.h>
#include <devguid.h>
#include <objbase.h>
#include <setupapi.h>
#include <shlobj.h>
#include <cfgmgr32.h>
#define VBOX_APP_NAME L"VirtualBox"
static int getDefaultInterfaceIndex()
{
int iIndex = -1;
{
if (!pIpTable)
return -1;
}
{
for (unsigned int i = 0; i < pIpTable->dwNumEntries; i++)
{
break;
}
}
return iIndex;
}
{
int rc = VINF_SUCCESS;
/*
* Most of the hosts probably have less than 10 adapters,
* so we'll mostly succeed from the first attempt.
*/
if (!pAddresses)
return VERR_NO_MEMORY;
if (dwRc == ERROR_BUFFER_OVERFLOW)
{
/* Impressive! More than 10 adapters! Get more memory and try again. */
if (!pAddresses)
return VERR_NO_MEMORY;
}
{
{
{
{
bool fIPFound, fIPv6Found;
fIPFound = fIPv6Found = false;
{
{
case AF_INET:
if (!fIPFound)
{
fIPFound = true;
}
break;
case AF_INET6:
if (!fIPv6Found)
{
fIPv6Found = true;
sizeof(pInfo->IPv6Address));
}
break;
}
}
fIPFound = fIPv6Found = false;
{
{
case AF_INET:
if (!fIPFound)
{
{
fIPFound = true;
}
else
Log(("collectNetIfInfo: Unexpected IPv4 prefix length of %d\n",
pPrefix->PrefixLength));
}
break;
case AF_INET6:
if (!fIPv6Found)
{
{
fIPv6Found = true;
}
else
Log(("collectNetIfInfo: Unexpected IPv6 prefix length of %d\n",
pPrefix->PrefixLength));
}
break;
}
}
Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
else
break;
}
}
}
{
{
}
}
else
{
pInfo->bDhcpEnabled = false;
}
}
return VINF_SUCCESS;
}
/* svc helper func */
struct StaticIpConfig
{
};
struct StaticIpV6Config
{
};
{
/* for SVCHlpMsg::CreateHostOnlyNetworkInterface */
/* for SVCHlpMsg::RemoveHostOnlyNetworkInterface */
union
{
} u;
};
{
LogFlowFunc(("aClient={%p}, aProgress={%p}, aUser={%p}\n",
d(static_cast<NetworkInterfaceHelperClientData *>(aUser));
{
/* "cleanup only" mode, just return (it will free aUser) */
return S_OK;
}
int vrc = VINF_SUCCESS;
switch (d->msgCode)
{
{
LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
// vrc = aClient->write(Utf8Str(d->name));
// if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* read the GUID */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* initialize the object returned to the caller by
* CreateHostOnlyNetworkInterface() */
{
{
}
}
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
{
LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
{
LogFlowFunc(("EnableDynamicIpConfig:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
{
LogFlowFunc(("EnableStaticIpConfig:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
{
LogFlowFunc(("EnableStaticIpConfigV6:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
{
LogFlowFunc(("DhcpRediscover:\n"));
/* write message and parameters */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE(vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE(vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
//"Invalid message code %d (%08lX)\n",
//reply, reply),
//rc = E_FAIL);
}
}
}
break;
}
default:
// "Invalid message code %d (%08lX)\n",
// d->msgCode, d->msgCode),
// rc = E_FAIL);
}
if (aVrc)
return rc;
}
{
int vrc = VINF_SUCCESS;
switch (aMsgCode)
{
{
LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
// Utf8Str name;
// vrc = aClient->read(name);
// if (RT_FAILURE(vrc)) break;
hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), name.asOutParam(), bstrErr.asOutParam());
{
{
/* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip,
* i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */
}
/* write success followed by GUID */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
{
LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
if (RT_FAILURE(vrc)) break;
{
/* write parameter-less success */
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
case SVCHlpMsg::EnableStaticIpConfigV6:
{
LogFlowFunc(("EnableStaticIpConfigV6:\n"));
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_SUCCESS(vrc))
{
/* write success followed by GUID */
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
case SVCHlpMsg::EnableStaticIpConfig:
{
LogFlowFunc(("EnableStaticIpConfig:\n"));
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
{
/* write success followed by GUID */
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
case SVCHlpMsg::EnableDynamicIpConfig:
{
LogFlowFunc(("EnableDynamicIpConfig:\n"));
if (RT_FAILURE(vrc)) break;
{
/* write success followed by GUID */
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
case SVCHlpMsg::DhcpRediscover:
{
LogFlowFunc(("DhcpRediscover:\n"));
if (RT_FAILURE(vrc)) break;
{
/* write success followed by GUID */
if (RT_FAILURE(vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE(vrc)) break;
if (RT_FAILURE(vrc)) break;
}
break;
}
default:
}
return vrc;
}
/** @todo REMOVE. OBSOLETE NOW. */
/**
* Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
* later OSes) and it has the UAC (User Account Control) feature enabled.
*/
static BOOL IsUACEnabled()
{
LogFlowFunc(("dwMajorVersion=%d, dwMinorVersion=%d\n",
/* we are interested only in Vista (and newer versions...). In all
* earlier versions UAC is not present. */
return FALSE;
/* the default EnableLUA value is 1 (Enabled) */
"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
0, KEY_QUERY_VALUE, &hKey);
if (rc == ERROR_SUCCESS)
{
}
return dwEnableLUA == 1;
}
/* end */
int iDefaultInterface)
{
int rc = VERR_GENERAL_FAILURE;
{
{
if (RT_FAILURE(rc))
{
}
/* create a new object and add it to the list */
/* remove the curly bracket at the end */
{
if (Info.bIsDefault)
else
rc = VINF_SUCCESS;
}
else
{
Assert(0);
}
}
}
return rc;
}
#endif /* VBOX_WITH_NETFLT */
{
#ifndef VBOX_WITH_NETFLT
/* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
return VERR_NOT_IMPLEMENTED;
#else /* # if defined VBOX_WITH_NETFLT */
/* we are using the INetCfg API for getting the list of miniports */
10000,
&lpszApp);
{
{
{
{
if (uComponentStatus == 0)
{
{
{
}
}
}
}
}
}
else
{
}
}
else if (lpszApp)
{
}
#endif /* # if defined VBOX_WITH_NETFLT */
return VINF_SUCCESS;
}
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
{
{
}
}
return VERR_GENERAL_FAILURE;
#endif
}
{
return VERR_NOT_IMPLEMENTED;
}
/**
* Obtain the current state of the interface.
*
* @returns VBox status code.
*
* @param pcszIfName Interface name.
* @param penmState Where to store the retrieved state.
*/
{
return VERR_NOT_IMPLEMENTED;
}
/**
* Retrieve the physical link speed in megabits per second. If the interface is
* not up or otherwise unavailable the zero speed is returned.
*
* @returns VBox status code.
*
* @param pcszIfName Interface name.
* @param puMbits Where to store the link speed.
*/
{
return VERR_NOT_IMPLEMENTED;
}
const char *pcszName)
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
/* create a progress object */
{
FALSE /* aCancelable */);
{
/* create a new uninitialized host interface object */
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
// d->name = aName;
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
#endif
}
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
/* create a progress object */
{
FALSE /* aCancelable */);
{
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
#endif
}
int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask)
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
{
// ComPtr<VirtualBox> vBox;
// rc = pIf->getVirtualBox(vBox.asOutParam());
// if (SUCCEEDED(rc))
{
/* create a progress object */
// ComPtr<IHost> host;
// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
// if (SUCCEEDED(rc))
{
FALSE /* aCancelable */);
{
// progress.queryInterfaceTo(aProgress);
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
}
}
#endif
}
int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
{
// ComPtr<VirtualBox> vBox;
// rc = pIf->getVirtualBox(vBox.asOutParam());
// if (SUCCEEDED(rc))
{
/* create a progress object */
// ComPtr<IHost> host;
// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
// if (SUCCEEDED(rc))
{
FALSE /* aCancelable */);
{
// progress.queryInterfaceTo(aProgress);
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
}
}
#endif
}
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
{
// ComPtr<VirtualBox> vBox;
// rc = pIf->getVirtualBox(vBox.asOutParam());
// if (SUCCEEDED(rc))
{
/* create a progress object */
// ComPtr<IHost> host;
// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
// if (SUCCEEDED(rc))
{
FALSE /* aCancelable */);
{
// progress.queryInterfaceTo(aProgress);
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
}
}
#endif
}
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else
{
// ComPtr<VirtualBox> vBox;
// rc = pIf->getVirtualBox(vBox.asOutParam());
// if (SUCCEEDED(rc))
{
/* create a progress object */
// ComPtr<IHost> host;
// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
// if (SUCCEEDED(rc))
{
FALSE /* aCancelable */);
{
// progress.queryInterfaceTo(aProgress);
/* create the networkInterfaceHelperClient() argument */
d(new NetworkInterfaceHelperClientData());
static_cast<void *>(d.get()),
progress);
{
/* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
d.release();
}
}
}
}
}
#endif
}
{
#ifndef VBOX_WITH_NETFLT
return VERR_NOT_IMPLEMENTED;
#else /* # if defined VBOX_WITH_NETFLT */
int iDefault = getDefaultInterfaceIndex();
/* we are using the INetCfg API for getting the list of miniports */
10000,
&lpszApp);
{
# ifdef VBOX_NETFLT_ONDEMAND_BIND
/* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
# else
/* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
# ifndef VBOX_WITH_HARDENING
{
/* TODO: try to install the netflt from here */
}
# endif
# endif
{
{
{
{
{
/* S_OK == enabled, S_FALSE == disabled */
{
{
{
{
{
{
if (uComponentStatus == 0)
{
}
}
}
}
}
}
}
}
}
}
}
}
else
{
}
}
return VINF_SUCCESS;
#endif /* # if defined VBOX_WITH_NETFLT */
}