diff options
Diffstat (limited to 'src/VBox/Main/src-server/VirtualBoxImpl.cpp')
-rw-r--r-- | src/VBox/Main/src-server/VirtualBoxImpl.cpp | 296 |
1 files changed, 204 insertions, 92 deletions
diff --git a/src/VBox/Main/src-server/VirtualBoxImpl.cpp b/src/VBox/Main/src-server/VirtualBoxImpl.cpp index 94376c27a..2770f5205 100644 --- a/src/VBox/Main/src-server/VirtualBoxImpl.cpp +++ b/src/VBox/Main/src-server/VirtualBoxImpl.cpp @@ -1,11 +1,11 @@ -/* $Id: VirtualBoxImpl.cpp $ */ +/* $Id: VirtualBoxImpl.cpp 37985 2011-07-15 15:04:39Z vboxsync $ */ /** @file * Implementation of IVirtualBox in VBoxSVC. */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -103,49 +103,8 @@ ULONG VirtualBox::sRevision; // static Bstr VirtualBox::sPackageType; -//////////////////////////////////////////////////////////////////////////////// -// -// VirtualBoxCallbackRegistration -// -//////////////////////////////////////////////////////////////////////////////// - -/** - * Registered IVirtualBoxCallback, used by VirtualBox::CallbackList and - * VirtualBox::Data::llCallbacks. - * - * In addition to keeping the interface pointer this also keeps track of the - * methods that asked to not be called again. The latter is for reducing - * unnecessary IPC. - */ -class VirtualBoxCallbackRegistration -{ -public: - /** Callback bit indexes (for bmDisabled). */ - typedef enum - { - kOnMachineStateChanged = 0, - kOnMachineDataChanged, - kOnExtraDataCanChange, - kOnExtraDataChanged, - kOnMediumRegistered, - kOnMachineRegistered, - kOnSessionStateChanged, - kOnSnapshotTaken, - kOnSnapshotDeleted, - kOnSnapshotChanged, - kOnGuestPropertyChanged - } CallbackBit; - - VirtualBoxCallbackRegistration() - { - /* nothing */ - } - - ~VirtualBoxCallbackRegistration() - { - /* nothing */ - } -}; +// static +Bstr VirtualBox::sAPIVersion; //////////////////////////////////////////////////////////////////////////////// // @@ -167,7 +126,7 @@ class VirtualBox::CallbackEvent : public Event { public: - CallbackEvent(VirtualBox *aVirtualBox, VirtualBoxCallbackRegistration::CallbackBit aWhat) + CallbackEvent(VirtualBox *aVirtualBox, VBoxEventType_T aWhat) : mVirtualBox(aVirtualBox), mWhat(aWhat) { Assert(aVirtualBox); @@ -183,9 +142,9 @@ private: * Note that this is a weak ref -- the CallbackEvent handler thread * is bound to the lifetime of the VirtualBox instance, so it's safe. */ - VirtualBox *mVirtualBox; + VirtualBox *mVirtualBox; protected: - VirtualBoxCallbackRegistration::CallbackBit mWhat; + VBoxEventType_T mWhat; }; //////////////////////////////////////////////////////////////////////////////// @@ -343,7 +302,11 @@ HRESULT VirtualBox::FinalConstruct() { LogFlowThisFunc(("\n")); - return init(); + HRESULT rc = init(); + + BaseFinalConstruct(); + + return rc; } void VirtualBox::FinalRelease() @@ -351,6 +314,8 @@ void VirtualBox::FinalRelease() LogFlowThisFunc(("\n")); uninit(); + + BaseFinalRelease(); } // public initializer/uninitializer for internal purposes only @@ -383,7 +348,9 @@ HRESULT VirtualBox::init() sRevision = RTBldCfgRevision(); if (sPackageType.isEmpty()) sPackageType = VBOX_PACKAGE_STRING; - LogFlowThisFunc(("Version: %ls, Package: %ls\n", sVersion.raw(), sPackageType.raw())); + if (sAPIVersion.isEmpty()) + sAPIVersion = VBOX_API_VERSION_STRING; + LogFlowThisFunc(("Version: %ls, Package: %ls, API Version: %ls\n", sVersion.raw(), sPackageType.raw(), sAPIVersion.raw())); /* Get the VirtualBox home directory. */ { @@ -881,6 +848,17 @@ STDMETHODIMP VirtualBox::COMGETTER(PackageType)(BSTR *aPackageType) return S_OK; } +STDMETHODIMP VirtualBox::COMGETTER(APIVersion)(BSTR *aAPIVersion) +{ + CheckComArgNotNull(aAPIVersion); + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + sAPIVersion.cloneTo(aAPIVersion); + return S_OK; +} + STDMETHODIMP VirtualBox::COMGETTER(HomeFolder)(BSTR *aHomeFolder) { CheckComArgNotNull(aHomeFolder); @@ -1102,6 +1080,138 @@ VirtualBox::COMGETTER(ExtensionPackManager)(IExtPackManager **aExtPackManager) return hrc; } +STDMETHODIMP VirtualBox::COMGETTER(InternalNetworks)(ComSafeArrayOut(BSTR, aInternalNetworks)) +{ + if (ComSafeArrayOutIsNull(aInternalNetworks)) + return E_POINTER; + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + std::list<Bstr> allInternalNetworks; + + /* get copy of all machine references, to avoid holding the list lock */ + MachinesOList::MyList allMachines; + { + AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS); + allMachines = m->allMachines.getList(); + } + for (MachinesOList::MyList::const_iterator it = allMachines.begin(); + it != allMachines.end(); + ++it) + { + const ComObjPtr<Machine> &pMachine = *it; + AutoCaller autoMachineCaller(pMachine); + if (FAILED(autoMachineCaller.rc())) + continue; + AutoReadLock mlock(pMachine COMMA_LOCKVAL_SRC_POS); + + if (pMachine->isAccessible()) + { + ULONG cNetworkAdapters = 0; + HRESULT rc = m->pSystemProperties->GetMaxNetworkAdapters(pMachine->getChipsetType(), &cNetworkAdapters); + if (FAILED(rc)) + continue; + cNetworkAdapters = RT_MIN(4, cNetworkAdapters); + for (ULONG i = 0; i < cNetworkAdapters; i++) + { + ComPtr<INetworkAdapter> pNet; + rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam()); + if (FAILED(rc) || pNet.isNull()) + continue; + Bstr strInternalNetwork; + rc = pNet->COMGETTER(InternalNetwork)(strInternalNetwork.asOutParam()); + if (FAILED(rc) || strInternalNetwork.isEmpty()) + continue; + + allInternalNetworks.push_back(strInternalNetwork); + } + } + } + + /* throw out any duplicates */ + allInternalNetworks.sort(); + allInternalNetworks.unique(); + com::SafeArray<BSTR> internalNetworks(allInternalNetworks.size()); + size_t i = 0; + for (std::list<Bstr>::const_iterator it = allInternalNetworks.begin(); + it != allInternalNetworks.end(); + ++it, i++) + { + const Bstr &tmp = *it; + tmp.cloneTo(&internalNetworks[i]); + } + internalNetworks.detachTo(ComSafeArrayOutArg(aInternalNetworks)); + + return S_OK; +} + +STDMETHODIMP VirtualBox::COMGETTER(GenericNetworkDrivers)(ComSafeArrayOut(BSTR, aGenericNetworkDrivers)) +{ + if (ComSafeArrayOutIsNull(aGenericNetworkDrivers)) + return E_POINTER; + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + std::list<Bstr> allGenericNetworkDrivers; + + /* get copy of all machine references, to avoid holding the list lock */ + MachinesOList::MyList allMachines; + { + AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS); + allMachines = m->allMachines.getList(); + } + for (MachinesOList::MyList::const_iterator it = allMachines.begin(); + it != allMachines.end(); + ++it) + { + const ComObjPtr<Machine> &pMachine = *it; + AutoCaller autoMachineCaller(pMachine); + if (FAILED(autoMachineCaller.rc())) + continue; + AutoReadLock mlock(pMachine COMMA_LOCKVAL_SRC_POS); + + if (pMachine->isAccessible()) + { + ULONG cNetworkAdapters = 0; + HRESULT rc = m->pSystemProperties->GetMaxNetworkAdapters(pMachine->getChipsetType(), &cNetworkAdapters); + if (FAILED(rc)) + continue; + cNetworkAdapters = RT_MIN(4, cNetworkAdapters); + for (ULONG i = 0; i < cNetworkAdapters; i++) + { + ComPtr<INetworkAdapter> pNet; + rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam()); + if (FAILED(rc) || pNet.isNull()) + continue; + Bstr strGenericNetworkDriver; + rc = pNet->COMGETTER(GenericDriver)(strGenericNetworkDriver.asOutParam()); + if (FAILED(rc) || strGenericNetworkDriver.isEmpty()) + continue; + + allGenericNetworkDrivers.push_back(strGenericNetworkDriver); + } + } + } + + /* throw out any duplicates */ + allGenericNetworkDrivers.sort(); + allGenericNetworkDrivers.unique(); + com::SafeArray<BSTR> genericNetworks(allGenericNetworkDrivers.size()); + size_t i = 0; + for (std::list<Bstr>::const_iterator it = allGenericNetworkDrivers.begin(); + it != allGenericNetworkDrivers.end(); + ++it, i++) + { + const Bstr &tmp = *it; + tmp.cloneTo(&genericNetworks[i]); + } + genericNetworks.detachTo(ComSafeArrayOutArg(aGenericNetworkDrivers)); + + return S_OK; +} + STDMETHODIMP VirtualBox::CheckFirmwarePresent(FirmwareType_T aFirmwareType, IN_BSTR aVersion, @@ -1114,11 +1224,10 @@ VirtualBox::CheckFirmwarePresent(FirmwareType_T aFirmwareType, AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); - const char *url; - NOREF(aVersion); - static const struct { + static const struct + { FirmwareType_T type; const char* fileName; const char* url; @@ -1153,22 +1262,23 @@ VirtualBox::CheckFirmwarePresent(FirmwareType_T aFirmwareType, } Utf8Str shortName, fullName; - int rc; shortName = Utf8StrFmt("Firmware%c%s", RTPATH_DELIMITER, firmwareDesc[i].fileName); - rc = calculateFullPath(shortName, fullName); AssertRCReturn(rc, rc); + int rc = calculateFullPath(shortName, fullName); + AssertRCReturn(rc, rc); if (RTFileExists(fullName.c_str())) { *aResult = TRUE; - if (aFile) + if (aFile) Utf8Str(fullName).cloneTo(aFile); break; } char pszVBoxPath[RTPATH_MAX]; - rc = RTPathExecDir(pszVBoxPath, RTPATH_MAX); AssertRCReturn(rc, rc); + rc = RTPathExecDir(pszVBoxPath, RTPATH_MAX); + AssertRCReturn(rc, rc); fullName = Utf8StrFmt("%s%c%s", pszVBoxPath, RTPATH_DELIMITER, @@ -1181,8 +1291,6 @@ VirtualBox::CheckFirmwarePresent(FirmwareType_T aFirmwareType, break; } - - url = firmwareDesc[i].url; /** @todo: account for version in the URL */ if (aUrl != NULL) { @@ -1461,6 +1569,7 @@ STDMETHODIMP VirtualBox::CreateHardDisk(IN_BSTR aFormat, STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation, DeviceType_T deviceType, AccessMode_T accessMode, + BOOL fForceNewUuid, IMedium **aMedium) { CheckComArgStrNotEmptyOrNull(aLocation); @@ -1508,6 +1617,7 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation, rc = pMedium->init(this, aLocation, (accessMode == AccessMode_ReadWrite) ? Medium::OpenReadWrite : Medium::OpenReadOnly, + fForceNewUuid, deviceType); if (SUCCEEDED(rc)) @@ -2205,34 +2315,30 @@ void VirtualBox::addProcessToReap(RTPROCESS pid) /** Event for onMachineStateChange(), onMachineDataChange(), onMachineRegistered() */ struct MachineEvent : public VirtualBox::CallbackEvent { - MachineEvent(VirtualBox *aVB, const Guid &aId) - : CallbackEvent(aVB, VirtualBoxCallbackRegistration::kOnMachineDataChanged), id(aId.toUtf16()) - {} - - MachineEvent(VirtualBox *aVB, const Guid &aId, MachineState_T aState) - : CallbackEvent(aVB, VirtualBoxCallbackRegistration::kOnMachineStateChanged), id(aId.toUtf16()) - , state(aState) - {} - - MachineEvent(VirtualBox *aVB, const Guid &aId, BOOL aRegistered) - : CallbackEvent(aVB, VirtualBoxCallbackRegistration::kOnMachineRegistered), id(aId.toUtf16()) - , registered(aRegistered) + MachineEvent(VirtualBox *aVB, VBoxEventType_T aWhat, const Guid &aId, BOOL aBool) + : CallbackEvent(aVB, aWhat), id(aId.toUtf16()) + , mBool(aBool) + { } + + MachineEvent(VirtualBox *aVB, VBoxEventType_T aWhat, const Guid &aId, MachineState_T aState) + : CallbackEvent(aVB, aWhat), id(aId.toUtf16()) + , mState(aState) {} virtual HRESULT prepareEventDesc(IEventSource* aSource, VBoxEventDesc& aEvDesc) { switch (mWhat) { - case VirtualBoxCallbackRegistration::kOnMachineDataChanged: - aEvDesc.init(aSource, VBoxEventType_OnMachineDataChanged, id.raw()); + case VBoxEventType_OnMachineDataChanged: + aEvDesc.init(aSource, mWhat, id.raw(), mBool); break; - case VirtualBoxCallbackRegistration::kOnMachineStateChanged: - aEvDesc.init(aSource, VBoxEventType_OnMachineStateChanged, id.raw(), state); + case VBoxEventType_OnMachineStateChanged: + aEvDesc.init(aSource, mWhat, id.raw(), mState); break; - case VirtualBoxCallbackRegistration::kOnMachineRegistered: - aEvDesc.init(aSource, VBoxEventType_OnMachineRegistered, id.raw(), registered); + case VBoxEventType_OnMachineRegistered: + aEvDesc.init(aSource, mWhat, id.raw(), mBool); break; default: @@ -2242,8 +2348,8 @@ struct MachineEvent : public VirtualBox::CallbackEvent } Bstr id; - MachineState_T state; - BOOL registered; + MachineState_T mState; + BOOL mBool; }; /** @@ -2251,15 +2357,15 @@ struct MachineEvent : public VirtualBox::CallbackEvent */ void VirtualBox::onMachineStateChange(const Guid &aId, MachineState_T aState) { - postEvent(new MachineEvent(this, aId, aState)); + postEvent(new MachineEvent(this, VBoxEventType_OnMachineStateChanged, aId, aState)); } /** * @note Doesn't lock any object. */ -void VirtualBox::onMachineDataChange(const Guid &aId) +void VirtualBox::onMachineDataChange(const Guid &aId, BOOL aTemporary) { - postEvent(new MachineEvent(this, aId)); + postEvent(new MachineEvent(this, VBoxEventType_OnMachineDataChanged, aId, aTemporary)); } /** @@ -2311,7 +2417,7 @@ struct ExtraDataEvent : public VirtualBox::CallbackEvent { ExtraDataEvent(VirtualBox *aVB, const Guid &aMachineId, IN_BSTR aKey, IN_BSTR aVal) - : CallbackEvent(aVB, VirtualBoxCallbackRegistration::kOnExtraDataChanged) + : CallbackEvent(aVB, VBoxEventType_OnExtraDataChanged) , machineId(aMachineId.toUtf16()), key(aKey), val(aVal) {} @@ -2336,14 +2442,14 @@ void VirtualBox::onExtraDataChange(const Guid &aId, IN_BSTR aKey, IN_BSTR aValue */ void VirtualBox::onMachineRegistered(const Guid &aId, BOOL aRegistered) { - postEvent(new MachineEvent(this, aId, aRegistered)); + postEvent(new MachineEvent(this, VBoxEventType_OnMachineRegistered, aId, aRegistered)); } /** Event for onSessionStateChange() */ struct SessionEvent : public VirtualBox::CallbackEvent { SessionEvent(VirtualBox *aVB, const Guid &aMachineId, SessionState_T aState) - : CallbackEvent(aVB, VirtualBoxCallbackRegistration::kOnSessionStateChanged) + : CallbackEvent(aVB, VBoxEventType_OnSessionStateChanged) , machineId(aMachineId.toUtf16()), sessionState(aState) {} @@ -2367,7 +2473,7 @@ void VirtualBox::onSessionStateChange(const Guid &aId, SessionState_T aState) struct SnapshotEvent : public VirtualBox::CallbackEvent { SnapshotEvent(VirtualBox *aVB, const Guid &aMachineId, const Guid &aSnapshotId, - VirtualBoxCallbackRegistration::CallbackBit aWhat) + VBoxEventType_T aWhat) : CallbackEvent(aVB, aWhat) , machineId(aMachineId), snapshotId(aSnapshotId) {} @@ -2388,7 +2494,7 @@ struct SnapshotEvent : public VirtualBox::CallbackEvent void VirtualBox::onSnapshotTaken(const Guid &aMachineId, const Guid &aSnapshotId) { postEvent(new SnapshotEvent(this, aMachineId, aSnapshotId, - VirtualBoxCallbackRegistration::kOnSnapshotTaken)); + VBoxEventType_OnSnapshotTaken)); } /** @@ -2397,7 +2503,7 @@ void VirtualBox::onSnapshotTaken(const Guid &aMachineId, const Guid &aSnapshotId void VirtualBox::onSnapshotDeleted(const Guid &aMachineId, const Guid &aSnapshotId) { postEvent(new SnapshotEvent(this, aMachineId, aSnapshotId, - VirtualBoxCallbackRegistration::kOnSnapshotDeleted)); + VBoxEventType_OnSnapshotDeleted)); } /** @@ -2406,7 +2512,7 @@ void VirtualBox::onSnapshotDeleted(const Guid &aMachineId, const Guid &aSnapshot void VirtualBox::onSnapshotChange(const Guid &aMachineId, const Guid &aSnapshotId) { postEvent(new SnapshotEvent(this, aMachineId, aSnapshotId, - VirtualBoxCallbackRegistration::kOnSnapshotChanged)); + VBoxEventType_OnSnapshotChanged)); } /** Event for onGuestPropertyChange() */ @@ -2414,7 +2520,7 @@ struct GuestPropertyEvent : public VirtualBox::CallbackEvent { GuestPropertyEvent(VirtualBox *aVBox, const Guid &aMachineId, IN_BSTR aName, IN_BSTR aValue, IN_BSTR aFlags) - : CallbackEvent(aVBox, VirtualBoxCallbackRegistration::kOnGuestPropertyChanged), + : CallbackEvent(aVBox, VBoxEventType_OnGuestPropertyChanged), machineId(aMachineId), name(aName), value(aValue), @@ -3731,7 +3837,7 @@ HRESULT VirtualBox::unregisterMachine(Machine *pMachine, // 2) better registry found: then use that pMedium->addRegistry(*puuidBetter, true /* fRecurse */); // 3) and make sure the registry is saved below - addGuidToListUniquely(llRegistriesThatNeedSaving, *puuidBetter); + VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, *puuidBetter); } } } @@ -3753,6 +3859,7 @@ HRESULT VirtualBox::unregisterMachine(Machine *pMachine, * @param llRegistriesThatNeedSaving * @param uuid */ +/* static */ void VirtualBox::addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving, const Guid &uuid) { @@ -3883,7 +3990,7 @@ HRESULT VirtualBox::handleUnexpectedExceptions(RT_SRC_POS_DECL) /* re-throw the current exception */ throw; } - catch (const iprt::Error &err) // includes all XML exceptions + catch (const RTCError &err) // includes all XML exceptions { return setErrorStatic(E_FAIL, Utf8StrFmt(tr("%s.\n%s[%d] (%s)"), @@ -4420,6 +4527,8 @@ DECLCALLBACK(int) VirtualBox::AsyncEventHandler(RTTHREAD thread, void *pvUser) AssertReturn(pvUser, VERR_INVALID_POINTER); + com::Initialize(); + // create an event queue for the current thread EventQueue *eventQ = new EventQueue(); AssertReturn(eventQ, VERR_NO_MEMORY); @@ -4434,6 +4543,9 @@ DECLCALLBACK(int) VirtualBox::AsyncEventHandler(RTTHREAD thread, void *pvUser) delete eventQ; + com::Shutdown(); + + LogFlowFuncLeave(); return 0; |