Settings.cpp revision 9601ea695ea96905d6f5d484facd272732365c40
/* $Id$ */
/** @file
* Settings File Manipulation API.
*
* Two classes, MainConfigFile and MachineConfigFile, represent the VirtualBox.xml and
* machine XML files. They share a common ancestor class, ConfigFileBase, which shares
* functionality such as talking to the XML back-end classes and settings version management.
*
* The code can read all VirtualBox settings files version 1.3 and higher. That version was
* written by VirtualBox 2.0. It can write settings version 1.7 (used by VirtualBox 2.2 and
* 3.0) and 1.9 (used by VirtualBox 3.1) and newer ones obviously.
*
* The settings versions enum is defined in src/VBox/Main/idl/VirtualBox.xidl. To introduce
* a new settings version (should be necessary at most once per VirtualBox major release,
* if at all), add a new SettingsVersion value to that enum and grep for the previously
* highest value to see which code in here needs adjusting.
*
* Certainly ConfigFileBase::ConfigFileBase() will. Change VBOX_XML_VERSION below as well.
* VBOX_XML_VERSION does not have to be changed if the settings for a default VM do not
* touch newly introduced attributes or tags. It has the benefit that older VirtualBox
* versions do not trigger their "newer" code path.
*
* Once a new settings version has been added, these are the rules for introducing a new
* setting: If an XML element or attribute or value is introduced that was not present in
* previous versions, then settings version checks need to be introduced. See the
* SettingsVersion enumeration in src/VBox/Main/idl/VirtualBox.xidl for details about which
* version was used when.
*
* The settings versions checks are necessary because since version 3.1, VirtualBox no longer
* automatically converts XML settings files but only if necessary, that is, if settings are
* present that the old format does not support. If we write an element or attribute to a
* settings file of an older version, then an old VirtualBox (before 3.1) will attempt to
* validate it with XML schema, and that will certainly fail.
*
* So, to introduce a new setting:
*
* 1) Make sure the constructor of corresponding settings structure has a proper default.
*
* 2) In the settings reader method, try to read the setting; if it's there, great, if not,
* the default value will have been set by the constructor. The rule is to be tolerant
* here.
*
* 3) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has
* a non-default value (i.e. that differs from the constructor). If so, bump the
* settings version to the current version so the settings writer (4) can write out
* the non-default value properly.
*
* So far a corresponding method for MainConfigFile has not been necessary since there
* have been no incompatible changes yet.
*
* 4) In the settings writer method, write the setting _only_ if the current settings
* version (stored in m->sv) is high enough. That is, for VirtualBox 4.0, write it
* only if (m->sv >= SettingsVersion_v1_11).
*/
/*
* Copyright (C) 2007-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "VBox/settings.h"
// generated header
#include "SchemaDefs.h"
#include "Logging.h"
#include "HashedPw.h"
using namespace com;
using namespace settings;
////////////////////////////////////////////////////////////////////////////////
//
// Defines
//
////////////////////////////////////////////////////////////////////////////////
/** VirtualBox XML settings namespace */
/** VirtualBox XML settings version number substring ("x.y") */
#define VBOX_XML_VERSION "1.12"
/** VirtualBox XML settings version platform substring */
#if defined (RT_OS_DARWIN)
# define VBOX_XML_PLATFORM "macosx"
#elif defined (RT_OS_FREEBSD)
# define VBOX_XML_PLATFORM "freebsd"
#elif defined (RT_OS_LINUX)
# define VBOX_XML_PLATFORM "linux"
#elif defined (RT_OS_NETBSD)
# define VBOX_XML_PLATFORM "netbsd"
#elif defined (RT_OS_OPENBSD)
# define VBOX_XML_PLATFORM "openbsd"
# define VBOX_XML_PLATFORM "os2"
#elif defined (RT_OS_SOLARIS)
# define VBOX_XML_PLATFORM "solaris"
#elif defined (RT_OS_WINDOWS)
# define VBOX_XML_PLATFORM "windows"
#else
#endif
/** VirtualBox XML settings full version string ("x.y-platform") */
////////////////////////////////////////////////////////////////////////////////
//
// Internal data
//
////////////////////////////////////////////////////////////////////////////////
/**
* Opaque data structore for ConfigFileBase (only declared
* in header, defined only here).
*/
struct ConfigFileBase::Data
{
Data()
{}
~Data()
{
cleanup();
}
bool fFileExists;
// or SettingsVersion_Null if none
{
strFilename = d.strFilename;
fFileExists = d.fFileExists;
}
void cleanup()
{
if (pDoc)
{
delete pDoc;
}
}
};
/**
* Private exception class (not in the header file) that makes
* throwing xml::LogicError instances easier. That class is public
* and should be caught by client code.
*/
{
public:
const char *pcszFormat, ...)
: xml::LogicError()
{
if (pNode)
}
};
////////////////////////////////////////////////////////////////////////////////
//
// MediaRegistry
//
////////////////////////////////////////////////////////////////////////////////
{
&& (strLocation == m.strLocation)
&& (strDescription == m.strDescription)
&& (fAutoReset == m.fAutoReset)
&& (properties == m.properties)
}
bool MediaRegistry::operator==(const MediaRegistry &m) const
{
return llHardDisks == m.llHardDisks
&& llDvdImages == m.llDvdImages
&& llFloppyImages == m.llFloppyImages;
}
////////////////////////////////////////////////////////////////////////////////
//
// ConfigFileBase
//
////////////////////////////////////////////////////////////////////////////////
/**
* Constructor. Allocates the XML internals, parses the XML file if
* pstrFilename is != NULL and reads the settings version from it.
* @param strFilename
*/
: m(new Data)
{
m->fFileExists = false;
if (pstrFilename)
{
// reading existing settings file:
m->strFilename = *pstrFilename;
*m->pDoc);
m->fFileExists = true;
throw ConfigFileError(this, NULL, N_("Root element in VirtualBox settings files must be \"VirtualBox\"."));
LogRel(("Loading settings file \"%s\" with version \"%s\"\n", m->strFilename.c_str(), m->strSettingsVersionFull.c_str()));
// parse settings version; allow future versions but fail if file is older than 1.6
m->sv = SettingsVersion_Null;
{
char c;
while ( (c = *pcsz)
&& RT_C_IS_DIGIT(c)
)
{
++pcsz;
}
if (*pcsz++ == '.')
{
while ( (c = *pcsz)
&& RT_C_IS_DIGIT(c)
)
{
++pcsz;
}
}
if (ulMajor == 1)
{
if (ulMinor == 3)
m->sv = SettingsVersion_v1_3;
else if (ulMinor == 4)
m->sv = SettingsVersion_v1_4;
else if (ulMinor == 5)
m->sv = SettingsVersion_v1_5;
else if (ulMinor == 6)
m->sv = SettingsVersion_v1_6;
else if (ulMinor == 7)
m->sv = SettingsVersion_v1_7;
else if (ulMinor == 8)
m->sv = SettingsVersion_v1_8;
else if (ulMinor == 9)
m->sv = SettingsVersion_v1_9;
else if (ulMinor == 10)
m->sv = SettingsVersion_v1_10;
else if (ulMinor == 11)
m->sv = SettingsVersion_v1_11;
else if (ulMinor == 12)
m->sv = SettingsVersion_v1_12;
else if (ulMinor == 13)
m->sv = SettingsVersion_v1_13;
else if (ulMinor == 14)
m->sv = SettingsVersion_v1_14;
else if (ulMinor == 15)
m->sv = SettingsVersion_v1_15;
else if (ulMinor > 15)
m->sv = SettingsVersion_Future;
}
else if (ulMajor > 1)
m->sv = SettingsVersion_Future;
}
if (m->sv == SettingsVersion_Null)
throw ConfigFileError(this, m->pelmRoot, N_("Cannot handle settings version '%s'"), m->strSettingsVersionFull.c_str());
// remember the settings version we read in case it gets upgraded later,
// so we know when to make backups
}
else
{
// creating new settings file:
m->sv = SettingsVersion_v1_12;
}
}
: m(new Data)
{
m->strFilename = "";
m->fFileExists = false;
}
/**
* Clean up.
*/
{
if (m)
{
delete m;
m = NULL;
}
}
/**
* Helper function that parses a UUID in string form into
* a com::Guid item. Accepts UUIDs both with and without
* "{}" brackets. Throws on errors.
* @param guid
* @param strUUID
*/
{
}
/**
* Parses the given string in str and attempts to treat it as an ISO
* @param timestamp
* @param str
*/
{
// yyyy-mm-ddThh:mm:ss
// "2009-07-10T11:54:03Z"
// 01234567890123456789
// 1
{
// timezone must either be unspecified or 'Z' for UTC
if ( (pcsz[19])
)
throw ConfigFileError(this, NULL, N_("Cannot handle ISO timestamp '%s': is not UTC date"), str.c_str());
)
{
int rc;
// could theoretically be negative but let's assume that nobody
// created virtual machines before the Christian era
)
{
{
yyyy,
0,
0,
0,
0
};
if (RTTimeNormalize(&time))
return;
}
throw ConfigFileError(this, NULL, N_("Cannot parse ISO timestamp '%s': runtime error, %Rra"), str.c_str(), rc);
}
throw ConfigFileError(this, NULL, N_("Cannot parse ISO timestamp '%s': invalid format"), str.c_str());
}
}
/**
* Helper to create a string for a RTTIMESPEC for writing out ISO timestamps.
* @param stamp
* @return
*/
{
return Utf8StrFmt("%04u-%02u-%02uT%02u:%02u:%02uZ",
}
/**
* Helper method to read in an ExtraData subtree and stores its contents
* in the given map of extradata items. Used for both main and machine
* extradata (MainConfigFile and MachineConfigFile).
* @param elmExtraData
* @param map
*/
{
{
{
// <ExtraDataItem name="GUI/LastWindowPostion" value="97,88,981,858"/>
else
throw ConfigFileError(this, pelmExtraDataItem, N_("Required ExtraDataItem/@name or @value attribute is missing"));
}
}
}
/**
* Reads <USBDeviceFilter> entries from under the given elmDeviceFilters node and
* stores them in the given linklist. This is in ConfigFileBase because it's used
* from both MainConfigFile (for host filters) and MachineConfigFile (for machine
* filters).
* @param elmDeviceFilters
* @param ll
*/
{
{
{
// the next 2 are irrelevant for host USB objects
// action is only used with host USB objects
{
if (strAction == "Ignore")
else if (strAction == "Hold")
else
throw ConfigFileError(this, pelmLevel4Child, N_("Invalid value '%s' in DeviceFilter/@action attribute"), strAction.c_str());
}
}
}
}
/**
* Reads a media registry entry from the main VirtualBox.xml file.
*
* Whereas the current media registry code is fairly straightforward, it was quite a mess
* with settings format before 1.4 (VirtualBox 2.0 used settings format 1.3). The elements
* in the media registry were much more inconsistent, and different elements were used
* depending on the type of device and image.
*
* @param t
* @param elmMedium
* @param llMedia
*/
// child HardDisk node or DiffHardDisk node for pre-1.4
{
// <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
throw ConfigFileError(this, &elmMedium, N_("Required %s/@uuid attribute is missing"), elmMedium.getName());
bool fNeedsLocation = true;
if (t == HardDisk)
{
if (m->sv < SettingsVersion_v1_4)
{
// here the system is:
// <HardDisk uuid="{....}" type="normal">
// </HardDisk>
fNeedsLocation = false;
bool fNeedsFilePath = true;
{
fNeedsFilePath = false;
// string for the location and also have several disk properties for these, whereas this used
// to be hidden in several sub-elements before 1.4, so compose a location string and set up
// the properties:
{
}
{
}
{
if (strServerAndPort.length())
}
{
}
{
}
}
{
fNeedsFilePath = false;
fNeedsLocation = true;
// also requires @format attribute, which will be queried below
}
else
throw ConfigFileError(this, &elmMedium, N_("Required %s/VirtualDiskImage element is missing"), elmMedium.getName());
if (fNeedsFilePath)
{
throw ConfigFileError(this, &elmMedium, N_("Required %s/@filePath attribute is missing"), elmMedium.getName());
}
}
throw ConfigFileError(this, &elmMedium, N_("Required %s/@format attribute is missing"), elmMedium.getName());
med.fAutoReset = false;
{
// pre-1.4 used lower case, so make this case-insensitive
if (strType == "NORMAL")
else if (strType == "IMMUTABLE")
else if (strType == "WRITETHROUGH")
else if (strType == "SHAREABLE")
else if (strType == "READONLY")
else if (strType == "MULTIATTACH")
else
throw ConfigFileError(this, &elmMedium, N_("HardDisk/@type attribute must be one of Normal, Immutable, Writethrough, Shareable, Readonly or MultiAttach"));
}
}
else
{
if (m->sv < SettingsVersion_v1_4)
{
// DVD and floppy images before 1.4 had "src" attribute instead of "location"
throw ConfigFileError(this, &elmMedium, N_("Required %s/@src attribute is missing"), elmMedium.getName());
fNeedsLocation = false;
}
{
// DVD and floppy images before 1.11 had no format attribute. assign the default.
}
if (t == DVDImage)
else if (t == FloppyImage)
}
if (fNeedsLocation)
// current files and 1.4 CustomHardDisk elements must have a location attribute
throw ConfigFileError(this, &elmMedium, N_("Required %s/@location attribute is missing"), elmMedium.getName());
// recurse to handle children
{
if ( t == HardDisk
|| ( (m->sv < SettingsVersion_v1_4)
)
)
)
// recurse with this element and push the child onto our current children list
readMedium(t,
{
else
throw ConfigFileError(this, pelmHDChild, N_("Required HardDisk/Property/@name or @value attribute is missing"));
}
}
}
/**
* Reads in the entire <MediaRegistry> chunk and stores its media in the lists
* of the given MediaRegistry structure.
*
* This is used in both MainConfigFile and MachineConfigFile since starting with
* VirtualBox 4.0, we can have media registries in both.
*
* For pre-1.4 files, this gets called with the <DiskRegistry> chunk instead.
*
* @param elmMediaRegistry
*/
{
{
t = HardDisk;
t = DVDImage;
t = FloppyImage;
else
continue;
{
if ( t == HardDisk
)
readMedium(t,
else if ( t == DVDImage
)
readMedium(t,
else if ( t == FloppyImage
)
readMedium(t,
}
}
}
/**
* This is common version for reading NAT port forward rule in per-_machine's_adapter_ and
* per-network approaches.
* Note: this function doesn't in fill given list from xml::ElementNodesList, because there is conflicting
* declaration in ovmfreader.h.
*/
void ConfigFileBase::readNATForwardRuleList(const xml::ElementNode &elmParent, NATRuleList &llRules)
{
{
}
}
void ConfigFileBase::readNATLoopbacks(const xml::ElementNode &elmParent, NATLoopbackOffsetList &llLoopbacks)
{
{
}
}
/**
* Adds a "version" attribute to the given XML element with the
* VirtualBox settings version (e.g. "1.10-linux"). Used by
* the XML format for the root element and by the OVF export
* for the vbox:Machine element.
* @param elm
*/
{
const char *pcszVersion = NULL;
switch (m->sv)
{
case SettingsVersion_v1_8:
pcszVersion = "1.8";
break;
case SettingsVersion_v1_9:
pcszVersion = "1.9";
break;
case SettingsVersion_v1_10:
pcszVersion = "1.10";
break;
case SettingsVersion_v1_11:
pcszVersion = "1.11";
break;
case SettingsVersion_v1_12:
pcszVersion = "1.12";
break;
case SettingsVersion_v1_13:
pcszVersion = "1.13";
break;
case SettingsVersion_v1_14:
pcszVersion = "1.14";
break;
case SettingsVersion_v1_15:
pcszVersion = "1.15";
break;
case SettingsVersion_Future:
// can be set if this code runs on XML files that were created by a future version of VBox;
// in that case, downgrade to current version when writing since we can't write future versions...
pcszVersion = "1.15";
m->sv = SettingsVersion_v1_15;
break;
default:
// silently upgrade if this is less than 1.7 because that's the oldest we can write
pcszVersion = "1.7";
m->sv = SettingsVersion_v1_7;
break;
}
VBOX_XML_PLATFORM)); // e.g. "linux"
}
/**
* Creates a new stub xml::Document in the m->pDoc member with the
* root "VirtualBox" element set up. This is used by both
* MainConfigFile and MachineConfigFile at the beginning of writing
* out their XML.
*
* Before calling this, it is the responsibility of the caller to
* set the "sv" member to the required settings version that is to
* be written. For newly created files, the settings version will be
* the latest (1.12); for files read in from disk earlier, it will be
* the settings version indicated in the file. However, this method
* will silently make sure that the settings version is always
* at least 1.7 and change it if necessary, since there is no write
* support for earlier settings versions.
*/
void ConfigFileBase::createStubDocument()
{
"\n"
"** DO NOT EDIT THIS FILE.\n"
"** If you make changes to this file while any VirtualBox related application\n"
"** is running, your changes will be overwritten later, without taking effect.\n"
"** Use VBoxManage or the VirtualBox Manager GUI to make changes.\n"
);
// add settings version attribute to root element
setVersionAttribute(*m->pelmRoot);
// since this gets called before the XML document is actually written out,
// this is where we must check whether we're upgrading the settings version
// and need to make a backup, so the user can go back to an earlier
// VirtualBox version and recover his old settings files.
)
{
// compose new filename: strip off trailing ".xml"/".vbox"
{
strExt = ".vbox";
}
// and append something like "-1.3-linux.xml"
0); // no RTFILEMOVE_FLAGS_REPLACE
// do this only once
m->svRead = SettingsVersion_Null;
}
}
/**
* Creates an <ExtraData> node under the given parent element with
* <ExtraDataItem> childern according to the contents of the given
* map.
*
* This is in ConfigFileBase because it's used in both MainConfigFile
* and MachineConfigFile, which both can have extradata.
*
* @param elmParent
* @param me
*/
const StringsMap &me)
{
{
++it)
{
}
}
}
/**
* Creates <DeviceFilter> nodes under the given parent element according to
* the contents of the given USBDeviceFiltersList. This is in ConfigFileBase
* because it's used in both MainConfigFile (for host filters) and
* MachineConfigFile (for machine filters).
*
* If fHostMode is true, this means that we're supposed to write filters
* for the IHost interface (respect "action", omit "strRemote" and
* "ulMaskedInterfaces" in struct USBDeviceFilter).
*
* @param elmParent
* @param ll
* @param fHostMode
*/
const USBDeviceFiltersList &ll,
bool fHostMode)
{
++it)
{
if (fHostMode)
{
const char *pcsz =
: /*(flt.action == USBDeviceFilterAction_Hold) ?*/ "Hold";
}
else
{
if (flt.ulMaskedInterfaces)
}
}
}
/**
* Creates a single <HardDisk> element for the given Medium structure
* and recurses to write the child hard disks underneath. Called from
* MainConfigFile::write().
*
* @param elmMedium
* @param m
* @param level
*/
{
if (devType == DeviceType_HardDisk)
else
if ( devType == DeviceType_HardDisk
&& mdm.fAutoReset)
++it)
{
}
// only for base hard disks, save the type
if (level == 0)
{
if ( ( devType != DeviceType_DVD
&& ( devType != DeviceType_Floppy
{
const char *pcszType =
"INVALID";
}
}
++it)
{
// recurse for children
devType, // device type
*it, // settings::Medium
++level); // recursion level
}
}
/**
* Creates a <MediaRegistry> node under the given parent and writes out all
* hard disks and DVD and floppy images from the lists in the given MediaRegistry
* structure under it.
*
* This is used in both MainConfigFile and MachineConfigFile since starting with
* VirtualBox 4.0, we can have media registries in both.
*
* @param elmParent
* @param mr
*/
const MediaRegistry &mr)
{
++it)
{
}
++it)
{
}
++it)
{
}
}
/**
* Serialize NAT port-forwarding rules in parent container.
* Note: it's responsibility of caller to create parent of the list tag.
* because this method used for serializing per-_mahine's_adapter_ and per-network approaches.
*/
void ConfigFileBase::buildNATForwardRuleList(xml::ElementNode &elmParent, const NATRuleList &natRuleList)
{
r != natRuleList.end(); ++r)
{
if ((*r).u16HostPort)
if ((*r).strGuestIP.length())
if ((*r).u16GuestPort)
}
}
void ConfigFileBase::buildNATLoopbacks(xml::ElementNode &elmParent, const NATLoopbackOffsetList &natLoopbackOffsetList)
{
{
}
}
/**
* Cleans up memory allocated by the internal XML parser. To be called by
* descendant classes when they're done analyzing the DOM tree to discard it.
*/
void ConfigFileBase::clearDocument()
{
m->cleanup();
}
/**
* Returns true only if the underlying config file exists on disk;
* either because the file has been loaded from disk, or it's been written
* to disk, or both.
* @return
*/
bool ConfigFileBase::fileExists()
{
return m->fFileExists;
}
/**
* Copies the base variables from another instance. Used by Machine::saveSettings
* so that the settings version does not get lost when a copy of the Machine settings
* file is made to see if settings have actually changed.
* @param b
*/
{
m->copyFrom(*b.m);
}
////////////////////////////////////////////////////////////////////////////////
//
// Structures shared between Machine XML and VirtualBox.xml
//
////////////////////////////////////////////////////////////////////////////////
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool USBDeviceFilter::operator==(const USBDeviceFilter &u) const
{
return ( (this == &u)
&& (strVendorId == u.strVendorId)
&& (strProductId == u.strProductId)
&& (strRevision == u.strRevision)
&& (strManufacturer == u.strManufacturer)
&& (strProduct == u.strProduct)
&& (strSerialNumber == u.strSerialNumber)
&& (ulMaskedInterfaces == u.ulMaskedInterfaces)
)
);
}
////////////////////////////////////////////////////////////////////////////////
//
// MainConfigFile
//
////////////////////////////////////////////////////////////////////////////////
/**
* Reads one <MachineEntry> from the main VirtualBox.xml file.
* @param elmMachineRegistry
*/
{
// <MachineEntry uuid="{ xxx }" src=" xxx "/>
{
{
{
}
else
throw ConfigFileError(this, pelmChild1, N_("Required MachineEntry/@uuid or @src attribute is missing"));
}
}
}
/**
* Reads in the <DHCPServers> chunk.
* @param elmDHCPServers
*/
{
{
{
{
/* XXX: Options are in 1:1 relation to DHCPServer */
{
} /* end of forall("Options") */
{
}
}
else
throw ConfigFileError(this, pelmServer, N_("Required DHCPServer/@networkName, @IPAddress, @networkMask, @lowerIP, @upperIP or @enabled attribute is missing"));
}
}
}
{
{
if (OptName == DhcpOpt_SubnetMask)
continue;
} /* end of forall("Option") */
}
/**
* Reads in the <NATNetworks> chunk.
* @param elmNATNetworks
*/
{
{
{
{
}
else
throw ConfigFileError(this, pelmNet, N_("Required NATNetwork/@networkName, @gateway, @network,@advertiseDefaultIpv6Route , @needDhcp or @enabled attribute is missing"));
}
}
}
/**
* Constructor.
*
* If pstrFilename is != NULL, this reads the given settings file into the member
* variables and various substructures and lists. Otherwise, the member variables
* are initialized with default values.
*
* Throws variants of xml::Error for I/O, XML and logical content errors, which
* the caller should catch; if this constructor does not throw, then the member
* variables contain meaningful values (either from the file or defaults).
*
* @param strFilename
*/
{
if (pstrFilename)
{
// the ConfigFileBase constructor has loaded the XML file, so now
// we need only analyze what is in there
{
{
{
{
pelmGlobalChild->getAttributeValue("defaultMachineFolder", systemProperties.strDefaultMachineFolder);
pelmGlobalChild->getAttributeValue("defaultHardDiskFormat", systemProperties.strDefaultHardDiskFormat);
// pre-1.11 used @remoteDisplayAuthLibrary instead
pelmGlobalChild->getAttributeValue("remoteDisplayAuthLibrary", systemProperties.strVRDEAuthLibrary);
pelmGlobalChild->getAttributeValue("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
pelmGlobalChild->getAttributeValue("autostartDatabasePath", systemProperties.strAutostartDatabasePath);
}
|| ( (m->sv < SettingsVersion_v1_4)
)
)
{
{
}
}
}
} // end if (pelmRootChild->nameEquals("Global"))
}
}
// DHCP servers were introduced with settings version 1.7; if we're loading
// from an older version OR this is a fresh install, then add one DHCP server
// with default settings
if ( (!llDhcpServers.size())
&& ( (!pstrFilename) // empty VirtualBox.xml file
)
)
{
#ifdef RT_OS_WINDOWS
"HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter";
#else
"HostInterfaceNetworking-vboxnet0";
#endif
}
}
{
if (m->sv < SettingsVersion_v1_14)
{
// VirtualBox 4.3 adds NAT networks.
if ( !llNATNetworks.empty())
m->sv = SettingsVersion_v1_14;
}
}
/**
* Called from the IVirtualBox interface to write out VirtualBox.xml. This
* builds an XML DOM tree and writes it out to disk.
*/
{
m->strFilename = strFilename;
++it)
{
// <MachineEntry uuid="{5f102a55-a51b-48e3-b45a-b28d33469488}" src="/mnt/innotek-unix/vbox-machines/Windows 5.1 XP 1 (Office 2003)/Windows 5.1 XP 1 (Office 2003).xml"/>
}
++it)
{
const DHCPServer &d = *it;
/* We assume that if there're only 1 element it means that */
/* We don't want duplicate validation check of networkMask here*/
&& cOpt > 0)
|| cOpt > 1)
{
++itOpt)
{
continue;
if (!pelmOpt)
break;
}
} /* end of if */
if (d.VmSlot2OptionsM.size() > 0)
{
++itVmSlot)
{
++itOpt1)
{
}
}
} /* and of if */
}
/* don't create entry if no NAT networks are registered. */
if (!llNATNetworks.empty())
{
++it)
{
const NATNetwork &n = *it;
if (n.llPortForwardRules4.size())
{
}
if (n.llPortForwardRules6.size())
{
}
if (n.llHostLoopbackOffsetList.size())
{
}
}
}
true); // fHostMode
// now go write the XML
m->fFileExists = true;
}
////////////////////////////////////////////////////////////////////////////////
//
// Machine XML structures
//
////////////////////////////////////////////////////////////////////////////////
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool VRDESettings::operator==(const VRDESettings& v) const
{
return ( (this == &v)
&& (ulAuthTimeout == v.ulAuthTimeout)
&& (strAuthLibrary == v.strAuthLibrary)
&& (fAllowMultiConnection == v.fAllowMultiConnection)
&& (fReuseSingleConnection == v.fReuseSingleConnection)
&& (strVrdeExtPack == v.strVrdeExtPack)
&& (mapProperties == v.mapProperties)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool BIOSSettings::operator==(const BIOSSettings &d) const
{
return ( (this == &d)
|| ( fACPIEnabled == d.fACPIEnabled
&& fIOAPICEnabled == d.fIOAPICEnabled
&& fLogoFadeIn == d.fLogoFadeIn
&& fLogoFadeOut == d.fLogoFadeOut
&& ulLogoDisplayTime == d.ulLogoDisplayTime
&& strLogoImagePath == d.strLogoImagePath
&& biosBootMenuMode == d.biosBootMenuMode
&& fPXEDebugEnabled == d.fPXEDebugEnabled
&& llTimeOffset == d.llTimeOffset)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool USBController::operator==(const USBController &u) const
{
return ( (this == &u)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
{
return ( (this == &u)
|| ( (llUSBControllers == u.llUSBControllers)
&& (llDeviceFilters == u.llDeviceFilters)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool NetworkAdapter::operator==(const NetworkAdapter &n) const
{
return ( (this == &n)
&& (strMACAddress == n.strMACAddress)
&& (fCableConnected == n.fCableConnected)
&& (ulLineSpeed == n.ulLineSpeed)
&& (enmPromiscModePolicy == n.enmPromiscModePolicy)
&& (fTraceEnabled == n.fTraceEnabled)
&& (strTraceFile == n.strTraceFile)
&& (strBridgedName == n.strBridgedName)
&& (strHostOnlyName == n.strHostOnlyName)
&& (strInternalNetworkName == n.strInternalNetworkName)
&& (strGenericDriver == n.strGenericDriver)
&& (genericProperties == n.genericProperties)
&& (ulBootPriority == n.ulBootPriority)
&& (strBandwidthGroup == n.strBandwidthGroup)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool SerialPort::operator==(const SerialPort &s) const
{
return ( (this == &s)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool ParallelPort::operator==(const ParallelPort &s) const
{
return ( (this == &s)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool SharedFolder::operator==(const SharedFolder &g) const
{
return ( (this == &g)
&& (strHostPath == g.strHostPath)
&& (fAutoMount == g.fAutoMount)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool GuestProperty::operator==(const GuestProperty &g) const
{
return ( (this == &g)
)
);
}
: strVersion("1"),
fHardwareVirt(true),
fNestedPaging(true),
fVPID(true),
fUnrestrictedExecution(true),
fHardwareVirtForce(false),
fSyntheticCpu(false),
fTripleFaultReset(false),
fPAE(false),
cCPUs(1),
fCpuHotPlug(false),
fHPETEnabled(false),
ulCpuExecutionCap(100),
ulVRAMSizeMB(8),
cMonitors(1),
fAccelerate3D(false),
fAccelerate2DVideo(false),
ulVideoCaptureHorzRes(1024),
ulVideoCaptureVertRes(768),
ulVideoCaptureRate(512),
ulVideoCaptureFPS(25),
fVideoCaptureEnabled(false),
strVideoCaptureFile(""),
fEmulatedUSBCardReader(false),
fPageFusionEnabled(false)
{
/* The default value for PAE depends on the host:
* - 64 bits host -> always true
* - 32 bits host -> true for Windows & Darwin (masked off if the host cpu doesn't support it anyway)
*/
fPAE = true;
#endif
/* The default value of large page supports depends on the host:
* - 64 bits host -> true, unless it's Linux (pending further prediction work due to excessively expensive large page allocations)
* - 32 bits host -> false
*/
fLargePages = true;
#else
/* Not supported on 32 bits hosts. */
fLargePages = false;
#endif
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
{
return ( (this == &h)
|| ( (strVersion == h.strVersion)
&& (fHardwareVirt == h.fHardwareVirt)
&& (fNestedPaging == h.fNestedPaging)
&& (fLargePages == h.fLargePages)
&& (fUnrestrictedExecution == h.fUnrestrictedExecution)
&& (fHardwareVirtForce == h.fHardwareVirtForce)
&& (fSyntheticCpu == h.fSyntheticCpu)
&& (enmLongMode == h.enmLongMode)
&& (fTripleFaultReset == h.fTripleFaultReset)
&& (fCpuHotPlug == h.fCpuHotPlug)
&& (ulCpuExecutionCap == h.ulCpuExecutionCap)
&& (fHPETEnabled == h.fHPETEnabled)
&& (llCpuIdLeafs == h.llCpuIdLeafs)
&& (ulMemorySizeMB == h.ulMemorySizeMB)
&& (mapBootOrder == h.mapBootOrder)
&& (graphicsControllerType == h.graphicsControllerType)
&& (ulVRAMSizeMB == h.ulVRAMSizeMB)
&& (fAccelerate3D == h.fAccelerate3D)
&& (fAccelerate2DVideo == h.fAccelerate2DVideo)
&& (fVideoCaptureEnabled == h.fVideoCaptureEnabled)
&& (u64VideoCaptureScreens == h.u64VideoCaptureScreens)
&& (strVideoCaptureFile == h.strVideoCaptureFile)
&& (ulVideoCaptureHorzRes == h.ulVideoCaptureHorzRes)
&& (ulVideoCaptureVertRes == h.ulVideoCaptureVertRes)
&& (ulVideoCaptureRate == h.ulVideoCaptureRate)
&& (ulVideoCaptureFPS == h.ulVideoCaptureFPS)
&& (firmwareType == h.firmwareType)
&& (pointingHIDType == h.pointingHIDType)
&& (keyboardHIDType == h.keyboardHIDType)
&& (chipsetType == h.chipsetType)
&& (fEmulatedUSBCardReader == h.fEmulatedUSBCardReader)
&& (vrdeSettings == h.vrdeSettings)
&& (biosSettings == h.biosSettings)
&& (usbSettings == h.usbSettings)
&& (llNetworkAdapters == h.llNetworkAdapters)
&& (llSerialPorts == h.llSerialPorts)
&& (llParallelPorts == h.llParallelPorts)
&& (audioAdapter == h.audioAdapter)
&& (llSharedFolders == h.llSharedFolders)
&& (clipboardMode == h.clipboardMode)
&& (dragAndDropMode == h.dragAndDropMode)
&& (ulMemoryBalloonSize == h.ulMemoryBalloonSize)
&& (fPageFusionEnabled == h.fPageFusionEnabled)
&& (llGuestProperties == h.llGuestProperties)
&& (ioSettings == h.ioSettings)
&& (pciAttachments == h.pciAttachments)
&& (strDefaultFrontend == h.strDefaultFrontend)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool AttachedDevice::operator==(const AttachedDevice &a) const
{
return ( (this == &a)
|| ( (deviceType == a.deviceType)
&& (fPassThrough == a.fPassThrough)
&& (fTempEject == a.fTempEject)
&& (fNonRotational == a.fNonRotational)
&& (fHotPluggable == a.fHotPluggable)
&& (strHostDriveSrc == a.strHostDriveSrc)
&& (strBwGroup == a.strBwGroup)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
bool StorageController::operator==(const StorageController &s) const
{
return ( (this == &s)
&& (storageBus == s.storageBus)
&& (controllerType == s.controllerType)
&& (ulPortCount == s.ulPortCount)
&& (ulInstance == s.ulInstance)
&& (fUseHostIOCache == s.fUseHostIOCache)
&& (llAttachedDevices == s.llAttachedDevices)
)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
{
return ( (this == &s)
);
}
/**
* Comparison operator. This gets called from MachineConfigFile::operator==,
* which in turn gets called from Machine::saveSettings to figure out whether
* machine settings have really changed and thus need to be written out to disk.
*/
{
return ( (this == &s)
&& (strDescription == s.strDescription)
&& (strStateFile == s.strStateFile)
)
);
}
/**
* IOSettings constructor.
*/
{
fIOCacheEnabled = true;
ulIOCacheSize = 5;
}
////////////////////////////////////////////////////////////////////////////////
//
// MachineConfigFile
//
////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*
* If pstrFilename is != NULL, this reads the given settings file into the member
* variables and various substructures and lists. Otherwise, the member variables
* are initialized with default values.
*
* Throws variants of xml::Error for I/O, XML and logical content errors, which
* the caller should catch; if this constructor does not throw, then the member
* variables contain meaningful values (either from the file or defaults).
*
* @param strFilename
*/
fCurrentStateModified(true),
fAborted(false)
{
if (pstrFilename)
{
// the ConfigFileBase constructor has loaded the XML file, so now
// we need only analyze what is in there
{
}
// clean up memory allocated by XML engine
}
}
/**
* Public routine which returns true if this machine config file can have its
* own media registry (which is true for settings version v1.11 and higher,
* i.e. files created by VirtualBox 4.0 and higher).
* @return
*/
bool MachineConfigFile::canHaveOwnMediaRegistry() const
{
return (m->sv >= SettingsVersion_v1_11);
}
/**
* Public routine which allows for importing machine XML from an external DOM tree.
* Use this after having called the constructor with a NULL argument.
*
* This is used by the OVF code if a <vbox:Machine> element has been encountered
* in an OVF VirtualSystem element.
*
* @param elmMachine
*/
{
}
/**
* Comparison operator. This gets called from Machine::saveSettings to figure out
* whether machine settings have really changed and thus need to be written out to disk.
*
* Even though this is called operator==, this does NOT compare all fields; the "equals"
* should be understood as "has the same machine config as". The following fields are
* NOT compared:
* -- settings versions and file names inherited from ConfigFileBase;
* -- fCurrentStateModified because that is considered separately in Machine::saveSettings!!
*
* The "deep" comparisons marked below will invoke the operator== functions of the
* structs defined in this file, which may in turn go into comparing lists of
* other structures. As a result, invoking this can be expensive, but it's
* less expensive than writing out XML to disk.
*/
bool MachineConfigFile::operator==(const MachineConfigFile &c) const
{
return ( (this == &c)
&& (machineUserData == c.machineUserData)
&& (strStateFile == c.strStateFile)
&& (uuidCurrentSnapshot == c.uuidCurrentSnapshot)
// skip fCurrentStateModified!
)
);
}
/**
* Called from MachineConfigFile::readHardware() to read cpu information.
* @param elmCpuid
* @param ll
*/
{
{
}
}
/**
* Called from MachineConfigFile::readHardware() to cpuid information.
* @param elmCpuid
* @param ll
*/
{
{
}
}
/**
* Called from MachineConfigFile::readHardware() to network information.
* @param elmNetwork
* @param ll
*/
{
{
{
if (strTemp == "Am79C970A")
else if (strTemp == "Am79C973")
else if (strTemp == "82540EM")
else if (strTemp == "82543GC")
else if (strTemp == "82545EM")
else if (strTemp == "virtio")
else
throw ConfigFileError(this, pelmAdapter, N_("Invalid value '%s' in Adapter/@type attribute"), strTemp.c_str());
}
{
if (strTemp == "Deny")
else if (strTemp == "AllowNetwork")
else if (strTemp == "AllowAll")
else
throw ConfigFileError(this, pelmAdapter,
}
/* We should have only active mode descriptor and disabled modes set */
{
throw ConfigFileError(this, pelmAdapter, N_("Invalid number of modes ('%d') attached to Adapter attribute"), llNetworkModes.size());
}
{
{
/* run over disabled list and load settings */
{
}
}
else
}
// else: default is NetworkAttachmentType_Null
}
}
void MachineConfigFile::readAttachedNetworkMode(const xml::ElementNode &elmMode, bool fEnabled, NetworkAdapter &nic)
{
{
{
}
{
}
{
}
}
{
}
{
}
{
}
{
// get all properties
{
{
else
throw ConfigFileError(this, pelmModeChild, N_("Required GenericInterface/Property/@name or @value attribute is missing"));
}
}
}
{
}
{
}
}
/**
* Called from MachineConfigFile::readHardware() to read serial port information.
* @param elmUART
* @param ll
*/
{
{
// slot must be unique
++it)
throw ConfigFileError(this, pelmPort, N_("Invalid value %RU32 in UART/Port/@slot attribute: value is not unique"), port.ulSlot);
if (strPortMode == "RawFile")
else if (strPortMode == "HostPipe")
else if (strPortMode == "HostDevice")
else if (strPortMode == "Disconnected")
else
throw ConfigFileError(this, pelmPort, N_("Invalid value '%s' in UART/Port/@hostMode attribute"), strPortMode.c_str());
}
}
/**
* Called from MachineConfigFile::readHardware() to read parallel port information.
* @param elmLPT
* @param ll
*/
{
{
// slot must be unique
++it)
throw ConfigFileError(this, pelmPort, N_("Invalid value %RU32 in LPT/Port/@slot attribute: value is not unique"), port.ulSlot);
}
}
/**
* Called from MachineConfigFile::readHardware() to read audio adapter information
* and maybe fix driver information depending on the current host hardware.
*
* @param elmAudioAdapter "AudioAdapter" XML element.
* @param hw
*/
{
{
if (strTemp == "SB16")
else if (strTemp == "AC97")
else if (strTemp == "HDA")
else
throw ConfigFileError(this, &elmAudioAdapter, N_("Invalid value '%s' in AudioAdapter/@controller attribute"), strTemp.c_str());
}
{
// settings before 1.3 used lower case so make sure this is case-insensitive
if (strTemp == "NULL")
else if (strTemp == "WINMM")
else if (strTemp == "SOLAUDIO")
else if (strTemp == "ALSA")
else if (strTemp == "PULSE")
else if (strTemp == "OSS")
else if (strTemp == "COREAUDIO")
else if (strTemp == "MMPM")
else
throw ConfigFileError(this, &elmAudioAdapter, N_("Invalid value '%s' in AudioAdapter/@driver attribute"), strTemp.c_str());
// now check if this is actually supported on the current host platform;
// people might be opening a file created on a Windows host, and that
// VM should still start on a Linux host
}
}
/**
* Called from MachineConfigFile::readHardware() to read guest property information.
* @param elmGuestProperties
* @param hw
*/
{
{
}
}
/**
* Helper function to read attributes that are common to <SATAController> (pre-1.7)
* and <StorageController>.
* @param elmStorageController
* @param strg
*/
void MachineConfigFile::readStorageControllerAttributes(const xml::ElementNode &elmStorageController,
{
}
/**
* Reads in a <Hardware> block and stores it in the given structure. Used
* both directly from readMachine and from readSnapshot, since snapshots
* have their own hardware sections.
*
* For legacy pre-1.7 settings we also need a storage structure because
* the IDE and SATA controllers used to be defined under <Hardware>.
*
* @param elmHardware
* @param hw
*/
{
{
/* KLUDGE ALERT! For a while during the 3.1 development this was not
written because it was thought to have a default value of "2". For
sv <= 1.3 it defaults to "1" because the attribute didn't exist,
while for 1.4+ it is sort of mandatory. Now, the buggy XML writer
code only wrote 1.7 and later. So, if it's a 1.7+ XML file and it's
missing the hardware version, then it probably should be "2" instead
of "1". */
if (m->sv < SettingsVersion_v1_7)
else
}
{
{
{
// pre-1.5 variant; not sure if this actually exists in the wild anywhere
}
if (hw.fCpuHotPlug)
{
}
{
}
{
/* The default for pre 3.1 was false, so we must respect that. */
if (m->sv < SettingsVersion_v1_9)
}
else
bool fLongMode;
else
}
{
}
{
{
if ( (strFirmwareType == "BIOS")
)
else if ( (strFirmwareType == "EFI")
)
else if ( strFirmwareType == "EFI32")
else if ( strFirmwareType == "EFI64")
else if ( strFirmwareType == "EFIDUAL")
else
throw ConfigFileError(this,
N_("Invalid value '%s' in Firmware/@type"),
strFirmwareType.c_str());
}
}
{
{
if (strHIDType == "None")
else if (strHIDType == "USBKeyboard")
else if (strHIDType == "PS2Keyboard")
else if (strHIDType == "ComboKeyboard")
else
throw ConfigFileError(this,
strHIDType.c_str());
}
{
if (strHIDType == "None")
else if (strHIDType == "USBMouse")
else if (strHIDType == "USBTablet")
else if (strHIDType == "PS2Mouse")
else if (strHIDType == "ComboMouse")
else if (strHIDType == "USBMultiTouch")
else
throw ConfigFileError(this,
strHIDType.c_str());
}
}
{
{
if (strChipsetType == "PIIX3")
else if (strChipsetType == "ICH9")
else
throw ConfigFileError(this,
N_("Invalid value '%s' in Chipset/@type"),
strChipsetType.c_str());
}
}
{
}
{
{
if ( ulPos < 1
)
throw ConfigFileError(this,
// XML is 1-based but internal data is 0-based
--ulPos;
throw ConfigFileError(this, pelmOrder, N_("Invalid value '%RU32' in Boot/Order/@position: value is not unique"), ulPos);
if (strDevice == "None")
else if (strDevice == "Floppy")
else if (strDevice == "DVD")
else if (strDevice == "HardDisk")
else if (strDevice == "Network")
else
throw ConfigFileError(this, pelmOrder, N_("Invalid value '%s' in Boot/Order/@device attribute"), strDevice.c_str());
}
}
{
else
{
if (strGraphicsControllerType == "VBOXVGA")
else if (strGraphicsControllerType == "VMSVGA")
else if (strGraphicsControllerType == "NONE")
else
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in Display/@controller attribute"), strGraphicsControllerType.c_str());
}
}
{
}
{
{
// settings before 1.3 used lower case so make sure this is case-insensitive
if (strAuthType == "NULL")
else if (strAuthType == "GUEST")
else if (strAuthType == "EXTERNAL")
else
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in RemoteDisplay/@authType attribute"), strAuthType.c_str());
}
/* 3.2 and 4.0 betas, 4.0 has this information in VRDEProperties. */
{
bool fVideoChannel = false;
{
}
else
}
if (pelmProperties != NULL)
{
{
{
else
throw ConfigFileError(this, pelmProperty, N_("Required VRDE Property/@name or @value attribute is missing"));
}
}
}
}
{
{
}
{
{
// settings before 1.3 used lower case so make sure this is case-insensitive
if (strBootMenuMode == "DISABLED")
else if (strBootMenuMode == "MENUONLY")
else if (strBootMenuMode == "MESSAGEANDMENU")
else
throw ConfigFileError(this, pelmBIOSChild, N_("Invalid value '%s' in BootMenu/@mode attribute"), strBootMenuMode.c_str());
}
}
// legacy BIOS/IDEController (pre 1.7)
if ( (m->sv < SettingsVersion_v1_7)
)
{
{
if (strType == "PIIX3")
else if (strType == "PIIX4")
else if (strType == "ICH6")
else
throw ConfigFileError(this, pelmBIOSChild, N_("Invalid value '%s' for IDEController/@type attribute"), strType.c_str());
}
}
}
else if ( (m->sv <= SettingsVersion_v1_14)
{
bool fEnabled = false;
if (fEnabled)
{
/* Create OHCI controller with default name. */
}
if (fEnabled)
{
/* Create OHCI controller with default name. */
}
}
{
{
{
{
if (strCtrlType == "OHCI")
else if (strCtrlType == "EHCI")
else if (strCtrlType == "XHCI")
else
throw ConfigFileError(this, pelmCtrl, N_("Invalid value '%s' for Controller/@type attribute"), strCtrlType.c_str());
}
}
}
}
else if ( m->sv < SettingsVersion_v1_7
{
bool f;
&& f)
{
}
}
{
&& strLocalOrUTC == "UTC";
}
)
)
{
{
}
}
{
{
if (strTemp == "Disabled")
else if (strTemp == "HostToGuest")
else if (strTemp == "GuestToHost")
else if (strTemp == "Bidirectional")
else
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in Clipboard/@mode attribute"), strTemp.c_str());
}
}
{
{
if (strTemp == "Disabled")
else if (strTemp == "HostToGuest")
else if (strTemp == "GuestToHost")
else if (strTemp == "Bidirectional")
else
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in DragAndDrop/@mode attribute"), strTemp.c_str());
}
}
{
}
{
{
}
{
{
{
if (strTemp == "Disk")
else if (strTemp == "Network")
else
throw ConfigFileError(this, pelmBandwidthGroup, N_("Invalid value '%s' in BandwidthGroup/@type attribute"), strTemp.c_str());
}
else
{
}
}
}
}
{
{
{
/* name is optional */
}
}
}
{
{
}
}
{
{
}
}
}
throw ConfigFileError(this, &elmHardware, N_("Required Memory/@RAMSize element/attribute is missing"));
}
/**
* This gets called instead of readStorageControllers() for legacy pre-1.7 settings
* files which have a <HardDiskAttachments> node and storage controller settings
* hidden in the <Hardware> settings. We set the StorageControllers fields just the
* same, just from different sources.
* @param elmHardware <Hardware> XML node.
* @param elmHardDiskAttachments <HardDiskAttachments> XML node.
* @param strg
*/
void MachineConfigFile::readHardDiskAttachments_pre1_7(const xml::ElementNode &elmHardDiskAttachments,
{
++it)
{
StorageController &s = *it;
if (s.storageBus == StorageBus_IDE)
pIDEController = &s;
else if (s.storageBus == StorageBus_SATA)
pSATAController = &s;
}
{
throw ConfigFileError(this, pelmAttachment, N_("Required HardDiskAttachment/@hardDisk attribute is missing"));
throw ConfigFileError(this, pelmAttachment, N_("Required HardDiskAttachment/@bus attribute is missing"));
// pre-1.7 'channel' is now port
throw ConfigFileError(this, pelmAttachment, N_("Required HardDiskAttachment/@channel attribute is missing"));
// pre-1.7 'device' is still device
throw ConfigFileError(this, pelmAttachment, N_("Required HardDiskAttachment/@device attribute is missing"));
if (strBus == "IDE")
{
if (!pIDEController)
throw ConfigFileError(this, pelmAttachment, N_("HardDiskAttachment/@bus is 'IDE' but cannot find IDE controller"));
}
else if (strBus == "SATA")
{
if (!pSATAController)
throw ConfigFileError(this, pelmAttachment, N_("HardDiskAttachment/@bus is 'SATA' but cannot find SATA controller"));
}
else
throw ConfigFileError(this, pelmAttachment, N_("HardDiskAttachment/@bus attribute has illegal value '%s'"), strBus.c_str());
}
}
/**
* Reads in a <StorageControllers> block and stores it in the given Storage structure.
* Used both directly from readMachine and from readSnapshot, since snapshots
* have their own storage controllers sections.
*
* This is only called for settings version 1.7 and above; see readHardDiskAttachments_pre1_7()
* for earlier versions.
*
* @param elmStorageControllers
*/
{
{
throw ConfigFileError(this, pelmController, N_("Required StorageController/@name attribute is missing"));
// canonicalize storage controller names for configs in the switchover
// period.
if (m->sv < SettingsVersion_v1_9)
{
}
// default from constructor is 0
// default from constructor is true which is true
// for settings below version 1.11 because they allowed only
// one controller per type.
throw ConfigFileError(this, pelmController, N_("Required StorageController/@type attribute is missing"));
if (strType == "AHCI")
{
}
else if (strType == "LsiLogic")
{
}
else if (strType == "BusLogic")
{
}
else if (strType == "PIIX3")
{
}
else if (strType == "PIIX4")
{
}
else if (strType == "ICH6")
{
}
else if ( (m->sv >= SettingsVersion_v1_9)
&& (strType == "I82078")
)
{
}
else if (strType == "LsiLogicSas")
{
}
else if (strType == "USB")
{
}
else
throw ConfigFileError(this, pelmController, N_("Invalid value '%s' for StorageController/@type attribute"), strType.c_str());
{
att.fNonRotational = false;
att.fHotPluggable = false;
if (strTemp == "HardDisk")
{
}
else if (m->sv >= SettingsVersion_v1_9)
{
// starting with 1.9 we list DVD and floppy drive info + attachments under <StorageControllers>
if (strTemp == "DVD")
{
}
else if (strTemp == "Floppy")
}
{
// all types can have images attached, but for HardDisk it's required
{
else
{
// DVDs and floppies can also have <HostDrive> instead of <Image>
throw ConfigFileError(this, pelmHostDrive, N_("Required AttachedDevice/HostDrive/@src attribute is missing"));
}
}
else
{
throw ConfigFileError(this, pelmImage, N_("Required AttachedDevice/Image/@uuid attribute is missing"));
}
/* AHCI controller ports are hotpluggable by default, keep compatibility with existing settings. */
if (m->sv >= SettingsVersion_v1_15)
att.fHotPluggable = true;
}
}
}
}
/**
* This gets called for legacy pre-1.9 settings files after having parsed the
* <Hardware> and <StorageControllers> sections to parse <Hardware> once more
* for the <DVDDrive> and <FloppyDrive> sections.
*
* Before settings version 1.9, DVD and floppy drives were specified separately
* under <Hardware>; we then need this extra loop to make sure the storage
* controller structs are already set up so we can add stuff to them.
*
* @param elmHardware
* @param strg
*/
{
{
{
// create a DVD "attached device" and attach it to the existing IDE controller
// legacy DVD drive is always secondary master (port 1, device 0)
// find the IDE controller and attach the DVD drive
bool fFound = false;
++it)
{
{
fFound = true;
break;
}
}
if (!fFound)
throw ConfigFileError(this, pelmHwChild, N_("Internal error: found DVD drive but IDE controller does not exist"));
// shouldn't happen because pre-1.9 settings files always had at least one IDE controller in the settings
// which should have gotten parsed in <StorageControllers> before this got called
}
{
bool fEnabled;
&& fEnabled)
{
// create a new floppy controller and attach a floppy "attached device"
// store attachment with controller
// store controller with storage
}
}
}
}
/**
* Called for reading the <Teleporter> element under <Machine>.
*/
{
}
/**
* Called for reading the <Debugging> element under <Machine> or <Snapshot>.
*/
{
return;
if (pelmTracing)
{
}
}
/**
* Called for reading the <Autostart> element under <Machine> or <Snapshot>.
*/
{
return;
if (strAutostop == "Disabled")
else if (strAutostop == "SaveState")
else if (strAutostop == "PowerOff")
else if (strAutostop == "AcpiShutdown")
else
throw ConfigFileError(this, pElmAutostart, N_("Invalid value '%s' for Autostart/@autostop attribute"), strAutostop.c_str());
}
/**
* Called for reading the <Groups> element under <Machine>.
*/
{
{
return;
}
{
{
}
}
}
/**
* Called initially for the <Snapshot> element under <Machine>, if present,
* to store the snapshot's data into the given Snapshot structure (which is
* then the one in the Machine struct). This might then recurse if
* a <Snapshots> (plural) element is found in the snapshot, which should
* contain a list of child snapshots; such lists are maintained in the
* Snapshot structure.
*
* @param curSnapshotUuid
* @param depth
* @param elmSnapshot
* @param snap
* @returns true if curSnapshotUuid is in this snapshot subtree, otherwise false
*/
{
if (depth > SETTINGS_SNAPSHOT_DEPTH_MAX)
// earlier 3.1 trunk builds had a bug and added Description as an attribute, read it silently and write it back as an element
// parse Hardware before the other elements because other things depend on it
{
else if ( m->sv < SettingsVersion_v1_7
else if ( m->sv >= SettingsVersion_v1_7
{
{
{
// Use the heap to reduce the stack footprint. Each
// recursion needs over 1K, and there can be VMs with
// deeply nested snapshots. The stack can be quite
// small, especially with XPCOM.
delete child;
}
}
}
}
if (m->sv < SettingsVersion_v1_9)
// go through Hardware once more to repair the settings controller structures
// with data from old DVDDrive and FloppyDrive elements
// note: Groups exist only for Machine, not for Snapshot
return foundCurrentSnapshot;
}
const struct {
const char *pcszOld;
const char *pcszNew;
} aConvertOSTypes[] =
{
{ "unknown", "Other" },
{ "dos", "DOS" },
{ "win31", "Windows31" },
{ "win95", "Windows95" },
{ "win98", "Windows98" },
{ "winme", "WindowsMe" },
{ "winnt4", "WindowsNT4" },
{ "win2k", "Windows2000" },
{ "winxp", "WindowsXP" },
{ "win2k3", "Windows2003" },
{ "winvista", "WindowsVista" },
{ "win2k8", "Windows2008" },
{ "os2warp3", "OS2Warp3" },
{ "os2warp4", "OS2Warp4" },
{ "os2warp45", "OS2Warp45" },
{ "ecs", "OS2eCS" },
{ "linux22", "Linux22" },
{ "linux24", "Linux24" },
{ "linux26", "Linux26" },
{ "archlinux", "ArchLinux" },
{ "debian", "Debian" },
{ "opensuse", "OpenSUSE" },
{ "fedoracore", "Fedora" },
{ "gentoo", "Gentoo" },
{ "mandriva", "Mandriva" },
{ "redhat", "RedHat" },
{ "ubuntu", "Ubuntu" },
{ "xandros", "Xandros" },
{ "freebsd", "FreeBSD" },
{ "openbsd", "OpenBSD" },
{ "netbsd", "NetBSD" },
{ "netware", "Netware" },
{ "solaris", "Solaris" },
{ "opensolaris", "OpenSolaris" },
{ "l4", "L4" }
};
{
for (unsigned u = 0;
u < RT_ELEMENTS(aConvertOSTypes);
++u)
{
{
break;
}
}
}
/**
* Called from the constructor to actually read in the <Machine> element
* of a machine config file.
* @param elmMachine
*/
{
{
if (m->sv < SettingsVersion_v1_5)
fCurrentStateModified = true;
// constructor has called RTTimeNow(&timeLastStateChange) before
fAborted = true;
// parse Hardware before the other elements because other things depend on it
{
else if ( (m->sv < SettingsVersion_v1_7)
)
else if ( (m->sv >= SettingsVersion_v1_7)
)
{
if (uuidCurrentSnapshot.isZero())
throw ConfigFileError(this, &elmMachine, N_("Snapshots present but required Machine/@currentSnapshot attribute is missing"));
bool foundCurrentSnapshot = false;
// this will recurse into child snapshots, if necessary
if (!foundCurrentSnapshot)
throw ConfigFileError(this, &elmMachine, N_("Snapshots present but none matches the UUID in the Machine/@currentSnapshot attribute"));
}
{
{
if (strFaultToleranceSate == "master")
else
if (strFaultToleranceSate == "standby")
else
}
}
}
if (m->sv < SettingsVersion_v1_9)
// go through Hardware once more to repair the settings controller structures
// with data from old DVDDrive and FloppyDrive elements
}
else
throw ConfigFileError(this, &elmMachine, N_("Required Machine/@uuid or @name attributes is missing"));
}
/**
* Creates a <Hardware> node under elmParent and then writes out the XML
* keys under that. Called for both the <Machine> node and for snapshots.
* @param elmParent
* @param st
*/
{
if (m->sv >= SettingsVersion_v1_4)
if ((m->sv >= SettingsVersion_v1_9)
)
pelmCPU->createChild("LongMode")->setAttribute("enabled", hw.enmLongMode == Hardware::LongMode_Enabled);
if (hw.fSyntheticCpu)
if (hw.fTripleFaultReset)
/* Always save this setting as we have changed the default in 4.0 (on for large memory 64-bit systems). */
if (m->sv >= SettingsVersion_v1_9)
if (m->sv >= SettingsVersion_v1_10)
{
++it)
{
if (pelmCpuTree == NULL)
}
}
++it)
{
if (pelmCpuIdTree == NULL)
}
if (m->sv >= SettingsVersion_v1_10)
{
}
if ( (m->sv >= SettingsVersion_v1_9)
)
{
const char *pcszFirmware;
switch (hw.firmwareType)
{
default: pcszFirmware = "None"; break;
}
}
if ( (m->sv >= SettingsVersion_v1_10)
)
{
const char *pcszHID;
switch (hw.pointingHIDType)
{
}
switch (hw.keyboardHIDType)
{
}
}
if ( (m->sv >= SettingsVersion_v1_10)
)
{
}
if ( (m->sv >= SettingsVersion_v1_11)
)
{
const char *pcszChipset;
switch (hw.chipsetType)
{
}
}
++it)
{
const char *pcszDevice;
switch (type)
{
}
i + 1); // XML is 1-based but internal data is 0-based
}
{
const char *pcszGraphics;
switch (hw.graphicsControllerType)
{
}
}
if (m->sv >= SettingsVersion_v1_8)
if (m->sv >= SettingsVersion_v1_14)
{
}
if (m->sv < SettingsVersion_v1_11)
{
/* In VBox 4.0 these attributes are replaced with "Properties". */
strPort = "3389";
if (strAddress.length())
}
const char *pcszAuthType;
{
}
if (m->sv == SettingsVersion_v1_10)
{
/* In 4.0 videochannel settings were replaced with properties, so look at properties. */
uint32_t ulVideoChannelQuality = RTStrToUInt32(str.c_str()); /* This returns 0 on invalid string which is ok. */
if (ulVideoChannelQuality == 0)
ulVideoChannelQuality = 75;
else
}
if (m->sv >= SettingsVersion_v1_11)
{
{
++it)
{
}
}
}
const char *pcszBootMenu;
{
}
if (m->sv < SettingsVersion_v1_9)
{
// settings formats before 1.9 had separate DVDDrive and FloppyDrive items under Hardware;
// run thru the storage controllers to see if we have a DVD or floppy drives
++it)
{
// in old settings format, the DVD drive could only have been under the IDE controller
{
++it2)
{
{
if (cDVDs > 0)
throw ConfigFileError(this, NULL, N_("Internal error: cannot save more than one DVD drive with old settings format"));
++cDVDs;
if (att.fTempEject)
}
}
}
{
if (cFloppiesHere > 1)
throw ConfigFileError(this, NULL, N_("Internal error: floppy controller cannot have more than one device attachment"));
if (cFloppiesHere)
{
}
}
}
if (cFloppies == 0)
else if (cFloppies > 1)
throw ConfigFileError(this, NULL, N_("Internal error: cannot save more than one floppy drive with old settings format"));
}
if (m->sv < SettingsVersion_v1_14)
{
bool fOhciEnabled = false;
bool fEhciEnabled = false;
++it)
{
{
case USBControllerType_OHCI:
fOhciEnabled = true;
break;
case USBControllerType_EHCI:
fEhciEnabled = true;
break;
default:
}
}
}
else
{
++it)
{
{
case USBControllerType_OHCI:
strType = "OHCI";
break;
case USBControllerType_EHCI:
strType = "EHCI";
break;
case USBControllerType_XHCI:
strType = "XHCI";
break;
default:
}
}
}
++it)
{
if (nic.ulBootPriority != 0)
{
}
if (nic.fTraceEnabled)
{
}
const char *pszPolicy;
switch (nic.enmPromiscModePolicy)
{
}
if (pszPolicy)
const char *pcszType;
{
}
if (m->sv < SettingsVersion_v1_10)
{
{
break;
break;
break;
break;
default: /*case NetworkAttachmentType_Null:*/
break;
}
}
else
{
/* m->sv >= SettingsVersion_v1_10 */
}
}
++it)
{
const char *pcszHostMode;
{
}
{
case PortMode_HostPipe:
/* no break */
case PortMode_HostDevice:
case PortMode_RawFile:
break;
default:
break;
}
}
++it)
{
}
const char *pcszController;
{
case AudioControllerType_SB16:
pcszController = "SB16";
break;
case AudioControllerType_HDA:
if (m->sv >= SettingsVersion_v1_11)
{
pcszController = "HDA";
break;
}
/* fall through */
case AudioControllerType_AC97:
default:
pcszController = "AC97";
break;
}
if (m->sv >= SettingsVersion_v1_10)
{
}
const char *pcszDriver;
{
}
++it)
{
}
const char *pcszClip;
switch (hw.clipboardMode)
{
}
const char *pcszDragAndDrop;
switch (hw.dragAndDropMode)
{
}
if (m->sv >= SettingsVersion_v1_10)
{
if (m->sv >= SettingsVersion_v1_11)
{
++it)
{
const char *pcszType;
{
}
if (m->sv >= SettingsVersion_v1_13)
else
}
}
}
if (m->sv >= SettingsVersion_v1_12)
{
++it)
{
}
}
if (m->sv >= SettingsVersion_v1_12)
{
}
if ( m->sv >= SettingsVersion_v1_14
{
}
++it)
{
}
}
/**
* Fill a <Network> node. Only relevant for XML version >= v1_10.
* @param mode
* @param elmParent
* @param fEnabled
* @param nic
*/
bool fEnabled,
const NetworkAdapter &nic)
{
switch (mode)
{
{
}
break;
break;
break;
break;
{
++it)
{
}
}
break;
break;
default: /*case NetworkAttachmentType_Null:*/
break;
}
}
/**
* Creates a <StorageControllers> node under elmParent and then writes out the XML
* keys under that. Called for both the <Machine> node and for snapshots.
* @param elmParent
* @param st
* @param fSkipRemovableMedia If true, DVD and floppy attachments are skipped and
* an empty drive is always written instead. This is for the OVF export case.
* This parameter is ignored unless the settings version is at least v1.9, which
* is always the case when this gets called for OVF export.
* @param pllElementsWithUuidAttributes If not NULL, must point to a list of element node
* pointers to which we will append all elements that we created here that contain
* UUID attributes. This allows the OVF export code to quickly replace the internal
* media UUIDs with the UUIDs of the media that were exported.
*/
bool fSkipRemovableMedia,
{
++it)
{
if ( (m->sv < SettingsVersion_v1_9)
)
// floppy controller already got written into <Hardware>/<FloppyController> in buildHardwareXML()
// for pre-1.9 settings
continue;
if (m->sv < SettingsVersion_v1_8)
{
// pre-1.8 settings use shorter controller names, they are
// expanded when reading the settings
if (name == "IDE Controller")
name = "IDE";
else if (name == "SATA Controller")
name = "SATA";
else if (name == "SCSI Controller")
name = "SCSI";
}
const char *pcszType;
switch (sc.controllerType)
{
}
if (m->sv >= SettingsVersion_v1_9)
if (sc.ulInstance)
if (m->sv >= SettingsVersion_v1_10)
if (m->sv >= SettingsVersion_v1_11)
{
}
++it2)
{
// For settings version before 1.9, DVDs and floppies are in hardware, not storage controllers,
// so we shouldn't write them here; we only get here for DVDs though because we ruled out
// the floppy controller at the top of the loop
&& m->sv < SettingsVersion_v1_9
)
continue;
switch (att.deviceType)
{
case DeviceType_HardDisk:
pcszType = "HardDisk";
if (att.fNonRotational)
break;
case DeviceType_DVD:
pcszType = "DVD";
if (att.fTempEject)
break;
case DeviceType_Floppy:
pcszType = "Floppy";
break;
}
if (m->sv >= SettingsVersion_v1_15)
// attached image, if any
)
)
{
// if caller wants a list of UUID elements, give it to them
}
else if ( (m->sv >= SettingsVersion_v1_9)
)
}
}
}
/**
* Creates a <Debugging> node under elmParent and then writes out the XML
* keys under that. Called for both the <Machine> node and for snapshots.
*
* @param pElmParent Pointer to the parent element.
* @param pDbg Pointer to the debugging settings.
*/
{
return;
}
/**
* Creates a <Autostart> node under elmParent and then writes out the XML
* keys under that. Called for both the <Machine> node and for snapshots.
*
* @param pElmParent Pointer to the parent element.
* @param pAutostart Pointer to the autostart settings.
*/
void MachineConfigFile::buildAutostartXML(xml::ElementNode *pElmParent, const Autostart *pAutostart)
{
const char *pcszAutostop = NULL;
return;
switch (pAutostart->enmAutostopType)
{
}
}
/**
* Creates a <Groups> node under elmParent and then writes out the XML
* keys under that. Called for the <Machine> node only.
*
* @param pElmParent Pointer to the parent element.
* @param pllGroups Pointer to the groups list.
*/
{
return;
++it)
{
}
}
/**
* Writes a single snapshot into the DOM tree. Initially this gets called from MachineConfigFile::write()
* for the root snapshot of a machine, if present; elmParent then points to the <Snapshots> node under the
* <Machine> node to which <Snapshot> must be added. This may then recurse for child snapshots.
*
* @param depth
* @param elmParent
* @param snap
*/
{
if (depth > SETTINGS_SNAPSHOT_DEPTH_MAX)
throw ConfigFileError(this, NULL, N_("Maximum snapshot tree depth of %u exceeded"), SETTINGS_SNAPSHOT_DEPTH_MAX);
false /* fSkipRemovableMedia */,
NULL); /* pllElementsWithUuidAttributes */
// we only skip removable media for OVF, but we never get here for OVF
// since snapshots never get written then
// note: Groups exist only for Machine, not for Snapshot
{
++it)
{
}
}
}
/**
* Builds the XML DOM tree for the machine config under the given XML element.
*
* This has been separated out from write() so it can be called from elsewhere,
* such as the OVF code, to build machine XML in an existing XML tree.
*
* As a result, this gets called from two locations:
*
* -- MachineConfigFile::write();
*
* -- Appliance::buildXMLForOneVirtualSystem()
*
* In fl, the following flag bits are recognized:
*
* -- BuildMachineXML_MediaRegistry: If set, the machine's media registry will
* be written, if present. This is not set when called from OVF because OVF
* has its own variant of a media registry. This flag is ignored unless the
* settings version is at least v1.11 (VirtualBox 4.0).
*
* -- BuildMachineXML_IncludeSnapshots: If set, descend into the snapshots tree
* of the machine and write out <Snapshot> and possibly more snapshots under
* that, if snapshots are present. Otherwise all snapshots are suppressed
* (when called from OVF).
*
* -- BuildMachineXML_WriteVBoxVersionAttribute: If set, add a settingsVersion
* attribute to the machine tag with the vbox settings version. This is for
* the OVF export case in which we don't have the settings version set in
* the root element.
*
* -- BuildMachineXML_SkipRemovableMedia: If set, removable media attachments
* (DVDs, floppies) are silently skipped. This is for the OVF export case
* until we support copying ISO and RAW media as well. This flag is ignored
* unless the settings version is at least v1.9, which is always the case
* when this gets called for OVF export.
*
* -- BuildMachineXML_SuppressSavedState: If set, the Machine/@stateFile
* attribute is never set. This is also for the OVF export case because we
* cannot save states with OVF.
*
* @param elmMachine XML <Machine> element to add attributes and elements to.
* @param fl Flags.
* @param pllElementsWithUuidAttributes pointer to list that should receive UUID elements or NULL;
* see buildStorageControllersXML() for details.
*/
{
// add settings version attribute to machine element
if (!machineUserData.fNameSync)
if ( strStateFile.length()
&& !(fl & BuildMachineXML_SuppressSavedState)
)
if ((fl & BuildMachineXML_IncludeSnapshots)
&& !uuidCurrentSnapshot.isZero()
&& uuidCurrentSnapshot.isValid())
if (!fCurrentStateModified)
if (fAborted)
// Please keep the icon last so that one doesn't have to check if there
// is anything in the line after this very long attribute in the XML.
if ( m->sv >= SettingsVersion_v1_9
)
)
{
}
if ( m->sv >= SettingsVersion_v1_11
)
)
{
switch (machineUserData.enmFaultToleranceState)
{
break;
break;
break;
}
}
if ( (fl & BuildMachineXML_MediaRegistry)
&& (m->sv >= SettingsVersion_v1_11)
)
if ( (fl & BuildMachineXML_IncludeSnapshots)
&& llFirstSnapshot.size())
}
/**
* Returns true only if the given AudioDriverType is supported on
* the current host platform. For example, this would return false
* for AudioDriverType_DirectSound when compiled on a Linux host.
* @param drv AudioDriverType_* enum to test.
* @return true only if the current host supports that driver.
*/
/*static*/
{
switch (drv)
{
case AudioDriverType_Null:
#ifdef RT_OS_WINDOWS
# ifdef VBOX_WITH_WINMM
case AudioDriverType_WinMM:
# endif
#endif /* RT_OS_WINDOWS */
#ifdef RT_OS_SOLARIS
case AudioDriverType_SolAudio:
#endif
#ifdef RT_OS_LINUX
# ifdef VBOX_WITH_ALSA
case AudioDriverType_ALSA:
# endif
# ifdef VBOX_WITH_PULSE
case AudioDriverType_Pulse:
# endif
#endif /* RT_OS_LINUX */
case AudioDriverType_OSS:
#endif
#ifdef RT_OS_FREEBSD
# ifdef VBOX_WITH_PULSE
case AudioDriverType_Pulse:
# endif
#endif
#ifdef RT_OS_DARWIN
#endif
#ifdef RT_OS_OS2
case AudioDriverType_MMPM:
#endif
return true;
}
return false;
}
/**
* Returns the AudioDriverType_* which should be used by default on this
* host platform. On Linux, this will check at runtime whether PulseAudio
* or ALSA are actually supported on the first call.
* @return
*/
/*static*/
{
#if defined(RT_OS_WINDOWS)
# ifdef VBOX_WITH_WINMM
return AudioDriverType_WinMM;
# else /* VBOX_WITH_WINMM */
return AudioDriverType_DirectSound;
# endif /* !VBOX_WITH_WINMM */
#elif defined(RT_OS_SOLARIS)
return AudioDriverType_SolAudio;
#elif defined(RT_OS_LINUX)
// on Linux, we need to check at runtime what's actually supported...
static RTCLockMtx s_mtx;
{
# if defined(VBOX_WITH_PULSE)
/* Check for the pulse library & that the pulse audio daemon is running. */
if (RTProcIsRunningByName("pulseaudio") &&
RTLdrIsLoadable("libpulse.so.0"))
else
# endif /* VBOX_WITH_PULSE */
# if defined(VBOX_WITH_ALSA)
/* Check if we can load the ALSA library */
if (RTLdrIsLoadable("libasound.so.2"))
else
# endif /* VBOX_WITH_ALSA */
}
return s_linuxDriver;
// end elif defined(RT_OS_LINUX)
#elif defined(RT_OS_DARWIN)
return AudioDriverType_CoreAudio;
return AudioDriverType_MMPM;
#elif defined(RT_OS_FREEBSD)
return AudioDriverType_OSS;
#else
return AudioDriverType_Null;
#endif
}
/**
* Called from write() before calling ConfigFileBase::createStubDocument().
* This adjusts the settings version in m->sv if incompatible settings require
* a settings bump, whereas otherwise we try to preserve the settings version
* to avoid breaking compatibility with older versions.
*
* We do the checks in here in reverse order: newest first, oldest last, so
* that we avoid unnecessary checks since some of these are expensive.
*/
{
if (m->sv < SettingsVersion_v1_15)
{
/*
* Check whether the hotpluggable flag of all storage devices differs
* from the default for old settings.
* AHCI ports are hotpluggable by default every other device is not.
*/
++it)
{
bool fSettingsBumped = false;
++it2)
{
if ( ( att.fHotPluggable
|| ( !att.fHotPluggable
{
m->sv = SettingsVersion_v1_15;
fSettingsBumped = true;
break;
}
}
/* Abort early if possible. */
if (fSettingsBumped)
break;
}
}
if (m->sv < SettingsVersion_v1_14)
{
// VirtualBox 4.3 adds default frontend setting, graphics controller
// setting, explicit long mode setting, video capturing and NAT networking.
{
m->sv = SettingsVersion_v1_14;
return;
}
++netit)
{
{
m->sv = SettingsVersion_v1_14;
break;
}
}
}
if (m->sv < SettingsVersion_v1_14)
{
unsigned cOhciCtrls = 0;
unsigned cEhciCtrls = 0;
bool fNonStdName = false;
++it)
{
{
case USBControllerType_OHCI:
cOhciCtrls++;
fNonStdName = true;
break;
case USBControllerType_EHCI:
cEhciCtrls++;
fNonStdName = true;
break;
default:
}
/* Skip checking other controllers if the settings bump is necessary. */
{
m->sv = SettingsVersion_v1_14;
break;
}
}
}
if (m->sv < SettingsVersion_v1_13)
{
// VirtualBox 4.2 adds tracing, autostart, UUID in directory and groups.
if ( !debugging.areDefaultSettings()
|| !autostart.areDefaultSettings()
m->sv = SettingsVersion_v1_13;
}
if (m->sv < SettingsVersion_v1_13)
{
// VirtualBox 4.2 changes the units for bandwidth group limits.
++it)
{
{
// Bump version if a limit cannot be expressed in megabytes
m->sv = SettingsVersion_v1_13;
break;
}
}
}
if (m->sv < SettingsVersion_v1_12)
{
// VirtualBox 4.1 adds PCI passthrough and emulated USB Smart Card reader
m->sv = SettingsVersion_v1_12;
}
if (m->sv < SettingsVersion_v1_12)
{
// VirtualBox 4.1 adds a promiscuous mode policy to the network
// adapters and a generic network driver transport.
++netit)
{
)
{
m->sv = SettingsVersion_v1_12;
break;
}
}
}
if (m->sv < SettingsVersion_v1_11)
{
// VirtualBox 4.0 adds HD audio, CPU priorities, fault tolerance,
// per-machine media registries, VRDE, JRockitVE, bandwidth groups,
// ICH9 chipset
)
m->sv = SettingsVersion_v1_11;
}
if (m->sv < SettingsVersion_v1_10)
{
* then increase the version to at least VBox 3.2, which can have video channel properties.
*/
unsigned cOldProperties = 0;
m->sv = SettingsVersion_v1_10;
}
if (m->sv < SettingsVersion_v1_11)
{
* "VideoChannel/Enabled" and "VideoChannel/Quality" then increase the version to VBox 4.0.
*/
unsigned cOldProperties = 0;
m->sv = SettingsVersion_v1_11;
}
// settings version 1.9 is required if there is not exactly one DVD
// or more than one floppy drive present or the DVD is not at the secondary
// master; this check is a bit more complicated
//
// settings version 1.10 is required if the host cache should be disabled
//
// settings version 1.11 is required for bandwidth limits and if more than
// one controller of each type is present.
if (m->sv < SettingsVersion_v1_11)
{
// count attached DVDs and floppies (only if < v1.9)
// count storage controllers (if < v1.11)
size_t cScsiBuslogic = 0;
// need to run thru all the storage controllers and attached devices to figure this out
++it)
{
// count storage controllers of each type; 1.11 is required if more than one
// controller of one type is present
switch (sctl.storageBus)
{
case StorageBus_IDE:
cIde++;
break;
case StorageBus_SATA:
cSata++;
break;
case StorageBus_SAS:
cSas++;
break;
case StorageBus_SCSI:
cScsiLsi++;
else
break;
case StorageBus_Floppy:
cFloppy++;
break;
default:
// Do nothing
break;
}
if ( cSata > 1
|| cScsiLsi > 1
|| cScsiBuslogic > 1
|| cSas > 1
|| cIde > 1
|| cFloppy > 1)
{
m->sv = SettingsVersion_v1_11;
break; // abort the loop -- we will not raise the version further
}
++it2)
{
// Bandwidth limitations are new in VirtualBox 4.0 (1.11)
if (m->sv < SettingsVersion_v1_11)
{
{
m->sv = SettingsVersion_v1_11;
break; // abort the loop -- we will not raise the version further
}
}
// disabling the host IO cache requires settings version 1.10
if ( (m->sv < SettingsVersion_v1_10)
&& (!sctl.fUseHostIOCache)
)
m->sv = SettingsVersion_v1_10;
// we can only write the StorageController/@Instance attribute with v1.9
if ( (m->sv < SettingsVersion_v1_9)
&& (sctl.ulInstance != 0)
)
m->sv = SettingsVersion_v1_9;
if (m->sv < SettingsVersion_v1_9)
{
{
)
m->sv = SettingsVersion_v1_9;
++cDVDs;
}
++cFloppies;
}
}
if (m->sv >= SettingsVersion_v1_11)
break; // abort the loop -- we will not raise the version further
}
// VirtualBox before 3.1 had zero or one floppy and exactly one DVD,
// so any deviation from that will require settings version 1.9
if ( (m->sv < SettingsVersion_v1_9)
&& ( (cDVDs != 1)
|| (cFloppies > 1)
)
)
m->sv = SettingsVersion_v1_9;
}
// VirtualBox 3.2: Check for non default I/O settings
if (m->sv < SettingsVersion_v1_10)
{
// and page fusion
// and CPU hotplug, RTC timezone control, HID type and HPET
)
m->sv = SettingsVersion_v1_10;
}
// VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main
// VirtualBox 4.0 adds network bandwitdth
if (m->sv < SettingsVersion_v1_11)
{
++netit)
{
if ( (m->sv < SettingsVersion_v1_12)
)
{
/* New in VirtualBox 4.1 */
m->sv = SettingsVersion_v1_12;
break;
}
else if ( (m->sv < SettingsVersion_v1_10)
)
)
{
m->sv = SettingsVersion_v1_10;
// no break because we still might need v1.11 above
}
else if ( (m->sv < SettingsVersion_v1_10)
&& (netit->ulBootPriority != 0)
)
{
m->sv = SettingsVersion_v1_10;
// no break because we still might need v1.11 above
}
}
}
// all the following require settings version 1.9
if ( (m->sv < SettingsVersion_v1_9)
)
)
m->sv = SettingsVersion_v1_9;
// "accelerate 2d video" requires settings version 1.8
if ( (m->sv < SettingsVersion_v1_8)
)
m->sv = SettingsVersion_v1_8;
// The hardware versions other than "1" requires settings version 1.4 (2.1+).
if ( m->sv < SettingsVersion_v1_4
)
m->sv = SettingsVersion_v1_4;
}
/**
* Called from Main code to write a machine config file to disk. This builds a DOM tree from
* the member variables and then writes the XML file; it throws xml::Error instances on errors,
* in particular if the file cannot be written.
*/
{
try
{
// createStubDocument() sets the settings version to at least 1.7; however,
// we might need to enfore a later settings version if incompatible settings
// are present:
m->strFilename = strFilename;
// but not BuildMachineXML_WriteVBoxVersionAttribute
NULL); /* pllElementsWithUuidAttributes */
// now go write the XML
m->fFileExists = true;
}
catch (...)
{
throw;
}
}