VirtualBoxImpl.cpp revision 92fbfeea65ca674e060dd91ab3a8b8cf9658d4f4
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // 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 /** Callback bit indexes (for bmDisabled). */ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// * Abstract callback event class to asynchronously call VirtualBox callbacks * on a dedicated event thread. Subclasses reimplement #handleCallback() * to call appropriate IVirtualBoxCallback methods depending on the event * @note The VirtualBox instance passed to the constructor is strongly * referenced, so that the VirtualBox singleton won't be released until the * event gets handled by the event thread. * 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 private member data definition //////////////////////////////////////////////////////////////////////////////// * Main VirtualBox data structure. * @note |const| members are persistent during lifetime so can be accessed // const data members not requiring locking // VirtualBox main settings file // constant pseudo-machine ID for global media registry // const objects not requiring locking #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ // Each of the following lists use a particular lock handle that protects the // list as a whole. As opposed to version 3.1 and earlier, these lists no // longer need the main VirtualBox object lock, but only the respective list // lock. In each case, the locking order is defined that the list must be // requested before object locks of members of the lists (see the order definitions // in AutoLock.h; e.g. LOCKCLASS_LISTOFMACHINES before LOCKCLASS_MACHINEOBJECT). // All the media lists are protected by the following locking handle: // the hard disks map is an additional map sorted by UUID for quick lookup // and contains ALL hard disks (base and differencing); it is protected by // the same lock as the other media lists above // list of pending machine renames (also protected by media tree lock; // see VirtualBox::rememberMachineNameChangeForMedia()) // the following are data for the client watcher thread // the following are data for the async event thread /** The extension pack manager object lives here. */ // constructor / destructor ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// * Initializes the VirtualBox object. * @return COM result code /* Enclose the state transition NotReady->InInit->Ready */ /* Locking this object for writing during init sounds a bit paradoxical, * but in the current locking mess this avoids that some code gets a * read lock and later calls code which wants the same write lock. */ // allocate our instance data LogFlow((
"===========================================================\n"));
/* Get the VirtualBox home directory. */ tr(
"Could not create the VirtualBox home directory '%s' (%Rrc)"),
// load and parse VirtualBox.xml; this will throw on XML or logic errors // this is thrown by the XML backend if the RTOpen() call fails; // only if the main settings file does not exist, create it, // if there's something more serious, then do fail! /* create the performance collector object BEFORE host */ #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ /* create the host object early, machines will need it */ /* create the system properties object, someone may need it too */ /* guest OS type objects, needed by machines */ /* all registered media, needed by machines */ /* we assume that error info is set by the thrower */ /* start the client watcher thread */ /* start the async event handler thread */ /* wait until the thread sets m->pAsyncEventQ */ /* Confirm a successful initialization when it's the case */ /* Let the extension packs have a go at things. */ LogFlow((
"===========================================================\n"));
* Loads a media registry from XML and adds the media contained therein to * the global lists of known media. * This now (4.0) gets called from two locations: * -- VirtualBox::init(), to load the global media registry from VirtualBox.xml; * -- Machine::loadMachineDataFromSettings(), to load the per-machine registry * from machine XML, for machines created with VirtualBox 4.0 or later. * In both cases, the media found are added to the global lists so the * global arrays of media (including the GUI's virtual media manager) * continue to work as before. * @param uuidMachineRegistry The UUID of the media registry. This is either the * transient UUID created at VirtualBox startup for the global registry or * @param mediaRegistry The XML settings structure to load, either from VirtualBox.xml LogFlow((
"VirtualBox::initMedia ENTERING, uuidRegistry=%s, strMachineFolder=%s\n",
xmlHD,
// XML data; this recurses to processes the children NULL /* pllRegistriesThatNeedSaving */);
NULL /* pllRegistriesThatNeedSaving */);
LogFlow((
"VirtualBox::initMedia LEAVING\n"));
/* Enclose the state transition Ready->InUninit->NotReady */ LogFlow((
"===========================================================\n"));
/* tell all our child objects we've been uninitialized */ /* It is necessary to hold the VirtualBox and Host locks here because we may have to uninitialize SessionMachines. */ /* Note that we release singleton children after we've all other children. * In some cases this is important because these other children may use * some resources of the singletons which would prevent them from * uninitializing (as for example, mSystemProperties which owns * MediumFormat objects which Medium objects refer to) */ #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ /* signal to exit the event loop */ * Wait for thread termination (only after we've successfully * interrupted the event queue processing!) // we don't perform uninit() as it's possible that some pending event refers to this source /* signal the client watcher thread */ /* wait for the termination */ // clean up our instance data /* Unload hard disk plugin backends. */ LogFlow((
"===========================================================\n"));
// IVirtualBox properties ///////////////////////////////////////////////////////////////////////////// /* mHomeDir is const and doesn't need a lock */ /* mCfgFile.mName is const and doesn't need a lock */ /* mHost is const, no need to lock */ /* mSystemProperties is const, no need to lock */ /* protect mProgressOperations */ #
endif /* RT_OS_WINDOWS */ /* mPerformanceCollector is const, no need to lock */ #
else /* !VBOX_WITH_RESOURCE_USAGE_API */#
endif /* !VBOX_WITH_RESOURCE_USAGE_API */ /* event source is const, no need to lock */ /* The extension pack manager is const, no need to lock. */ /* compiled-in firmware */ /* compiled-in firmware */ /** @todo: account for version in the URL */ /* Assume single record per firmware type */ ///////////////////////////////////////////////////////////////////////////// /* Compose the settings file name using the following scheme: * <base_folder>/<machine_name>/<machine_name>.xml * If a non-null and non-empty base folder is specified, the default * machine folder will be used as a base folder. /* we use the non-full folder value below to keep the path relative */ /** @note Locks mSystemProperties object for reading. */ /** @todo tighten checks on aId? */ /* NULL settings file means compose automatically */ /* create a new object */ /* Create UUID if an empty one was specified. */ /* initialize the machine object */ /* set the return value */ /* call the extension pack hooks */ /* create a new object */ /* initialize the machine object */ NULL);
/* const Guid *aId */ /* set the return value */ /** @note Locks objects! */ /* We can safely cast child to Machine * here because only Machine * implementations of IMachine can be among our children. */ /** @note Locks this object for reading, then some machine objects for reading. */ /* start with not found */ true /* fPermitInaccessible */,
// returns VBOX_E_OBJECT_NOT_FOUND if not found and sets error continue;
// we can't ask inaccessible machines for their names tr(
"Could not find a registered machine named '%ls'"),
aNameOrId);
/* this will set (*machine) to NULL if machineObj is null */ /* we don't access non-const data members so no need to lock */ NULL /* pllRegistriesThatNeedSaving */);
/* we don't access non-const data members so no need to lock */ // check if the device type is correct, and see if a medium for the // given path has already initialized; if so, return that // enforce read-only for DVDs even if caller specified ReadWrite NULL /* pllRegistriesThatNeedSaving */);
/* Note that it's important to call uninit() on failure to register * because the differencing hard disk would have been already associated * with the parent and this association needs to be broken. */ /* the below will set *aHardDisk to NULL if hardDisk is null */ /** @note Locks this object for reading. */ /* Old ID to new ID conversion table. See r39691 for a source */ L
"winnt4", L
"WindowsNT4",
L
"win2k", L
"Windows2000",
L
"win2k3", L
"Windows2003",
L
"winvista", L
"WindowsVista",
L
"win2k8", L
"Windows2008",
L
"fedoracore", L
"Fedora",
/* the rest is covered by the case-insensitive comparison */ /* first, look for a substitution */ tr(
"'%ls' is not a valid Guest OS type"),
BOOL /* aWritable */,
BOOL /* aAutoMount */)
* @note Locks this object for reading. * @note Locks this object for reading. /* start with nothing found */ /* return the result to caller (may be empty) */ * @note Locks this object for writing. // locking note: we only hold the read lock briefly to look up the old value, // then release it and call the onExtraCanChange callbacks. There is a small // chance of a race insofar as the callback might be called twice if two callers // change the same key at the same time, but that's a much better solution // than the deadlock we had here before. The actual changing of the extradata // is then performed under the write lock and race-free. // look up the old value first; if nothing has changed then we need not do anything // ask for permission from all listeners outside the locks; // onExtraDataCanChange() only briefly requests the VirtualBox // lock to copy the list of callbacks to invoke tr(
"Could not set extra data because someone refused the requested change of '%ls' to '%ls'%s%ls"),
// data is changing and change not vetoed: then write it out under the lock // creates a new key if needed /* save settings on success */ // fire notification outside the lock // public methods only for internal purposes ///////////////////////////////////////////////////////////////////////////// * Posts an event to the event queue that is processed asynchronously * Posting events to the dedicated event queue is useful to perform secondary * actions outside any object locks -- for example, to iterate over a list * of callbacks and inform them about some change caused by some object's * @param event event to post; must have been allocated using |new|, will * be deleted automatically by the event thread after processing * @note Doesn't lock any object. LogWarningFunc((
"VirtualBox has been uninitialized (state=%d), the event is discarded!\n",
// in any event of failure, we must clean up here, or we'll leak; // the caller has allocated the object using new() * Adds a progress to the global collection of pending operations. * Usually gets called upon progress object initialization. * @param aProgress Operation to add to the collection. * @note Doesn't lock objects. /* protect mProgressOperations */ * Removes the progress from the global collection of pending operations. * Usually gets called upon progress completion. * @param aId UUID of the progress operation to remove * @note Doesn't lock objects. /* protect mProgressOperations */ * Helper method that starts a worker thread that: * - creates a pipe communication channel using SVCHlpClient; * - starts an SVC Helper process that will inherit this channel; * - executes the supplied function by passing it the created SVCHlpClient * and opened instance to communicate to the Helper process and the given * The user function is supposed to communicate to the helper process * using the \a aClient argument to do the requested job and optionally expose * the progress through the \a aProgress object. The user function should never * call notifyComplete() on it: this will be done automatically using the * result code returned by the function. * Before the user function is started, the communication channel passed to * the \a aClient argument is fully set up, the function should start using * its write() and read() methods directly. * The \a aVrc parameter of the user function may be used to return an error * code if it is related to communication errors (for example, returned by * the SVCHlpClient members when they fail). In this case, the correct error * message using this value will be reported to the caller. Note that the * value of \a aVrc is inspected only if the user function itself returns * If a failure happens anywhere before the user function would be normally * called, it will be called anyway in special "cleanup only" mode indicated * by \a aClient, \a aProgress and \aVrc arguments set to NULL. In this mode, * all the function is supposed to do is to cleanup its aUser argument if * necessary (it's assumed that the ownership of this argument is passed to * the user function once #startSVCHelperClient() returns a success, thus * making it responsible for the cleanup). * After the user function returns, the thread will send the SVCHlpMsg::Null * message to indicate a process termination. * @param aPrivileged |true| to start the SVC Helper process as a privileged * user that can perform administrative tasks * @param aFunc user function to run * @param aUser argument to the user function * @param aProgress progress object that will track operation completion * @note aPrivileged is currently ignored (due to some unsolved problems in * Vista) and the process will be started as a normal (unprivileged) * @note Doesn't lock anything. /* create the SVCHelperClientThread() argument */ static_cast <
void *>(d.
get()),
/* d is now owned by SVCHelperClientThread(), so release it */ * Worker thread for startSVCHelperClient(). /* protect VirtualBox from uninitialization */ tr(
"Could not create the communication channel (%Rrc)"),
vrc);
/* get the path to the executable */ /* Attempt to start a privileged process using the Run As dialog */ /* hide excessive details in case of a frequent error * (pressing the Cancel button to close the Run As dialog) */ tr(
"Operation canceled by the user"));
tr(
"Could not launch a privileged process '%s' (%Rrc)"),
tr(
"Could not launch a process '%s' (%Rrc)"),
exePath,
vrc);
/* wait for the client to connect */ /* start the user supplied function */ /* send the termination signal to the process anyway */ tr(
"Could not operate the communication channel (%Rrc)"),
vrc);
/* call the user function in the "cleanup only" mode * to let it free resources passed to in aUser */ #
endif /* RT_OS_WINDOWS */ * Sends a signal to the client watcher thread to rescan the set of machines * that have open sessions. * @note Doesn't lock anything. /* sent an update request */ * Adds the given child process ID to the list of processes to be reaped. * This call should be followed by #updateClientWatcher() to take the effect. /** Event for onMachineStateChange(), onMachineDataChange(), onMachineRegistered() */ * @note Doesn't lock any object. * @note Doesn't lock any object. * @note Locks this object for reading. /** Event for onExtraDataChange() */ * @note Doesn't lock any object. * @note Doesn't lock any object. /** Event for onSessionStateChange() */ * @note Doesn't lock any object. /** Event for onSnapshotTaken(), onSnapshotDeleted() and onSnapshotChange() */ * @note Doesn't lock any object. * @note Doesn't lock any object. * @note Doesn't lock any object. /** Event for onGuestPropertyChange() */ * @note Doesn't lock any object. /** Event for onMachineUninit(), this is not a CallbackEvent */ /* Handle unregistering metrics here, as it is not vital to get * it done immediately. It reduces the number of locks needed and * the lock contention in SessionMachine::uninit. */ #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ * Note that this is a weak ref -- the CallbackEvent handler thread * is bound to the lifetime of the VirtualBox instance, so it's safe. /** Reference to the machine object. */ * Trigger internal event. This isn't meant to be signalled to clients. * @note Doesn't lock any object. * @note Doesn't lock any object. * @note Locks this object for reading. /* unknown type must always be the first */ * Returns the list of opened machines (machines having direct sessions opened * by client processes) and optionally the list of direct session controls. * @param aMachines Where to put opened machines (will be empty if none). * @param aControls Where to put direct session controls (optional). * @note The returned lists contain smart pointers. So, clear it as soon as * it becomes no more necessary to release instances. * @note It can be possible that a session machine from the list has been * when accessing unprotected data directly. * @note Locks objects for reading. * Searches for a machine object with the given ID in the collection * of registered machines. * @param aId Machine UUID to look for. * @param aPermitInaccessible If true, inaccessible machines will be found; * if false, this will fail if the given machine is inaccessible. * @param aSetError If true, set errorinfo if the machine is not found. * @param aMachine Returned machine, if found. // skip inaccessible machines tr(
"Could not find a registered machine with UUID {%RTuuid}"),
* Searches for a Medium object with the given ID in the list of registered * @param aId ID of the hard disk. Must not be empty. * @param aSetError If @c true , the appropriate error info is set in case * when the hard disk is not found. * @param aHardDisk Where to store the found hard disk object (can be NULL). * @return S_OK, E_INVALIDARG or VBOX_E_OBJECT_NOT_FOUND when not found. * @note Locks the media tree for reading. // we use the hard disks map, but it is protected by the // hard disk _list_ lock handle tr(
"Could not find an open hard disk with UUID {%RTuuid}"),
* Searches for a Medium object with the given ID or location in the list of * registered hard disks. If both ID and location are specified, the first * object that matches either of them (not necessarily both) is returned. * @param aLocation Full location specification. Must not be empty. * @param aSetError If @c true , the appropriate error info is set in case * when the hard disk is not found. * @param aHardDisk Where to store the found hard disk object (can be NULL). * @return S_OK, E_INVALIDARG or VBOX_E_OBJECT_NOT_FOUND when not found. * @note Locks the media tree for reading. // we use the hard disks map, but it is protected by the // hard disk _list_ lock handle tr(
"Could not find an open hard disk with location '%s'"),
* Searches for a Medium object with the given ID or location in the list of * registered DVD or floppy images, depending on the @a mediumType argument. * If both ID and file path are specified, the first object that matches either * of them (not necessarily both) is returned. * @param mediumType Must be either DeviceType_DVD or DeviceType_Floppy. * @param aId ID of the image file (unused when NULL). * @param aLocation Full path to the image file (unused when NULL). * @param aSetError If @c true, the appropriate error info is set in case when * the image is not found. * @param aImage Where to store the found image object (can be NULL). * @return S_OK when found or E_INVALIDARG or VBOX_E_OBJECT_NOT_FOUND when not found. * @note Locks the media tree for reading. tr(
"Invalid image file location '%ls' (%Rrc)"),
// no AutoCaller, registered image life time is bound to this tr(
"Could not find an image file with UUID {%RTuuid} in the media registry ('%s')"),
tr(
"Could not find an image file with location '%ls' in the media registry ('%s')"),
* Searches for an IMedium object that represents the given UUID. * If the UUID is empty (indicating an empty drive), this sets pMedium * to NULL and returns S_OK. * If the UUID refers to a host drive of the given device type, this * sets pMedium to the object from the list in IHost and returns S_OK. * If the UUID is an image file, this sets pMedium to the object that * findDVDOrFloppyImage() returned. * If none of the above apply, this returns VBOX_E_OBJECT_NOT_FOUND. * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy. * @param uuid UUID to search for; must refer to a host drive or an image file or be null. * @param fRefresh Whether to refresh the list of host drives in IHost (see Host::getDrives()) * @param pMedium out: IMedium object found. // first search for host drive with that UUID // then search for an image with that UUID /* Look for a GuestOSType object */ (
"Guest OS types array must be filled"));
tr(
"Guest OS type '%ls' is invalid"),
* Returns the constant pseudo-machine UUID that is used to identify the * Starting with VirtualBox 4.0 each medium remembers in its instance data * in which media registry it is saved (if any): this can either be a machine * UUID, if it's in a per-machine media registry, or this global ID. * This UUID is only used to identify the VirtualBox object while VirtualBox * is running. It is a compile-time constant and not saved anywhere. * Getter that SystemProperties and others can use to talk to the extension #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ * Returns the default machine folder from the system properties * Returns the default hard disk format from the system properties * Calculates the absolute path of the given path taking the VirtualBox home * directory as the current directory. * @param aPath Path to calculate the absolute path for. * @param aResult Where to put the result (used only on success, can be the * same Utf8Str instance as passed in @a aPath). * @note Doesn't lock any object. /* no need to lock since mHomeDir is const */ * Copies strSource to strTarget, making it relative to the VirtualBox config folder * if it is a subdirectory thereof, or simply copying it otherwise. * @param strSource Path to evalue and copy. * @param strTarget Buffer to receive target path. // no need to lock since mHomeDir is const // use strTarget as a temporary buffer to hold the machine settings dir // is relative: then append what's left // is not relative: then overwrite ///////////////////////////////////////////////////////////////////////////// * Checks if there is a hard disk, DVD or floppy image with the given ID or * location already registered. * On return, sets @a aConflict to the string describing the conflicting medium, * or sets it to @c Null if no conflicting media is found. Returns S_OK in * either case. A failure is unexpected. * @param aId UUID to check. * @param aLocation Location to check. * @param aConflict Where to return parameters of the conflicting medium. * @note Locks the media tree and media objects for reading. /* Note: no AutoCaller since bound to this */ * Called from Machine::prepareSaveSettings() when it has detected * that a machine has been renamed. Such renames will require * updating the global media registry during the * VirtualBox::saveSettings() that follows later. * When a machine is renamed, there may well be media (in particular, * diff images for snapshots) in the global registry that will need * to have their paths updated. Before 3.2, Machine::saveSettings * used to call VirtualBox::saveSettings implicitly, which was both * unintuitive and caused locking order problems. Now, we remember * such pending name changes with this method so that * VirtualBox::saveSettings() can process them properly. * Goes through all known media (hard disks, floppies and DVDs) and saves * those into the given settings::MediaRegistry structures whose registry * ID match the given UUID. * Before actually writing to the structures, all media paths (not just the * ones for the given registry) are updated if machines have been renamed * This gets called from two contexts: * -- VirtualBox::saveSettings() with the UUID of the global registry * (VirtualBox::Data.uuidRegistry); this will save those media * which had been loaded from the global registry or have been * attached to a "legacy" machine which can't save its own registry; * -- Machine::saveSettings() with the UUID of a machine, if a medium * has been attached to a machine created with VirtualBox 4.0 or later. * Media which have only been temporarily opened without having been * attached to a machine have a NULL registry UUID and therefore don't * This locks the media tree. Throws HRESULT on errors! * @param mediaRegistry Settings structure to fill. * @param uuidRegistry The UUID of the media registry; either a machine UUID (if machine registry) or the UUID of the global registry. * @param hardDiskFolder The machine folder for relative paths, if machine registry, or an empty string otherwise. // lock all media for the following; use a write lock because we're // modifying the PendingMachineRenamesList, which is protected by this // if a machine was renamed, then we'll need to refresh media paths // make a single list from the three media lists so we don't need three loops // with hard disks, we must use the map, not the list, because the list only has base images // done, don't do it again until we have more machine renames * Helper function which actually writes out VirtualBox.xml, the main configuration file. * Gets called from the public VirtualBox::SaveSettings() as well as from various other * places internally when settings need saving. * @note Caller must have locked the VirtualBox object for writing and must not hold any * other locks since this locks all kinds of member objects and trees temporarily, * which could cause conflicts. // save actual machine registry entry // leave extra data alone, it's still in the config file // host data (USB filters) // and write out the XML, still under the lock /* we assume that error info is set by the thrower */ * Helper to register the machine. * When called during VirtualBox startup, adds the given machine to the * collection of registered machines. Otherwise tries to mark the machine * as registered, and, if succeeded, adds it to the collection and * @note The caller must have added itself as a caller of the @a aMachine * object if calls this method not on VirtualBox startup. * @param aMachine machine to register true /* fPermitInaccessible */,
tr(
"Registered machine with UUID {%RTuuid} ('%s') already exists"),
/* add to the collection of registered machines */ * Remembers the given hard disk by storing it in either the global hard disk registry * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading * @param aHardDisk Hard disk object to remember. * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry. * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving. // caller must hold the media tree write lock tr(
"Cannot register the hard disk '%s' {%RTuuid} because a %s already exists"),
// store base (root) hard disks in the list // access the list directly because we already locked the list above // store all hard disks (even differencing images) in the map * Removes the given hard disk from the hard disk registry. * @param aHardDisk Hard disk object to remove. * @param pfNeedsGlobalSaveSettings 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 // caller must hold the media tree write lock // remove base (root) hard disks from the list // access the list directly because caller must have locked the list // remove all hard disks (even differencing images) from map * Remembers the given image by storing it in the CD/DVD or floppy image registry. * @param argImage Image object to remember. * @param argType Either DeviceType_DVD or DeviceType_Floppy. * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry. * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading // caller must hold the media tree write lock // work on DVDs or floppies list? // lock the images lists (list + map) while checking for conflicts tr(
"Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists"),
// access the list directly because we already locked the list above * Removes the given image from the CD/DVD or floppy image registry. * @param argImage Image object to remove. * @param argType Either DeviceType_DVD or DeviceType_Floppy. * @param pfNeedsGlobalSaveSettings 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 // caller must hold the media tree write lock // work on DVDs or floppies list? // access the list directly because the caller must have requested the lock * Little helper called from unregisterMachineMedia() to recursively add media to the given list, * with children appearing before their parents. // recurse first, then add ourselves; this way children end up on the // list before their parents * Unregisters all Medium objects which belong to the given machine registry. * Gets called from Machine::uninit() just before the machine object dies * and must only be called with a machine UUID as the registry ID. * @param uuidMachine Medium registry ID (always a machine UUID) // recursively with children first * Removes the given machine object from the internal list of registered machines. * Called from Machine::Unregister(). * @param id UUID of the machine. Must be passed by caller because machine may be dead by this time. // remove from the collection of registered machines // save the global registry * Adds uuid to llRegistriesThatNeedSaving unless it's already on the list. * @todo maybe there's something in libstdc++ for this * @param llRegistriesThatNeedSaving // uuid is already in list: * Saves all settings files according to the given list of UUIDs, which are * either machine IDs (in which case Machine::saveSettings is invoked) or * the global registry UUID (in which case VirtualBox::saveSettings is invoked). * This locks machines and the VirtualBox object as necessary, so better not * hold any locks before calling this. * @param llRegistriesThatNeedSaving // should be machine ID then: false /* fPermitInaccessible */,
* Creates the path to the specified file according to the path information * present in the file name. * Note that the given file name must contain the full path otherwise the * extracted relative path will be created based on the current working * directory which is normally unknown. * @param aFileName Full file name which path needs to be created. * @return Extended error information on failure to create the path. Utf8StrFmt(
tr(
"Could not create the directory '%s' (%Rrc)"),
* Handles unexpected exceptions by turning them into COM errors in release * builds or by hitting a breakpoint in the release builds. rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS); * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation. /* re-throw the current exception */ catch (
const iprt::
Error &
err)
// includes all XML exceptions Utf8StrFmt(
tr(
"Unexpected exception: %s [%s]\n%s[%d] (%s)"),
/* should not get here */ * Returns the lock handle which protects the media trees (hard disks, * DVDs, floppies). As opposed to version 3.1 and earlier, these lists * are no longer protected by the VirtualBox lock, but by this more * specialized lock. Mind the locking order: always request this lock * after the VirtualBox object lock but before the locks of the media * objects contained in these lists. See AutoLock.h. * Thread function that watches the termination of all client processes * that have opened sessions using IMachine::LockMachine() /// @todo (dmik) processes reaping! /* VirtualBox has been early uninitialized, terminate */ /* release the caller to let uninit() ever proceed */ /* Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. */ /* update event is signaled */ /* machine mutex is released */ /* machine mutex is abandoned due to client process termination */ /* spawned VM process has terminated (normally or abnormally) */ /* close old process handles */ // lock the machines list for reading /* obtain a new set of opened machines */ /// @todo handle situations with more than 64 objects (
"MAXIMUM_WAIT_OBJECTS reached"));
/* obtain a new set of spawned machines */ /// @todo handle situations with more than 64 objects (
"MAXIMUM_WAIT_OBJECTS reached"));
// machines lock unwinds here /* close old process handles */ /* release sets of machines if any */ /// @todo (dmik) processes reaping! /* according to PMREF, 64 is the maximum for the muxwait list */ /* VirtualBox has been early uninitialized, terminate */ /* release the caller to let uninit() ever proceed */ /* Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. */ /* update event is signaled */ (
"RTSemEventWait returned %Rrc\n",
vrc));
/* are there any mutexes? */ /* figure out what's going on with machines */ /* machine mutex is normally released */ /* machine mutex is abandoned due to client process * termination; find which mutex is in the Owner Died /* close the dead mutex as asked by PMREF */ (
"DosWaitMuxWaitSem returned %d\n",
arc));
/* are there any spawning sessions? */ /* close the old muxsem */ /* obtain a new set of opened machines */ /// @todo handle situations with more than 64 objects (
"maximum of 64 mutex semaphores reached (%d)",
/* create a new muxsem */ (
"DosCreateMuxWaitSem returned %d\n",
arc));
/* obtain a new set of spawned machines */ /* release sets of machines if any */ /* release the caller to let uninit() ever proceed */ * Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. /* RT_SUCCESS(rc) means an update event is signaled */ // lock the machines list for reading /* obtain a new set of opened machines */ /* obtain a new set of spawned machines */ // machines lock unwinds here /* reap child processes */ LogFlowFunc((
"pid %d (%x) was reaped, status=%d, reason=%d\n",
/* remove the process if it is not already running */ /* release sets of machines if any */ * Thread function that handles custom events posted using #postEvent(). // create an event queue for the current thread // return the queue to the one who created this thread // signal that we're ready //////////////////////////////////////////////////////////////////////////////// * Takes the current list of registered callbacks of the managed VirtualBox * instance, and calls #handleCallback() for every callback item from the * list, passing the item as an argument. * @note Locks the managed VirtualBox object for reading but leaves the lock * before iterating over callbacks and calling their methods. LogWarningFunc((
"VirtualBox has been uninitialized (state=%d), the callback event is discarded!\n",
/* We don't need mVirtualBox any more, so release it */ mVirtualBox =
NULL;
/* Not needed any longer. Still make sense to do this? */ //STDMETHODIMP VirtualBox::CreateDHCPServerForInterface(/*IHostNetworkInterface * aIinterface,*/ IDHCPServer ** aServer) * Remembers the given dhcp server by storing it in the hard disk registry. * @param aDHCPServer Dhcp Server object to remember. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the dhcp server object * will not be remembered. It is therefore the responsibility of the caller to * call this method as the last step of some action that requires registration * in order to make sure that only fully functional dhcp server objects get * @note Locks this object for writing and @a aDHCPServer for reading. * Removes the given hard disk from the hard disk registry. * @param aHardDisk Hard disk object to remove. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the hard disk object * will NOT be removed from the registry when this method returns. It is * therefore the responsibility of the caller to call this method as the first * step of some action that requires unregistration, before calling uninit() on * @note Locks this object for writing and @a aHardDisk for reading. /* vi: set tabstop=4 shiftwidth=4 expandtab: */