/* $Id: NetIf-win.cpp 19130 2009-04-23 08:19:03Z vboxsync $ */ /** @file * Main - NetIfList, Windows implementation. */ /* * Copyright (C) 2008 Sun Microsystems, Inc. * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * 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. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 USA or visit http://www.sun.com if you need * additional information or have any questions. */ /******************************************************************************* * Header Files * *******************************************************************************/ #define LOG_GROUP LOG_GROUP_MAIN #include #include #include #define _WIN32_DCOM #include #include #include #ifdef VBOX_WITH_NETFLT #include "VBox/WinNetConfig.h" #include "devguid.h" #endif #include #include "Logging.h" #include "HostNetworkInterfaceImpl.h" #include "ProgressImpl.h" #include "VirtualBoxImpl.h" #include "netif.h" #ifdef VBOX_WITH_NETFLT #include #include #include "svchlp.h" #include #define INITGUID #include #include #include #include #include #include #define VBOX_APP_NAME L"VirtualBox" static HRESULT netIfWinIsHostOnly(IWbemClassObject * pAdapterConfig, BOOL * pbIsHostOnly) { VARIANT vtServiceName; BOOL bIsHostOnly = FALSE; VariantInit(&vtServiceName); HRESULT hr = pAdapterConfig->Get(L"ServiceName", 0, &vtServiceName, 0, 0); if(SUCCEEDED(hr)) { *pbIsHostOnly = !Bstr(vtServiceName.bstrVal).compare(Bstr("VBoxNetAdp")); VariantClear(&vtServiceName); } return hr; } static HRESULT netIfWinCreateIWbemServices(IWbemServices ** ppSvc) { HRESULT hres; // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if(SUCCEEDED(hres)) { // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *pSvc = NULL; // Connect to the root\cimv2 namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if(SUCCEEDED(hres)) { LogRel(("Connected to ROOT\\CIMV2 WMI namespace\n")); // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if(SUCCEEDED(hres)) { *ppSvc = pSvc; /* do not need it any more */ pLoc->Release(); return hres; } else { LogRel(("Could not set proxy blanket. Error code = 0x%x\n", hres)); } pSvc->Release(); } else { LogRel(("Could not connect. Error code = 0x%x\n", hres)); } pLoc->Release(); } else { LogRel(("Failed to create IWbemLocator object. Err code = 0x%x\n", hres)); // CoUninitialize(); } return hres; } static HRESULT netIfWinFindAdapterClassById(IWbemServices * pSvc, const Guid &guid, IWbemClassObject **pAdapterConfig) { HRESULT hres; WCHAR aQueryString[256]; // char uuidStr[RTUUID_STR_LENGTH]; // int rc = RTUuidToStr(guid.toString().raw(), uuidStr, sizeof(uuidStr)); { swprintf(aQueryString, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"{%S}\"", guid.toString().raw()); // Step 6: -------------------------------------------------- // Use the IWbemServices pointer to make requests of WMI ---- IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t(aQueryString), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if(SUCCEEDED(hres)) { // Step 7: ------------------------------------------------- // Get the data from the query in step 6 ------------------- IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(SUCCEEDED(hres)) { if(uReturn) { pEnumerator->Release(); *pAdapterConfig = pclsObj; hres = S_OK; return hres; } else { hres = S_FALSE; } } } pEnumerator->Release(); } else { Log(("Query for operating system name failed. Error code = 0x%x\n", hres)); } } return hres; } static HRESULT netIfWinAdapterConfigPath(IWbemClassObject *pObj, BSTR * pStr) { VARIANT index; // Get the value of the key property HRESULT hr = pObj->Get(L"Index", 0, &index, 0, 0); if(SUCCEEDED(hr)) { WCHAR strIndex[8]; swprintf(strIndex, L"%u", index.uintVal); *pStr = (bstr_t(L"Win32_NetworkAdapterConfiguration.Index='") + strIndex + "'").copy(); } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static HRESULT netIfExecMethod(IWbemServices * pSvc, IWbemClassObject *pClass, BSTR ObjPath, BSTR MethodName, LPWSTR *pArgNames, LPVARIANT *pArgs, UINT cArgs, IWbemClassObject** ppOutParams ) { HRESULT hres = S_OK; // Step 6: -------------------------------------------------- // Use the IWbemServices pointer to make requests of WMI ---- ComPtr pInParamsDefinition; ComPtr pClassInstance; if(cArgs) { hres = pClass->GetMethod(MethodName, 0, pInParamsDefinition.asOutParam(), NULL); if(SUCCEEDED(hres)) { hres = pInParamsDefinition->SpawnInstance(0, pClassInstance.asOutParam()); if(SUCCEEDED(hres)) { for(UINT i = 0; i < cArgs; i++) { // Store the value for the in parameters hres = pClassInstance->Put(pArgNames[i], 0, pArgs[i], 0); if(FAILED(hres)) { break; } } } } } if(SUCCEEDED(hres)) { IWbemClassObject* pOutParams = NULL; hres = pSvc->ExecMethod(ObjPath, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL); if(SUCCEEDED(hres)) { *ppOutParams = pOutParams; } } return hres; } static HRESULT netIfWinCreateIpArray(SAFEARRAY **ppArray, in_addr* aIp, UINT cIp) { HRESULT hr; SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, cIp); if(pIpArray) { for(UINT i = 0; i < cIp; i++) { char* addr = inet_ntoa(aIp[i]); BSTR val = bstr_t(addr).copy(); long aIndex[1]; aIndex[0] = i; hr = SafeArrayPutElement(pIpArray, aIndex, val); if(FAILED(hr)) { SysFreeString(val); SafeArrayDestroy(pIpArray); break; } } if(SUCCEEDED(hr)) { *ppArray = pIpArray; } } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static HRESULT netIfWinCreateIpArrayV4V6(SAFEARRAY **ppArray, BSTR Ip) { HRESULT hr; SAFEARRAY * pIpArray = SafeArrayCreateVector(VT_BSTR, 0, 1); if(pIpArray) { BSTR val = bstr_t(Ip, false).copy(); long aIndex[1]; aIndex[0] = 0; hr = SafeArrayPutElement(pIpArray, aIndex, val); if(FAILED(hr)) { SysFreeString(val); SafeArrayDestroy(pIpArray); } if(SUCCEEDED(hr)) { *ppArray = pIpArray; } } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static HRESULT netIfWinCreateIpArrayVariantV4(VARIANT * pIpAddresses, in_addr* aIp, UINT cIp) { HRESULT hr; VariantInit(pIpAddresses); pIpAddresses->vt = VT_ARRAY | VT_BSTR; SAFEARRAY *pIpArray; hr = netIfWinCreateIpArray(&pIpArray, aIp, cIp); if(SUCCEEDED(hr)) { pIpAddresses->parray = pIpArray; } return hr; } static HRESULT netIfWinCreateIpArrayVariantV4V6(VARIANT * pIpAddresses, BSTR Ip) { HRESULT hr; VariantInit(pIpAddresses); pIpAddresses->vt = VT_ARRAY | VT_BSTR; SAFEARRAY *pIpArray; hr = netIfWinCreateIpArrayV4V6(&pIpArray, Ip); if(SUCCEEDED(hr)) { pIpAddresses->parray = pIpArray; } return hr; } static HRESULT netIfWinEnableStatic(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pIp, VARIANT * pMask) { ComPtr pClass; BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration"); HRESULT hr; if(ClassName) { hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL); if(SUCCEEDED(hr)) { LPWSTR argNames[] = {L"IPAddress", L"SubnetMask"}; LPVARIANT args[] = {pIp, pMask}; ComPtr pOutParams; hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableStatic"), argNames, args, 2, pOutParams.asOutParam()); if(SUCCEEDED(hr)) { VARIANT varReturnValue; hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0); Assert(SUCCEEDED(hr)); if(SUCCEEDED(hr)) { // Assert(varReturnValue.vt == VT_UINT); int winEr = varReturnValue.uintVal; switch(winEr) { case 0: hr = S_OK; break; default: hr = HRESULT_FROM_WIN32( winEr ); break; } } } } SysFreeString(ClassName); } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static HRESULT netIfWinEnableStaticV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aIp, in_addr * aMask, UINT cIp) { VARIANT ipAddresses; HRESULT hr = netIfWinCreateIpArrayVariantV4(&ipAddresses, aIp, cIp); if(SUCCEEDED(hr)) { VARIANT ipMasks; hr = netIfWinCreateIpArrayVariantV4(&ipMasks, aMask, cIp); if(SUCCEEDED(hr)) { netIfWinEnableStatic(pSvc, ObjPath, &ipAddresses, &ipMasks); VariantClear(&ipMasks); } VariantClear(&ipAddresses); } return hr; } static HRESULT netIfWinEnableStaticV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Ip, BSTR Mask) { VARIANT ipAddresses; HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&ipAddresses, Ip); if(SUCCEEDED(hr)) { VARIANT ipMasks; hr = netIfWinCreateIpArrayVariantV4V6(&ipMasks, Mask); if(SUCCEEDED(hr)) { netIfWinEnableStatic(pSvc, ObjPath, &ipAddresses, &ipMasks); VariantClear(&ipMasks); } VariantClear(&ipAddresses); } return hr; } /* win API allows to set gw metrics as well, we are not setting them */ static HRESULT netIfWinSetGateways(IWbemServices * pSvc, BSTR ObjPath, VARIANT * pGw) { ComPtr pClass; BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration"); HRESULT hr; if(ClassName) { hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL); if(SUCCEEDED(hr)) { LPWSTR argNames[] = {L"DefaultIPGateway"}; LPVARIANT args[] = {pGw}; ComPtr pOutParams; hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"SetGateways"), argNames, args, 1, pOutParams.asOutParam()); if(SUCCEEDED(hr)) { VARIANT varReturnValue; hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0); Assert(SUCCEEDED(hr)); if(SUCCEEDED(hr)) { // Assert(varReturnValue.vt == VT_UINT); int winEr = varReturnValue.uintVal; switch(winEr) { case 0: hr = S_OK; break; default: hr = HRESULT_FROM_WIN32( winEr ); break; } } } } SysFreeString(ClassName); } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } /* win API allows to set gw metrics as well, we are not setting them */ static HRESULT netIfWinSetGatewaysV4(IWbemServices * pSvc, BSTR ObjPath, in_addr* aGw, UINT cGw) { VARIANT gwais; HRESULT hr = netIfWinCreateIpArrayVariantV4(&gwais, aGw, cGw); if(SUCCEEDED(hr)) { netIfWinSetGateways(pSvc, ObjPath, &gwais); VariantClear(&gwais); } return hr; } /* win API allows to set gw metrics as well, we are not setting them */ static HRESULT netIfWinSetGatewaysV4V6(IWbemServices * pSvc, BSTR ObjPath, BSTR Gw) { VARIANT vGw; HRESULT hr = netIfWinCreateIpArrayVariantV4V6(&vGw, Gw); if(SUCCEEDED(hr)) { netIfWinSetGateways(pSvc, ObjPath, &vGw); VariantClear(&vGw); } return hr; } static HRESULT netIfWinEnableDHCP(IWbemServices * pSvc, BSTR ObjPath) { ComPtr pClass; BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration"); HRESULT hr; if(ClassName) { hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL); if(SUCCEEDED(hr)) { ComPtr pOutParams; hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"EnableDHCP"), NULL, NULL, 0, pOutParams.asOutParam()); if(SUCCEEDED(hr)) { VARIANT varReturnValue; hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0); Assert(SUCCEEDED(hr)); if(SUCCEEDED(hr)) { // Assert(varReturnValue.vt == VT_UINT); int winEr = varReturnValue.uintVal; switch(winEr) { case 0: hr = S_OK; break; default: hr = HRESULT_FROM_WIN32( winEr ); break; } } } } SysFreeString(ClassName); } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static HRESULT netIfWinDhcpRediscover(IWbemServices * pSvc, BSTR ObjPath) { ComPtr pClass; BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration"); HRESULT hr; if(ClassName) { hr = pSvc->GetObject(ClassName, 0, NULL, pClass.asOutParam(), NULL); if(SUCCEEDED(hr)) { ComPtr pOutParams; hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"ReleaseDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam()); if(SUCCEEDED(hr)) { VARIANT varReturnValue; hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0); Assert(SUCCEEDED(hr)); if(SUCCEEDED(hr)) { // Assert(varReturnValue.vt == VT_UINT); int winEr = varReturnValue.uintVal; if(winEr == 0) { hr = netIfExecMethod(pSvc, pClass, ObjPath, bstr_t(L"RenewDHCPLease"), NULL, NULL, 0, pOutParams.asOutParam()); if(SUCCEEDED(hr)) { VARIANT varReturnValue; hr = pOutParams->Get(bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0); Assert(SUCCEEDED(hr)); if(SUCCEEDED(hr)) { // Assert(varReturnValue.vt == VT_UINT); int winEr = varReturnValue.uintVal; if(winEr == 0) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32( winEr ); } } } } else { hr = HRESULT_FROM_WIN32( winEr ); } } } } SysFreeString(ClassName); } else { DWORD dwError = GetLastError(); Assert(0); hr = HRESULT_FROM_WIN32( dwError ); } return hr; } static int netIfWinIsDhcpEnabled(const Guid &guid, BOOL *pEnabled) { HRESULT hr; ComPtr pSvc; hr = netIfWinCreateIWbemServices(pSvc.asOutParam()); if(SUCCEEDED(hr)) { ComPtr pAdapterConfig; hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam()); if(SUCCEEDED(hr)) { VARIANT vtEnabled; hr = pAdapterConfig->Get(L"DHCPEnabled", 0, &vtEnabled, 0, 0); if(SUCCEEDED(hr)) { *pEnabled = vtEnabled.boolVal; } } } return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; } static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo) { DWORD dwRc; int rc = VINF_SUCCESS; /* * Most of the hosts probably have less than 10 adapters, * so we'll mostly succeed from the first attempt. */ ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10; PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen); if (!pAddresses) return VERR_NO_MEMORY; dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen); if (dwRc == ERROR_BUFFER_OVERFLOW) { /* Impressive! More than 10 adapters! Get more memory and try again. */ RTMemFree(pAddresses); pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen); if (!pAddresses) return VERR_NO_MEMORY; dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen); } if (dwRc == NO_ERROR) { PIP_ADAPTER_ADDRESSES pAdapter; for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next) { char *pszUuid = RTStrDup(pAdapter->AdapterName); size_t len = strlen(pszUuid) - 1; if (pszUuid[0] == '{' && pszUuid[len] == '}') { pszUuid[len] = 0; if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1)) { bool fIPFound, fIPv6Found; PIP_ADAPTER_UNICAST_ADDRESS pAddr; fIPFound = fIPv6Found = false; for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next) { switch (pAddr->Address.lpSockaddr->sa_family) { case AF_INET: if (!fIPFound) { fIPFound = true; memcpy(&pInfo->IPAddress, &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr, sizeof(pInfo->IPAddress)); } break; case AF_INET6: if (!fIPv6Found) { fIPv6Found = true; memcpy(&pInfo->IPv6Address, ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr, sizeof(pInfo->IPv6Address)); } break; } } PIP_ADAPTER_PREFIX pPrefix; fIPFound = fIPv6Found = false; for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next) { switch (pPrefix->Address.lpSockaddr->sa_family) { case AF_INET: if (!fIPFound) { fIPFound = true; ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength); } break; case AF_INET6: if (!fIPv6Found) { fIPv6Found = true; ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength); } break; } } if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength) Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength)); else memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress)); pInfo->enmMediumType = NETIF_T_ETHERNET; pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN; RTStrFree(pszUuid); break; } } RTStrFree(pszUuid); } BOOL bEnabled; rc = netIfWinIsDhcpEnabled(guid, &bEnabled); Assert(RT_SUCCESS(rc)); if(RT_SUCCESS(rc)) { pInfo->bDhcpEnabled = bEnabled; } } RTMemFree(pAddresses); return VINF_SUCCESS; } static int netIfEnableStaticIpConfigV6(const Guid & guid, IN_BSTR aIPV6Address, IN_BSTR aIPV6Mask, IN_BSTR aIPV6DefaultGateway) { HRESULT hr; ComPtr pSvc; hr = netIfWinCreateIWbemServices(pSvc.asOutParam()); if(SUCCEEDED(hr)) { ComPtr pAdapterConfig; hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam()); if(SUCCEEDED(hr)) { BSTR ObjPath; hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath); if(SUCCEEDED(hr)) { hr = netIfWinEnableStaticV4V6(pSvc, ObjPath, aIPV6Address, aIPV6Mask); if(SUCCEEDED(hr)) { if(aIPV6DefaultGateway) { hr = netIfWinSetGatewaysV4V6(pSvc, ObjPath, aIPV6DefaultGateway); } if(SUCCEEDED(hr)) { // hr = netIfWinUpdateConfig(pIf); } } SysFreeString(ObjPath); } } } return SUCCEEDED(hr) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; } static int netIfEnableStaticIpConfigV6(const Guid &guid, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength) { #if 0 RTNETADDRIPV6 Mask; int rc = prefixLength2IPv6Address(aIPV6MaskPrefixLength, &Mask); if(RT_SUCCESS(rc)) { Bstr maskStr = composeIPv6Address(&Mask); rc = netIfEnableStaticIpConfigV6(guid, aIPV6Address, maskStr, NULL); } return rc; #else return VERR_NOT_IMPLEMENTED; #endif } static HRESULT netIfEnableDynamicIpConfig(const Guid &guid) { HRESULT hr; ComPtr pSvc; hr = netIfWinCreateIWbemServices(pSvc.asOutParam()); if(SUCCEEDED(hr)) { ComPtr pAdapterConfig; hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam()); if(SUCCEEDED(hr)) { BOOL bIsHostOnly; hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly); if(SUCCEEDED(hr)) { if(bIsHostOnly) { BSTR ObjPath; hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath); if(SUCCEEDED(hr)) { hr = netIfWinEnableDHCP(pSvc, ObjPath); if(SUCCEEDED(hr)) { // hr = netIfWinUpdateConfig(pIf); } SysFreeString(ObjPath); } } else { hr = E_FAIL; } } } } return hr; } static HRESULT netIfDhcpRediscover(const Guid &guid) { HRESULT hr; ComPtr pSvc; hr = netIfWinCreateIWbemServices(pSvc.asOutParam()); if(SUCCEEDED(hr)) { ComPtr pAdapterConfig; hr = netIfWinFindAdapterClassById(pSvc, guid, pAdapterConfig.asOutParam()); if(SUCCEEDED(hr)) { BOOL bIsHostOnly; hr = netIfWinIsHostOnly(pAdapterConfig, &bIsHostOnly); if(SUCCEEDED(hr)) { if(bIsHostOnly) { BSTR ObjPath; hr = netIfWinAdapterConfigPath(pAdapterConfig, &ObjPath); if(SUCCEEDED(hr)) { hr = netIfWinDhcpRediscover(pSvc, ObjPath); if(SUCCEEDED(hr)) { // hr = netIfWinUpdateConfig(pIf); } SysFreeString(ObjPath); } } else { hr = E_FAIL; } } } } return hr; } /* svc helper func */ struct StaticIpConfig { ULONG IPAddress; ULONG IPNetMask; }; struct StaticIpV6Config { BSTR IPV6Address; ULONG IPV6NetMaskLength; }; struct NetworkInterfaceHelperClientData { SVCHlpMsg::Code msgCode; /* for SVCHlpMsg::CreateHostOnlyNetworkInterface */ Bstr name; ComObjPtr iface; ComObjPtr vBox; /* for SVCHlpMsg::RemoveHostOnlyNetworkInterface */ Guid guid; union { StaticIpConfig StaticIP; StaticIpV6Config StaticIPV6; } u; }; static HRESULT netIfNetworkInterfaceHelperClient (SVCHlpClient *aClient, Progress *aProgress, void *aUser, int *aVrc) { LogFlowFuncEnter(); LogFlowFunc (("aClient={%p}, aProgress={%p}, aUser={%p}\n", aClient, aProgress, aUser)); AssertReturn ((aClient == NULL && aProgress == NULL && aVrc == NULL) || (aClient != NULL && aProgress != NULL && aVrc != NULL), E_POINTER); AssertReturn (aUser, E_POINTER); std::auto_ptr d (static_cast (aUser)); if (aClient == NULL) { /* "cleanup only" mode, just return (it will free aUser) */ return S_OK; } HRESULT rc = S_OK; int vrc = VINF_SUCCESS; switch (d->msgCode) { case SVCHlpMsg::CreateHostOnlyNetworkInterface: { LogFlowFunc (("CreateHostOnlyNetworkInterface:\n")); LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); 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) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::CreateHostOnlyNetworkInterface_OK: { /* read the GUID */ Guid guid; Utf8Str name; vrc = aClient->read (name); if (RT_FAILURE (vrc)) break; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; LogFlowFunc (("Network connection GUID = {%RTuuid}\n", guid.raw())); /* initialize the object returned to the caller by * CreateHostOnlyNetworkInterface() */ rc = d->iface->init (Bstr(name), guid, HostNetworkInterfaceType_HostOnly); if(SUCCEEDED(rc)) { rc = d->iface->setVirtualBox(d->vBox); if(SUCCEEDED(rc)) { rc = d->iface->updateConfig(); } } endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL;//TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL;//TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } case SVCHlpMsg::RemoveHostOnlyNetworkInterface: { LogFlowFunc (("RemoveHostOnlyNetworkInterface:\n")); LogFlowFunc (("Network connection GUID = {%RTuuid}\n", d->guid.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->guid); if (RT_FAILURE (vrc)) break; /* wait for a reply */ bool endLoop = false; while (!endLoop) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::OK: { /* no parameters */ rc = S_OK; endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL; // TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } case SVCHlpMsg::EnableDynamicIpConfig: /* see usage in code */ { LogFlowFunc (("EnableDynamicIpConfig:\n")); LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->guid); if (RT_FAILURE (vrc)) break; /* wait for a reply */ bool endLoop = false; while (!endLoop) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::OK: { /* no parameters */ rc = d->iface->updateConfig(); endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL; // TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } case SVCHlpMsg::EnableStaticIpConfig: /* see usage in code */ { LogFlowFunc (("EnableStaticIpConfig:\n")); LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->guid); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->u.StaticIP.IPAddress); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->u.StaticIP.IPNetMask); if (RT_FAILURE (vrc)) break; /* wait for a reply */ bool endLoop = false; while (!endLoop) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::OK: { /* no parameters */ rc = d->iface->updateConfig(); endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL; // TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } case SVCHlpMsg::EnableStaticIpConfigV6: /* see usage in code */ { LogFlowFunc (("EnableStaticIpConfigV6:\n")); LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->guid); if (RT_FAILURE (vrc)) break; vrc = aClient->write (Utf8Str(d->u.StaticIPV6.IPV6Address)); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->u.StaticIPV6.IPV6NetMaskLength); if (RT_FAILURE (vrc)) break; /* wait for a reply */ bool endLoop = false; while (!endLoop) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::OK: { /* no parameters */ rc = d->iface->updateConfig(); endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL; // TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } case SVCHlpMsg::DhcpRediscover: /* see usage in code */ { LogFlowFunc (("DhcpRediscover:\n")); LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw())); /* write message and parameters */ vrc = aClient->write (d->msgCode); if (RT_FAILURE (vrc)) break; vrc = aClient->write (d->guid); if (RT_FAILURE (vrc)) break; /* wait for a reply */ bool endLoop = false; while (!endLoop) { SVCHlpMsg::Code reply = SVCHlpMsg::Null; vrc = aClient->read (reply); if (RT_FAILURE (vrc)) break; switch (reply) { case SVCHlpMsg::OK: { /* no parameters */ rc = d->iface->updateConfig(); endLoop = true; break; } case SVCHlpMsg::Error: { /* read the error message */ Utf8Str errMsg; vrc = aClient->read (errMsg); if (RT_FAILURE (vrc)) break; rc = E_FAIL; // TODO: setError (E_FAIL, errMsg); endLoop = true; break; } default: { endLoop = true; rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( //"Invalid message code %d (%08lX)\n", //reply, reply), //rc = E_FAIL); } } } break; } default: rc = E_FAIL; // TODO: ComAssertMsgFailedBreak (( // "Invalid message code %d (%08lX)\n", // d->msgCode, d->msgCode), // rc = E_FAIL); } if (aVrc) *aVrc = vrc; LogFlowFunc (("rc=0x%08X, vrc=%Rrc\n", rc, vrc)); LogFlowFuncLeave(); return rc; } int netIfNetworkInterfaceHelperServer (SVCHlpClient *aClient, SVCHlpMsg::Code aMsgCode) { LogFlowFuncEnter(); LogFlowFunc (("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode)); AssertReturn (aClient, VERR_INVALID_POINTER); int vrc = VINF_SUCCESS; HRESULT hrc; switch (aMsgCode) { case SVCHlpMsg::CreateHostOnlyNetworkInterface: { LogFlowFunc (("CreateHostOnlyNetworkInterface:\n")); // Utf8Str name; // vrc = aClient->read (name); // if (RT_FAILURE (vrc)) break; Guid guid; Utf8Str errMsg; Bstr name; Bstr bstrErr; hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface (guid.asOutParam(), name.asOutParam(), bstrErr.asOutParam()); if (hrc == S_OK) { ULONG ip, mask; hrc = VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(&ip, &mask); if(hrc == S_OK) { /* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip, * i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */ ip = ip | (1 << 24); hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID*)guid.raw(), ip, mask); } /* write success followed by GUID */ vrc = aClient->write (SVCHlpMsg::CreateHostOnlyNetworkInterface_OK); if (RT_FAILURE (vrc)) break; vrc = aClient->write (Utf8Str (name)); if (RT_FAILURE (vrc)) break; vrc = aClient->write (guid); if (RT_FAILURE (vrc)) break; } else { vrc = VERR_GENERAL_FAILURE; errMsg = Utf8Str(bstrErr); /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } case SVCHlpMsg::RemoveHostOnlyNetworkInterface: { LogFlowFunc (("RemoveHostOnlyNetworkInterface:\n")); Guid guid; Bstr bstrErr; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; Utf8Str errMsg; hrc = VBoxNetCfgWinRemoveHostOnlyNetworkInterface ((const GUID*)guid.raw(), bstrErr.asOutParam()); if (hrc == S_OK) { /* write parameter-less success */ vrc = aClient->write (SVCHlpMsg::OK); if (RT_FAILURE (vrc)) break; } else { vrc = VERR_GENERAL_FAILURE; errMsg = Utf8Str(bstrErr); /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } case SVCHlpMsg::EnableStaticIpConfigV6: { LogFlowFunc (("EnableStaticIpConfigV6:\n")); Guid guid; Utf8Str ipV6; ULONG maskLengthV6; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; vrc = aClient->read (ipV6); if (RT_FAILURE (vrc)) break; vrc = aClient->read (maskLengthV6); if (RT_FAILURE (vrc)) break; Utf8Str errMsg; vrc = VERR_NOT_IMPLEMENTED; if (RT_SUCCESS (vrc)) { /* write success followed by GUID */ vrc = aClient->write (SVCHlpMsg::OK); if (RT_FAILURE (vrc)) break; } else { /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } case SVCHlpMsg::EnableStaticIpConfig: { LogFlowFunc (("EnableStaticIpConfig:\n")); Guid guid; ULONG ip, mask; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; vrc = aClient->read (ip); if (RT_FAILURE (vrc)) break; vrc = aClient->read (mask); if (RT_FAILURE (vrc)) break; Utf8Str errMsg; hrc = VBoxNetCfgWinEnableStaticIpConfig ((const GUID *)guid.raw(), ip, mask); if (hrc == S_OK) { /* write success followed by GUID */ vrc = aClient->write (SVCHlpMsg::OK); if (RT_FAILURE (vrc)) break; } else { vrc = VERR_GENERAL_FAILURE; /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } case SVCHlpMsg::EnableDynamicIpConfig: { LogFlowFunc (("EnableDynamicIpConfig:\n")); Guid guid; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; Utf8Str errMsg; hrc = VBoxNetCfgWinEnableDynamicIpConfig ((const GUID *)guid.raw()); if (hrc == S_OK) { /* write success followed by GUID */ vrc = aClient->write (SVCHlpMsg::OK); if (RT_FAILURE (vrc)) break; } else { vrc = VERR_GENERAL_FAILURE; /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } case SVCHlpMsg::DhcpRediscover: { LogFlowFunc (("DhcpRediscover:\n")); Guid guid; vrc = aClient->read (guid); if (RT_FAILURE (vrc)) break; Utf8Str errMsg; hrc = VBoxNetCfgWinDhcpRediscover ((const GUID *)guid.raw()); if (hrc == S_OK) { /* write success followed by GUID */ vrc = aClient->write (SVCHlpMsg::OK); if (RT_FAILURE (vrc)) break; } else { vrc = VERR_GENERAL_FAILURE; /* write failure followed by error message */ if (errMsg.isEmpty()) errMsg = Utf8StrFmt ("Unspecified error (%Rrc)", vrc); vrc = aClient->write (SVCHlpMsg::Error); if (RT_FAILURE (vrc)) break; vrc = aClient->write (errMsg); if (RT_FAILURE (vrc)) break; } break; } default: AssertMsgFailedBreakStmt ( ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode), VERR_GENERAL_FAILURE); } LogFlowFunc (("vrc=%Rrc\n", vrc)); LogFlowFuncLeave(); 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() { LONG rc = 0; OSVERSIONINFOEX info; ZeroMemory (&info, sizeof (OSVERSIONINFOEX)); info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); rc = GetVersionEx ((OSVERSIONINFO *) &info); AssertReturn (rc != 0, FALSE); LogFlowFunc (("dwMajorVersion=%d, dwMinorVersion=%d\n", info.dwMajorVersion, info.dwMinorVersion)); /* we are interested only in Vista (and newer versions...). In all * earlier versions UAC is not present. */ if (info.dwMajorVersion < 6) return FALSE; /* the default EnableLUA value is 1 (Enabled) */ DWORD dwEnableLUA = 1; HKEY hKey; rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_QUERY_VALUE, &hKey); Assert (rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND); if (rc == ERROR_SUCCESS) { DWORD cbEnableLUA = sizeof (dwEnableLUA); rc = RegQueryValueExA (hKey, "EnableLUA", NULL, NULL, (LPBYTE) &dwEnableLUA, &cbEnableLUA); RegCloseKey (hKey); Assert (rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND); } LogFlowFunc (("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA)); return dwEnableLUA == 1; } /* end */ static int vboxNetWinAddComponent(std::list > * pPist, INetCfgComponent * pncc, HostNetworkInterfaceType enmType) { LPWSTR lpszName; GUID IfGuid; HRESULT hr; int rc = VERR_GENERAL_FAILURE; hr = pncc->GetDisplayName( &lpszName ); Assert(hr == S_OK); if(hr == S_OK) { size_t cUnicodeName = wcslen(lpszName) + 1; size_t uniLen = (cUnicodeName * 2 + sizeof (OLECHAR) - 1) / sizeof (OLECHAR); Bstr name (uniLen + 1 /* extra zero */); wcscpy((wchar_t *) name.mutableRaw(), lpszName); hr = pncc->GetInstanceGuid(&IfGuid); Assert(hr == S_OK); if (hr == S_OK) { NETIFINFO Info; memset(&Info, 0, sizeof(Info)); Info.Uuid = *(Guid(IfGuid).raw()); rc = collectNetIfInfo(name, Guid(IfGuid), &Info); if (RT_FAILURE(rc)) { Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc)); } /* create a new object and add it to the list */ ComObjPtr iface; iface.createObject(); /* remove the curly bracket at the end */ if (SUCCEEDED (iface->init (name, enmType, &Info))) { pPist->push_back (iface); rc = VINF_SUCCESS; } else { Assert(0); } } CoTaskMemFree(lpszName); } return rc; } #endif /* VBOX_WITH_NETFLT */ static int netIfListHostAdapters(std::list > &list) { #ifndef VBOX_WITH_NETFLT /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */ return VERR_NOT_IMPLEMENTED; #else /* # if defined VBOX_WITH_NETFLT */ INetCfg *pNc; INetCfgComponent *pMpNcc; LPWSTR lpszApp = NULL; HRESULT hr; IEnumNetCfgComponent *pEnumComponent; /* we are using the INetCfg API for getting the list of miniports */ hr = VBoxNetCfgWinQueryINetCfg( FALSE, VBOX_APP_NAME, &pNc, &lpszApp ); Assert(hr == S_OK); if(hr == S_OK) { hr = VBoxNetCfgWinGetComponentEnum(pNc, &GUID_DEVCLASS_NET, &pEnumComponent); if(hr == S_OK) { while((hr = VBoxNetCfgWinGetNextComponent(pEnumComponent, &pMpNcc)) == S_OK) { ULONG uComponentStatus; hr = pMpNcc->GetDeviceStatus(&uComponentStatus); //#ifndef DEBUG_bird // Assert(hr == S_OK); //#endif if(hr == S_OK) { if(uComponentStatus == 0) { LPWSTR pId; hr = pMpNcc->GetId(&pId); Assert(hr == S_OK); if(hr == S_OK) { if(!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2)) { vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly); } CoTaskMemFree(pId); } } } VBoxNetCfgWinReleaseRef(pMpNcc); } Assert(hr == S_OK || hr == S_FALSE); VBoxNetCfgWinReleaseRef(pEnumComponent); } else { LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr)); } VBoxNetCfgWinReleaseINetCfg(pNc, FALSE); } else if(lpszApp) { CoTaskMemFree(lpszApp); } #endif /* # if defined VBOX_WITH_NETFLT */ return VINF_SUCCESS; } int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else Bstr name; HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam()); if(hr == S_OK) { GUID IfGuid; hr = pIf->COMGETTER(Id)(&IfGuid); Assert(hr == S_OK); if (hr == S_OK) { memset(pInfo, 0, sizeof(NETIFINFO)); Guid guid(IfGuid); pInfo->Uuid = *(guid.raw()); return collectNetIfInfo(name, guid, pInfo); } } return VERR_GENERAL_FAILURE; #endif } int NetIfCreateHostOnlyNetworkInterface (VirtualBox *pVBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else /* create a progress object */ ComObjPtr progress; progress.createObject(); ComPtr host; HRESULT rc = pVBox->COMGETTER(Host)(host.asOutParam()); if(SUCCEEDED(rc)) { rc = progress->init (pVBox, host, Bstr (_T ("Creating host only network interface")), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); progress.queryInterfaceTo (aProgress); /* create a new uninitialized host interface object */ ComObjPtr iface; iface.createObject(); iface.queryInterfaceTo (aHostNetworkInterface); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface; // d->name = aName; d->iface = iface; d->vBox = pVBox; rc = pVBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfRemoveHostOnlyNetworkInterface (VirtualBox *pVBox, IN_GUID aId, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else /* create a progress object */ ComObjPtr progress; progress.createObject(); ComPtr host; HRESULT rc = pVBox->COMGETTER(Host)(host.asOutParam()); if(SUCCEEDED(rc)) { rc = progress->init (pVBox, host, Bstr (_T ("Removing host network interface")), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); progress.queryInterfaceTo (aProgress); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface; d->guid = aId; rc = pVBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else HRESULT rc; GUID guid; rc = pIf->COMGETTER(Id) (&guid); if(SUCCEEDED(rc)) { // ComPtr vBox; // rc = pIf->getVirtualBox (vBox.asOutParam()); // if(SUCCEEDED(rc)) { /* create a progress object */ ComObjPtr progress; progress.createObject(); // ComPtr host; // HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam()); // if(SUCCEEDED(rc)) { rc = progress->init (vBox, (IHostNetworkInterface*)pIf, Bstr ("Enabling Dynamic Ip Configuration"), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); // progress.queryInterfaceTo (aProgress); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::EnableStaticIpConfig; d->guid = guid; d->iface = pIf; d->u.StaticIP.IPAddress = ip; d->u.StaticIP.IPNetMask = mask; rc = vBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); progress->WaitForCompletion(-1); } } } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else HRESULT rc; GUID guid; rc = pIf->COMGETTER(Id) (&guid); if(SUCCEEDED(rc)) { // ComPtr vBox; // rc = pIf->getVirtualBox (vBox.asOutParam()); // if(SUCCEEDED(rc)) { /* create a progress object */ ComObjPtr progress; progress.createObject(); // ComPtr host; // HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam()); // if(SUCCEEDED(rc)) { rc = progress->init (vBox, (IHostNetworkInterface*)pIf, Bstr ("Enabling Dynamic Ip Configuration"), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); // progress.queryInterfaceTo (aProgress); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6; d->guid = guid; d->iface = pIf; d->u.StaticIPV6.IPV6Address = aIPV6Address; d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength; rc = vBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); progress->WaitForCompletion(-1); } } } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else HRESULT rc; GUID guid; rc = pIf->COMGETTER(Id) (&guid); if(SUCCEEDED(rc)) { // ComPtr vBox; // rc = pIf->getVirtualBox (vBox.asOutParam()); // if(SUCCEEDED(rc)) { /* create a progress object */ ComObjPtr progress; progress.createObject(); // ComPtr host; // HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam()); // if(SUCCEEDED(rc)) { rc = progress->init (vBox, (IHostNetworkInterface*)pIf, Bstr ("Enabling Dynamic Ip Configuration"), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); // progress.queryInterfaceTo (aProgress); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::EnableDynamicIpConfig; d->guid = guid; d->iface = pIf; rc = vBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); progress->WaitForCompletion(-1); } } } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else HRESULT rc; GUID guid; rc = pIf->COMGETTER(Id) (&guid); if(SUCCEEDED(rc)) { // ComPtr vBox; // rc = pIf->getVirtualBox (vBox.asOutParam()); // if(SUCCEEDED(rc)) { /* create a progress object */ ComObjPtr progress; progress.createObject(); // ComPtr host; // HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam()); // if(SUCCEEDED(rc)) { rc = progress->init (vBox, (IHostNetworkInterface*)pIf, Bstr ("Enabling Dynamic Ip Configuration"), FALSE /* aCancelable */); if(SUCCEEDED(rc)) { CheckComRCReturnRC (rc); // progress.queryInterfaceTo (aProgress); /* create the networkInterfaceHelperClient() argument */ std::auto_ptr d (new NetworkInterfaceHelperClientData()); AssertReturn (d.get(), E_OUTOFMEMORY); d->msgCode = SVCHlpMsg::DhcpRediscover; d->guid = guid; d->iface = pIf; rc = vBox->startSVCHelperClient ( IsUACEnabled() == TRUE /* aPrivileged */, netIfNetworkInterfaceHelperClient, static_cast (d.get()), progress); if (SUCCEEDED (rc)) { /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */ d.release(); progress->WaitForCompletion(-1); } } } } } return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; #endif } int NetIfList(std::list > &list) { #ifndef VBOX_WITH_NETFLT return VERR_NOT_IMPLEMENTED; #else /* # if defined VBOX_WITH_NETFLT */ INetCfg *pNc; INetCfgComponent *pMpNcc; INetCfgComponent *pTcpIpNcc; LPWSTR lpszApp; HRESULT hr; IEnumNetCfgBindingPath *pEnumBp; INetCfgBindingPath *pBp; IEnumNetCfgBindingInterface *pEnumBi; INetCfgBindingInterface *pBi; /* we are using the INetCfg API for getting the list of miniports */ hr = VBoxNetCfgWinQueryINetCfg( FALSE, VBOX_APP_NAME, &pNc, &lpszApp ); Assert(hr == S_OK); if(hr == S_OK) { # ifdef VBOX_NETFLT_ONDEMAND_BIND /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */ hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc); # else /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */ hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc); # ifndef VBOX_WITH_HARDENING if(hr != S_OK) { /* TODO: try to install the netflt from here */ } # endif # endif if(hr == S_OK) { hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp); Assert(hr == S_OK); if ( hr == S_OK ) { hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp); Assert(hr == S_OK || hr == S_FALSE); while( hr == S_OK ) { /* S_OK == enabled, S_FALSE == disabled */ if(pBp->IsEnabled() == S_OK) { hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi); Assert(hr == S_OK); if ( hr == S_OK ) { hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi); Assert(hr == S_OK); while(hr == S_OK) { hr = pBi->GetLowerComponent( &pMpNcc ); Assert(hr == S_OK); if(hr == S_OK) { ULONG uComponentStatus; hr = pMpNcc->GetDeviceStatus(&uComponentStatus); //#ifndef DEBUG_bird // Assert(hr == S_OK); //#endif if(hr == S_OK) { if(uComponentStatus == 0) { vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_Bridged); } } VBoxNetCfgWinReleaseRef( pMpNcc ); } VBoxNetCfgWinReleaseRef(pBi); hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi); } VBoxNetCfgWinReleaseRef(pEnumBi); } } VBoxNetCfgWinReleaseRef(pBp); hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp); } VBoxNetCfgWinReleaseRef(pEnumBp); } VBoxNetCfgWinReleaseRef(pTcpIpNcc); } else { LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr)); } VBoxNetCfgWinReleaseINetCfg(pNc, FALSE); } netIfListHostAdapters(list); return VINF_SUCCESS; #endif /* # if defined VBOX_WITH_NETFLT */ }