int NetIfEnableStaticIpConfigV6(VirtualBox * /* vBox */, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength) { char szAddress[5*8 + 1 + 5 + 1]; if (Bstr(aIPV6Address).length()) { RTStrPrintf(szAddress, sizeof(szAddress), "%ls/%d", aIPV6Address, aIPV6MaskPrefixLength); return NetIfAdpCtl(pIf, szAddress, NULL, NULL); } else { RTStrPrintf(szAddress, sizeof(szAddress), "%ls", aOldIPV6Address); return NetIfAdpCtl(pIf, szAddress, "remove", NULL); } }
HRESULT HostNetworkInterface::setVirtualBox(VirtualBox *pVBox) { AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AssertReturn(mVBox != pVBox, S_OK); unconst(mVBox) = pVBox; #if !defined(RT_OS_WINDOWS) /* If IPv4 address hasn't been initialized */ if (m.IPAddress == 0 && mIfType == HostNetworkInterfaceType_HostOnly) { Bstr tmpAddr, tmpMask; HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), tmpAddr.asOutParam()); if (FAILED(hrc) || tmpAddr.isEmpty()) tmpAddr = getDefaultIPv4Address(mInterfaceName); hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), tmpMask.asOutParam()); if (FAILED(hrc) || tmpMask.isEmpty()) tmpMask = Bstr(VBOXNET_IPV4MASK_DEFAULT); m.IPAddress = inet_addr(Utf8Str(tmpAddr).c_str()); m.networkMask = inet_addr(Utf8Str(tmpMask).c_str()); } if (m.IPV6Address.isEmpty()) { Bstr tmpPrefixLen; HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), m.IPV6Address.asOutParam()); if (SUCCEEDED(hrc) && !m.IPV6Address.isEmpty()) { hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6PrefixLen", mInterfaceName.raw()).raw(), tmpPrefixLen.asOutParam()); if (SUCCEEDED(hrc) && !tmpPrefixLen.isEmpty()) m.IPV6NetworkMaskPrefixLength = Utf8Str(tmpPrefixLen).toUInt32(); else m.IPV6NetworkMaskPrefixLength = 64; } } #endif return S_OK; }
HRESULT VFSExplorer::remove(const std::vector<com::Utf8Str> &aNames, ComPtr<IProgress> &aProgress) { AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT rc = S_OK; ComObjPtr<Progress> progress; try { /* Create the progress object */ progress.createObject(); rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this), Bstr(tr("Delete files")).raw(), TRUE /* aCancelable */); if (FAILED(rc)) throw rc; /* Initialize our worker task */ std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress)); /* Add all filenames to delete as task data */ for (size_t i = 0; i < aNames.size(); ++i) task->filenames.push_back(aNames[i]); rc = task->startThread(); if (FAILED(rc)) throw rc; /* Don't destruct on success */ task.release(); } catch (HRESULT aRC) { rc = aRC; } if (SUCCEEDED(rc)) /* Return progress to the caller */ progress.queryInterfaceTo(aProgress.asOutParam()); return rc; }
STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress) { AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); Utf8Str strUpPath; { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); /* Remove lowest dir entry in a platform neutral way. */ char *pszNewPath = RTStrDup(m->strPath.c_str()); RTPathStripTrailingSlash(pszNewPath); RTPathStripFilename(pszNewPath); strUpPath = pszNewPath; RTStrFree(pszNewPath); } return Cd(Bstr(strUpPath).raw(), aProgress); }
HRESULT HostNetworkInterface::enableStaticIPConfigV6(const com::Utf8Str &aIPV6Address, ULONG aIPV6NetworkMaskPrefixLength) { #ifndef VBOX_WITH_HOSTNETIF_API return E_NOTIMPL; #else if (aIPV6NetworkMaskPrefixLength > 128) return E_INVALIDARG; int rc = S_OK; if ( m.realIPV6Address != aIPV6Address || m.realIPV6PrefixLength != aIPV6NetworkMaskPrefixLength) { BSTR bstr; aIPV6Address.cloneTo(&bstr); if (aIPV6NetworkMaskPrefixLength == 0) aIPV6NetworkMaskPrefixLength = 64; rc = NetIfEnableStaticIpConfigV6(mVirtualBox, this, m.IPV6Address.raw(), bstr, aIPV6NetworkMaskPrefixLength); if (RT_FAILURE(rc)) { LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc)); return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL; } else { m.realIPV6Address = aIPV6Address; m.realIPV6PrefixLength = aIPV6NetworkMaskPrefixLength; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), Bstr(aIPV6Address).raw()))) return E_FAIL; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", mInterfaceName.raw()).raw(), BstrFmt("%u", aIPV6NetworkMaskPrefixLength).raw()))) return E_FAIL; } } return S_OK; #endif }
/** * Deletes a variable. * * @param pThis The NVRAM driver instance data. * @param pszVarNodeNm The variable node name. */ static void drvNvram_deleteVar(PNVRAM pThis, const char *pszVarNodeNm) { char szExtraName[256]; size_t offValue = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16, NVRAM_CFGM_OVERLAY_PATH "/%s/", pszVarNodeNm); static const char *s_apszValueNames[] = { "Name", "Uuid", "Value", "Attribs" }; for (unsigned i = 0; i < RT_ELEMENTS(s_apszValueNames); i++) { Assert(strlen(s_apszValueNames[i]) < 16); strcpy(szExtraName + offValue, s_apszValueNames[i]); try { HRESULT hrc = pThis->pNvram->getParent()->i_machine()->SetExtraData(Bstr(szExtraName).raw(), Bstr().raw()); if (FAILED(hrc)) LogRel(("drvNvram_deleteVar: SetExtraData(%s,) returned %Rhrc\n", szExtraName, hrc)); } catch (...) { LogRel(("drvNvram_deleteVar: SetExtraData(%s,) threw exception\n", szExtraName)); } } }
STDMETHODIMP HostNetworkInterface::EnableStaticIpConfigV6 (IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength) { #ifndef VBOX_WITH_HOSTNETIF_API return E_NOTIMPL; #else if (!aIPV6Address) return E_INVALIDARG; if (aIPV6MaskPrefixLength > 128) return E_INVALIDARG; AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); int rc = S_OK; if (m.realIPV6Address != aIPV6Address || m.realIPV6PrefixLength != aIPV6MaskPrefixLength) { if (aIPV6MaskPrefixLength == 0) aIPV6MaskPrefixLength = 64; rc = NetIfEnableStaticIpConfigV6(mVBox, this, m.IPV6Address.raw(), aIPV6Address, aIPV6MaskPrefixLength); if (RT_FAILURE(rc)) { LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc)); return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL; } else { m.realIPV6Address = aIPV6Address; m.realIPV6PrefixLength = aIPV6MaskPrefixLength; if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), Bstr(aIPV6Address).raw()))) return E_FAIL; if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", mInterfaceName.raw()).raw(), BstrFmt("%u", aIPV6MaskPrefixLength).raw()))) return E_FAIL; } } return S_OK; #endif }
HRESULT DHCPServer::getMacOptions(const com::Utf8Str &aMAC, std::vector<com::Utf8Str> &aOption) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hrc = S_OK; ComPtr<IMachine> machine; ComPtr<INetworkAdapter> nic; settings::VmSlot2OptionsIterator it; for(it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it) { alock.release(); hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam()); alock.acquire(); if (FAILED(hrc)) continue; alock.release(); hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam()); alock.acquire(); if (FAILED(hrc)) continue; com::Bstr mac; alock.release(); hrc = nic->COMGETTER(MACAddress)(mac.asOutParam()); alock.acquire(); if (FAILED(hrc)) /* no MAC address ??? */ break; if (!RTStrICmp(com::Utf8Str(mac).c_str(), aMAC.c_str())) return getVmSlotOptions(it->first.VmName, it->first.Slot, aOption); } /* end of for */ return hrc; }
/** * Returns the netwok mask of the host network interface. * * @returns COM status code * @param aNetworkMask address of result pointer */ STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkMask)(BSTR *aNetworkMask) { CheckComArgOutPointerValid(aNetworkMask); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); in_addr tmp; #if defined(RT_OS_WINDOWS) tmp.S_un.S_addr = m.networkMask; #else tmp.s_addr = m.networkMask; #endif char *addr = inet_ntoa(tmp); if (addr) { Bstr(addr).detachTo(aNetworkMask); return S_OK; } return E_FAIL; }
HRESULT Guest::taskCopyFileFromGuest(GuestTask *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* * Do *not* take a write lock here since we don't (and won't) * touch any class-specific data (of IGuest) here - only the member functions * which get called here can do that. */ HRESULT rc = S_OK; try { ComObjPtr<Guest> pGuest = aTask->pGuest; /* Does our source file exist? */ BOOL fFileExists; rc = pGuest->FileExists(Bstr(aTask->strSource).raw(), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), &fFileExists); if (SUCCEEDED(rc)) { if (!fFileExists) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Source file \"%s\" does not exist, or is not a file"), aTask->strSource.c_str()); } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); /* Query file size to make an estimate for our progress object. */ if (SUCCEEDED(rc)) { LONG64 lFileSize; rc = pGuest->FileQuerySize(Bstr(aTask->strSource).raw(), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), &lFileSize); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; if (SUCCEEDED(rc)) { /* * Prepare tool command line. */ char szSource[RTPATH_MAX]; if (RTStrPrintf(szSource, sizeof(szSource), "%s", aTask->strSource.c_str()) <= sizeof(szSource) - 1) { /* * Normalize path slashes, based on the detected guest. */ Utf8Str osType = mData.mOSTypeId; if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) || osType.contains("Windows", Utf8Str::CaseInsensitive)) { /* We have a Windows guest. */ RTPathChangeToDosSlashes(szSource, true /* Force conversion. */); } else /* ... or something which isn't from Redmond ... */ { RTPathChangeToUnixSlashes(szSource, true /* Force conversion. */); } args.push_back(Bstr(szSource).raw()); /* Tell our cat tool which file to output. */ } else rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error preparing command line")); } ComPtr<IProgress> execProgress; ULONG uPID; if (SUCCEEDED(rc)) { LogRel(("Copying file \"%s\" to host \"%s\" (%u bytes) ...\n", aTask->strSource.c_str(), aTask->strDest.c_str(), lFileSize)); /* * Okay, since we gathered all stuff we need until now to start the * actual copying, start the guest part now. */ rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(), Bstr("Copying file to host").raw(), ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), ExecuteProcessFlag_WaitForProcessStartOnly | ExecuteProcessFlag_WaitForStdOut, NULL, NULL, execProgress.asOutParam(), &uPID); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } if (SUCCEEDED(rc)) { BOOL fCompleted = FALSE; BOOL fCanceled = FALSE; RTFILE hFileDest; int vrc = RTFileOpen(&hFileDest, aTask->strDest.c_str(), RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); if (RT_FAILURE(vrc)) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Unable to create/open destination file \"%s\", rc=%Rrc"), aTask->strDest.c_str(), vrc); else { size_t cbToRead = lFileSize; size_t cbTransfered = 0; while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { SafeArray<BYTE> aOutputData; rc = pGuest->GetProcessOutput(uPID, ProcessOutputFlag_None /* StdOut */, 0 /* No timeout. */, _64K, ComSafeArrayAsOutParam(aOutputData)); if (SUCCEEDED(rc)) { if (aOutputData.size()) { vrc = RTFileWrite(hFileDest, aOutputData.raw(), aOutputData.size(), NULL /* No partial writes */); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error writing to file \"%s\" (%u bytes left), rc=%Rrc"), aTask->strSource.c_str(), cbToRead, vrc); break; } Assert(cbToRead >= aOutputData.size()); cbToRead -= aOutputData.size(); cbTransfered += aOutputData.size(); aTask->pProgress->SetCurrentOperationProgress(cbTransfered / (lFileSize / 100.0)); } /* Nothing read this time; try next round. */ } else { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } } RTFileClose(hFileDest); if (SUCCEEDED(rc)) { if ( cbTransfered && (cbTransfered != lFileSize)) { /* * Only bitch about an unexpected end of a file when there already * was data read from that file. If this was the very first read we can * be (almost) sure that this file is not meant to be read by the specified user. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Unexpected end of file \"%s\" (%u bytes total, %u bytes transferred)"), aTask->strSource.c_str(), lFileSize, cbTransfered); } if (SUCCEEDED(rc)) aTask->pProgress->notifyComplete(S_OK); } } } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
void HostPowerService::notify(Reason_T aReason) { SessionMachinesList machines; VirtualBox::InternalControlList controls; HRESULT rc = S_OK; switch (aReason) { case Reason_HostSuspend: { LogFunc(("HOST SUSPEND\n")); #ifdef VBOX_WITH_RESOURCE_USAGE_API /* Suspend performance sampling to avoid unnecessary callbacks due to jumps in time. */ PerformanceCollector *perfcollector = mVirtualBox->i_performanceCollector(); if (perfcollector) perfcollector->suspendSampling(); #endif mVirtualBox->i_getOpenedMachines(machines, &controls); /* pause running VMs */ for (VirtualBox::InternalControlList::const_iterator it = controls.begin(); it != controls.end(); ++it) { ComPtr<IInternalSessionControl> pControl = *it; /* PauseWithReason() will simply return a failure if * the VM is in an inappropriate state */ rc = pControl->PauseWithReason(Reason_HostSuspend); if (FAILED(rc)) continue; /* save the control to un-pause the VM later */ mSessionControls.push_back(pControl); } LogRel(("Host suspending: Paused %d VMs\n", mSessionControls.size())); break; } case Reason_HostResume: { LogFunc(("HOST RESUME\n")); size_t resumed = 0; /* go through VMs we paused on Suspend */ for (size_t i = 0; i < mSessionControls.size(); ++i) { /* note that Resume() will simply return a failure if the VM is * in an inappropriate state (it will also fail if the VM has * been somehow closed by this time already so that the * console reference we have is dead) */ rc = mSessionControls[i]->ResumeWithReason(Reason_HostResume); if (FAILED(rc)) continue; ++resumed; } LogRel(("Host resumed: Resumed %d VMs\n", resumed)); #ifdef VBOX_WITH_RESOURCE_USAGE_API /* Resume the performance sampling. */ PerformanceCollector *perfcollector = mVirtualBox->i_performanceCollector(); if (perfcollector) perfcollector->resumeSampling(); #endif mSessionControls.clear(); break; } case Reason_HostBatteryLow: { LogFunc(("BATTERY LOW\n")); Bstr value; rc = mVirtualBox->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(), value.asOutParam()); int fGlobal = 0; if (SUCCEEDED(rc) && !value.isEmpty()) { if (value != "0") fGlobal = 1; else if (value == "0") fGlobal = -1; } mVirtualBox->i_getOpenedMachines(machines, &controls); size_t saved = 0; /* save running VMs */ for (SessionMachinesList::const_iterator it = machines.begin(); it != machines.end(); ++it) { ComPtr<SessionMachine> pMachine = *it; rc = pMachine->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(), value.asOutParam()); int fPerVM = 0; if (SUCCEEDED(rc) && !value.isEmpty()) { /* per-VM overrides global */ if (value != "0") fPerVM = 2; else if (value == "0") fPerVM = -2; } /* default is true */ if (fGlobal + fPerVM >= 0) { ComPtr<IProgress> progress; /* SessionMachine::i_saveStateWithReason() will return * a failure if the VM is in an inappropriate state */ rc = pMachine->i_saveStateWithReason(Reason_HostBatteryLow, progress); if (FAILED(rc)) { LogRel(("SaveState '%s' failed with %Rhrc\n", pMachine->i_getName().c_str(), rc)); continue; } /* Wait until the operation has been completed. */ rc = progress->WaitForCompletion(-1); if (SUCCEEDED(rc)) { LONG iRc; progress->COMGETTER(ResultCode)(&iRc); rc = iRc; } AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc)); if (SUCCEEDED(rc)) { LogRel(("SaveState '%s' succeeded\n", pMachine->i_getName().c_str())); ++saved; } } } LogRel(("Battery Low: saved %d VMs\n", saved)); break; } default: /* nothing */; } }
STDMETHODIMP Guest::COMGETTER(AdditionsVersion) (BSTR *aAdditionsVersion) { CheckComArgOutPointerValid(aAdditionsVersion); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hr = S_OK; if ( mData.mAdditionsVersion.isEmpty() /* Only try alternative way if GA are active! */ && mData.mAdditionsRunLevel > AdditionsRunLevelType_None) { /* * If we got back an empty string from GetAdditionsVersion() we either * really don't have the Guest Additions version yet or the guest is running * older Guest Additions (< 3.2.0) which don't provide VMMDevReq_ReportGuestInfo2, * so get the version + revision from the (hopefully) provided guest properties * instead. */ Bstr addVersion; LONG64 u64Timestamp; Bstr flags; hr = mParent->machine()->GetGuestProperty(Bstr("/VirtualBox/GuestAdd/Version").raw(), addVersion.asOutParam(), &u64Timestamp, flags.asOutParam()); if (hr == S_OK) { Bstr addRevision; hr = mParent->machine()->GetGuestProperty(Bstr("/VirtualBox/GuestAdd/Revision").raw(), addRevision.asOutParam(), &u64Timestamp, flags.asOutParam()); if ( hr == S_OK && !addVersion.isEmpty() && !addRevision.isEmpty()) { /* Some Guest Additions versions had interchanged version + revision values, * so check if the version value at least has a dot to identify it and change * both values to reflect the right content. */ if (!Utf8Str(addVersion).contains(".")) { Bstr addTemp = addVersion; addVersion = addRevision; addRevision = addTemp; } Bstr additionsVersion = BstrFmt("%ls r%ls", addVersion.raw(), addRevision.raw()); additionsVersion.cloneTo(aAdditionsVersion); } /** @todo r=bird: else: Should not return failure! */ } else { /* If getting the version + revision above fails or they simply aren't there * because of *really* old Guest Additions we only can report the interface * version to at least have something. */ mData.mInterfaceVersion.cloneTo(aAdditionsVersion); /** @todo r=bird: hr is still indicating failure! */ } } else mData.mAdditionsVersion.cloneTo(aAdditionsVersion); return hr; }
/** * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqPut) */ DECLCALLBACK(int) drvNvram_VarStoreSeqPut(PPDMINVRAMCONNECTOR pInterface, int idxVariable, PCRTUUID pVendorUuid, const char *pszName, size_t cchName, uint32_t fAttributes, uint8_t const *pbValue, size_t cbValue) { PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector); int rc = VINF_SUCCESS; if (pThis->fPermanentSave && pThis->pNvram) { char szExtraName[256]; size_t offValueNm = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16, NVRAM_CFGM_OVERLAY_PATH "/%04u/", idxVariable); char szUuid[RTUUID_STR_LENGTH]; int rc2 = RTUuidToStr(pVendorUuid, szUuid, sizeof(szUuid)); AssertRC(rc2); char szAttribs[32]; if (fAttributes != NVRAM_DEFAULT_ATTRIB) RTStrPrintf(szAttribs, sizeof(szAttribs), "%#x", fAttributes); else szAttribs[0] = '\0'; char *pszValue = drvNvram_binaryToCfgmString(pbValue, cbValue); if (pszValue) { const char *apszTodo[] = { "Name", pszName, "Uuid", szUuid, "Value", pszValue, "Attribs", szAttribs, }; for (unsigned i = 0; i < RT_ELEMENTS(apszTodo); i += 2) { if (!apszTodo[i + 1][0]) continue; Assert(strlen(apszTodo[i]) < 16); strcpy(szExtraName + offValueNm, apszTodo[i]); try { HRESULT hrc = pThis->pNvram->getParent()->i_machine()->SetExtraData(Bstr(szExtraName).raw(), Bstr(apszTodo[i + 1]).raw()); if (FAILED(hrc)) { LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) returned %Rhrc\n", szExtraName, apszTodo[i + 1], hrc)); rc = Global::vboxStatusCodeFromCOM(hrc); } } catch (...) { LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) threw exception\n", szExtraName, apszTodo[i + 1])); rc = VERR_UNEXPECTED_EXCEPTION; } } } else rc = VERR_NO_MEMORY; RTMemFree(pszValue); } NOREF(cchName); LogFlowFuncLeaveRC(rc); return rc; }
HRESULT HostNetworkInterface::eraseAdapterConfigParameter(const char *szParamName) { AssertReturn(mVirtualBox != NULL, E_POINTER); return mVirtualBox->SetExtraData(Bstr(Utf8StrFmt("HostOnly/{%RTuuid}/%s", mGuid, szParamName)).raw(), NULL); }
int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list) { int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { Log(("NetIfList: socket() -> %d\n", errno)); return NULL; } struct ifaddrs *IfAddrs, *pAddr; int rc = getifaddrs(&IfAddrs); if (rc) { close(sock); Log(("NetIfList: getifaddrs() -> %d\n", rc)); return VERR_INTERNAL_ERROR; } PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers(); while (pEtherNICs) { size_t cbNameLen = strlen(pEtherNICs->szName) + 1; PNETIFINFO pNew = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen])); pNew->MACAddress = pEtherNICs->Mac; pNew->enmMediumType = NETIF_T_ETHERNET; pNew->Uuid = pEtherNICs->Uuid; Assert(sizeof(pNew->szShortName) > sizeof(pEtherNICs->szBSDName)); memcpy(pNew->szShortName, pEtherNICs->szBSDName, sizeof(pEtherNICs->szBSDName)); pNew->szShortName[sizeof(pEtherNICs->szBSDName)] = '\0'; memcpy(pNew->szName, pEtherNICs->szName, cbNameLen); struct ifreq IfReq; RTStrCopy(IfReq.ifr_name, sizeof(IfReq.ifr_name), pNew->szShortName); if (ioctl(sock, SIOCGIFFLAGS, &IfReq) < 0) { Log(("NetIfList: ioctl(SIOCGIFFLAGS) -> %d\n", errno)); pNew->enmStatus = NETIF_S_UNKNOWN; } else pNew->enmStatus = (IfReq.ifr_flags & IFF_UP) ? NETIF_S_UP : NETIF_S_DOWN; for (pAddr = IfAddrs; pAddr != NULL; pAddr = pAddr->ifa_next) { if (strcmp(pNew->szShortName, pAddr->ifa_name)) continue; struct sockaddr_in *pIPAddr, *pIPNetMask; struct sockaddr_in6 *pIPv6Addr, *pIPv6NetMask; switch (pAddr->ifa_addr->sa_family) { case AF_INET: if (pNew->IPAddress.u) break; pIPAddr = (struct sockaddr_in *)pAddr->ifa_addr; Assert(sizeof(pNew->IPAddress) == sizeof(pIPAddr->sin_addr)); pNew->IPAddress.u = pIPAddr->sin_addr.s_addr; pIPNetMask = (struct sockaddr_in *)pAddr->ifa_netmask; Assert(pIPNetMask->sin_family == AF_INET); Assert(sizeof(pNew->IPNetMask) == sizeof(pIPNetMask->sin_addr)); pNew->IPNetMask.u = pIPNetMask->sin_addr.s_addr; break; case AF_INET6: if (pNew->IPv6Address.s.Lo || pNew->IPv6Address.s.Hi) break; pIPv6Addr = (struct sockaddr_in6 *)pAddr->ifa_addr; Assert(sizeof(pNew->IPv6Address) == sizeof(pIPv6Addr->sin6_addr)); memcpy(pNew->IPv6Address.au8, pIPv6Addr->sin6_addr.__u6_addr.__u6_addr8, sizeof(pNew->IPv6Address)); pIPv6NetMask = (struct sockaddr_in6 *)pAddr->ifa_netmask; Assert(pIPv6NetMask->sin6_family == AF_INET6); Assert(sizeof(pNew->IPv6NetMask) == sizeof(pIPv6NetMask->sin6_addr)); memcpy(pNew->IPv6NetMask.au8, pIPv6NetMask->sin6_addr.__u6_addr.__u6_addr8, sizeof(pNew->IPv6NetMask)); break; } } ComObjPtr<HostNetworkInterface> IfObj; IfObj.createObject(); if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), HostNetworkInterfaceType_Bridged, pNew))) list.push_back(IfObj); RTMemFree(pNew); /* next, free current */ void *pvFree = pEtherNICs; pEtherNICs = pEtherNICs->pNext; RTMemFree(pvFree); } freeifaddrs(IfAddrs); close(sock); return VINF_SUCCESS; }
void ErrorInfo::init(bool aKeepObj /* = false */) { HRESULT rc = E_FAIL; #if !defined(VBOX_WITH_XPCOM) ComPtr<IErrorInfo> err; rc = ::GetErrorInfo(0, err.asOutParam()); if (rc == S_OK && err) { if (aKeepObj) mErrorInfo = err; ComPtr<IVirtualBoxErrorInfo> info; rc = err.queryInterfaceTo(info.asOutParam()); if (SUCCEEDED(rc) && info) init(info); if (!mIsFullAvailable) { bool gotSomething = false; rc = err->GetGUID(mInterfaceID.asOutParam()); gotSomething |= SUCCEEDED(rc); if (SUCCEEDED(rc)) GetInterfaceNameByIID(mInterfaceID.ref(), mInterfaceName.asOutParam()); rc = err->GetSource(mComponent.asOutParam()); gotSomething |= SUCCEEDED(rc); rc = err->GetDescription(mText.asOutParam()); gotSomething |= SUCCEEDED(rc); if (gotSomething) mIsBasicAvailable = true; AssertMsg(gotSomething, ("Nothing to fetch!\n")); } } #else // defined(VBOX_WITH_XPCOM) nsCOMPtr<nsIExceptionService> es; es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc); if (NS_SUCCEEDED(rc)) { nsCOMPtr<nsIExceptionManager> em; rc = es->GetCurrentExceptionManager(getter_AddRefs(em)); if (NS_SUCCEEDED(rc)) { ComPtr<nsIException> ex; rc = em->GetCurrentException(ex.asOutParam()); if (NS_SUCCEEDED(rc) && ex) { if (aKeepObj) mErrorInfo = ex; ComPtr<IVirtualBoxErrorInfo> info; rc = ex.queryInterfaceTo(info.asOutParam()); if (NS_SUCCEEDED(rc) && info) init(info); if (!mIsFullAvailable) { bool gotSomething = false; rc = ex->GetResult(&mResultCode); gotSomething |= NS_SUCCEEDED(rc); char *pszMsg; rc = ex->GetMessage(&pszMsg); gotSomething |= NS_SUCCEEDED(rc); if (NS_SUCCEEDED(rc)) { mText = Bstr(pszMsg); nsMemory::Free(pszMsg); } if (gotSomething) mIsBasicAvailable = true; AssertMsg(gotSomething, ("Nothing to fetch!\n")); } // set the exception to NULL (to emulate Win32 behavior) em->SetCurrentException(NULL); rc = NS_OK; } } } /* Ignore failure when called after nsComponentManagerImpl::Shutdown(). */ else if (rc == NS_ERROR_UNEXPECTED) rc = NS_OK; AssertComRC(rc); #endif // defined(VBOX_WITH_XPCOM) }
Bstr Operation::deencrypt() { //TODO return Bstr(NULL, 0); }
int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list) { int rc = VINF_SUCCESS; size_t cbNeeded; char *pBuf, *pNext; int aiMib[6]; unsigned short u16DefaultIface = 0; /* initialized to shut up gcc */ /* Get the index of the interface associated with default route. */ rc = getDefaultIfaceIndex(&u16DefaultIface); if (RT_FAILURE(rc)) return rc; aiMib[0] = CTL_NET; aiMib[1] = PF_ROUTE; aiMib[2] = 0; aiMib[3] = 0; /* address family */ aiMib[4] = NET_RT_IFLIST; aiMib[5] = 0; if (sysctl(aiMib, 6, NULL, &cbNeeded, NULL, 0) < 0) { Log(("NetIfList: Failed to get estimate for list size (errno=%d).\n", errno)); return RTErrConvertFromErrno(errno); } if ((pBuf = (char*)RTMemAlloc(cbNeeded)) == NULL) return VERR_NO_MEMORY; if (sysctl(aiMib, 6, pBuf, &cbNeeded, NULL, 0) < 0) { RTMemFree(pBuf); Log(("NetIfList: Failed to retrieve interface table (errno=%d).\n", errno)); return RTErrConvertFromErrno(errno); } int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { RTMemFree(pBuf); Log(("NetIfList: socket() -> %d\n", errno)); return RTErrConvertFromErrno(errno); } PDARWINETHERNIC pNIC; PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers(); char *pEnd = pBuf + cbNeeded; for (pNext = pBuf; pNext < pEnd;) { struct if_msghdr *pIfMsg = (struct if_msghdr *)pNext; if (pIfMsg->ifm_type != RTM_IFINFO) { Log(("NetIfList: Got message %u while expecting %u.\n", pIfMsg->ifm_type, RTM_IFINFO)); rc = VERR_INTERNAL_ERROR; break; } struct sockaddr_dl *pSdl = (struct sockaddr_dl *)(pIfMsg + 1); size_t cbNameLen = pSdl->sdl_nlen + 1; Assert(pSdl->sdl_nlen < sizeof(pNIC->szBSDName)); for (pNIC = pEtherNICs; pNIC; pNIC = pNIC->pNext) if ( !strncmp(pSdl->sdl_data, pNIC->szBSDName, pSdl->sdl_nlen) && pNIC->szBSDName[pSdl->sdl_nlen] == '\0') { cbNameLen = strlen(pNIC->szName) + 1; break; } PNETIFINFO pNew = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen])); if (!pNew) { rc = VERR_NO_MEMORY; break; } memcpy(pNew->MACAddress.au8, LLADDR(pSdl), sizeof(pNew->MACAddress.au8)); pNew->enmMediumType = NETIF_T_ETHERNET; Assert(sizeof(pNew->szShortName) > pSdl->sdl_nlen); memcpy(pNew->szShortName, pSdl->sdl_data, RT_MIN(pSdl->sdl_nlen, sizeof(pNew->szShortName) - 1)); /* * If we found the adapter in the list returned by * DarwinGetEthernetControllers() copy the name and UUID from there. */ if (pNIC) { memcpy(pNew->szName, pNIC->szName, cbNameLen); pNew->Uuid = pNIC->Uuid; } else { memcpy(pNew->szName, pSdl->sdl_data, pSdl->sdl_nlen); /* Generate UUID from name and MAC address. */ RTUUID uuid; RTUuidClear(&uuid); memcpy(&uuid, pNew->szShortName, RT_MIN(cbNameLen, sizeof(uuid))); uuid.Gen.u8ClockSeqHiAndReserved = (uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; uuid.Gen.u16TimeHiAndVersion = (uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; memcpy(uuid.Gen.au8Node, pNew->MACAddress.au8, sizeof(uuid.Gen.au8Node)); pNew->Uuid = uuid; } pNext += pIfMsg->ifm_msglen; while (pNext < pEnd) { struct ifa_msghdr *pIfAddrMsg = (struct ifa_msghdr *)pNext; if (pIfAddrMsg->ifam_type != RTM_NEWADDR) break; extractAddressesToNetInfo(pIfAddrMsg->ifam_addrs, (char *)(pIfAddrMsg + 1), pIfAddrMsg->ifam_msglen + (char *)pIfAddrMsg, pNew); pNext += pIfAddrMsg->ifam_msglen; } if (pSdl->sdl_type == IFT_ETHER) { struct ifreq IfReq; RTStrCopy(IfReq.ifr_name, sizeof(IfReq.ifr_name), pNew->szShortName); if (ioctl(sock, SIOCGIFFLAGS, &IfReq) < 0) { Log(("NetIfList: ioctl(SIOCGIFFLAGS) -> %d\n", errno)); pNew->enmStatus = NETIF_S_UNKNOWN; } else pNew->enmStatus = (IfReq.ifr_flags & IFF_UP) ? NETIF_S_UP : NETIF_S_DOWN; HostNetworkInterfaceType_T enmType; if (strncmp(pNew->szName, RT_STR_TUPLE("vboxnet"))) enmType = HostNetworkInterfaceType_Bridged; else enmType = HostNetworkInterfaceType_HostOnly; ComObjPtr<HostNetworkInterface> IfObj; IfObj.createObject(); if (SUCCEEDED(IfObj->init(Bstr(pNew->szName), enmType, pNew))) { /* Make sure the default interface gets to the beginning. */ if (pIfMsg->ifm_index == u16DefaultIface) list.push_front(IfObj); else list.push_back(IfObj); } } RTMemFree(pNew); } for (pNIC = pEtherNICs; pNIC;) { void *pvFree = pNIC; pNIC = pNIC->pNext; RTMemFree(pvFree); } close(sock); RTMemFree(pBuf); return rc; }
Bstr Operation::deencrypt() { // to be implemented... return Bstr(NULL, 0); }
HRESULT HostNetworkInterface::enableStaticIPConfigV6(const com::Utf8Str &aIPV6Address, ULONG aIPV6NetworkMaskPrefixLength) { #ifndef VBOX_WITH_HOSTNETIF_API return E_NOTIMPL; #else if (aIPV6NetworkMaskPrefixLength > 128) return mVirtualBox->setErrorBoth(E_INVALIDARG, VERR_INVALID_PARAMETER, "Invalid IPv6 prefix length"); int rc; RTNETADDRIPV6 AddrOld, AddrNew; char *pszZoneIgnored; bool fAddrChanged; rc = RTNetStrToIPv6Addr(aIPV6Address.c_str(), &AddrNew, &pszZoneIgnored); if (RT_FAILURE(rc)) { return mVirtualBox->setErrorBoth(E_INVALIDARG, rc, "Invalid IPv6 address"); } rc = RTNetStrToIPv6Addr(com::Utf8Str(m.realIPV6Address).c_str(), &AddrOld, &pszZoneIgnored); if (RT_SUCCESS(rc)) { fAddrChanged = (AddrNew.s.Lo != AddrOld.s.Lo || AddrNew.s.Hi != AddrOld.s.Hi); } else { fAddrChanged = true; } if ( fAddrChanged || m.realIPV6PrefixLength != aIPV6NetworkMaskPrefixLength) { if (aIPV6NetworkMaskPrefixLength == 0) aIPV6NetworkMaskPrefixLength = 64; rc = NetIfEnableStaticIpConfigV6(mVirtualBox, this, m.IPV6Address.c_str(), aIPV6Address.c_str(), aIPV6NetworkMaskPrefixLength); if (RT_FAILURE(rc)) { LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc)); return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL; } else { m.realIPV6Address = aIPV6Address; m.realIPV6PrefixLength = aIPV6NetworkMaskPrefixLength; #if defined(RT_OS_WINDOWS) saveAdapterConfigIPv6(Bstr(aIPV6Address).raw(), aIPV6NetworkMaskPrefixLength); #else /* !defined(RT_OS_WINDOWS) */ if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6Address", mInterfaceName.c_str()).raw(), Bstr(aIPV6Address).raw()))) return E_FAIL; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", mInterfaceName.c_str()).raw(), BstrFmt("%u", aIPV6NetworkMaskPrefixLength).raw()))) #endif /* !defined(RT_OS_WINDOWS) */ return E_FAIL; } } return S_OK; #endif }
/** * Creates a TCP server that listens for the source machine and passes control * over to Console::teleporterTrgServeConnection(). * * @returns VBox status code. * @param pUVM The user-mode VM handle * @param pMachine The IMachine for the virtual machine. * @param pErrorMsg Pointer to the error string for VMSetError. * @param fStartPaused Whether to start it in the Paused (true) or * Running (false) state, * @param pProgress Pointer to the progress object. * @param pfPowerOffOnFailure Whether the caller should power off * the VM on failure. * * @remarks The caller expects error information to be set on failure. * @todo Check that all the possible failure paths sets error info... */ HRESULT Console::teleporterTrg(PUVM pUVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused, Progress *pProgress, bool *pfPowerOffOnFailure) { LogThisFunc(("pUVM=%p pMachine=%p fStartPaused=%RTbool pProgress=%p\n", pUVM, pMachine, fStartPaused, pProgress)); *pfPowerOffOnFailure = true; /* * Get the config. */ ULONG uPort; HRESULT hrc = pMachine->COMGETTER(TeleporterPort)(&uPort); if (FAILED(hrc)) return hrc; ULONG const uPortOrg = uPort; Bstr bstrAddress; hrc = pMachine->COMGETTER(TeleporterAddress)(bstrAddress.asOutParam()); if (FAILED(hrc)) return hrc; Utf8Str strAddress(bstrAddress); const char *pszAddress = strAddress.isEmpty() ? NULL : strAddress.c_str(); Bstr bstrPassword; hrc = pMachine->COMGETTER(TeleporterPassword)(bstrPassword.asOutParam()); if (FAILED(hrc)) return hrc; Utf8Str strPassword(bstrPassword); strPassword.append('\n'); /* To simplify password checking. */ /* * Create the TCP server. */ int vrc; PRTTCPSERVER hServer; if (uPort) vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer); else { for (int cTries = 10240; cTries > 0; cTries--) { uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534); vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer); if (vrc != VERR_NET_ADDRESS_IN_USE) break; } if (RT_SUCCESS(vrc)) { hrc = pMachine->COMSETTER(TeleporterPort)(uPort); if (FAILED(hrc)) { RTTcpServerDestroy(hServer); return hrc; } } } if (RT_FAILURE(vrc)) return setError(E_FAIL, tr("RTTcpServerCreateEx failed with status %Rrc"), vrc); /* * Create a one-shot timer for timing out after 5 mins. */ RTTIMERLR hTimerLR; vrc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, teleporterDstTimeout, hServer); if (RT_SUCCESS(vrc)) { vrc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/); if (RT_SUCCESS(vrc)) { /* * Do the job, when it returns we're done. */ TeleporterStateTrg theState(this, pUVM, pProgress, pMachine, mControl, &hTimerLR, fStartPaused); theState.mstrPassword = strPassword; theState.mhServer = hServer; void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(&theState)); if (pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser)) { LogRel(("Teleporter: Waiting for incoming VM...\n")); hrc = pProgress->SetNextOperation(Bstr(tr("Waiting for incoming VM")).raw(), 1); if (SUCCEEDED(hrc)) { vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &theState); pProgress->setCancelCallback(NULL, NULL); if (vrc == VERR_TCP_SERVER_STOP) { vrc = theState.mRc; /* Power off the VM on failure unless the state callback already did that. */ *pfPowerOffOnFailure = false; if (RT_SUCCESS(vrc)) hrc = S_OK; else { VMSTATE enmVMState = VMR3GetStateU(pUVM); if ( enmVMState != VMSTATE_OFF && enmVMState != VMSTATE_POWERING_OFF) *pfPowerOffOnFailure = true; /* Set error. */ if (pErrorMsg->length()) hrc = setError(E_FAIL, "%s", pErrorMsg->c_str()); else hrc = setError(E_FAIL, tr("Teleporation failed (%Rrc)"), vrc); } } else if (vrc == VERR_TCP_SERVER_SHUTDOWN) { BOOL fCanceled = TRUE; hrc = pProgress->COMGETTER(Canceled)(&fCanceled); if (FAILED(hrc) || fCanceled) hrc = setError(E_FAIL, tr("Teleporting canceled")); else hrc = setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection")); LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc)); } else { hrc = setError(E_FAIL, tr("Unexpected RTTcpServerListen status code %Rrc"), vrc); LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc)); } } else LogThisFunc(("SetNextOperation failed, %Rhrc\n", hrc)); } else { LogThisFunc(("Canceled - check point #1\n")); hrc = setError(E_FAIL, tr("Teleporting canceled")); } } else hrc = setError(E_FAIL, "RTTimerLRStart -> %Rrc", vrc); RTTimerLRDestroy(hTimerLR); } else hrc = setError(E_FAIL, "RTTimerLRCreate -> %Rrc", vrc); RTTcpServerDestroy(hServer); /* * If we change TeleporterPort above, set it back to it's original * value before returning. */ if (uPortOrg != uPort) { ErrorInfoKeeper Eik; pMachine->COMSETTER(TeleporterPort)(uPortOrg); } return hrc; }
int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, const char *pcszName) { #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) /* create a progress object */ ComObjPtr<Progress> progress; progress.createObject(); ComPtr<IHost> host; HRESULT hrc = pVirtualBox->COMGETTER(Host)(host.asOutParam()); if (SUCCEEDED(hrc)) { hrc = progress->init(pVirtualBox, host, Bstr("Creating host only network interface").raw(), FALSE /* aCancelable */); if (SUCCEEDED(hrc)) { progress.queryInterfaceTo(aProgress); char szAdpCtl[RTPATH_MAX]; int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add")); if (RT_FAILURE(rc)) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to get program path, rc=%Rrc\n", rc); return rc; } strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " "); if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - sizeof(" add")) { strcat(szAdpCtl, pcszName); strcat(szAdpCtl, " add"); } else strcat(szAdpCtl, "add"); if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1")) strcat(szAdpCtl, " 2>&1"); FILE *fp = popen(szAdpCtl, "r"); if (fp) { char szBuf[128]; /* We are not interested in long error messages. */ if (fgets(szBuf, sizeof(szBuf), fp)) { /* Remove trailing new line characters. */ char *pLast = szBuf + strlen(szBuf) - 1; if (pLast >= szBuf && *pLast == '\n') *pLast = 0; if (!strncmp(VBOXNETADPCTL_NAME ":", szBuf, sizeof(VBOXNETADPCTL_NAME))) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "%s", szBuf); pclose(fp); return E_FAIL; } size_t cbNameLen = strlen(szBuf) + 1; PNETIFINFO pInfo = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen])); if (!pInfo) rc = VERR_NO_MEMORY; else { strcpy(pInfo->szShortName, szBuf); strcpy(pInfo->szName, szBuf); rc = NetIfGetConfigByName(pInfo); if (RT_FAILURE(rc)) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to get config info for %s (as reported by '" VBOXNETADPCTL_NAME " add')\n", szBuf); } else { Bstr IfName(szBuf); /* create a new uninitialized host interface object */ ComObjPtr<HostNetworkInterface> iface; iface.createObject(); iface->init(IfName, HostNetworkInterfaceType_HostOnly, pInfo); iface->i_setVirtualBox(pVirtualBox); iface.queryInterfaceTo(aHostNetworkInterface); } RTMemFree(pInfo); } if ((rc = pclose(fp)) != 0) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME " add' (exit status: %d)", rc); rc = VERR_INTERNAL_ERROR; } } else { /* Failed to add an interface */ rc = VERR_PERMISSION_DENIED; progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME " add' (exit status: %d). Check permissions!", rc); pclose(fp); } } if (RT_SUCCESS(rc)) progress->i_notifyComplete(rc); else hrc = E_FAIL; } } return hrc; #else NOREF(pVirtualBox); NOREF(aHostNetworkInterface); NOREF(aProgress); NOREF(pcszName); return VERR_NOT_IMPLEMENTED; #endif }
HRESULT Guest::taskCopyFileToGuest(GuestTask *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* * Do *not* take a write lock here since we don't (and won't) * touch any class-specific data (of IGuest) here - only the member functions * which get called here can do that. */ HRESULT rc = S_OK; try { ComObjPtr<Guest> pGuest = aTask->pGuest; /* Does our source file exist? */ if (!RTFileExists(aTask->strSource.c_str())) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Source file \"%s\" does not exist, or is not a file"), aTask->strSource.c_str()); } else { RTFILE fileSource; int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"), aTask->strSource.c_str(), vrc); } else { uint64_t cbSize; vrc = RTFileGetSize(fileSource, &cbSize); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not query file size of \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); } else { com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; /* * Prepare tool command line. */ char szOutput[RTPATH_MAX]; if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1) { /* * Normalize path slashes, based on the detected guest. */ Utf8Str osType = mData.mOSTypeId; if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) || osType.contains("Windows", Utf8Str::CaseInsensitive)) { /* We have a Windows guest. */ RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */); } else /* ... or something which isn't from Redmond ... */ { RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */); } args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */ } else { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error preparing command line")); } ComPtr<IProgress> execProgress; ULONG uPID; if (SUCCEEDED(rc)) { LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n", aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize)); /* * Okay, since we gathered all stuff we need until now to start the * actual copying, start the guest part now. */ rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(), Bstr("Copying file to guest").raw(), ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), ExecuteProcessFlag_WaitForProcessStartOnly, NULL, NULL, execProgress.asOutParam(), &uPID); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } if (SUCCEEDED(rc)) { BOOL fCompleted = FALSE; BOOL fCanceled = FALSE; uint64_t cbTransferedTotal = 0; SafeArray<BYTE> aInputData(_64K); while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { size_t cbToRead = cbSize; size_t cbRead = 0; if (cbSize) /* If we have nothing to read, take a shortcut. */ { /** @todo Not very efficient, but works for now. */ vrc = RTFileSeek(fileSource, cbTransferedTotal, RTFILE_SEEK_BEGIN, NULL /* poffActual */); if (RT_SUCCESS(vrc)) { vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), RT_MIN(cbToRead, _64K), &cbRead); /* * Some other error occured? There might be a chance that RTFileRead * could not resolve/map the native error code to an IPRT code, so just * print a generic error. */ if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not read from file \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); break; } } else { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Seeking file \"%s\" failed; offset = %RU64 (%Rrc)"), aTask->strSource.c_str(), cbTransferedTotal, vrc); break; } } /* Resize buffer to reflect amount we just have read. * Size 0 is allowed! */ aInputData.resize(cbRead); ULONG uFlags = ProcessInputFlag_None; /* Did we reach the end of the content we want to transfer (last chunk)? */ if ( (cbRead < _64K) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { uFlags |= ProcessInputFlag_EndOfFile; } ULONG uBytesWritten = 0; rc = pGuest->SetProcessInput(uPID, uFlags, 0 /* Infinite timeout */, ComSafeArrayAsInParam(aInputData), &uBytesWritten); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } Assert(cbRead <= cbToRead); Assert(cbToRead >= cbRead); cbToRead -= cbRead; cbTransferedTotal += uBytesWritten; Assert(cbTransferedTotal <= cbSize); aTask->pProgress->SetCurrentOperationProgress(cbTransferedTotal / (cbSize / 100.0)); /* End of file reached? */ if (cbToRead == 0) break; /* Did the user cancel the operation above? */ if (fCanceled) break; /* Progress canceled by Main API? */ if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copy operation of file \"%s\" was canceled on guest side"), aTask->strSource.c_str()); break; } } if (SUCCEEDED(rc)) { /* * If we got here this means the started process either was completed, * canceled or we simply got all stuff transferred. */ ExecuteProcessStatus_T retStatus; ULONG uRetExitCode; rc = executeWaitForExit(uPID, execProgress, 0 /* No timeout */, &retStatus, &uRetExitCode); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } else { if ( uRetExitCode != 0 || retStatus != ExecuteProcessStatus_TerminatedNormally) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest process reported error %u (status: %u) while copying file \"%s\" to \"%s\""), uRetExitCode, retStatus, aTask->strSource.c_str(), aTask->strDest.c_str()); } } } if (SUCCEEDED(rc)) { if (fCanceled) { /* * In order to make the progress object to behave nicely, we also have to * notify the object with a complete event when it's canceled. */ aTask->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest), Guest::getStaticComponentName(), Guest::tr("Copying file \"%s\" canceled"), aTask->strSource.c_str()); } else { /* * Even if we succeeded until here make sure to check whether we really transfered * everything. */ if ( cbSize > 0 && cbTransferedTotal == 0) { /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write * to the destination -> access denied. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Access denied when copying file \"%s\" to \"%s\""), aTask->strSource.c_str(), aTask->strDest.c_str()); } else if (cbTransferedTotal < cbSize) { /* If we did not copy all let the user know. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"), aTask->strSource.c_str(), cbTransferedTotal, cbSize); } else /* Yay, all went fine! */ aTask->pProgress->notifyComplete(S_OK); } } } } RTFileClose(fileSource); } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
Console::teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser) { TeleporterStateTrg *pState = (TeleporterStateTrg *)pvUser; pState->mhSocket = Sock; /* * Disable Nagle and say hello. */ int vrc = RTTcpSetSendCoalescing(pState->mhSocket, false /*fEnable*/); AssertRC(vrc); vrc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1); if (RT_FAILURE(vrc)) { LogRel(("Teleporter: Failed to write welcome message: %Rrc\n", vrc)); return VINF_SUCCESS; } /* * Password (includes '\n', see teleporterTrg). */ const char *pszPassword = pState->mstrPassword.c_str(); unsigned off = 0; while (pszPassword[off]) { char ch; vrc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); if ( RT_FAILURE(vrc) || pszPassword[off] != ch) { if (RT_FAILURE(vrc)) LogRel(("Teleporter: Password read failure (off=%u): %Rrc\n", off, vrc)); else LogRel(("Teleporter: Invalid password (off=%u)\n", off)); teleporterTcpWriteNACK(pState, VERR_AUTHENTICATION_FAILURE); return VINF_SUCCESS; } off++; } vrc = teleporterTcpWriteACK(pState); if (RT_FAILURE(vrc)) return VINF_SUCCESS; /* * Update the progress bar, with peer name if available. */ HRESULT hrc; RTNETADDR Addr; vrc = RTTcpGetPeerAddress(Sock, &Addr); if (RT_SUCCESS(vrc)) { LogRel(("Teleporter: Incoming VM from %RTnaddr!\n", &Addr)); hrc = pState->mptrProgress->SetNextOperation(BstrFmt(tr("Teleporting VM from %RTnaddr"), &Addr).raw(), 8); } else { LogRel(("Teleporter: Incoming VM!\n")); hrc = pState->mptrProgress->SetNextOperation(Bstr(tr("Teleporting VM")).raw(), 8); } AssertMsg(SUCCEEDED(hrc) || hrc == E_FAIL, ("%Rhrc\n", hrc)); /* * Stop the server and cancel the timeout timer. * * Note! After this point we must return VERR_TCP_SERVER_STOP, while prior * to it we must not return that value! */ RTTcpServerShutdown(pState->mhServer); RTTimerLRDestroy(*pState->mphTimerLR); *pState->mphTimerLR = NIL_RTTIMERLR; /* * Command processing loop. */ bool fDone = false; for (;;) { char szCmd[128]; vrc = teleporterTcpReadLine(pState, szCmd, sizeof(szCmd)); if (RT_FAILURE(vrc)) break; if (!strcmp(szCmd, "load")) { vrc = teleporterTcpWriteACK(pState); if (RT_FAILURE(vrc)) break; int vrc2 = VMR3AtErrorRegisterU(pState->mpUVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2); RTSocketRetain(pState->mhSocket); /* For concurrent access by I/O thread and EMT. */ pState->moffStream = 0; void *pvUser2 = static_cast<void *>(static_cast<TeleporterState *>(pState)); vrc = VMR3LoadFromStream(VMR3GetVM(pState->mpUVM), &g_teleporterTcpOps, pvUser2, teleporterProgressCallback, pvUser2); RTSocketRelease(pState->mhSocket); vrc2 = VMR3AtErrorDeregister(VMR3GetVM(pState->mpUVM), Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2); if (RT_FAILURE(vrc)) { LogRel(("Teleporter: VMR3LoadFromStream -> %Rrc\n", vrc)); teleporterTcpWriteNACK(pState, vrc, pState->mErrorText.c_str()); break; } /* The EOS might not have been read, make sure it is. */ pState->mfStopReading = false; size_t cbRead; vrc = teleporterTcpOpRead(pvUser2, pState->moffStream, szCmd, 1, &cbRead); if (vrc != VERR_EOF) { LogRel(("Teleporter: Draining teleporterTcpOpRead -> %Rrc\n", vrc)); teleporterTcpWriteNACK(pState, vrc); break; } vrc = teleporterTcpWriteACK(pState); } else if (!strcmp(szCmd, "cancel")) { /* Don't ACK this. */ LogRel(("Teleporter: Received cancel command.\n")); vrc = VERR_SSM_CANCELLED; } else if (!strcmp(szCmd, "lock-media")) { hrc = pState->mpControl->LockMedia(); if (SUCCEEDED(hrc)) { pState->mfLockedMedia = true; vrc = teleporterTcpWriteACK(pState); } else { vrc = VERR_FILE_LOCK_FAILED; teleporterTcpWriteNACK(pState, vrc); } } else if ( !strcmp(szCmd, "hand-over-resume") || !strcmp(szCmd, "hand-over-paused")) { /* * Point of no return. * * Note! Since we cannot tell whether a VMR3Resume failure is * destructive for the source or not, we have little choice * but to ACK it first and take any failures locally. * * Ideally, we should try resume it first and then ACK (or * NACK) the request since this would reduce latency and * make it possible to recover from some VMR3Resume failures. */ if ( pState->mptrProgress->notifyPointOfNoReturn() && pState->mfLockedMedia) { vrc = teleporterTcpWriteACK(pState); if (RT_SUCCESS(vrc)) { if (!strcmp(szCmd, "hand-over-resume")) vrc = VMR3Resume(VMR3GetVM(pState->mpUVM)); else pState->mptrConsole->setMachineState(MachineState_Paused); fDone = true; break; } } else { vrc = pState->mfLockedMedia ? VERR_WRONG_ORDER : VERR_SSM_CANCELLED; teleporterTcpWriteNACK(pState, vrc); } } else { LogRel(("Teleporter: Unknown command '%s' (%.*Rhxs)\n", szCmd, strlen(szCmd), szCmd)); vrc = VERR_NOT_IMPLEMENTED; teleporterTcpWriteNACK(pState, vrc); } if (RT_FAILURE(vrc)) break; } if (RT_SUCCESS(vrc) && !fDone) vrc = VERR_WRONG_ORDER; if (RT_FAILURE(vrc)) teleporterTrgUnlockMedia(pState); pState->mRc = vrc; pState->mhSocket = NIL_RTSOCKET; LogFlowFunc(("returns mRc=%Rrc\n", vrc)); return VERR_TCP_SERVER_STOP; }
/** * Start teleporter to the specified target. * * @returns COM status code. * * @param aHostname The name of the target host. * @param aPort The TCP port number. * @param aPassword The password. * @param aMaxDowntime Max allowed "downtime" in milliseconds. * @param aProgress Where to return the progress object. */ STDMETHODIMP Console::Teleport(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, ULONG aMaxDowntime, IProgress **aProgress) { /* * Validate parameters, check+hold object status, write lock the object * and validate the state. */ CheckComArgOutPointerValid(aProgress); CheckComArgStrNotEmptyOrNull(aHostname); CheckComArgStrNotEmptyOrNull(aPassword); CheckComArgExprMsg(aPort, aPort > 0 && aPort <= 65535, ("is %u", aPort)); CheckComArgExprMsg(aMaxDowntime, aMaxDowntime > 0, ("is %u", aMaxDowntime)); Utf8Str strPassword(aPassword); if (!strPassword.isEmpty()) { if (VBoxIsPasswordHashed(&strPassword)) return setError(E_INVALIDARG, tr("The specified password resembles a hashed password, expected plain text")); VBoxHashPassword(&strPassword); } AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS); LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); switch (mMachineState) { case MachineState_Running: case MachineState_Paused: break; default: return setError(VBOX_E_INVALID_VM_STATE, tr("Invalid machine state: %s (must be Running or Paused)"), Global::stringifyMachineState(mMachineState)); } /* * Create a progress object, spawn a worker thread and change the state. * Note! The thread won't start working until we release the lock. */ LogFlowThisFunc(("Initiating TELEPORT request...\n")); ComObjPtr<Progress> ptrProgress; HRESULT hrc = ptrProgress.createObject(); if (SUCCEEDED(hrc)) hrc = ptrProgress->init(static_cast<IConsole *>(this), Bstr(tr("Teleporter")).raw(), TRUE /*aCancelable*/); if (FAILED(hrc)) return hrc; TeleporterStateSrc *pState = new TeleporterStateSrc(this, mpUVM, ptrProgress, mMachineState); pState->mstrPassword = strPassword; pState->mstrHostname = aHostname; pState->muPort = aPort; pState->mcMsMaxDowntime = aMaxDowntime; void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(pState)); ptrProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser); int vrc = RTThreadCreate(NULL, Console::teleporterSrcThreadWrapper, (void *)pState, 0 /*cbStack*/, RTTHREADTYPE_EMULATION, 0 /*fFlags*/, "Teleport"); if (RT_SUCCESS(vrc)) { if (mMachineState == MachineState_Running) hrc = setMachineState(MachineState_Teleporting); else hrc = setMachineState(MachineState_TeleportingPausedVM); if (SUCCEEDED(hrc)) { ptrProgress.queryInterfaceTo(aProgress); mptrCancelableProgress = ptrProgress; } else ptrProgress->Cancel(); } else { ptrProgress->setCancelCallback(NULL, NULL); delete pState; hrc = setError(E_FAIL, tr("RTThreadCreate -> %Rrc"), vrc); } return hrc; }
HRESULT HostNetworkInterface::enableStaticIPConfig(const com::Utf8Str &aIPAddress, const com::Utf8Str &aNetworkMask) { #ifndef VBOX_WITH_HOSTNETIF_API return E_NOTIMPL; #else if (aIPAddress.isEmpty()) { if (m.IPAddress) { int rc = NetIfEnableStaticIpConfig(mVirtualBox, this, m.IPAddress, 0, 0); if (RT_SUCCESS(rc)) { m.realIPAddress = 0; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), NULL))) return E_FAIL; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), NULL))) return E_FAIL; return S_OK; } } else return S_OK; } ULONG ip, mask; ip = inet_addr(aIPAddress.c_str()); if (ip != INADDR_NONE) { if (aNetworkMask.isEmpty()) mask = 0xFFFFFF; else mask = inet_addr(aNetworkMask.c_str()); if (mask != INADDR_NONE) { if (m.realIPAddress == ip && m.realNetworkMask == mask) return S_OK; int rc = NetIfEnableStaticIpConfig(mVirtualBox, this, m.IPAddress, ip, mask); if (RT_SUCCESS(rc)) { m.realIPAddress = ip; m.realNetworkMask = mask; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), Bstr(aIPAddress).raw()))) return E_FAIL; if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), Bstr(aNetworkMask).raw()))) return E_FAIL; return S_OK; } else { LogRel(("Failed to EnableStaticIpConfig with rc=%Rrc\n", rc)); return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL; } } } return E_FAIL; #endif }
HRESULT Guest::taskUpdateGuestAdditions(GuestTask *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* * Do *not* take a write lock here since we don't (and won't) * touch any class-specific data (of IGuest) here - only the member functions * which get called here can do that. */ HRESULT rc = S_OK; BOOL fCompleted; BOOL fCanceled; try { ComObjPtr<Guest> pGuest = aTask->pGuest; aTask->pProgress->SetCurrentOperationProgress(10); /* * Determine guest OS type and the required installer image. * At the moment only Windows guests are supported. */ Utf8Str installerImage; Bstr osTypeId; if ( SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam()))) && !osTypeId.isEmpty()) { Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */ if ( osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive) || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive)) { if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive)) installerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE"; else installerImage = "VBOXWINDOWSADDITIONS_X86.EXE"; /* Since the installers are located in the root directory, * no further path processing needs to be done (yet). */ } else /* Everything else is not supported (yet). */ throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"), osTypeIdUtf8.c_str()); } else throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Could not detected guest OS type/version, please update manually")); Assert(!installerImage.isEmpty()); /* * Try to open the .ISO file and locate the specified installer. */ RTISOFSFILE iso; int vrc = RTIsoFsOpen(&iso, aTask->strSource.c_str()); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_FILE_ERROR, aTask->pProgress, Guest::tr("Invalid installation medium detected: \"%s\""), aTask->strSource.c_str()); } else { uint32_t cbOffset; size_t cbLength; vrc = RTIsoFsGetFileInfo(&iso, installerImage.c_str(), &cbOffset, &cbLength); if ( RT_SUCCESS(vrc) && cbOffset && cbLength) { vrc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(vrc)) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not seek to setup file on installation medium \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); } else { switch (vrc) { case VERR_FILE_NOT_FOUND: rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Setup file was not found on installation medium \"%s\""), aTask->strSource.c_str()); break; default: rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("An unknown error (%Rrc) occured while retrieving information of setup file on installation medium \"%s\""), vrc, aTask->strSource.c_str()); break; } } /* Specify the ouput path on the guest side. */ Utf8Str strInstallerPath = "%TEMP%\\VBoxWindowsAdditions.exe"; if (RT_SUCCESS(vrc)) { /* Okay, we're ready to start our copy routine on the guest! */ aTask->pProgress->SetCurrentOperationProgress(15); /* Prepare command line args. */ com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; args.push_back(Bstr("--output").raw()); /* We want to write a file ... */ args.push_back(Bstr(strInstallerPath.c_str()).raw()); /* ... with this path. */ if (SUCCEEDED(rc)) { ComPtr<IProgress> progressCat; ULONG uPID; /* * Start built-in "vbox_cat" tool (inside VBoxService) to * copy over/pipe the data into a file on the guest (with * system rights, no username/password specified). */ rc = pGuest->executeProcessInternal(Bstr(VBOXSERVICE_TOOL_CAT).raw(), ExecuteProcessFlag_Hidden | ExecuteProcessFlag_WaitForProcessStartOnly, ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr("").raw() /* Username. */, Bstr("").raw() /* Password */, 5 * 1000 /* Wait 5s for getting the process started. */, &uPID, progressCat.asOutParam(), &vrc); if (FAILED(rc)) { /* Errors which return VBOX_E_NOT_SUPPORTED can be safely skipped by the caller * to silently fall back to "normal" (old) .ISO mounting. */ /* Due to a very limited COM error range we use vrc for a more detailed error * lookup to figure out what went wrong. */ switch (vrc) { /* Guest execution service is not (yet) ready. This basically means that either VBoxService * is not running (yet) or that the Guest Additions are too old (because VBoxService does not * support the guest execution feature in this version). */ case VERR_NOT_FOUND: LogRel(("Guest Additions seem not to be installed yet\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Guest Additions seem not to be installed or are not ready to update yet")); break; /* Getting back a VERR_INVALID_PARAMETER indicates that the installed Guest Additions are supporting the guest * execution but not the built-in "vbox_cat" tool of VBoxService (< 4.0). */ case VERR_INVALID_PARAMETER: LogRel(("Guest Additions are installed but don't supported automatic updating\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Installed Guest Additions do not support automatic updating")); break; case VERR_TIMEOUT: LogRel(("Guest was unable to start copying the Guest Additions setup within time\n")); rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress, Guest::tr("Guest was unable to start copying the Guest Additions setup within time")); break; default: rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress, Guest::tr("Error copying Guest Additions setup file to guest path \"%s\" (%Rrc)"), strInstallerPath.c_str(), vrc); break; } } else { LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", aTask->strSource.c_str())); LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n", installerImage.c_str(), strInstallerPath.c_str())); aTask->pProgress->SetCurrentOperationProgress(20); /* Wait for process to exit ... */ SafeArray<BYTE> aInputData(_64K); while ( SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted))) && !fCompleted) { size_t cbRead; /* cbLength contains remaining bytes of our installer file * opened above to read. */ size_t cbToRead = RT_MIN(cbLength, _64K); if (cbToRead) { vrc = RTFileRead(iso.file, (uint8_t*)aInputData.raw(), cbToRead, &cbRead); if ( cbRead && RT_SUCCESS(vrc)) { /* Resize buffer to reflect amount we just have read. */ if (cbRead > 0) aInputData.resize(cbRead); /* Did we reach the end of the content we want to transfer (last chunk)? */ ULONG uFlags = ProcessInputFlag_None; if ( (cbRead < _64K) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { uFlags |= ProcessInputFlag_EndOfFile; } /* Transfer the current chunk ... */ #ifdef DEBUG_andy LogRel(("Copying Guest Additions (%u bytes left) ...\n", cbLength)); #endif ULONG uBytesWritten; rc = pGuest->SetProcessInput(uPID, uFlags, 10 * 1000 /* Wait 10s for getting the input data transfered. */, ComSafeArrayAsInParam(aInputData), &uBytesWritten); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } /* If task was canceled above also cancel the process execution. */ if (fCanceled) progressCat->Cancel(); #ifdef DEBUG_andy LogRel(("Copying Guest Additions (%u bytes written) ...\n", uBytesWritten)); #endif Assert(cbLength >= uBytesWritten); cbLength -= uBytesWritten; } else if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error while reading setup file \"%s\" (To read: %u, Size: %u) from installation medium (%Rrc)"), installerImage.c_str(), cbToRead, cbLength, vrc); } } /* Internal progress canceled? */ if ( SUCCEEDED(progressCat->COMGETTER(Canceled(&fCanceled))) && fCanceled) { aTask->pProgress->Cancel(); break; } } } } } RTIsoFsClose(&iso); if ( SUCCEEDED(rc) && ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && !fCanceled ) ) { /* * Installer was transferred successfully, so let's start it * (with system rights). */ LogRel(("Preparing to execute Guest Additions update ...\n")); aTask->pProgress->SetCurrentOperationProgress(66); /* Prepare command line args for installer. */ com::SafeArray<IN_BSTR> installerArgs; com::SafeArray<IN_BSTR> installerEnv; /** @todo Only Windows! */ installerArgs.push_back(Bstr(strInstallerPath).raw()); /* The actual (internal) installer image (as argv[0]). */ /* Note that starting at Windows Vista the lovely session 0 separation applies: * This means that if we run an application with the profile/security context * of VBoxService (system rights!) we're not able to show any UI. */ installerArgs.push_back(Bstr("/S").raw()); /* We want to install in silent mode. */ installerArgs.push_back(Bstr("/l").raw()); /* ... and logging enabled. */ /* Don't quit VBoxService during upgrade because it still is used for this * piece of code we're in right now (that is, here!) ... */ installerArgs.push_back(Bstr("/no_vboxservice_exit").raw()); /* Tell the installer to report its current installation status * using a running VBoxTray instance via balloon messages in the * Windows taskbar. */ installerArgs.push_back(Bstr("/post_installstatus").raw()); /* * Start the just copied over installer with system rights * in silent mode on the guest. Don't use the hidden flag since there * may be pop ups the user has to process. */ ComPtr<IProgress> progressInstaller; ULONG uPID; rc = pGuest->executeProcessInternal(Bstr(strInstallerPath).raw(), ExecuteProcessFlag_WaitForProcessStartOnly, ComSafeArrayAsInParam(installerArgs), ComSafeArrayAsInParam(installerEnv), Bstr("").raw() /* Username */, Bstr("").raw() /* Password */, 10 * 1000 /* Wait 10s for getting the process started */, &uPID, progressInstaller.asOutParam(), &vrc); if (SUCCEEDED(rc)) { LogRel(("Guest Additions update is running ...\n")); /* If the caller does not want to wait for out guest update process to end, * complete the progress object now so that the caller can do other work. */ if (aTask->uFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly) aTask->pProgress->notifyComplete(S_OK); else aTask->pProgress->SetCurrentOperationProgress(70); /* Wait until the Guest Additions installer finishes ... */ while ( SUCCEEDED(progressInstaller->COMGETTER(Completed(&fCompleted))) && !fCompleted) { if ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) { progressInstaller->Cancel(); break; } /* Progress canceled by Main API? */ if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled))) && fCanceled) { break; } RTThreadSleep(100); } ExecuteProcessStatus_T retStatus; ULONG uRetExitCode, uRetFlags; rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); if (SUCCEEDED(rc)) { if (fCompleted) { if (uRetExitCode == 0) { LogRel(("Guest Additions update successful!\n")); if ( SUCCEEDED(aTask->pProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) aTask->pProgress->notifyComplete(S_OK); } else { LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n", uRetExitCode, retStatus, uRetFlags)); rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"), uRetExitCode, retStatus, uRetFlags); } } else if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled))) && fCanceled) { LogRel(("Guest Additions update was canceled\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"), uRetExitCode, retStatus, uRetFlags); } else { LogRel(("Guest Additions update was canceled by the user\n")); } } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
/** * Initializes the USB device filter object. * * @param aParent Handle of the parent object. * @param data Reference filter settings. */ HRESULT USBDeviceFilter::init(USBDeviceFilters *aParent, const settings::USBDeviceFilter &data) { LogFlowThisFunc(("aParent=%p\n", aParent)); ComAssertRet(aParent && !data.strName.isEmpty(), E_INVALIDARG); /* Enclose the state transition NotReady->InInit->Ready */ AutoInitSpan autoInitSpan(this); AssertReturn(autoInitSpan.isOk(), E_FAIL); unconst(mParent) = aParent; /* mPeer is left null */ m_fModified = false; bd.allocate(); bd->mData.strName = data.strName; bd->mData.fActive = data.fActive; bd->mData.ulMaskedInterfaces = 0; /* initialize all filters to any match using null string */ USBFilterInit(&bd->mUSBFilter, USBFILTERTYPE_CAPTURE); bd->mRemote = NULL; mInList = false; /* use setters for the attributes below to reuse parsing errors * handling */ HRESULT rc = S_OK; do { rc = i_usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, data.strVendorId); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProductId); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_DEVICE, data.strRevision); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, data.strProduct); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber); if (FAILED(rc)) break; rc = i_usbFilterFieldSetter(USBFILTERIDX_PORT, data.strPort); if (FAILED(rc)) break; rc = COMSETTER(Remote)(Bstr(data.strRemote).raw()); if (FAILED(rc)) break; rc = COMSETTER(MaskedInterfaces)(data.ulMaskedInterfaces); if (FAILED(rc)) break; } while (0); /* Confirm successful initialization when it's the case */ if (SUCCEEDED(rc)) autoInitSpan.setSucceeded(); return rc; }
static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNetworkInterfaceList) { std::list<ComObjPtr<HostNetworkInterface> > *pList = (std::list<ComObjPtr<HostNetworkInterface> > *)pvHostNetworkInterfaceList; Assert(pList); typedef std::map <std::string, std::string> NICMap; typedef std::pair <std::string, std::string> NICPair; static NICMap SolarisNICMap; if (SolarisNICMap.empty()) { SolarisNICMap.insert(NICPair("afe", "ADMtek Centaur/Comet Fast Ethernet")); SolarisNICMap.insert(NICPair("atge", "Atheros/Attansic Gigabit Ethernet")); SolarisNICMap.insert(NICPair("aggr", "Link Aggregation Interface")); SolarisNICMap.insert(NICPair("bfe", "Broadcom BCM4401 Fast Ethernet")); SolarisNICMap.insert(NICPair("bge", "Broadcom BCM57xx Gigabit Ethernet")); SolarisNICMap.insert(NICPair("bnx", "Broadcom NetXtreme Gigabit Ethernet")); SolarisNICMap.insert(NICPair("bnxe", "Broadcom NetXtreme II 10 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("ce", "Cassini Gigabit Ethernet")); SolarisNICMap.insert(NICPair("chxge", "Chelsio Ethernet")); SolarisNICMap.insert(NICPair("dmfe", "Davicom 9102 Fast Ethernet")); SolarisNICMap.insert(NICPair("dnet", "DEC 21040/41 21140 Ethernet")); SolarisNICMap.insert(NICPair("e1000", "Intel PRO/1000 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("e1000g", "Intel PRO/1000 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("elx", "3COM Etherlink III Ethernet")); SolarisNICMap.insert(NICPair("elxl", "3COM Etherlink XL Ethernet")); SolarisNICMap.insert(NICPair("eri", "eri Fast Ethernet")); SolarisNICMap.insert(NICPair("ge", "GEM Gigabit Ethernet")); SolarisNICMap.insert(NICPair("hme", "SUNW,hme Fast-Ethernet")); SolarisNICMap.insert(NICPair("hxge", "Sun Blade 10 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("igb", "Intel 82575 PCI-E Gigabit Ethernet")); SolarisNICMap.insert(NICPair("ipge", "PCI-E Gigabit Ethernet")); SolarisNICMap.insert(NICPair("iprb", "Intel 82557/58/59 Ethernet")); SolarisNICMap.insert(NICPair("ixgb", "Intel 82597ex 10 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("ixgbe", "Intel 10 Gigabit PCI-E Ethernet")); SolarisNICMap.insert(NICPair("mcxe", "Mellanox ConnectX-2 10 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("mxfe", "Macronix 98715 Fast Ethernet")); SolarisNICMap.insert(NICPair("nfo", "Nvidia Gigabit Ethernet")); SolarisNICMap.insert(NICPair("nge", "Nvidia Gigabit Ethernet")); SolarisNICMap.insert(NICPair("ntxn", "NetXen 10/1 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("nxge", "Sun 10/1 Gigabit Ethernet")); SolarisNICMap.insert(NICPair("pcelx", "3COM EtherLink III PCMCIA Ethernet")); SolarisNICMap.insert(NICPair("pcn", "AMD PCnet Ethernet")); SolarisNICMap.insert(NICPair("qfe", "SUNW,qfe Quad Fast-Ethernet")); SolarisNICMap.insert(NICPair("rge", "Realtek Gigabit Ethernet")); SolarisNICMap.insert(NICPair("rtls", "Realtek 8139 Fast Ethernet")); SolarisNICMap.insert(NICPair("sfe", "SiS900 Fast Ethernet")); SolarisNICMap.insert(NICPair("skge", "SksKonnect Gigabit Ethernet")); SolarisNICMap.insert(NICPair("spwr", "SMC EtherPower II 10/100 (9432) Ethernet")); SolarisNICMap.insert(NICPair("vboxnet", "VirtualBox Host Ethernet")); SolarisNICMap.insert(NICPair("vboxvnic_template", "VirtualBox Virtual Network Interface Template")); SolarisNICMap.insert(NICPair("vlan", "Virtual LAN Ethernet")); SolarisNICMap.insert(NICPair("vr", "VIA Rhine Fast Ethernet")); SolarisNICMap.insert(NICPair("vnic", "Virtual Network Interface Ethernet")); SolarisNICMap.insert(NICPair("xge", "Neterior Xframe 10Gigabit Ethernet")); SolarisNICMap.insert(NICPair("yge", "Marvell Yukon 2 Fast Ethernet")); } /* * Try picking up description from our NIC map. */ char szNICInstance[128]; RTStrPrintf(szNICInstance, sizeof(szNICInstance), "%s%d", pszIface, Instance); char szNICDesc[256]; std::string Description = SolarisNICMap[pszIface]; if (Description != "VirtualBox Host Ethernet") { if (Description != "") RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - %s", szNICInstance, Description.c_str()); else RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - Ethernet", szNICInstance); } else RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s", szNICInstance); /* * Try to get IP V4 address and netmask as well as Ethernet address. */ NETIFINFO Info; memset(&Info, 0, sizeof(Info)); int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (Sock > 0) { struct lifreq IfReq; strcpy(IfReq.lifr_name, szNICInstance); if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0) { memcpy(Info.IPAddress.au8, &((struct sockaddr_in *)&IfReq.lifr_addr)->sin_addr.s_addr, sizeof(Info.IPAddress.au8)); struct arpreq ArpReq; memcpy(&ArpReq.arp_pa, &IfReq.lifr_addr, sizeof(struct sockaddr_in)); /* * We might fail if the interface has not been assigned an IP address. * That doesn't matter; as long as it's plumbed we can pick it up. * But, if it has not acquired an IP address we cannot obtain it's MAC * address this way, so we just use all zeros there. */ if (ioctl(Sock, SIOCGARP, &ArpReq) >= 0) { memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress)); } } if (ioctl(Sock, SIOCGLIFNETMASK, &IfReq) >= 0) { memcpy(Info.IPNetMask.au8, &((struct sockaddr_in *)&IfReq.lifr_addr)->sin_addr.s_addr, sizeof(Info.IPNetMask.au8)); } if (ioctl(Sock, SIOCGLIFFLAGS, &IfReq) >= 0) { Info.enmStatus = IfReq.lifr_flags & IFF_UP ? NETIF_S_UP : NETIF_S_DOWN; } close(Sock); } /* * Try to get IP V6 address and netmask. */ Sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); if (Sock > 0) { struct lifreq IfReq; strcpy(IfReq.lifr_name, szNICInstance); if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0) { memcpy(Info.IPv6Address.au8, ((struct sockaddr_in6 *)&IfReq.lifr_addr)->sin6_addr.s6_addr, sizeof(Info.IPv6Address.au8)); } if (ioctl(Sock, SIOCGLIFNETMASK, &IfReq) >= 0) { memcpy(Info.IPv6NetMask.au8, ((struct sockaddr_in6 *)&IfReq.lifr_addr)->sin6_addr.s6_addr, sizeof(Info.IPv6NetMask.au8)); } close(Sock); } /* * Construct UUID with interface name and the MAC address if available. */ RTUUID Uuid; RTUuidClear(&Uuid); memcpy(&Uuid, szNICInstance, RT_MIN(strlen(szNICInstance), sizeof(Uuid))); Uuid.Gen.u8ClockSeqHiAndReserved = (Uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; Uuid.Gen.u16TimeHiAndVersion = (Uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; Uuid.Gen.au8Node[0] = Info.MACAddress.au8[0]; Uuid.Gen.au8Node[1] = Info.MACAddress.au8[1]; Uuid.Gen.au8Node[2] = Info.MACAddress.au8[2]; Uuid.Gen.au8Node[3] = Info.MACAddress.au8[3]; Uuid.Gen.au8Node[4] = Info.MACAddress.au8[4]; Uuid.Gen.au8Node[5] = Info.MACAddress.au8[5]; Info.Uuid = Uuid; Info.enmMediumType = NETIF_T_ETHERNET; strncpy(Info.szShortName, szNICInstance, sizeof(Info.szShortName) - 1); HostNetworkInterfaceType_T enmType; if (strncmp("vboxnet", szNICInstance, 7)) enmType = HostNetworkInterfaceType_Bridged; else enmType = HostNetworkInterfaceType_HostOnly; queryIfaceSpeed(&Info); ComObjPtr<HostNetworkInterface> IfObj; IfObj.createObject(); if (SUCCEEDED(IfObj->init(Bstr(szNICDesc), enmType, &Info))) pList->push_back(IfObj); }