/* $Id: NetIf-win.cpp 21878 2009-07-30 12:42:08Z 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 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); } ADAPTER_SETTINGS Settings; HRESULT hr = VBoxNetCfgWinGetAdapterSettings((const GUID *)guid.raw(), &Settings); if(hr == S_OK) { if(Settings.ip) { pInfo->IPAddress.u = Settings.ip; pInfo->IPNetMask.u = Settings.mask; } pInfo->bDhcpEnabled = Settings.bDhcp; } else { pInfo->bDhcpEnabled = false; } } RTMemFree(pAddresses); return VINF_SUCCESS; } /* 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) { Bstr IfGuid; hr = pIf->COMGETTER(Id)(IfGuid.asOutParam()); 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 NetIfGetConfigByName(PNETIFINFO) { return VERR_NOT_IMPLEMENTED; } 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; Bstr guid; rc = pIf->COMGETTER(Id) (guid.asOutParam()); 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(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; Bstr guid; rc = pIf->COMGETTER(Id) (guid.asOutParam()); 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; Bstr guid; rc = pIf->COMGETTER(Id) (guid.asOutParam()); 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; Bstr guid; rc = pIf->COMGETTER(Id) (guid.asOutParam()); 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 */ }