HRESULT DHCPServer::start(const com::Utf8Str &aNetworkName, const com::Utf8Str &aTrunkName, const com::Utf8Str &aTrunkType) { /* Silently ignore attempts to run disabled servers. */ if (!m->enabled) return S_OK; /* Commmon Network Settings */ m->dhcp.setOption(NetworkServiceRunner::kNsrKeyNetwork, aNetworkName.c_str()); if (!aTrunkName.isEmpty()) m->dhcp.setOption(NetworkServiceRunner::kNsrTrunkName, aTrunkName.c_str()); m->dhcp.setOption(NetworkServiceRunner::kNsrKeyTrunkType, aTrunkType.c_str()); /* XXX: should this MAC default initialization moved to NetworkServiceRunner? */ char strMAC[32]; Guid guid; guid.create(); RTStrPrintf (strMAC, sizeof(strMAC), "08:00:27:%02X:%02X:%02X", guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]); m->dhcp.setOption(NetworkServiceRunner::kNsrMacAddress, strMAC); m->dhcp.setOption(NetworkServiceRunner::kNsrIpAddress, Utf8Str(m->IPAddress).c_str()); m->dhcp.setOption(NetworkServiceRunner::kNsrIpNetmask, Utf8Str(m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text).c_str()); m->dhcp.setOption(DHCPServerRunner::kDsrKeyLowerIp, Utf8Str(m->lowerIP).c_str()); m->dhcp.setOption(DHCPServerRunner::kDsrKeyUpperIp, Utf8Str(m->upperIP).c_str()); /* XXX: This parameters Dhcp Server will fetch via API */ return RT_FAILURE(m->dhcp.start(!m->router /* KillProcOnExit */)) ? E_FAIL : S_OK; //m->dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */ }
HRESULT SystemProperties::setDefaultVRDEExtPack(const com::Utf8Str &aExtPack) { HRESULT hrc = S_OK; if (aExtPack.isNotEmpty()) { if (aExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME)) hrc = S_OK; else #ifdef VBOX_WITH_EXTPACK hrc = mParent->i_getExtPackManager()->i_checkVrdeExtPack(&aExtPack); #else hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), aExtPack.c_str()); #endif } if (SUCCEEDED(hrc)) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); hrc = i_setDefaultVRDEExtPack(aExtPack); if (SUCCEEDED(hrc)) { /* VirtualBox::i_saveSettings() needs the VirtualBox write lock. */ alock.release(); AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS); hrc = mParent->i_saveSettings(); } } return hrc; }
HRESULT SystemProperties::i_setAutostartDatabasePath(const com::Utf8Str &aPath) { HRESULT rc = S_OK; AutostartDb *autostartDb = this->mParent->i_getAutostartDb(); if (!aPath.isEmpty()) { /* Update path in the autostart database. */ int vrc = autostartDb->setAutostartDbPath(aPath.c_str()); if (RT_SUCCESS(vrc)) m->strAutostartDatabasePath = aPath; else rc = setError(E_FAIL, tr("Cannot set the autostart database path (%Rrc)"), vrc); } else { int vrc = autostartDb->setAutostartDbPath(NULL); if (RT_SUCCESS(vrc) || vrc == VERR_NOT_SUPPORTED) m->strAutostartDatabasePath = ""; else rc = setError(E_FAIL, tr("Deleting the autostart database path failed (%Rrc)"), vrc); } return rc; }
/** Reset the chosen one. */ void i_unchooseTheOne(bool fIrregular) { if (m_ptrTheChosenOne.isNotNull()) { if (!fIrregular) m_ptrTheChosenOne.setNull(); else { LogRel(("i_unchooseTheOne: Irregular release ... (pid=%d (%#x) user=%s sid=%s)\n", m_pidTheChosenOne, m_pidTheChosenOne, m_strUsername.c_str(), m_strUserSid.c_str())); m_ptrTheChosenOne.setNull(); LogRel(("i_unchooseTheOne: ... done.\n")); } } m_pidTheChosenOne = NIL_RTPROCESS; }
HRESULT USBController::setName(const com::Utf8Str &aName) { /* the machine needs to be mutable */ AutoMutableStateDependency adep(m->pParent); if (FAILED(adep.rc())) return adep.rc(); AutoMultiWriteLock2 alock(m->pParent, this COMMA_LOCKVAL_SRC_POS); if (m->bd->strName != aName) { ComObjPtr<USBController> ctrl; HRESULT rc = m->pParent->i_getUSBControllerByName(aName, ctrl, false /* aSetError */); if (SUCCEEDED(rc)) return setError(VBOX_E_OBJECT_IN_USE, tr("USB controller named '%s' already exists"), aName.c_str()); m->bd.backup(); m->bd->strName = aName; m->pParent->i_setModified(Machine::IsModified_USB); alock.release(); m->pParent->i_onUSBControllerChange(); } return S_OK; }
HRESULT USBDeviceFilter::setRemote(const com::Utf8Str &aRemote) { /* the machine needs to be mutable */ AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine()); if (FAILED(adep.rc())) return adep.rc(); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Bstr bRemote = Bstr(aRemote).raw(); if (bd->mRemote.string() != bRemote) { BackupableUSBDeviceFilterData::BOOLFilter flt = bRemote; ComAssertRet(!flt.isNull(), E_FAIL); if (!flt.isValid()) return setError(E_INVALIDARG, tr("Remote state filter string '%s' is not valid (error at position %d)"), aRemote.c_str(), flt.errorPosition() + 1); m_fModified = true; ComObjPtr<Machine> pMachine = mParent->i_getMachine(); bd.backup(); bd->mRemote = flt; // leave the lock before informing callbacks alock.release(); AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS); pMachine->i_setModified(Machine::IsModified_USB); mlock.release(); return mParent->i_onDeviceFilterChange(this); } return S_OK; }
static int i_vrdpServerVerifyPortsString(com::Utf8Str portRange) { const char *pszPortRange = portRange.c_str(); if (!pszPortRange || *pszPortRange == 0) /* Reject empty string. */ return VERR_INVALID_PARAMETER; /* The string should be like "1000-1010,1020,2000-2003" */ while (*pszPortRange) { const char *pszStart = pszPortRange; const char *pszDash = NULL; const char *pszEnd = pszStart; while (*pszEnd && *pszEnd != ',') { if (*pszEnd == '-') { if (pszDash != NULL) return VERR_INVALID_PARAMETER; /* More than one '-'. */ pszDash = pszEnd; } else if (!RT_C_IS_DIGIT(*pszEnd)) return VERR_INVALID_PARAMETER; pszEnd++; } /* Update the next range pointer. */ pszPortRange = pszEnd; if (*pszPortRange == ',') { pszPortRange++; } /* A probably valid range. Verify and parse it. */ int rc; if (pszDash) { rc = i_portParseNumber(NULL, pszStart, pszDash); if (RT_SUCCESS(rc)) rc = i_portParseNumber(NULL, pszDash + 1, pszEnd); } else rc = i_portParseNumber(NULL, pszStart, pszEnd); if (RT_FAILURE(rc)) return rc; } return VINF_SUCCESS; }
HRESULT Guest::findSession(const com::Utf8Str &aSessionName, std::vector<ComPtr<IGuestSession> > &aSessions) { #ifndef VBOX_WITH_GUEST_CONTROL ReturnComNotImplemented(); #else /* VBOX_WITH_GUEST_CONTROL */ LogFlowFuncEnter(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Utf8Str strName(aSessionName); std::list < ComObjPtr<GuestSession> > listSessions; GuestSessions::const_iterator itSessions = mData.mGuestSessions.begin(); while (itSessions != mData.mGuestSessions.end()) { if (strName.contains(itSessions->second->i_getName())) /** @todo Use a (simple) pattern match (IPRT?). */ listSessions.push_back(itSessions->second); ++itSessions; } LogFlowFunc(("Sessions with \"%s\" = %RU32\n", aSessionName.c_str(), listSessions.size())); aSessions.resize(listSessions.size()); if (!listSessions.empty()) { size_t i = 0; for (std::list < ComObjPtr<GuestSession> >::const_iterator it = listSessions.begin(); it != listSessions.end(); ++it, ++i) (*it).queryInterfaceTo(aSessions[i].asOutParam()); return S_OK; } return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND, tr("Could not find sessions with name '%s'"), aSessionName.c_str()); #endif /* VBOX_WITH_GUEST_CONTROL */ }
// public methods only for internal purposes ///////////////////////////////////////////////////////////////////////////// HRESULT VRDEServer::setVRDEExtPack(const com::Utf8Str &aExtPack) { HRESULT hrc = S_OK; /* the machine can also be in saved state for this property to change */ AutoMutableOrSavedOrRunningStateDependency adep(mParent); hrc = adep.rc(); if (SUCCEEDED(hrc)) { /* * If not empty, check the specific extension pack. */ if (!aExtPack.isEmpty()) { if (aExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME)) hrc = S_OK; else { #ifdef VBOX_WITH_EXTPACK ExtPackManager *pExtPackMgr = mParent->i_getVirtualBox()->i_getExtPackManager(); hrc = pExtPackMgr->i_checkVrdeExtPack(&aExtPack); #else hrc = setError(E_FAIL, tr("Extension pack '%s' does not exist"), aExtPack.c_str()); #endif } } if (SUCCEEDED(hrc)) { /* * Update the setting if there is an actual change, post an * change event to trigger a VRDE server restart. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (aExtPack != mData->mVrdeExtPack) { mData.backup(); mData->mVrdeExtPack = aExtPack; /* leave the lock before informing callbacks */ alock.release(); AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); mParent->i_setModified(Machine::IsModified_VRDEServer); mlock.release(); mParent->i_onVRDEServerChange(/* aRestart */ TRUE); } } } return hrc; }
HRESULT Guest::setCredentials(const com::Utf8Str &aUserName, const com::Utf8Str &aPassword, const com::Utf8Str &aDomain, BOOL aAllowInteractiveLogon) { /* Check for magic domain names which are used to pass encryption keys to the disk. */ if (Utf8Str(aDomain) == "@@disk") return mParent->i_setDiskEncryptionKeys(aPassword); else if (Utf8Str(aDomain) == "@@mem") { /** @todo */ return E_NOTIMPL; } else { /* forward the information to the VMM device */ VMMDev *pVMMDev = mParent->i_getVMMDev(); if (pVMMDev) { PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); if (pVMMDevPort) { uint32_t u32Flags = VMMDEV_SETCREDENTIALS_GUESTLOGON; if (!aAllowInteractiveLogon) u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON; pVMMDevPort->pfnSetCredentials(pVMMDevPort, aUserName.c_str(), aPassword.c_str(), aDomain.c_str(), u32Flags); return S_OK; } } } return setError(VBOX_E_VM_ERROR, tr("VMM device is not available (is the VM running?)")); }
HRESULT MachineDebugger::dumpGuestCore(const com::Utf8Str &aFilename, const com::Utf8Str &aCompression) { if (aCompression.length()) return setError(E_INVALIDARG, tr("The compression parameter must be empty")); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = DBGFR3CoreWrite(ptrVM.rawUVM(), aFilename.c_str(), false /*fReplaceFile*/); if (RT_SUCCESS(vrc)) hrc = S_OK; else hrc = setError(E_FAIL, tr("DBGFR3CoreWrite failed with %Rrc"), vrc); } return hrc; }
HRESULT StorageController::setName(const com::Utf8Str &aName) { /* the machine needs to be mutable */ AutoMutableStateDependency adep(m->pParent); if (FAILED(adep.rc())) return adep.rc(); AutoMultiWriteLock2 alock(m->pParent, this COMMA_LOCKVAL_SRC_POS); if (m->bd->strName != aName) { ComObjPtr<StorageController> ctrl; HRESULT rc = m->pParent->i_getStorageControllerByName(aName, ctrl, false /* aSetError */); if (SUCCEEDED(rc)) return setError(VBOX_E_OBJECT_IN_USE, tr("Storage controller named '%s' already exists"), aName.c_str()); Machine::MediumAttachmentList atts; rc = m->pParent->i_getMediumAttachmentsOfController(m->bd->strName, atts); for (Machine::MediumAttachmentList::const_iterator it = atts.begin(); it != atts.end(); ++it) { IMediumAttachment *iA = *it; MediumAttachment *pAttach = static_cast<MediumAttachment *>(iA); AutoWriteLock attlock(pAttach COMMA_LOCKVAL_SRC_POS); pAttach->i_updateName(aName); } m->bd.backup(); m->bd->strName = aName; m->pParent->i_setModified(Machine::IsModified_Storage); alock.release(); m->pParent->i_onStorageControllerChange(m->pParent->i_getId(), aName); } return S_OK; }
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; }
HRESULT GuestDnDSource::drop(const com::Utf8Str &aFormat, DnDAction_T aAction, ComPtr<IProgress> &aProgress) { #if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH) ReturnComNotImplemented(); #else /* VBOX_WITH_DRAG_AND_DROP */ /* Input validation. */ if (RT_UNLIKELY((aFormat.c_str()) == NULL || *(aFormat.c_str()) == '\0')) return setError(E_INVALIDARG, tr("No drop format specified")); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); uint32_t uAction = GuestDnD::toHGCMAction(aAction); /* If there is no usable action, ignore this request. */ if (isDnDIgnoreAction(uAction)) return S_OK; HRESULT hr = S_OK; const char *pcszFormat = aFormat.c_str(); bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat)); LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n", pcszFormat, uAction, fNeedsDropDir)); GuestDnDResponse *pResp = GuestDnDInst()->response(); if (pResp) { /* Reset any old data. */ pResp->reset(); pResp->resetProgress(m_pGuest); /* Set the format we are going to retrieve to have it around * when retrieving the data later. */ pResp->setFormat(aFormat); if (fNeedsDropDir) { char szDropDir[RTPATH_MAX]; int rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir)); LogFlowFunc(("rc=%Rrc, szDropDir=%s\n", rc, szDropDir)); if (RT_FAILURE(rc)) return setError(VBOX_E_IPRT_ERROR, tr("Unable to create the temporary drag and drop directory \"%s\" (%Rrc)\n"), szDropDir, rc); pResp->setDropDir(szDropDir); } VBOXHGCMSVCPARM paParms[4]; int i = 0; paParms[i++].setPointer((void*)aFormat.c_str(), (uint32_t)aFormat.length() + 1); paParms[i++].setUInt32((uint32_t)aFormat.length() + 1); paParms[i++].setUInt32(uAction); int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_GH_EVT_DROPPED, i, paParms); if (RT_SUCCESS(rc)) { /* Query the progress object to the caller. */ pResp->queryProgressTo(aProgress.asOutParam()); } else hr = setError(VBOX_E_IPRT_ERROR, tr("Error signalling to drop data (%Rrc)\n"), rc); } LogFlowFunc(("Returning hr=%Rhrc\n", hr)); return hr; #endif /* VBOX_WITH_DRAG_AND_DROP */ }
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 }
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 SystemProperties::setLoggingLevel(const com::Utf8Str &aLoggingLevel) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT rc = i_setLoggingLevel(aLoggingLevel); alock.release(); if (SUCCEEDED(rc)) { AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS); rc = mParent->i_saveSettings(); } else LogRel(("Cannot set passed logging level=%s, or the default one - Error=%Rhrc \n", aLoggingLevel.c_str(), rc)); return rc; }
int DHCPServer::addOption(settings::DhcpOptionMap &aMap, DhcpOpt_T aOption, const com::Utf8Str &aValue) { settings::DhcpOptValue OptValue; if (aOption != 0) { OptValue = settings::DhcpOptValue(aValue, DhcpOptEncoding_Legacy); } /* * This is a kludge to sneak in option encoding information * through existing API. We use option 0 and supply the real * option/value in the same format that encodeOption() above * produces for getter methods. */ else { uint8_t u8Code; uint32_t u32Enc; char *pszNext; int rc; rc = RTStrToUInt8Ex(aValue.c_str(), &pszNext, 10, &u8Code); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; switch (*pszNext) { case ':': /* support legacy format too */ { u32Enc = DhcpOptEncoding_Legacy; break; } case '=': { u32Enc = DhcpOptEncoding_Hex; break; } case '@': { rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 10, &u32Enc); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; if (*pszNext != '=') return VERR_PARSE_ERROR; break; } default: return VERR_PARSE_ERROR; } aOption = (DhcpOpt_T)u8Code; OptValue = settings::DhcpOptValue(pszNext + 1, (DhcpOptEncoding_T)u32Enc); } aMap[aOption] = OptValue; return VINF_SUCCESS; }