void ParsedRegexpFilter_base::parse (const Bstr &aFilter) { /// @todo (dmik) parse "rx:<regexp>" string // note, that min/max checks must not be done, when the string // begins with "rx:". These limits are for exact matching only! // empty or null string means any match (see #isMatch() below), // so we don't apply Min/Max restrictions in this case if (!aFilter.isEmpty()) { size_t len = aFilter.length(); if (mMinLen > 0 && len < mMinLen) { mNull = mValid = false; mErrorPosition = len; return; } if (mMaxLen > 0 && len > mMaxLen) { mNull = mValid = false; mErrorPosition = mMaxLen; return; } } mSimple = aFilter; mNull = false; mValid = true; mErrorPosition = 0; }
STDMETHODIMP VRDEServer::COMGETTER(AuthLibrary) (BSTR *aLibrary) { CheckComArgOutPointerValid(aLibrary); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); Bstr bstrLibrary; AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); bstrLibrary = mData->mAuthLibrary; alock.release(); if (bstrLibrary.isEmpty()) { /* Get the global setting. */ ComPtr<ISystemProperties> systemProperties; HRESULT hrc = mParent->getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam()); if (SUCCEEDED(hrc)) hrc = systemProperties->COMGETTER(VRDEAuthLibrary)(bstrLibrary.asOutParam()); if (FAILED(hrc)) return setError(hrc, "failed to query the library setting\n"); } bstrLibrary.cloneTo(aLibrary); return S_OK; }
/** * Determines the maximum balloon size to set for the specified machine. * * @return unsigned long Balloon size (in MB) to set, 0 if no ballooning required. * @param rptrMachine Pointer to interface of specified machine. */ static unsigned long balloonGetMaxSize(const ComPtr<IMachine> &rptrMachine) { /* * Try to retrieve the balloon maximum size via the following order: * - command line parameter ("--balloon-max") * Legacy (VBoxBalloonCtrl): * - per-VM parameter ("VBoxInternal/Guest/BalloonSizeMax") * Global: * - global parameter ("VBoxInternal/Guest/BalloonSizeMax") * New: * - per-VM parameter ("VBoxInternal2/Watchdog/BalloonCtrl/BalloonSizeMax") * * By default (e.g. if none of above is set), ballooning is disabled. */ unsigned long ulBalloonMax = g_ulMemoryBalloonMaxMB; if (!ulBalloonMax) { int vrc = cfgGetValueULong(g_pVirtualBox, rptrMachine, "VBoxInternal/Guest/BalloonSizeMax", "VBoxInternal/Guest/BalloonSizeMax", &ulBalloonMax, 0 /* Ballooning disabled */); if (RT_FAILURE(vrc)) { /* Try (new) VBoxWatch per-VM approach. */ Bstr strValue; HRESULT rc = rptrMachine->GetExtraData(Bstr("VBoxInternal2/Watchdog/BalloonCtrl/BalloonSizeMax").raw(), strValue.asOutParam()); if ( SUCCEEDED(rc) && !strValue.isEmpty()) { ulBalloonMax = Utf8Str(strValue).toUInt32(); } } } return ulBalloonMax; }
/** * Sets the general Guest Additions information like * API (interface) version and OS type. Gets called by * vmmdevUpdateGuestInfo. * * @param aInterfaceVersion * @param aOsType */ void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType) { AutoCaller autoCaller(this); AssertComRCReturnVoid(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* * Note: The Guest Additions API (interface) version is deprecated * and will not be used anymore! We might need it to at least report * something as version number if *really* ancient Guest Additions are * installed (without the guest version + revision properties having set). */ mData.mInterfaceVersion = aInterfaceVersion; /* * Older Additions rely on the Additions API version whether they * are assumed to be active or not. Since newer Additions do report * the Additions version *before* calling this function (by calling * VMMDevReportGuestInfo2, VMMDevReportGuestStatus, VMMDevReportGuestInfo, * in that order) we can tell apart old and new Additions here. Old * Additions never would set VMMDevReportGuestInfo2 (which set mData.mAdditionsVersion) * so they just rely on the aInterfaceVersion string (which gets set by * VMMDevReportGuestInfo). * * So only mark the Additions as being active (run level = system) when we * don't have the Additions version set. */ if (mData.mAdditionsVersion.isEmpty()) { if (aInterfaceVersion.isEmpty()) mData.mAdditionsRunLevel = AdditionsRunLevelType_None; else { mData.mAdditionsRunLevel = AdditionsRunLevelType_System; /* * To keep it compatible with the old Guest Additions behavior we need to set the * "graphics" (feature) facility to active as soon as we got the Guest Additions * interface version. */ facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active); } } /* * Older Additions didn't have this finer grained capability bit, * so enable it by default. Newer Additions will not enable this here * and use the setSupportedFeatures function instead. */ facilityUpdate(VBoxGuestFacilityType_Graphics, facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver) ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive); /* * Note! There is a race going on between setting mAdditionsRunLevel and * mSupportsGraphics here and disabling/enabling it later according to * its real status when using new(er) Guest Additions. */ mData.mOSTypeId = Global::OSTypeId (aOsType); }
HRESULT HostNetworkInterface::i_setVirtualBox(VirtualBox *pVirtualBox) { AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AssertReturn(mVirtualBox != pVirtualBox, S_OK); unconst(mVirtualBox) = pVirtualBox; #if !defined(RT_OS_WINDOWS) /* If IPv4 address hasn't been initialized */ if (m.IPAddress == 0 && mIfType == HostNetworkInterfaceType_HostOnly) { Bstr tmpAddr, tmpMask; HRESULT hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress", mInterfaceName.c_str()).raw(), tmpAddr.asOutParam()); if (FAILED(hrc) || tmpAddr.isEmpty()) tmpAddr = getDefaultIPv4Address(mInterfaceName); hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask", mInterfaceName.c_str()).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 bstrIPV4Addr; Bstr tmpPrefixLen; HRESULT hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address", mInterfaceName.c_str()).raw(), bstrIPV4Addr.asOutParam()); if (SUCCEEDED(hrc)) { m.IPV6Address = bstrIPV4Addr; if (!m.IPV6Address.isEmpty()) { hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6PrefixLen", mInterfaceName.c_str()).raw(), tmpPrefixLen.asOutParam()); if (SUCCEEDED(hrc) && !tmpPrefixLen.isEmpty()) m.IPV6NetworkMaskPrefixLength = Utf8Str(tmpPrefixLen).toUInt32(); else m.IPV6NetworkMaskPrefixLength = 64; } } } #endif return S_OK; }
static int handleGetGuestProperty(HandlerArg *a) { HRESULT rc = S_OK; bool verbose = false; if ( a->argc == 3 && ( !strcmp(a->argv[2], "--verbose") || !strcmp(a->argv[2], "-verbose"))) verbose = true; else if (a->argc != 2) return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters"); ComPtr<IMachine> machine; CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), machine.asOutParam())); if (machine) { /* open a session for the VM - new or existing */ CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); /* get the mutable session machine */ a->session->COMGETTER(Machine)(machine.asOutParam()); Bstr value; LONG64 i64Timestamp; Bstr flags; CHECK_ERROR(machine, GetGuestProperty(Bstr(a->argv[1]).raw(), value.asOutParam(), &i64Timestamp, flags.asOutParam())); if (value.isEmpty()) RTPrintf("No value set!\n"); else RTPrintf("Value: %ls\n", value.raw()); if (!value.isEmpty() && verbose) { RTPrintf("Timestamp: %lld\n", i64Timestamp); RTPrintf("Flags: %ls\n", flags.raw()); } } return SUCCEEDED(rc) ? 0 : 1; }
STDMETHODIMP Guest::COMGETTER(AdditionsVersion)(BSTR *a_pbstrAdditionsVersion) { CheckComArgOutPointerValid(a_pbstrAdditionsVersion); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); /* * Return the ReportGuestInfo2 version info if available. */ if ( !mData.mAdditionsVersionNew.isEmpty() || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None) mData.mAdditionsVersionNew.cloneTo(a_pbstrAdditionsVersion); else { /* * If we're running older guest additions (< 3.2.0) try get it from * the guest properties. Detected switched around Version and * Revision in early 3.1.x releases (see r57115). */ ComPtr<IMachine> ptrMachine = mParent->machine(); alock.release(); /* No need to hold this during the IPC fun. */ Bstr bstr; hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam()); if ( SUCCEEDED(hrc) && !bstr.isEmpty()) { Utf8Str str(bstr); if (str.count('.') == 0) hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam()); str = bstr; if (str.count('.') != 2) hrc = E_FAIL; } if (SUCCEEDED(hrc)) bstr.detachTo(a_pbstrAdditionsVersion); else { /* Returning 1.4 is better than nothing. */ alock.acquire(); mData.mInterfaceVersion.cloneTo(a_pbstrAdditionsVersion); hrc = S_OK; } } } return hrc; }
static DECLCALLBACK(int) VBoxModAPIMonitorMain(void) { static uint64_t uLastRun = 0; uint64_t uNow = RTTimeProgramMilliTS(); uint64_t uDelta = uNow - uLastRun; if (uDelta < 1000) /* Only check every second (or later). */ return VINF_SUCCESS; uLastRun = uNow; int vrc = VINF_SUCCESS; HRESULT rc; #ifdef DEBUG serviceLogVerbose(("apimon: Checking for API heartbeat (%RU64ms) ...\n", g_ulAPIMonIslnTimeoutMS)); #endif do { Bstr strHeartbeat; CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/Heartbeat").raw(), strHeartbeat.asOutParam())); if ( SUCCEEDED(rc) && !strHeartbeat.isEmpty() && g_strAPIMonIslnLastBeat.compare(strHeartbeat, Bstr::CaseSensitive)) { serviceLogVerbose(("apimon: API heartbeat received, resetting timeout\n")); g_uAPIMonIslnLastBeatMS = 0; g_strAPIMonIslnLastBeat = strHeartbeat; } else { g_uAPIMonIslnLastBeatMS += uDelta; if (g_uAPIMonIslnLastBeatMS > g_ulAPIMonIslnTimeoutMS) { serviceLogVerbose(("apimon: No API heartbeat within time received (%RU64ms)\n", g_ulAPIMonIslnTimeoutMS)); vrc = apimonTrigger(g_enmAPIMonIslnResp); g_uAPIMonIslnLastBeatMS = 0; } } } while (0); if (FAILED(rc)) vrc = VERR_COM_IPRT_ERROR; return vrc; }
int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId, IProgress **aProgress) { #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; int rc = VINF_SUCCESS; HRESULT hr = pVirtualBox->COMGETTER(Host)(host.asOutParam()); if (SUCCEEDED(hr)) { Bstr ifname; ComPtr<IHostNetworkInterface> iface; if (FAILED(host->FindHostNetworkInterfaceById(Guid(aId).toUtf16().raw(), iface.asOutParam()))) return VERR_INVALID_PARAMETER; iface->COMGETTER(Name)(ifname.asOutParam()); if (ifname.isEmpty()) return VERR_INTERNAL_ERROR; rc = progress->init(pVirtualBox, host, Bstr("Removing host network interface").raw(), FALSE /* aCancelable */); if (SUCCEEDED(rc)) { progress.queryInterfaceTo(aProgress); rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL); if (RT_FAILURE(rc)) progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME "' (exit status: %d)", rc); else progress->i_notifyComplete(S_OK); } } else { progress->i_notifyComplete(hr); rc = VERR_INTERNAL_ERROR; } return rc; #else NOREF(pVirtualBox); NOREF(aId); NOREF(aProgress); return VERR_NOT_IMPLEMENTED; #endif }
/** * Determines the requested balloon size to set for the specified machine. * * @return Requested ballooning size (in MB), 0 if ballooning should be disabled. * @param pMachine Machine to determine maximum ballooning size for. */ static uint32_t balloonGetRequestedSize(PVBOXWATCHDOG_MACHINE pMachine) { const ComPtr<IMachine> &rptrMachine = pMachine->machine; /* * The maximum balloning size can be set * - via per-VM extra-data ("VBoxInternal2/Watchdog/BalloonCtrl/BalloonSizeMax") * - via per-VM extra-data (legacy) ("VBoxInternal/Guest/BalloonSizeMax") * * Precedence from top to bottom. */ uint32_t cMbBalloonReq = 0; char szSource[64]; Bstr strValue; HRESULT hr = rptrMachine->GetExtraData(Bstr("VBoxInternal2/Watchdog/BalloonCtrl/BalloonSizeMax").raw(), strValue.asOutParam()); if ( SUCCEEDED(hr) && strValue.isNotEmpty()) { cMbBalloonReq = Utf8Str(strValue).toUInt32(); if (g_fVerbose) RTStrPrintf(szSource, sizeof(szSource), "per-VM extra-data"); } else { hr = rptrMachine->GetExtraData(Bstr("VBoxInternal/Guest/BalloonSizeMax").raw(), strValue.asOutParam()); if ( SUCCEEDED(hr) && strValue.isNotEmpty()) { cMbBalloonReq = Utf8Str(strValue).toUInt32(); if (g_fVerbose) RTStrPrintf(szSource, sizeof(szSource), "per-VM extra-data (legacy)"); } } if ( FAILED(hr) || strValue.isEmpty()) { cMbBalloonReq = 0; if (g_fVerbose) RTStrPrintf(szSource, sizeof(szSource), "none (disabled)"); } serviceLogVerbose(("[%ls] Requested balloning size is (%s): %RU32MB\n", pMachine->strName.raw(), szSource, cMbBalloonReq)); return cMbBalloonReq; }
/** * Sets the Guest Additions version information details. * Gets called by vmmdevUpdateGuestInfo2. * * @param aAdditionsVersion * @param aVersionName */ void Guest::setAdditionsInfo2(Bstr aAdditionsVersion, Bstr aVersionName, Bstr aRevision) { AutoCaller autoCaller(this); AssertComRCReturnVoid(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (!aVersionName.isEmpty()) /* * aVersionName could be "x.y.z_BETA1_FOOBAR", so append revision manually to * become "x.y.z_BETA1_FOOBAR r12345". */ mData.mAdditionsVersion = BstrFmt("%ls r%ls", aVersionName.raw(), aRevision.raw()); else /* aAdditionsVersion is in x.y.zr12345 format. */ mData.mAdditionsVersion = aAdditionsVersion; }
void GluePrintErrorInfo(const com::ErrorInfo &info) { bool haveResultCode = false; #if defined (RT_OS_WIN) haveResultCode = info.isFullAvailable(); bool haveComponent = true; bool haveInterfaceID = true; #else /* defined (RT_OS_WIN) */ haveResultCode = true; bool haveComponent = info.isFullAvailable(); bool haveInterfaceID = info.isFullAvailable(); #endif Utf8Str str; RTCList<Utf8Str> comp; Bstr bstrDetailsText = info.getText(); if (!bstrDetailsText.isEmpty()) str = Utf8StrFmt("%ls\n", bstrDetailsText.raw()); if (haveResultCode) comp.append(Utf8StrFmt("code %Rhrc (0x%RX32)", info.getResultCode(), info.getResultCode())); if (haveComponent) comp.append(Utf8StrFmt("component %ls", info.getComponent().raw())); if (haveInterfaceID) comp.append(Utf8StrFmt("interface %ls", info.getInterfaceName().raw())); if (!info.getCalleeName().isEmpty()) comp.append(Utf8StrFmt("callee %ls", info.getCalleeName().raw())); if (comp.size() > 0) { str += "Details: "; for (size_t i = 0; i < comp.size() - 1; ++i) str += comp.at(i) + ", "; str += comp.last(); str += "\n"; } // print and log RTMsgError("%s", str.c_str()); Log(("ERROR: %s", str.c_str())); }
HRESULT Guest::getAdditionsVersion(com::Utf8Str &aAdditionsVersion) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hrc = S_OK; /* * Return the ReportGuestInfo2 version info if available. */ if ( !mData.mAdditionsVersionNew.isEmpty() || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None) aAdditionsVersion = mData.mAdditionsVersionNew; else { /* * If we're running older guest additions (< 3.2.0) try get it from * the guest properties. Detected switched around Version and * Revision in early 3.1.x releases (see r57115). */ ComPtr<IMachine> ptrMachine = mParent->i_machine(); alock.release(); /* No need to hold this during the IPC fun. */ Bstr bstr; hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam()); if ( SUCCEEDED(hrc) && !bstr.isEmpty()) { Utf8Str str(bstr); if (str.count('.') == 0) hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam()); str = bstr; if (str.count('.') != 2) hrc = E_FAIL; } if (SUCCEEDED(hrc)) aAdditionsVersion = bstr; else { /* Returning 1.4 is better than nothing. */ alock.acquire(); aAdditionsVersion = mData.mInterfaceVersion; hrc = S_OK; } } return hrc; }
/** * Initializes the host object. * * @returns COM result indicator * @param aInterfaceName name of the network interface * @param aGuid GUID of the host network interface */ HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Guid aGuid, HostNetworkInterfaceType_T ifType) { LogFlowThisFunc(("aInterfaceName={%ls}, aGuid={%s}\n", aInterfaceName.raw(), aGuid.toString().c_str())); ComAssertRet(!aInterfaceName.isEmpty(), E_INVALIDARG); ComAssertRet(!aGuid.isEmpty(), E_INVALIDARG); /* Enclose the state transition NotReady->InInit->Ready */ AutoInitSpan autoInitSpan(this); AssertReturn(autoInitSpan.isOk(), E_FAIL); unconst(mInterfaceName) = aInterfaceName; unconst(mGuid) = aGuid; mIfType = ifType; /* Confirm a successful initialization */ autoInitSpan.setSucceeded(); return S_OK; }
void ParsedBoolFilter::parse (const Bstr &aFilter) { mNull = false; mValid = true; mErrorPosition = 0; if (aFilter.isEmpty()) { mValueAny = true; mValue = false; } else { mValueAny = false; if (aFilter == L"true" || aFilter == L"yes" || aFilter == L"1") mValue = true; else if (aFilter == L"false" || aFilter == L"no" || aFilter == L"0") mValue = false; else mValid = false; } }
/** * Determines the maximum balloon size to set for the specified machine. * * @return Maximum ballooning size (in MB), 0 if no maximum set. * @param pMachine Machine to determine maximum ballooning size for. */ static uint32_t balloonGetMaxSize(PVBOXWATCHDOG_MACHINE pMachine) { /* * Is a maximum ballooning size set? Make sure we're within bounds. * * The maximum balloning size can be set * - via global extra-data ("VBoxInternal/Guest/BalloonSizeMax") * - via command line ("--balloon-max") * * Precedence from top to bottom. */ uint32_t cMbBalloonMax = 0; char szSource[64]; Bstr strValue; HRESULT hr = g_pVirtualBox->GetExtraData(Bstr("VBoxInternal/Guest/BalloonSizeMax").raw(), strValue.asOutParam()); if ( SUCCEEDED(hr) && strValue.isNotEmpty()) { cMbBalloonMax = Utf8Str(strValue).toUInt32(); if (g_fVerbose) RTStrPrintf(szSource, sizeof(szSource), "global extra-data"); } if (strValue.isEmpty()) { Assert(cMbBalloonMax == 0); cMbBalloonMax = g_cMbMemoryBalloonMax; if (g_fVerbose) RTStrPrintf(szSource, sizeof(szSource), "command line"); } serviceLogVerbose(("[%ls] Maximum balloning size is (%s): %RU32MB\n", pMachine->strName.raw(), szSource, cMbBalloonMax)); return cMbBalloonMax; }
/** * Removes a specified machine from the list of handled machines. * Does not do locking -- needs to be done by caller! * * @return IPRT status code. * @param strUuid UUID of the specified machine. */ static int machineRemove(const Bstr &strUuid) { AssertReturn(!strUuid.isEmpty(), VERR_INVALID_PARAMETER); int rc = VINF_SUCCESS; mapVMIter it = g_mapVM.find(strUuid); if (it != g_mapVM.end()) { int rc2 = machineDestroy(strUuid); if (RT_FAILURE(rc)) { serviceLog(("Machine \"%ls\" failed to destroy, rc=%Rc\n")); if (RT_SUCCESS(rc)) rc = rc2; } } else { serviceLogVerbose(("Warning: Removing not added machine \"%ls\"\n", strUuid.raw())); rc = VERR_NOT_FOUND; } return rc; }
static int machineDestroy(const Bstr &strUuid) { AssertReturn(!strUuid.isEmpty(), VERR_INVALID_PARAMETER); int rc = VINF_SUCCESS; /* Let all modules know. */ for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++) if (g_aModules[j].fEnabled) { int rc2 = g_aModules[j].pDesc->pfnOnMachineUnregistered(strUuid); if (RT_FAILURE(rc2)) serviceLog("OnMachineUnregistered: Module '%s' reported an error: %Rrc\n", g_aModules[j].pDesc->pszName, rc); /* Keep going. */ } /* Must log before erasing the iterator because of the UUID ref! */ serviceLogVerbose(("Removing machine \"%ls\"\n", strUuid.raw())); try { mapVMIter itVM = g_mapVM.find(strUuid); Assert(itVM != g_mapVM.end()); /* Remove machine from group(s). */ mapGroupsIterConst itGroups = itVM->second.groups.begin(); while (itGroups != itVM->second.groups.end()) { mapGroupIter itGroup = g_mapGroup.find(itGroups->first); Assert(itGroup != g_mapGroup.end()); vecGroupMembers vecMembers = itGroup->second; vecGroupMembersIter itMember = std::find(vecMembers.begin(), vecMembers.end(), strUuid); Assert(itMember != vecMembers.end()); vecMembers.erase(itMember); serviceLogVerbose(("Group \"%s\" has %ld machines left\n", itGroup->first.c_str(), vecMembers.size())); if (!vecMembers.size()) { serviceLogVerbose(("Deleting group \"%s\"\n", itGroup->first.c_str())); g_mapGroup.erase(itGroup); } ++itGroups; } #ifndef VBOX_WATCHDOG_GLOBAL_PERFCOL itVM->second.collector.setNull(); #endif itVM->second.machine.setNull(); /* * Remove machine from map. */ g_mapVM.erase(itVM); } catch (...) { AssertFailed(); } return rc; }
int handleGetExtraData(HandlerArg *a) { HRESULT rc = S_OK; if (a->argc != 2) return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters"); /* global data? */ if (!strcmp(a->argv[0], "global")) { /* enumeration? */ if (!strcmp(a->argv[1], "enumerate")) { SafeArray<BSTR> aKeys; CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys))); for (size_t i = 0; i < aKeys.size(); ++i) { Bstr bstrKey(aKeys[i]); Bstr bstrValue; CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey.raw(), bstrValue.asOutParam())); RTPrintf("Key: %ls, Value: %ls\n", bstrKey.raw(), bstrValue.raw()); } } else { Bstr value; CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]).raw(), value.asOutParam())); if (!value.isEmpty()) RTPrintf("Value: %ls\n", value.raw()); else RTPrintf("No value set!\n"); } } else { ComPtr<IMachine> machine; CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), machine.asOutParam())); if (machine) { /* enumeration? */ if (!strcmp(a->argv[1], "enumerate")) { SafeArray<BSTR> aKeys; CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys))); for (size_t i = 0; i < aKeys.size(); ++i) { Bstr bstrKey(aKeys[i]); Bstr bstrValue; CHECK_ERROR(machine, GetExtraData(bstrKey.raw(), bstrValue.asOutParam())); RTPrintf("Key: %ls, Value: %ls\n", bstrKey.raw(), bstrValue.raw()); } } else { Bstr value; CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]).raw(), value.asOutParam())); if (!value.isEmpty()) RTPrintf("Value: %ls\n", value.raw()); else RTPrintf("No value set!\n"); } } } return SUCCEEDED(rc) ? 0 : 1; }
int handleCloneVM(HandlerArg *a) { HRESULT rc; const char *pszSrcName = NULL; const char *pszSnapshotName = NULL; CloneMode_T mode = CloneMode_MachineState; com::SafeArray<CloneOptions_T> options; const char *pszTrgName = NULL; const char *pszTrgBaseFolder = NULL; bool fRegister = false; Bstr bstrUuid; com::SafeArray<BSTR> groups; int c; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; // start at 0 because main() has hacked both the argc and argv given to us RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneVMOptions, RT_ELEMENTS(g_aCloneVMOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); while ((c = RTGetOpt(&GetState, &ValueUnion))) { switch (c) { case 's': // --snapshot pszSnapshotName = ValueUnion.psz; break; case 'n': // --name pszTrgName = ValueUnion.psz; break; case 'g': // --groups parseGroups(ValueUnion.psz, &groups); break; case 'p': // --basefolder pszTrgBaseFolder = ValueUnion.psz; break; case 'm': // --mode if (RT_FAILURE(parseCloneMode(ValueUnion.psz, &mode))) return errorArgument("Invalid clone mode '%s'\n", ValueUnion.psz); break; case 'o': // --options if (RT_FAILURE(parseCloneOptions(ValueUnion.psz, &options))) return errorArgument("Invalid clone options '%s'\n", ValueUnion.psz); break; case 'u': // --uuid bstrUuid = Guid(ValueUnion.Uuid).toUtf16().raw(); break; case 'r': // --register fRegister = true; break; case VINF_GETOPT_NOT_OPTION: if (!pszSrcName) pszSrcName = ValueUnion.psz; else return errorSyntax(USAGE_CLONEVM, "Invalid parameter '%s'", ValueUnion.psz); break; default: return errorGetOpt(USAGE_CLONEVM, c, &ValueUnion); } } /* Check for required options */ if (!pszSrcName) return errorSyntax(USAGE_CLONEVM, "VM name required"); /* Get the machine object */ ComPtr<IMachine> srcMachine; CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(), srcMachine.asOutParam()), RTEXITCODE_FAILURE); /* If a snapshot name/uuid was given, get the particular machine of this * snapshot. */ if (pszSnapshotName) { ComPtr<ISnapshot> srcSnapshot; CHECK_ERROR_RET(srcMachine, FindSnapshot(Bstr(pszSnapshotName).raw(), srcSnapshot.asOutParam()), RTEXITCODE_FAILURE); CHECK_ERROR_RET(srcSnapshot, COMGETTER(Machine)(srcMachine.asOutParam()), RTEXITCODE_FAILURE); } /* Default name necessary? */ if (!pszTrgName) pszTrgName = RTStrAPrintf2("%s Clone", pszSrcName); Bstr createFlags; if (!bstrUuid.isEmpty()) createFlags = BstrFmt("UUID=%ls", bstrUuid.raw()); Bstr bstrPrimaryGroup; if (groups.size()) bstrPrimaryGroup = groups[0]; Bstr bstrSettingsFile; CHECK_ERROR_RET(a->virtualBox, ComposeMachineFilename(Bstr(pszTrgName).raw(), bstrPrimaryGroup.raw(), createFlags.raw(), Bstr(pszTrgBaseFolder).raw(), bstrSettingsFile.asOutParam()), RTEXITCODE_FAILURE); ComPtr<IMachine> trgMachine; CHECK_ERROR_RET(a->virtualBox, CreateMachine(bstrSettingsFile.raw(), Bstr(pszTrgName).raw(), ComSafeArrayAsInParam(groups), NULL, createFlags.raw(), trgMachine.asOutParam()), RTEXITCODE_FAILURE); /* Start the cloning */ ComPtr<IProgress> progress; CHECK_ERROR_RET(srcMachine, CloneTo(trgMachine, mode, ComSafeArrayAsInParam(options), progress.asOutParam()), RTEXITCODE_FAILURE); rc = showProgress(progress); CHECK_PROGRESS_ERROR_RET(progress, ("Clone VM failed"), RTEXITCODE_FAILURE); if (fRegister) CHECK_ERROR_RET(a->virtualBox, RegisterMachine(trgMachine), RTEXITCODE_FAILURE); Bstr bstrNewName; CHECK_ERROR_RET(trgMachine, COMGETTER(Name)(bstrNewName.asOutParam()), RTEXITCODE_FAILURE); RTPrintf("Machine has been successfully cloned as \"%ls\"\n", bstrNewName.raw()); return RTEXITCODE_SUCCESS; }
int handleCreateVM(HandlerArg *a) { HRESULT rc; Bstr bstrBaseFolder; Bstr bstrName; Bstr bstrOsTypeId; Bstr bstrUuid; bool fRegister = false; com::SafeArray<BSTR> groups; int c; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; // start at 0 because main() has hacked both the argc and argv given to us RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateVMOptions, RT_ELEMENTS(g_aCreateVMOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); while ((c = RTGetOpt(&GetState, &ValueUnion))) { switch (c) { case 'n': // --name bstrName = ValueUnion.psz; break; case 'g': // --groups parseGroups(ValueUnion.psz, &groups); break; case 'p': // --basefolder bstrBaseFolder = ValueUnion.psz; break; case 'o': // --ostype bstrOsTypeId = ValueUnion.psz; break; case 'u': // --uuid bstrUuid = Guid(ValueUnion.Uuid).toUtf16().raw(); break; case 'r': // --register fRegister = true; break; default: return errorGetOpt(USAGE_CREATEVM, c, &ValueUnion); } } /* check for required options */ if (bstrName.isEmpty()) return errorSyntax(USAGE_CREATEVM, "Parameter --name is required"); do { Bstr createFlags; if (!bstrUuid.isEmpty()) createFlags = BstrFmt("UUID=%ls", bstrUuid.raw()); Bstr bstrPrimaryGroup; if (groups.size()) bstrPrimaryGroup = groups[0]; Bstr bstrSettingsFile; CHECK_ERROR_BREAK(a->virtualBox, ComposeMachineFilename(bstrName.raw(), bstrPrimaryGroup.raw(), createFlags.raw(), bstrBaseFolder.raw(), bstrSettingsFile.asOutParam())); ComPtr<IMachine> machine; CHECK_ERROR_BREAK(a->virtualBox, CreateMachine(bstrSettingsFile.raw(), bstrName.raw(), ComSafeArrayAsInParam(groups), bstrOsTypeId.raw(), createFlags.raw(), machine.asOutParam())); CHECK_ERROR_BREAK(machine, SaveSettings()); if (fRegister) { CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine)); } Bstr uuid; CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam())); Bstr settingsFile; CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam())); RTPrintf("Virtual machine '%ls' is created%s.\n" "UUID: %s\n" "Settings file: '%ls'\n", bstrName.raw(), fRegister ? " and registered" : "", Utf8Str(uuid).c_str(), settingsFile.raw()); } while (0); return SUCCEEDED(rc) ? 0 : 1; }
HRESULT showMediumInfo(const ComPtr<IVirtualBox> &pVirtualBox, const ComPtr<IMedium> &pMedium, const char *pszParentUUID, bool fOptLong) { HRESULT rc = S_OK; do { Bstr uuid; pMedium->COMGETTER(Id)(uuid.asOutParam()); RTPrintf("UUID: %ls\n", uuid.raw()); if (pszParentUUID) RTPrintf("Parent UUID: %s\n", pszParentUUID); /* check for accessibility */ MediumState_T enmState; CHECK_ERROR_BREAK(pMedium, RefreshState(&enmState)); pMedium->RefreshState(&enmState); const char *pszState = "unknown"; switch (enmState) { case MediumState_NotCreated: pszState = "not created"; break; case MediumState_Created: pszState = "created"; break; case MediumState_LockedRead: pszState = "locked read"; break; case MediumState_LockedWrite: pszState = "locked write"; break; case MediumState_Inaccessible: pszState = "inaccessible"; break; case MediumState_Creating: pszState = "creating"; break; case MediumState_Deleting: pszState = "deleting"; break; } RTPrintf("State: %s\n", pszState); if (fOptLong && enmState == MediumState_Inaccessible) { Bstr err; CHECK_ERROR_BREAK(pMedium, COMGETTER(LastAccessError)(err.asOutParam())); RTPrintf("Access Error: %ls\n", err.raw()); } if (fOptLong) { Bstr description; pMedium->COMGETTER(Description)(description.asOutParam()); if (!description.isEmpty()) RTPrintf("Description: %ls\n", description.raw()); } MediumType_T type; pMedium->COMGETTER(Type)(&type); const char *typeStr = "unknown"; switch (type) { case MediumType_Normal: if (pszParentUUID && Guid(pszParentUUID).isValid()) typeStr = "normal (differencing)"; else typeStr = "normal (base)"; break; case MediumType_Immutable: typeStr = "immutable"; break; case MediumType_Writethrough: typeStr = "writethrough"; break; case MediumType_Shareable: typeStr = "shareable"; break; case MediumType_Readonly: typeStr = "readonly"; break; case MediumType_MultiAttach: typeStr = "multiattach"; break; } RTPrintf("Type: %s\n", typeStr); /* print out information specific for differencing hard disks */ if (fOptLong && pszParentUUID && Guid(pszParentUUID).isValid()) { BOOL autoReset = FALSE; pMedium->COMGETTER(AutoReset)(&autoReset); RTPrintf("Auto-Reset: %s\n", autoReset ? "on" : "off"); } Bstr loc; pMedium->COMGETTER(Location)(loc.asOutParam()); RTPrintf("Location: %ls\n", loc.raw()); Bstr format; pMedium->COMGETTER(Format)(format.asOutParam()); RTPrintf("Storage format: %ls\n", format.raw()); if (fOptLong) { com::SafeArray<MediumVariant_T> safeArray_variant; pMedium->COMGETTER(Variant)(ComSafeArrayAsOutParam(safeArray_variant)); ULONG variant=0; for (size_t i = 0; i < safeArray_variant.size(); i++) variant |= safeArray_variant[i]; const char *variantStr = "unknown"; switch (variant & ~(MediumVariant_Fixed | MediumVariant_Diff)) { case MediumVariant_VmdkSplit2G: variantStr = "split2G"; break; case MediumVariant_VmdkStreamOptimized: variantStr = "streamOptimized"; break; case MediumVariant_VmdkESX: variantStr = "ESX"; break; case MediumVariant_Standard: variantStr = "default"; break; } const char *variantTypeStr = "dynamic"; if (variant & MediumVariant_Fixed) variantTypeStr = "fixed"; else if (variant & MediumVariant_Diff) variantTypeStr = "differencing"; RTPrintf("Format variant: %s %s\n", variantTypeStr, variantStr); } LONG64 logicalSize; pMedium->COMGETTER(LogicalSize)(&logicalSize); RTPrintf("Capacity: %lld MBytes\n", logicalSize >> 20); if (fOptLong) { LONG64 actualSize; pMedium->COMGETTER(Size)(&actualSize); RTPrintf("Size on disk: %lld MBytes\n", actualSize >> 20); } if (fOptLong) { com::SafeArray<BSTR> names; com::SafeArray<BSTR> values; pMedium->GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values)); size_t cNames = names.size(); size_t cValues = values.size(); bool fFirst = true; for (size_t i = 0; i < cNames; i++) { Bstr value; if (i < cValues) value = values[i]; RTPrintf("%s%ls=%ls\n", fFirst ? "Property: " : " ", names[i], value.raw()); } } if (fOptLong) { bool fFirst = true; com::SafeArray<BSTR> machineIds; pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds)); for (size_t i = 0; i < machineIds.size(); i++) { ComPtr<IMachine> machine; CHECK_ERROR(pVirtualBox, FindMachine(machineIds[i], machine.asOutParam())); if (machine) { Bstr name; machine->COMGETTER(Name)(name.asOutParam()); machine->COMGETTER(Id)(uuid.asOutParam()); RTPrintf("%s%ls (UUID: %ls)", fFirst ? "In use by VMs: " : " ", name.raw(), machineIds[i]); fFirst = false; com::SafeArray<BSTR> snapshotIds; pMedium->GetSnapshotIds(machineIds[i], ComSafeArrayAsOutParam(snapshotIds)); for (size_t j = 0; j < snapshotIds.size(); j++) { ComPtr<ISnapshot> snapshot; machine->FindSnapshot(snapshotIds[j], snapshot.asOutParam()); if (snapshot) { Bstr snapshotName; snapshot->COMGETTER(Name)(snapshotName.asOutParam()); RTPrintf(" [%ls (UUID: %ls)]", snapshotName.raw(), snapshotIds[j]); } } RTPrintf("\n"); } } } if (fOptLong) { com::SafeIfaceArray<IMedium> children; pMedium->COMGETTER(Children)(ComSafeArrayAsOutParam(children)); bool fFirst = true; for (size_t i = 0; i < children.size(); i++) { ComPtr<IMedium> pChild(children[i]); if (pChild) { Bstr childUUID; pChild->COMGETTER(Id)(childUUID.asOutParam()); RTPrintf("%s%ls\n", fFirst ? "Child UUIDs: " : " ", childUUID.raw()); fFirst = false; } } } } while (0); return rc; }
DECLEXPORT(AuthResult) AUTHCALL AuthEntry(const char *szCaller, PAUTHUUID pUuid, AuthGuestJudgement guestJudgement, const char *szUser, const char *szPassword, const char *szDomain, int fLogon, unsigned clientId) { /* default is failed */ AuthResult result = AuthResultAccessDenied; /* only interested in logon */ if (!fLogon) /* return value ignored */ return result; char uuid[RTUUID_STR_LENGTH] = {0}; if (pUuid) RTUuidToStr((PCRTUUID)pUuid, (char*)uuid, RTUUID_STR_LENGTH); /* the user might contain a domain name, split it */ char *user = strchr((char*)szUser, '\\'); if (user) user++; else user = (char*)szUser; dprintf("VBoxAuth: uuid: %s, user: %s, szPassword: %s\n", uuid, user, szPassword); ComPtr<IVirtualBoxClient> virtualBoxClient; ComPtr<IVirtualBox> virtualBox; HRESULT rc; rc = virtualBoxClient.createInprocObject(CLSID_VirtualBoxClient); if (SUCCEEDED(rc)) rc = virtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam()); if (SUCCEEDED(rc)) { Bstr key = BstrFmt("VBoxAuthSimple/users/%s", user); Bstr password; /* lookup in VM's extra data? */ if (pUuid) { ComPtr<IMachine> machine; virtualBox->FindMachine(Bstr(uuid).raw(), machine.asOutParam()); if (machine) machine->GetExtraData(key.raw(), password.asOutParam()); } else /* lookup global extra data */ virtualBox->GetExtraData(key.raw(), password.asOutParam()); if (!password.isEmpty()) { /* calculate hash */ uint8_t abDigest[RTSHA256_HASH_SIZE]; RTSha256(szPassword, strlen(szPassword), abDigest); char pszDigest[RTSHA256_DIGEST_LEN + 1]; RTSha256ToString(abDigest, pszDigest, sizeof(pszDigest)); if (password == pszDigest) result = AuthResultAccessGranted; } } else dprintf("VBoxAuth: failed to get VirtualBox object reference: %Rhrc\n", rc); return result; }
HRESULT VRDEServer::getVRDEProperties(std::vector<com::Utf8Str> &aProperties) { size_t cProperties = 0; aProperties.resize(0); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); if (!mData->mEnabled) { return S_OK; } alock.release(); /* * Check that a VRDE extension pack name is set and resolve it into a * library path. */ Bstr bstrExtPack; HRESULT hrc = COMGETTER(VRDEExtPack)(bstrExtPack.asOutParam()); Log(("VRDEPROP: get extpack hrc 0x%08X, isEmpty %d\n", hrc, bstrExtPack.isEmpty())); if (FAILED(hrc)) return hrc; if (bstrExtPack.isEmpty()) return E_FAIL; Utf8Str strExtPack(bstrExtPack); Utf8Str strVrdeLibrary; int vrc = VINF_SUCCESS; if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME)) strVrdeLibrary = "VBoxVRDP"; else { #ifdef VBOX_WITH_EXTPACK VirtualBox *pVirtualBox = mParent->i_getVirtualBox(); ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager(); vrc = pExtPackMgr->i_getVrdeLibraryPathForExtPack(&strExtPack, &strVrdeLibrary); #else vrc = VERR_FILE_NOT_FOUND; #endif } Log(("VRDEPROP: library get rc %Rrc\n", vrc)); if (RT_SUCCESS(vrc)) { /* * Load the VRDE library and start the server, if it is enabled. */ PFNVRDESUPPORTEDPROPERTIES pfn = NULL; RTLDRMOD hmod = NIL_RTLDRMOD; vrc = loadVRDELibrary(strVrdeLibrary.c_str(), &hmod, &pfn); Log(("VRDEPROP: load library [%s] rc %Rrc\n", strVrdeLibrary.c_str(), vrc)); if (RT_SUCCESS(vrc)) { const char * const *papszNames = pfn(); if (papszNames) { size_t i; for (i = 0; papszNames[i] != NULL; ++i) { cProperties++; } } Log(("VRDEPROP: %d properties\n", cProperties)); if (cProperties > 0) { aProperties.resize(cProperties); for (size_t i = 0; papszNames[i] != NULL && i < cProperties; ++i) { aProperties[i] = papszNames[i]; } } /* Do not forget to unload the library. */ RTLdrClose(hmod); hmod = NIL_RTLDRMOD; } } if (RT_FAILURE(vrc)) { return E_FAIL; } return S_OK; }
/** * Returns true if the given USB device matches to at least one of * this controller's USB device filters. * * A generic version that accepts any IUSBDevice on input. * * @note * This method MUST correlate with HostUSBDevice::isMatch() * in the sense of the device matching logic. * * @note Locks this object for reading. */ bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs) { LogFlowThisFuncEnter(); AutoCaller autoCaller(this); AssertComRCReturn (autoCaller.rc(), false); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); /* Disabled USB controllers cannot actually work with USB devices */ if (!m->bd->fEnabled) return false; HRESULT rc = S_OK; /* query fields */ USBFILTER dev; USBFilterInit (&dev, USBFILTERTYPE_CAPTURE); USHORT vendorId = 0; rc = aUSBDevice->COMGETTER(VendorId) (&vendorId); ComAssertComRCRet(rc, false); ComAssertRet(vendorId, false); int vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_VENDOR_ID, vendorId, true); AssertRC(vrc); USHORT productId = 0; rc = aUSBDevice->COMGETTER(ProductId) (&productId); ComAssertComRCRet(rc, false); vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_PRODUCT_ID, productId, true); AssertRC(vrc); USHORT revision; rc = aUSBDevice->COMGETTER(Revision) (&revision); ComAssertComRCRet(rc, false); vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_DEVICE, revision, true); AssertRC(vrc); Bstr manufacturer; rc = aUSBDevice->COMGETTER(Manufacturer) (manufacturer.asOutParam()); ComAssertComRCRet(rc, false); if (!manufacturer.isEmpty()) USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true); Bstr product; rc = aUSBDevice->COMGETTER(Product) (product.asOutParam()); ComAssertComRCRet(rc, false); if (!product.isEmpty()) USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true); Bstr serialNumber; rc = aUSBDevice->COMGETTER(SerialNumber) (serialNumber.asOutParam()); ComAssertComRCRet(rc, false); if (!serialNumber.isEmpty()) USBFilterSetStringExact (&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber).c_str(), true); Bstr address; rc = aUSBDevice->COMGETTER(Address) (address.asOutParam()); ComAssertComRCRet(rc, false); USHORT port = 0; rc = aUSBDevice->COMGETTER(Port)(&port); ComAssertComRCRet(rc, false); USBFilterSetNumExact (&dev, USBFILTERIDX_PORT, port, true); BOOL remote = FALSE; rc = aUSBDevice->COMGETTER(Remote)(&remote); ComAssertComRCRet(rc, false); ComAssertRet(remote == TRUE, false); bool match = false; /* apply self filters */ for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin(); it != m->llDeviceFilters->end(); ++ it) { AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS); const USBDeviceFilter::Data &aData = (*it)->getData(); if (!aData.mActive) continue; if (!aData.mRemote.isMatch (remote)) continue; if (!USBFilterMatch (&aData.mUSBFilter, &dev)) continue; match = true; *aMaskedIfs = aData.mMaskedIfs; break; } LogFlowThisFunc(("returns: %d\n", match)); LogFlowThisFuncLeave(); return match; }
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; }
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; }
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 */; } }
int handleCloneHardDisk(HandlerArg *a) { HRESULT rc; int vrc; const char *pszSrc = NULL; const char *pszDst = NULL; Bstr format; MediumVariant_T DiskVariant = MediumVariant_Standard; bool fExisting = false; int c; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; // start at 0 because main() has hacked both the argc and argv given to us RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneHardDiskOptions, RT_ELEMENTS(g_aCloneHardDiskOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); while ((c = RTGetOpt(&GetState, &ValueUnion))) { switch (c) { case 'o': // --format format = ValueUnion.psz; break; case 'F': // --static { unsigned uDiskVariant = (unsigned)DiskVariant; uDiskVariant |= MediumVariant_Fixed; DiskVariant = (MediumVariant_T)uDiskVariant; break; } case 'E': // --existing fExisting = true; break; case 'm': // --variant vrc = parseDiskVariant(ValueUnion.psz, &DiskVariant); if (RT_FAILURE(vrc)) return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz); break; case VINF_GETOPT_NOT_OPTION: if (!pszSrc) pszSrc = ValueUnion.psz; else if (!pszDst) pszDst = ValueUnion.psz; else return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", ValueUnion.psz); break; default: if (c > 0) { if (RT_C_IS_GRAPH(c)) return errorSyntax(USAGE_CLONEHD, "unhandled option: -%c", c); else return errorSyntax(USAGE_CLONEHD, "unhandled option: %i", c); } else if (c == VERR_GETOPT_UNKNOWN_OPTION) return errorSyntax(USAGE_CLONEHD, "unknown option: %s", ValueUnion.psz); else if (ValueUnion.pDef) return errorSyntax(USAGE_CLONEHD, "%s: %Rrs", ValueUnion.pDef->pszLong, c); else return errorSyntax(USAGE_CLONEHD, "error: %Rrs", c); } } if (!pszSrc) return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing"); if (!pszDst) return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing"); if (fExisting && (!format.isEmpty() || DiskVariant != MediumType_Normal)) return errorSyntax(USAGE_CLONEHD, "Specified options which cannot be used with --existing"); ComPtr<IMedium> srcDisk; ComPtr<IMedium> dstDisk; rc = openMedium(a, pszSrc, DeviceType_HardDisk, AccessMode_ReadOnly, srcDisk, false /* fForceNewUuidOnOpen */, false /* fSilent */); if (FAILED(rc)) return 1; do { /* open/create destination hard disk */ if (fExisting) { rc = openMedium(a, pszDst, DeviceType_HardDisk, AccessMode_ReadWrite, dstDisk, false /* fForceNewUuidOnOpen */, false /* fSilent */); if (FAILED(rc)) break; /* Perform accessibility check now. */ MediumState_T state; CHECK_ERROR_BREAK(dstDisk, RefreshState(&state)); CHECK_ERROR_BREAK(dstDisk, COMGETTER(Format)(format.asOutParam())); } else { /* use the format of the source hard disk if unspecified */ if (format.isEmpty()) CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format)(format.asOutParam())); rc = createHardDisk(a, Utf8Str(format).c_str(), pszDst, dstDisk); if (FAILED(rc)) break; } ComPtr<IProgress> progress; com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8); for (ULONG i = 0; i < l_variants.size(); ++i) { ULONG temp = DiskVariant; temp &= 1<<i; l_variants [i] = (MediumVariant_T)temp; } CHECK_ERROR_BREAK(srcDisk, CloneTo(dstDisk, ComSafeArrayAsInParam(l_variants), NULL, progress.asOutParam())); rc = showProgress(progress); CHECK_PROGRESS_ERROR_BREAK(progress, ("Failed to clone hard disk")); Bstr uuid; CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam())); RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n", format.raw(), Utf8Str(uuid).c_str()); } while (0); return SUCCEEDED(rc) ? 0 : 1; }
/** * Sets the general Guest Additions information like * API (interface) version and OS type. Gets called by * vmmdevUpdateGuestInfo. * * @param aInterfaceVersion * @param aOsType */ void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType) { RTTIMESPEC TimeSpecTS; RTTimeNow(&TimeSpecTS); AutoCaller autoCaller(this); AssertComRCReturnVoid(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* * Note: The Guest Additions API (interface) version is deprecated * and will not be used anymore! We might need it to at least report * something as version number if *really* ancient Guest Additions are * installed (without the guest version + revision properties having set). */ mData.mInterfaceVersion = aInterfaceVersion; /* * Older Additions rely on the Additions API version whether they * are assumed to be active or not. Since newer Additions do report * the Additions version *before* calling this function (by calling * VMMDevReportGuestInfo2, VMMDevReportGuestStatus, VMMDevReportGuestInfo, * in that order) we can tell apart old and new Additions here. Old * Additions never would set VMMDevReportGuestInfo2 (which set mData.mAdditionsVersion) * so they just rely on the aInterfaceVersion string (which gets set by * VMMDevReportGuestInfo). * * So only mark the Additions as being active (run level = system) when we * don't have the Additions version set. */ if (mData.mAdditionsVersionNew.isEmpty()) { if (aInterfaceVersion.isEmpty()) mData.mAdditionsRunLevel = AdditionsRunLevelType_None; else { mData.mAdditionsRunLevel = AdditionsRunLevelType_System; /* * To keep it compatible with the old Guest Additions behavior we need to set the * "graphics" (feature) facility to active as soon as we got the Guest Additions * interface version. */ facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active, 0 /*fFlags*/, &TimeSpecTS); } } /* * Older Additions didn't have this finer grained capability bit, * so enable it by default. Newer Additions will not enable this here * and use the setSupportedFeatures function instead. */ /** @todo r=bird: I don't get the above comment nor the code below... * One talks about capability bits, the one always does something to a facility. * Then there is the comment below it all, which is placed like it addresses the * mOSTypeId, but talks about something which doesn't remotely like mOSTypeId... * * Andy, could you please try clarify and make the comments shorter and more * coherent! Also, explain why this is important and what depends on it. * * PS. There is the VMMDEV_GUEST_SUPPORTS_GRAPHICS capability* report... It * should come in pretty quickly after this update, normally. */ facilityUpdate(VBoxGuestFacilityType_Graphics, facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver) ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive, 0 /*fFlags*/, &TimeSpecTS); /** @todo the timestamp isn't gonna be right here on saved state restore. */ /* * Note! There is a race going on between setting mAdditionsRunLevel and * mSupportsGraphics here and disabling/enabling it later according to * its real status when using new(er) Guest Additions. */ mData.mOSTypeId = Global::OSTypeId(aOsType); }