VirtualBoxImpl.cpp revision f409459bdd4c15cdb8d7fb6c6d54338cce9ac814
af062818b47340eef15700d2f0211576ba3506eevboxsync * Implementation of IVirtualBox in VBoxSVC.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2010 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_WITH_RESOURCE_USAGE_API */
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// Definitions
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// Global variables
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// VirtualBoxCallbackRegistration
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync * Registered IVirtualBoxCallback, used by VirtualBox::CallbackList and
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox::Data::llCallbacks.
af062818b47340eef15700d2f0211576ba3506eevboxsync * In addition to keeping the interface pointer this also keeps track of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * methods that asked to not be called again. The latter is for reducing
af062818b47340eef15700d2f0211576ba3506eevboxsync * unnecessary IPC.
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Callback bit indexes (for bmDisabled). */
af062818b47340eef15700d2f0211576ba3506eevboxsync typedef enum
af062818b47340eef15700d2f0211576ba3506eevboxsync /* nothing */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* nothing */
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// CallbackEvent class
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync * Abstract callback event class to asynchronously call VirtualBox callbacks
af062818b47340eef15700d2f0211576ba3506eevboxsync * on a dedicated event thread. Subclasses reimplement #handleCallback()
af062818b47340eef15700d2f0211576ba3506eevboxsync * to call appropriate IVirtualBoxCallback methods depending on the event
af062818b47340eef15700d2f0211576ba3506eevboxsync * to be dispatched.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note The VirtualBox instance passed to the constructor is strongly
af062818b47340eef15700d2f0211576ba3506eevboxsync * referenced, so that the VirtualBox singleton won't be released until the
af062818b47340eef15700d2f0211576ba3506eevboxsync * event gets handled by the event thread.
af062818b47340eef15700d2f0211576ba3506eevboxsync CallbackEvent(VirtualBox *aVirtualBox, VirtualBoxCallbackRegistration::CallbackBit aWhat)
af062818b47340eef15700d2f0211576ba3506eevboxsync virtual HRESULT prepareEventDesc(IEventSource* aSource, VBoxEventDesc& aEvDesc) = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync * Note that this is a weak ref -- the CallbackEvent handler thread
af062818b47340eef15700d2f0211576ba3506eevboxsync * is bound to the lifetime of the VirtualBox instance, so it's safe.
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// VirtualBox private member data definition
af062818b47340eef15700d2f0211576ba3506eevboxsync////////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef ObjectsList<SharedFolder> SharedFoldersOList;
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef std::map<Guid, ComPtr<IProgress> > ProgressMap;
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap;
af062818b47340eef15700d2f0211576ba3506eevboxsync * Main VirtualBox data structure.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note |const| members are persistent during lifetime so can be accessed
af062818b47340eef15700d2f0211576ba3506eevboxsync * without locking.
af062818b47340eef15700d2f0211576ba3506eevboxsync // const data members not requiring locking
af062818b47340eef15700d2f0211576ba3506eevboxsync // VirtualBox main settings file
af062818b47340eef15700d2f0211576ba3506eevboxsync // const objects not requiring locking
af062818b47340eef15700d2f0211576ba3506eevboxsync const ComObjPtr<SystemProperties> pSystemProperties;
af062818b47340eef15700d2f0211576ba3506eevboxsync const ComObjPtr<PerformanceCollector> pPerformanceCollector;
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_WITH_RESOURCE_USAGE_API */
af062818b47340eef15700d2f0211576ba3506eevboxsync // Each of the following lists use a particular lock handle that protects the
af062818b47340eef15700d2f0211576ba3506eevboxsync // list as a whole. As opposed to version 3.1 and earlier, these lists no
af062818b47340eef15700d2f0211576ba3506eevboxsync // longer need the main VirtualBox object lock, but only the respective list
af062818b47340eef15700d2f0211576ba3506eevboxsync // lock. In each case, the locking order is defined that the list must be
af062818b47340eef15700d2f0211576ba3506eevboxsync // requested before object locks of members of the lists (see the order definitions
af062818b47340eef15700d2f0211576ba3506eevboxsync // in AutoLock.h; e.g. LOCKCLASS_LISTOFMACHINES before LOCKCLASS_MACHINEOBJECT).
af062818b47340eef15700d2f0211576ba3506eevboxsync // All the media lists are protected by the following locking handle:
af062818b47340eef15700d2f0211576ba3506eevboxsync // the hard disks map is an additional map sorted by UUID for quick lookup
af062818b47340eef15700d2f0211576ba3506eevboxsync // and contains ALL hard disks (base and differencing); it is protected by
af062818b47340eef15700d2f0211576ba3506eevboxsync // the same lock as the other media lists above
af062818b47340eef15700d2f0211576ba3506eevboxsync // list of pending machine renames (also protected by media tree lock;
af062818b47340eef15700d2f0211576ba3506eevboxsync // see VirtualBox::rememberMachineNameChangeForMedia())
af062818b47340eef15700d2f0211576ba3506eevboxsync typedef std::list<PendingMachineRename> PendingMachineRenamesList;
af062818b47340eef15700d2f0211576ba3506eevboxsync // the following are data for the client watcher thread
af062818b47340eef15700d2f0211576ba3506eevboxsync // the following are data for the async event thread
af062818b47340eef15700d2f0211576ba3506eevboxsync// constructor / destructor
af062818b47340eef15700d2f0211576ba3506eevboxsync/////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync// public initializer/uninitializer for internal purposes only
af062818b47340eef15700d2f0211576ba3506eevboxsync/////////////////////////////////////////////////////////////////////////////
af062818b47340eef15700d2f0211576ba3506eevboxsync * Initializes the VirtualBox object.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @return COM result code
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Enclose the state transition NotReady->InInit->Ready */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Locking this object for writing during init sounds a bit paradoxical,
af062818b47340eef15700d2f0211576ba3506eevboxsync * but in the current locking mess this avoids that some code gets a
af062818b47340eef15700d2f0211576ba3506eevboxsync * read lock and later calls code which wants the same write lock. */
af062818b47340eef15700d2f0211576ba3506eevboxsync // allocate our instance data
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlow(("===========================================================\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowThisFunc(("Version: %ls, Package: %ls\n", sVersion.raw(), sPackageType.raw()));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Get the VirtualBox home directory. */
af062818b47340eef15700d2f0211576ba3506eevboxsync int vrc = com::GetVBoxUserHomeDirectory(szHomeDir, sizeof(szHomeDir));
af062818b47340eef15700d2f0211576ba3506eevboxsync tr("Could not create the VirtualBox home directory '%s' (%Rrc)"),
af062818b47340eef15700d2f0211576ba3506eevboxsync /* compose the VirtualBox.xml file name */
af062818b47340eef15700d2f0211576ba3506eevboxsync unconst(m->strSettingsFilePath) = Utf8StrFmt("%s%c%s",
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fCreate = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync // load and parse VirtualBox.xml; this will throw on XML or logic errors
af062818b47340eef15700d2f0211576ba3506eevboxsync m->pMainConfigFile = new settings::MainConfigFile(&m->strSettingsFilePath);
af062818b47340eef15700d2f0211576ba3506eevboxsync // this is thrown by the XML backend if the RTOpen() call fails;
af062818b47340eef15700d2f0211576ba3506eevboxsync // only if the main settings file does not exist, create it,
af062818b47340eef15700d2f0211576ba3506eevboxsync // if there's something more serious, then do fail!
af062818b47340eef15700d2f0211576ba3506eevboxsync m->pMainConfigFile = new settings::MainConfigFile(NULL);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* create the performance collector object BEFORE host */
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_WITH_RESOURCE_USAGE_API */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* create the host object early, machines will need it */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = m->pHost->loadSettings(m->pMainConfigFile->host);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* create the system properties object, someone may need it too */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = m->pSystemProperties->loadSettings(m->pMainConfigFile->systemProperties);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* guest OS type objects, needed by machines */
af062818b47340eef15700d2f0211576ba3506eevboxsync for (size_t i = 0; i < RT_ELEMENTS(Global::sOSTypes); ++ i)
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = guestOSTypeObj->init(Global::sOSTypes[i].familyId,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* all registered media, needed by machines */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* machines */
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowThisFunc(("Dumping media backreferences\n"));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* net services */
af062818b47340eef15700d2f0211576ba3506eevboxsync for (settings::DHCPServersList::const_iterator it = m->pMainConfigFile->llDhcpServers.begin();
++it)
#if defined(RT_OS_WINDOWS)
return rc;
++it)
&uuid);
return rc;
return S_OK;
++it)
++it)
++it)
return S_OK;
if (m->pHost)
if (m->pSystemProperties)
if (m->pHost)
#ifdef VBOX_WITH_RESOURCE_USAGE_API
if (m->pPerformanceCollector)
if (m->pEventSource)
#if defined(RT_OS_WINDOWS)
VDShutdown();
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return E_POINTER;
return S_OK;
return E_POINTER;
return S_OK;
return E_POINTER;
return S_OK;
return E_POINTER;
return S_OK;
return S_OK;
return S_OK;
#ifndef RT_OS_WINDOWS
#ifdef VBOX_WITH_RESOURCE_USAGE_API
return S_OK;
return E_POINTER;
return S_OK;
return S_OK;
const char* fileName;
const char* url;
} firmwareDesc[] = {
int rc;
if (aFile)
if (aFile)
return S_OK;
LogFlowThisFunc(("aName=\"%ls\",aOsTypeId =\"%ls\",aBaseFolder=\"%ls\"\n", aName, aOsTypeId, aBaseFolder));
aName);
id,
return rc;
id,
return rc;
return rc;
return rc;
&machine);
return rc;
++it)
? S_OK
return rc;
bool fNeedsSaveSettings = false;
if (fNeedsSaveSettings)
saveSettings();
return rc;
if (aSetImageId)
if (aSetParentId)
parentId);
bool fNeedsSaveSettings = false;
if (fNeedsSaveSettings)
saveSettings();
return rc;
return rc;
return rc;
bool fNeedsSaveSettings = false;
if (fNeedsSaveSettings)
saveSettings();
return rc;
return rc;
return rc;
rc = image->init(this, aLocation, Medium::OpenReadWrite, DeviceType_Floppy, true, id, false, Guid());
bool fNeedsSaveSettings = false;
if (fNeedsSaveSettings)
saveSettings();
return rc;
return rc;
return rc;
static const wchar_t *kOldNewIDs[] =
++it)
aId);
using namespace settings;
return E_POINTER;
++it, ++i)
return S_OK;
settings::ExtraDataItemsMap::const_iterator it = m->pMainConfigFile->mapExtraDataItems.find(strKey);
return S_OK;
settings::ExtraDataItemsMap::const_iterator it = m->pMainConfigFile->mapExtraDataItems.find(strKey);
bool fChanged;
aKey,
sep,
err);
if (fChanged)
return S_OK;
#ifdef DEBUG
++mt)
++mt)
return S_OK;
return S_OK;
return E_FAIL;
return S_OK;
return S_OK;
#ifdef RT_OS_WINDOWS
struct StartSVCHelperClientData
bool privileged;
void *user;
d(new StartSVCHelperClientData());
d->that = this;
static_cast <void *>(d.get()),
d.release();
return S_OK;
DECLCALLBACK(int)
bool userFuncCalled = false;
if (!exePath)
if (d->privileged)
userFuncCalled = true;
#if defined(RT_OS_WINDOWS)
#ifndef RT_OS_WINDOWS
switch (mWhat)
return S_OK;
if (fDelivered)
if (!allowChange)
return allowChange;
return aEvDesc.init(aSource, VBoxEventType_OnExtraDataChanged, machineId.raw(), key.raw(), val.raw());
void *handler()
#ifdef VBOX_WITH_RESOURCE_USAGE_API
return NULL;
* already uninitialized, so do a usual AutoCaller/AutoReadLock sequence
if (aControls)
++it)
if (aControls)
bool fPermitInaccessible,
bool aSetError,
++it)
if (!fPermitInaccessible)
if (aMachine)
return rc;
bool aSetError,
if (aId)
if (aHardDisk)
return S_OK;
if (aLocation)
++ it)
if (result == 0)
if (aHardDisk)
if (aId)
return rc;
bool aSetError,
vrc);
bool found = false;
++ it)
if (found)
if (aImage)
if (aId)
return rc;
bool aSetError,
bool found = false;
++ it)
if (found)
if (aImage)
if (aId)
return rc;
return S_OK;
++it)
return S_OK;
return m->pHost;
return m->pSystemProperties;
#ifdef VBOX_WITH_RESOURCE_USAGE_API
return m->pPerformanceCollector;
return m->strHomeDir;
return vrc;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
* Helper function which actually writes out VirtualBox.xml, the main configuration file.
++it)
++it)
++it2)
++it)
++it)
++it)
++it)
return rc;
&pMachine);
return rc;
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
bool *pfNeedsSaveSettings)
tr("Cannot register the hard disk '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
if (pfNeedsSaveSettings)
*pfNeedsSaveSettings = true;
return rc;
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
bool *pfNeedsSaveSettings)
if (pfNeedsSaveSettings)
*pfNeedsSaveSettings = true;
return S_OK;
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
bool *pfNeedsSaveSettings)
tr("Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
if (pfNeedsSaveSettings)
*pfNeedsSaveSettings = true;
return rc;
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
bool *pfNeedsSaveSettings)
if (pfNeedsSaveSettings)
*pfNeedsSaveSettings = true;
return rc;
return rc;
vrc));
return S_OK;
AssertFailed();
return E_FAIL;
return m->strSettingsFilePath;
* objects contained in these lists. See AutoLock.h.
return m->lockMedia;
#if defined(RT_OS_WINDOWS)
INFINITE);
bool update = false;
update = true;
update = true;
update = true;
update = true;
if (update)
cnt = 0;
++it)
++cnt;
cntSpawned = 0;
++it)
if (rc == 0)
++cntSpawned;
::CoUninitialize();
bool update = false;
bool updateSpawned = false;
update = true;
updateSpawned = true;
if (cnt > 0)
unsigned long semId = 0;
#ifdef DEBUG
update = true;
unsigned long reqCnt;
if (i >= 0 && i < cnt)
#ifdef DEBUG
update = true;
if (cntSpawned > 0)
if (update)
cnt = 0;
cnt));
++ cnt;
if (cnt > 0)
if (updateSpawned)
bool update = false;
bool updateSpawned = false;
++it)
++it)
update = false;
updateSpawned = false;
++ it;
delete eventQ;
if (!mVirtualBox)
return NULL;
return NULL;
return NULL;
//STDMETHODIMP VirtualBox::CreateDHCPServerForInterface(/*IHostNetworkInterface * aIinterface,*/ IDHCPServer ** aServer)
return rc;
++it)
if (!found)
return E_INVALIDARG;
return rc;
return E_INVALIDARG;
if (aSaveRegistry)
return rc;
if (aSaveRegistry)
return rc;