~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/xml/Settings.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: Settings.cpp $ */
 
1
/* $Id: Settings.cpp 35151 2010-12-15 16:42:08Z vboxsync $ */
2
2
/** @file
3
3
 * Settings File Manipulation API.
4
4
 *
8
8
 *
9
9
 * The code can read all VirtualBox settings files version 1.3 and higher. That version was
10
10
 * written by VirtualBox 2.0. It can write settings version 1.7 (used by VirtualBox 2.2 and
11
 
 * 3.0) and 1.9 (used by VirtualBox 3.1).
12
 
 *
13
 
 * Rules for introducing new settings: If an element or attribute is introduced that was not
14
 
 * present before VirtualBox 3.1, then settings version checks need to be introduced. The
15
 
 * settings version for VirtualBox 3.1 is 1.9; see the SettingsVersion enumeration in
16
 
 * src/VBox/Main/idl/VirtualBox.xidl for details about which version was used when.
17
 
 *
18
 
 * The settings versions checks are necessary because VirtualBox 3.1 no longer automatically
19
 
 * converts XML settings files but only if necessary, that is, if settings are present that
20
 
 * the old format does not support. If we write an element or attribute to a settings file
21
 
 * of an older version, then an old VirtualBox (before 3.1) will attempt to validate it
22
 
 * with XML schema, and that will certainly fail.
 
11
 * 3.0) and 1.9 (used by VirtualBox 3.1) and newer ones obviously.
 
12
 *
 
13
 * The settings versions enum is defined in src/VBox/Main/idl/VirtualBox.xidl. To introduce
 
14
 * a new settings version (should be necessary at most once per VirtualBox major release,
 
15
 * if at all), add a new SettingsVersion value to that enum and grep for the previously
 
16
 * highest value to see which code in here needs adjusting.
 
17
 *
 
18
 * Certainly ConfigFileBase::ConfigFileBase() will. Change VBOX_XML_VERSION below as well.
 
19
 *
 
20
 * Once a new settings version has been added, these are the rules for introducing a new
 
21
 * setting: If an XML element or attribute or value is introduced that was not present in
 
22
 * previous versions, then settings version checks need to be introduced. See the
 
23
 * SettingsVersion enumeration in src/VBox/Main/idl/VirtualBox.xidl for details about which
 
24
 * version was used when.
 
25
 *
 
26
 * The settings versions checks are necessary because since version 3.1, VirtualBox no longer
 
27
 * automatically converts XML settings files but only if necessary, that is, if settings are
 
28
 * present that the old format does not support. If we write an element or attribute to a
 
29
 * settings file of an older version, then an old VirtualBox (before 3.1) will attempt to
 
30
 * validate it with XML schema, and that will certainly fail.
23
31
 *
24
32
 * So, to introduce a new setting:
25
33
 *
26
34
 *   1) Make sure the constructor of corresponding settings structure has a proper default.
27
35
 *
28
36
 *   2) In the settings reader method, try to read the setting; if it's there, great, if not,
29
 
 *      the default value will have been set by the constructor.
30
 
 *
31
 
 *   3) In the settings writer method, write the setting _only_ if the current settings
32
 
 *      version (stored in m->sv) is high enough. That is, for VirtualBox 3.2, write it
33
 
 *      only if (m->sv >= SettingsVersion_v1_10).
34
 
 *
35
 
 *   4) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has
 
37
 *      the default value will have been set by the constructor. The rule is to be tolerant
 
38
 *      here.
 
39
 *
 
40
 *   3) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has
36
41
 *      a non-default value (i.e. that differs from the constructor). If so, bump the
37
 
 *      settings version to the current version so the settings writer (3) can write out
 
42
 *      settings version to the current version so the settings writer (4) can write out
38
43
 *      the non-default value properly.
39
44
 *
40
45
 *      So far a corresponding method for MainConfigFile has not been necessary since there
41
46
 *      have been no incompatible changes yet.
 
47
 *
 
48
 *   4) In the settings writer method, write the setting _only_ if the current settings
 
49
 *      version (stored in m->sv) is high enough. That is, for VirtualBox 4.0, write it
 
50
 *      only if (m->sv >= SettingsVersion_v1_11).
42
51
 */
43
52
 
44
53
/*
81
90
#define VBOX_XML_NAMESPACE      "http://www.innotek.de/VirtualBox-settings"
82
91
 
83
92
/** VirtualBox XML settings version number substring ("x.y")  */
84
 
#define VBOX_XML_VERSION        "1.10"
 
93
#define VBOX_XML_VERSION        "1.11"
85
94
 
86
95
/** VirtualBox XML settings version platform substring */
87
96
#if defined (RT_OS_DARWIN)
179
188
    {
180
189
        va_list args;
181
190
        va_start(args, pcszFormat);
182
 
        Utf8StrFmtVA strWhat(pcszFormat, args);
 
191
        Utf8Str strWhat(pcszFormat, args);
183
192
        va_end(args);
184
193
 
185
194
        Utf8Str strLine;
198
207
 
199
208
////////////////////////////////////////////////////////////////////////////////
200
209
//
 
210
// MediaRegistry
 
211
//
 
212
////////////////////////////////////////////////////////////////////////////////
 
213
 
 
214
bool Medium::operator==(const Medium &m) const
 
215
{
 
216
    return    (uuid == m.uuid)
 
217
           && (strLocation == m.strLocation)
 
218
           && (strDescription == m.strDescription)
 
219
           && (strFormat == m.strFormat)
 
220
           && (fAutoReset == m.fAutoReset)
 
221
           && (properties == m.properties)
 
222
           && (hdType == m.hdType)
 
223
           && (llChildren== m.llChildren);         // this is deep and recurses
 
224
}
 
225
 
 
226
bool MediaRegistry::operator==(const MediaRegistry &m) const
 
227
{
 
228
    return    llHardDisks == m.llHardDisks
 
229
           && llDvdImages == m.llDvdImages
 
230
           && llFloppyImages == m.llFloppyImages;
 
231
}
 
232
 
 
233
////////////////////////////////////////////////////////////////////////////////
 
234
//
201
235
// ConfigFileBase
202
236
//
203
237
////////////////////////////////////////////////////////////////////////////////
204
238
 
205
239
/**
206
 
 * Constructor. Allocates the XML internals.
 
240
 * Constructor. Allocates the XML internals, parses the XML file if
 
241
 * pstrFilename is != NULL and reads the settings version from it.
207
242
 * @param strFilename
208
243
 */
209
244
ConfigFileBase::ConfigFileBase(const com::Utf8Str *pstrFilename)
282
317
                    m->sv = SettingsVersion_v1_9;
283
318
                else if (ulMinor == 10)
284
319
                    m->sv = SettingsVersion_v1_10;
285
 
                else if (ulMinor > 10)
 
320
                else if (ulMinor == 11)
 
321
                    m->sv = SettingsVersion_v1_11;
 
322
                else if (ulMinor > 11)
286
323
                    m->sv = SettingsVersion_Future;
287
324
            }
288
325
            else if (ulMajor > 1)
302
339
    {
303
340
        // creating new settings file:
304
341
        m->strSettingsVersionFull = VBOX_XML_VERSION_FULL;
305
 
        m->sv = SettingsVersion_v1_10;
 
342
        m->sv = SettingsVersion_v1_11;
306
343
    }
307
344
}
308
345
 
320
357
 
321
358
/**
322
359
 * Helper function that parses a UUID in string form into
323
 
 * a com::Guid item. Since that uses an IPRT function which
324
 
 * does not accept "{}" characters around the UUID string,
325
 
 * we handle that here. Throws on errors.
 
360
 * a com::Guid item. Accepts UUIDs both with and without
 
361
 * "{}" brackets. Throws on errors.
326
362
 * @param guid
327
363
 * @param strUUID
328
364
 */
329
365
void ConfigFileBase::parseUUID(Guid &guid,
330
366
                               const Utf8Str &strUUID) const
331
367
{
332
 
    // {5f102a55-a51b-48e3-b45a-b28d33469488}
333
 
    // 01234567890123456789012345678901234567
334
 
    //           1         2         3
335
 
    if (    (strUUID[0] == '{')
336
 
         && (strUUID[37] == '}')
337
 
       )
338
 
        guid = strUUID.substr(1, 36).c_str();
339
 
    else
340
 
        guid = strUUID.c_str();
341
 
 
 
368
    guid = strUUID.c_str();
342
369
    if (guid.isEmpty())
343
370
        throw ConfigFileError(this, NULL, N_("UUID \"%s\" has invalid format"), strUUID.c_str());
344
371
}
439
466
 * @param map
440
467
 */
441
468
void ConfigFileBase::readExtraData(const xml::ElementNode &elmExtraData,
442
 
                                   ExtraDataItemsMap &map)
 
469
                                   StringsMap &map)
443
470
{
444
471
    xml::NodesLoop nlLevel4(elmExtraData);
445
472
    const xml::ElementNode *pelmExtraDataItem;
513
540
}
514
541
 
515
542
/**
 
543
 * Reads a media registry entry from the main VirtualBox.xml file.
 
544
 *
 
545
 * Whereas the current media registry code is fairly straightforward, it was quite a mess
 
546
 * with settings format before 1.4 (VirtualBox 2.0 used settings format 1.3). The elements
 
547
 * in the media registry were much more inconsistent, and different elements were used
 
548
 * depending on the type of device and image.
 
549
 *
 
550
 * @param t
 
551
 * @param elmMedium
 
552
 * @param llMedia
 
553
 */
 
554
void ConfigFileBase::readMedium(MediaType t,
 
555
                                const xml::ElementNode &elmMedium,  // HardDisk node if root; if recursing,
 
556
                                                                    // child HardDisk node or DiffHardDisk node for pre-1.4
 
557
                                MediaList &llMedia)     // list to append medium to (root disk or child list)
 
558
{
 
559
    // <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
 
560
    settings::Medium med;
 
561
    Utf8Str strUUID;
 
562
    if (!(elmMedium.getAttributeValue("uuid", strUUID)))
 
563
        throw ConfigFileError(this, &elmMedium, N_("Required %s/@uuid attribute is missing"), elmMedium.getName());
 
564
 
 
565
    parseUUID(med.uuid, strUUID);
 
566
 
 
567
    bool fNeedsLocation = true;
 
568
 
 
569
    if (t == HardDisk)
 
570
    {
 
571
        if (m->sv < SettingsVersion_v1_4)
 
572
        {
 
573
            // here the system is:
 
574
            //         <HardDisk uuid="{....}" type="normal">
 
575
            //           <VirtualDiskImage filePath="/path/to/xxx.vdi"/>
 
576
            //         </HardDisk>
 
577
 
 
578
            fNeedsLocation = false;
 
579
            bool fNeedsFilePath = true;
 
580
            const xml::ElementNode *pelmImage;
 
581
            if ((pelmImage = elmMedium.findChildElement("VirtualDiskImage")))
 
582
                med.strFormat = "VDI";
 
583
            else if ((pelmImage = elmMedium.findChildElement("VMDKImage")))
 
584
                med.strFormat = "VMDK";
 
585
            else if ((pelmImage = elmMedium.findChildElement("VHDImage")))
 
586
                med.strFormat = "VHD";
 
587
            else if ((pelmImage = elmMedium.findChildElement("ISCSIHardDisk")))
 
588
            {
 
589
                med.strFormat = "iSCSI";
 
590
 
 
591
                fNeedsFilePath = false;
 
592
                // location is special here: current settings specify an "iscsi://user@server:port/target/lun"
 
593
                // string for the location and also have several disk properties for these, whereas this used
 
594
                // to be hidden in several sub-elements before 1.4, so compose a location string and set up
 
595
                // the properties:
 
596
                med.strLocation = "iscsi://";
 
597
                Utf8Str strUser, strServer, strPort, strTarget, strLun;
 
598
                if (pelmImage->getAttributeValue("userName", strUser))
 
599
                {
 
600
                    med.strLocation.append(strUser);
 
601
                    med.strLocation.append("@");
 
602
                }
 
603
                Utf8Str strServerAndPort;
 
604
                if (pelmImage->getAttributeValue("server", strServer))
 
605
                {
 
606
                    strServerAndPort = strServer;
 
607
                }
 
608
                if (pelmImage->getAttributeValue("port", strPort))
 
609
                {
 
610
                    if (strServerAndPort.length())
 
611
                        strServerAndPort.append(":");
 
612
                    strServerAndPort.append(strPort);
 
613
                }
 
614
                med.strLocation.append(strServerAndPort);
 
615
                if (pelmImage->getAttributeValue("target", strTarget))
 
616
                {
 
617
                    med.strLocation.append("/");
 
618
                    med.strLocation.append(strTarget);
 
619
                }
 
620
                if (pelmImage->getAttributeValue("lun", strLun))
 
621
                {
 
622
                    med.strLocation.append("/");
 
623
                    med.strLocation.append(strLun);
 
624
                }
 
625
 
 
626
                if (strServer.length() && strPort.length())
 
627
                    med.properties["TargetAddress"] = strServerAndPort;
 
628
                if (strTarget.length())
 
629
                    med.properties["TargetName"] = strTarget;
 
630
                if (strUser.length())
 
631
                    med.properties["InitiatorUsername"] = strUser;
 
632
                Utf8Str strPassword;
 
633
                if (pelmImage->getAttributeValue("password", strPassword))
 
634
                    med.properties["InitiatorSecret"] = strPassword;
 
635
                if (strLun.length())
 
636
                    med.properties["LUN"] = strLun;
 
637
            }
 
638
            else if ((pelmImage = elmMedium.findChildElement("CustomHardDisk")))
 
639
            {
 
640
                fNeedsFilePath = false;
 
641
                fNeedsLocation = true;
 
642
                    // also requires @format attribute, which will be queried below
 
643
            }
 
644
            else
 
645
                throw ConfigFileError(this, &elmMedium, N_("Required %s/VirtualDiskImage element is missing"), elmMedium.getName());
 
646
 
 
647
            if (fNeedsFilePath)
 
648
            {
 
649
                if (!(pelmImage->getAttributeValuePath("filePath", med.strLocation)))
 
650
                    throw ConfigFileError(this, &elmMedium, N_("Required %s/@filePath attribute is missing"), elmMedium.getName());
 
651
            }
 
652
        }
 
653
 
 
654
        if (med.strFormat.isEmpty())        // not set with 1.4 format above, or 1.4 Custom format?
 
655
            if (!(elmMedium.getAttributeValue("format", med.strFormat)))
 
656
                throw ConfigFileError(this, &elmMedium, N_("Required %s/@format attribute is missing"), elmMedium.getName());
 
657
 
 
658
        if (!(elmMedium.getAttributeValue("autoReset", med.fAutoReset)))
 
659
            med.fAutoReset = false;
 
660
 
 
661
        Utf8Str strType;
 
662
        if ((elmMedium.getAttributeValue("type", strType)))
 
663
        {
 
664
            // pre-1.4 used lower case, so make this case-insensitive
 
665
            strType.toUpper();
 
666
            if (strType == "NORMAL")
 
667
                med.hdType = MediumType_Normal;
 
668
            else if (strType == "IMMUTABLE")
 
669
                med.hdType = MediumType_Immutable;
 
670
            else if (strType == "WRITETHROUGH")
 
671
                med.hdType = MediumType_Writethrough;
 
672
            else if (strType == "SHAREABLE")
 
673
                med.hdType = MediumType_Shareable;
 
674
            else if (strType == "READONLY")
 
675
                med.hdType = MediumType_Readonly;
 
676
            else if (strType == "MULTIATTACH")
 
677
                med.hdType = MediumType_MultiAttach;
 
678
            else
 
679
                throw ConfigFileError(this, &elmMedium, N_("HardDisk/@type attribute must be one of Normal, Immutable, Writethrough, Shareable, Readonly or MultiAttach"));
 
680
        }
 
681
    }
 
682
    else
 
683
    {
 
684
        if (m->sv < SettingsVersion_v1_4)
 
685
        {
 
686
            // DVD and floppy images before 1.4 had "src" attribute instead of "location"
 
687
            if (!(elmMedium.getAttributeValue("src", med.strLocation)))
 
688
                throw ConfigFileError(this, &elmMedium, N_("Required %s/@src attribute is missing"), elmMedium.getName());
 
689
 
 
690
            fNeedsLocation = false;
 
691
        }
 
692
 
 
693
        if (!(elmMedium.getAttributeValue("format", med.strFormat)))
 
694
        {
 
695
            // DVD and floppy images before 1.11 had no format attribute. assign the default.
 
696
            med.strFormat = "RAW";
 
697
        }
 
698
    }
 
699
 
 
700
    if (fNeedsLocation)
 
701
        // current files and 1.4 CustomHardDisk elements must have a location attribute
 
702
        if (!(elmMedium.getAttributeValue("location", med.strLocation)))
 
703
            throw ConfigFileError(this, &elmMedium, N_("Required %s/@location attribute is missing"), elmMedium.getName());
 
704
 
 
705
    elmMedium.getAttributeValue("Description", med.strDescription);       // optional
 
706
 
 
707
    // recurse to handle children
 
708
    xml::NodesLoop nl2(elmMedium);
 
709
    const xml::ElementNode *pelmHDChild;
 
710
    while ((pelmHDChild = nl2.forAllNodes()))
 
711
    {
 
712
        if (    t == HardDisk
 
713
             && (    pelmHDChild->nameEquals("HardDisk")
 
714
                  || (    (m->sv < SettingsVersion_v1_4)
 
715
                       && (pelmHDChild->nameEquals("DiffHardDisk"))
 
716
                     )
 
717
                )
 
718
           )
 
719
            // recurse with this element and push the child onto our current children list
 
720
            readMedium(t,
 
721
                        *pelmHDChild,
 
722
                        med.llChildren);
 
723
        else if (pelmHDChild->nameEquals("Property"))
 
724
        {
 
725
            Utf8Str strPropName, strPropValue;
 
726
            if (    (pelmHDChild->getAttributeValue("name", strPropName))
 
727
                 && (pelmHDChild->getAttributeValue("value", strPropValue))
 
728
               )
 
729
                med.properties[strPropName] = strPropValue;
 
730
            else
 
731
                throw ConfigFileError(this, pelmHDChild, N_("Required HardDisk/Property/@name or @value attribute is missing"));
 
732
        }
 
733
    }
 
734
 
 
735
    llMedia.push_back(med);
 
736
}
 
737
 
 
738
/**
 
739
 * Reads in the entire <MediaRegistry> chunk and stores its media in the lists
 
740
 * of the given MediaRegistry structure.
 
741
 *
 
742
 * This is used in both MainConfigFile and MachineConfigFile since starting with
 
743
 * VirtualBox 4.0, we can have media registries in both.
 
744
 *
 
745
 * For pre-1.4 files, this gets called with the <DiskRegistry> chunk instead.
 
746
 *
 
747
 * @param elmMediaRegistry
 
748
 */
 
749
void ConfigFileBase::readMediaRegistry(const xml::ElementNode &elmMediaRegistry,
 
750
                                       MediaRegistry &mr)
 
751
{
 
752
    xml::NodesLoop nl1(elmMediaRegistry);
 
753
    const xml::ElementNode *pelmChild1;
 
754
    while ((pelmChild1 = nl1.forAllNodes()))
 
755
    {
 
756
        MediaType t = Error;
 
757
        if (pelmChild1->nameEquals("HardDisks"))
 
758
            t = HardDisk;
 
759
        else if (pelmChild1->nameEquals("DVDImages"))
 
760
            t = DVDImage;
 
761
        else if (pelmChild1->nameEquals("FloppyImages"))
 
762
            t = FloppyImage;
 
763
        else
 
764
            continue;
 
765
 
 
766
        xml::NodesLoop nl2(*pelmChild1);
 
767
        const xml::ElementNode *pelmMedium;
 
768
        while ((pelmMedium = nl2.forAllNodes()))
 
769
        {
 
770
            if (    t == HardDisk
 
771
                 && (pelmMedium->nameEquals("HardDisk"))
 
772
               )
 
773
                readMedium(t,
 
774
                           *pelmMedium,
 
775
                           mr.llHardDisks);      // list to append hard disk data to: the root list
 
776
            else if (    t == DVDImage
 
777
                      && (pelmMedium->nameEquals("Image"))
 
778
                    )
 
779
                readMedium(t,
 
780
                           *pelmMedium,
 
781
                           mr.llDvdImages);      // list to append dvd images to: the root list
 
782
            else if (    t == FloppyImage
 
783
                      && (pelmMedium->nameEquals("Image"))
 
784
                    )
 
785
                readMedium(t,
 
786
                           *pelmMedium,
 
787
                           mr.llFloppyImages);      // list to append floppy images to: the root list
 
788
        }
 
789
    }
 
790
}
 
791
 
 
792
/**
516
793
 * Adds a "version" attribute to the given XML element with the
517
794
 * VirtualBox settings version (e.g. "1.10-linux"). Used by
518
795
 * the XML format for the root element and by the OVF export
526
803
    {
527
804
        case SettingsVersion_v1_8:
528
805
            pcszVersion = "1.8";
529
 
        break;
 
806
            break;
530
807
 
531
808
        case SettingsVersion_v1_9:
532
809
            pcszVersion = "1.9";
533
 
        break;
 
810
            break;
534
811
 
535
812
        case SettingsVersion_v1_10:
536
 
        case SettingsVersion_Future:                // can be set if this code runs on XML files that were created by a future version of VBox;
537
 
                                                    // in that case, downgrade to current version when writing since we can't write future versions...
538
813
            pcszVersion = "1.10";
 
814
            break;
 
815
 
 
816
        case SettingsVersion_v1_11:
 
817
            pcszVersion = "1.11";
 
818
            break;
 
819
 
 
820
        case SettingsVersion_Future:
 
821
            // can be set if this code runs on XML files that were created by a future version of VBox;
 
822
            // in that case, downgrade to current version when writing since we can't write future versions...
 
823
            pcszVersion = "1.11";
539
824
            m->sv = SettingsVersion_v1_10;
540
825
        break;
541
826
 
560
845
 * Before calling this, it is the responsibility of the caller to
561
846
 * set the "sv" member to the required settings version that is to
562
847
 * be written. For newly created files, the settings version will be
563
 
 * the latest (1.9); for files read in from disk earlier, it will be
 
848
 * the latest (1.11); for files read in from disk earlier, it will be
564
849
 * the settings version indicated in the file. However, this method
565
850
 * will silently make sure that the settings version is always
566
851
 * at least 1.7 and change it if necessary, since there is no write
585
870
         && (m->svRead < m->sv)                     // we're upgrading?
586
871
       )
587
872
    {
588
 
        // compose new filename: strip off trailing ".xml"
589
 
        Utf8Str strFilenameNew = m->strFilename.substr(0, m->strFilename.length() - 4);
590
 
        // and append something likd "-1.3-linux.xml"
 
873
        // compose new filename: strip off trailing ".xml"/".vbox"
 
874
        Utf8Str strFilenameNew;
 
875
        Utf8Str strExt = ".xml";
 
876
        if (m->strFilename.endsWith(".xml"))
 
877
            strFilenameNew = m->strFilename.substr(0, m->strFilename.length() - 4);
 
878
        else if (m->strFilename.endsWith(".vbox"))
 
879
        {
 
880
            strFilenameNew = m->strFilename.substr(0, m->strFilename.length() - 5);
 
881
            strExt = ".vbox";
 
882
        }
 
883
 
 
884
        // and append something like "-1.3-linux.xml"
591
885
        strFilenameNew.append("-");
592
886
        strFilenameNew.append(m->strSettingsVersionFull);       // e.g. "1.3-linux"
593
 
        strFilenameNew.append(".xml");
 
887
        strFilenameNew.append(strExt);                          // .xml for main config, .vbox for machine config
594
888
 
595
889
        RTFileMove(m->strFilename.c_str(),
596
890
                   strFilenameNew.c_str(),
605
899
 * Creates an <ExtraData> node under the given parent element with
606
900
 * <ExtraDataItem> childern according to the contents of the given
607
901
 * map.
 
902
 *
608
903
 * This is in ConfigFileBase because it's used in both MainConfigFile
609
 
 * MachineConfigFile, which both can have extradata.
 
904
 * and MachineConfigFile, which both can have extradata.
610
905
 *
611
906
 * @param elmParent
612
907
 * @param me
613
908
 */
614
 
void ConfigFileBase::writeExtraData(xml::ElementNode &elmParent,
615
 
                                    const ExtraDataItemsMap &me)
 
909
void ConfigFileBase::buildExtraData(xml::ElementNode &elmParent,
 
910
                                    const StringsMap &me)
616
911
{
617
912
    if (me.size())
618
913
    {
619
914
        xml::ElementNode *pelmExtraData = elmParent.createChild("ExtraData");
620
 
        for (ExtraDataItemsMap::const_iterator it = me.begin();
 
915
        for (StringsMap::const_iterator it = me.begin();
621
916
             it != me.end();
622
917
             ++it)
623
918
        {
644
939
 * @param ll
645
940
 * @param fHostMode
646
941
 */
647
 
void ConfigFileBase::writeUSBDeviceFilters(xml::ElementNode &elmParent,
 
942
void ConfigFileBase::buildUSBDeviceFilters(xml::ElementNode &elmParent,
648
943
                                           const USBDeviceFiltersList &ll,
649
944
                                           bool fHostMode)
650
945
{
689
984
}
690
985
 
691
986
/**
 
987
 * Creates a single <HardDisk> element for the given Medium structure
 
988
 * and recurses to write the child hard disks underneath. Called from
 
989
 * MainConfigFile::write().
 
990
 *
 
991
 * @param elmMedium
 
992
 * @param m
 
993
 * @param level
 
994
 */
 
995
void ConfigFileBase::buildMedium(xml::ElementNode &elmMedium,
 
996
                                 DeviceType_T devType,
 
997
                                 const Medium &mdm,
 
998
                                 uint32_t level)          // 0 for "root" call, incremented with each recursion
 
999
{
 
1000
    xml::ElementNode *pelmMedium;
 
1001
 
 
1002
    if (devType == DeviceType_HardDisk)
 
1003
        pelmMedium = elmMedium.createChild("HardDisk");
 
1004
    else
 
1005
        pelmMedium = elmMedium.createChild("Image");
 
1006
 
 
1007
    pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
 
1008
 
 
1009
    pelmMedium->setAttributePath("location", mdm.strLocation);
 
1010
 
 
1011
    if (devType == DeviceType_HardDisk || RTStrICmp(mdm.strFormat.c_str(), "RAW"))
 
1012
        pelmMedium->setAttribute("format", mdm.strFormat);
 
1013
    if (mdm.fAutoReset)
 
1014
        pelmMedium->setAttribute("autoReset", mdm.fAutoReset);
 
1015
    if (mdm.strDescription.length())
 
1016
        pelmMedium->setAttribute("Description", mdm.strDescription);
 
1017
 
 
1018
    for (StringsMap::const_iterator it = mdm.properties.begin();
 
1019
         it != mdm.properties.end();
 
1020
         ++it)
 
1021
    {
 
1022
        xml::ElementNode *pelmProp = pelmMedium->createChild("Property");
 
1023
        pelmProp->setAttribute("name", it->first);
 
1024
        pelmProp->setAttribute("value", it->second);
 
1025
    }
 
1026
 
 
1027
    // only for base hard disks, save the type
 
1028
    if (level == 0)
 
1029
    {
 
1030
        const char *pcszType =
 
1031
            mdm.hdType == MediumType_Normal ? "Normal" :
 
1032
            mdm.hdType == MediumType_Immutable ? "Immutable" :
 
1033
            mdm.hdType == MediumType_Writethrough ? "Writethrough" :
 
1034
            mdm.hdType == MediumType_Shareable ? "Shareable" :
 
1035
            mdm.hdType == MediumType_Readonly ? "Readonly" :
 
1036
            mdm.hdType == MediumType_MultiAttach ? "MultiAttach" :
 
1037
            "INVALID";
 
1038
        // no need to save the usual DVD/floppy medium types
 
1039
        if (   (   devType != DeviceType_DVD
 
1040
                || (   mdm.hdType != MediumType_Writethrough // shouldn't happen
 
1041
                    && mdm.hdType != MediumType_Readonly))
 
1042
            && (   devType != DeviceType_Floppy
 
1043
                || mdm.hdType != MediumType_Writethrough))
 
1044
            pelmMedium->setAttribute("type", pcszType);
 
1045
    }
 
1046
 
 
1047
    for (MediaList::const_iterator it = mdm.llChildren.begin();
 
1048
         it != mdm.llChildren.end();
 
1049
         ++it)
 
1050
    {
 
1051
        // recurse for children
 
1052
        buildMedium(*pelmMedium, // parent
 
1053
                    devType,     // device type
 
1054
                    *it,         // settings::Medium
 
1055
                    ++level);    // recursion level
 
1056
    }
 
1057
}
 
1058
 
 
1059
/**
 
1060
 * Creates a <MediaRegistry> node under the given parent and writes out all
 
1061
 * hard disks and DVD and floppy images from the lists in the given MediaRegistry
 
1062
 * structure under it.
 
1063
 *
 
1064
 * This is used in both MainConfigFile and MachineConfigFile since starting with
 
1065
 * VirtualBox 4.0, we can have media registries in both.
 
1066
 *
 
1067
 * @param elmParent
 
1068
 * @param mr
 
1069
 */
 
1070
void ConfigFileBase::buildMediaRegistry(xml::ElementNode &elmParent,
 
1071
                                        const MediaRegistry &mr)
 
1072
{
 
1073
    xml::ElementNode *pelmMediaRegistry = elmParent.createChild("MediaRegistry");
 
1074
 
 
1075
    xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks");
 
1076
    for (MediaList::const_iterator it = mr.llHardDisks.begin();
 
1077
         it != mr.llHardDisks.end();
 
1078
         ++it)
 
1079
    {
 
1080
        buildMedium(*pelmHardDisks, DeviceType_HardDisk, *it, 0);
 
1081
    }
 
1082
 
 
1083
    xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages");
 
1084
    for (MediaList::const_iterator it = mr.llDvdImages.begin();
 
1085
         it != mr.llDvdImages.end();
 
1086
         ++it)
 
1087
    {
 
1088
        buildMedium(*pelmDVDImages, DeviceType_DVD, *it, 0);
 
1089
    }
 
1090
 
 
1091
    xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages");
 
1092
    for (MediaList::const_iterator it = mr.llFloppyImages.begin();
 
1093
         it != mr.llFloppyImages.end();
 
1094
         ++it)
 
1095
    {
 
1096
        buildMedium(*pelmFloppyImages, DeviceType_Floppy, *it, 0);
 
1097
    }
 
1098
}
 
1099
 
 
1100
/**
692
1101
 * Cleans up memory allocated by the internal XML parser. To be called by
693
1102
 * descendant classes when they're done analyzing the DOM tree to discard it.
694
1103
 */
784
1193
}
785
1194
 
786
1195
/**
787
 
 * Reads a media registry entry from the main VirtualBox.xml file.
788
 
 *
789
 
 * Whereas the current media registry code is fairly straightforward, it was quite a mess
790
 
 * with settings format before 1.4 (VirtualBox 2.0 used settings format 1.3). The elements
791
 
 * in the media registry were much more inconsistent, and different elements were used
792
 
 * depending on the type of device and image.
793
 
 *
794
 
 * @param t
795
 
 * @param elmMedium
796
 
 * @param llMedia
797
 
 */
798
 
void MainConfigFile::readMedium(MediaType t,
799
 
                                const xml::ElementNode &elmMedium,  // HardDisk node if root; if recursing,
800
 
                                                                    // child HardDisk node or DiffHardDisk node for pre-1.4
801
 
                                MediaList &llMedia)     // list to append medium to (root disk or child list)
802
 
{
803
 
    // <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
804
 
    settings::Medium med;
805
 
    Utf8Str strUUID;
806
 
    if (!(elmMedium.getAttributeValue("uuid", strUUID)))
807
 
        throw ConfigFileError(this, &elmMedium, N_("Required %s/@uuid attribute is missing"), elmMedium.getName());
808
 
 
809
 
    parseUUID(med.uuid, strUUID);
810
 
 
811
 
    bool fNeedsLocation = true;
812
 
 
813
 
    if (t == HardDisk)
814
 
    {
815
 
        if (m->sv < SettingsVersion_v1_4)
816
 
        {
817
 
            // here the system is:
818
 
            //         <HardDisk uuid="{....}" type="normal">
819
 
            //           <VirtualDiskImage filePath="/path/to/xxx.vdi"/>
820
 
            //         </HardDisk>
821
 
 
822
 
            fNeedsLocation = false;
823
 
            bool fNeedsFilePath = true;
824
 
            const xml::ElementNode *pelmImage;
825
 
            if ((pelmImage = elmMedium.findChildElement("VirtualDiskImage")))
826
 
                med.strFormat = "VDI";
827
 
            else if ((pelmImage = elmMedium.findChildElement("VMDKImage")))
828
 
                med.strFormat = "VMDK";
829
 
            else if ((pelmImage = elmMedium.findChildElement("VHDImage")))
830
 
                med.strFormat = "VHD";
831
 
            else if ((pelmImage = elmMedium.findChildElement("ISCSIHardDisk")))
832
 
            {
833
 
                med.strFormat = "iSCSI";
834
 
 
835
 
                fNeedsFilePath = false;
836
 
                // location is special here: current settings specify an "iscsi://user@server:port/target/lun"
837
 
                // string for the location and also have several disk properties for these, whereas this used
838
 
                // to be hidden in several sub-elements before 1.4, so compose a location string and set up
839
 
                // the properties:
840
 
                med.strLocation = "iscsi://";
841
 
                Utf8Str strUser, strServer, strPort, strTarget, strLun;
842
 
                if (pelmImage->getAttributeValue("userName", strUser))
843
 
                {
844
 
                    med.strLocation.append(strUser);
845
 
                    med.strLocation.append("@");
846
 
                }
847
 
                Utf8Str strServerAndPort;
848
 
                if (pelmImage->getAttributeValue("server", strServer))
849
 
                {
850
 
                    strServerAndPort = strServer;
851
 
                }
852
 
                if (pelmImage->getAttributeValue("port", strPort))
853
 
                {
854
 
                    if (strServerAndPort.length())
855
 
                        strServerAndPort.append(":");
856
 
                    strServerAndPort.append(strPort);
857
 
                }
858
 
                med.strLocation.append(strServerAndPort);
859
 
                if (pelmImage->getAttributeValue("target", strTarget))
860
 
                {
861
 
                    med.strLocation.append("/");
862
 
                    med.strLocation.append(strTarget);
863
 
                }
864
 
                if (pelmImage->getAttributeValue("lun", strLun))
865
 
                {
866
 
                    med.strLocation.append("/");
867
 
                    med.strLocation.append(strLun);
868
 
                }
869
 
 
870
 
                if (strServer.length() && strPort.length())
871
 
                    med.properties["TargetAddress"] = strServerAndPort;
872
 
                if (strTarget.length())
873
 
                    med.properties["TargetName"] = strTarget;
874
 
                if (strUser.length())
875
 
                    med.properties["InitiatorUsername"] = strUser;
876
 
                Utf8Str strPassword;
877
 
                if (pelmImage->getAttributeValue("password", strPassword))
878
 
                    med.properties["InitiatorSecret"] = strPassword;
879
 
                if (strLun.length())
880
 
                    med.properties["LUN"] = strLun;
881
 
            }
882
 
            else if ((pelmImage = elmMedium.findChildElement("CustomHardDisk")))
883
 
            {
884
 
                fNeedsFilePath = false;
885
 
                fNeedsLocation = true;
886
 
                    // also requires @format attribute, which will be queried below
887
 
            }
888
 
            else
889
 
                throw ConfigFileError(this, &elmMedium, N_("Required %s/VirtualDiskImage element is missing"), elmMedium.getName());
890
 
 
891
 
            if (fNeedsFilePath)
892
 
                if (!(pelmImage->getAttributeValue("filePath", med.strLocation)))
893
 
                    throw ConfigFileError(this, &elmMedium, N_("Required %s/@filePath attribute is missing"), elmMedium.getName());
894
 
        }
895
 
 
896
 
        if (med.strFormat.isEmpty())        // not set with 1.4 format above, or 1.4 Custom format?
897
 
            if (!(elmMedium.getAttributeValue("format", med.strFormat)))
898
 
                throw ConfigFileError(this, &elmMedium, N_("Required %s/@format attribute is missing"), elmMedium.getName());
899
 
 
900
 
        if (!(elmMedium.getAttributeValue("autoReset", med.fAutoReset)))
901
 
            med.fAutoReset = false;
902
 
 
903
 
        Utf8Str strType;
904
 
        if ((elmMedium.getAttributeValue("type", strType)))
905
 
        {
906
 
            // pre-1.4 used lower case, so make this case-insensitive
907
 
            strType.toUpper();
908
 
            if (strType == "NORMAL")
909
 
                med.hdType = MediumType_Normal;
910
 
            else if (strType == "IMMUTABLE")
911
 
                med.hdType = MediumType_Immutable;
912
 
            else if (strType == "WRITETHROUGH")
913
 
                med.hdType = MediumType_Writethrough;
914
 
            else if (strType == "SHAREABLE")
915
 
                med.hdType = MediumType_Shareable;
916
 
            else
917
 
                throw ConfigFileError(this, &elmMedium, N_("HardDisk/@type attribute must be one of Normal, Immutable or Writethrough"));
918
 
        }
919
 
    }
920
 
    else if (m->sv < SettingsVersion_v1_4)
921
 
    {
922
 
        // DVD and floppy images before 1.4 had "src" attribute instead of "location"
923
 
        if (!(elmMedium.getAttributeValue("src", med.strLocation)))
924
 
            throw ConfigFileError(this, &elmMedium, N_("Required %s/@src attribute is missing"), elmMedium.getName());
925
 
 
926
 
        fNeedsLocation = false;
927
 
    }
928
 
 
929
 
    if (fNeedsLocation)
930
 
        // current files and 1.4 CustomHardDisk elements must have a location attribute
931
 
        if (!(elmMedium.getAttributeValue("location", med.strLocation)))
932
 
            throw ConfigFileError(this, &elmMedium, N_("Required %s/@location attribute is missing"), elmMedium.getName());
933
 
 
934
 
    elmMedium.getAttributeValue("Description", med.strDescription);       // optional
935
 
 
936
 
    // recurse to handle children
937
 
    xml::NodesLoop nl2(elmMedium);
938
 
    const xml::ElementNode *pelmHDChild;
939
 
    while ((pelmHDChild = nl2.forAllNodes()))
940
 
    {
941
 
        if (    t == HardDisk
942
 
             && (    pelmHDChild->nameEquals("HardDisk")
943
 
                  || (    (m->sv < SettingsVersion_v1_4)
944
 
                       && (pelmHDChild->nameEquals("DiffHardDisk"))
945
 
                     )
946
 
                )
947
 
           )
948
 
            // recurse with this element and push the child onto our current children list
949
 
            readMedium(t,
950
 
                        *pelmHDChild,
951
 
                        med.llChildren);
952
 
        else if (pelmHDChild->nameEquals("Property"))
953
 
        {
954
 
            Utf8Str strPropName, strPropValue;
955
 
            if (    (pelmHDChild->getAttributeValue("name", strPropName))
956
 
                 && (pelmHDChild->getAttributeValue("value", strPropValue))
957
 
               )
958
 
                med.properties[strPropName] = strPropValue;
959
 
            else
960
 
                throw ConfigFileError(this, pelmHDChild, N_("Required HardDisk/Property/@name or @value attribute is missing"));
961
 
        }
962
 
    }
963
 
 
964
 
    llMedia.push_back(med);
965
 
}
966
 
 
967
 
/**
968
 
 * Reads in the entire <MediaRegistry> chunk. For pre-1.4 files, this gets called
969
 
 * with the <DiskRegistry> chunk instead.
970
 
 * @param elmMediaRegistry
971
 
 */
972
 
void MainConfigFile::readMediaRegistry(const xml::ElementNode &elmMediaRegistry)
973
 
{
974
 
    xml::NodesLoop nl1(elmMediaRegistry);
975
 
    const xml::ElementNode *pelmChild1;
976
 
    while ((pelmChild1 = nl1.forAllNodes()))
977
 
    {
978
 
        MediaType t = Error;
979
 
        if (pelmChild1->nameEquals("HardDisks"))
980
 
            t = HardDisk;
981
 
        else if (pelmChild1->nameEquals("DVDImages"))
982
 
            t = DVDImage;
983
 
        else if (pelmChild1->nameEquals("FloppyImages"))
984
 
            t = FloppyImage;
985
 
        else
986
 
            continue;
987
 
 
988
 
        xml::NodesLoop nl2(*pelmChild1);
989
 
        const xml::ElementNode *pelmMedium;
990
 
        while ((pelmMedium = nl2.forAllNodes()))
991
 
        {
992
 
            if (    t == HardDisk
993
 
                 && (pelmMedium->nameEquals("HardDisk"))
994
 
               )
995
 
                readMedium(t,
996
 
                           *pelmMedium,
997
 
                           llHardDisks);      // list to append hard disk data to: the root list
998
 
            else if (    t == DVDImage
999
 
                      && (pelmMedium->nameEquals("Image"))
1000
 
                    )
1001
 
                readMedium(t,
1002
 
                           *pelmMedium,
1003
 
                           llDvdImages);      // list to append dvd images to: the root list
1004
 
            else if (    t == FloppyImage
1005
 
                      && (pelmMedium->nameEquals("Image"))
1006
 
                    )
1007
 
                readMedium(t,
1008
 
                           *pelmMedium,
1009
 
                           llFloppyImages);      // list to append floppy images to: the root list
1010
 
        }
1011
 
    }
1012
 
}
1013
 
 
1014
 
/**
1015
1196
 * Reads in the <DHCPServers> chunk.
1016
1197
 * @param elmDHCPServers
1017
1198
 */
1071
1252
                    if (pelmGlobalChild->nameEquals("SystemProperties"))
1072
1253
                    {
1073
1254
                        pelmGlobalChild->getAttributeValue("defaultMachineFolder", systemProperties.strDefaultMachineFolder);
1074
 
                        if (!pelmGlobalChild->getAttributeValue("defaultHardDiskFolder", systemProperties.strDefaultHardDiskFolder))
1075
 
                            // pre-1.4 used @defaultVDIFolder instead
1076
 
                            pelmGlobalChild->getAttributeValue("defaultVDIFolder", systemProperties.strDefaultHardDiskFolder);
1077
1255
                        pelmGlobalChild->getAttributeValue("defaultHardDiskFormat", systemProperties.strDefaultHardDiskFormat);
1078
 
                        pelmGlobalChild->getAttributeValue("remoteDisplayAuthLibrary", systemProperties.strRemoteDisplayAuthLibrary);
 
1256
                        if (!pelmGlobalChild->getAttributeValue("VRDEAuthLibrary", systemProperties.strVRDEAuthLibrary))
 
1257
                            // pre-1.11 used @remoteDisplayAuthLibrary instead
 
1258
                            pelmGlobalChild->getAttributeValue("remoteDisplayAuthLibrary", systemProperties.strVRDEAuthLibrary);
1079
1259
                        pelmGlobalChild->getAttributeValue("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
 
1260
                        pelmGlobalChild->getAttributeValue("defaultVRDEExtPack", systemProperties.strDefaultVRDEExtPack);
1080
1261
                        pelmGlobalChild->getAttributeValue("LogHistoryCount", systemProperties.ulLogHistoryCount);
1081
1262
                    }
1082
1263
                    else if (pelmGlobalChild->nameEquals("ExtraData"))
1088
1269
                                   && (pelmGlobalChild->nameEquals("DiskRegistry"))
1089
1270
                                 )
1090
1271
                            )
1091
 
                        readMediaRegistry(*pelmGlobalChild);
 
1272
                        readMediaRegistry(*pelmGlobalChild, mediaRegistry);
1092
1273
                    else if (pelmGlobalChild->nameEquals("NetserviceRegistry"))
1093
1274
                    {
1094
1275
                        xml::NodesLoop nlLevel4(*pelmGlobalChild);
1134
1315
}
1135
1316
 
1136
1317
/**
1137
 
 * Creates a single <HardDisk> element for the given Medium structure
1138
 
 * and recurses to write the child hard disks underneath. Called from
1139
 
 * MainConfigFile::write().
1140
 
 *
1141
 
 * @param elmMedium
1142
 
 * @param m
1143
 
 * @param level
1144
 
 */
1145
 
void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,
1146
 
                                   const Medium &mdm,
1147
 
                                   uint32_t level)          // 0 for "root" call, incremented with each recursion
1148
 
{
1149
 
    xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");
1150
 
    pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly());
1151
 
    pelmHardDisk->setAttribute("location", mdm.strLocation);
1152
 
    pelmHardDisk->setAttribute("format", mdm.strFormat);
1153
 
    if (mdm.fAutoReset)
1154
 
        pelmHardDisk->setAttribute("autoReset", mdm.fAutoReset);
1155
 
    if (mdm.strDescription.length())
1156
 
        pelmHardDisk->setAttribute("Description", mdm.strDescription);
1157
 
 
1158
 
    for (PropertiesMap::const_iterator it = mdm.properties.begin();
1159
 
         it != mdm.properties.end();
1160
 
         ++it)
1161
 
    {
1162
 
        xml::ElementNode *pelmProp = pelmHardDisk->createChild("Property");
1163
 
        pelmProp->setAttribute("name", it->first);
1164
 
        pelmProp->setAttribute("value", it->second);
1165
 
    }
1166
 
 
1167
 
    // only for base hard disks, save the type
1168
 
    if (level == 0)
1169
 
    {
1170
 
        const char *pcszType =
1171
 
            mdm.hdType == MediumType_Normal ? "Normal" :
1172
 
            mdm.hdType == MediumType_Immutable ? "Immutable" :
1173
 
            mdm.hdType == MediumType_Writethrough ? "Writethrough" :
1174
 
            mdm.hdType == MediumType_Shareable ? "Shareable" : "INVALID";
1175
 
        pelmHardDisk->setAttribute("type", pcszType);
1176
 
    }
1177
 
 
1178
 
    for (MediaList::const_iterator it = mdm.llChildren.begin();
1179
 
         it != mdm.llChildren.end();
1180
 
         ++it)
1181
 
    {
1182
 
        // recurse for children
1183
 
        writeHardDisk(*pelmHardDisk, // parent
1184
 
                      *it,           // settings::Medium
1185
 
                      ++level);      // recursion level
1186
 
    }
1187
 
}
1188
 
 
1189
 
/**
1190
1318
 * Called from the IVirtualBox interface to write out VirtualBox.xml. This
1191
1319
 * builds an XML DOM tree and writes it out to disk.
1192
1320
 */
1197
1325
 
1198
1326
    xml::ElementNode *pelmGlobal = m->pelmRoot->createChild("Global");
1199
1327
 
1200
 
    writeExtraData(*pelmGlobal, mapExtraDataItems);
 
1328
    buildExtraData(*pelmGlobal, mapExtraDataItems);
1201
1329
 
1202
1330
    xml::ElementNode *pelmMachineRegistry = pelmGlobal->createChild("MachineRegistry");
1203
1331
    for (MachinesRegistry::const_iterator it = llMachines.begin();
1211
1339
        pelmMachineEntry->setAttribute("src", mre.strSettingsFile);
1212
1340
    }
1213
1341
 
1214
 
    xml::ElementNode *pelmMediaRegistry = pelmGlobal->createChild("MediaRegistry");
1215
 
 
1216
 
    xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks");
1217
 
    for (MediaList::const_iterator it = llHardDisks.begin();
1218
 
         it != llHardDisks.end();
1219
 
         ++it)
1220
 
    {
1221
 
        writeHardDisk(*pelmHardDisks, *it, 0);
1222
 
    }
1223
 
 
1224
 
    xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages");
1225
 
    for (MediaList::const_iterator it = llDvdImages.begin();
1226
 
         it != llDvdImages.end();
1227
 
         ++it)
1228
 
    {
1229
 
        const Medium &mdm = *it;
1230
 
        xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image");
1231
 
        pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
1232
 
        pelmMedium->setAttribute("location", mdm.strLocation);
1233
 
        if (mdm.strDescription.length())
1234
 
            pelmMedium->setAttribute("Description", mdm.strDescription);
1235
 
    }
1236
 
 
1237
 
    xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages");
1238
 
    for (MediaList::const_iterator it = llFloppyImages.begin();
1239
 
         it != llFloppyImages.end();
1240
 
         ++it)
1241
 
    {
1242
 
        const Medium &mdm = *it;
1243
 
        xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image");
1244
 
        pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
1245
 
        pelmMedium->setAttribute("location", mdm.strLocation);
1246
 
        if (mdm.strDescription.length())
1247
 
            pelmMedium->setAttribute("Description", mdm.strDescription);
1248
 
    }
 
1342
    buildMediaRegistry(*pelmGlobal, mediaRegistry);
1249
1343
 
1250
1344
    xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry");
1251
1345
    xml::ElementNode *pelmDHCPServers = pelmNetserviceRegistry->createChild("DHCPServers");
1266
1360
    xml::ElementNode *pelmSysProps = pelmGlobal->createChild("SystemProperties");
1267
1361
    if (systemProperties.strDefaultMachineFolder.length())
1268
1362
        pelmSysProps->setAttribute("defaultMachineFolder", systemProperties.strDefaultMachineFolder);
1269
 
    if (systemProperties.strDefaultHardDiskFolder.length())
1270
 
        pelmSysProps->setAttribute("defaultHardDiskFolder", systemProperties.strDefaultHardDiskFolder);
1271
1363
    if (systemProperties.strDefaultHardDiskFormat.length())
1272
1364
        pelmSysProps->setAttribute("defaultHardDiskFormat", systemProperties.strDefaultHardDiskFormat);
1273
 
    if (systemProperties.strRemoteDisplayAuthLibrary.length())
1274
 
        pelmSysProps->setAttribute("remoteDisplayAuthLibrary", systemProperties.strRemoteDisplayAuthLibrary);
 
1365
    if (systemProperties.strVRDEAuthLibrary.length())
 
1366
        pelmSysProps->setAttribute("VRDEAuthLibrary", systemProperties.strVRDEAuthLibrary);
1275
1367
    if (systemProperties.strWebServiceAuthLibrary.length())
1276
1368
        pelmSysProps->setAttribute("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
 
1369
    if (systemProperties.strDefaultVRDEExtPack.length())
 
1370
        pelmSysProps->setAttribute("defaultVRDEExtPack", systemProperties.strDefaultVRDEExtPack);
1277
1371
    pelmSysProps->setAttribute("LogHistoryCount", systemProperties.ulLogHistoryCount);
1278
1372
 
1279
 
    writeUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
 
1373
    buildUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
1280
1374
                          host.llUSBDeviceFilters,
1281
1375
                          true);               // fHostMode
1282
1376
 
1300
1394
 * which in turn gets called from Machine::saveSettings to figure out whether
1301
1395
 * machine settings have really changed and thus need to be written out to disk.
1302
1396
 */
1303
 
bool VRDPSettings::operator==(const VRDPSettings& v) const
 
1397
bool VRDESettings::operator==(const VRDESettings& v) const
1304
1398
{
1305
1399
    return (    (this == &v)
1306
1400
             || (    (fEnabled                  == v.fEnabled)
1307
 
                  && (strPort                   == v.strPort)
1308
 
                  && (strNetAddress             == v.strNetAddress)
1309
1401
                  && (authType                  == v.authType)
1310
1402
                  && (ulAuthTimeout             == v.ulAuthTimeout)
 
1403
                  && (strAuthLibrary            == v.strAuthLibrary)
1311
1404
                  && (fAllowMultiConnection     == v.fAllowMultiConnection)
1312
1405
                  && (fReuseSingleConnection    == v.fReuseSingleConnection)
1313
 
                  && (fVideoChannel             == v.fVideoChannel)
1314
 
                  && (ulVideoChannelQuality     == v.ulVideoChannelQuality)
 
1406
                  && (strVrdeExtPack            == v.strVrdeExtPack)
 
1407
                  && (mapProperties             == v.mapProperties)
1315
1408
                )
1316
1409
           );
1317
1410
}
1423
1516
             || (    (strName       == g.strName)
1424
1517
                  && (strHostPath   == g.strHostPath)
1425
1518
                  && (fWritable     == g.fWritable)
 
1519
                  && (fAutoMount    == g.fAutoMount)
1426
1520
                )
1427
1521
           );
1428
1522
}
1460
1554
          fHardwareVirt(true),
1461
1555
          fHardwareVirtExclusive(HWVIRTEXCLUSIVEDEFAULT),
1462
1556
          fNestedPaging(true),
1463
 
          fLargePages(false),
1464
1557
          fVPID(true),
1465
1558
          fHardwareVirtForce(false),
1466
1559
          fSyntheticCpu(false),
1468
1561
          cCPUs(1),
1469
1562
          fCpuHotPlug(false),
1470
1563
          fHpetEnabled(false),
 
1564
          ulCpuExecutionCap(100),
1471
1565
          ulMemorySizeMB((uint32_t)-1),
1472
1566
          ulVRAMSizeMB(8),
1473
1567
          cMonitors(1),
1476
1570
          firmwareType(FirmwareType_BIOS),
1477
1571
          pointingHidType(PointingHidType_PS2Mouse),
1478
1572
          keyboardHidType(KeyboardHidType_PS2Keyboard),
 
1573
          chipsetType(ChipsetType_PIIX3),
1479
1574
          clipboardMode(ClipboardMode_Bidirectional),
1480
1575
          ulMemoryBalloonSize(0),
1481
1576
          fPageFusionEnabled(false)
1491
1586
#if HC_ARCH_BITS == 64 || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN)
1492
1587
    fPAE = true;
1493
1588
#endif
 
1589
 
 
1590
    /* The default value of large page supports depends on the host:
 
1591
     * - 64 bits host -> true, unless it's Linux (pending further prediction work due to excessively expensive large page allocations)
 
1592
     * - 32 bits host -> false
 
1593
     */
 
1594
#if HC_ARCH_BITS == 64 && !defined(RT_OS_LINUX)
 
1595
    fLargePages = true;
 
1596
#else
 
1597
    /* Not supported on 32 bits hosts. */
 
1598
    fLargePages = false;
 
1599
#endif
1494
1600
}
1495
1601
 
1496
1602
/**
1513
1619
                  && (fPAE                      == h.fPAE)
1514
1620
                  && (cCPUs                     == h.cCPUs)
1515
1621
                  && (fCpuHotPlug               == h.fCpuHotPlug)
 
1622
                  && (ulCpuExecutionCap         == h.ulCpuExecutionCap)
1516
1623
                  && (fHpetEnabled              == h.fHpetEnabled)
1517
1624
                  && (llCpus                    == h.llCpus)
1518
1625
                  && (llCpuIdLeafs              == h.llCpuIdLeafs)
1525
1632
                  && (firmwareType              == h.firmwareType)
1526
1633
                  && (pointingHidType           == h.pointingHidType)
1527
1634
                  && (keyboardHidType           == h.keyboardHidType)
1528
 
                  && (vrdpSettings              == h.vrdpSettings)
 
1635
                  && (chipsetType               == h.chipsetType)
 
1636
                  && (vrdeSettings              == h.vrdeSettings)
1529
1637
                  && (biosSettings              == h.biosSettings)
1530
1638
                  && (usbController             == h.usbController)
1531
1639
                  && (llNetworkAdapters         == h.llNetworkAdapters)
1538
1646
                  && (fPageFusionEnabled        == h.fPageFusionEnabled)
1539
1647
                  && (llGuestProperties         == h.llGuestProperties)
1540
1648
                  && (strNotificationPatterns   == h.strNotificationPatterns)
 
1649
                  && (ioSettings                == h.ioSettings)
1541
1650
                )
1542
1651
            );
1543
1652
}
1556
1665
                  && (lDevice                   == a.lDevice)
1557
1666
                  && (uuid                      == a.uuid)
1558
1667
                  && (strHostDriveSrc           == a.strHostDriveSrc)
 
1668
                  && (strBwGroup                == a.strBwGroup)
1559
1669
                )
1560
1670
           );
1561
1671
}
1622
1732
{
1623
1733
    fIoCacheEnabled  = true;
1624
1734
    ulIoCacheSize    = 5;
1625
 
    ulIoBandwidthMax = 0;
1626
1735
}
1627
1736
 
1628
1737
////////////////////////////////////////////////////////////////////////////////
1646
1755
 */
1647
1756
MachineConfigFile::MachineConfigFile(const Utf8Str *pstrFilename)
1648
1757
    : ConfigFileBase(pstrFilename),
1649
 
      fNameSync(true),
1650
 
      fTeleporterEnabled(false),
1651
 
      uTeleporterPort(0),
1652
 
      fRTCUseUTC(false),
1653
1758
      fCurrentStateModified(true),
1654
1759
      fAborted(false)
1655
1760
{
1674
1779
}
1675
1780
 
1676
1781
/**
 
1782
 * Public routine which returns true if this machine config file can have its
 
1783
 * own media registry (which is true for settings version v1.11 and higher,
 
1784
 * i.e. files created by VirtualBox 4.0 and higher).
 
1785
 * @return
 
1786
 */
 
1787
bool MachineConfigFile::canHaveOwnMediaRegistry() const
 
1788
{
 
1789
    return (m->sv >= SettingsVersion_v1_11);
 
1790
}
 
1791
 
 
1792
/**
1677
1793
 * Public routine which allows for importing machine XML from an external DOM tree.
1678
1794
 * Use this after having called the constructor with a NULL argument.
1679
1795
 *
1706
1822
{
1707
1823
    return (    (this == &c)
1708
1824
            || (    (uuid                       == c.uuid)
1709
 
                 && (strName                    == c.strName)
1710
 
                 && (fNameSync                  == c.fNameSync)
1711
 
                 && (strDescription             == c.strDescription)
1712
 
                 && (strOsType                  == c.strOsType)
 
1825
                 && (machineUserData            == c.machineUserData)
1713
1826
                 && (strStateFile               == c.strStateFile)
1714
1827
                 && (uuidCurrentSnapshot        == c.uuidCurrentSnapshot)
1715
 
                 && (strSnapshotFolder          == c.strSnapshotFolder)
1716
 
                 && (fTeleporterEnabled         == c.fTeleporterEnabled)
1717
 
                 && (uTeleporterPort            == c.uTeleporterPort)
1718
 
                 && (strTeleporterAddress       == c.strTeleporterAddress)
1719
 
                 && (strTeleporterPassword      == c.strTeleporterPassword)
1720
 
                 && (fRTCUseUTC                 == c.fRTCUseUTC)
1721
1828
                 // skip fCurrentStateModified!
1722
1829
                 && (RTTimeSpecIsEqual(&timeLastStateChange, &c.timeLastStateChange))
1723
1830
                 && (fAborted                   == c.fAborted)
1724
1831
                 && (hardwareMachine            == c.hardwareMachine)       // this one's deep
1725
1832
                 && (storageMachine             == c.storageMachine)        // this one's deep
 
1833
                 && (mediaRegistry              == c.mediaRegistry)         // this one's deep
1726
1834
                 && (mapExtraDataItems          == c.mapExtraDataItems)     // this one's deep
1727
1835
                 && (llFirstSnapshot            == c.llFirstSnapshot)       // this one's deep
1728
1836
               )
1819
1927
        pelmAdapter->getAttributeValue("trace", nic.fTraceEnabled);
1820
1928
        pelmAdapter->getAttributeValue("tracefile", nic.strTraceFile);
1821
1929
        pelmAdapter->getAttributeValue("bootPriority", nic.ulBootPriority);
 
1930
        pelmAdapter->getAttributeValue("bandwidthLimit", nic.ulBandwidthLimit);
1822
1931
 
1823
1932
        xml::ElementNodesList llNetworkModes;
1824
1933
        pelmAdapter->getChildElements(llNetworkModes);
1896
2005
            NATRule rule;
1897
2006
            uint32_t port = 0;
1898
2007
            (*pf)->getAttributeValue("name", rule.strName);
1899
 
            (*pf)->getAttributeValue("proto", rule.u32Proto);
 
2008
            (*pf)->getAttributeValue("proto", (uint32_t&)rule.proto);
1900
2009
            (*pf)->getAttributeValue("hostip", rule.strHostIP);
1901
2010
            (*pf)->getAttributeValue("hostport", port);
1902
2011
            rule.u16HostPort = port;
2044
2153
            aa.controllerType = AudioControllerType_SB16;
2045
2154
        else if (strTemp == "AC97")
2046
2155
            aa.controllerType = AudioControllerType_AC97;
 
2156
        else if (strTemp == "HDA")
 
2157
            aa.controllerType = AudioControllerType_HDA;
2047
2158
        else
2048
2159
            throw ConfigFileError(this, &elmAudioAdapter, N_("Invalid value '%s' in AudioAdapter/@controller attribute"), strTemp.c_str());
2049
2160
    }
2171
2282
            }
2172
2283
 
2173
2284
            pelmHwChild->getAttributeValue("hotplug", hw.fCpuHotPlug);
 
2285
            pelmHwChild->getAttributeValue("executionCap", hw.ulCpuExecutionCap);
2174
2286
 
2175
2287
            const xml::ElementNode *pelmCPUChild;
2176
2288
            if (hw.fCpuHotPlug)
2191
2303
            if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExVPID")))
2192
2304
                pelmCPUChild->getAttributeValue("enabled", hw.fVPID);
2193
2305
            if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtForce")))
2194
 
                pelmCPUChild->getAttributeValue("enabled", hw.fHardwareVirtForce);            
 
2306
                pelmCPUChild->getAttributeValue("enabled", hw.fHardwareVirtForce);
2195
2307
 
2196
2308
            if (!(pelmCPUChild = pelmHwChild->findChildElement("PAE")))
2197
2309
            {
2276
2388
                                          strHidType.c_str());
2277
2389
            }
2278
2390
        }
 
2391
        else if (pelmHwChild->nameEquals("Chipset"))
 
2392
        {
 
2393
            Utf8Str strChipsetType;
 
2394
            if (pelmHwChild->getAttributeValue("type", strChipsetType))
 
2395
            {
 
2396
                if (strChipsetType == "PIIX3")
 
2397
                    hw.chipsetType = ChipsetType_PIIX3;
 
2398
                else if (strChipsetType == "ICH9")
 
2399
                    hw.chipsetType = ChipsetType_ICH9;
 
2400
                else
 
2401
                    throw ConfigFileError(this,
 
2402
                                          pelmHwChild,
 
2403
                                          N_("Invalid value '%s' in Chipset/@type"),
 
2404
                                          strChipsetType.c_str());
 
2405
            }
 
2406
        }
2279
2407
        else if (pelmHwChild->nameEquals("HPET"))
2280
2408
        {
2281
2409
            pelmHwChild->getAttributeValue("enabled", hw.fHpetEnabled);
2337
2465
        }
2338
2466
        else if (pelmHwChild->nameEquals("RemoteDisplay"))
2339
2467
        {
2340
 
            pelmHwChild->getAttributeValue("enabled", hw.vrdpSettings.fEnabled);
2341
 
            pelmHwChild->getAttributeValue("port", hw.vrdpSettings.strPort);
2342
 
            pelmHwChild->getAttributeValue("netAddress", hw.vrdpSettings.strNetAddress);
 
2468
            pelmHwChild->getAttributeValue("enabled", hw.vrdeSettings.fEnabled);
 
2469
 
 
2470
            Utf8Str str;
 
2471
            if (pelmHwChild->getAttributeValue("port", str))
 
2472
                hw.vrdeSettings.mapProperties["TCP/Ports"] = str;
 
2473
            if (pelmHwChild->getAttributeValue("netAddress", str))
 
2474
                hw.vrdeSettings.mapProperties["TCP/Address"] = str;
2343
2475
 
2344
2476
            Utf8Str strAuthType;
2345
2477
            if (pelmHwChild->getAttributeValue("authType", strAuthType))
2347
2479
                // settings before 1.3 used lower case so make sure this is case-insensitive
2348
2480
                strAuthType.toUpper();
2349
2481
                if (strAuthType == "NULL")
2350
 
                    hw.vrdpSettings.authType = VRDPAuthType_Null;
 
2482
                    hw.vrdeSettings.authType = AuthType_Null;
2351
2483
                else if (strAuthType == "GUEST")
2352
 
                    hw.vrdpSettings.authType = VRDPAuthType_Guest;
 
2484
                    hw.vrdeSettings.authType = AuthType_Guest;
2353
2485
                else if (strAuthType == "EXTERNAL")
2354
 
                    hw.vrdpSettings.authType = VRDPAuthType_External;
 
2486
                    hw.vrdeSettings.authType = AuthType_External;
2355
2487
                else
2356
2488
                    throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in RemoteDisplay/@authType attribute"), strAuthType.c_str());
2357
2489
            }
2358
2490
 
2359
 
            pelmHwChild->getAttributeValue("authTimeout", hw.vrdpSettings.ulAuthTimeout);
2360
 
            pelmHwChild->getAttributeValue("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
2361
 
            pelmHwChild->getAttributeValue("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
 
2491
            pelmHwChild->getAttributeValue("authLibrary", hw.vrdeSettings.strAuthLibrary);
 
2492
            pelmHwChild->getAttributeValue("authTimeout", hw.vrdeSettings.ulAuthTimeout);
 
2493
            pelmHwChild->getAttributeValue("allowMultiConnection", hw.vrdeSettings.fAllowMultiConnection);
 
2494
            pelmHwChild->getAttributeValue("reuseSingleConnection", hw.vrdeSettings.fReuseSingleConnection);
2362
2495
 
 
2496
            /* 3.2 and 4.0 betas, 4.0 has this information in VRDEProperties. */
2363
2497
            const xml::ElementNode *pelmVideoChannel;
2364
2498
            if ((pelmVideoChannel = pelmHwChild->findChildElement("VideoChannel")))
2365
2499
            {
2366
 
                pelmVideoChannel->getAttributeValue("enabled", hw.vrdpSettings.fVideoChannel);
2367
 
                pelmVideoChannel->getAttributeValue("quality", hw.vrdpSettings.ulVideoChannelQuality);
2368
 
                hw.vrdpSettings.ulVideoChannelQuality = RT_CLAMP(hw.vrdpSettings.ulVideoChannelQuality, 10, 100);
 
2500
                bool fVideoChannel = false;
 
2501
                pelmVideoChannel->getAttributeValue("enabled", fVideoChannel);
 
2502
                hw.vrdeSettings.mapProperties["VideoChannel/Enabled"] = fVideoChannel? "true": "false";
 
2503
 
 
2504
                uint32_t ulVideoChannelQuality = 75;
 
2505
                pelmVideoChannel->getAttributeValue("quality", ulVideoChannelQuality);
 
2506
                ulVideoChannelQuality = RT_CLAMP(ulVideoChannelQuality, 10, 100);
 
2507
                char *pszBuffer = NULL;
 
2508
                if (RTStrAPrintf(&pszBuffer, "%d", ulVideoChannelQuality) >= 0)
 
2509
                {
 
2510
                    hw.vrdeSettings.mapProperties["VideoChannel/Quality"] = pszBuffer;
 
2511
                    RTStrFree(pszBuffer);
 
2512
                }
 
2513
                else
 
2514
                    hw.vrdeSettings.mapProperties["VideoChannel/Quality"] = "75";
 
2515
            }
 
2516
            pelmHwChild->getAttributeValue("VRDEExtPack", hw.vrdeSettings.strVrdeExtPack);
 
2517
 
 
2518
            const xml::ElementNode *pelmProperties = pelmHwChild->findChildElement("VRDEProperties");
 
2519
            if (pelmProperties != NULL)
 
2520
            {
 
2521
                xml::NodesLoop nl(*pelmProperties);
 
2522
                const xml::ElementNode *pelmProperty;
 
2523
                while ((pelmProperty = nl.forAllNodes()))
 
2524
                {
 
2525
                    if (pelmProperty->nameEquals("Property"))
 
2526
                    {
 
2527
                        /* <Property name="TCP/Ports" value="3000-3002"/> */
 
2528
                        Utf8Str strName, strValue;
 
2529
                        if (    ((pelmProperty->getAttributeValue("name", strName)))
 
2530
                             && ((pelmProperty->getAttributeValue("value", strValue)))
 
2531
                           )
 
2532
                            hw.vrdeSettings.mapProperties[strName] = strValue;
 
2533
                        else
 
2534
                            throw ConfigFileError(this, pelmProperty, N_("Required VRDE Property/@name or @value attribute is missing"));
 
2535
                    }
 
2536
                }
2369
2537
            }
2370
2538
        }
2371
2539
        else if (pelmHwChild->nameEquals("BIOS"))
2461
2629
        else if (pelmHwChild->nameEquals("RTC"))
2462
2630
        {
2463
2631
            Utf8Str strLocalOrUTC;
2464
 
            fRTCUseUTC =    pelmHwChild->getAttributeValue("localOrUTC", strLocalOrUTC)
2465
 
                         && strLocalOrUTC == "UTC";
 
2632
            machineUserData.fRTCUseUTC =    pelmHwChild->getAttributeValue("localOrUTC", strLocalOrUTC)
 
2633
                                         && strLocalOrUTC == "UTC";
2466
2634
        }
2467
2635
        else if (    (pelmHwChild->nameEquals("UART"))
2468
2636
                  || (pelmHwChild->nameEquals("Uart"))      // used before 1.3
2484
2652
                pelmFolder->getAttributeValue("name", sf.strName);
2485
2653
                pelmFolder->getAttributeValue("hostPath", sf.strHostPath);
2486
2654
                pelmFolder->getAttributeValue("writable", sf.fWritable);
 
2655
                pelmFolder->getAttributeValue("autoMount", sf.fAutoMount);
2487
2656
                hw.llSharedFolders.push_back(sf);
2488
2657
            }
2489
2658
        }
2513
2682
            readGuestProperties(*pelmHwChild, hw);
2514
2683
        else if (pelmHwChild->nameEquals("IO"))
2515
2684
        {
 
2685
            const xml::ElementNode *pelmBwGroups;
2516
2686
            const xml::ElementNode *pelmIoChild;
2517
2687
 
2518
2688
            if ((pelmIoChild = pelmHwChild->findChildElement("IoCache")))
2520
2690
                pelmIoChild->getAttributeValue("enabled", hw.ioSettings.fIoCacheEnabled);
2521
2691
                pelmIoChild->getAttributeValue("size", hw.ioSettings.ulIoCacheSize);
2522
2692
            }
2523
 
            if ((pelmIoChild = pelmHwChild->findChildElement("IoBandwidth")))
 
2693
 
 
2694
            if ((pelmBwGroups = pelmHwChild->findChildElement("BandwidthGroups")))
2524
2695
            {
2525
 
                pelmIoChild->getAttributeValue("max", hw.ioSettings.ulIoBandwidthMax);
 
2696
                xml::NodesLoop nl2(*pelmBwGroups, "BandwidthGroup");
 
2697
                const xml::ElementNode *pelmBandwidthGroup;
 
2698
                while ((pelmBandwidthGroup = nl2.forAllNodes()))
 
2699
                {
 
2700
                    BandwidthGroup gr;
 
2701
                    Utf8Str strTemp;
 
2702
 
 
2703
                    pelmBandwidthGroup->getAttributeValue("name", gr.strName);
 
2704
 
 
2705
                    if (pelmBandwidthGroup->getAttributeValue("type", strTemp))
 
2706
                    {
 
2707
                        if (strTemp == "Disk")
 
2708
                            gr.enmType = BandwidthGroupType_Disk;
 
2709
                        else if (strTemp == "Network")
 
2710
                            gr.enmType = BandwidthGroupType_Network;
 
2711
                        else
 
2712
                            throw ConfigFileError(this, pelmBandwidthGroup, N_("Invalid value '%s' in BandwidthGroup/@type attribute"), strTemp.c_str());
 
2713
                    }
 
2714
                    else
 
2715
                        throw ConfigFileError(this, pelmBandwidthGroup, N_("Missing BandwidthGroup/@type attribute"));
 
2716
 
 
2717
                    pelmBandwidthGroup->getAttributeValue("maxMbPerSec", gr.cMaxMbPerSec);
 
2718
                    hw.ioSettings.llBandwidthGroups.push_back(gr);
 
2719
                }
2526
2720
            }
2527
2721
        }
2528
2722
    }
2632
2826
        pelmController->getAttributeValue("Instance", sctl.ulInstance);
2633
2827
            // default from constructor is 0
2634
2828
 
 
2829
        pelmController->getAttributeValue("Bootable", sctl.fBootable);
 
2830
            // default from constructor is true which is true
 
2831
            // for settings below version 1.11 because they allowed only
 
2832
            // one controller per type.
 
2833
 
2635
2834
        Utf8Str strType;
2636
2835
        if (!pelmController->getAttributeValue("type", strType))
2637
2836
            throw ConfigFileError(this, pelmController, N_("Required StorageController/@type attribute is missing"));
2734
2933
                if (!pelmAttached->getAttributeValue("device", att.lDevice))
2735
2934
                    throw ConfigFileError(this, pelmImage, N_("Required AttachedDevice/@device attribute is missing"));
2736
2935
 
 
2936
                pelmAttached->getAttributeValue("bandwidthGroup", att.strBwGroup);
2737
2937
                sctl.llAttachedDevices.push_back(att);
2738
2938
            }
2739
2939
        }
2867
3067
        throw ConfigFileError(this, &elmSnapshot, N_("Required Snapshot/@timeStamp attribute is missing"));
2868
3068
    parseTimestamp(snap.timestamp, strTemp);
2869
3069
 
2870
 
    elmSnapshot.getAttributeValue("stateFile", snap.strStateFile);      // online snapshots only
 
3070
    elmSnapshot.getAttributeValuePath("stateFile", snap.strStateFile);      // online snapshots only
2871
3071
 
2872
3072
    // parse Hardware before the other elements because other things depend on it
2873
3073
    const xml::ElementNode *pelmHardware;
2976
3176
{
2977
3177
    Utf8Str strUUID;
2978
3178
    if (    (elmMachine.getAttributeValue("uuid", strUUID))
2979
 
         && (elmMachine.getAttributeValue("name", strName))
 
3179
         && (elmMachine.getAttributeValue("name", machineUserData.strName))
2980
3180
       )
2981
3181
    {
2982
3182
        parseUUID(uuid, strUUID);
2983
3183
 
2984
 
        if (!elmMachine.getAttributeValue("nameSync", fNameSync))
2985
 
            fNameSync = true;
 
3184
        elmMachine.getAttributeValue("nameSync", machineUserData.fNameSync);
2986
3185
 
2987
3186
        Utf8Str str;
2988
 
        elmMachine.getAttributeValue("Description", strDescription);
 
3187
        elmMachine.getAttributeValue("Description", machineUserData.strDescription);
2989
3188
 
2990
 
        elmMachine.getAttributeValue("OSType", strOsType);
 
3189
        elmMachine.getAttributeValue("OSType", machineUserData.strOsType);
2991
3190
        if (m->sv < SettingsVersion_v1_5)
2992
 
            convertOldOSType_pre1_5(strOsType);
2993
 
 
2994
 
        elmMachine.getAttributeValue("stateFile", strStateFile);
 
3191
            convertOldOSType_pre1_5(machineUserData.strOsType);
 
3192
 
 
3193
        elmMachine.getAttributeValuePath("stateFile", strStateFile);
 
3194
 
2995
3195
        if (elmMachine.getAttributeValue("currentSnapshot", str))
2996
3196
            parseUUID(uuidCurrentSnapshot, str);
2997
 
        elmMachine.getAttributeValue("snapshotFolder", strSnapshotFolder);
 
3197
 
 
3198
        elmMachine.getAttributeValuePath("snapshotFolder", machineUserData.strSnapshotFolder);
 
3199
 
2998
3200
        if (!elmMachine.getAttributeValue("currentStateModified", fCurrentStateModified))
2999
3201
            fCurrentStateModified = true;
3000
3202
        if (elmMachine.getAttributeValue("lastStateChange", str))
3030
3232
                llFirstSnapshot.push_back(snap);
3031
3233
            }
3032
3234
            else if (pelmMachineChild->nameEquals("Description"))
3033
 
                strDescription = pelmMachineChild->getValue();
 
3235
                machineUserData.strDescription = pelmMachineChild->getValue();
3034
3236
            else if (pelmMachineChild->nameEquals("Teleporter"))
3035
3237
            {
3036
 
                if (!pelmMachineChild->getAttributeValue("enabled", fTeleporterEnabled))
3037
 
                    fTeleporterEnabled = false;
3038
 
                if (!pelmMachineChild->getAttributeValue("port", uTeleporterPort))
3039
 
                    uTeleporterPort = 0;
3040
 
                if (!pelmMachineChild->getAttributeValue("address", strTeleporterAddress))
3041
 
                    strTeleporterAddress = "";
3042
 
                if (!pelmMachineChild->getAttributeValue("password", strTeleporterPassword))
3043
 
                    strTeleporterPassword = "";
3044
 
            }
 
3238
                pelmMachineChild->getAttributeValue("enabled", machineUserData.fTeleporterEnabled);
 
3239
                pelmMachineChild->getAttributeValue("port", machineUserData.uTeleporterPort);
 
3240
                pelmMachineChild->getAttributeValue("address", machineUserData.strTeleporterAddress);
 
3241
                pelmMachineChild->getAttributeValue("password", machineUserData.strTeleporterPassword);
 
3242
            }
 
3243
            else if (pelmMachineChild->nameEquals("FaultTolerance"))
 
3244
            {
 
3245
                Utf8Str strFaultToleranceSate;
 
3246
                if (pelmMachineChild->getAttributeValue("state", strFaultToleranceSate))
 
3247
                {
 
3248
                    if (strFaultToleranceSate == "master")
 
3249
                        machineUserData.enmFaultToleranceState = FaultToleranceState_Master;
 
3250
                    else
 
3251
                    if (strFaultToleranceSate == "standby")
 
3252
                        machineUserData.enmFaultToleranceState = FaultToleranceState_Standby;
 
3253
                    else
 
3254
                        machineUserData.enmFaultToleranceState = FaultToleranceState_Inactive;
 
3255
                }
 
3256
                pelmMachineChild->getAttributeValue("port", machineUserData.uFaultTolerancePort);
 
3257
                pelmMachineChild->getAttributeValue("address", machineUserData.strFaultToleranceAddress);
 
3258
                pelmMachineChild->getAttributeValue("interval", machineUserData.uFaultToleranceInterval);
 
3259
                pelmMachineChild->getAttributeValue("password", machineUserData.strFaultTolerancePassword);
 
3260
            }
 
3261
            else if (pelmMachineChild->nameEquals("MediaRegistry"))
 
3262
                readMediaRegistry(*pelmMachineChild, mediaRegistry);
3045
3263
        }
3046
3264
 
3047
3265
        if (m->sv < SettingsVersion_v1_9)
3086
3304
    if (hw.fSyntheticCpu)
3087
3305
        pelmCPU->createChild("SyntheticCpu")->setAttribute("enabled", hw.fSyntheticCpu);
3088
3306
    pelmCPU->setAttribute("count", hw.cCPUs);
3089
 
 
3090
 
    if (hw.fLargePages)
3091
 
        pelmCPU->createChild("HardwareVirtExLargePages")->setAttribute("enabled", hw.fLargePages);
3092
 
    
 
3307
    if (hw.ulCpuExecutionCap != 100)
 
3308
        pelmCPU->setAttribute("executionCap", hw.ulCpuExecutionCap);
 
3309
 
 
3310
    /* Always save this setting as we have changed the default in 4.0 (on for large memory 64-bit systems). */
 
3311
    pelmCPU->createChild("HardwareVirtExLargePages")->setAttribute("enabled", hw.fLargePages);
 
3312
 
3093
3313
    if (m->sv >= SettingsVersion_v1_9)
3094
 
        pelmCPU->createChild("HardwareVirtForce")->setAttribute("enabled", hw.fHardwareVirtForce);    
 
3314
        pelmCPU->createChild("HardwareVirtForce")->setAttribute("enabled", hw.fHardwareVirtForce);
3095
3315
 
3096
3316
    if (m->sv >= SettingsVersion_v1_10)
3097
3317
    {
3190
3410
         pelmHpet->setAttribute("enabled", hw.fHpetEnabled);
3191
3411
    }
3192
3412
 
 
3413
    if (    (m->sv >= SettingsVersion_v1_11)
 
3414
       )
 
3415
    {
 
3416
         xml::ElementNode *pelmChipset = pelmHardware->createChild("Chipset");
 
3417
         const char *pcszChipset;
 
3418
 
 
3419
         switch (hw.chipsetType)
 
3420
         {
 
3421
            case ChipsetType_PIIX3:             pcszChipset = "PIIX3";   break;
 
3422
            case ChipsetType_ICH9:              pcszChipset = "ICH9";    break;
 
3423
            default:            Assert(false);  pcszChipset = "PIIX3";   break;
 
3424
         }
 
3425
         pelmChipset->setAttribute("type", pcszChipset);
 
3426
    }
 
3427
 
3193
3428
    xml::ElementNode *pelmBoot = pelmHardware->createChild("Boot");
3194
3429
    for (BootOrderMap::const_iterator it = hw.mapBootOrder.begin();
3195
3430
         it != hw.mapBootOrder.end();
3222
3457
    if (m->sv >= SettingsVersion_v1_8)
3223
3458
        pelmDisplay->setAttribute("accelerate2DVideo", hw.fAccelerate2DVideo);
3224
3459
 
3225
 
    xml::ElementNode *pelmVRDP = pelmHardware->createChild("RemoteDisplay");
3226
 
    pelmVRDP->setAttribute("enabled", hw.vrdpSettings.fEnabled);
3227
 
    Utf8Str strPort = hw.vrdpSettings.strPort;
3228
 
    if (!strPort.length())
3229
 
        strPort = "3389";
3230
 
    pelmVRDP->setAttribute("port", strPort);
3231
 
    if (hw.vrdpSettings.strNetAddress.length())
3232
 
        pelmVRDP->setAttribute("netAddress", hw.vrdpSettings.strNetAddress);
 
3460
    xml::ElementNode *pelmVRDE = pelmHardware->createChild("RemoteDisplay");
 
3461
    pelmVRDE->setAttribute("enabled", hw.vrdeSettings.fEnabled);
 
3462
    if (m->sv < SettingsVersion_v1_11)
 
3463
    {
 
3464
        /* In VBox 4.0 these attributes are replaced with "Properties". */
 
3465
        Utf8Str strPort;
 
3466
        StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.find("TCP/Ports");
 
3467
        if (it != hw.vrdeSettings.mapProperties.end())
 
3468
            strPort = it->second;
 
3469
        if (!strPort.length())
 
3470
            strPort = "3389";
 
3471
        pelmVRDE->setAttribute("port", strPort);
 
3472
 
 
3473
        Utf8Str strAddress;
 
3474
        it = hw.vrdeSettings.mapProperties.find("TCP/Address");
 
3475
        if (it != hw.vrdeSettings.mapProperties.end())
 
3476
            strAddress = it->second;
 
3477
        if (strAddress.length())
 
3478
            pelmVRDE->setAttribute("netAddress", strAddress);
 
3479
    }
3233
3480
    const char *pcszAuthType;
3234
 
    switch (hw.vrdpSettings.authType)
3235
 
    {
3236
 
        case VRDPAuthType_Guest:    pcszAuthType = "Guest";    break;
3237
 
        case VRDPAuthType_External: pcszAuthType = "External"; break;
3238
 
        default: /*case VRDPAuthType_Null:*/ pcszAuthType = "Null"; break;
3239
 
    }
3240
 
    pelmVRDP->setAttribute("authType", pcszAuthType);
3241
 
 
3242
 
    if (hw.vrdpSettings.ulAuthTimeout != 0)
3243
 
        pelmVRDP->setAttribute("authTimeout", hw.vrdpSettings.ulAuthTimeout);
3244
 
    if (hw.vrdpSettings.fAllowMultiConnection)
3245
 
        pelmVRDP->setAttribute("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
3246
 
    if (hw.vrdpSettings.fReuseSingleConnection)
3247
 
        pelmVRDP->setAttribute("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
3248
 
 
3249
 
    if (m->sv >= SettingsVersion_v1_10)
3250
 
    {
3251
 
        xml::ElementNode *pelmVideoChannel = pelmVRDP->createChild("VideoChannel");
3252
 
        pelmVideoChannel->setAttribute("enabled", hw.vrdpSettings.fVideoChannel);
3253
 
        pelmVideoChannel->setAttribute("quality", hw.vrdpSettings.ulVideoChannelQuality);
 
3481
    switch (hw.vrdeSettings.authType)
 
3482
    {
 
3483
        case AuthType_Guest:    pcszAuthType = "Guest";    break;
 
3484
        case AuthType_External: pcszAuthType = "External"; break;
 
3485
        default: /*case AuthType_Null:*/ pcszAuthType = "Null"; break;
 
3486
    }
 
3487
    pelmVRDE->setAttribute("authType", pcszAuthType);
 
3488
 
 
3489
    if (hw.vrdeSettings.ulAuthTimeout != 0)
 
3490
        pelmVRDE->setAttribute("authTimeout", hw.vrdeSettings.ulAuthTimeout);
 
3491
    if (hw.vrdeSettings.fAllowMultiConnection)
 
3492
        pelmVRDE->setAttribute("allowMultiConnection", hw.vrdeSettings.fAllowMultiConnection);
 
3493
    if (hw.vrdeSettings.fReuseSingleConnection)
 
3494
        pelmVRDE->setAttribute("reuseSingleConnection", hw.vrdeSettings.fReuseSingleConnection);
 
3495
 
 
3496
    if (m->sv == SettingsVersion_v1_10)
 
3497
    {
 
3498
        xml::ElementNode *pelmVideoChannel = pelmVRDE->createChild("VideoChannel");
 
3499
 
 
3500
        /* In 4.0 videochannel settings were replaced with properties, so look at properties. */
 
3501
        Utf8Str str;
 
3502
        StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.find("VideoChannel/Enabled");
 
3503
        if (it != hw.vrdeSettings.mapProperties.end())
 
3504
            str = it->second;
 
3505
        bool fVideoChannel =    RTStrICmp(str.c_str(), "true") == 0
 
3506
                             || RTStrCmp(str.c_str(), "1") == 0;
 
3507
        pelmVideoChannel->setAttribute("enabled", fVideoChannel);
 
3508
 
 
3509
        it = hw.vrdeSettings.mapProperties.find("VideoChannel/Quality");
 
3510
        if (it != hw.vrdeSettings.mapProperties.end())
 
3511
            str = it->second;
 
3512
        uint32_t ulVideoChannelQuality = RTStrToUInt32(str.c_str()); /* This returns 0 on invalid string which is ok. */
 
3513
        if (ulVideoChannelQuality == 0)
 
3514
            ulVideoChannelQuality = 75;
 
3515
        else
 
3516
            ulVideoChannelQuality = RT_CLAMP(ulVideoChannelQuality, 10, 100);
 
3517
        pelmVideoChannel->setAttribute("quality", ulVideoChannelQuality);
 
3518
    }
 
3519
    if (m->sv >= SettingsVersion_v1_11)
 
3520
    {
 
3521
        if (hw.vrdeSettings.strAuthLibrary.length())
 
3522
            pelmVRDE->setAttribute("authLibrary", hw.vrdeSettings.strAuthLibrary);
 
3523
        if (hw.vrdeSettings.strVrdeExtPack.isNotEmpty())
 
3524
            pelmVRDE->setAttribute("VRDEExtPack", hw.vrdeSettings.strVrdeExtPack);
 
3525
        if (hw.vrdeSettings.mapProperties.size() > 0)
 
3526
        {
 
3527
            xml::ElementNode *pelmProperties = pelmVRDE->createChild("VRDEProperties");
 
3528
            for (StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.begin();
 
3529
                 it != hw.vrdeSettings.mapProperties.end();
 
3530
                 ++it)
 
3531
            {
 
3532
                const Utf8Str &strName = it->first;
 
3533
                const Utf8Str &strValue = it->second;
 
3534
                xml::ElementNode *pelm = pelmProperties->createChild("Property");
 
3535
                pelm->setAttribute("name", strName);
 
3536
                pelm->setAttribute("value", strValue);
 
3537
            }
 
3538
        }
3254
3539
    }
3255
3540
 
3256
3541
    xml::ElementNode *pelmBIOS = pelmHardware->createChild("BIOS");
3342
3627
    pelmUSB->setAttribute("enabled", hw.usbController.fEnabled);
3343
3628
    pelmUSB->setAttribute("enabledEhci", hw.usbController.fEnabledEHCI);
3344
3629
 
3345
 
    writeUSBDeviceFilters(*pelmUSB,
 
3630
    buildUSBDeviceFilters(*pelmUSB,
3346
3631
                          hw.usbController.llDeviceFilters,
3347
3632
                          false);               // fHostMode
3348
3633
 
3368
3653
            pelmAdapter->setAttribute("trace", nic.fTraceEnabled);
3369
3654
            pelmAdapter->setAttribute("tracefile", nic.strTraceFile);
3370
3655
        }
 
3656
        if (nic.ulBandwidthLimit)
 
3657
            pelmAdapter->setAttribute("bandwidthLimit", nic.ulBandwidthLimit);
3371
3658
 
3372
3659
        const char *pcszType;
3373
3660
        switch (nic.type)
3417
3704
        else
3418
3705
        {
3419
3706
            /* m->sv >= SettingsVersion_v1_10 */
3420
 
            xml::ElementNode *pelmDisabledNode;
 
3707
            xml::ElementNode *pelmDisabledNode= NULL;
3421
3708
            if (nic.fHasDisabledNAT)
3422
3709
                pelmDisabledNode = pelmAdapter->createChild("DisabledModes");
3423
3710
            if (nic.fHasDisabledNAT)
3478
3765
    }
3479
3766
 
3480
3767
    xml::ElementNode *pelmAudio = pelmHardware->createChild("AudioAdapter");
3481
 
    pelmAudio->setAttribute("controller", (hw.audioAdapter.controllerType == AudioControllerType_SB16) ? "SB16" : "AC97");
 
3768
    const char *pcszController;
 
3769
    switch (hw.audioAdapter.controllerType)
 
3770
    {
 
3771
        case AudioControllerType_SB16:
 
3772
            pcszController = "SB16";
 
3773
            break;
 
3774
        case AudioControllerType_HDA:
 
3775
            if (m->sv >= SettingsVersion_v1_11)
 
3776
            {
 
3777
                pcszController = "HDA";
 
3778
                break;
 
3779
            }
 
3780
            /* fall through */
 
3781
        case AudioControllerType_AC97:
 
3782
        default:
 
3783
            pcszController = "AC97"; break;
 
3784
    }
 
3785
    pelmAudio->setAttribute("controller", pcszController);
3482
3786
 
3483
 
    if (   m->sv >= SettingsVersion_v1_10)
 
3787
    if (m->sv >= SettingsVersion_v1_10)
3484
3788
    {
3485
3789
        xml::ElementNode *pelmRTC = pelmHardware->createChild("RTC");
3486
 
        pelmRTC->setAttribute("localOrUTC", fRTCUseUTC ? "UTC" : "local");
 
3790
        pelmRTC->setAttribute("localOrUTC", machineUserData.fRTCUseUTC ? "UTC" : "local");
3487
3791
    }
3488
3792
 
3489
3793
    const char *pcszDriver;
3513
3817
        pelmThis->setAttribute("name", sf.strName);
3514
3818
        pelmThis->setAttribute("hostPath", sf.strHostPath);
3515
3819
        pelmThis->setAttribute("writable", sf.fWritable);
 
3820
        pelmThis->setAttribute("autoMount", sf.fAutoMount);
3516
3821
    }
3517
3822
 
3518
3823
    xml::ElementNode *pelmClip = pelmHardware->createChild("Clipboard");
3530
3835
    {
3531
3836
        xml::ElementNode *pelmIo = pelmHardware->createChild("IO");
3532
3837
        xml::ElementNode *pelmIoCache;
3533
 
        xml::ElementNode *pelmIoBandwidth;
3534
3838
 
3535
3839
        pelmIoCache = pelmIo->createChild("IoCache");
3536
3840
        pelmIoCache->setAttribute("enabled", hw.ioSettings.fIoCacheEnabled);
3537
3841
        pelmIoCache->setAttribute("size", hw.ioSettings.ulIoCacheSize);
3538
 
        pelmIoBandwidth = pelmIo->createChild("IoBandwidth");
3539
 
        pelmIoBandwidth->setAttribute("max", hw.ioSettings.ulIoBandwidthMax);
 
3842
 
 
3843
        if (m->sv >= SettingsVersion_v1_11)
 
3844
        {
 
3845
            xml::ElementNode *pelmBandwidthGroups = pelmIo->createChild("BandwidthGroups");
 
3846
            for (BandwidthGroupList::const_iterator it = hw.ioSettings.llBandwidthGroups.begin();
 
3847
                 it != hw.ioSettings.llBandwidthGroups.end();
 
3848
                 ++it)
 
3849
            {
 
3850
                const BandwidthGroup &gr = *it;
 
3851
                const char *pcszType;
 
3852
                xml::ElementNode *pelmThis = pelmBandwidthGroups->createChild("BandwidthGroup");
 
3853
                pelmThis->setAttribute("name", gr.strName);
 
3854
                switch (gr.enmType)
 
3855
                {
 
3856
                    case BandwidthGroupType_Network: pcszType = "Network"; break;
 
3857
                    default: /* BandwidthGrouptype_Disk */ pcszType = "Disk"; break;
 
3858
                }
 
3859
                pelmThis->setAttribute("type", pcszType);
 
3860
                pelmThis->setAttribute("maxMbPerSec", gr.cMaxMbPerSec);
 
3861
            }
 
3862
        }
3540
3863
    }
3541
3864
 
3542
3865
    xml::ElementNode *pelmGuest = pelmHardware->createChild("Guest");
3621
3944
                pelmPF = pelmNAT->createChild("Forwarding");
3622
3945
                if ((*rule).strName.length())
3623
3946
                    pelmPF->setAttribute("name", (*rule).strName);
3624
 
                pelmPF->setAttribute("proto", (*rule).u32Proto);
 
3947
                pelmPF->setAttribute("proto", (*rule).proto);
3625
3948
                if ((*rule).strHostIP.length())
3626
3949
                    pelmPF->setAttribute("hostip", (*rule).strHostIP);
3627
3950
                if ((*rule).u16HostPort)
3666
3989
 *   This parameter is ignored unless the settings version is at least v1.9, which
3667
3990
 *   is always the case when this gets called for OVF export.
3668
3991
 * @param pllElementsWithUuidAttributes If not NULL, must point to a list of element node
3669
 
 *   pointers to which we will append all allements that we created here that contain
 
3992
 *   pointers to which we will append all elements that we created here that contain
3670
3993
 *   UUID attributes. This allows the OVF export code to quickly replace the internal
3671
3994
 *   media UUIDs with the UUIDs of the media that were exported.
3672
3995
 */
3691
4014
            continue;
3692
4015
 
3693
4016
        xml::ElementNode *pelmController = pelmStorageControllers->createChild("StorageController");
3694
 
        com::Utf8Str name = sc.strName.raw();
3695
 
        //
 
4017
        com::Utf8Str name = sc.strName;
3696
4018
        if (m->sv < SettingsVersion_v1_8)
3697
4019
        {
3698
4020
            // pre-1.8 settings use shorter controller names, they are
3729
4051
        if (m->sv >= SettingsVersion_v1_10)
3730
4052
            pelmController->setAttribute("useHostIOCache", sc.fUseHostIOCache);
3731
4053
 
 
4054
        if (m->sv >= SettingsVersion_v1_11)
 
4055
            pelmController->setAttribute("Bootable", sc.fBootable);
 
4056
 
3732
4057
        if (sc.controllerType == StorageControllerType_IntelAhci)
3733
4058
        {
3734
4059
            pelmController->setAttribute("IDE0MasterEmulationPort", sc.lIDE0MasterEmulationPort);
3776
4101
            pelmDevice->setAttribute("port", att.lPort);
3777
4102
            pelmDevice->setAttribute("device", att.lDevice);
3778
4103
 
 
4104
            if (att.strBwGroup.length())
 
4105
                pelmDevice->setAttribute("bandwidthGroup", att.strBwGroup);
 
4106
 
3779
4107
            // attached image, if any
3780
4108
            if (    !att.uuid.isEmpty()
3781
4109
                 && (    att.deviceType == DeviceType_HardDisk
3815
4143
    pelmSnapshot->setAttribute("timeStamp", makeString(snap.timestamp));
3816
4144
 
3817
4145
    if (snap.strStateFile.length())
3818
 
        pelmSnapshot->setAttribute("stateFile", snap.strStateFile);
 
4146
        pelmSnapshot->setAttributePath("stateFile", snap.strStateFile);
3819
4147
 
3820
4148
    if (snap.strDescription.length())
3821
4149
        pelmSnapshot->createChild("Description")->addContent(snap.strDescription);
3855
4183
 *
3856
4184
 * In fl, the following flag bits are recognized:
3857
4185
 *
 
4186
 *  --  BuildMachineXML_MediaRegistry: If set, the machine's media registry will
 
4187
 *      be written, if present. This is not set when called from OVF because OVF
 
4188
 *      has its own variant of a media registry. This flag is ignored unless the
 
4189
 *      settings version is at least v1.11 (VirtualBox 4.0).
 
4190
 *
3858
4191
 *  --  BuildMachineXML_IncludeSnapshots: If set, descend into the snapshots tree
3859
4192
 *      of the machine and write out <Snapshot> and possibly more snapshots under
3860
 
 *      that, if snapshots are present. Otherwise all snapshots are suppressed.
 
4193
 *      that, if snapshots are present. Otherwise all snapshots are suppressed
 
4194
 *      (when called from OVF).
3861
4195
 *
3862
4196
 *  --  BuildMachineXML_WriteVboxVersionAttribute: If set, add a settingsVersion
3863
4197
 *      attribute to the machine tag with the vbox settings version. This is for
3866
4200
 *
3867
4201
 *  --  BuildMachineXML_SkipRemovableMedia: If set, removable media attachments
3868
4202
 *      (DVDs, floppies) are silently skipped. This is for the OVF export case
3869
 
 *      until we support copying ISO and RAW media as well.  This flas is ignored
 
4203
 *      until we support copying ISO and RAW media as well.  This flag is ignored
3870
4204
 *      unless the settings version is at least v1.9, which is always the case
3871
4205
 *      when this gets called for OVF export.
3872
4206
 *
 
4207
 * --   BuildMachineXML_SuppressSavedState: If set, the Machine/@stateFile
 
4208
 *      attribute is never set. This is also for the OVF export case because we
 
4209
 *      cannot save states with OVF.
 
4210
 *
3873
4211
 * @param elmMachine XML <Machine> element to add attributes and elements to.
3874
4212
 * @param fl Flags.
3875
4213
 * @param pllElementsWithUuidAttributes pointer to list that should receive UUID elements or NULL;
3884
4222
        setVersionAttribute(elmMachine);
3885
4223
 
3886
4224
    elmMachine.setAttribute("uuid", uuid.toStringCurly());
3887
 
    elmMachine.setAttribute("name", strName);
3888
 
    if (!fNameSync)
3889
 
        elmMachine.setAttribute("nameSync", fNameSync);
3890
 
    if (strDescription.length())
3891
 
        elmMachine.createChild("Description")->addContent(strDescription);
3892
 
    elmMachine.setAttribute("OSType", strOsType);
3893
 
    if (strStateFile.length())
3894
 
        elmMachine.setAttribute("stateFile", strStateFile);
 
4225
    elmMachine.setAttribute("name", machineUserData.strName);
 
4226
    if (!machineUserData.fNameSync)
 
4227
        elmMachine.setAttribute("nameSync", machineUserData.fNameSync);
 
4228
    if (machineUserData.strDescription.length())
 
4229
        elmMachine.createChild("Description")->addContent(machineUserData.strDescription);
 
4230
    elmMachine.setAttribute("OSType", machineUserData.strOsType);
 
4231
    if (    strStateFile.length()
 
4232
         && !(fl & BuildMachineXML_SuppressSavedState)
 
4233
       )
 
4234
        elmMachine.setAttributePath("stateFile", strStateFile);
3895
4235
    if (    (fl & BuildMachineXML_IncludeSnapshots)
3896
4236
         && !uuidCurrentSnapshot.isEmpty())
3897
4237
        elmMachine.setAttribute("currentSnapshot", uuidCurrentSnapshot.toStringCurly());
3898
 
    if (strSnapshotFolder.length())
3899
 
        elmMachine.setAttribute("snapshotFolder", strSnapshotFolder);
 
4238
 
 
4239
    if (machineUserData.strSnapshotFolder.length())
 
4240
        elmMachine.setAttributePath("snapshotFolder", machineUserData.strSnapshotFolder);
3900
4241
    if (!fCurrentStateModified)
3901
4242
        elmMachine.setAttribute("currentStateModified", fCurrentStateModified);
3902
4243
    elmMachine.setAttribute("lastStateChange", makeString(timeLastStateChange));
3903
4244
    if (fAborted)
3904
4245
        elmMachine.setAttribute("aborted", fAborted);
3905
4246
    if (    m->sv >= SettingsVersion_v1_9
3906
 
        &&  (   fTeleporterEnabled
3907
 
            ||  uTeleporterPort
3908
 
            ||  !strTeleporterAddress.isEmpty()
3909
 
            ||  !strTeleporterPassword.isEmpty()
 
4247
        &&  (   machineUserData.fTeleporterEnabled
 
4248
            ||  machineUserData.uTeleporterPort
 
4249
            ||  !machineUserData.strTeleporterAddress.isEmpty()
 
4250
            ||  !machineUserData.strTeleporterPassword.isEmpty()
3910
4251
            )
3911
4252
       )
3912
4253
    {
3913
4254
        xml::ElementNode *pelmTeleporter = elmMachine.createChild("Teleporter");
3914
 
        pelmTeleporter->setAttribute("enabled", fTeleporterEnabled);
3915
 
        pelmTeleporter->setAttribute("port", uTeleporterPort);
3916
 
        pelmTeleporter->setAttribute("address", strTeleporterAddress);
3917
 
        pelmTeleporter->setAttribute("password", strTeleporterPassword);
3918
 
    }
3919
 
 
3920
 
    writeExtraData(elmMachine, mapExtraDataItems);
 
4255
        pelmTeleporter->setAttribute("enabled", machineUserData.fTeleporterEnabled);
 
4256
        pelmTeleporter->setAttribute("port", machineUserData.uTeleporterPort);
 
4257
        pelmTeleporter->setAttribute("address", machineUserData.strTeleporterAddress);
 
4258
        pelmTeleporter->setAttribute("password", machineUserData.strTeleporterPassword);
 
4259
    }
 
4260
 
 
4261
    if (    m->sv >= SettingsVersion_v1_11
 
4262
        &&  (   machineUserData.enmFaultToleranceState != FaultToleranceState_Inactive
 
4263
            ||  machineUserData.uFaultTolerancePort
 
4264
            ||  machineUserData.uFaultToleranceInterval
 
4265
            ||  !machineUserData.strFaultToleranceAddress.isEmpty()
 
4266
            )
 
4267
       )
 
4268
    {
 
4269
        xml::ElementNode *pelmFaultTolerance = elmMachine.createChild("FaultTolerance");
 
4270
        switch (machineUserData.enmFaultToleranceState)
 
4271
        {
 
4272
        case FaultToleranceState_Inactive:
 
4273
            pelmFaultTolerance->setAttribute("state", "inactive");
 
4274
            break;
 
4275
        case FaultToleranceState_Master:
 
4276
            pelmFaultTolerance->setAttribute("state", "master");
 
4277
            break;
 
4278
        case FaultToleranceState_Standby:
 
4279
            pelmFaultTolerance->setAttribute("state", "standby");
 
4280
            break;
 
4281
        }
 
4282
 
 
4283
        pelmFaultTolerance->setAttribute("port", machineUserData.uFaultTolerancePort);
 
4284
        pelmFaultTolerance->setAttribute("address", machineUserData.strFaultToleranceAddress);
 
4285
        pelmFaultTolerance->setAttribute("interval", machineUserData.uFaultToleranceInterval);
 
4286
        pelmFaultTolerance->setAttribute("password", machineUserData.strFaultTolerancePassword);
 
4287
    }
 
4288
 
 
4289
    if (    (fl & BuildMachineXML_MediaRegistry)
 
4290
         && (m->sv >= SettingsVersion_v1_11)
 
4291
       )
 
4292
        buildMediaRegistry(elmMachine, mediaRegistry);
 
4293
 
 
4294
    buildExtraData(elmMachine, mapExtraDataItems);
3921
4295
 
3922
4296
    if (    (fl & BuildMachineXML_IncludeSnapshots)
3923
4297
         && llFirstSnapshot.size())
4024
4398
#elif defined(RT_OS_DARWIN)
4025
4399
    return AudioDriverType_CoreAudio;
4026
4400
#elif defined(RT_OS_OS2)
4027
 
    return AudioDriverType_MMP;
 
4401
    return AudioDriverType_MMPM;
4028
4402
#elif defined(RT_OS_FREEBSD)
4029
4403
    return AudioDriverType_OSS;
4030
4404
#else
4037
4411
 * This adjusts the settings version in m->sv if incompatible settings require
4038
4412
 * a settings bump, whereas otherwise we try to preserve the settings version
4039
4413
 * to avoid breaking compatibility with older versions.
 
4414
 *
 
4415
 * We do the checks in here in reverse order: newest first, oldest last, so
 
4416
 * that we avoid unnecessary checks since some of these are expensive.
4040
4417
 */
4041
4418
void MachineConfigFile::bumpSettingsVersionIfNeeded()
4042
4419
{
4043
 
    // The hardware versions other than "1" requires settings version 1.4 (2.1+).
4044
 
    if (    m->sv < SettingsVersion_v1_4
4045
 
         && hardwareMachine.strVersion != "1"
4046
 
       )
4047
 
        m->sv = SettingsVersion_v1_4;
4048
 
 
4049
 
    // "accelerate 2d video" requires settings version 1.8
4050
 
    if (    (m->sv < SettingsVersion_v1_8)
4051
 
         && (hardwareMachine.fAccelerate2DVideo)
4052
 
       )
4053
 
        m->sv = SettingsVersion_v1_8;
4054
 
 
4055
 
    // all the following require settings version 1.9
4056
 
    if (    (m->sv < SettingsVersion_v1_9)
4057
 
         && (    (hardwareMachine.firmwareType >= FirmwareType_EFI)
4058
 
              || (hardwareMachine.fHardwareVirtExclusive != HWVIRTEXCLUSIVEDEFAULT)
4059
 
              || fTeleporterEnabled
4060
 
              || uTeleporterPort
4061
 
              || !strTeleporterAddress.isEmpty()
4062
 
              || !strTeleporterPassword.isEmpty()
4063
 
              || !hardwareMachine.uuid.isEmpty()
4064
 
            )
4065
 
        )
4066
 
        m->sv = SettingsVersion_v1_9;
4067
 
 
4068
 
    // settings version 1.9 is also required if there is not exactly one DVD
 
4420
    if (m->sv < SettingsVersion_v1_11)
 
4421
    {
 
4422
        // VirtualBox 4.0 adds HD audio, CPU priorities, fault tolerance,
 
4423
        // per-machine media registries, VRDE, JRockitVE and bandwidth gorups.
 
4424
        if (    hardwareMachine.audioAdapter.controllerType == AudioControllerType_HDA
 
4425
             || hardwareMachine.ulCpuExecutionCap != 100
 
4426
             || machineUserData.enmFaultToleranceState != FaultToleranceState_Inactive
 
4427
             || machineUserData.uFaultTolerancePort
 
4428
             || machineUserData.uFaultToleranceInterval
 
4429
             || !machineUserData.strFaultToleranceAddress.isEmpty()
 
4430
             || mediaRegistry.llHardDisks.size()
 
4431
             || mediaRegistry.llDvdImages.size()
 
4432
             || mediaRegistry.llFloppyImages.size()
 
4433
             || !hardwareMachine.vrdeSettings.strVrdeExtPack.isEmpty()
 
4434
             || !hardwareMachine.vrdeSettings.strAuthLibrary.isEmpty()
 
4435
             || machineUserData.strOsType == "JRockitVE"
 
4436
             || hardwareMachine.ioSettings.llBandwidthGroups.size()
 
4437
           )
 
4438
            m->sv = SettingsVersion_v1_11;
 
4439
    }
 
4440
 
 
4441
    if (m->sv < SettingsVersion_v1_10)
 
4442
    {
 
4443
        /* If the properties contain elements other than "TCP/Ports" and "TCP/Address",
 
4444
         * then increase the version to at least VBox 3.2, which can have video channel properties.
 
4445
         */
 
4446
        unsigned cOldProperties = 0;
 
4447
 
 
4448
        StringsMap::const_iterator it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Ports");
 
4449
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4450
            cOldProperties++;
 
4451
        it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Address");
 
4452
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4453
            cOldProperties++;
 
4454
 
 
4455
        if (hardwareMachine.vrdeSettings.mapProperties.size() != cOldProperties)
 
4456
            m->sv = SettingsVersion_v1_10;
 
4457
    }
 
4458
 
 
4459
    if (m->sv < SettingsVersion_v1_11)
 
4460
    {
 
4461
        /* If the properties contain elements other than "TCP/Ports", "TCP/Address",
 
4462
         * "VideoChannel/Enabled" and "VideoChannel/Quality" then increase the version to VBox 4.0.
 
4463
         */
 
4464
        unsigned cOldProperties = 0;
 
4465
 
 
4466
        StringsMap::const_iterator it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Ports");
 
4467
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4468
            cOldProperties++;
 
4469
        it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Address");
 
4470
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4471
            cOldProperties++;
 
4472
        it = hardwareMachine.vrdeSettings.mapProperties.find("VideoChannel/Enabled");
 
4473
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4474
            cOldProperties++;
 
4475
        it = hardwareMachine.vrdeSettings.mapProperties.find("VideoChannel/Quality");
 
4476
        if (it != hardwareMachine.vrdeSettings.mapProperties.end())
 
4477
            cOldProperties++;
 
4478
 
 
4479
        if (hardwareMachine.vrdeSettings.mapProperties.size() != cOldProperties)
 
4480
            m->sv = SettingsVersion_v1_11;
 
4481
    }
 
4482
 
 
4483
    // settings version 1.9 is required if there is not exactly one DVD
4069
4484
    // or more than one floppy drive present or the DVD is not at the secondary
4070
4485
    // master; this check is a bit more complicated
4071
4486
    //
4072
4487
    // settings version 1.10 is required if the host cache should be disabled
4073
 
    if (m->sv < SettingsVersion_v1_10)
 
4488
    //
 
4489
    // settings version 1.11 is required for bandwidth limits and if more than
 
4490
    // one controller of each type is present.
 
4491
    if (m->sv < SettingsVersion_v1_11)
4074
4492
    {
 
4493
        // count attached DVDs and floppies (only if < v1.9)
4075
4494
        size_t cDVDs = 0;
4076
4495
        size_t cFloppies = 0;
4077
4496
 
4078
 
        // need to run thru all the storage controllers to figure this out
 
4497
        // count storage controllers (if < v1.11)
 
4498
        size_t cSata = 0;
 
4499
        size_t cScsiLsi = 0;
 
4500
        size_t cScsiBuslogic = 0;
 
4501
        size_t cSas = 0;
 
4502
        size_t cIde = 0;
 
4503
        size_t cFloppy = 0;
 
4504
 
 
4505
        // need to run thru all the storage controllers and attached devices to figure this out
4079
4506
        for (StorageControllersList::const_iterator it = storageMachine.llStorageControllers.begin();
4080
4507
             it != storageMachine.llStorageControllers.end();
4081
4508
             ++it)
4082
4509
        {
4083
4510
            const StorageController &sctl = *it;
 
4511
 
 
4512
            // count storage controllers of each type; 1.11 is required if more than one
 
4513
            // controller of one type is present
 
4514
            switch (sctl.storageBus)
 
4515
            {
 
4516
                case StorageBus_IDE:
 
4517
                    cIde++;
 
4518
                    break;
 
4519
                case StorageBus_SATA:
 
4520
                    cSata++;
 
4521
                    break;
 
4522
                case StorageBus_SAS:
 
4523
                    cSas++;
 
4524
                    break;
 
4525
                case StorageBus_SCSI:
 
4526
                    if (sctl.controllerType == StorageControllerType_LsiLogic)
 
4527
                        cScsiLsi++;
 
4528
                    else
 
4529
                        cScsiBuslogic++;
 
4530
                    break;
 
4531
                case StorageBus_Floppy:
 
4532
                    cFloppy++;
 
4533
                    break;
 
4534
                default:
 
4535
                    // Do nothing
 
4536
                    break;
 
4537
            }
 
4538
 
 
4539
            if (   cSata > 1
 
4540
                || cScsiLsi > 1
 
4541
                || cScsiBuslogic > 1
 
4542
                || cSas > 1
 
4543
                || cIde > 1
 
4544
                || cFloppy > 1)
 
4545
            {
 
4546
                m->sv = SettingsVersion_v1_11;
 
4547
                break; // abort the loop -- we will not raise the version further
 
4548
            }
 
4549
 
4084
4550
            for (AttachedDevicesList::const_iterator it2 = sctl.llAttachedDevices.begin();
4085
4551
                 it2 != sctl.llAttachedDevices.end();
4086
4552
                 ++it2)
4087
4553
            {
 
4554
                const AttachedDevice &att = *it2;
 
4555
 
 
4556
                // Bandwidth limitations are new in VirtualBox 4.0 (1.11)
 
4557
                if (m->sv < SettingsVersion_v1_11)
 
4558
                {
 
4559
                    if (att.strBwGroup.length() != 0)
 
4560
                    {
 
4561
                        m->sv = SettingsVersion_v1_11;
 
4562
                        break; // abort the loop -- we will not raise the version further
 
4563
                    }
 
4564
                }
 
4565
 
 
4566
                // disabling the host IO cache requires settings version 1.10
 
4567
                if (    (m->sv < SettingsVersion_v1_10)
 
4568
                     && (!sctl.fUseHostIOCache)
 
4569
                   )
 
4570
                    m->sv = SettingsVersion_v1_10;
 
4571
 
4088
4572
                // we can only write the StorageController/@Instance attribute with v1.9
4089
 
                if (sctl.ulInstance != 0)
4090
 
                {
4091
 
                    if (m->sv < SettingsVersion_v1_9)
4092
 
                        m->sv = SettingsVersion_v1_9;
4093
 
                }
 
4573
                if (    (m->sv < SettingsVersion_v1_9)
 
4574
                     && (sctl.ulInstance != 0)
 
4575
                   )
 
4576
                    m->sv = SettingsVersion_v1_9;
4094
4577
 
4095
 
                const AttachedDevice &att = *it2;
4096
 
                if (att.deviceType == DeviceType_DVD)
 
4578
                if (m->sv < SettingsVersion_v1_9)
4097
4579
                {
4098
 
                    if (    (sctl.storageBus != StorageBus_IDE) // DVD at bus other than DVD?
4099
 
                         || (att.lPort != 1)                    // DVDs not at secondary master?
4100
 
                         || (att.lDevice != 0)
4101
 
                       )
 
4580
                    if (att.deviceType == DeviceType_DVD)
4102
4581
                    {
4103
 
                        if (m->sv < SettingsVersion_v1_9)
 
4582
                         if (    (sctl.storageBus != StorageBus_IDE) // DVD at bus other than DVD?
 
4583
                              || (att.lPort != 1)                    // DVDs not at secondary master?
 
4584
                              || (att.lDevice != 0)
 
4585
                            )
4104
4586
                            m->sv = SettingsVersion_v1_9;
 
4587
 
 
4588
                        ++cDVDs;
4105
4589
                    }
4106
 
 
4107
 
                    ++cDVDs;
4108
 
                }
4109
 
                else if (att.deviceType == DeviceType_Floppy)
4110
 
                    ++cFloppies;
4111
 
 
4112
 
                // Disabling the host IO cache requires settings version 1.10
4113
 
                if (!sctl.fUseHostIOCache)
4114
 
                {
4115
 
                    m->sv = SettingsVersion_v1_10;
4116
 
                    break; /* abort the loop -- we will not raise the version further */
 
4590
                    else if (att.deviceType == DeviceType_Floppy)
 
4591
                        ++cFloppies;
4117
4592
                }
4118
4593
            }
 
4594
 
 
4595
            if (m->sv >= SettingsVersion_v1_11)
 
4596
                break;  // abort the loop -- we will not raise the version further
4119
4597
        }
4120
4598
 
4121
4599
        // VirtualBox before 3.1 had zero or one floppy and exactly one DVD,
4128
4606
            m->sv = SettingsVersion_v1_9;
4129
4607
    }
4130
4608
 
4131
 
    // VirtualBox 3.2 adds support for CPU hotplug, RTC timezone control, HID type and HPET
4132
 
    if (    m->sv < SettingsVersion_v1_10
4133
 
         && (    fRTCUseUTC
4134
 
              || hardwareMachine.fCpuHotPlug
4135
 
              || hardwareMachine.pointingHidType != PointingHidType_PS2Mouse
4136
 
              || hardwareMachine.keyboardHidType != KeyboardHidType_PS2Keyboard
4137
 
              || hardwareMachine.fHpetEnabled
4138
 
            )
4139
 
       )
4140
 
        m->sv = SettingsVersion_v1_10;
4141
 
 
4142
 
    // VirtualBox 3.2 adds support for page fusion
4143
 
    if (    m->sv < SettingsVersion_v1_10
4144
 
        &&  hardwareMachine.fPageFusionEnabled
4145
 
       )
4146
 
        m->sv = SettingsVersion_v1_10;
4147
 
 
4148
 
    // VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main.
 
4609
    // VirtualBox 3.2: Check for non default I/O settings
 
4610
    if (m->sv < SettingsVersion_v1_10)
 
4611
    {
 
4612
        if (   (hardwareMachine.ioSettings.fIoCacheEnabled != true)
 
4613
            || (hardwareMachine.ioSettings.ulIoCacheSize != 5)
 
4614
                // and page fusion
 
4615
            || (hardwareMachine.fPageFusionEnabled)
 
4616
                // and CPU hotplug, RTC timezone control, HID type and HPET
 
4617
            || machineUserData.fRTCUseUTC
 
4618
            || hardwareMachine.fCpuHotPlug
 
4619
            || hardwareMachine.pointingHidType != PointingHidType_PS2Mouse
 
4620
            || hardwareMachine.keyboardHidType != KeyboardHidType_PS2Keyboard
 
4621
            || hardwareMachine.fHpetEnabled
 
4622
           )
 
4623
            m->sv = SettingsVersion_v1_10;
 
4624
    }
 
4625
 
 
4626
    // VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main
4149
4627
    if (m->sv < SettingsVersion_v1_10)
4150
4628
    {
4151
4629
        NetworkAdaptersList::const_iterator netit;
4152
4630
        for (netit = hardwareMachine.llNetworkAdapters.begin();
4153
 
             netit != hardwareMachine.llNetworkAdapters.end(); ++netit)
 
4631
             netit != hardwareMachine.llNetworkAdapters.end();
 
4632
             ++netit)
4154
4633
        {
4155
 
            if (    netit->fEnabled
4156
 
                 && netit->mode == NetworkAttachmentType_NAT
4157
 
                 && (   netit->nat.u32Mtu != 0
4158
 
                     || netit->nat.u32SockRcv != 0
4159
 
                     || netit->nat.u32SockSnd != 0
4160
 
                     || netit->nat.u32TcpRcv != 0
4161
 
                     || netit->nat.u32TcpSnd != 0
4162
 
                     || !netit->nat.fDnsPassDomain
4163
 
                     || netit->nat.fDnsProxy
4164
 
                     || netit->nat.fDnsUseHostResolver
4165
 
                     || netit->nat.fAliasLog
4166
 
                     || netit->nat.fAliasProxyOnly
4167
 
                     || netit->nat.fAliasUseSamePorts
4168
 
                     || netit->nat.strTftpPrefix.length()
4169
 
                     || netit->nat.strTftpBootFile.length()
4170
 
                     || netit->nat.strTftpNextServer.length()
4171
 
                     || netit->nat.llRules.size())
4172
 
                )
4173
 
            {
4174
 
                m->sv = SettingsVersion_v1_10;
4175
 
                break;
4176
 
            }
4177
 
            if (    netit->fEnabled
4178
 
                 && netit->ulBootPriority != 0)
4179
 
            {
4180
 
                m->sv = SettingsVersion_v1_10;
4181
 
                break;
 
4634
            if (    (m->sv < SettingsVersion_v1_11)
 
4635
                 && (netit->ulBandwidthLimit)
 
4636
               )
 
4637
            {
 
4638
                /* New in VirtualBox 4.0 */
 
4639
                m->sv = SettingsVersion_v1_11;
 
4640
                break;
 
4641
            }
 
4642
            else if (    (m->sv < SettingsVersion_v1_10)
 
4643
                      && (netit->fEnabled)
 
4644
                      && (netit->mode == NetworkAttachmentType_NAT)
 
4645
                      && (   netit->nat.u32Mtu != 0
 
4646
                          || netit->nat.u32SockRcv != 0
 
4647
                          || netit->nat.u32SockSnd != 0
 
4648
                          || netit->nat.u32TcpRcv != 0
 
4649
                          || netit->nat.u32TcpSnd != 0
 
4650
                          || !netit->nat.fDnsPassDomain
 
4651
                          || netit->nat.fDnsProxy
 
4652
                          || netit->nat.fDnsUseHostResolver
 
4653
                          || netit->nat.fAliasLog
 
4654
                          || netit->nat.fAliasProxyOnly
 
4655
                          || netit->nat.fAliasUseSamePorts
 
4656
                          || netit->nat.strTftpPrefix.length()
 
4657
                          || netit->nat.strTftpBootFile.length()
 
4658
                          || netit->nat.strTftpNextServer.length()
 
4659
                          || netit->nat.llRules.size()
 
4660
                         )
 
4661
                     )
 
4662
            {
 
4663
                m->sv = SettingsVersion_v1_10;
 
4664
                // no break because we still might need v1.11 above
 
4665
            }
 
4666
            else if (    (m->sv < SettingsVersion_v1_10)
 
4667
                      && (netit->fEnabled)
 
4668
                      && (netit->ulBootPriority != 0)
 
4669
                    )
 
4670
            {
 
4671
                m->sv = SettingsVersion_v1_10;
 
4672
                // no break because we still might need v1.11 above
4182
4673
            }
4183
4674
        }
4184
4675
    }
4185
 
    // Check for non default I/O settings and bump the settings version.
4186
 
    if (m->sv < SettingsVersion_v1_10)
4187
 
    {
4188
 
        if (   hardwareMachine.ioSettings.fIoCacheEnabled != true
4189
 
            || hardwareMachine.ioSettings.ulIoCacheSize != 5
4190
 
            || hardwareMachine.ioSettings.ulIoBandwidthMax != 0)
4191
 
            m->sv = SettingsVersion_v1_10;
4192
 
    }
4193
4676
 
4194
 
    // VirtualBox 3.2 adds support for VRDP video channel
4195
 
    if (    m->sv < SettingsVersion_v1_10
4196
 
         && (    hardwareMachine.vrdpSettings.fVideoChannel
 
4677
    // all the following require settings version 1.9
 
4678
    if (    (m->sv < SettingsVersion_v1_9)
 
4679
         && (    (hardwareMachine.firmwareType >= FirmwareType_EFI)
 
4680
              || (hardwareMachine.fHardwareVirtExclusive != HWVIRTEXCLUSIVEDEFAULT)
 
4681
              || machineUserData.fTeleporterEnabled
 
4682
              || machineUserData.uTeleporterPort
 
4683
              || !machineUserData.strTeleporterAddress.isEmpty()
 
4684
              || !machineUserData.strTeleporterPassword.isEmpty()
 
4685
              || !hardwareMachine.uuid.isEmpty()
4197
4686
            )
4198
 
       )
4199
 
        m->sv = SettingsVersion_v1_10;
4200
 
 
 
4687
        )
 
4688
        m->sv = SettingsVersion_v1_9;
 
4689
 
 
4690
    // "accelerate 2d video" requires settings version 1.8
 
4691
    if (    (m->sv < SettingsVersion_v1_8)
 
4692
         && (hardwareMachine.fAccelerate2DVideo)
 
4693
       )
 
4694
        m->sv = SettingsVersion_v1_8;
 
4695
 
 
4696
    // The hardware versions other than "1" requires settings version 1.4 (2.1+).
 
4697
    if (    m->sv < SettingsVersion_v1_4
 
4698
         && hardwareMachine.strVersion != "1"
 
4699
       )
 
4700
        m->sv = SettingsVersion_v1_4;
4201
4701
}
4202
4702
 
4203
4703
/**
4219
4719
 
4220
4720
        xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine");
4221
4721
        buildMachineXML(*pelmMachine,
4222
 
                        MachineConfigFile::BuildMachineXML_IncludeSnapshots,
 
4722
                          MachineConfigFile::BuildMachineXML_IncludeSnapshots
 
4723
                        | MachineConfigFile::BuildMachineXML_MediaRegistry,
4223
4724
                            // but not BuildMachineXML_WriteVboxVersionAttribute
4224
4725
                        NULL); /* pllElementsWithUuidAttributes */
4225
4726
 
4236
4737
        throw;
4237
4738
    }
4238
4739
}
4239