VirtualBoxImpl.cpp revision 6870881f24c540938ae6b34293e803ee2ba52da1
2736N/A * VirtualBox COM class implementation 2736N/A * Copyright (C) 2006-2007 innotek GmbH 2736N/A * This file is part of VirtualBox Open Source Edition (OSE), as 2736N/A * you can redistribute it and/or modify it under the terms of the GNU 2736N/A * General Public License (GPL) as published by the Free Software 2736N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 2736N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 2736N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. #
include <
memory>
// for auto_ptr///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // constructor / destructor ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// * Initializes the VirtualBox object. * @return COM result code /* Enclose the state transition NotReady->InInit->Ready */ LogFlow ((
"===========================================================\n"));
/* Get the VirtualBox home directory. */ tr (
"Could not create the VirtualBox home directory '%s'" /* compose the global config file name (always full path) */ /* store the config file name */ /* lock the config file */ * This means the config file not found. This is not fatal -- * we just create an empty one. /* we do not close the file to simulate lockConfig() */ /* create the host object early, machines will need it */ /* create the system properties object */ /* guest OS type objects, needed by machines */ /* hard disks, needed by machines */ /* check hard disk consistency */ /// @todo (r=dmik) add IVirtualBox::cleanupHardDisks() instead or similar // for (HardDiskList::const_iterator it = mData.mHardDisks.begin(); // it != mData.mHardDisks.end() && SUCCEEDED (rc); // rc = (*it)->checkConsistency(); // CheckComRCBreakRC ((rc)); /// @todo (dmik) if successful, check for orphan (unused) diffs // that might be left because of the server crash, and remove // Hmm, is it the same remark as above?.. /* 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 mAsyncEventQ */ /* Confirm a successful initialization when it's the case */ LogFlow ((
"===========================================================\n"));
/* Enclose the state transition Ready->InUninit->NotReady */ LogFlow ((
"===========================================================\n"));
/* tell all our child objects we've been uninitialized */ * Uninit all other children still referenced by clients * (unregistered machines, hard disks, DVD/floppy images, * server-side progress operations). /* unlock the config file */ /* release all callbacks */ /* signal to exit the event loop */ * Wait for thread termination (only if we've successfully posted /* signal the client watcher thread */ /* wait for the termination */ LogFlow ((
"===========================================================\n"));
// IVirtualBox properties ///////////////////////////////////////////////////////////////////////////// /* mHomeDir is const and doesn't need a lock */ /* mCfgFile.mName is const and doesn't need a lock */ * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. ///////////////////////////////////////////////////////////////////////////// /** @note Locks mSystemProperties object for reading. */ tr (
"Machine name cannot be empty"));
/* 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 */ /* create a new object */ /* Create UUID if an empty one was specified. */ /* initialize the machine object */ /* set the return value */ /* null and empty strings are not allowed as path names */ tr (
"Machine name cannot be empty"));
/* append the default extension if none */ /* create a new object */ /* Create UUID if an empty one was specified. */ /* initialize the machine object */ /* set the return value */ /* null and empty strings are not allowed as path names */ /* create a new object */ /* initialize the machine object */ /* 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 * this machine was not created by CreateMachine() * or opened by OpenMachine() or loaded during startup tr (
"The machine named '%ls' is not created within this " "VirtualBox instance"),
name.
raw());
/** @note Locks objects! */ /* the below will set *aMachine to NULL if machine is null */ /** @note Locks this object for reading, then some machine objects for reading. */ /* start with not found */ /* take a copy for safe iteration outside the lock */ /* skip inaccessible machines */ /* this will set (*machine) to NULL if machineObj is null */ tr (
"Could not find a registered machine named '%ls'"),
aName);
/** @note Locks objects! */ /* remove from the collection of registered machines */ /* save the global registry */ /* return the unregistered machine to the caller */ /** @note Locks mSystemProperties object for reading. */ /* null and empty strings are not allowed locations */ /* Currently, the location is always a path. So, append the * default path if only a name is given. */ /** @note Locks mSystemProperties object for reading. */ /* null and empty strings are not allowed as path names here */ /* append the default path if only a name is given */ /** @note Locks objects! */ "this VirtualBox instance"));
* we can safely cast child to HardDisk * here because only HardDisk * implementations of IHardDisk can be among our children /** @note Locks objects! */ /* the below will set *aHardDisk to NULL if hd is null */ /** @note Locks objects! */ /* For locations represented by file paths, append the default path if * only a name is given, and then get the full path. */ /* get the full file name */ /* the below will set *aHardDisk to NULL if hardDisk is null */ /** @note Locks objects! */ /* append the default path if only a name is given */ /* get the full file name */ /* the below will set *aImage to NULL if vdi is null */ /** @note Locks objects! */ /** @note Doesn't lock anything. */ /* null and empty strings are not allowed as path names */ /* generate an UUID if not specified */ /** @note Locks objects! */ "this VirtualBox instance"));
* we can safely cast child to DVDImage * here because only DVDImage * implementations of IDVDImage can be among our children /** @note Locks objects! */ /* the below will set *aDVDImage to NULL if dvd is null */ /** @note Locks objects! */ /* get the full file name */ /* the below will set *dvdImage to NULL if dvd is null */ /** @note Locks objects! */ /** @note Locks objects! */ /* remove from the collection */ /* save the global config file */ tr (
"The CD/DVD image with the UUID {%s} is currently in use"),
/** @note Doesn't lock anything. */ /* null and empty strings are not allowed as path names */ /* generate an UUID if not specified */ /** @note Locks objects! */ "this VirtualBox instance"));
* we can safely cast child to FloppyImage * here because only FloppyImage * implementations of IFloppyImage can be among our children /** @note Locks objects! */ /* the below will set *aFloppyImage to NULL if dvd is null */ /** @note Locks objects! */ /* get the full file name */ /* the below will set *image to NULL if img is null */ /** @note Locks objects! */ /** @note Locks objects! */ /* remove from the collection */ /* save the global config file */ tr (
"A floppy image with UUID {%s} is currently in use"),
/** @note Locks this object for reading. */ tr (
"'%ls' is not a valid Guest OS type"),
* @note Locks this object for reading. /* start with nothing found */ /* serialize config file access */ /* load the config file */ /* if we're supposed to return the first one */ /* did we find the key we're looking for? */ /* is there another item? */ /* else it's the last one, arguments are already NULL */ /* Here we are when a) there are no items at all or b) there are items * but none of them equals to the requested non-NULL key. b) is an * error as well as a) if the key is non-NULL. When the key is NULL * (which is the case only when there are no items), we just fall * through to return NULLs and S_OK. */ tr (
"Could not find the extra data key '%ls'"),
aKey);
* @note Locks this object for reading. /* start with nothing found */ /* serialize file access */ /* load the config file */ /* check if the key exists */ * @note Locks this object for writing. /* serialize file access */ /* load the config file */ /* When no key is found, oldVal is null */ /* ask for permission from all listeners */ tr (
"Could not set extra data because someone refused " "the requested change of '%ls' to '%ls'%s%ls"),
/* an old value does for sure exist here (XML schema * guarantees that "value" may not absent in the * <ExtraDataItem> element) */ /* save settings on success */ /* fire a notification */ /* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ * tell the client watcher thread to update the set of * machines that have open sessions /* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ /* create a progress object */ Bstr (
tr (
"Spawning session")),
FALSE /* aCancelable */);
/* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ * @note Locks this object for writing. * @note Locks this object for writing. /* saveSettings() needs write lock */ /* perform backup only when there was auto-conversion */ // 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 be allocated using |new|, will be deleted automatically * by the event thread after processing) * @note Doesn't lock any object. "the event is discarded!\n",
* Helper method to add a progress to the global collection of pending * @param aProgress operation to add to the collection * @return COM status code * @note Locks this object for writing. * Helper method to remove the progress from the global collection of pending * operations. Usualy gets called upon progress completion. * @param aId UUID of the progress operation to remove * @return COM status code * @note Locks this object for writing. * Helper method to that starts a worker thread that: * - creates a pipe communication channel using SVCHlpClient; * - starts a 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 prgress 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 stared, the communication channel passed to in * the \a aClient argument, is fully set up, the function should start using * it's 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 Hepler process as a privlieged * 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 (%Vrc)"),
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 (
"Operatiion cancelled by the user"));
tr (
"Could not launch a privileged process '%s' (%Vrc)"),
tr (
"Could not launch a process '%s' (%Vrc)"),
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 (%Vrc)"),
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() */ LogFlow ((
"OnMachineStateChange: id={%Vuuid}, state=%d\n",
LogFlow ((
"OnMachineRegistered: id={%Vuuid}, registered=%d\n",
* @note Doesn't lock any object. * @note Doesn't lock any object. * @note Locks this object for reading. /* if a call to this method fails for some reason (for ex., because * the other side is dead), we ensure allowChange stays true * (MS COM RPC implementation seems to zero all output vars before * issuing an IPC call or after a failure, so it's essential /** Event for onExtraDataChange() */ LogFlow ((
"OnExtraDataChange: machineId={%Vuuid}, key='%ls', val='%ls'\n",
* @note Doesn't lock any object. * @note Doesn't lock any object. /** Event for onSessionStateChange() */ LogFlow ((
"OnSessionStateChange: machineId={%Vuuid}, sessionState=%d\n",
* @note Doesn't lock any object. /** Event for onSnapshotTaken(), onSnapshotRemoved() and onSnapshotChange() */ LogFlow ((
"OnSnapshotTaken: machineId={%Vuuid}, snapshotId={%Vuuid}\n",
LogFlow ((
"OnSnapshotDiscarded: machineId={%Vuuid}, snapshotId={%Vuuid}\n",
LogFlow ((
"OnSnapshotChange: machineId={%Vuuid}, snapshotId={%Vuuid}\n",
* @note Doesn't lock any object. * @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 (i.e. machines having direct sessions * opened by client processes). * @note the returned list contains 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 * already uninitialized, so a) lock the instance and b) chheck for * instance->isReady() return value before manipulating the object directly * (i.e. not through COM methods). * @note Locks objects for reading. /* SessionMachine is null when there are no open sessions */ * Helper to find machines that use the given DVD image. * This method also checks whether an existing snapshot refers to the given * image. However, only the machine ID is returned in this case, not IDs of * @param aId Image ID to get usage for. * @param aUsage Type of the check. * @param aMachineIDs Where to store the list of machine IDs (can be NULL) * @return @c true if at least one machine or its snapshot found and @c false * @note For now, we just scan all the machines. We can optimize this later * if required by adding the corresponding field to DVDImage and requiring all * IDVDImage instances to be DVDImage objects. * @note Locks objects for reading. /* ignore inaccessible machines */ /* if not interested in the list, return shortly */ /* convert to a string of UUIDs */ /* replace EOS with a space char */ /* remove the trailing space */ * Helper to find machines that use the given Floppy image. * This method also checks whether an existing snapshot refers to the given * image. However, only the machine ID is returned in this case, not IDs of * @param aId Image ID to get usage for. * @param aUsage Type of the check. * @param aMachineIDs Where to store the list of machine IDs (can be NULL) * @return @c true if at least one machine or its snapshot found and @c false * @note For now, we just scan all the machines. We can optimize this later * if required by adding the corresponding field to FloppyImage and requiring all * FloppyImage instances to be FloppyImage objects. * @note Locks objects for reading. /* ignore inaccessible machines */ /* if not interested in the list, return shortly */ /* convert to a string of UUIDs */ /* replace EOS with a space char */ /* remove the trailing space */ * Tries to calculate the relative path of the given absolute path using the * directory of the VirtualBox settings file as the base directory. * @param aPath absolute path to calculate the relative path for * @param aResult where to put the result (used only when it's possible to * make a relative path from the given absolute path; * otherwise left untouched) * @note Doesn't lock any object. /* no need to lock since mHomeDir is const */ /* when assigning, we create a separate Utf8Str instance because both * aPath and aResult can point to the same memory location when this * func is called (if we just do aResult = aPath, aResult will be freed * first, and since its the same as aPath, an attempt to copy garbage ///////////////////////////////////////////////////////////////////////////// * Searches for a Machine object with the given ID in the collection * of registered machines. * if TRUE, the appropriate error info is set in case when the machine * where to store the found machine object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks this object for reading. tr (
"Could not find a registered machine with UUID {%Vuuid}"),
* Searches for a HardDisk object with the given ID or location specification * in the collection of registered hard disks. If both ID and location are * specified, the first object that matches either of them (not necessarily * @param aId ID of the hard disk (NULL when unused) * @param aLocation full location specification (NULL when unused) * @param aSetError if TRUE, the appropriate error info is set in case when * the disk is not found and only one search criteria (ID * or file name) is specified. * @param aHardDisk where to store the found hard disk object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks objects for reading! /* first lookup the map by UUID if UUID is provided */ /* then iterate and find by location */ /* locations of VDI and VMDK hard disks for now are just (
false /* aShort */))) == 0;
"with UUID {%Vuuid}"),
aId->
raw());
* @deprecated Use #findHardDisk() instead. * Searches for a HVirtualDiskImage object with the given ID or file path in the * collection of registered hard disks. If both ID and file path are specified, * the first object that matches either of them (not necessarily both) * @param aId ID of the hard disk (NULL when unused) * @param filePathFull full path to the image file (NULL when unused) * @param aSetError if TRUE, the appropriate error info is set in case when * the disk is not found and only one search criteria (ID * or file name) is specified. * @param aHardDisk where to store the found hard disk object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks objects for reading! /* first lookup the map by UUID if UUID is provided */ /* then iterate and find by name */ setError (
rc,
tr (
"Could not find a registered VDI hard disk " "with UUID {%Vuuid}"),
aId->
raw());
setError (
rc,
tr (
"Could not find a registered VDI hard disk " * Searches for a DVDImage object with the given ID or file path in the * collection of registered DVD images. If both ID and file path are specified, * the first object that matches either of them (not necessarily both) * ID of the DVD image (unused when NULL) * full path to the image file (unused when NULL) * if TRUE, the appropriate error info is set in case when the image is not * found and only one search criteria (ID or file name) is specified. * where to store the found DVD image object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks this object for reading. /* DVDImage fields are constant, so no need to lock */ * Searches for a FloppyImage object with the given ID or file path in the * collection of registered floppy images. If both ID and file path are specified, * the first object that matches either of them (not necessarily both) * ID of the floppy image (unused when NULL) * full path to the image file (unused when NULL) * if TRUE, the appropriate error info is set in case when the image is not * found and only one search criteria (ID or file name) is specified. * where to store the found floppy image object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks this object for reading. /* FloppyImage fields are constant, so no need to lock */ setError (
rc,
tr (
"Could not find a registered floppy image " setError (
rc,
tr (
"Could not find a registered floppy image " * When \a aHardDisk is not NULL, searches for an object equal to the given * hard disk in the collection of registered hard disks, or, if the given hard * disk is HVirtualDiskImage, for an object with the given file path in the * collection of all registered non-hard disk images (DVDs and floppies). * Other parameters are unused. * When \a aHardDisk is NULL, searches for an object with the given ID or file * path in the collection of all registered images (VDIs, DVDs and floppies). * If both ID and file path are specified, matching either of them will satisfy * If a matching object is found, this method returns E_INVALIDARG and sets the * appropriate error info. Otherwise, S_OK is returned. * @param aHardDisk hard disk object to check against registered media * @param aId UUID of the media to check (NULL when unused) * @param aFilePathFull full path to the image file (NULL when unused) tr (
"A hard disk with UUID {%Vuuid} or with the same properties " "('%ls') is already registered"),
/// @todo (dmik) stupid BSTR declaration lacks the BCSTR counterpart tr (
"A disk image with UUID {%Vuuid} is already registered"),
tr (
"A disk image with file path '%ls' is already registered"),
tr (
"A disk image with UUID {%Vuuid} or file path '%ls' " * Reads in the machine definitions from the configuration loader * and creates the relevant objects. * @param aGlobal <Global> node. * @note Can be called only from #init(). * @note Doesn't lock anything. /* create a new machine object */ /* initialize the machine object and register it */ * Reads in the disk registration entries from the global settings file * and creates the relevant objects * @param aGlobal <Global> node * @note Can be called only from #init(). * @note Doesn't lock anything. const char *
kMediaNodes[] = {
"HardDisks",
"DVDImages",
"FloppyImages" };
/* All three media nodes are optional */ case 2:
/* FloppyImages */ * Loads all hard disks from the given <HardDisks> node. * Note that all loaded hard disks register themselves within this VirtualBox. * @param aNode <HardDisks> node. * @note Can be called only from #init(). * @note Doesn't lock anything. /* detect the type of the hard disk (either one of VirtualDiskImage, * ISCSIHardDisk, VMDKImage or HCustomHardDisk) */ * Helper function to write out the configuration tree. * @note Locks objects for reading! /* first, delete the entire machine registry */ /* write out the machines */ /* first, delete the entire disk image registr */ /* write out the hard disks */ /* write out the CD/DVD images */ /* no need to lock: fields are constant */ /* write out the floppy images */ /* no need to lock: fields are constant */ /* host data (USB filters) */ /* save the settings on success */ /* we assume that error info is set by the thrower */ * Saves all hard disks to the given <HardDisks> node. * @param aNode <HardDisks> node. * @note Locks this object for reding. * 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 tr (
"Registered machine with UUID {%Vuuid} ('%ls') already exists"),
/* Machine::trySetRegistered() will commit and save machine settings */ /* add to the collection of registered machines */ * Helper to register the hard disk. * @param aHardDisk object to register * @param aFlags one of RHD_* values /* mark the hard disk as registered only when registration is external */ /* add to the collection of top-level images */ /* insert to the map of hard disks */ /* save global config file if not on startup */ /// @todo (dmik) optimize later to save only the <HardDisks> node * Helper to unregister the hard disk. * If the hard disk is a differencing hard disk and if the unregistration * succeeds, the hard disk image is deleted and the object is uninitialized. * @param aHardDisk hard disk to unregister /* Lock the hard disk to ensure nobody registers it again before we delete * the differencing image (sanity check actually -- should never happen). */ /* remove from the map of hard disks */ /* non-differencing hard disk: * remove from the collection of top-level hard disks */ /* differencing hard disk: delete and uninitialize * Note that we ignore errors because this operation may be a result * of unregistering a missing (inaccessible) differencing hard disk * in which case a failure to implicitly delete the image will not * prevent it from being unregistered and therefore should not pop up * on the caller's side. */ /* save the global config file anyway (already unregistered) */ /// @todo (dmik) optimize later to save only the <HardDisks> node * Helper to unregister the differencing hard disk image. * Resets machine ID of the hard disk (to let the unregistration succeed) * and then calls #unregisterHardDisk(). * @param aHardDisk differencing hard disk image to unregister * Note: it's safe to lock aHardDisk here because the same object * will be locked by #unregisterHardDisk(). * deassociate the machine from the hard disk * (otherwise trySetRegistered() will definitely fail) * Helper to update the global settings file when the name of some machine * changes so that file and directory renaming occurs. This method ensures * that all affected paths in the disk registry are properly updated. * @param aOldPath old path (full) * @param aNewPath new path (full) * @note Locks this object + DVD, Floppy and HardDisk children for writing. /* no need to lock: fields are constant */ /* no need to lock: fields are constant */ /* check HardDisk paths */ * Helper method to load the setting tree and turn expected exceptions into * COM errors, according to arguments. * Note that this method will not catch unexpected errors so it may still * @param aTree Tree to load into settings. * @param aFile File to load settings from. * @param aValidate @c @true to enable tree validation. * @param aCatchLoadErrors @c true to catch exceptions caused by file * access or validation errors. * @param aAddDefaults @c true to cause the substitution of default * values for for missing attributes that have * defaults in the XML schema. * @param aFormatVersion Where to store the current format version of the * loaded settings tree (optional, may be NULL). /* on success, memorize the current settings file version or set it to * the most recent version if no settings conversion took place. Note * that it's not necessary to do it every time we load the settings file * (i.e. only loadSettingsTree_FirstTime() passes a non-NULL * aFormatVersion value) because currently we keep the settings * files locked so that the only legal way to change the format version * while VirtualBox is running is saveSettingsTree(). */ tr (
"Could not load the settings file '%s' (%Vrc)"),
tr (
"Could not load the settings file '%s'.\n%s"),
* Helper method to save the settings tree and turn expected exceptions to COM * Note that this method will not catch unexpected errors so it may still * @param aTree Tree to save. * @param aFile File to save the tree to. * @param aFormatVersion Where to store the (recent) format version of the * saved settings tree on success. /* set the current settings file version to the most recent version on * success. See also VirtualBox::loadSettingsTree(). */ /* this is the only expected exception for now */ tr (
"Could not save the settings file '%s' (%Vrc)"),
* Creates a backup copy of the given settings file by suffixing it with the * supplied version format string and optionally with numbers from .0 to .9 * if the backup file already exists. * @param aFileName Orignal settings file name. * @param aOldFormat Version of the original format. * @param aBakFileName File name of the created backup copy (only on success). /* try progressive suffix from .0 to .9 on failure */ tr (
"Could not copy the settings file '%s' to '%s' (%Vrc)"),
* 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. /* rethrow the current exception */ /* should not get here */ * Helper to register the DVD image. * @param aImage object to register * @param aOnStartUp whether this method called during VirtualBox init or not * @return COM status code /* add to the collection */ /* save global config file if we're supposed to */ * Helper to register the floppy image. * @param aImage object to register * @param aOnStartUp whether this method called during VirtualBox init or not * @return COM status code /* add to the collection */ /* save global config file if we're supposed to */ * Helper function to create the guest OS type objects and our collection * @returns COM status code // this table represents our os type / string mapping /// @todo (dmik) get the list of OS types from the XML schema /* NOTE1: we assume that unknown is always the first entry! * NOTE2: please use powers of 2 when specifying the size of harddisks since * '2GB' looks better than '1.95GB' (= 2000MB) */ * Helper to lock the VirtualBox configuration for write access. * @note This method is not thread safe (must be called only from #init() * @note If the configuration file is not found, the method returns * S_OK, but subsequent #isConfigLocked() will return FALSE. This is used * in some places to determine the (valid) situation when no config file * exists yet, and therefore a new one should be created from scatch. /* open the associated config file */ * It is ok if the file is not found, it will be created by * init(). Otherwise return an error. tr (
"Could not lock the settings file '%ls' (%Vrc)"),
* Helper to unlock the VirtualBox configuration from write access. * @note This method is not thread safe (must be called only from #init() /** @todo flush the directory too. */ * Thread function that watches the termination of all client processes * that have opened sessions using IVirtualBox::OpenSession() /// @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 */ /* obtain a new set of opened machines */ (
"MAXIMUM_WAIT_OBJECTS reached"));
/* renew the set of event handles */ /* delete the set of event handles */ /* delete the set of opened 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 %Vrc\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));
/* close the old muxsem */ /* obtain a new set of opened machines */ /// @todo use several muxwait sems if cnt is > 64 (
"maximum of 64 mutex semaphores reached (%d)",
cnt));
/* renew the set of event handles */ /* create a new muxsem */ (
"DosCreateMuxWaitSem returned %d\n",
arc));
NOREF(
arc);
/* delete the set of opened 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. /* VBOX_SUCCESS (rc) means an update event is signaled */ /* obtain a new set of opened machines */ /* reap child processes */ "status=%d, reason=%d\n",
LogFlowFunc ((
"pid %d (%x) was NOT reaped, vrc=%Vrc\n",
/* remove the process if it is not already running */ /* delete the set of opened 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. "the callback event is discarded!\n",
/* We don't need mVirtualBox any more, so release it */ /* Make a copy to release the lock before iterating */ /* We don't need mVirtualBox any more, so release it */