VirtualBox

Changeset 6076 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Dec 14, 2007 7:23:03 PM (17 years ago)
Author:
vboxsync
Message:

Merged dmik/s2 branch (r25959:26751) to the trunk.

Location:
trunk/src/VBox/Main
Files:
2 added
1 deleted
46 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/AudioAdapterImpl.cpp

    r6056 r6076  
    272272
    273273/**
     274 *  Loads settings from the given machine node.
     275 *  May be called once right after this object creation.
     276 *
     277 *  @param aMachineNode <Machine> node.
     278 *
     279 *  @note Locks this object for writing.
     280 */
     281HRESULT AudioAdapter::loadSettings (const settings::Key &aMachineNode)
     282{
     283    using namespace settings;
     284
     285    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     286
     287    AutoCaller autoCaller (this);
     288    AssertComRCReturnRC (autoCaller.rc());
     289
     290    AutoLock alock (this);
     291
     292    /* Note: we assume that the default values for attributes of optional
     293     * nodes are assigned in the Data::Data() constructor and don't do it
     294     * here. It implies that this method may only be called after constructing
     295     * a new BIOSSettings object while all its data fields are in the default
     296     * values. Exceptions are fields whose creation time defaults don't match
     297     * values that should be applied when these fields are not explicitly set
     298     * in the settings file (for backwards compatibility reasons). This takes
     299     * place when a setting of a newly created object must default to A while
     300     * the same setting of an object loaded from the old settings file must
     301     * default to B. */
     302
     303    /* AudioAdapter node (required) */
     304    Key audioAdapterNode = aMachineNode.key ("AudioAdapter");
     305
     306    /* is the adapter enabled? (required) */
     307    mData->mEnabled = audioAdapterNode.value <bool> ("enabled");
     308
     309    /* now check the audio driver (required) */
     310    const char *driver = audioAdapterNode.stringValue ("driver");
     311    mData->mAudioDriver = AudioDriverType_NullAudioDriver;
     312    if      (strcmp (driver, "null") == 0)
     313        ; /* Null has been set above */
     314#ifdef RT_OS_WINDOWS
     315    else if (strcmp (driver, "winmm") == 0)
     316#ifdef VBOX_WITH_WINMM
     317        mData->mAudioDriver = AudioDriverType_WINMMAudioDriver;
     318#else
     319        /* fall back to dsound */
     320        mData->mAudioDriver = AudioDriverType_DSOUNDAudioDriver;
     321#endif
     322    else if (strcmp (driver, "dsound") == 0)
     323        mData->mAudioDriver = AudioDriverType_DSOUNDAudioDriver;
     324#endif // RT_OS_WINDOWS
     325#ifdef RT_OS_LINUX
     326    else if (strcmp (driver, "oss") == 0)
     327        mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
     328    else if (strcmp (driver, "alsa") == 0)
     329# ifdef VBOX_WITH_ALSA
     330        mData->mAudioDriver = AudioDriverType_ALSAAudioDriver;
     331# else
     332        /* fall back to OSS */
     333        mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
     334# endif
     335    else if (strcmp (driver, "pulse") == 0)
     336# ifdef VBOX_WITH_PULSE
     337        mData->mAudioDriver = AudioDriverType_PulseAudioDriver;
     338# else
     339        /* fall back to OSS */
     340        mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
     341# endif
     342#endif // RT_OS_LINUX
     343#ifdef RT_OS_DARWIN
     344    else if (strcmp (driver, "coreaudio") == 0)
     345        mData->mAudioDriver = AudioDriverType_CoreAudioDriver;
     346#endif
     347#ifdef RT_OS_OS2
     348    else if (strcmp (driver, "mmpm") == 0)
     349        mData->mAudioDriver = AudioDriverType_MMPMAudioDriver;
     350#endif
     351    else
     352        AssertMsgFailed (("Invalid driver '%s'\n", driver));
     353
     354    return S_OK;
     355}
     356
     357/**
     358 *  Saves settings to the given machine node.
     359 *
     360 *  @param aMachineNode <Machine> node.
     361 *
     362 *  @note Locks this object for reading.
     363 */
     364HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode)
     365{
     366    using namespace settings;
     367
     368    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     369
     370    AutoCaller autoCaller (this);
     371    AssertComRCReturnRC (autoCaller.rc());
     372
     373    AutoReaderLock alock (this);
     374
     375    Key node = aMachineNode.createKey ("AudioAdapter");
     376
     377    const char *driverStr = NULL;
     378    switch (mData->mAudioDriver)
     379    {
     380        case AudioDriverType_NullAudioDriver:
     381        {
     382            driverStr = "null";
     383            break;
     384        }
     385#ifdef RT_OS_WINDOWS
     386            case AudioDriverType_WINMMAudioDriver:
     387# ifdef VBOX_WITH_WINMM
     388            {
     389                driverStr = "winmm";
     390                break;
     391            }
     392# endif
     393            case AudioDriverType_DSOUNDAudioDriver:
     394            {
     395                driverStr = "dsound";
     396                break;
     397            }
     398#endif /* RT_OS_WINDOWS */
     399#ifdef RT_OS_LINUX
     400            case AudioDriverType_ALSAAudioDriver:
     401# ifdef VBOX_WITH_ALSA
     402            {
     403                driverStr = "alsa";
     404                break;
     405            }
     406# endif
     407            case AudioDriverType_PulseAudioDriver:
     408# ifdef VBOX_WITH_PULSE
     409            {
     410                driverStr = "pulse";
     411                break;
     412            }
     413# endif
     414            case AudioDriverType_OSSAudioDriver:
     415            {
     416                driverStr = "oss";
     417                break;
     418            }
     419#endif /* RT_OS_LINUX */
     420#ifdef RT_OS_DARWIN
     421            case AudioDriverType_CoreAudioDriver:
     422            {
     423                driverStr = "coreaudio";
     424                break;
     425            }
     426#endif
     427#ifdef RT_OS_OS2
     428            case AudioDriverType_MMPMAudioDriver:
     429            {
     430                driverStr = "mmpm";
     431                break;
     432            }
     433#endif
     434            default:
     435                ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d\n",
     436                                        mData->mAudioDriver),
     437                                       E_FAIL);
     438    }
     439    node.setStringValue ("driver", driverStr);
     440
     441    node.setValue <bool> ("enabled", !!mData->mEnabled);
     442
     443    return S_OK;
     444}
     445
     446/**
    274447 *  @note Locks this object for writing.
    275448 */
  • trunk/src/VBox/Main/BIOSSettingsImpl.cpp

    r5999 r6076  
    489489/////////////////////////////////////////////////////////////////////////////
    490490
     491/**
     492 *  Loads settings from the given machine node.
     493 *  May be called once right after this object creation.
     494 *
     495 *  @param aMachineNode <Machine> node.
     496 *
     497 *  @note Locks this object for writing.
     498 */
     499HRESULT BIOSSettings::loadSettings (const settings::Key &aMachineNode)
     500{
     501    using namespace settings;
     502
     503    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     504
     505    AutoCaller autoCaller (this);
     506    AssertComRCReturnRC (autoCaller.rc());
     507
     508    AutoLock alock (this);
     509
     510    /* Note: we assume that the default values for attributes of optional
     511     * nodes are assigned in the Data::Data() constructor and don't do it
     512     * here. It implies that this method may only be called after constructing
     513     * a new BIOSSettings object while all its data fields are in the default
     514     * values. Exceptions are fields whose creation time defaults don't match
     515     * values that should be applied when these fields are not explicitly set
     516     * in the settings file (for backwards compatibility reasons). This takes
     517     * place when a setting of a newly created object must default to A while
     518     * the same setting of an object loaded from the old settings file must
     519     * default to B. */
     520
     521    /* BIOS node (required) */
     522    Key biosNode = aMachineNode.key ("BIOS");
     523
     524    /* ACPI (required) */
     525    {
     526        Key acpiNode = biosNode.key ("ACPI");
     527
     528        mData->mACPIEnabled = acpiNode.value <bool> ("enabled");
     529    }
     530
     531    /* IOAPIC (optional) */
     532    {
     533        Key ioapicNode = biosNode.findKey ("IOAPIC");
     534        if (!ioapicNode.isNull())
     535            mData->mIOAPICEnabled = ioapicNode.value <bool> ("enabled");
     536    }
     537
     538    /* Logo (optional) */
     539    {
     540        Key logoNode = biosNode.findKey ("Logo");
     541        if (!logoNode.isNull())
     542        {
     543            mData->mLogoFadeIn = logoNode.value <bool> ("fadeIn");
     544            mData->mLogoFadeOut = logoNode.value <bool> ("fadeOut");
     545            mData->mLogoDisplayTime = logoNode.value <ULONG> ("displayTime");
     546            mData->mLogoImagePath = logoNode.stringValue ("imagePath");
     547        }
     548    }
     549
     550    /* boot menu (optional) */
     551    {
     552        Key bootMenuNode = biosNode.findKey ("BootMenu");
     553        if (!bootMenuNode.isNull())
     554        {
     555            mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
     556            const char *modeStr = bootMenuNode.stringValue ("mode");
     557
     558            if (strcmp (modeStr, "disabled") == 0)
     559                mData->mBootMenuMode = BIOSBootMenuMode_Disabled;
     560            else if (strcmp (modeStr, "menuonly") == 0)
     561                mData->mBootMenuMode = BIOSBootMenuMode_MenuOnly;
     562            else if (strcmp (modeStr, "messageandmenu") == 0)
     563                mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
     564            else
     565                ComAssertMsgFailedRet (("Invalid boot menu mode '%s'\n", modeStr),
     566                                       E_FAIL);
     567        }
     568    }
     569
     570    /* PXE debug logging (optional) */
     571    {
     572        Key pxedebugNode = biosNode.findKey ("PXEDebug");
     573        if (!pxedebugNode.isNull())
     574            mData->mPXEDebugEnabled = pxedebugNode.value <bool> ("enabled");
     575    }
     576
     577    /* time offset (optional) */
     578    {
     579        Key timeOffsetNode = biosNode.findKey ("TimeOffset");
     580        if (!timeOffsetNode.isNull())
     581            mData->mTimeOffset = timeOffsetNode.value <LONG64> ("value");
     582    }
     583
     584    /* IDE controller type (optional, for old machines that lack this node,
     585     * defaults to PIIX3) */
     586    {
     587        mData->mIDEControllerType = IDEControllerType_IDEControllerPIIX3;
     588
     589        Key ideControllerNode = biosNode.findKey ("IDEController");
     590        if (!ideControllerNode.isNull())
     591        {
     592            const char *typeStr = ideControllerNode.stringValue ("type");
     593            if (strcmp (typeStr, "PIIX3") == 0)
     594                mData->mIDEControllerType = IDEControllerType_IDEControllerPIIX3;
     595            else if (strcmp (typeStr, "PIIX4") == 0)
     596                mData->mIDEControllerType = IDEControllerType_IDEControllerPIIX4;
     597            else
     598                ComAssertMsgFailedRet (("Invalid boot menu mode '%s'\n", typeStr),
     599                                       E_FAIL);
     600        }
     601    }
     602
     603    return S_OK;
     604}
     605
     606/**
     607 *  Saves settings to the given machine node.
     608 *
     609 *  @param aMachineNode <Machine> node.
     610 *
     611 *  @note Locks this object for reading.
     612 */
     613HRESULT BIOSSettings::saveSettings (settings::Key &aMachineNode)
     614{
     615    using namespace settings;
     616
     617    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     618
     619    AutoCaller autoCaller (this);
     620    AssertComRCReturnRC (autoCaller.rc());
     621
     622    AutoReaderLock alock (this);
     623
     624    Key biosNode = aMachineNode.createKey ("BIOS");
     625
     626    /* ACPI */
     627    {
     628        Key acpiNode = biosNode.createKey ("ACPI");
     629        acpiNode.setValue <bool> ("enabled", !!mData->mACPIEnabled);
     630    }
     631
     632    /* IOAPIC */
     633    {
     634        Key ioapicNode = biosNode.createKey ("IOAPIC");
     635        ioapicNode.setValue <bool> ("enabled", !!mData->mIOAPICEnabled);
     636    }
     637
     638    /* BIOS logo (optional) **/
     639    {
     640        Key logoNode = biosNode.createKey ("Logo");
     641        logoNode.setValue <bool> ("fadeIn", !!mData->mLogoFadeIn);
     642        logoNode.setValue <bool> ("fadeOut", !!mData->mLogoFadeOut);
     643        logoNode.setValue <ULONG> ("displayTime", mData->mLogoDisplayTime);
     644        logoNode.setValueOr <Bstr> ("imagePath", mData->mLogoImagePath, Bstr::Null);
     645    }
     646
     647    /* boot menu (optional) */
     648    {
     649        Key bootMenuNode = biosNode.createKey ("BootMenu");
     650        const char *modeStr = NULL;
     651        switch (mData->mBootMenuMode)
     652        {
     653            case BIOSBootMenuMode_Disabled:
     654                modeStr = "disabled";
     655                break;
     656            case BIOSBootMenuMode_MenuOnly:
     657                modeStr = "menuonly";
     658                break;
     659            case BIOSBootMenuMode_MessageAndMenu:
     660                modeStr = "messageandmenu";
     661                break;
     662            default:
     663                ComAssertMsgFailedRet (("Invalid boot menu type: %d\n",
     664                                        mData->mBootMenuMode),
     665                                       E_FAIL);
     666        }
     667        bootMenuNode.setStringValue ("mode", modeStr);
     668    }
     669
     670    /* time offset (optional) */
     671    {
     672        Key timeOffsetNode = biosNode.createKey ("TimeOffset");
     673        timeOffsetNode.setValue <LONG64> ("value", mData->mTimeOffset);
     674    }
     675
     676    /* PXE debug flag (optional) */
     677    {
     678        Key pxedebugNode = biosNode.createKey ("PXEDebug");
     679        pxedebugNode.setValue <bool> ("enabled", !!mData->mPXEDebugEnabled);
     680    }
     681
     682    /* IDE controller type */
     683    {
     684        Key ideControllerNode = biosNode.createKey ("IDEController");
     685        const char *ideControllerTypeStr = NULL;
     686        switch (mData->mIDEControllerType)
     687        {
     688            case IDEControllerType_IDEControllerPIIX3:
     689                ideControllerTypeStr = "PIIX3";
     690                break;
     691            case IDEControllerType_IDEControllerPIIX4:
     692                ideControllerTypeStr = "PIIX4";
     693                break;
     694            default:
     695                ComAssertMsgFailedRet (("Invalid IDE Controller type: %d\n",
     696                                        mData->mIDEControllerType),
     697                                       E_FAIL);
     698        }
     699        ideControllerNode.setStringValue ("type", ideControllerTypeStr);
     700    }
     701
     702    return S_OK;
     703}
     704
    491705void BIOSSettings::commit()
    492706{
  • trunk/src/VBox/Main/DVDDriveImpl.cpp

    r5999 r6076  
    1818#include "DVDDriveImpl.h"
    1919#include "MachineImpl.h"
     20#include "HostImpl.h"
     21#include "HostDVDDriveImpl.h"
    2022#include "VirtualBoxImpl.h"
     23
    2124#include "Logging.h"
    2225
     
    347350// public methods only for internal purposes
    348351////////////////////////////////////////////////////////////////////////////////
     352
     353/**
     354 *  Loads settings from the given machine node.
     355 *  May be called once right after this object creation.
     356 *
     357 *  @param aMachineNode <Machine> node.
     358 *
     359 *  @note Locks this object for writing.
     360 */
     361HRESULT DVDDrive::loadSettings (const settings::Key &aMachineNode)
     362{
     363    using namespace settings;
     364
     365    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     366
     367    AutoCaller autoCaller (this);
     368    AssertComRCReturnRC (autoCaller.rc());
     369
     370    AutoLock alock (this);
     371
     372    /* Note: we assume that the default values for attributes of optional
     373     * nodes are assigned in the Data::Data() constructor and don't do it
     374     * here. It implies that this method may only be called after constructing
     375     * a new BIOSSettings object while all its data fields are in the default
     376     * values. Exceptions are fields whose creation time defaults don't match
     377     * values that should be applied when these fields are not explicitly set
     378     * in the settings file (for backwards compatibility reasons). This takes
     379     * place when a setting of a newly created object must default to A while
     380     * the same setting of an object loaded from the old settings file must
     381     * default to B. */
     382
     383    HRESULT rc = S_OK;
     384
     385    /* DVD drive (required, contains either Image or HostDrive or nothing) */
     386    Key dvdDriveNode = aMachineNode.key ("DVDDrive");
     387
     388    /* optional, defaults to false */
     389    mData->mPassthrough = dvdDriveNode.value <bool> ("passthrough");
     390
     391    Key typeNode;
     392
     393    if (!(typeNode = dvdDriveNode.findKey ("Image")).isNull())
     394    {
     395        Guid uuid = typeNode.value <Guid> ("uuid");
     396        rc = MountImage (uuid);
     397        CheckComRCReturnRC (rc);
     398    }
     399    else if (!(typeNode = dvdDriveNode.findKey ("HostDrive")).isNull())
     400    {
     401
     402        Bstr src = typeNode.stringValue ("src");
     403
     404        /* find the correspoding object */
     405        ComObjPtr <Host> host = mParent->virtualBox()->host();
     406
     407        ComPtr <IHostDVDDriveCollection> coll;
     408        rc = host->COMGETTER(DVDDrives) (coll.asOutParam());
     409        AssertComRC (rc);
     410
     411        ComPtr <IHostDVDDrive> drive;
     412        rc = coll->FindByName (src, drive.asOutParam());
     413        if (SUCCEEDED (rc))
     414        {
     415            rc = CaptureHostDrive (drive);
     416            CheckComRCReturnRC (rc);
     417        }
     418        else if (rc == E_INVALIDARG)
     419        {
     420            /* the host DVD drive is not currently available. we
     421             * assume it will be available later and create an
     422             * extra object now */
     423            ComObjPtr <HostDVDDrive> hostDrive;
     424            hostDrive.createObject();
     425            rc = hostDrive->init (src);
     426            AssertComRC (rc);
     427            rc = CaptureHostDrive (hostDrive);
     428            CheckComRCReturnRC (rc);
     429        }
     430        else
     431            AssertComRC (rc);
     432    }
     433
     434    return S_OK;
     435}
     436
     437/**
     438 *  Saves settings to the given machine node.
     439 *
     440 *  @param aMachineNode <Machine> node.
     441 *
     442 *  @note Locks this object for reading.
     443 */
     444HRESULT DVDDrive::saveSettings (settings::Key &aMachineNode)
     445{
     446    using namespace settings;
     447
     448    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     449
     450    AutoCaller autoCaller (this);
     451    AssertComRCReturnRC (autoCaller.rc());
     452
     453    AutoReaderLock alock (this);
     454
     455    Key node = aMachineNode.createKey ("DVDDrive");
     456
     457    node.setValue <bool> ("passthrough", !!mData->mPassthrough);
     458
     459    switch (mData->mDriveState)
     460    {
     461        case DriveState_ImageMounted:
     462        {
     463            Assert (!mData->mDVDImage.isNull());
     464
     465            Guid id;
     466            HRESULT rc = mData->mDVDImage->COMGETTER(Id) (id.asOutParam());
     467            AssertComRC (rc);
     468            Assert (!id.isEmpty());
     469
     470            Key imageNode = node.createKey ("Image");
     471            imageNode.setValue <Guid> ("uuid", id);
     472            break;
     473        }
     474        case DriveState_HostDriveCaptured:
     475        {
     476            Assert (!mData->mHostDrive.isNull());
     477
     478            Bstr name;
     479            HRESULT  rc = mData->mHostDrive->COMGETTER(Name) (name.asOutParam());
     480            AssertComRC (rc);
     481            Assert (!name.isEmpty());
     482
     483            Key hostDriveNode = node.createKey ("HostDrive");
     484            hostDriveNode.setValue <Bstr> ("src", name);
     485            break;
     486        }
     487        case DriveState_NotMounted:
     488            /* do nothing, i.e.leave the drive node empty */
     489            break;
     490        default:
     491            ComAssertMsgFailedRet (("Invalid drive state: %d\n",
     492                                      mData->mDriveState),
     493                                     E_FAIL);
     494    }
     495
     496    return S_OK;
     497}
    349498
    350499/**
  • trunk/src/VBox/Main/Doxyfile.Main

    r1 r6076  
    982982    CFGMGCDECL \
    983983    CFGMDECL \
    984     CFGLDRR3DECL \
    985984    EMR3DECL \
    986985    EMR0DECL \
  • trunk/src/VBox/Main/FloppyDriveImpl.cpp

    r5999 r6076  
    1818#include "FloppyDriveImpl.h"
    1919#include "MachineImpl.h"
     20#include "HostImpl.h"
     21#include "HostFloppyDriveImpl.h"
    2022#include "VirtualBoxImpl.h"
     23
    2124#include "Logging.h"
    2225
     
    354357// public methods only for internal purposes
    355358/////////////////////////////////////////////////////////////////////////////
     359
     360/**
     361 *  Loads settings from the given machine node.
     362 *  May be called once right after this object creation.
     363 *
     364 *  @param aMachineNode <Machine> node.
     365 *
     366 *  @note Locks this object for writing.
     367 */
     368HRESULT FloppyDrive::loadSettings (const settings::Key &aMachineNode)
     369{
     370    using namespace settings;
     371
     372    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     373
     374    AutoCaller autoCaller (this);
     375    AssertComRCReturnRC (autoCaller.rc());
     376
     377    AutoLock alock (this);
     378
     379    /* Note: we assume that the default values for attributes of optional
     380     * nodes are assigned in the Data::Data() constructor and don't do it
     381     * here. It implies that this method may only be called after constructing
     382     * a new BIOSSettings object while all its data fields are in the default
     383     * values. Exceptions are fields whose creation time defaults don't match
     384     * values that should be applied when these fields are not explicitly set
     385     * in the settings file (for backwards compatibility reasons). This takes
     386     * place when a setting of a newly created object must default to A while
     387     * the same setting of an object loaded from the old settings file must
     388     * default to B. */
     389
     390    HRESULT rc = S_OK;
     391
     392    /* Floppy drive (required, contains either Image or HostDrive or nothing) */
     393    Key floppyDriveNode = aMachineNode.key ("FloppyDrive");
     394
     395    /* optional, defaults to true */
     396    mData->mEnabled = floppyDriveNode.value <bool> ("enabled");
     397
     398    Key typeNode;
     399
     400    if (!(typeNode = floppyDriveNode.findKey ("Image")).isNull())
     401    {
     402        Guid uuid = typeNode.value <Guid> ("uuid");
     403        rc = MountImage (uuid);
     404        CheckComRCReturnRC (rc);
     405    }
     406    else if (!(typeNode = floppyDriveNode.findKey ("HostDrive")).isNull())
     407    {
     408
     409        Bstr src = typeNode.stringValue ("src");
     410
     411        /* find the correspoding object */
     412        ComObjPtr <Host> host = mParent->virtualBox()->host();
     413
     414        ComPtr <IHostFloppyDriveCollection> coll;
     415        rc = host->COMGETTER(FloppyDrives) (coll.asOutParam());
     416        AssertComRC (rc);
     417
     418        ComPtr <IHostFloppyDrive> drive;
     419        rc = coll->FindByName (src, drive.asOutParam());
     420        if (SUCCEEDED (rc))
     421        {
     422            rc = CaptureHostDrive (drive);
     423            CheckComRCReturnRC (rc);
     424        }
     425        else if (rc == E_INVALIDARG)
     426        {
     427            /* the host DVD drive is not currently available. we
     428             * assume it will be available later and create an
     429             * extra object now */
     430            ComObjPtr <HostFloppyDrive> hostDrive;
     431            hostDrive.createObject();
     432            rc = hostDrive->init (src);
     433            AssertComRC (rc);
     434            rc = CaptureHostDrive (hostDrive);
     435            CheckComRCReturnRC (rc);
     436        }
     437        else
     438            AssertComRC (rc);
     439    }
     440
     441    return S_OK;
     442}
     443
     444/**
     445 *  Saves settings to the given machine node.
     446 *
     447 *  @param aMachineNode <Machine> node.
     448 *
     449 *  @note Locks this object for reading.
     450 */
     451HRESULT FloppyDrive::saveSettings (settings::Key &aMachineNode)
     452{
     453    using namespace settings;
     454
     455    AssertReturn (!aMachineNode.isNull(), E_FAIL);
     456
     457    AutoCaller autoCaller (this);
     458    AssertComRCReturnRC (autoCaller.rc());
     459
     460    AutoReaderLock alock (this);
     461
     462    Key node = aMachineNode.createKey ("FloppyDrive");
     463
     464    node.setValue <bool> ("enabled", !!mData->mEnabled);
     465
     466    switch (mData->mDriveState)
     467    {
     468        case DriveState_ImageMounted:
     469        {
     470            Assert (!mData->mFloppyImage.isNull());
     471
     472            Guid id;
     473            HRESULT rc = mData->mFloppyImage->COMGETTER(Id) (id.asOutParam());
     474            AssertComRC (rc);
     475            Assert (!id.isEmpty());
     476
     477            Key imageNode = node.createKey ("Image");
     478            imageNode.setValue <Guid> ("uuid", id);
     479            break;
     480        }
     481        case DriveState_HostDriveCaptured:
     482        {
     483            Assert (!mData->mHostDrive.isNull());
     484
     485            Bstr name;
     486            HRESULT  rc = mData->mHostDrive->COMGETTER(Name) (name.asOutParam());
     487            AssertComRC (rc);
     488            Assert (!name.isEmpty());
     489
     490            Key hostDriveNode = node.createKey ("HostDrive");
     491            hostDriveNode.setValue <Bstr> ("src", name);
     492            break;
     493        }
     494        case DriveState_NotMounted:
     495            /* do nothing, i.e.leave the drive node empty */
     496            break;
     497        default:
     498            ComAssertMsgFailedRet (("Invalid drive state: %d\n",
     499                                      mData->mDriveState),
     500                                     E_FAIL);
     501    }
     502
     503    return S_OK;
     504}
    356505
    357506/**
  • trunk/src/VBox/Main/HardDiskImpl.cpp

    r5999 r6076  
    11871187 *
    11881188 *  @param aHDNode      <HardDisk> node when #isDifferencing() = false, or
    1189  *                      <DiffHardDisk> node otherwise
     1189 *                      <DiffHardDisk> node otherwise.
    11901190 *
    11911191 *  @note
    11921192 *      Must be called from under the object's lock
    11931193 */
    1194 HRESULT HardDisk::loadSettings (CFGNODE aHDNode)
    1195 {
    1196     AssertReturn (aHDNode, E_FAIL);
    1197 
    1198     Guid uuid; /* uuid (required) */
    1199     CFGLDRQueryUUID (aHDNode, "uuid", uuid.ptr());
    1200     mId = uuid;
     1194HRESULT HardDisk::loadSettings (const settings::Key &aHDNode)
     1195{
     1196    using namespace settings;
     1197
     1198    AssertReturn (!aHDNode.isNull(), E_FAIL);
     1199
     1200    /* required */
     1201    mId = aHDNode.value <Guid> ("uuid");
    12011202
    12021203    if (!isDifferencing())
    12031204    {
    1204         Bstr type; /* type (required for <HardDisk> nodes only) */
    1205         CFGLDRQueryBSTR (aHDNode, "type", type.asOutParam());
    1206         if (type == L"normal")
     1205        /* type required for <HardDisk> nodes only */
     1206        const char *type = aHDNode.stringValue ("type");
     1207        if (strcmp (type, "normal") == 0)
    12071208            mType = HardDiskType_NormalHardDisk;
    1208         else if (type == L"immutable")
     1209        else if (strcmp (type, "immutable") == 0)
    12091210            mType = HardDiskType_ImmutableHardDisk;
    1210         else if (type == L"writethrough")
     1211        else if (strcmp (type, "writethrough") == 0)
    12111212            mType = HardDiskType_WritethroughHardDisk;
    12121213        else
    1213             ComAssertMsgFailedRet (("Invalid hard disk type '%ls'\n", type.raw()),
     1214            ComAssertMsgFailedRet (("Invalid hard disk type '%s'\n", type),
    12141215                                   E_FAIL);
    12151216    }
     
    12181219
    12191220    HRESULT rc = mVirtualBox->registerHardDisk (this, VirtualBox::RHD_OnStartUp);
    1220     if (FAILED (rc))
    1221         return rc;
     1221    CheckComRCReturnRC (rc);
    12221222
    12231223    /* load all children */
    1224     unsigned count = 0;
    1225     CFGLDRCountChildren (aHDNode, "DiffHardDisk", &count);
    1226     for (unsigned i = 0; i < count && SUCCEEDED (rc); ++ i)
    1227     {
    1228         CFGNODE hdNode = 0;
    1229 
    1230         CFGLDRGetChildNode (aHDNode, "DiffHardDisk", i, &hdNode);
    1231         ComAssertBreak (hdNode, rc = E_FAIL);
    1232 
    1233         do
    1234         {
    1235             CFGNODE vdiNode = 0;
    1236             CFGLDRGetChildNode (hdNode, "VirtualDiskImage", 0, &vdiNode);
    1237             ComAssertBreak (vdiNode, rc = E_FAIL);
    1238 
    1239             ComObjPtr <HVirtualDiskImage> vdi;
    1240             vdi.createObject();
    1241             rc = vdi->init (mVirtualBox, this, hdNode, vdiNode);
    1242 
    1243             CFGLDRReleaseNode (vdiNode);
    1244         }
    1245         while (0);
    1246 
    1247         CFGLDRReleaseNode (hdNode);
     1224    Key::List children = aHDNode.keys ("DiffHardDisk");
     1225    for (Key::List::const_iterator it = children.begin();
     1226         it != children.end(); ++ it)
     1227    {
     1228        Key vdiNode = (*it).key ("VirtualDiskImage");
     1229
     1230        ComObjPtr <HVirtualDiskImage> vdi;
     1231        vdi.createObject();
     1232        rc = vdi->init (mVirtualBox, this, (*it), vdiNode);
     1233        CheckComRCBreakRC (rc);
    12481234    }
    12491235
     
    12591245 *
    12601246 *  @param aHDNode      <HardDisk> node when #isDifferencing() = false, or
    1261  *                      <DiffHardDisk> node otherwise
     1247 *                      <DiffHardDisk> node otherwise.
    12621248 *
    12631249 *  @note
    12641250 *      Must be called from under the object's lock
    12651251 */
    1266 HRESULT HardDisk::saveSettings (CFGNODE aHDNode)
    1267 {
    1268     AssertReturn (aHDNode, E_FAIL);
     1252HRESULT HardDisk::saveSettings (settings::Key &aHDNode)
     1253{
     1254    using namespace settings;
     1255
     1256    AssertReturn (!aHDNode.isNull(), E_FAIL);
    12691257
    12701258    /* uuid (required) */
    1271     CFGLDRSetUUID (aHDNode, "uuid", mId.ptr());
     1259    aHDNode.setValue <Guid> ("uuid", mId);
    12721260
    12731261    if (!isDifferencing())
     
    12871275                break;
    12881276        }
    1289         CFGLDRSetString (aHDNode, "type", type);
    1290     }
    1291 
    1292     HRESULT rc = S_OK;
     1277        aHDNode.setStringValue ("type", type);
     1278    }
    12931279
    12941280    /* save all children */
    12951281    AutoLock chLock (childrenLock());
    12961282    for (HardDiskList::const_iterator it = children().begin();
    1297          it != children().end() && SUCCEEDED (rc);
     1283         it != children().end();
    12981284         ++ it)
    12991285    {
     
    13011287        AutoLock childLock (child);
    13021288
    1303         CFGNODE hdNode = 0;
    1304         CFGLDRAppendChildNode (aHDNode, "DiffHardDisk", &hdNode);
    1305         ComAssertBreak (hdNode, rc = E_FAIL);
    1306 
    1307         do
    1308         {
    1309             CFGNODE vdiNode = 0;
    1310             CFGLDRAppendChildNode (hdNode, "VirtualDiskImage", &vdiNode);
    1311             ComAssertBreak (vdiNode, rc = E_FAIL);
    1312 
    1313             rc = child->saveSettings (hdNode, vdiNode);
    1314 
    1315             CFGLDRReleaseNode (vdiNode);
    1316         }
    1317         while (0);
    1318 
    1319         CFGLDRReleaseNode (hdNode);
    1320     }
    1321 
    1322     return rc;
     1289        Key hdNode = aHDNode.appendKey ("DiffHardDisk");
     1290
     1291        {
     1292            Key vdiNode = hdNode.createKey ("VirtualDiskImage");
     1293            HRESULT rc = child->saveSettings (hdNode, vdiNode);
     1294            CheckComRCReturnRC (rc);
     1295        }
     1296    }
     1297
     1298    return S_OK;
    13231299}
    13241300
     
    13631339 *  registered on success.
    13641340 *
    1365  *  @param aHDNode      <HardDisk> node
    1366  *  @param aVDINode     <VirtualDiskImage> node
     1341 *  @param aHDNode      <HardDisk> or <DiffHardDisk> node.
     1342 *  @param aVDINode     <VirtualDiskImage> node.
    13671343 */
    13681344HRESULT HVirtualDiskImage::init (VirtualBox *aVirtualBox, HardDisk *aParent,
    1369                                  CFGNODE aHDNode, CFGNODE aVDINode)
    1370 {
    1371     LogFlowThisFunc (("aHDNode=%p, aVDINode=%p\n", aHDNode, aVDINode));
    1372 
    1373     AssertReturn (aHDNode && aVDINode, E_FAIL);
     1345                                 const settings::Key &aHDNode,
     1346                                 const settings::Key &aVDINode)
     1347{
     1348    using namespace settings;
     1349
     1350    LogFlowThisFunc (("\n"));
     1351
     1352    AssertReturn (!aHDNode.isNull() && !aVDINode.isNull(), E_FAIL);
    13741353
    13751354    AutoLock alock (this);
     
    13891368
    13901369        /* filePath (required) */
    1391         Bstr filePath;
    1392         CFGLDRQueryBSTR (aVDINode, "filePath", filePath.asOutParam());
    1393 
     1370        Bstr filePath = aVDINode.stringValue ("filePath");
    13941371        rc = setFilePath (filePath);
    13951372        CheckComRCBreakRC (rc);
     
    17681745 *  all children to the specified hard disk node
    17691746 *
    1770  *  @param aHDNode      <HardDisk> or <DiffHardDisk> node
    1771  *  @param aStorageNode <VirtualDiskImage> node
    1772  */
    1773 HRESULT HVirtualDiskImage::saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode)
    1774 {
    1775     AssertReturn (aHDNode && aStorageNode, E_FAIL);
    1776 
    1777     AutoLock alock (this);
    1778     CHECK_READY();
    1779 
    1780     // filePath (required)
    1781     CFGLDRSetBSTR (aStorageNode, "filePath", mFilePath);
    1782 
    1783     // save basic settings and children
     1747 *  @param aHDNode      <HardDisk> or <DiffHardDisk> node.
     1748 *  @param aStorageNode <VirtualDiskImage> node.
     1749 */
     1750HRESULT HVirtualDiskImage::saveSettings (settings::Key &aHDNode,
     1751                                         settings::Key &aStorageNode)
     1752{
     1753    AssertReturn (!aHDNode.isNull() && !aStorageNode.isNull(), E_FAIL);
     1754
     1755    AutoLock alock (this);
     1756    CHECK_READY();
     1757
     1758    /* filePath (required) */
     1759    aStorageNode.setValue <Bstr> ("filePath", mFilePath);
     1760
     1761    /* save basic settings and children */
    17841762    return HardDisk::saveSettings (aHDNode);
    17851763}
     
    28342812 *  registered on success.
    28352813 *
    2836  *  @param aHDNode      <HardDisk> node
    2837  *  @param aVDINod      <ISCSIHardDisk> node
     2814 *  @param aHDNode      <HardDisk> node.
     2815 *  @param aVDINod      <ISCSIHardDisk> node.
    28382816 */
    28392817HRESULT HISCSIHardDisk::init (VirtualBox *aVirtualBox,
    2840                               CFGNODE aHDNode, CFGNODE aISCSINode)
    2841 {
    2842     LogFlowThisFunc (("aHDNode=%p, aISCSINode=%p\n", aHDNode, aISCSINode));
    2843 
    2844     AssertReturn (aHDNode && aISCSINode, E_FAIL);
     2818                              const settings::Key &aHDNode,
     2819                              const settings::Key &aISCSINode)
     2820{
     2821    using namespace settings;
     2822
     2823    LogFlowThisFunc (("\n"));
     2824
     2825    AssertReturn (!aHDNode.isNull() && !aISCSINode.isNull(), E_FAIL);
    28452826
    28462827    AutoLock alock (this);
     
    28602841
    28612842        /* server (required) */
    2862         CFGLDRQueryBSTR (aISCSINode, "server", mServer.asOutParam());
     2843        mServer = aISCSINode.stringValue ("server");
    28632844        /* target (required) */
    2864         CFGLDRQueryBSTR (aISCSINode, "target", mTarget.asOutParam());
     2845        mTarget = aISCSINode.stringValue ("target");
    28652846
    28662847        /* port (optional) */
    2867         CFGLDRQueryUInt16 (aISCSINode, "port", &mPort);
     2848        mPort = aISCSINode.value <USHORT> ("port");
    28682849        /* lun (optional) */
    2869         CFGLDRQueryUInt64 (aISCSINode, "lun", &mLun);
     2850        mLun = aISCSINode.value <ULONG64> ("lun");
    28702851        /* userName (optional) */
    2871         CFGLDRQueryBSTR (aISCSINode, "userName", mUserName.asOutParam());
     2852        mUserName = aISCSINode.stringValue ("userName");
    28722853        /* password (optional) */
    2873         CFGLDRQueryBSTR (aISCSINode, "password", mPassword.asOutParam());
     2854        mPassword = aISCSINode.stringValue ("password");
    28742855
    28752856        LogFlowThisFunc (("'iscsi:%ls:%hu@%ls/%ls:%llu'\n",
     
    32373218 *  all children to the specified hard disk node
    32383219 *
    3239  *  @param aHDNode      <HardDisk>
    3240  *  @param aStorageNode <ISCSIHardDisk> node
    3241  */
    3242 HRESULT HISCSIHardDisk::saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode)
    3243 {
    3244     AssertReturn (aHDNode && aStorageNode, E_FAIL);
     3220 *  @param aHDNode      <HardDisk>.
     3221 *  @param aStorageNode <ISCSIHardDisk> node.
     3222 */
     3223HRESULT HISCSIHardDisk::saveSettings (settings::Key &aHDNode,
     3224                                      settings::Key &aStorageNode)
     3225{
     3226    AssertReturn (!aHDNode.isNull() && !aStorageNode.isNull(), E_FAIL);
    32453227
    32463228    AutoLock alock (this);
     
    32483230
    32493231    /* server (required) */
    3250     CFGLDRSetBSTR (aStorageNode, "server", mServer);
     3232    aStorageNode.setValue <Bstr> ("server", mServer);
    32513233    /* target (required) */
    3252     CFGLDRSetBSTR (aStorageNode, "target", mTarget);
    3253 
    3254     /* port (optional) */
    3255     if (mPort != 0)
    3256         CFGLDRSetUInt16 (aStorageNode, "port", mPort);
    3257     else
    3258         CFGLDRDeleteAttribute (aStorageNode, "port");
     3234    aStorageNode.setValue <Bstr> ("target", mTarget);
     3235
     3236    /* port (optional, defaults to 0) */
     3237    aStorageNode.setValueOr <USHORT> ("port", mPort, 0);
    32593238    /* lun (optional, force 0x format to coform to XML Schema!) */
    3260     if (mLun != 0)
    3261         CFGLDRSetUInt64Ex (aStorageNode, "lun", mLun, 16);
    3262     else
    3263         CFGLDRDeleteAttribute (aStorageNode, "lun");
     3239    aStorageNode.setValueOr <ULONG64> ("lun", mLun, 0, 16);
    32643240    /* userName (optional) */
    3265     if (!mUserName.isNull())
    3266         CFGLDRSetBSTR (aStorageNode, "userName", mUserName);
    3267     else
    3268         CFGLDRDeleteAttribute (aStorageNode, "userName");
     3241    aStorageNode.setValueOr <Bstr> ("userName", mUserName, Bstr::Null);
    32693242    /* password (optional) */
    3270     if (!mPassword.isNull())
    3271         CFGLDRSetBSTR (aStorageNode, "password", mPassword);
    3272     else
    3273         CFGLDRDeleteAttribute (aStorageNode, "password");
     3243    aStorageNode.setValueOr <Bstr> ("password", mPassword, Bstr::Null);
    32743244
    32753245    /* save basic settings and children */
     
    34223392 *  registered on success.
    34233393 *
    3424  *  @param aHDNode      <HardDisk> node
    3425  *  @param aVMDKNode    <VirtualDiskImage> node
     3394 *  @param aHDNode      <HardDisk> node.
     3395 *  @param aVMDKNode    <VirtualDiskImage> node.
    34263396 */
    34273397HRESULT HVMDKImage::init (VirtualBox *aVirtualBox, HardDisk *aParent,
    3428                           CFGNODE aHDNode, CFGNODE aVMDKNode)
    3429 {
    3430     LogFlowThisFunc (("aHDNode=%p, aVMDKNode=%p\n", aHDNode, aVMDKNode));
    3431 
    3432     AssertReturn (aHDNode && aVMDKNode, E_FAIL);
     3398                          const settings::Key &aHDNode,
     3399                          const settings::Key &aVMDKNode)
     3400{
     3401    using namespace settings;
     3402
     3403    LogFlowThisFunc (("\n"));
     3404
     3405    AssertReturn (!aHDNode.isNull() && !aVMDKNode.isNull(), E_FAIL);
    34333406
    34343407    AutoLock alock (this);
     
    34483421
    34493422        /* filePath (required) */
    3450         Bstr filePath;
    3451         CFGLDRQueryBSTR (aVMDKNode, "filePath", filePath.asOutParam());
    3452 
     3423        Bstr filePath = aVMDKNode.stringValue ("filePath");
    34533424        rc = setFilePath (filePath);
    34543425        CheckComRCBreakRC (rc);
     
    38583829 *  all children to the specified hard disk node
    38593830 *
    3860  *  @param aHDNode      <HardDisk> or <DiffHardDisk> node
    3861  *  @param aStorageNode <VirtualDiskImage> node
    3862  */
    3863 HRESULT HVMDKImage::saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode)
    3864 {
    3865     AssertReturn (aHDNode && aStorageNode, E_FAIL);
     3831 *  @param aHDNode      <HardDisk> or <DiffHardDisk> node.
     3832 *  @param aStorageNode <VirtualDiskImage> node.
     3833 */
     3834HRESULT HVMDKImage::saveSettings (settings::Key &aHDNode,
     3835                                  settings::Key &aStorageNode)
     3836{
     3837    AssertReturn (!aHDNode.isNull() && !aStorageNode.isNull(), E_FAIL);
    38663838
    38673839    AutoLock alock (this);
     
    38693841
    38703842    /* filePath (required) */
    3871     CFGLDRSetBSTR (aStorageNode, "filePath", mFilePath);
     3843    aStorageNode.setValue <Bstr> ("filePath", mFilePath);
    38723844
    38733845    /* save basic settings and children */
     
    42914263 *  registered on success.
    42924264 *
    4293  *  @param aHDNode      <HardDisk> node
    4294  *  @param aCustomNode  <VirtualDiskImage> node
     4265 *  @param aHDNode      <HardDisk> node.
     4266 *  @param aCustomNode  <VirtualDiskImage> node.
    42954267 */
    42964268HRESULT HCustomHardDisk::init (VirtualBox *aVirtualBox, HardDisk *aParent,
    4297                           CFGNODE aHDNode, CFGNODE aCustomNode)
    4298 {
    4299     LogFlowThisFunc (("aHDNode=%p, aCustomNode=%p\n", aHDNode, aCustomNode));
    4300 
    4301     AssertReturn (aHDNode && aCustomNode, E_FAIL);
     4269                               const settings::Key &aHDNode,
     4270                               const settings::Key &aCustomNode)
     4271{
     4272    using namespace settings;
     4273
     4274    LogFlowThisFunc (("\n"));
     4275
     4276    AssertReturn (!aHDNode.isNull() && !aCustomNode.isNull(), E_FAIL);
    43024277
    43034278    AutoLock alock (this);
     
    43174292
    43184293        /* location (required) */
    4319         Bstr location;
    4320         CFGLDRQueryBSTR (aCustomNode, "location", location.asOutParam());
    4321 
     4294        Bstr location = aCustomNode.stringValue ("location");
    43224295        rc = setLocation (location);
    43234296        CheckComRCBreakRC (rc);
     
    43264299
    43274300        /* format (required) */
    4328         CFGLDRQueryBSTR (aCustomNode, "format", mFormat.asOutParam());
     4301        mFormat = aCustomNode.stringValue ("format");
    43294302
    43304303        /* initialize the container */
     
    47324705 *  all children to the specified hard disk node
    47334706 *
    4734  *  @param aHDNode      <HardDisk> or <DiffHardDisk> node
    4735  *  @param aStorageNode <VirtualDiskImage> node
    4736  */
    4737 HRESULT HCustomHardDisk::saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode)
    4738 {
    4739     AssertReturn (aHDNode && aStorageNode, E_FAIL);
     4707 *  @param aHDNode      <HardDisk> or <DiffHardDisk> node.
     4708 *  @param aStorageNode <VirtualDiskImage> node.
     4709 */
     4710HRESULT HCustomHardDisk::saveSettings (settings::Key &aHDNode,
     4711                                       settings::Key &aStorageNode)
     4712{
     4713    AssertReturn (!aHDNode.isNull() && !aStorageNode.isNull(), E_FAIL);
    47404714
    47414715    AutoLock alock (this);
     
    47434717
    47444718    /* location (required) */
    4745     CFGLDRSetBSTR (aStorageNode, "location", mLocationFull);
     4719    aStorageNode.setValue <Bstr> ("location", mLocationFull);
    47464720
    47474721    /* format (required) */
    4748     CFGLDRSetBSTR (aStorageNode, "format", mFormat);
     4722    aStorageNode.setValue <Bstr> ("format", mFormat);
    47494723
    47504724    /* save basic settings and children */
  • trunk/src/VBox/Main/HostImpl.cpp

    r5999 r6076  
    11331133}
    11341134
    1135 HRESULT Host::loadSettings (CFGNODE aGlobal)
    1136 {
     1135HRESULT Host::loadSettings (const settings::Key &aGlobal)
     1136{
     1137    using namespace settings;
     1138
    11371139    AutoLock lock (this);
    11381140    CHECK_READY();
    11391141
    1140     ComAssertRet (aGlobal, E_FAIL);
    1141 
    1142     CFGNODE filters = NULL;
    1143     CFGLDRGetChildNode (aGlobal, "USBDeviceFilters", 0, &filters);
    1144     Assert (filters);
     1142    AssertReturn (!aGlobal.isNull(), E_FAIL);
    11451143
    11461144    HRESULT rc = S_OK;
    11471145
    1148     unsigned filterCount = 0;
    1149     CFGLDRCountChildren (filters, "DeviceFilter", &filterCount);
    1150     for (unsigned i = 0; i < filterCount && SUCCEEDED (rc); i++)
    1151     {
    1152         CFGNODE filter = NULL;
    1153         CFGLDRGetChildNode (filters, "DeviceFilter", i, &filter);
    1154         Assert (filter);
    1155 
    1156         Bstr name;
    1157         CFGLDRQueryBSTR (filter, "name", name.asOutParam());
    1158         bool active;
    1159         CFGLDRQueryBool (filter, "active", &active);
    1160 
    1161         Bstr vendorId;
    1162         CFGLDRQueryBSTR (filter, "vendorid", vendorId.asOutParam());
    1163         Bstr productId;
    1164         CFGLDRQueryBSTR (filter, "productid", productId.asOutParam());
    1165         Bstr revision;
    1166         CFGLDRQueryBSTR (filter, "revision", revision.asOutParam());
    1167         Bstr manufacturer;
    1168         CFGLDRQueryBSTR (filter, "manufacturer", manufacturer.asOutParam());
    1169         Bstr product;
    1170         CFGLDRQueryBSTR (filter, "product", product.asOutParam());
    1171         Bstr serialNumber;
    1172         CFGLDRQueryBSTR (filter, "serialnumber", serialNumber.asOutParam());
    1173         Bstr port;
    1174         CFGLDRQueryBSTR (filter, "port", port.asOutParam());
     1146    Key::List filters = aGlobal.key ("USBDeviceFilters").keys ("DeviceFilter");
     1147    for (Key::List::const_iterator it = filters.begin();
     1148         it != filters.end(); ++ it)
     1149    {
     1150        Bstr name = (*it).stringValue ("name");
     1151        bool active = (*it).value <bool> ("active");
     1152
     1153        Bstr vendorId = (*it).stringValue ("vendorid");
     1154        Bstr productId = (*it).stringValue ("productid");
     1155        Bstr revision = (*it).stringValue ("revision");
     1156        Bstr manufacturer = (*it).stringValue ("manufacturer");
     1157        Bstr product = (*it).stringValue ("product");
     1158        Bstr serialNumber = (*it).stringValue ("serialnumber");
     1159        Bstr port = (*it).stringValue ("port");
    11751160
    11761161        USBDeviceFilterAction_T action;
    11771162        action = USBDeviceFilterAction_USBDeviceFilterIgnore;
    1178         Bstr actionStr;
    1179         CFGLDRQueryBSTR (filter, "action", actionStr.asOutParam());
    1180         if (actionStr == L"Ignore")
     1163        const char *actionStr = (*it).stringValue ("action");
     1164        if (strcmp (actionStr, "Ignore") == 0)
    11811165            action = USBDeviceFilterAction_USBDeviceFilterIgnore;
    11821166        else
    1183         if (actionStr == L"Hold")
     1167        if (strcmp (actionStr, "Hold") == 0)
    11841168            action = USBDeviceFilterAction_USBDeviceFilterHold;
    11851169        else
    1186             AssertMsgFailed (("Invalid action: %ls\n", actionStr.raw()));
     1170            AssertMsgFailed (("Invalid action: '%s'\n", actionStr));
    11871171
    11881172        ComObjPtr <HostUSBDeviceFilter> filterObj;
     
    11921176                              manufacturer, product, serialNumber, port,
    11931177                              action);
    1194         // error info is set by init() when appropriate
    1195         if (SUCCEEDED (rc))
    1196         {
    1197             mUSBDeviceFilters.push_back (filterObj);
    1198             filterObj->mInList = true;
    1199 
    1200             // notify the proxy (only when the filter is active)
    1201             if (filterObj->data().mActive)
    1202             {
    1203                 HostUSBDeviceFilter *flt = filterObj; // resolve ambiguity
     1178        /* error info is set by init() when appropriate */
     1179        CheckComRCBreakRC (rc);
     1180
     1181        mUSBDeviceFilters.push_back (filterObj);
     1182        filterObj->mInList = true;
     1183
     1184        /* notify the proxy (only when the filter is active) */
     1185        if (filterObj->data().mActive)
     1186        {
     1187            HostUSBDeviceFilter *flt = filterObj; /* resolve ambiguity */
    12041188#ifndef VBOX_WITH_USBFILTER
    1205                 flt->id() =
    1206                     mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (flt));
     1189            flt->id() =
     1190                mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (flt));
    12071191#else
    1208                 flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
     1192            flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
    12091193#endif
    1210             }
    1211         }
    1212 
    1213         CFGLDRReleaseNode (filter);
    1214     }
    1215 
    1216     CFGLDRReleaseNode (filters);
     1194        }
     1195    }
    12171196
    12181197    return rc;
    12191198}
    12201199
    1221 HRESULT Host::saveSettings (CFGNODE aGlobal)
    1222 {
     1200HRESULT Host::saveSettings (settings::Key &aGlobal)
     1201{
     1202    using namespace settings;
     1203
    12231204    AutoLock lock (this);
    12241205    CHECK_READY();
    12251206
    1226     ComAssertRet (aGlobal, E_FAIL);
    1227 
    1228     // first, delete the entry
    1229     CFGNODE filters = NULL;
    1230     int vrc = CFGLDRGetChildNode (aGlobal, "USBDeviceFilters", 0, &filters);
    1231     if (VBOX_SUCCESS (vrc))
    1232     {
    1233         vrc = CFGLDRDeleteNode (filters);
    1234         ComAssertRCRet (vrc, E_FAIL);
    1235     }
    1236     // then, recreate it
    1237     vrc = CFGLDRCreateChildNode (aGlobal, "USBDeviceFilters", &filters);
    1238     ComAssertRCRet (vrc, E_FAIL);
     1207    ComAssertRet (!aGlobal.isNull(), E_FAIL);
     1208
     1209    /* first, delete the entry */
     1210    Key filters = aGlobal.findKey ("USBDeviceFilters");
     1211    if (!filters.isNull())
     1212        filters.zap();
     1213    /* then, recreate it */
     1214    filters = aGlobal.createKey ("USBDeviceFilters");
    12391215
    12401216    USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
     
    12441220        const HostUSBDeviceFilter::Data &data = (*it)->data();
    12451221
    1246         CFGNODE filter = NULL;
    1247         CFGLDRAppendChildNode (filters, "DeviceFilter",  &filter);
    1248 
    1249         CFGLDRSetBSTR (filter, "name", data.mName);
    1250         CFGLDRSetBool (filter, "active", !!data.mActive);
     1222        Key filter = filters.appendKey ("DeviceFilter");
     1223
     1224        filter.setValue <Bstr> ("name", data.mName);
     1225        filter.setValue <bool> ("active", !!data.mActive);
    12511226
    12521227#ifndef VBOX_WITH_USBFILTER
    1253         // all are optional
     1228
     1229        /* all are optional */
    12541230        if (data.mVendorId.string())
    1255             CFGLDRSetBSTR (filter, "vendorid", data.mVendorId.string());
     1231            filter.setValue <Bstr> ("vendorid", data.mVendorId.string());
    12561232        if (data.mProductId.string())
    1257             CFGLDRSetBSTR (filter, "productid", data.mProductId.string());
     1233            filter.setValue <Bstr> ("productid", data.mProductId.string());
    12581234        if (data.mRevision.string())
    1259             CFGLDRSetBSTR (filter, "revision", data.mRevision.string());
     1235            filter.setValue <Bstr> ("revision", data.mRevision.string());
    12601236        if (data.mManufacturer.string())
    1261             CFGLDRSetBSTR (filter, "manufacturer", data.mManufacturer.string());
     1237            filter.setValue <Bstr> ("manufacturer", data.mManufacturer.string());
    12621238        if (data.mProduct.string())
    1263             CFGLDRSetBSTR (filter, "product", data.mProduct.string());
     1239            filter.setValue <Bstr> ("product", data.mProduct.string());
    12641240        if (data.mSerialNumber.string())
    1265             CFGLDRSetBSTR (filter, "serialnumber", data.mSerialNumber.string());
     1241            filter.setValue <Bstr> ("serialnumber", data.mSerialNumber.string());
    12661242        if (data.mPort.string())
    1267             CFGLDRSetBSTR (filter, "port", data.mPort.string());
    1268 
    1269         // action is mandatory
     1243            filter.setValue <Bstr> ("port", data.mPort.string());
     1244
     1245        /* action is mandatory */
    12701246        if (data.mAction == USBDeviceFilterAction_USBDeviceFilterIgnore)
    1271             CFGLDRSetString (filter, "action", "Ignore");
     1247            filter.setStringValue ("action", "Ignore");
    12721248        else
    12731249        if (data.mAction == USBDeviceFilterAction_USBDeviceFilterHold)
    1274             CFGLDRSetString (filter, "action", "Hold");
     1250            filter.setStringValue ("action", "Hold");
    12751251        else
    12761252            AssertMsgFailed (("Invalid action: %d\n", data.mAction));
    12771253
    12781254#else  /* VBOX_WITH_USBFILTER */
    1279         // all are optional
     1255
     1256        /* all are optional */
    12801257        Bstr str;
    12811258        (*it)->COMGETTER (VendorId) (str.asOutParam());
    12821259        if (!str.isNull())
    1283             CFGLDRSetBSTR (filter, "vendorid", str);
     1260            filter.setValue <Bstr> ("vendorid", str);
    12841261
    12851262        (*it)->COMGETTER (ProductId) (str.asOutParam());
    12861263        if (!str.isNull())
    1287             CFGLDRSetBSTR (filter, "productid", str);
     1264            filter.setValue <Bstr> ("productid", str);
    12881265
    12891266        (*it)->COMGETTER (Revision) (str.asOutParam());
    12901267        if (!str.isNull())
    1291             CFGLDRSetBSTR (filter, "revision", str);
     1268            filter.setValue <Bstr> ("revision", str);
    12921269
    12931270        (*it)->COMGETTER (Manufacturer) (str.asOutParam());
    12941271        if (!str.isNull())
    1295             CFGLDRSetBSTR (filter, "manufacturer", str);
     1272            filter.setValue <Bstr> ("manufacturer", str);
    12961273
    12971274        (*it)->COMGETTER (Product) (str.asOutParam());
    12981275        if (!str.isNull())
    1299             CFGLDRSetBSTR (filter, "product", str);
     1276            filter.setValue <Bstr> ("product", str);
    13001277
    13011278        (*it)->COMGETTER (SerialNumber) (str.asOutParam());
    13021279        if (!str.isNull())
    1303             CFGLDRSetBSTR (filter, "serialnumber", str);
     1280            filter.setValue <Bstr> ("serialnumber", str);
    13041281
    13051282        (*it)->COMGETTER (Port) (str.asOutParam());
    13061283        if (!str.isNull())
    1307             CFGLDRSetBSTR (filter, "port", str);
    1308 
    1309         // action is mandatory
     1284            filter.setValue <Bstr> ("port", str);
     1285
     1286        /* action is mandatory */
    13101287        ULONG action = USBDeviceFilterAction_InvalidUSBDeviceFilterAction;
    13111288        (*it)->COMGETTER (Action) (&action);
    13121289        if (action == USBDeviceFilterAction_USBDeviceFilterIgnore)
    1313             CFGLDRSetString (filter, "action", "Ignore");
     1290            filter.setStringValue ("action", "Ignore");
    13141291        else if (action == USBDeviceFilterAction_USBDeviceFilterHold)
    1315             CFGLDRSetString (filter, "action", "Hold");
     1292            filter.setStringValue ("action", "Hold");
    13161293        else
    13171294            AssertMsgFailed (("Invalid action: %d\n", action));
     1295
    13181296#endif /* VBOX_WITH_USBFILTER */
    13191297
    1320         CFGLDRReleaseNode (filter);
    1321 
    13221298        ++ it;
    13231299    }
    1324 
    1325     CFGLDRReleaseNode (filters);
    13261300
    13271301    return S_OK;
  • trunk/src/VBox/Main/MachineDebuggerImpl.cpp

    r5999 r6076  
    173173
    174174    char *pszSnapshot;
    175     int vrc = STAMR3Snapshot(pVM, Utf8Str(aPattern).raw(), &pszSnapshot, NULL, aWithDescriptions);
     175    int vrc = STAMR3Snapshot(pVM, Utf8Str(aPattern).raw(), &pszSnapshot, NULL,
     176                             !!aWithDescriptions);
    176177    if (RT_FAILURE(vrc))
    177178        return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
  • trunk/src/VBox/Main/MachineImpl.cpp

    r6056 r6076  
    3131#include "MachineImpl.h"
    3232#include "HardDiskImpl.h"
    33 #include "HostDVDDriveImpl.h"
    34 #include "HostFloppyDriveImpl.h"
    3533#include "ProgressImpl.h"
    3634#include "HardDiskAttachmentImpl.h"
     
    4543#include "USBProxyService.h"
    4644
     45#include "VirtualBoxXMLUtil.h"
     46
    4747#include "Logging.h"
    4848
     
    5858
    5959#include <VBox/err.h>
    60 #include <VBox/cfgldr.h>
    6160#include <VBox/param.h>
    6261
    6362#include <algorithm>
     63
     64#include <typeinfo>
    6465
    6566#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     
    116117
    117118    mMachineState = MachineState_PoweredOff;
    118     RTTIMESPEC time;
    119     mLastStateChange = RTTimeSpecGetMilli (RTTimeNow (&time));
     119    RTTimeNow (&mLastStateChange);
    120120
    121121    mMachineStateDeps = 0;
     
    13991399    AutoReaderLock alock (this);
    14001400
    1401     *aLastStateChange = mData->mLastStateChange;
     1401    *aLastStateChange = RTTimeSpecGetMilli (&mData->mLastStateChange);
    14021402
    14031403    return S_OK;
     
    19301930}
    19311931
     1932/**
     1933 *  @note Locks this object for reading.
     1934 */
    19321935STDMETHODIMP Machine::GetNextExtraDataKey (INPTR BSTR aKey, BSTR *aNextKey, BSTR *aNextValue)
    19331936{
     
    19421945    /* start with nothing found */
    19431946    *aNextKey = NULL;
    1944 
    1945     /*
    1946      *  if we're ready and isConfigLocked() is FALSE then it means
    1947      *  that no config file exists yet, so return shortly
    1948      */
     1947    if (aNextValue)
     1948        *aNextValue = NULL;
     1949
     1950    /* if we're ready and isConfigLocked() is FALSE then it means
     1951     * that no config file exists yet, so return shortly */
    19491952    if (!isConfigLocked())
    19501953        return S_OK;
     
    19521955    HRESULT rc = S_OK;
    19531956
    1954     /* load the config file */
    1955     CFGHANDLE configLoader = 0;
    1956     rc = openConfigLoader (&configLoader);
    1957     if (FAILED (rc))
    1958         return  E_FAIL;
    1959 
    1960     CFGNODE machineNode;
    1961     CFGNODE extraDataNode;
    1962 
    1963     /* navigate to the right position */
    1964     if (VBOX_SUCCESS(CFGLDRGetNode(configLoader, "VirtualBox/Machine", 0, &machineNode)) &&
    1965         VBOX_SUCCESS(CFGLDRGetChildNode(machineNode, "ExtraData", 0, &extraDataNode)))
    1966     {
    1967         /* check if it exists */
    1968         bool found = false;
    1969         unsigned count;
    1970         CFGNODE extraDataItemNode;
    1971         CFGLDRCountChildren(extraDataNode, "ExtraDataItem", &count);
    1972         for (unsigned i = 0; (i < count) && (found == false); i++)
    1973         {
    1974             Bstr name;
    1975             CFGLDRGetChildNode(extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    1976             CFGLDRQueryBSTR(extraDataItemNode, "name", name.asOutParam());
    1977 
    1978             /* if we're supposed to return the first one */
    1979             if (aKey == NULL)
     1957    try
     1958    {
     1959        using namespace settings;
     1960
     1961        /* load the config file */
     1962        File file (File::ReadWrite, mData->mHandleCfgFile,
     1963                   Utf8Str (mData->mConfigFileFull));
     1964        XmlTreeBackend tree;
     1965
     1966        rc = VirtualBox::loadSettingsTree_Again (tree, file);
     1967        CheckComRCReturnRC (rc);
     1968
     1969        Key machineNode = tree.rootKey().key ("Machine");
     1970        Key extraDataNode = machineNode.findKey ("ExtraData");
     1971
     1972        if (!extraDataNode.isNull())
     1973        {
     1974            Key::List items = extraDataNode.keys ("ExtraDataItem");
     1975            if (items.size())
    19801976            {
    1981                 name.cloneTo(aNextKey);
    1982                 if (aNextValue)
    1983                     CFGLDRQueryBSTR(extraDataItemNode, "value", aNextValue);
    1984                 found = true;
    1985             }
    1986             /* did we find the key we're looking for? */
    1987             else if (name == aKey)
    1988             {
    1989                 found = true;
    1990                 /* is there another item? */
    1991                 if (i + 1 < count)
     1977                for (Key::List::const_iterator it = items.begin();
     1978                     it != items.end(); ++ it)
    19921979                {
    1993                     CFGLDRGetChildNode(extraDataNode, "ExtraDataItem", i + 1, &extraDataItemNode);
    1994                     CFGLDRQueryBSTR(extraDataItemNode, "name", name.asOutParam());
    1995                     name.cloneTo(aNextKey);
    1996                     if (aNextValue)
    1997                         CFGLDRQueryBSTR(extraDataItemNode, "value", aNextValue);
    1998                     found = true;
    1999                 }
    2000                 else
    2001                 {
    2002                     /* it's the last one */
    2003                     *aNextKey = NULL;
     1980                    Bstr key = (*it).stringValue ("name");
     1981
     1982                    /* if we're supposed to return the first one */
     1983                    if (aKey == NULL)
     1984                    {
     1985                        key.cloneTo (aNextKey);
     1986                        if (aNextValue)
     1987                        {
     1988                            Bstr val = (*it).stringValue ("value");
     1989                            val.cloneTo (aNextValue);
     1990                        }
     1991                        return S_OK;
     1992                    }
     1993
     1994                    /* did we find the key we're looking for? */
     1995                    if (key == aKey)
     1996                    {
     1997                        ++ it;
     1998                        /* is there another item? */
     1999                        if (it != items.end())
     2000                        {
     2001                            Bstr key = (*it).stringValue ("name");
     2002                            key.cloneTo (aNextKey);
     2003                            if (aNextValue)
     2004                            {
     2005                                Bstr val = (*it).stringValue ("value");
     2006                                val.cloneTo (aNextValue);
     2007                            }
     2008                        }
     2009                        /* else it's the last one, arguments are already NULL */
     2010                        return S_OK;
     2011                    }
    20042012                }
    20052013            }
    2006             CFGLDRReleaseNode(extraDataItemNode);
    2007         }
    2008 
    2009         /* if we haven't found the key, it's an error */
    2010         if (!found)
    2011             rc = setError(E_FAIL, tr("Could not find extra data key"));
    2012 
    2013         CFGLDRReleaseNode(extraDataNode);
    2014         CFGLDRReleaseNode(machineNode);
    2015     }
    2016 
    2017     closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
     2014        }
     2015
     2016        /* Here we are when a) there are no items at all or b) there are items
     2017         * but none of them equals to the requested non-NULL key. b) is an
     2018         * error as well as a) if the key is non-NULL. When the key is NULL
     2019         * (which is the case only when there are no items), we just fall
     2020         * through to return NULLs and S_OK. */
     2021
     2022        if (aKey != NULL)
     2023            return setError (E_FAIL,
     2024                tr ("Could not find the extra data key '%ls'"), aKey);
     2025    }
     2026    catch (...)
     2027    {
     2028        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     2029    }
    20182030
    20192031    return rc;
    20202032}
    20212033
     2034/**
     2035 *  @note Locks this object for reading.
     2036 */
    20222037STDMETHODIMP Machine::GetExtraData (INPTR BSTR aKey, BSTR *aValue)
    20232038{
     
    20352050    *aValue = NULL;
    20362051
    2037     /*
    2038      *  if we're ready and isConfigLocked() is FALSE then it means
    2039      *  that no config file exists yet, so return shortly
    2040      */
     2052    /* if we're ready and isConfigLocked() is FALSE then it means
     2053     * that no config file exists yet, so return shortly */
    20412054    if (!isConfigLocked())
    20422055        return S_OK;
     
    20442057    HRESULT rc = S_OK;
    20452058
    2046     /* load the config file */
    2047     CFGHANDLE configLoader = 0;
    2048     rc = openConfigLoader (&configLoader);
    2049     if (FAILED (rc))
    2050         return  E_FAIL;
    2051 
    2052     CFGNODE machineNode;
    2053     CFGNODE extraDataNode;
    2054 
    2055     /* navigate to the right position */
    2056     if (VBOX_SUCCESS(CFGLDRGetNode(configLoader, "VirtualBox/Machine", 0, &machineNode)) &&
    2057         VBOX_SUCCESS(CFGLDRGetChildNode(machineNode, "ExtraData", 0, &extraDataNode)))
    2058     {
    2059         /* check if it exists */
    2060         bool found = false;
    2061         unsigned count;
    2062         CFGNODE extraDataItemNode;
    2063         CFGLDRCountChildren(extraDataNode, "ExtraDataItem", &count);
    2064         for (unsigned i = 0; (i < count) && (found == false); i++)
    2065         {
    2066             Bstr name;
    2067             CFGLDRGetChildNode(extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    2068             CFGLDRQueryBSTR(extraDataItemNode, "name", name.asOutParam());
    2069             if (name == aKey)
     2059    try
     2060    {
     2061        using namespace settings;
     2062
     2063        /* load the config file */
     2064        File file (File::ReadWrite, mData->mHandleCfgFile,
     2065                   Utf8Str (mData->mConfigFileFull));
     2066        XmlTreeBackend tree;
     2067
     2068        rc = VirtualBox::loadSettingsTree_Again (tree, file);
     2069        CheckComRCReturnRC (rc);
     2070
     2071        const Utf8Str key = aKey;
     2072
     2073        Key machineNode = tree.rootKey().key ("Machine");
     2074        Key extraDataNode = machineNode.findKey ("ExtraData");
     2075
     2076        if (!extraDataNode.isNull())
     2077        {
     2078            /* check if the key exists */
     2079            Key::List items = extraDataNode.keys ("ExtraDataItem");
     2080            for (Key::List::const_iterator it = items.begin();
     2081                 it != items.end(); ++ it)
    20702082            {
    2071                 found = true;
    2072                 CFGLDRQueryBSTR(extraDataItemNode, "value", aValue);
     2083                if (key == (*it).stringValue ("name"))
     2084                {
     2085                    Bstr val = (*it).stringValue ("value");
     2086                    val.cloneTo (aValue);
     2087                    break;
     2088                }
    20732089            }
    2074             CFGLDRReleaseNode(extraDataItemNode);
    2075         }
    2076 
    2077         CFGLDRReleaseNode(extraDataNode);
    2078         CFGLDRReleaseNode(machineNode);
    2079     }
    2080 
    2081     rc = closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
     2090        }
     2091    }
     2092    catch (...)
     2093    {
     2094        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     2095    }
    20822096
    20832097    return rc;
     
    20852099
    20862100/**
    2087  *  @note Locks mParent for reading + this object for writing.
     2101 *  @note Locks mParent for writing + this object for writing.
    20882102 */
    20892103STDMETHODIMP Machine::SetExtraData (INPTR BSTR aKey, INPTR BSTR aValue)
     
    20952109    CheckComRCReturnRC (autoCaller.rc());
    20962110
    2097     /* VirtualBox::onExtraDataCanChange() needs mParent lock */
    2098     AutoMultiLock <2> alock (mParent->rlock(), this->wlock());
     2111    /* VirtualBox::onExtraDataCanChange() and saveSettings() need mParent
     2112     * lock (saveSettings() needs a write one) */
     2113    AutoMultiLock <2> alock (mParent->wlock(), this->wlock());
    20992114
    21002115    if (mType == IsSnapshotMachine)
     
    21072122    HRESULT rc = S_OK;
    21082123
    2109     /*
    2110      *  if we're ready and isConfigLocked() is FALSE then it means
    2111      *  that no config file exists yet, so call saveSettings() to create one
    2112      */
     2124    /* If we're ready and isConfigLocked() is FALSE then it means that no
     2125     * config file exists yet, so call saveSettings() to create one. */
    21132126    if (!isConfigLocked())
    21142127    {
    21152128        rc = saveSettings (false /* aMarkCurStateAsModified */);
    2116         if (FAILED (rc))
    2117             return rc;
    2118     }
    2119 
    2120     /* load the config file */
    2121     CFGHANDLE configLoader = 0;
    2122     rc = openConfigLoader (&configLoader);
    2123     if (FAILED (rc))
    2124         return rc;
    2125 
    2126     CFGNODE machineNode = 0;
    2127     CFGNODE extraDataNode = 0;
    2128 
    2129     int vrc = CFGLDRGetNode (configLoader, "VirtualBox/Machine", 0, &machineNode);
    2130     if (VBOX_FAILURE (vrc))
    2131         vrc = CFGLDRCreateNode (configLoader, "VirtualBox/Machine", &machineNode);
    2132 
    2133     vrc = CFGLDRGetChildNode (machineNode, "ExtraData", 0, &extraDataNode);
    2134     if (VBOX_FAILURE (vrc) && aValue)
    2135         vrc = CFGLDRCreateChildNode (machineNode, "ExtraData", &extraDataNode);
    2136 
    2137     if (extraDataNode)
    2138     {
    2139         CFGNODE extraDataItemNode = 0;
     2129        CheckComRCReturnRC (rc);
     2130    }
     2131
     2132    try
     2133    {
     2134        using namespace settings;
     2135
     2136        /* load the config file */
     2137        File file (File::ReadWrite, mData->mHandleCfgFile,
     2138                   Utf8Str (mData->mConfigFileFull));
     2139        XmlTreeBackend tree;
     2140
     2141        rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
     2142        CheckComRCReturnRC (rc);
     2143
     2144        const Utf8Str key = aKey;
    21402145        Bstr oldVal;
    21412146
    2142         unsigned count;
    2143         CFGLDRCountChildren (extraDataNode, "ExtraDataItem", &count);
    2144 
    2145         for (unsigned i = 0; i < count; i++)
    2146         {
    2147             CFGLDRGetChildNode (extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    2148             Bstr name;
    2149             CFGLDRQueryBSTR (extraDataItemNode, "name", name.asOutParam());
    2150             if (name == aKey)
     2147        Key machineNode = tree.rootKey().key ("Machine");
     2148        Key extraDataNode = machineNode.createKey ("ExtraData");
     2149        Key extraDataItemNode;
     2150
     2151        Key::List items = extraDataNode.keys ("ExtraDataItem");
     2152        for (Key::List::const_iterator it = items.begin();
     2153             it != items.end(); ++ it)
     2154        {
     2155            if (key == (*it).stringValue ("name"))
    21512156            {
    2152                 CFGLDRQueryBSTR (extraDataItemNode, "value", oldVal.asOutParam());
     2157                extraDataItemNode = *it;
     2158                oldVal = (*it).stringValue ("value");
    21532159                break;
    21542160            }
    2155             CFGLDRReleaseNode (extraDataItemNode);
    2156             extraDataItemNode = 0;
    2157         }
    2158 
    2159         /*
    2160          *  When no key is found, oldVal is null
    2161          *  Note:
    2162          *  1. when oldVal is null, |oldVal == (BSTR) NULL| is true
    2163          *  2. we cannot do |oldVal != aValue| because it will compare
    2164          *  BSTR pointers instead of strings (due to type conversion ops)
    2165          */
    2166         changed = !(oldVal == aValue);
     2161        }
     2162
     2163        /* When no key is found, oldVal is null */
     2164        changed = oldVal != aValue;
    21672165
    21682166        if (changed)
     
    21762174                LogWarningFunc (("Someone vetoed! Change refused%s%ls\n",
    21772175                                 sep, err));
    2178                 rc = setError (E_ACCESSDENIED,
     2176                return setError (E_ACCESSDENIED,
    21792177                    tr ("Could not set extra data because someone refused "
    21802178                        "the requested change of '%ls' to '%ls'%s%ls"),
    21812179                    aKey, aValue, sep, err);
    21822180            }
     2181
     2182            if (aValue != NULL)
     2183            {
     2184                if (extraDataItemNode.isNull())
     2185                {
     2186                    extraDataItemNode = extraDataNode.appendKey ("ExtraDataItem");
     2187                    extraDataItemNode.setStringValue ("name", key);
     2188                }
     2189                extraDataItemNode.setStringValue ("value", Utf8Str (aValue));
     2190            }
    21832191            else
    21842192            {
    2185                 if (aValue)
    2186                 {
    2187                     if (!extraDataItemNode)
    2188                     {
    2189                         /* create a new item */
    2190                         CFGLDRAppendChildNode (extraDataNode, "ExtraDataItem",
    2191                                                &extraDataItemNode);
    2192                         CFGLDRSetBSTR (extraDataItemNode, "name", aKey);
    2193                     }
    2194                     CFGLDRSetBSTR (extraDataItemNode, "value", aValue);
    2195                 }
    2196                 else
    2197                 {
    2198                     /* an old value does for sure exist here */
    2199                     CFGLDRDeleteNode (extraDataItemNode);
    2200                     extraDataItemNode = 0;
    2201                 }
     2193                /* an old value does for sure exist here (XML schema
     2194                 * guarantees that "value" may not absent in the
     2195                 * <ExtraDataItem> element) */
     2196                Assert (!extraDataItemNode.isNull());
     2197                extraDataItemNode.zap();
    22022198            }
    2203         }
    2204 
    2205         if (extraDataItemNode)
    2206             CFGLDRReleaseNode (extraDataItemNode);
    2207 
    2208         CFGLDRReleaseNode (extraDataNode);
    2209     }
    2210 
    2211     CFGLDRReleaseNode (machineNode);
    2212 
     2199
     2200            /* save settings on success */
     2201            rc = VirtualBox::saveSettingsTree (tree, file);
     2202            CheckComRCReturnRC (rc);
     2203        }
     2204    }
     2205    catch (...)
     2206    {
     2207        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     2208    }
     2209
     2210    /* fire a notification */
    22132211    if (SUCCEEDED (rc) && changed)
    2214         rc = closeConfigLoader (configLoader, true /* aSaveBeforeClose */);
    2215     else
    2216         closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
    2217 
    2218     /* fire an event */
    2219     if (SUCCEEDED (rc) && changed)
    2220     {
    22212212        mParent->onExtraDataChange (mData->mUuid, aKey, aValue);
    2222     }
    22232213
    22242214    return rc;
     
    22302220    CheckComRCReturnRC (autoCaller.rc());
    22312221
    2232     /* Under some circumstancies, saveSettings() needs mParent lock */
     2222    /* saveSettings() needs mParent lock */
    22332223    AutoMultiLock <2> alock (mParent->wlock(), this->wlock());
    22342224
     
    23232313        /* delete the directory that contains the settings file, but only
    23242314         * if it matches the VM name (i.e. a structure created by default in
    2325          * openConfigLoader()) */
     2315         * prepareSaveSettings()) */
    23262316        {
    23272317            Utf8Str settingsDir;
     
    25452535 *  @note locks this object for reading.
    25462536 */
    2547 HRESULT Machine::saveRegistryEntry (CFGNODE aEntryNode)
    2548 {
    2549     AssertReturn (aEntryNode, E_FAIL);
     2537HRESULT Machine::saveRegistryEntry (settings::Key &aEntryNode)
     2538{
     2539    AssertReturn (!aEntryNode.isNull(), E_FAIL);
    25502540
    25512541    AutoLimitedCaller autoCaller (this);
     
    25552545
    25562546    /* UUID */
    2557     CFGLDRSetUUID (aEntryNode, "uuid", mData->mUuid.raw());
     2547    aEntryNode.setValue <Guid> ("uuid", mData->mUuid);
    25582548    /* settings file name (possibly, relative) */
    2559     CFGLDRSetBSTR (aEntryNode, "src", mData->mConfigFile);
     2549    aEntryNode.setValue <Bstr> ("src", mData->mConfigFile);
    25602550
    25612551    return S_OK;
     
    32903280 *  on the current thread because this will block Machine::uninit().
    32913281 *
    3292  *  @note Locks this object and children for writing!
     3282 *  @note Must be called from mParent's write lock. Locks this object and
     3283 *  children for writing.
    32933284 */
    32943285HRESULT Machine::trySetRegistered (BOOL aRegistered)
    32953286{
     3287    AssertReturn (mParent->isLockedOnCurrentThread(), E_FAIL);
     3288
    32963289    AutoLimitedCaller autoCaller (this);
    32973290    AssertComRCReturnRC (autoCaller.rc());
     
    37833776        mData->mMachineState = aMachineState;
    37843777
    3785         RTTIMESPEC time;
    3786         mData->mLastStateChange = RTTimeSpecGetMilli(RTTimeNow(&time));
     3778        RTTimeNow (&mData->mLastStateChange);
    37873779
    37883780        mParent->onMachineStateChange (mData->mUuid, aMachineState);
     
    38513843    HRESULT rc = S_OK;
    38523844
    3853     CFGHANDLE configLoader = NULL;
    3854     char *loaderError = NULL;
    3855     int vrc = CFGLDRLoad (&configLoader,
    3856                           Utf8Str (mData->mConfigFileFull), mData->mHandleCfgFile,
    3857                           XmlSchemaNS, true, cfgLdrEntityResolver,
    3858                           &loaderError);
    3859     if (VBOX_FAILURE (vrc))
    3860     {
    3861         rc = setError (E_FAIL,
    3862             tr ("Could not load the settings file '%ls' (%Vrc)%s%s"),
    3863             mData->mConfigFileFull.raw(), vrc,
    3864             loaderError ? ".\n" : "", loaderError ? loaderError : "");
    3865 
    3866         if (loaderError)
    3867             RTMemTmpFree (loaderError);
    3868 
    3869         LogFlowThisFuncLeave();
    3870         return rc;
    3871     }
    3872 
    3873     /*
    3874      *  When reading the XML, we assume it has been validated, so we don't
    3875      *  do any structural checks here, Just Assert() some things.
    3876      */
    3877 
    3878     CFGNODE machineNode = 0;
    3879     CFGLDRGetNode (configLoader, "VirtualBox/Machine", 0, &machineNode);
    3880 
    3881     do
    3882     {
    3883         ComAssertBreak (machineNode, rc = E_FAIL);
     3845    try
     3846    {
     3847        using namespace settings;
     3848
     3849        File file (File::Read, mData->mHandleCfgFile,
     3850                   Utf8Str (mData->mConfigFileFull));
     3851        XmlTreeBackend tree;
     3852
     3853        rc = VirtualBox::loadSettingsTree_FirstTime (tree, file);
     3854        CheckComRCThrowRC (rc);
     3855
     3856        Key machineNode = tree.rootKey().key ("Machine");
    38843857
    38853858        /* uuid (required) */
    3886         Guid id;
    3887         CFGLDRQueryUUID (machineNode, "uuid", id.ptr());
     3859        Guid id = machineNode.value <Guid> ("uuid");
    38883860
    38893861        /* If the stored UUID is not empty, it means the registered machine
     
    38943866            if (mData->mUuid != id)
    38953867            {
    3896                 rc = setError (E_FAIL,
     3868                throw setError (E_FAIL,
    38973869                    tr ("Machine UUID {%Vuuid} in '%ls' doesn't match its "
    38983870                        "UUID {%s} in the registry file '%ls'"),
     
    39003872                    mData->mUuid.toString().raw(),
    39013873                    mParent->settingsFileName().raw());
    3902                 break;
    39033874            }
    39043875        }
     
    39073878
    39083879        /* name (required) */
    3909         CFGLDRQueryBSTR (machineNode, "name", mUserData->mName.asOutParam());
     3880        mUserData->mName = machineNode.stringValue ("name");
    39103881
    39113882        /* nameSync (optional, default is true) */
    3912         {
    3913             bool nameSync = true;
    3914             CFGLDRQueryBool (machineNode, "nameSync", &nameSync);
    3915             mUserData->mNameSync = nameSync;
    3916         }
     3883        mUserData->mNameSync = machineNode.value <bool> ("nameSync");
    39173884
    39183885        /* Description (optional, default is null) */
    39193886        {
    3920             CFGNODE descNode = 0;
    3921             CFGLDRGetChildNode (machineNode, "Description", 0, &descNode);
    3922             if (descNode)
    3923             {
    3924                 CFGLDRQueryBSTR (descNode, NULL,
    3925                                  mUserData->mDescription.asOutParam());
    3926                 CFGLDRReleaseNode (descNode);
    3927             }
     3887            Key descNode = machineNode.findKey ("Description");
     3888            if (!descNode.isNull())
     3889                mUserData->mDescription = descNode.keyStringValue();
    39283890            else
    39293891                mUserData->mDescription.setNull();
     
    39323894        /* OSType (required) */
    39333895        {
    3934             CFGLDRQueryBSTR (machineNode, "OSType",
    3935                              mUserData->mOSTypeId.asOutParam());
     3896            mUserData->mOSTypeId = machineNode.stringValue ("OSType");
    39363897
    39373898            /* look up the object by Id to check it is valid */
     
    39393900            rc = mParent->GetGuestOSType (mUserData->mOSTypeId,
    39403901                                          guestOSType.asOutParam());
    3941             if (FAILED (rc))
    3942                 break;
     3902            CheckComRCThrowRC (rc);
    39433903        }
    39443904
    39453905        /* stateFile (optional) */
    39463906        {
    3947             Bstr stateFilePath;
    3948             CFGLDRQueryBSTR (machineNode, "stateFile", stateFilePath.asOutParam());
     3907            Bstr stateFilePath = machineNode.stringValue ("stateFile");
    39493908            if (stateFilePath)
    39503909            {
     
    39533912                if (VBOX_FAILURE (vrc))
    39543913                {
    3955                     rc = setError (E_FAIL,
     3914                    throw setError (E_FAIL,
    39563915                        tr ("Invalid saved state file path: '%ls' (%Vrc)"),
    39573916                        stateFilePath.raw(), vrc);
    3958                     break;
    39593917                }
    39603918                mSSData->mStateFilePath = stateFilePathFull;
     
    39663924        /*
    39673925         *  currentSnapshot ID (optional)
    3968          *  Note that due to XML Schema constaraints this attribute, when present,
    3969          *  will guaranteedly refer to an existing snapshot definition in XML
     3926         *
     3927         *  Note that due to XML Schema constaraints, this attribute, when
     3928         *  present, will guaranteedly refer to an existing snapshot
     3929         *  definition in XML
    39703930         */
    3971         Guid currentSnapshotId;
    3972         CFGLDRQueryUUID (machineNode, "currentSnapshot", currentSnapshotId.ptr());
     3931        Guid currentSnapshotId = machineNode.valueOr <Guid> ("currentSnapshot",
     3932                                                             Guid());
    39733933
    39743934        /* snapshotFolder (optional) */
    39753935        {
    3976             Bstr folder;
    3977             CFGLDRQueryBSTR (machineNode, "snapshotFolder", folder.asOutParam());
     3936            Bstr folder = machineNode.stringValue ("snapshotFolder");
    39783937            rc = COMSETTER(SnapshotFolder) (folder);
    3979             if (FAILED (rc))
    3980                 break;
    3981         }
     3938            CheckComRCThrowRC (rc);
     3939        }
     3940
     3941        /* currentStateModified (optional, default is true) */
     3942        mData->mCurrentStateModified = machineNode.value <bool> ("currentStateModified");
    39823943
    39833944        /* lastStateChange (optional, for compatiblity) */
    39843945        {
    3985             int64_t lastStateChange = 0;
    3986             CFGLDRQueryDateTime (machineNode, "lastStateChange", &lastStateChange);
    3987             if (lastStateChange == 0)
    3988             {
    3989                 /// @todo (dmik) until lastStateChange is the required attribute,
    3990                 //  we simply set it to the current time if missing in the config
    3991                 RTTIMESPEC time;
    3992                 lastStateChange = RTTimeSpecGetMilli (RTTimeNow (&time));
    3993             }
    3994             mData->mLastStateChange = lastStateChange;
    3995         }
    3996 
    3997         /* aborted (optional) */
    3998         bool aborted = false;
    3999         CFGLDRQueryBool (machineNode, "aborted", &aborted);
    4000 
    4001         /* currentStateModified (optional, default is true) */
    4002         mData->mCurrentStateModified = TRUE;
    4003         {
    4004             bool val = true;
    4005             CFGLDRQueryBool (machineNode, "currentStateModified", &val);
    4006             mData->mCurrentStateModified = val;
    4007         }
     3946            /// @todo (dmik) until lastStateChange is the required attribute,
     3947            //  we simply set it to the current time if missing in the config
     3948            RTTIMESPEC now;
     3949            RTTimeNow (&now);
     3950            mData->mLastStateChange =
     3951                machineNode.valueOr <RTTIMESPEC> ("lastStateChange", now);
     3952        }
     3953
     3954        /* aborted (optional, default is false) */
     3955        bool aborted = machineNode.value <bool> ("aborted");
    40083956
    40093957        /*
     
    40163964        /* Snapshot node (optional) */
    40173965        {
    4018             CFGNODE snapshotNode = 0;
    4019             CFGLDRGetChildNode (machineNode, "Snapshot", 0, &snapshotNode);
    4020             if (snapshotNode)
     3966            Key snapshotNode = machineNode.findKey ("Snapshot");
     3967            if (!snapshotNode.isNull())
    40213968            {
    40223969                /* read all snapshots recursively */
    40233970                rc = loadSnapshot (snapshotNode, currentSnapshotId, NULL);
    4024                 CFGLDRReleaseNode (snapshotNode);
    4025                 if (FAILED (rc))
    4026                     break;
     3971                CheckComRCThrowRC (rc);
    40273972            }
    40283973        }
    40293974
    40303975        /* Hardware node (required) */
    4031         {
    4032             CFGNODE hardwareNode = 0;
    4033             CFGLDRGetChildNode (machineNode, "Hardware", 0, &hardwareNode);
    4034             ComAssertBreak (hardwareNode, rc = E_FAIL);
    4035             rc = loadHardware (hardwareNode);
    4036             CFGLDRReleaseNode (hardwareNode);
    4037             if (FAILED (rc))
    4038                 break;
    4039         }
     3976        rc = loadHardware (machineNode.key ("Hardware"));
     3977        CheckComRCThrowRC (rc);
    40403978
    40413979        /* HardDiskAttachments node (required) */
    4042         {
    4043             CFGNODE hdasNode = 0;
    4044             CFGLDRGetChildNode (machineNode, "HardDiskAttachments", 0, &hdasNode);
    4045             ComAssertBreak (hdasNode, rc = E_FAIL);
    4046 
    4047             rc = loadHardDisks (hdasNode, aRegistered);
    4048             CFGLDRReleaseNode (hdasNode);
    4049             if (FAILED (rc))
    4050                 break;
    4051         }
     3980        rc = loadHardDisks (machineNode.key ("HardDiskAttachments"), aRegistered);
     3981        CheckComRCThrowRC (rc);
    40523982
    40533983        /*
     
    40734003        }
    40744004    }
    4075     while (0);
    4076 
    4077     if (machineNode)
    4078         CFGLDRReleaseNode (machineNode);
    4079 
    4080     CFGLDRFree (configLoader);
     4005    catch (HRESULT err)
     4006    {
     4007        /* we assume that error info is set by the thrower */
     4008        rc = err;
     4009    }
     4010    catch (...)
     4011    {
     4012        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     4013    }
    40814014
    40824015    LogFlowThisFuncLeave();
     
    40874020 *  Recursively loads all snapshots starting from the given.
    40884021 *
    4089  *  @param aNode            <Snapshot> node
    4090  *  @param aCurSnapshotId   current snapshot ID from the settings file
    4091  *  @param aParentSnapshot  parent snapshot
     4022 *  @param aNode            <Snapshot> node.
     4023 *  @param aCurSnapshotId   Current snapshot ID from the settings file.
     4024 *  @param aParentSnapshot  Parent snapshot.
    40924025 */
    4093 HRESULT Machine::loadSnapshot (CFGNODE aNode, const Guid &aCurSnapshotId,
     4026HRESULT Machine::loadSnapshot (const settings::Key &aNode,
     4027                               const Guid &aCurSnapshotId,
    40944028                               Snapshot *aParentSnapshot)
    40954029{
    4096     AssertReturn (aNode, E_INVALIDARG);
     4030    using namespace settings;
     4031
     4032    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    40974033    AssertReturn (mType == IsMachine, E_FAIL);
    40984034
    4099     // create a snapshot machine object
     4035    /* create a snapshot machine object */
    41004036    ComObjPtr <SnapshotMachine> snapshotMachine;
    41014037    snapshotMachine.createObject();
     
    41034039    HRESULT rc = S_OK;
    41044040
    4105     Guid uuid; // required
    4106     CFGLDRQueryUUID (aNode, "uuid", uuid.ptr());
    4107 
    4108     Bstr stateFilePath; // optional
    4109     CFGLDRQueryBSTR (aNode, "stateFile", stateFilePath.asOutParam());
    4110     if (stateFilePath)
    4111     {
    4112         Utf8Str stateFilePathFull = stateFilePath;
    4113         int vrc = calculateFullPath (stateFilePathFull, stateFilePathFull);
    4114         if (VBOX_FAILURE (vrc))
    4115             return setError (E_FAIL,
    4116                 tr ("Invalid saved state file path: '%ls' (%Vrc)"),
    4117                 stateFilePath.raw(), vrc);
    4118 
    4119         stateFilePath = stateFilePathFull;
    4120     }
    4121 
    4122     do
    4123     {
    4124         // Hardware node (required)
    4125         CFGNODE hardwareNode = 0;
    4126         CFGLDRGetChildNode (aNode, "Hardware", 0, &hardwareNode);
    4127         ComAssertBreak (hardwareNode, rc = E_FAIL);
    4128 
    4129         do
    4130         {
    4131             // HardDiskAttachments node (required)
    4132             CFGNODE hdasNode = 0;
    4133             CFGLDRGetChildNode (aNode, "HardDiskAttachments", 0, &hdasNode);
    4134             ComAssertBreak (hdasNode, rc = E_FAIL);
    4135 
    4136             // initialize the snapshot machine
    4137             rc = snapshotMachine->init (this, hardwareNode, hdasNode,
    4138                                         uuid, stateFilePath);
    4139 
    4140             CFGLDRReleaseNode (hdasNode);
    4141         }
    4142         while (0);
    4143 
    4144         CFGLDRReleaseNode (hardwareNode);
    4145     }
    4146     while (0);
    4147 
    4148     if (FAILED (rc))
    4149         return rc;
    4150 
    4151     // create a snapshot object
     4041    /* required */
     4042    Guid uuid = aNode.value <Guid> ("uuid");
     4043
     4044    {
     4045        /* optional */
     4046        Bstr stateFilePath = aNode.stringValue ("stateFile");
     4047        if (stateFilePath)
     4048        {
     4049            Utf8Str stateFilePathFull = stateFilePath;
     4050            int vrc = calculateFullPath (stateFilePathFull, stateFilePathFull);
     4051            if (VBOX_FAILURE (vrc))
     4052                return setError (E_FAIL,
     4053                                 tr ("Invalid saved state file path: '%ls' (%Vrc)"),
     4054                                 stateFilePath.raw(), vrc);
     4055
     4056            stateFilePath = stateFilePathFull;
     4057        }
     4058
     4059        /* Hardware node (required) */
     4060        Key hardwareNode = aNode.key ("Hardware");
     4061
     4062        /* HardDiskAttachments node (required) */
     4063        Key hdasNode = aNode.key ("HardDiskAttachments");
     4064
     4065        /* initialize the snapshot machine */
     4066        rc = snapshotMachine->init (this, hardwareNode, hdasNode,
     4067                                    uuid, stateFilePath);
     4068        CheckComRCReturnRC (rc);
     4069    }
     4070
     4071    /* create a snapshot object */
    41524072    ComObjPtr <Snapshot> snapshot;
    41534073    snapshot.createObject();
    41544074
    41554075    {
    4156         Bstr name; // required
    4157         CFGLDRQueryBSTR (aNode, "name", name.asOutParam());
    4158 
    4159         LONG64 timeStamp = 0; // required
    4160         CFGLDRQueryDateTime (aNode, "timeStamp", &timeStamp);
    4161 
    4162         Bstr description; // optional
    4163         {
    4164             CFGNODE descNode = 0;
    4165             CFGLDRGetChildNode (aNode, "Description", 0, &descNode);
    4166             if (descNode)
    4167             {
    4168                 CFGLDRQueryBSTR (descNode, NULL, description.asOutParam());
    4169                 CFGLDRReleaseNode (descNode);
    4170             }
    4171         }
    4172 
    4173         // initialize the snapshot
     4076        /* required */
     4077        Bstr name = aNode.stringValue ("name");
     4078
     4079        /* required */
     4080        RTTIMESPEC timeStamp = aNode.value <RTTIMESPEC> ("timeStamp");
     4081
     4082        /* optional */
     4083        Bstr description;
     4084        {
     4085            Key descNode = aNode.findKey ("Description");
     4086            if (!descNode.isNull())
     4087                description = descNode.keyStringValue();
     4088        }
     4089
     4090        /* initialize the snapshot */
    41744091        rc = snapshot->init (uuid, name, description, timeStamp,
    41754092                             snapshotMachine, aParentSnapshot);
    4176         if (FAILED (rc))
    4177             return rc;
    4178     }
    4179 
    4180     // memorize the first snapshot if necessary
     4093        CheckComRCReturnRC (rc);
     4094    }
     4095
     4096    /* memorize the first snapshot if necessary */
    41814097    if (!mData->mFirstSnapshot)
    41824098        mData->mFirstSnapshot = snapshot;
    41834099
    4184     // memorize the current snapshot when appropriate
     4100    /* memorize the current snapshot when appropriate */
    41854101    if (!mData->mCurrentSnapshot && snapshot->data().mId == aCurSnapshotId)
    41864102        mData->mCurrentSnapshot = snapshot;
    41874103
    4188     // Snapshots node (optional)
    4189     {
    4190         CFGNODE snapshotsNode = 0;
    4191         CFGLDRGetChildNode (aNode, "Snapshots", 0, &snapshotsNode);
    4192         if (snapshotsNode)
    4193         {
    4194             unsigned cbDisks = 0;
    4195             CFGLDRCountChildren (snapshotsNode, "Snapshot", &cbDisks);
    4196             for (unsigned i = 0; i < cbDisks && SUCCEEDED (rc); i++)
     4104    /* Snapshots node (optional) */
     4105    {
     4106        Key snapshotsNode = aNode.findKey ("Snapshots");
     4107        if (!snapshotsNode.isNull())
     4108        {
     4109            Key::List children = snapshotsNode.keys ("Snapshot");
     4110            for (Key::List::const_iterator it = children.begin();
     4111                 it != children.end(); ++ it)
    41974112            {
    4198                 CFGNODE snapshotNode;
    4199                 CFGLDRGetChildNode (snapshotsNode, "Snapshot", i, &snapshotNode);
    4200                 ComAssertBreak (snapshotNode, rc = E_FAIL);
    4201 
    4202                 rc = loadSnapshot (snapshotNode, aCurSnapshotId, snapshot);
    4203 
    4204                 CFGLDRReleaseNode (snapshotNode);
     4113                rc = loadSnapshot ((*it), aCurSnapshotId, snapshot);
     4114                CheckComRCBreakRC (rc);
    42054115            }
    4206 
    4207             CFGLDRReleaseNode (snapshotsNode);
    42084116        }
    42094117    }
     
    42134121
    42144122/**
    4215  *  @param aNode    <Hardware> node
     4123 *  @param aNode    <Hardware> node.
    42164124 */
    4217 HRESULT Machine::loadHardware (CFGNODE aNode)
    4218 {
    4219     AssertReturn (aNode, E_INVALIDARG);
     4125HRESULT Machine::loadHardware (const settings::Key &aNode)
     4126{
     4127    using namespace settings;
     4128
     4129    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    42204130    AssertReturn (mType == IsMachine || mType == IsSnapshotMachine, E_FAIL);
     4131
     4132    HRESULT rc = S_OK;
    42214133
    42224134    /* CPU node (currently not required) */
     
    42254137        mHWData->mHWVirtExEnabled = TriStateBool_Default;
    42264138
    4227         CFGNODE cpuNode = 0;
    4228         CFGLDRGetChildNode (aNode, "CPU", 0, &cpuNode);
    4229         if (cpuNode)
    4230         {
    4231             CFGNODE hwVirtExNode = 0;
    4232             CFGLDRGetChildNode (cpuNode, "HardwareVirtEx", 0, &hwVirtExNode);
    4233             if (hwVirtExNode)
     4139        Key cpuNode = aNode.findKey ("CPU");
     4140        if (!cpuNode.isNull())
     4141        {
     4142            Key hwVirtExNode = cpuNode.key ("HardwareVirtEx");
     4143            if (!hwVirtExNode.isNull())
    42344144            {
    4235                 Bstr hwVirtExEnabled;
    4236                 CFGLDRQueryBSTR (hwVirtExNode, "enabled", hwVirtExEnabled.asOutParam());
    4237                 if      (hwVirtExEnabled == L"false")
     4145                const char *enabled = hwVirtExNode.stringValue ("enabled");
     4146                if      (strcmp (enabled, "false") == 0)
    42384147                    mHWData->mHWVirtExEnabled = TriStateBool_False;
    4239                 else if (hwVirtExEnabled == L"true")
     4148                else if (strcmp (enabled, "true") == 0)
    42404149                    mHWData->mHWVirtExEnabled = TriStateBool_True;
    42414150                else
    42424151                    mHWData->mHWVirtExEnabled = TriStateBool_Default;
    4243                 CFGLDRReleaseNode (hwVirtExNode);
    42444152            }
    4245             CFGLDRReleaseNode (cpuNode);
    42464153        }
    42474154    }
     
    42494156    /* Memory node (required) */
    42504157    {
    4251         CFGNODE memoryNode = 0;
    4252         CFGLDRGetChildNode (aNode, "Memory", 0, &memoryNode);
    4253         ComAssertRet (memoryNode, E_FAIL);
    4254 
    4255         uint32_t RAMSize;
    4256         CFGLDRQueryUInt32 (memoryNode, "RAMSize", &RAMSize);
    4257         mHWData->mMemorySize = RAMSize;
    4258         CFGLDRReleaseNode (memoryNode);
     4158        Key memoryNode = aNode.key ("Memory");
     4159
     4160        mHWData->mMemorySize = memoryNode.value <ULONG> ("RAMSize");
    42594161    }
    42604162
     
    42654167            mHWData->mBootOrder [i] = DeviceType_NoDevice;
    42664168
    4267         CFGNODE bootNode = 0;
    4268         CFGLDRGetChildNode (aNode, "Boot", 0, &bootNode);
    4269         ComAssertRet (bootNode, E_FAIL);
    4270 
    4271         HRESULT rc = S_OK;
    4272 
    4273         unsigned cOrder;
    4274         CFGLDRCountChildren (bootNode, "Order", &cOrder);
    4275         for (unsigned i = 0; i < cOrder; i++)
    4276         {
    4277             CFGNODE orderNode = 0;
    4278             CFGLDRGetChildNode (bootNode, "Order", i, &orderNode);
    4279             ComAssertBreak (orderNode, rc = E_FAIL);
    4280 
     4169        Key bootNode = aNode.key ("Boot");
     4170
     4171        Key::List orderNodes = bootNode.keys ("Order");
     4172        for (Key::List::const_iterator it = orderNodes.begin();
     4173             it != orderNodes.end(); ++ it)
     4174        {
    42814175            /* position (required) */
    42824176            /* position unicity is guaranteed by XML Schema */
    4283             uint32_t position = 0;
    4284             CFGLDRQueryUInt32 (orderNode, "position", &position);
     4177            uint32_t position = (*it).value <uint32_t> ("position");
    42854178            -- position;
    42864179            Assert (position < ELEMENTS (mHWData->mBootOrder));
    42874180
    42884181            /* device (required) */
    4289             Bstr device;
    4290             CFGLDRQueryBSTR (orderNode, "device", device.asOutParam());
    4291             if      (device == L"None")
     4182            const char *device = (*it).stringValue ("device");
     4183            if      (strcmp (device, "None") == 0)
    42924184                mHWData->mBootOrder [position] = DeviceType_NoDevice;
    4293             else if (device == L"Floppy")
     4185            else if (strcmp (device, "Floppy") == 0)
    42944186                mHWData->mBootOrder [position] = DeviceType_FloppyDevice;
    4295             else if (device == L"DVD")
     4187            else if (strcmp (device, "DVD") == 0)
    42964188                mHWData->mBootOrder [position] = DeviceType_DVDDevice;
    4297             else if (device == L"HardDisk")
     4189            else if (strcmp (device, "HardDisk") == 0)
    42984190                mHWData->mBootOrder [position] = DeviceType_HardDiskDevice;
    4299             else if (device == L"Network")
     4191            else if (strcmp (device, "Network") == 0)
    43004192                mHWData->mBootOrder [position] = DeviceType_NetworkDevice;
    43014193            else
    4302                 ComAssertMsgFailed (("Invalid device: %ls\n", device.raw()));
    4303 
    4304             CFGLDRReleaseNode (orderNode);
    4305         }
    4306 
    4307         CFGLDRReleaseNode (bootNode);
    4308         if (FAILED (rc))
    4309             return rc;
     4194                ComAssertMsgFailed (("Invalid device: %s\n", device));
     4195        }
    43104196    }
    43114197
    43124198    /* Display node (required) */
    43134199    {
    4314         CFGNODE displayNode = 0;
    4315         CFGLDRGetChildNode (aNode, "Display", 0, &displayNode);
    4316         ComAssertRet (displayNode, E_FAIL);
    4317 
    4318         uint32_t VRAMSize;
    4319         CFGLDRQueryUInt32 (displayNode, "VRAMSize", &VRAMSize);
    4320         mHWData->mVRAMSize = VRAMSize;
    4321 
    4322         uint32_t MonitorCount;
    4323         CFGLDRQueryUInt32 (displayNode, "MonitorCount", &MonitorCount);
    4324         mHWData->mMonitorCount = MonitorCount;
    4325 
    4326         CFGLDRReleaseNode (displayNode);
     4200        Key displayNode = aNode.key ("Display");
     4201
     4202        mHWData->mVRAMSize = displayNode.value <ULONG> ("VRAMSize");
     4203        mHWData->mMonitorCount = displayNode.value <ULONG> ("MonitorCount");
    43274204    }
    43284205
    43294206#ifdef VBOX_VRDP
    4330     /* RemoteDisplay node (optional) */
    4331     {
    4332         CFGNODE remoteDisplayNode = 0;
    4333         CFGLDRGetChildNode (aNode, "RemoteDisplay", 0, &remoteDisplayNode);
    4334         if (remoteDisplayNode)
    4335         {
    4336             HRESULT rc = mVRDPServer->loadSettings (remoteDisplayNode);
    4337             CFGLDRReleaseNode (remoteDisplayNode);
    4338             CheckComRCReturnRC (rc);
    4339         }
    4340     }
     4207    /* RemoteDisplay */
     4208    rc = mVRDPServer->loadSettings (aNode);
     4209    CheckComRCReturnRC (rc);
    43414210#endif
    43424211
    4343     /* BIOS node (required) */
    4344     {
    4345         CFGNODE biosNode = 0;
    4346         CFGLDRGetChildNode (aNode, "BIOS", 0, &biosNode);
    4347         ComAssertRet (biosNode, E_FAIL);
    4348 
    4349         HRESULT rc = S_OK;
    4350 
    4351         do
    4352         {
    4353             /* ACPI */
    4354             {
    4355                 CFGNODE acpiNode = 0;
    4356                 CFGLDRGetChildNode (biosNode, "ACPI", 0, &acpiNode);
    4357                 ComAssertBreak (acpiNode, rc = E_FAIL);
    4358 
    4359                 bool enabled;
    4360                 CFGLDRQueryBool (acpiNode, "enabled", &enabled);
    4361                 mBIOSSettings->COMSETTER(ACPIEnabled)(enabled);
    4362                 CFGLDRReleaseNode (acpiNode);
    4363             }
    4364 
    4365             /* IOAPIC */
    4366             {
    4367                 CFGNODE ioapicNode = 0;
    4368                 CFGLDRGetChildNode (biosNode, "IOAPIC", 0, &ioapicNode);
    4369                 if (ioapicNode)
    4370                 {
    4371                     bool enabled;
    4372                     CFGLDRQueryBool (ioapicNode, "enabled", &enabled);
    4373                     mBIOSSettings->COMSETTER(IOAPICEnabled)(enabled);
    4374                     CFGLDRReleaseNode (ioapicNode);
    4375                 }
    4376             }
    4377 
    4378             /* Logo (optional) */
    4379             {
    4380                 CFGNODE logoNode = 0;
    4381                 CFGLDRGetChildNode (biosNode, "Logo", 0, &logoNode);
    4382                 if (logoNode)
    4383                 {
    4384                     bool enabled = false;
    4385                     CFGLDRQueryBool (logoNode, "fadeIn", &enabled);
    4386                     mBIOSSettings->COMSETTER(LogoFadeIn)(enabled);
    4387                     CFGLDRQueryBool (logoNode, "fadeOut", &enabled);
    4388                     mBIOSSettings->COMSETTER(LogoFadeOut)(enabled);
    4389 
    4390                     uint32_t BIOSLogoDisplayTime;
    4391                     CFGLDRQueryUInt32 (logoNode, "displayTime", &BIOSLogoDisplayTime);
    4392                     mBIOSSettings->COMSETTER(LogoDisplayTime)(BIOSLogoDisplayTime);
    4393 
    4394                     Bstr logoPath;
    4395                     CFGLDRQueryBSTR (logoNode, "imagePath", logoPath.asOutParam());
    4396                     mBIOSSettings->COMSETTER(LogoImagePath)(logoPath);
    4397 
    4398                     CFGLDRReleaseNode (logoNode);
    4399                 }
    4400             }
    4401 
    4402             /* boot menu (optional) */
    4403             {
    4404                 CFGNODE bootMenuNode = 0;
    4405                 CFGLDRGetChildNode (biosNode, "BootMenu", 0, &bootMenuNode);
    4406                 if (bootMenuNode)
    4407                 {
    4408                     Bstr modeStr;
    4409                     BIOSBootMenuMode_T mode;
    4410                     CFGLDRQueryBSTR (bootMenuNode, "mode", modeStr.asOutParam());
    4411                     if (modeStr == L"disabled")
    4412                         mode = BIOSBootMenuMode_Disabled;
    4413                     else if (modeStr == L"menuonly")
    4414                         mode = BIOSBootMenuMode_MenuOnly;
    4415                     else
    4416                         mode = BIOSBootMenuMode_MessageAndMenu;
    4417                     mBIOSSettings->COMSETTER(BootMenuMode)(mode);
    4418 
    4419                     CFGLDRReleaseNode (bootMenuNode);
    4420                 }
    4421             }
    4422 
    4423             /* PXE debug logging (optional) */
    4424             {
    4425                 CFGNODE pxedebugNode = 0;
    4426                 CFGLDRGetChildNode (biosNode, "PXEDebug", 0, &pxedebugNode);
    4427                 if (pxedebugNode)
    4428                 {
    4429                     bool enabled;
    4430                     CFGLDRQueryBool (pxedebugNode, "enabled", &enabled);
    4431                     mBIOSSettings->COMSETTER(PXEDebugEnabled)(enabled);
    4432                     CFGLDRReleaseNode (pxedebugNode);
    4433                 }
    4434             }
    4435 
    4436             /* time offset (optional) */
    4437             {
    4438                 CFGNODE timeOffsetNode = 0;
    4439                 CFGLDRGetChildNode (biosNode, "TimeOffset", 0, &timeOffsetNode);
    4440                 if (timeOffsetNode)
    4441                 {
    4442                     LONG64 timeOffset;
    4443                     CFGLDRQueryInt64 (timeOffsetNode, "value", &timeOffset);
    4444                     mBIOSSettings->COMSETTER(TimeOffset)(timeOffset);
    4445                     CFGLDRReleaseNode (timeOffsetNode);
    4446                 }
    4447             }
    4448 
    4449             /* IDE controller type (optional, defaults to PIIX3) */
    4450             {
    4451                 CFGNODE ideControllerNode = 0;
    4452                 IDEControllerType_T controllerType = IDEControllerType_IDEControllerPIIX3;
    4453                 CFGLDRGetChildNode (biosNode, "IDEController", 0, &ideControllerNode);
    4454                 if (ideControllerNode)
    4455                 {
    4456                     Bstr IDEControllerType;
    4457 
    4458                     CFGLDRQueryBSTR (ideControllerNode, "type", IDEControllerType.asOutParam());
    4459                     ComAssertBreak (IDEControllerType, rc = E_FAIL);
    4460 
    4461                     if (IDEControllerType.compare(Bstr("PIIX3")) == 0)
    4462                         controllerType = IDEControllerType_IDEControllerPIIX3;
    4463                     else if (IDEControllerType.compare(Bstr("PIIX4")) == 0)
    4464                         controllerType = IDEControllerType_IDEControllerPIIX4;
    4465                     else
    4466                         ComAssertBreak (0, rc = E_FAIL);
    4467 
    4468                     CFGLDRReleaseNode (ideControllerNode);
    4469                 }
    4470                 mBIOSSettings->COMSETTER(IDEControllerType)(controllerType);
    4471             }
    4472 
    4473         }
    4474         while (0);
    4475 
    4476         CFGLDRReleaseNode (biosNode);
    4477         if (FAILED (rc))
    4478             return rc;
    4479     }
    4480 
    4481     /* DVD drive (contains either Image or HostDrive or nothing) */
    4482     /// @todo (dmik) move the code to DVDDrive
    4483     {
    4484         HRESULT rc = S_OK;
    4485 
    4486         CFGNODE dvdDriveNode = 0;
    4487         CFGLDRGetChildNode (aNode, "DVDDrive", 0, &dvdDriveNode);
    4488         ComAssertRet (dvdDriveNode, E_FAIL);
    4489 
    4490         bool fPassthrough;
    4491         CFGLDRQueryBool(dvdDriveNode, "passthrough", &fPassthrough);
    4492         mDVDDrive->COMSETTER(Passthrough)(fPassthrough);
    4493 
    4494         CFGNODE typeNode = 0;
    4495 
    4496         do
    4497         {
    4498             CFGLDRGetChildNode (dvdDriveNode, "Image", 0, &typeNode);
    4499             if (typeNode)
    4500             {
    4501                 Guid uuid;
    4502                 CFGLDRQueryUUID (typeNode, "uuid", uuid.ptr());
    4503                 rc = mDVDDrive->MountImage (uuid);
    4504             }
    4505             else
    4506             {
    4507                 CFGLDRGetChildNode (dvdDriveNode, "HostDrive", 0, &typeNode);
    4508                 if (typeNode)
    4509                 {
    4510                     Bstr src;
    4511                     CFGLDRQueryBSTR (typeNode, "src", src.asOutParam());
    4512 
    4513                     /* find the correspoding object */
    4514                     ComPtr <IHost> host;
    4515                     rc = mParent->COMGETTER(Host) (host.asOutParam());
    4516                     ComAssertComRCBreak (rc, rc = rc);
    4517 
    4518                     ComPtr <IHostDVDDriveCollection> coll;
    4519                     rc = host->COMGETTER(DVDDrives) (coll.asOutParam());
    4520                     ComAssertComRCBreak (rc, rc = rc);
    4521 
    4522                     ComPtr <IHostDVDDrive> drive;
    4523                     rc = coll->FindByName (src, drive.asOutParam());
    4524                     if (SUCCEEDED (rc))
    4525                         rc = mDVDDrive->CaptureHostDrive (drive);
    4526                     else if (rc == E_INVALIDARG)
    4527                     {
    4528                         /* the host DVD drive is not currently available. we
    4529                          * assume it will be available later and create an
    4530                          * extra object now */
    4531                         ComObjPtr <HostDVDDrive> hostDrive;
    4532                         hostDrive.createObject();
    4533                         rc = hostDrive->init (src);
    4534                         ComAssertComRCBreak (rc, rc = rc);
    4535                         rc = mDVDDrive->CaptureHostDrive (hostDrive);
    4536                     }
    4537                     else
    4538                         ComAssertComRCBreakRC (rc);
    4539                 }
    4540             }
    4541         }
    4542         while (0);
    4543 
    4544         if (typeNode)
    4545             CFGLDRReleaseNode (typeNode);
    4546         CFGLDRReleaseNode (dvdDriveNode);
    4547 
    4548         if (FAILED (rc))
    4549             return rc;
    4550     }
    4551 
    4552     /* Floppy drive (contains either Image or HostDrive or nothing) */
    4553     /// @todo (dmik) move the code to FloppyDrive
    4554     {
    4555         HRESULT rc = S_OK;
    4556 
    4557         CFGNODE driveNode = 0;
    4558         CFGLDRGetChildNode (aNode, "FloppyDrive", 0, &driveNode);
    4559         ComAssertRet (driveNode, E_FAIL);
    4560 
    4561         BOOL fFloppyEnabled = TRUE;
    4562         CFGLDRQueryBool (driveNode, "enabled", (bool*)&fFloppyEnabled);
    4563         rc = mFloppyDrive->COMSETTER(Enabled)(fFloppyEnabled);
    4564 
    4565         CFGNODE typeNode = 0;
    4566         do
    4567         {
    4568             CFGLDRGetChildNode (driveNode, "Image", 0, &typeNode);
    4569             if (typeNode)
    4570             {
    4571                 Guid uuid;
    4572                 CFGLDRQueryUUID (typeNode, "uuid", uuid.ptr());
    4573                 rc = mFloppyDrive->MountImage (uuid);
    4574             }
    4575             else
    4576             {
    4577                 CFGLDRGetChildNode (driveNode, "HostDrive", 0, &typeNode);
    4578                 if (typeNode)
    4579                 {
    4580                     Bstr src;
    4581                     CFGLDRQueryBSTR (typeNode, "src", src.asOutParam());
    4582 
    4583                     /* find the correspoding object */
    4584                     ComPtr <IHost> host;
    4585                     rc = mParent->COMGETTER(Host) (host.asOutParam());
    4586                     ComAssertComRCBreak (rc, rc = rc);
    4587 
    4588                     ComPtr <IHostFloppyDriveCollection> coll;
    4589                     rc = host->COMGETTER(FloppyDrives) (coll.asOutParam());
    4590                     ComAssertComRCBreak (rc, rc = rc);
    4591 
    4592                     ComPtr <IHostFloppyDrive> drive;
    4593                     rc = coll->FindByName (src, drive.asOutParam());
    4594                     if (SUCCEEDED (rc))
    4595                         rc = mFloppyDrive->CaptureHostDrive (drive);
    4596                     else if (rc == E_INVALIDARG)
    4597                     {
    4598                         /* the host Floppy drive is not currently available. we
    4599                          * assume it will be available later and create an
    4600                          * extra object now */
    4601                         ComObjPtr <HostFloppyDrive> hostDrive;
    4602                         hostDrive.createObject();
    4603                         rc = hostDrive->init (src);
    4604                         ComAssertComRCBreak (rc, rc = rc);
    4605                         rc = mFloppyDrive->CaptureHostDrive (hostDrive);
    4606                     }
    4607                     else
    4608                         ComAssertComRCBreakRC (rc);
    4609                 }
    4610             }
    4611         }
    4612         while (0);
    4613 
    4614         if (typeNode)
    4615             CFGLDRReleaseNode (typeNode);
    4616         CFGLDRReleaseNode (driveNode);
    4617 
    4618         CheckComRCReturnRC (rc);
    4619     }
     4212    /* BIOS */
     4213    rc = mBIOSSettings->loadSettings (aNode);
     4214    CheckComRCReturnRC (rc);
     4215
     4216    /* DVD drive */
     4217    rc = mDVDDrive->loadSettings (aNode);
     4218    CheckComRCReturnRC (rc);
     4219
     4220    /* Floppy drive */
     4221    rc = mFloppyDrive->loadSettings (aNode);
     4222    CheckComRCReturnRC (rc);
    46204223
    46214224    /* USB Controller */
    4622     {
    4623         HRESULT rc = mUSBController->loadSettings (aNode);
    4624         CheckComRCReturnRC (rc);
    4625     }
     4225    rc = mUSBController->loadSettings (aNode);
     4226    CheckComRCReturnRC (rc);
    46264227
    46274228    /* Network node (required) */
    4628     /// @todo (dmik) move the code to NetworkAdapter
    46294229    {
    46304230        /* we assume that all network adapters are initially disabled
    46314231         * and detached */
    46324232
    4633         CFGNODE networkNode = 0;
    4634         CFGLDRGetChildNode (aNode, "Network", 0, &networkNode);
    4635         ComAssertRet (networkNode, E_FAIL);
    4636 
    4637         HRESULT rc = S_OK;
    4638 
    4639         unsigned cAdapters = 0;
    4640         CFGLDRCountChildren (networkNode, "Adapter", &cAdapters);
    4641         for (unsigned i = 0; i < cAdapters; i++)
    4642         {
    4643             CFGNODE adapterNode = 0;
    4644             CFGLDRGetChildNode (networkNode, "Adapter", i, &adapterNode);
    4645             ComAssertBreak (adapterNode, rc = E_FAIL);
    4646 
     4233        Key networkNode = aNode.key ("Network");
     4234
     4235        rc = S_OK;
     4236
     4237        Key::List adapters = networkNode.keys ("Adapter");
     4238        for (Key::List::const_iterator it = adapters.begin();
     4239             it != adapters.end(); ++ it)
     4240        {
    46474241            /* slot number (required) */
    46484242            /* slot unicity is guaranteed by XML Schema */
    4649             uint32_t slot = 0;
    4650             CFGLDRQueryUInt32 (adapterNode, "slot", &slot);
    4651             Assert (slot < ELEMENTS (mNetworkAdapters));
    4652 
    4653             /* type */
    4654             Bstr adapterType;
    4655             CFGLDRQueryBSTR (adapterNode, "type", adapterType.asOutParam());
    4656             ComAssertBreak (adapterType, rc = E_FAIL);
    4657 
    4658             /* enabled (required) */
    4659             bool enabled = false;
    4660             CFGLDRQueryBool (adapterNode, "enabled", &enabled);
    4661             /* MAC address (can be null) */
    4662             Bstr macAddr;
    4663             CFGLDRQueryBSTR (adapterNode, "MACAddress", macAddr.asOutParam());
    4664             /* cable (required) */
    4665             bool cableConnected;
    4666             CFGLDRQueryBool (adapterNode, "cable", &cableConnected);
    4667             /* line speed (defaults to 100 Mbps) */
    4668             uint32_t lineSpeed = 100000;
    4669             CFGLDRQueryUInt32 (adapterNode, "speed", &lineSpeed);
    4670             /* tracing (defaults to false) */
    4671             bool traceEnabled;
    4672             CFGLDRQueryBool (adapterNode, "trace", &traceEnabled);
    4673             Bstr traceFile;
    4674             CFGLDRQueryBSTR (adapterNode, "tracefile", traceFile.asOutParam());
    4675 
    4676             rc = mNetworkAdapters [slot]->COMSETTER(Enabled) (enabled);
    4677             CheckComRCBreakRC (rc);
    4678             rc = mNetworkAdapters [slot]->COMSETTER(MACAddress) (macAddr);
    4679             CheckComRCBreakRC (rc);
    4680             rc = mNetworkAdapters [slot]->COMSETTER(CableConnected) (cableConnected);
    4681             CheckComRCBreakRC (rc);
    4682             rc = mNetworkAdapters [slot]->COMSETTER(LineSpeed) (lineSpeed);
    4683             CheckComRCBreakRC (rc);
    4684             rc = mNetworkAdapters [slot]->COMSETTER(TraceEnabled) (traceEnabled);
    4685             CheckComRCBreakRC (rc);
    4686             rc = mNetworkAdapters [slot]->COMSETTER(TraceFile) (traceFile);
    4687             CheckComRCBreakRC (rc);
    4688 
    4689             if (adapterType.compare(Bstr("Am79C970A")) == 0)
    4690                 mNetworkAdapters [slot]->COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C970A);
    4691             else if (adapterType.compare(Bstr("Am79C973")) == 0)
    4692                 mNetworkAdapters [slot]->COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C973);
    4693 #ifdef VBOX_WITH_E1000
    4694             else if (adapterType.compare(Bstr("82540EM")) == 0)
    4695                 mNetworkAdapters [slot]->COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapter82540EM);
    4696 #endif
    4697             else
    4698                 ComAssertBreak (0, rc = E_FAIL);
    4699 
    4700             CFGNODE attachmentNode = 0;
    4701             if (CFGLDRGetChildNode (adapterNode, "NAT", 0, &attachmentNode), attachmentNode)
     4243            uint32_t slot = (*it).value <uint32_t> ("slot");
     4244            AssertBreakVoid (slot < ELEMENTS (mNetworkAdapters));
     4245
     4246            rc = mNetworkAdapters [slot]->loadSettings (*it);
     4247            CheckComRCReturnRC (rc);
     4248        }
     4249    }
     4250
     4251    /* Serial node (optional) */
     4252    {
     4253        Key serialNode = aNode.findKey ("Uart");
     4254        if (!serialNode.isNull())
     4255        {
     4256            rc = S_OK;
     4257
     4258            Key::List ports = serialNode.keys ("Port");
     4259            for (Key::List::const_iterator it = ports.begin();
     4260                 it != ports.end(); ++ it)
    47024261            {
    4703                 rc = mNetworkAdapters [slot]->AttachToNAT();
    4704                 CheckComRCBreakRC (rc);
     4262                /* slot number (required) */
     4263                /* slot unicity is guaranteed by XML Schema */
     4264                uint32_t slot = (*it).value <uint32_t> ("slot");
     4265                AssertBreakVoid (slot < ELEMENTS (mSerialPorts));
     4266
     4267                rc = mSerialPorts [slot]->loadSettings (*it);
     4268                CheckComRCReturnRC (rc);
    47054269            }
    4706             else
    4707             if (CFGLDRGetChildNode (adapterNode, "HostInterface", 0, &attachmentNode), attachmentNode)
     4270        }
     4271    }
     4272
     4273    /* Parallel node (optional) */
     4274    {
     4275        Key parallelNode = aNode.findKey ("Lpt");
     4276        if (!parallelNode.isNull())
     4277        {
     4278            rc = S_OK;
     4279
     4280            Key::List ports = parallelNode.keys ("Port");
     4281            for (Key::List::const_iterator it = ports.begin();
     4282                 it != ports.end(); ++ it)
    47084283            {
    4709                 /* Host Interface Networking */
    4710                 Bstr name;
    4711                 CFGLDRQueryBSTR (attachmentNode, "name", name.asOutParam());
    4712 #ifdef RT_OS_WINDOWS
    4713                 /* @name can be empty on Win32, but not null */
    4714                 ComAssertBreak (!name.isNull(), rc = E_FAIL);
    4715 #endif
    4716                 rc = mNetworkAdapters [slot]->COMSETTER(HostInterface) (name);
    4717                 CheckComRCBreakRC (rc);
    4718 #ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
    4719                 Bstr tapSetupApp;
    4720                 CFGLDRQueryBSTR (attachmentNode, "TAPSetup", tapSetupApp.asOutParam());
    4721                 Bstr tapTerminateApp;
    4722                 CFGLDRQueryBSTR (attachmentNode, "TAPTerminate", tapTerminateApp.asOutParam());
    4723 
    4724                 rc = mNetworkAdapters [slot]->COMSETTER(TAPSetupApplication) (tapSetupApp);
    4725                 CheckComRCBreakRC (rc);
    4726                 rc = mNetworkAdapters [slot]->COMSETTER(TAPTerminateApplication) (tapTerminateApp);
    4727                 CheckComRCBreakRC (rc);
    4728 #endif // VBOX_WITH_UNIXY_TAP_NETWORKING
    4729                 rc = mNetworkAdapters [slot]->AttachToHostInterface();
    4730                 CheckComRCBreakRC (rc);
     4284                /* slot number (required) */
     4285                /* slot unicity is guaranteed by XML Schema */
     4286                uint32_t slot = (*it).value <uint32_t> ("slot");
     4287                AssertBreakVoid (slot < ELEMENTS (mSerialPorts));
     4288
     4289                rc = mParallelPorts [slot]->loadSettings (*it);
     4290                CheckComRCReturnRC (rc);
    47314291            }
    4732             else
    4733             if (CFGLDRGetChildNode(adapterNode, "InternalNetwork", 0, &attachmentNode), attachmentNode)
    4734             {
    4735                 /* Internal Networking */
    4736                 Bstr name;
    4737                 CFGLDRQueryBSTR (attachmentNode, "name", name.asOutParam());
    4738                 ComAssertBreak (!name.isNull(), rc = E_FAIL);
    4739                 rc = mNetworkAdapters[slot]->AttachToInternalNetwork();
    4740                 CheckComRCBreakRC (rc);
    4741                 rc = mNetworkAdapters[slot]->COMSETTER(InternalNetwork) (name);
    4742                 CheckComRCBreakRC (rc);
    4743             }
    4744             else
    4745             {
    4746                 /* Adapter has no children */
    4747                 rc = mNetworkAdapters [slot]->Detach();
    4748                 CheckComRCBreakRC (rc);
    4749             }
    4750             if (attachmentNode)
    4751                 CFGLDRReleaseNode (attachmentNode);
    4752 
    4753             CFGLDRReleaseNode (adapterNode);
    4754         }
    4755 
    4756         CFGLDRReleaseNode (networkNode);
    4757         CheckComRCReturnRC (rc);
    4758     }
    4759 
    4760     /* Serial node (optional) */
    4761     CFGNODE serialNode = 0;
    4762     CFGLDRGetChildNode (aNode, "Uart", 0, &serialNode);
    4763     if (serialNode)
    4764     {
    4765         HRESULT rc = S_OK;
    4766         unsigned cPorts = 0;
    4767         CFGLDRCountChildren (serialNode, "Port", &cPorts);
    4768         for (unsigned slot = 0; slot < cPorts; slot++)
    4769         {
    4770             rc = mSerialPorts [slot]->loadSettings (serialNode, slot);
    4771             CheckComRCBreakRC (rc);
    4772         }
    4773 
    4774         CFGLDRReleaseNode (serialNode);
    4775         CheckComRCReturnRC (rc);
    4776     }
    4777 
    4778     /* Parallel node (optional) */
    4779     CFGNODE parallelNode = 0;
    4780     CFGLDRGetChildNode (aNode, "Lpt", 0, &parallelNode);
    4781     if (parallelNode)
    4782     {
    4783         HRESULT rc = S_OK;
    4784         unsigned cPorts = 0;
    4785         CFGLDRCountChildren (parallelNode, "Port", &cPorts);
    4786         for (unsigned slot = 0; slot < cPorts; slot++)
    4787         {
    4788             rc = mParallelPorts [slot]->loadSettings (parallelNode, slot);
    4789             CheckComRCBreakRC (rc);
    4790         }
    4791 
    4792         CFGLDRReleaseNode (parallelNode);
    4793         CheckComRCReturnRC (rc);
    4794     }
    4795 
    4796     /* AudioAdapter node (required) */
    4797     /// @todo (dmik) move the code to AudioAdapter
    4798     {
    4799         CFGNODE audioAdapterNode = 0;
    4800         CFGLDRGetChildNode (aNode, "AudioAdapter", 0, &audioAdapterNode);
    4801         ComAssertRet (audioAdapterNode, E_FAIL);
    4802 
    4803         /* is the adapter enabled? */
    4804         bool enabled = false;
    4805         CFGLDRQueryBool (audioAdapterNode, "enabled", &enabled);
    4806         mAudioAdapter->COMSETTER(Enabled) (enabled);
    4807         /* now check the audio driver */
    4808         Bstr driver;
    4809         CFGLDRQueryBSTR (audioAdapterNode, "driver", driver.asOutParam());
    4810         AudioDriverType_T audioDriver;
    4811         audioDriver = AudioDriverType_NullAudioDriver;
    4812         if      (driver == L"null")
    4813             ; /* Null has been set above */
    4814 #ifdef RT_OS_WINDOWS
    4815         else if (driver == L"winmm")
    4816 #ifdef VBOX_WITH_WINMM
    4817             audioDriver = AudioDriverType_WINMMAudioDriver;
    4818 #else
    4819         /* fall back to dsound */
    4820             audioDriver = AudioDriverType_DSOUNDAudioDriver;
    4821 #endif
    4822         else if (driver == L"dsound")
    4823             audioDriver = AudioDriverType_DSOUNDAudioDriver;
    4824 #endif // RT_OS_WINDOWS
    4825 #ifdef RT_OS_LINUX
    4826         else if (driver == L"oss")
    4827             audioDriver = AudioDriverType_OSSAudioDriver;
    4828         else if (driver == L"alsa")
    4829 # ifdef VBOX_WITH_ALSA
    4830             audioDriver = AudioDriverType_ALSAAudioDriver;
    4831 # else
    4832             /* fall back to OSS */
    4833             audioDriver = AudioDriverType_OSSAudioDriver;
    4834 # endif
    4835         else if (driver == L"pulse")
    4836 # ifdef VBOX_WITH_PULSE
    4837             audioDriver = AudioDriverType_PulseAudioDriver;
    4838 # else
    4839             /* fall back to OSS */
    4840             audioDriver = AudioDriverType_OSSAudioDriver;
    4841 # endif
    4842 #endif // RT_OS_LINUX
    4843 #ifdef RT_OS_DARWIN
    4844         else if (driver == L"coreaudio")
    4845             audioDriver = AudioDriverType_CoreAudioDriver;
    4846 #endif
    4847 #ifdef RT_OS_OS2
    4848         else if (driver == L"mmpm")
    4849             audioDriver = AudioDriverType_MMPMAudioDriver;
    4850 #endif
    4851         else
    4852             AssertMsgFailed (("Invalid driver: %ls\n", driver.raw()));
    4853 
    4854         HRESULT rc = mAudioAdapter->COMSETTER(AudioDriver) (audioDriver);
    4855 
    4856         CFGLDRReleaseNode (audioAdapterNode);
    4857         CheckComRCReturnRC (rc);
    4858     }
     4292        }
     4293    }
     4294
     4295    /* AudioAdapter */
     4296    rc = mAudioAdapter->loadSettings (aNode);
     4297    CheckComRCReturnRC (rc);
    48594298
    48604299    /* Shared folders (optional) */
    48614300    /// @todo (dmik) make required on next format change!
    4862     do
    4863     {
    4864         CFGNODE sharedFoldersNode = 0;
    4865         CFGLDRGetChildNode (aNode, "SharedFolders", 0, &sharedFoldersNode);
    4866 
    4867         if (!sharedFoldersNode)
    4868             break;
    4869 
    4870         HRESULT rc = S_OK;
    4871 
    4872         unsigned cFolders = 0;
    4873         CFGLDRCountChildren (sharedFoldersNode, "SharedFolder", &cFolders);
    4874 
    4875         for (unsigned i = 0; i < cFolders; i++)
    4876         {
    4877             CFGNODE folderNode = 0;
    4878             CFGLDRGetChildNode (sharedFoldersNode, "SharedFolder", i, &folderNode);
    4879             ComAssertBreak (folderNode, rc = E_FAIL);
    4880 
    4881             // folder logical name (required)
    4882             Bstr name;
    4883             CFGLDRQueryBSTR (folderNode, "name", name.asOutParam());
    4884 
    4885             // folder host path (required)
    4886             Bstr hostPath;
    4887             CFGLDRQueryBSTR (folderNode, "hostPath", hostPath.asOutParam());
    4888 
    4889             rc = CreateSharedFolder (name, hostPath);
    4890             CheckComRCBreakRC (rc);
    4891 
    4892             CFGLDRReleaseNode (folderNode);
    4893         }
    4894 
    4895         CFGLDRReleaseNode (sharedFoldersNode);
    4896         CheckComRCReturnRC (rc);
    4897     }
    4898     while (0);
     4301    {
     4302        Key sharedFoldersNode = aNode.findKey ("SharedFolders");
     4303        if (!sharedFoldersNode.isNull())
     4304        {
     4305            rc = S_OK;
     4306
     4307            Key::List folders = sharedFoldersNode.keys ("SharedFolder");
     4308            for (Key::List::const_iterator it = folders.begin();
     4309                 it != folders.end(); ++ it)
     4310            {
     4311                /* folder logical name (required) */
     4312                Bstr name = (*it).stringValue ("name");
     4313                /* folder host path (required) */
     4314                Bstr hostPath = (*it).stringValue ("hostPath");
     4315
     4316                rc = CreateSharedFolder (name, hostPath);
     4317                CheckComRCReturnRC (rc);
     4318            }
     4319        }
     4320    }
    48994321
    49004322    /* Clipboard node (currently not required) */
    49014323    /// @todo (dmik) make required on next format change!
    49024324    {
    4903         /* default value in case the node is not there */
     4325        /* default value in case if the node is not there */
    49044326        mHWData->mClipboardMode = ClipboardMode_ClipDisabled;
    49054327
    4906         CFGNODE clipNode = 0;
    4907         CFGLDRGetChildNode (aNode, "Clipboard", 0, &clipNode);
    4908         if (clipNode)
    4909         {
    4910             Bstr mode;
    4911             CFGLDRQueryBSTR (clipNode, "mode", mode.asOutParam());
    4912             if      (mode == L"Disabled")
     4328        Key clipNode = aNode.findKey ("Clipboard");
     4329        if (!clipNode.isNull())
     4330        {
     4331            const char *mode = clipNode.stringValue ("mode");
     4332            if      (strcmp (mode, "Disabled") == 0)
    49134333                mHWData->mClipboardMode = ClipboardMode_ClipDisabled;
    4914             else if (mode == L"HostToGuest")
     4334            else if (strcmp (mode, "HostToGuest") == 0)
    49154335                mHWData->mClipboardMode = ClipboardMode_ClipHostToGuest;
    4916             else if (mode == L"GuestToHost")
     4336            else if (strcmp (mode, "GuestToHost") == 0)
    49174337                mHWData->mClipboardMode = ClipboardMode_ClipGuestToHost;
    4918             else if (mode == L"Bidirectional")
     4338            else if (strcmp (mode, "Bidirectional") == 0)
    49194339                mHWData->mClipboardMode = ClipboardMode_ClipBidirectional;
    49204340            else
    4921                 AssertMsgFailed (("%ls clipboard mode is invalid\n", mode.raw()));
    4922             CFGLDRReleaseNode (clipNode);
     4341                AssertMsgFailed (("Invalid clipboard mode '%s'\n", mode));
    49234342        }
    49244343    }
    49254344
    49264345    /* Guest node (optional) */
    4927     /// @todo (dmik) make required on next format change!
    4928     {
    4929         CFGNODE guestNode = 0;
    4930         CFGLDRGetChildNode (aNode, "Guest", 0, &guestNode);
    4931         if (guestNode)
    4932         {
    4933             uint32_t memoryBalloonSize = 0;
    4934             CFGLDRQueryUInt32 (guestNode, "MemoryBalloonSize",
    4935                                &memoryBalloonSize);
    4936             mHWData->mMemoryBalloonSize = memoryBalloonSize;
    4937 
    4938             uint32_t statisticsUpdateInterval = 0;
    4939             CFGLDRQueryUInt32 (guestNode, "StatisticsUpdateInterval",
    4940                                &statisticsUpdateInterval);
    4941             mHWData->mStatisticsUpdateInterval = statisticsUpdateInterval;
    4942 
    4943             CFGLDRReleaseNode (guestNode);
    4944         }
    4945     }
    4946 
    4947     return S_OK;
     4346    /// @todo (dmik) make required on next format change and change attribute
     4347    /// naming!
     4348    {
     4349        Key guestNode = aNode.findKey ("Guest");
     4350        if (!guestNode.isNull())
     4351        {
     4352            /* optional, defaults to 0) */
     4353            mHWData->mMemoryBalloonSize =
     4354                guestNode.value <ULONG> ("MemoryBalloonSize");
     4355            /* optional, defaults to 0) */
     4356            mHWData->mStatisticsUpdateInterval =
     4357                guestNode.value <ULONG> ("StatisticsUpdateInterval");
     4358        }
     4359    }
     4360
     4361    AssertComRC (rc);
     4362    return rc;
    49484363}
    49494364
    49504365/**
    4951  *  @param aNode        <HardDiskAttachments> node
     4366 *  @param aNode        <HardDiskAttachments> node.
    49524367 *  @param aRegistered  true when the machine is being loaded on VirtualBox
    49534368 *                      startup, or when a snapshot is being loaded (wchich
     
    49554370 *  @param aSnapshotId  pointer to the snapshot ID if this is a snapshot machine
    49564371 */
    4957 HRESULT Machine::loadHardDisks (CFGNODE aNode, bool aRegistered,
     4372HRESULT Machine::loadHardDisks (const settings::Key &aNode, bool aRegistered,
    49584373                                const Guid *aSnapshotId /* = NULL */)
    49594374{
    4960     AssertReturn (aNode, E_INVALIDARG);
     4375    using namespace settings;
     4376
     4377    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    49614378    AssertReturn ((mType == IsMachine && aSnapshotId == NULL) ||
    49624379                  (mType == IsSnapshotMachine && aSnapshotId != NULL), E_FAIL);
     
    49644381    HRESULT rc = S_OK;
    49654382
    4966     unsigned cbDisks = 0;
    4967     CFGLDRCountChildren (aNode, "HardDiskAttachment", &cbDisks);
    4968 
    4969     if (!aRegistered && cbDisks > 0)
     4383    Key::List children = aNode.keys ("HardDiskAttachment");
     4384
     4385    if (!aRegistered && children.size() > 0)
    49704386    {
    49714387        /* when the machine is being loaded (opened) from a file, it cannot
     
    49764392            tr ("Unregistered machine '%ls' cannot have hard disks attached "
    49774393                "(found %d hard disk attachments)"),
    4978             mUserData->mName.raw(), cbDisks);
    4979     }
    4980 
    4981     for (unsigned i = 0; i < cbDisks && SUCCEEDED (rc); ++ i)
    4982     {
    4983         CFGNODE hdNode;
    4984         CFGLDRGetChildNode (aNode, "HardDiskAttachment", i, &hdNode);
    4985         ComAssertRet (hdNode, E_FAIL);
    4986 
    4987         do
    4988         {
    4989             /* hardDisk uuid (required) */
    4990             Guid uuid;
    4991             CFGLDRQueryUUID (hdNode, "hardDisk", uuid.ptr());
    4992             /* bus (controller) type (required) */
    4993             Bstr bus;
    4994             CFGLDRQueryBSTR (hdNode, "bus", bus.asOutParam());
    4995             /* device (required) */
    4996             Bstr device;
    4997             CFGLDRQueryBSTR (hdNode, "device", device.asOutParam());
    4998 
    4999             /* find a hard disk by UUID */
    5000             ComObjPtr <HardDisk> hd;
    5001             rc = mParent->getHardDisk (uuid, hd);
    5002             if (FAILED (rc))
    5003                 break;
    5004 
    5005             AutoLock hdLock (hd);
    5006 
    5007             if (!hd->machineId().isEmpty())
    5008             {
    5009                 rc = setError (E_FAIL,
    5010                     tr ("Hard disk '%ls' with UUID {%s} is already "
    5011                         "attached to a machine with UUID {%s} (see '%ls')"),
    5012                     hd->toString().raw(), uuid.toString().raw(),
    5013                     hd->machineId().toString().raw(),
    5014                     mData->mConfigFileFull.raw());
    5015                 break;
    5016             }
    5017 
    5018             if (hd->type() == HardDiskType_ImmutableHardDisk)
    5019             {
    5020                 rc = setError (E_FAIL,
    5021                     tr ("Immutable hard disk '%ls' with UUID {%s} cannot be "
    5022                         "directly attached to a machine (see '%ls')"),
    5023                     hd->toString().raw(), uuid.toString().raw(),
    5024                     mData->mConfigFileFull.raw());
    5025                 break;
    5026             }
    5027 
    5028             /* attach the device */
    5029             DiskControllerType_T ctl = DiskControllerType_InvalidController;
    5030             LONG dev = -1;
    5031 
    5032             if (bus == L"ide0")
    5033             {
    5034                 ctl = DiskControllerType_IDE0Controller;
    5035                 if (device == L"master")
    5036                     dev = 0;
    5037                 else if (device == L"slave")
    5038                     dev = 1;
    5039                 else
    5040                     ComAssertMsgFailedBreak (("Invalid device: %ls\n", device.raw()),
    5041                                              rc = E_FAIL);
    5042             }
    5043             else if (bus == L"ide1")
    5044             {
    5045                 ctl = DiskControllerType_IDE1Controller;
    5046                 if (device == L"master")
    5047                     rc = setError (E_FAIL, tr("Could not attach a disk as a master "
    5048                                               "device on the secondary controller"));
    5049                 else if (device == L"slave")
    5050                     dev = 1;
    5051                 else
    5052                     ComAssertMsgFailedBreak (("Invalid device: %ls\n", device.raw()),
    5053                                              rc = E_FAIL);
    5054             }
     4394            mUserData->mName.raw(), children.size());
     4395    }
     4396
     4397
     4398    for (Key::List::const_iterator it = children.begin();
     4399         it != children.end(); ++ it)
     4400    {
     4401        /* hardDisk uuid (required) */
     4402        Guid uuid = (*it).value <Guid> ("hardDisk");
     4403        /* bus (controller) type (required) */
     4404        const char *bus = (*it).stringValue ("bus");
     4405        /* device (required) */
     4406        const char *device = (*it).stringValue ("device");
     4407
     4408        /* find a hard disk by UUID */
     4409        ComObjPtr <HardDisk> hd;
     4410        rc = mParent->getHardDisk (uuid, hd);
     4411        CheckComRCReturnRC (rc);
     4412
     4413        AutoLock hdLock (hd);
     4414
     4415        if (!hd->machineId().isEmpty())
     4416        {
     4417            return setError (E_FAIL,
     4418                tr ("Hard disk '%ls' with UUID {%s} is already "
     4419                    "attached to a machine with UUID {%s} (see '%ls')"),
     4420                hd->toString().raw(), uuid.toString().raw(),
     4421                hd->machineId().toString().raw(),
     4422                mData->mConfigFileFull.raw());
     4423        }
     4424
     4425        if (hd->type() == HardDiskType_ImmutableHardDisk)
     4426        {
     4427            return setError (E_FAIL,
     4428                tr ("Immutable hard disk '%ls' with UUID {%s} cannot be "
     4429                    "directly attached to a machine (see '%ls')"),
     4430                hd->toString().raw(), uuid.toString().raw(),
     4431                mData->mConfigFileFull.raw());
     4432        }
     4433
     4434        /* attach the device */
     4435        DiskControllerType_T ctl = DiskControllerType_InvalidController;
     4436        LONG dev = -1;
     4437
     4438        if (strcmp (bus, "ide0") == 0)
     4439        {
     4440            ctl = DiskControllerType_IDE0Controller;
     4441            if (strcmp (device, "master") == 0)
     4442                dev = 0;
     4443            else if (strcmp (device, "slave") == 0)
     4444                dev = 1;
    50554445            else
    5056                 ComAssertMsgFailedBreak (("Invalid bus: %ls\n", bus.raw()),
    5057                                          rc = E_FAIL);
    5058 
    5059             ComObjPtr <HardDiskAttachment> attachment;
    5060             attachment.createObject();
    5061             rc = attachment->init (hd, ctl, dev, false /* aDirty */);
    5062             if (FAILED (rc))
    5063                 break;
    5064 
    5065             /* associate the hard disk with this machine */
    5066             hd->setMachineId (mData->mUuid);
    5067 
    5068             /* associate the hard disk with the given snapshot ID */
    5069             if (mType == IsSnapshotMachine)
    5070                 hd->setSnapshotId (*aSnapshotId);
    5071 
    5072             mHDData->mHDAttachments.push_back (attachment);
    5073         }
    5074         while (0);
    5075 
    5076         CFGLDRReleaseNode (hdNode);
    5077     }
    5078 
    5079     return rc;
    5080 }
    5081 
    5082 /**
    5083  *  Creates a config loader and loads the settings file.
    5084  *
    5085  *  @param aIsNew   |true| if a newly created settings file is to be opened
    5086  *                  (must be the case only when called from #saveSettings())
    5087  *
    5088  *  @note
    5089  *      XML Schema errors are not detected by this method because
    5090  *      it assumes that it will load settings from an exclusively locked
    5091  *      file (using a file handle) that was previously validated when opened
    5092  *      for the first time. Thus, this method should be used only when
    5093  *      it's necessary to modify (save) the settings file.
    5094  *
    5095  *  @note The object must be locked at least for reading before calling
    5096  *        this method.
    5097  */
    5098 HRESULT Machine::openConfigLoader (CFGHANDLE *aLoader, bool aIsNew /* = false */)
    5099 {
    5100     AssertReturn (aLoader, E_FAIL);
    5101 
    5102     /* The settings file must be created and locked at this point */
    5103     ComAssertRet (isConfigLocked(), E_FAIL);
    5104 
    5105     /* load the config file */
    5106     int vrc = CFGLDRLoad (aLoader,
    5107                           Utf8Str (mData->mConfigFileFull), mData->mHandleCfgFile,
    5108                           aIsNew ? NULL : XmlSchemaNS, true, cfgLdrEntityResolver,
    5109                           NULL);
    5110     ComAssertRCRet (vrc, E_FAIL);
     4446                ComAssertMsgFailedRet (("Invalid device '%s'\n", device),
     4447                                       E_FAIL);
     4448        }
     4449        else if (strcmp (bus, "ide1") == 0)
     4450        {
     4451            ctl = DiskControllerType_IDE1Controller;
     4452            if (strcmp (device, "master") == 0)
     4453                rc = setError (E_FAIL, tr("Could not attach a disk as a master "
     4454                                          "device on the secondary controller"));
     4455            else if (strcmp (device, "slave") == 0)
     4456                dev = 1;
     4457            else
     4458                ComAssertMsgFailedRet (("Invalid device '%s'\n", device),
     4459                                       E_FAIL);
     4460        }
     4461        else
     4462            ComAssertMsgFailedRet (("Invalid bus '%s'\n", bus),
     4463                                   E_FAIL);
     4464
     4465        ComObjPtr <HardDiskAttachment> attachment;
     4466        attachment.createObject();
     4467        rc = attachment->init (hd, ctl, dev, false /* aDirty */);
     4468        CheckComRCBreakRC (rc);
     4469
     4470        /* associate the hard disk with this machine */
     4471        hd->setMachineId (mData->mUuid);
     4472
     4473        /* associate the hard disk with the given snapshot ID */
     4474        if (mType == IsSnapshotMachine)
     4475            hd->setSnapshotId (*aSnapshotId);
     4476
     4477        mHDData->mHDAttachments.push_back (attachment);
     4478    }
    51114479
    51124480    return S_OK;
    5113 }
    5114 
    5115 /**
    5116  *  Closes the config loader previously created by #openConfigLoader().
    5117  *  If \a aSaveBeforeClose is true, then the config is saved to the settings file
    5118  *  before closing. If saving fails, a proper error message is set.
    5119  *
    5120  *  @param aSaveBeforeClose whether to save the config before closing or not
    5121  */
    5122 HRESULT Machine::closeConfigLoader (CFGHANDLE aLoader, bool aSaveBeforeClose)
    5123 {
    5124     HRESULT rc = S_OK;
    5125 
    5126     if (aSaveBeforeClose)
    5127     {
    5128         char *loaderError = NULL;
    5129         int vrc = CFGLDRSave (aLoader, &loaderError);
    5130         if (VBOX_FAILURE (vrc))
    5131         {
    5132             rc = setError (E_FAIL,
    5133                 tr ("Could not save the settings file '%ls' (%Vrc)%s%s"),
    5134                 mData->mConfigFileFull.raw(), vrc,
    5135                 loaderError ? ".\n" : "", loaderError ? loaderError : "");
    5136             if (loaderError)
    5137                 RTMemTmpFree (loaderError);
    5138         }
    5139     }
    5140 
    5141     CFGLDRFree (aLoader);
    5142 
    5143     return rc;
    51444481}
    51454482
     
    51534490 *  \a aSnapshotNode are set to 0.
    51544491 *
    5155  *  @param aSnapshot        snapshot to search for
    5156  *  @param aMachineNode     <Machine> node to start from
     4492 *  @param aSnapshot        Snapshot to search for.
     4493 *  @param aMachineNode     <Machine> node to start from.
    51574494 *  @param aSnapshotsNode   <Snapshots> node containing the found <Snapshot> node
    5158  *                          (may be NULL if the caller is not interested)
    5159  *  @param aSnapshotNode    found <Snapshot> node
     4495 *                          (may be NULL if the caller is not interested).
     4496 *  @param aSnapshotNode    Found <Snapshot> node.
    51604497 */
    5161 HRESULT Machine::findSnapshotNode (Snapshot *aSnapshot, CFGNODE aMachineNode,
    5162                                    CFGNODE *aSnapshotsNode, CFGNODE *aSnapshotNode)
    5163 {
    5164     AssertReturn (aSnapshot && aMachineNode && aSnapshotNode, E_FAIL);
     4498HRESULT Machine::findSnapshotNode (Snapshot *aSnapshot, settings::Key &aMachineNode,
     4499                                   settings::Key *aSnapshotsNode,
     4500                                   settings::Key *aSnapshotNode)
     4501{
     4502    using namespace settings;
     4503
     4504    AssertReturn (aSnapshot && !aMachineNode.isNull()
     4505                  && aSnapshotNode != NULL, E_FAIL);
    51654506
    51664507    if (aSnapshotsNode)
    5167         *aSnapshotsNode = 0;
    5168     *aSnapshotNode = 0;
    5169 
    5170     // build the full uuid path (from the fist parent to the given snapshot)
     4508        aSnapshotsNode->setNull();
     4509    aSnapshotNode->setNull();
     4510
     4511    // build the full uuid path (from the top parent to the given snapshot)
    51714512    std::list <Guid> path;
    51724513    {
     
    51794520    }
    51804521
    5181     CFGNODE snapshotsNode = aMachineNode;
    5182     CFGNODE snapshotNode = 0;
     4522    Key snapshotsNode = aMachineNode;
     4523    Key snapshotNode;
    51834524
    51844525    for (std::list <Guid>::const_iterator it = path.begin();
     
    51864527         ++ it)
    51874528    {
    5188         if (snapshotNode)
    5189         {
    5190             // proceed to the nested <Snapshots> node
    5191             Assert (snapshotsNode);
    5192             if (snapshotsNode != aMachineNode)
    5193             {
    5194                 CFGLDRReleaseNode (snapshotsNode);
    5195                 snapshotsNode = 0;
    5196             }
    5197             CFGLDRGetChildNode (snapshotNode, "Snapshots", 0, &snapshotsNode);
    5198             CFGLDRReleaseNode (snapshotNode);
    5199             snapshotNode = 0;
    5200         }
    5201 
    5202         AssertReturn (snapshotsNode, E_FAIL);
    5203 
    5204         unsigned count = 0, i = 0;
    5205         CFGLDRCountChildren (snapshotsNode, "Snapshot", &count);
    5206         for (; i < count; ++ i)
    5207         {
    5208             snapshotNode = 0;
    5209             CFGLDRGetChildNode (snapshotsNode, "Snapshot", i, &snapshotNode);
    5210             Guid id;
    5211             CFGLDRQueryUUID (snapshotNode, "uuid", id.ptr());
     4529        if (!snapshotNode.isNull())
     4530        {
     4531            /* proceed to the nested <Snapshots> node */
     4532            snapshotsNode = snapshotNode.key ("Snapshots");
     4533            snapshotNode.setNull();
     4534        }
     4535
     4536        AssertReturn (!snapshotsNode.isNull(), E_FAIL);
     4537
     4538        Key::List children = snapshotsNode.keys ("Snapshot");
     4539        for (Key::List::const_iterator ch = children.begin();
     4540             ch != children.end();
     4541             ++ ch)
     4542        {
     4543            Guid id = (*ch).value <Guid> ("uuid");
    52124544            if (id == (*it))
    52134545            {
    5214                 // we keep (don't release) snapshotNode and snapshotsNode
     4546                /* pass over to the outer loop */
     4547                snapshotNode = *ch;
    52154548                break;
    52164549            }
    5217             CFGLDRReleaseNode (snapshotNode);
    5218             snapshotNode = 0;
    5219         }
    5220 
    5221         if (i == count)
    5222         {
    5223             // the next uuid is not found, no need to continue...
    5224             AssertFailed();
    5225             if (snapshotsNode != aMachineNode)
    5226             {
    5227                 CFGLDRReleaseNode (snapshotsNode);
    5228                 snapshotsNode = 0;
    5229             }
    5230             break;
    5231         }
     4550        }
     4551
     4552        if (!snapshotNode.isNull())
     4553            continue;
     4554
     4555        /* the next uuid is not found, no need to continue... */
     4556        AssertFailedBreakVoid();
    52324557    }
    52334558
    52344559    // we must always succesfully find the node
    5235     AssertReturn (snapshotNode, E_FAIL);
    5236     AssertReturn (snapshotsNode, E_FAIL);
    5237 
    5238     if (aSnapshotsNode)
    5239         *aSnapshotsNode = snapshotsNode != aMachineNode ? snapshotsNode : 0;
     4560    AssertReturn (!snapshotNode.isNull(), E_FAIL);
     4561    AssertReturn (!snapshotsNode.isNull(), E_FAIL);
     4562
     4563    if (aSnapshotsNode && (snapshotsNode != aMachineNode))
     4564        *aSnapshotsNode = snapshotsNode;
    52404565    *aSnapshotNode = snapshotNode;
    52414566
     
    53824707 *  if this is a new machine.
    53834708 *
    5384  *  @note Must be never called directly.
     4709 *  @note Must be never called directly but only from #saveSettings().
    53854710 *
    53864711 *  @param aRenamed receives |true| if the name was changed and the settings
     
    53914716HRESULT Machine::prepareSaveSettings (bool &aRenamed, bool &aNew)
    53924717{
     4718    /* Note: tecnhically, mParent needs to be locked only when the machine is
     4719     * registered (see prepareSaveSettings() for details) but we don't
     4720     * currently differentiate it in callers of saveSettings() so we don't
     4721     * make difference here too.  */
     4722    AssertReturn (mParent->isLockedOnCurrentThread(), E_FAIL);
     4723    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     4724
    53934725    HRESULT rc = S_OK;
    53944726
     
    55734905        }
    55744906
    5575         /* Note: open flags must correlated with RTFileOpen() in lockConfig() */
     4907        /* Note: open flags must correlate with RTFileOpen() in lockConfig() */
    55764908        path = Utf8Str (mData->mConfigFileFull);
    55774909        vrc = RTFileOpen (&mData->mHandleCfgFile, path,
     
    56014933 *
    56024934 *  @param aMarkCurStateAsModified
    5603  *      if true (default), mData->mCurrentStateModified will be set to
     4935 *      If true (default), mData->mCurrentStateModified will be set to
    56044936 *      what #isReallyModified() returns prior to saving settings to a file,
    56054937 *      otherwise the current value of mData->mCurrentStateModified will be
    56064938 *      saved.
    56074939 *  @param aInformCallbacksAnyway
    5608  *      if true, callbacks will be informed even if #isReallyModified()
     4940 *      If true, callbacks will be informed even if #isReallyModified()
    56094941 *      returns false. This is necessary for cases when we change machine data
    56104942 *      diectly, not through the backup()/commit() mechanism.
    56114943 *
    5612  *  @note Locks mParent (only in some cases, and only when #isConfigLocked() is
    5613  *        |TRUE|, see the #prepareSaveSettings() code for details) +
    5614  *        this object + children for writing.
     4944 *  @note Must be called from under mParent write lock (sometimes needed by
     4945 *  #prepareSaveSettings()) and this object's write lock. Locks children for
     4946 *  writing. There is one exception when mParent is unused and therefore may
     4947 *  be left unlocked: if this machine is an unregistered one.
    56154948 */
    56164949HRESULT Machine::saveSettings (bool aMarkCurStateAsModified /* = true */,
     
    56184951{
    56194952    LogFlowThisFuncEnter();
     4953
     4954    /* Note: tecnhically, mParent needs to be locked only when the machine is
     4955     * registered (see prepareSaveSettings() for details) but we don't
     4956     * currently differentiate it in callers of saveSettings() so we don't
     4957     * make difference here too.  */
     4958    AssertReturn (mParent->isLockedOnCurrentThread(), E_FAIL);
     4959    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
    56204960
    56214961    /// @todo (dmik) I guess we should lock all our child objects here
     
    56584998    CheckComRCReturnRC (rc);
    56594999
    5660     /* then, open the settings file */
    5661     CFGHANDLE configLoader = 0;
    5662     rc = openConfigLoader (&configLoader, isNew);
    5663     CheckComRCReturnRC (rc);
    5664 
    5665     /* save all snapshots when the machine name was changed since
    5666      * it may affect saved state file paths for online snapshots (see
    5667      * #openConfigLoader() for details) */
    5668     bool updateAllSnapshots = isRenamed;
    5669 
    5670     /* commit before saving, since it may change settings
    5671      * (for example, perform fixup of lazy hard disk changes) */
    5672     rc = commit();
    5673     if (FAILED (rc))
    5674     {
    5675         closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
    5676         return rc;
    5677     }
    5678 
    5679     /* include hard disk changes to the modified flag */
    5680     wasModified |= mHDData->mHDAttachmentsChanged;
    5681     if (aMarkCurStateAsModified)
    5682         mData->mCurrentStateModified |= BOOL (mHDData->mHDAttachmentsChanged);
    5683 
    5684 
    5685     CFGNODE machineNode = 0;
    5686     /* create if not exists */
    5687     CFGLDRCreateNode (configLoader, "VirtualBox/Machine", &machineNode);
    5688 
    5689     do
    5690     {
    5691         ComAssertBreak (machineNode, rc = E_FAIL);
     5000    try
     5001    {
     5002        using namespace settings;
     5003
     5004        File file (File::ReadWrite, mData->mHandleCfgFile,
     5005                   Utf8Str (mData->mConfigFileFull));
     5006        XmlTreeBackend tree;
     5007
     5008        /* The newly created settings file is incomplete therefore we turn off
     5009         * validation. The rest is like in loadSettingsTree_ForUpdate().*/
     5010        rc = VirtualBox::loadSettingsTree (tree, file,
     5011                                           !isNew /* aValidate */,
     5012                                           false /* aCatchLoadErrors */,
     5013                                           false /* aAddDefaults */);
     5014        CheckComRCThrowRC (rc);
     5015
     5016
     5017        /* ask to save all snapshots when the machine name was changed since
     5018         * it may affect saved state file paths for online snapshots (see
     5019         * #openConfigLoader() for details) */
     5020        bool updateAllSnapshots = isRenamed;
     5021
     5022        /* commit before saving, since it may change settings
     5023         * (for example, perform fixup of lazy hard disk changes) */
     5024        rc = commit();
     5025        CheckComRCReturnRC (rc);
     5026
     5027        /* include hard disk changes to the modified flag */
     5028        wasModified |= mHDData->mHDAttachmentsChanged;
     5029        if (aMarkCurStateAsModified)
     5030            mData->mCurrentStateModified |= BOOL (mHDData->mHDAttachmentsChanged);
     5031
     5032        Key machineNode = tree.rootKey().createKey ("Machine");
    56925033
    56935034        /* uuid (required) */
    5694         Assert (mData->mUuid);
    5695         CFGLDRSetUUID (machineNode, "uuid", mData->mUuid.raw());
     5035        Assert (!mData->mUuid.isEmpty());
     5036        machineNode.setValue <Guid> ("uuid", mData->mUuid);
    56965037
    56975038        /* name (required) */
    56985039        Assert (!mUserData->mName.isEmpty());
    5699         CFGLDRSetBSTR (machineNode, "name", mUserData->mName);
     5040        machineNode.setValue <Bstr> ("name", mUserData->mName);
    57005041
    57015042        /* nameSync (optional, default is true) */
    5702         if (!mUserData->mNameSync)
    5703             CFGLDRSetBool (machineNode, "nameSync", false);
    5704         else
    5705             CFGLDRDeleteAttribute (machineNode, "nameSync");
     5043        machineNode.setValueOr <bool> ("nameSync", !!mUserData->mNameSync, true);
    57065044
    57075045        /* Description node (optional) */
    57085046        if (!mUserData->mDescription.isNull())
    57095047        {
    5710             CFGNODE descNode = 0;
    5711             CFGLDRCreateChildNode (machineNode, "Description", &descNode);
    5712             Assert (descNode);
    5713             CFGLDRSetBSTR (descNode, NULL, mUserData->mDescription);
    5714             CFGLDRReleaseNode (descNode);
     5048            Key descNode = machineNode.createKey ("Description");
     5049            descNode.setKeyValue <Bstr> (mUserData->mDescription);
    57155050        }
    57165051        else
    57175052        {
    5718             CFGNODE descNode = 0;
    5719             CFGLDRGetChildNode (machineNode, "Description", 0, &descNode);
    5720             if (descNode)
    5721                 CFGLDRDeleteNode (descNode);
     5053            Key descNode = machineNode.findKey ("Description");
     5054            if (!descNode.isNull())
     5055                descNode.zap();
    57225056        }
    57235057
    57245058        /* OSType (required) */
    5725         {
    5726             CFGLDRSetBSTR (machineNode, "OSType", mUserData->mOSTypeId);
    5727         }
     5059        machineNode.setValue <Bstr> ("OSType", mUserData->mOSTypeId);
    57285060
    57295061        /* stateFile (optional) */
     
    57345066            Utf8Str stateFilePath = mSSData->mStateFilePath;
    57355067            calculateRelativePath (stateFilePath, stateFilePath);
    5736             CFGLDRSetString (machineNode, "stateFile", stateFilePath);
     5068            machineNode.setStringValue ("stateFile", stateFilePath);
    57375069        }
    57385070        else
    57395071        {
    57405072            Assert (mSSData->mStateFilePath.isNull());
    5741             CFGLDRDeleteAttribute (machineNode, "stateFile");
     5073            machineNode.zapValue ("stateFile");
    57425074        }
    57435075
     
    57465078        {
    57475079            Assert (!mData->mFirstSnapshot.isNull());
    5748             CFGLDRSetUUID (machineNode, "currentSnapshot",
    5749                            mData->mCurrentSnapshot->data().mId);
     5080            machineNode.setValue <Guid> ("currentSnapshot",
     5081                                         mData->mCurrentSnapshot->data().mId);
    57505082        }
    57515083        else
    57525084        {
    57535085            Assert (mData->mFirstSnapshot.isNull());
    5754             CFGLDRDeleteAttribute (machineNode, "currentSnapshot");
     5086            machineNode.zapValue ("currentSnapshot");
    57555087        }
    57565088
    57575089        /* snapshotFolder (optional) */
     5090        /// @todo use the Bstr::NullOrEmpty constant and setValueOr
    57585091        if (!mUserData->mSnapshotFolder.isEmpty())
    5759             CFGLDRSetBSTR (machineNode, "snapshotFolder", mUserData->mSnapshotFolder);
     5092            machineNode.setValue <Bstr> ("snapshotFolder", mUserData->mSnapshotFolder);
    57605093        else
    5761             CFGLDRDeleteAttribute (machineNode, "snapshotFolder");
    5762 
    5763         /* currentStateModified (optional, default is yes) */
    5764         if (!mData->mCurrentStateModified)
    5765             CFGLDRSetBool (machineNode, "currentStateModified", false);
    5766         else
    5767             CFGLDRDeleteAttribute (machineNode, "currentStateModified");
     5094            machineNode.zapValue ("snapshotFolder");
     5095
     5096        /* currentStateModified (optional, default is true) */
     5097        machineNode.setValueOr <bool> ("currentStateModified",
     5098                                       !!mData->mCurrentStateModified, true);
    57685099
    57695100        /* lastStateChange */
    5770         CFGLDRSetDateTime (machineNode, "lastStateChange",
    5771                            mData->mLastStateChange);
     5101        machineNode.setValue <RTTIMESPEC> ("lastStateChange",
     5102                                           mData->mLastStateChange);
     5103
     5104        /* set the aborted attribute when appropriate, defaults to false */
     5105        machineNode.setValueOr <bool> ("aborted",
     5106                                       mData->mMachineState == MachineState_Aborted,
     5107                                       false);
    57725108
    57735109        /* Hardware node (required) */
    57745110        {
    5775             CFGNODE hwNode = 0;
    5776             CFGLDRGetChildNode (machineNode, "Hardware", 0, &hwNode);
    57775111            /* first, delete the entire node if exists */
    5778             if (hwNode)
    5779                 CFGLDRDeleteNode (hwNode);
     5112            Key hwNode = machineNode.findKey ("Hardware");
     5113            if (!hwNode.isNull())
     5114                hwNode.zap();
    57805115            /* then recreate it */
    5781             hwNode = 0;
    5782             CFGLDRCreateChildNode (machineNode, "Hardware", &hwNode);
    5783             ComAssertBreak (hwNode, rc = E_FAIL);
    5784 
     5116            hwNode = machineNode.createKey ("Hardware");
     5117           
    57855118            rc = saveHardware (hwNode);
    5786 
    5787             CFGLDRReleaseNode (hwNode);
    5788             if (FAILED (rc))
    5789                 break;
     5119            CheckComRCThrowRC (rc);
    57905120        }
    57915121
    57925122        /* HardDiskAttachments node (required) */
    57935123        {
    5794             CFGNODE hdasNode = 0;
    5795             CFGLDRGetChildNode (machineNode, "HardDiskAttachments", 0, &hdasNode);
    57965124            /* first, delete the entire node if exists */
    5797             if (hdasNode)
    5798                 CFGLDRDeleteNode (hdasNode);
     5125            Key hdaNode = machineNode.findKey ("HardDiskAttachments");
     5126            if (!hdaNode.isNull())
     5127                hdaNode.zap();
    57995128            /* then recreate it */
    5800             hdasNode = 0;
    5801             CFGLDRCreateChildNode (machineNode, "HardDiskAttachments", &hdasNode);
    5802             ComAssertBreak (hdasNode, rc = E_FAIL);
    5803 
    5804             rc = saveHardDisks (hdasNode);
    5805 
    5806             CFGLDRReleaseNode (hdasNode);
    5807             if (FAILED (rc))
    5808                 break;
     5129            hdaNode = machineNode.createKey ("HardDiskAttachments");
     5130
     5131            rc = saveHardDisks (hdaNode);
     5132            CheckComRCThrowRC (rc);
    58095133        }
    58105134
    58115135        /* update all snapshots if requested */
    58125136        if (updateAllSnapshots)
     5137        {
    58135138            rc = saveSnapshotSettingsWorker (machineNode, NULL,
    58145139                                             SaveSS_UpdateAllOp);
    5815     }
    5816     while (0);
    5817 
    5818     if (machineNode)
    5819         CFGLDRReleaseNode (machineNode);
    5820 
    5821     if (SUCCEEDED (rc))
    5822         rc = closeConfigLoader (configLoader, true /* aSaveBeforeClose */);
    5823     else
    5824         closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
     5140            CheckComRCThrowRC (rc);
     5141        }
     5142
     5143        /* save the settings on success */
     5144        rc = VirtualBox::saveSettingsTree (tree, file);
     5145        CheckComRCThrowRC (rc);
     5146    }
     5147    catch (HRESULT err)
     5148    {
     5149        /* we assume that error info is set by the thrower */
     5150        rc = err;
     5151    }
     5152    catch (...)
     5153    {
     5154        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     5155    }
    58255156
    58265157    if (FAILED (rc))
    58275158    {
    5828         /*
    5829          *  backup arbitrary data item to cause #isModified() to still return
    5830          *  true in case of any error
    5831          */
     5159        /* backup arbitrary data item to cause #isModified() to still return
     5160         * true in case of any error */
    58325161        mHWData.backup();
    58335162    }
     
    58355164    if (wasModified || aInformCallbacksAnyway)
    58365165    {
    5837         /*
    5838          *  Fire the data change event, even on failure (since we've already
    5839          *  committed all data). This is done only for SessionMachines because
    5840          *  mutable Machine instances are always not registered (i.e. private
    5841          *  to the client process that creates them) and thus don't need to
    5842          *  inform callbacks.
    5843          */
     5166        /* Fire the data change event, even on failure (since we've already
     5167         * committed all data). This is done only for SessionMachines because
     5168         * mutable Machine instances are always not registered (i.e. private
     5169         * to the client process that creates them) and thus don't need to
     5170         * inform callbacks. */
    58445171        if (mType == IsSessionMachine)
    58455172            mParent->onMachineDataChange (mData->mUuid);
     
    58765203    HRESULT rc = S_OK;
    58775204
    5878     /* load the config file */
    5879     CFGHANDLE configLoader = 0;
    5880     rc = openConfigLoader (&configLoader);
    5881     if (FAILED (rc))
    5882         return rc;
    5883 
    5884     CFGNODE machineNode = 0;
    5885     CFGLDRGetNode (configLoader, "VirtualBox/Machine", 0, &machineNode);
    5886 
    5887     do
    5888     {
    5889         ComAssertBreak (machineNode, rc = E_FAIL);
     5205    try
     5206    {
     5207        using namespace settings;
     5208
     5209        /* load the config file */
     5210        File file (File::ReadWrite, mData->mHandleCfgFile,
     5211                   Utf8Str (mData->mConfigFileFull));
     5212        XmlTreeBackend tree;
     5213
     5214        rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
     5215        CheckComRCReturnRC (rc);
     5216
     5217        Key machineNode = tree.rootKey().key ("Machine");
    58905218
    58915219        rc = saveSnapshotSettingsWorker (machineNode, aSnapshot, aOpFlags);
    5892 
    5893         CFGLDRReleaseNode (machineNode);
    5894     }
    5895     while (0);
    5896 
    5897     if (SUCCEEDED (rc))
    5898         rc = closeConfigLoader (configLoader, true /* aSaveBeforeClose */);
    5899     else
    5900         closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
     5220        CheckComRCReturnRC (rc);
     5221
     5222        /* save settings on success */
     5223        rc = VirtualBox::saveSettingsTree (tree, file);
     5224        CheckComRCReturnRC (rc);
     5225    }
     5226    catch (...)
     5227    {
     5228        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     5229    }
    59015230
    59025231    return rc;
     
    59155244 *  attribute of <Machine> needs to be updated.
    59165245 *
    5917  *  @param aMachineNode <Machine> node in the opened settings file
    5918  *  @param aSnapshot    Snapshot to operate on
     5246 *  @param aMachineNode <Machine> node in the opened settings file.
     5247 *  @param aSnapshot    Snapshot to operate on.
    59195248 *  @param aOpFlags     Operation to perform, one of SaveSS_NoOp, SaveSS_AddOp
    59205249 *                      or SaveSS_UpdateAttrsOp possibly combined with
     
    59245253 *        Locks child objects.
    59255254 */
    5926 HRESULT Machine::saveSnapshotSettingsWorker (CFGNODE aMachineNode,
     5255HRESULT Machine::saveSnapshotSettingsWorker (settings::Key &aMachineNode,
    59275256                                             Snapshot *aSnapshot, int aOpFlags)
    59285257{
    5929     AssertReturn (aMachineNode, E_FAIL);
     5258    using namespace settings;
     5259
     5260    AssertReturn (!aMachineNode.isNull(), E_FAIL);
    59305261
    59315262    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     
    59525283        {
    59535284            /* first, delete the entire root snapshot node if it exists */
    5954             CFGNODE snapshotNode = 0;
    5955             CFGLDRGetChildNode (aMachineNode, "Snapshot", 0, &snapshotNode);
    5956             if (snapshotNode)
    5957                 CFGLDRDeleteNode (snapshotNode);
    5958 
    5959             /*
    5960              *  second, if we have any snapshots left, substitute aSnapshot with
    5961              *  the first snapshot to recreate the whole tree, otherwise break
    5962              */
     5285            Key snapshotNode = aMachineNode.findKey ("Snapshot");
     5286            if (!snapshotNode.isNull())
     5287                snapshotNode.zap();
     5288
     5289            /* second, if we have any snapshots left, substitute aSnapshot
     5290             * with the first snapshot to recreate the whole tree, otherwise
     5291             * break */
    59635292            if (mData->mFirstSnapshot)
    59645293            {
     
    59755304        if (op == SaveSS_AddOp)
    59765305        {
    5977             CFGNODE parentNode = 0;
     5306            Key parentNode;
    59785307
    59795308            if (parent)
    59805309            {
    59815310                rc = findSnapshotNode (parent, aMachineNode, NULL, &parentNode);
    5982                 if (FAILED (rc))
    5983                     break;
    5984                 ComAssertBreak (parentNode, rc = E_FAIL);
     5311                CheckComRCBreakRC (rc);
     5312
     5313                ComAssertBreak (!parentNode.isNull(), rc = E_FAIL);
    59855314            }
    59865315
    59875316            do
    59885317            {
    5989                 CFGNODE snapshotsNode = 0;
    5990 
    5991                 if (parentNode)
    5992                 {
    5993                     CFGLDRCreateChildNode (parentNode, "Snapshots", &snapshotsNode);
    5994                     ComAssertBreak (snapshotsNode, rc = E_FAIL);
    5995                 }
     5318                Key snapshotsNode;
     5319
     5320                if (!parentNode.isNull())
     5321                    snapshotsNode = parentNode.createKey ("Snapshots");
    59965322                else
    59975323                    snapshotsNode = aMachineNode;
    59985324                do
    59995325                {
    6000                     CFGNODE snapshotNode = 0;
    6001                     CFGLDRAppendChildNode (snapshotsNode, "Snapshot", &snapshotNode);
    6002                     ComAssertBreak (snapshotNode, rc = E_FAIL);
     5326                    Key snapshotNode = snapshotsNode.appendKey ("Snapshot");
    60035327                    rc = saveSnapshot (snapshotNode, aSnapshot, false /* aAttrsOnly */);
    6004                     CFGLDRReleaseNode (snapshotNode);
    6005 
    6006                     if (FAILED (rc))
    6007                         break;
    6008 
    6009                     /*
    6010                      *  when a new snapshot is added, this means diffs were created
    6011                      *  for every normal/immutable hard disk of the VM, so we need to
    6012                      *  save the current hard disk attachments
    6013                      */
    6014 
    6015                     CFGNODE hdasNode = 0;
    6016                     CFGLDRGetChildNode (aMachineNode, "HardDiskAttachments", 0, &hdasNode);
    6017                     if (hdasNode)
    6018                         CFGLDRDeleteNode (hdasNode);
    6019                     CFGLDRCreateChildNode (aMachineNode, "HardDiskAttachments", &hdasNode);
    6020                     ComAssertBreak (hdasNode, rc = E_FAIL);
    6021 
    6022                     rc = saveHardDisks (hdasNode);
     5328                    CheckComRCBreakRC (rc);
     5329
     5330                    /* when a new snapshot is added, this means diffs were created
     5331                     * for every normal/immutable hard disk of the VM, so we need to
     5332                     * save the current hard disk attachments */
     5333
     5334                    Key hdaNode = aMachineNode.findKey ("HardDiskAttachments");
     5335                    if (!hdaNode.isNull())
     5336                        hdaNode.zap();
     5337                    hdaNode = aMachineNode.createKey ("HardDiskAttachments");
     5338
     5339                    rc = saveHardDisks (hdaNode);
     5340                    CheckComRCBreakRC (rc);
    60235341
    60245342                    if (mHDData->mHDAttachments.size() != 0)
    60255343                    {
    6026                         /*
    6027                          *  If we have one or more attachments then we definitely
    6028                          *  created diffs for them and associated new diffs with
    6029                          *  current settngs. So, since we don't use saveSettings(),
    6030                          *  we need to inform callbacks manually.
    6031                          */
     5344                        /* If we have one or more attachments then we definitely
     5345                         * created diffs for them and associated new diffs with
     5346                         * current settngs. So, since we don't use saveSettings(),
     5347                         * we need to inform callbacks manually. */
    60325348                        if (mType == IsSessionMachine)
    60335349                            mParent->onMachineDataChange (mData->mUuid);
    60345350                    }
    6035 
    6036                     CFGLDRReleaseNode (hdasNode);
    60375351                }
    60385352                while (0);
    6039 
    6040                 if (snapshotsNode != aMachineNode)
    6041                     CFGLDRReleaseNode (snapshotsNode);
    60425353            }
    60435354            while (0);
    60445355
    6045             if (parentNode)
    6046                 CFGLDRReleaseNode (parentNode);
    6047 
    60485356            break;
    60495357        }
     
    60525360                op == SaveSS_UpdateAllOp);
    60535361
    6054         CFGNODE snapshotsNode = 0;
    6055         CFGNODE snapshotNode = 0;
     5362        Key snapshotsNode;
     5363        Key snapshotNode;
    60565364
    60575365        if (!recreateWholeTree)
     
    60595367            rc = findSnapshotNode (aSnapshot, aMachineNode,
    60605368                                   &snapshotsNode, &snapshotNode);
    6061             if (FAILED (rc))
    6062                 break;
    6063             ComAssertBreak (snapshotNode, rc = E_FAIL);
    6064         }
    6065 
    6066         if (!snapshotsNode)
     5369            CheckComRCBreakRC (rc);
     5370        }
     5371
     5372        if (snapshotsNode.isNull())
    60675373            snapshotsNode = aMachineNode;
    60685374
    60695375        if (op == SaveSS_UpdateAttrsOp)
    60705376            rc = saveSnapshot (snapshotNode, aSnapshot, true /* aAttrsOnly */);
    6071         else do
    6072         {
    6073             if (snapshotNode)
    6074             {
    6075                 CFGLDRDeleteNode (snapshotNode);
    6076                 snapshotNode = 0;
    6077             }
    6078             CFGLDRAppendChildNode (snapshotsNode, "Snapshot", &snapshotNode);
    6079             ComAssertBreak (snapshotNode, rc = E_FAIL);
     5377        else
     5378        {
     5379            if (!snapshotNode.isNull())
     5380                snapshotNode.zap();
     5381
     5382            snapshotNode = snapshotsNode.appendKey ("Snapshot");
    60805383            rc = saveSnapshot (snapshotNode, aSnapshot, false /* aAttrsOnly */);
    6081         }
    6082         while (0);
    6083 
    6084         CFGLDRReleaseNode (snapshotNode);
    6085         if (snapshotsNode != aMachineNode)
    6086             CFGLDRReleaseNode (snapshotsNode);
     5384            CheckComRCBreakRC (rc);
     5385        }
    60875386    }
    60885387    while (0);
     
    60945393        {
    60955394            if (!mData->mCurrentSnapshot.isNull())
    6096                 CFGLDRSetUUID (aMachineNode, "currentSnapshot",
    6097                                mData->mCurrentSnapshot->data().mId);
     5395                aMachineNode.setValue <Guid> ("currentSnapshot",
     5396                                              mData->mCurrentSnapshot->data().mId);
    60985397            else
    6099                 CFGLDRDeleteAttribute (aMachineNode, "currentSnapshot");
     5398                aMachineNode.zapValue ("currentSnapshot");
    61005399        }
    61015400        if (aOpFlags & SaveSS_UpdateCurStateModified)
    61025401        {
    6103             if (!mData->mCurrentStateModified)
    6104                 CFGLDRSetBool (aMachineNode, "currentStateModified", false);
    6105             else
    6106                 CFGLDRDeleteAttribute (aMachineNode, "currentStateModified");
     5402            aMachineNode.setValue <bool> ("currentStateModified", true);
    61075403        }
    61085404    }
     
    61155411 *  It is assumed that the given node is empty (unless \a aAttrsOnly is true).
    61165412 *
    6117  *  @param aNode        <Snapshot> node to save the snapshot to
    6118  *  @param aSnapshot    snapshot to save
    6119  *  @param aAttrsOnly   if true, only updatge user-changeable attrs
     5413 *  @param aNode        <Snapshot> node to save the snapshot to.
     5414 *  @param aSnapshot    Snapshot to save.
     5415 *  @param aAttrsOnly   If true, only updatge user-changeable attrs.
    61205416 */
    6121 HRESULT Machine::saveSnapshot (CFGNODE aNode, Snapshot *aSnapshot, bool aAttrsOnly)
    6122 {
    6123     AssertReturn (aNode && aSnapshot, E_INVALIDARG);
     5417HRESULT Machine::saveSnapshot (settings::Key &aNode, Snapshot *aSnapshot, bool aAttrsOnly)
     5418{
     5419    using namespace settings;
     5420
     5421    AssertReturn (!aNode.isNull() && aSnapshot, E_INVALIDARG);
    61245422    AssertReturn (mType == IsMachine || mType == IsSessionMachine, E_FAIL);
    61255423
    61265424    /* uuid (required) */
    61275425    if (!aAttrsOnly)
    6128         CFGLDRSetUUID (aNode, "uuid", aSnapshot->data().mId);
     5426        aNode.setValue <Guid> ("uuid", aSnapshot->data().mId);
    61295427
    61305428    /* name (required) */
    6131     CFGLDRSetBSTR (aNode, "name", aSnapshot->data().mName);
     5429    aNode.setValue <Bstr> ("name", aSnapshot->data().mName);
    61325430
    61335431    /* timeStamp (required) */
    6134     CFGLDRSetDateTime (aNode, "timeStamp", aSnapshot->data().mTimeStamp);
     5432    aNode.setValue <RTTIMESPEC> ("timeStamp", aSnapshot->data().mTimeStamp);
    61355433
    61365434    /* Description node (optional) */
    61375435    if (!aSnapshot->data().mDescription.isNull())
    61385436    {
    6139         CFGNODE descNode = 0;
    6140         CFGLDRCreateChildNode (aNode, "Description", &descNode);
    6141         Assert (descNode);
    6142         CFGLDRSetBSTR (descNode, NULL, aSnapshot->data().mDescription);
    6143         CFGLDRReleaseNode (descNode);
     5437        Key descNode = aNode.createKey ("Description");
     5438        descNode.setKeyValue <Bstr> (aSnapshot->data().mDescription);
    61445439    }
    61455440    else
    61465441    {
    6147         CFGNODE descNode = 0;
    6148         CFGLDRGetChildNode (aNode, "Description", 0, &descNode);
    6149         if (descNode)
    6150             CFGLDRDeleteNode (descNode);
     5442        Key descNode = aNode.findKey ("Description");
     5443        if (!descNode.isNull())
     5444            descNode.zap();
    61515445    }
    61525446
     
    61605454        Utf8Str stateFilePath = aSnapshot->stateFilePath();
    61615455        calculateRelativePath (stateFilePath, stateFilePath);
    6162         CFGLDRSetString (aNode, "stateFile", stateFilePath);
     5456        aNode.setStringValue ("stateFile", stateFilePath);
    61635457    }
    61645458
     
    61695463        /* save hardware */
    61705464        {
    6171             CFGNODE hwNode = 0;
    6172             CFGLDRCreateChildNode (aNode, "Hardware", &hwNode);
    6173 
     5465            Key hwNode = aNode.createKey ("Hardware");
    61745466            HRESULT rc = snapshotMachine->saveHardware (hwNode);
    6175 
    6176             CFGLDRReleaseNode (hwNode);
    6177             if (FAILED (rc))
    6178                 return rc;
     5467            CheckComRCReturnRC (rc);
    61795468        }
    61805469
    61815470        /* save hard disks */
    61825471        {
    6183             CFGNODE hdasNode = 0;
    6184             CFGLDRCreateChildNode (aNode, "HardDiskAttachments", &hdasNode);
    6185 
     5472            Key hdasNode = aNode.createKey ("HardDiskAttachments");
    61865473            HRESULT rc = snapshotMachine->saveHardDisks (hdasNode);
    6187 
    6188             CFGLDRReleaseNode (hdasNode);
    6189             if (FAILED (rc))
    6190                 return rc;
     5474            CheckComRCReturnRC (rc);
    61915475        }
    61925476    }
     
    61985482        if (aSnapshot->children().size())
    61995483        {
    6200             CFGNODE snapshotsNode = 0;
    6201             CFGLDRCreateChildNode (aNode, "Snapshots", &snapshotsNode);
     5484            Key snapshotsNode = aNode.createKey ("Snapshots");
    62025485
    62035486            HRESULT rc = S_OK;
    62045487
    62055488            for (Snapshot::SnapshotList::const_iterator it = aSnapshot->children().begin();
    6206                  it != aSnapshot->children().end() && SUCCEEDED (rc);
     5489                 it != aSnapshot->children().end();
    62075490                 ++ it)
    62085491            {
    6209                 CFGNODE snapshotNode = 0;
    6210                 CFGLDRCreateChildNode (snapshotsNode, "Snapshot", &snapshotNode);
    6211 
     5492                Key snapshotNode = snapshotsNode.createKey ("Snapshot");
    62125493                rc = saveSnapshot (snapshotNode, (*it), aAttrsOnly);
    6213 
    6214                 CFGLDRReleaseNode (snapshotNode);
     5494                CheckComRCReturnRC (rc);
    62155495            }
    6216 
    6217             CFGLDRReleaseNode (snapshotsNode);
    6218             if (FAILED (rc))
    6219                 return rc;
    62205496        }
    62215497    }
     
    62285504 *  It is assumed that the given node is empty.
    62295505 *
    6230  *  @param aNode    <Hardware> node to save the VM hardware confguration to
     5506 *  @param aNode    <Hardware> node to save the VM hardware confguration to.
    62315507 */
    6232 HRESULT Machine::saveHardware (CFGNODE aNode)
    6233 {
    6234     AssertReturn (aNode, E_INVALIDARG);
     5508HRESULT Machine::saveHardware (settings::Key &aNode)
     5509{
     5510    using namespace settings;
     5511
     5512    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    62355513
    62365514    HRESULT rc = S_OK;
    62375515
    6238     /* CPU */
    6239     {
    6240         CFGNODE cpuNode = 0;
    6241         CFGLDRCreateChildNode (aNode, "CPU", &cpuNode);
    6242         CFGNODE hwVirtExNode = 0;
    6243         CFGLDRCreateChildNode (cpuNode, "HardwareVirtEx", &hwVirtExNode);
     5516    /* CPU (optional) */
     5517    {
     5518        Key cpuNode = aNode.createKey ("CPU");
     5519        Key hwVirtExNode = cpuNode.createKey ("HardwareVirtEx");
    62445520        const char *value = NULL;
    62455521        switch (mHWData->mHWVirtExEnabled)
     
    62515527                value = "true";
    62525528                break;
    6253             default:
     5529            case TriStateBool_Default:
    62545530                value = "default";
    62555531        }
    6256         CFGLDRSetString (hwVirtExNode, "enabled", value);
    6257         CFGLDRReleaseNode (hwVirtExNode);
    6258         CFGLDRReleaseNode (cpuNode);
     5532        hwVirtExNode.setStringValue ("enabled", value);
    62595533    }
    62605534
    62615535    /* memory (required) */
    62625536    {
    6263         CFGNODE memoryNode = 0;
    6264         CFGLDRCreateChildNode (aNode, "Memory", &memoryNode);
    6265         CFGLDRSetUInt32 (memoryNode, "RAMSize", mHWData->mMemorySize);
    6266         CFGLDRReleaseNode (memoryNode);
     5537        Key memoryNode = aNode.createKey ("Memory");
     5538        memoryNode.setValue <ULONG> ("RAMSize", mHWData->mMemorySize);
    62675539    }
    62685540
    62695541    /* boot (required) */
    6270     do
    6271     {
    6272         CFGNODE bootNode = 0;
    6273         CFGLDRCreateChildNode (aNode, "Boot", &bootNode);
    6274 
    6275         for (ULONG pos = 0; pos < ELEMENTS (mHWData->mBootOrder); pos ++)
     5542    {
     5543        Key bootNode = aNode.createKey ("Boot");
     5544
     5545        for (ULONG pos = 0; pos < ELEMENTS (mHWData->mBootOrder); ++ pos)
    62765546        {
    62775547            const char *device = NULL;
     
    62825552                     * when loading, the default value NoDevice will remain */
    62835553                    continue;
    6284                 case DeviceType_FloppyDevice:   device = "Floppy";  break;
     5554                case DeviceType_FloppyDevice:   device = "Floppy"; break;
    62855555                case DeviceType_DVDDevice:      device = "DVD"; break;
    62865556                case DeviceType_HardDiskDevice: device = "HardDisk"; break;
    62875557                case DeviceType_NetworkDevice:  device = "Network"; break;
    62885558                default:
    6289                     ComAssertMsgFailedBreak (("Invalid boot device: %d\n",
    6290                                               mHWData->mBootOrder [pos]),
    6291                                               rc = E_FAIL);
     5559                {
     5560                    ComAssertMsgFailedRet (("Invalid boot device: %d\n",
     5561                                            mHWData->mBootOrder [pos]),
     5562                                            E_FAIL);
     5563                }
    62925564            }
    6293             if (FAILED (rc))
    6294                 break;
    6295 
    6296             CFGNODE orderNode = 0;
    6297             CFGLDRAppendChildNode (bootNode, "Order", &orderNode);
    6298 
    6299             CFGLDRSetUInt32 (orderNode, "position", pos + 1);
    6300             CFGLDRSetString (orderNode, "device", device);
    6301 
    6302             CFGLDRReleaseNode (orderNode);
    6303         }
    6304 
    6305         CFGLDRReleaseNode (bootNode);
    6306     }
    6307     while (0);
    6308 
    6309     CheckComRCReturnRC (rc);
     5565
     5566            Key orderNode = bootNode.appendKey ("Order");
     5567            orderNode.setValue <ULONG> ("position", pos + 1);
     5568            orderNode.setStringValue ("device", device);
     5569        }
     5570    }
    63105571
    63115572    /* display (required) */
    63125573    {
    6313         CFGNODE displayNode = 0;
    6314         CFGLDRCreateChildNode (aNode, "Display", &displayNode);
    6315         CFGLDRSetUInt32 (displayNode, "VRAMSize", mHWData->mVRAMSize);
    6316         CFGLDRSetUInt32 (displayNode, "MonitorCount", mHWData->mMonitorCount);
    6317         CFGLDRReleaseNode (displayNode);
     5574        Key displayNode = aNode.createKey ("Display");
     5575        displayNode.setValue <ULONG> ("VRAMSize", mHWData->mVRAMSize);
     5576        displayNode.setValue <ULONG> ("MonitorCount", mHWData->mMonitorCount);
    63185577    }
    63195578
    63205579#ifdef VBOX_VRDP
    63215580    /* VRDP settings (optional) */
    6322     {
    6323         CFGNODE remoteDisplayNode = 0;
    6324         CFGLDRCreateChildNode (aNode, "RemoteDisplay", &remoteDisplayNode);
    6325         if (remoteDisplayNode)
    6326         {
    6327             rc = mVRDPServer->saveSettings (remoteDisplayNode);
    6328             CFGLDRReleaseNode (remoteDisplayNode);
    6329             CheckComRCReturnRC (rc);
    6330         }
    6331     }
     5581    rc = mVRDPServer->saveSettings (aNode);
     5582    CheckComRCReturnRC (rc);
    63325583#endif
    63335584
    63345585    /* BIOS (required) */
    6335     {
    6336         CFGNODE biosNode = 0;
    6337         CFGLDRCreateChildNode (aNode, "BIOS", &biosNode);
    6338         {
    6339             BOOL fSet;
    6340             /* ACPI */
    6341             CFGNODE acpiNode = 0;
    6342             CFGLDRCreateChildNode (biosNode, "ACPI", &acpiNode);
    6343             mBIOSSettings->COMGETTER(ACPIEnabled)(&fSet);
    6344             CFGLDRSetBool (acpiNode, "enabled", !!fSet);
    6345             CFGLDRReleaseNode (acpiNode);
    6346 
    6347             /* IOAPIC */
    6348             CFGNODE ioapicNode = 0;
    6349             CFGLDRCreateChildNode (biosNode, "IOAPIC", &ioapicNode);
    6350             mBIOSSettings->COMGETTER(IOAPICEnabled)(&fSet);
    6351             CFGLDRSetBool (ioapicNode, "enabled", !!fSet);
    6352             CFGLDRReleaseNode (ioapicNode);
    6353 
    6354             /* BIOS logo (optional) **/
    6355             CFGNODE logoNode = 0;
    6356             CFGLDRCreateChildNode (biosNode, "Logo", &logoNode);
    6357             mBIOSSettings->COMGETTER(LogoFadeIn)(&fSet);
    6358             CFGLDRSetBool (logoNode, "fadeIn", !!fSet);
    6359             mBIOSSettings->COMGETTER(LogoFadeOut)(&fSet);
    6360             CFGLDRSetBool (logoNode, "fadeOut", !!fSet);
    6361             ULONG ulDisplayTime;
    6362             mBIOSSettings->COMGETTER(LogoDisplayTime)(&ulDisplayTime);
    6363             CFGLDRSetUInt32 (logoNode, "displayTime", ulDisplayTime);
    6364             Bstr logoPath;
    6365             mBIOSSettings->COMGETTER(LogoImagePath)(logoPath.asOutParam());
    6366             if (logoPath)
    6367                 CFGLDRSetBSTR (logoNode, "imagePath", logoPath);
    6368             else
    6369                 CFGLDRDeleteAttribute (logoNode, "imagePath");
    6370             CFGLDRReleaseNode (logoNode);
    6371 
    6372             /* boot menu (optional) */
    6373             CFGNODE bootMenuNode = 0;
    6374             CFGLDRCreateChildNode (biosNode, "BootMenu", &bootMenuNode);
    6375             BIOSBootMenuMode_T bootMenuMode;
    6376             Bstr bootMenuModeStr;
    6377             mBIOSSettings->COMGETTER(BootMenuMode)(&bootMenuMode);
    6378             switch (bootMenuMode)
    6379             {
    6380                 case BIOSBootMenuMode_Disabled:
    6381                     bootMenuModeStr = "disabled";
    6382                     break;
    6383                 case BIOSBootMenuMode_MenuOnly:
    6384                     bootMenuModeStr = "menuonly";
    6385                     break;
    6386                 default:
    6387                     bootMenuModeStr = "messageandmenu";
    6388             }
    6389             CFGLDRSetBSTR (bootMenuNode, "mode", bootMenuModeStr);
    6390             CFGLDRReleaseNode (bootMenuNode);
    6391 
    6392             /* time offset (optional) */
    6393             CFGNODE timeOffsetNode = 0;
    6394             CFGLDRCreateChildNode (biosNode, "TimeOffset", &timeOffsetNode);
    6395             LONG64 timeOffset;
    6396             mBIOSSettings->COMGETTER(TimeOffset)(&timeOffset);
    6397             CFGLDRSetInt64 (timeOffsetNode, "value", timeOffset);
    6398             CFGLDRReleaseNode (timeOffsetNode);
    6399 
    6400             /* PXE debug flag (optional) */
    6401             CFGNODE pxedebugNode = 0;
    6402             CFGLDRCreateChildNode (biosNode, "PXEDebug", &pxedebugNode);
    6403             mBIOSSettings->COMGETTER(PXEDebugEnabled)(&fSet);
    6404             CFGLDRSetBool (pxedebugNode, "enabled", !!fSet);
    6405             CFGLDRReleaseNode (pxedebugNode);
    6406 
    6407             /* IDE controller type */
    6408             CFGNODE ideControllerNode = 0;
    6409             IDEControllerType_T controllerType;
    6410             CFGLDRCreateChildNode (biosNode, "IDEController", &ideControllerNode);
    6411             mBIOSSettings->COMGETTER(IDEControllerType)(&controllerType);
    6412             switch (controllerType)
    6413             {
    6414                 case IDEControllerType_IDEControllerPIIX3:
    6415                     CFGLDRSetString (ideControllerNode, "type", "PIIX3");
    6416                     break;
    6417                 case IDEControllerType_IDEControllerPIIX4:
    6418                     CFGLDRSetString (ideControllerNode, "type", "PIIX4");
    6419                     break;
    6420                 default:
    6421                     ComAssertMsgFailedBreak (("Invalid IDE Controller type: %d\n",
    6422                                               controllerType), rc = E_FAIL);
    6423             }
    6424             CFGLDRReleaseNode (ideControllerNode);
    6425 
    6426         }
    6427         CFGLDRReleaseNode(biosNode);
    6428     }
     5586    rc = mBIOSSettings->saveSettings (aNode);
     5587    CheckComRCReturnRC (rc);
    64295588
    64305589    /* DVD drive (required) */
    6431     /// @todo (dmik) move the code to DVDDrive
    6432     do
    6433     {
    6434         CFGNODE dvdNode = 0;
    6435         CFGLDRCreateChildNode (aNode, "DVDDrive", &dvdNode);
    6436 
    6437         BOOL fPassthrough;
    6438         mDVDDrive->COMGETTER(Passthrough)(&fPassthrough);
    6439         CFGLDRSetBool(dvdNode, "passthrough", !!fPassthrough);
    6440 
    6441         switch (mDVDDrive->data()->mDriveState)
    6442         {
    6443             case DriveState_ImageMounted:
    6444             {
    6445                 Assert (!mDVDDrive->data()->mDVDImage.isNull());
    6446 
    6447                 Guid id;
    6448                 rc = mDVDDrive->data()->mDVDImage->COMGETTER(Id) (id.asOutParam());
    6449                 Assert (!id.isEmpty());
    6450 
    6451                 CFGNODE imageNode = 0;
    6452                 CFGLDRCreateChildNode (dvdNode, "Image", &imageNode);
    6453                 CFGLDRSetUUID (imageNode, "uuid", id.ptr());
    6454                 CFGLDRReleaseNode (imageNode);
    6455                 break;
    6456             }
    6457             case DriveState_HostDriveCaptured:
    6458             {
    6459                 Assert (!mDVDDrive->data()->mHostDrive.isNull());
    6460 
    6461                 Bstr name;
    6462                 rc = mDVDDrive->data()->mHostDrive->COMGETTER(Name) (name.asOutParam());
    6463                 Assert (!name.isEmpty());
    6464 
    6465                 CFGNODE hostDriveNode = 0;
    6466                 CFGLDRCreateChildNode (dvdNode, "HostDrive", &hostDriveNode);
    6467                 CFGLDRSetBSTR (hostDriveNode, "src", name);
    6468                 CFGLDRReleaseNode (hostDriveNode);
    6469                 break;
    6470             }
    6471             case DriveState_NotMounted:
    6472                 /* do nothing, i.e.leave the DVD drive node empty */
    6473                 break;
    6474             default:
    6475                 ComAssertMsgFailedBreak (("Invalid DVD drive state: %d\n",
    6476                                           mDVDDrive->data()->mDriveState),
    6477                                           rc = E_FAIL);
    6478         }
    6479 
    6480         CFGLDRReleaseNode (dvdNode);
    6481     }
    6482     while (0);
    6483 
     5590    rc = mDVDDrive->saveSettings (aNode);
    64845591    CheckComRCReturnRC (rc);
    64855592
    64865593    /* Flooppy drive (required) */
    6487     /// @todo (dmik) move the code to DVDDrive
    6488     do
    6489     {
    6490         CFGNODE floppyNode = 0;
    6491         CFGLDRCreateChildNode (aNode, "FloppyDrive", &floppyNode);
    6492 
    6493         BOOL fFloppyEnabled;
    6494         rc = mFloppyDrive->COMGETTER(Enabled)(&fFloppyEnabled);
    6495         CFGLDRSetBool (floppyNode, "enabled", !!fFloppyEnabled);
    6496 
    6497         switch (mFloppyDrive->data()->mDriveState)
    6498         {
    6499             case DriveState_ImageMounted:
    6500             {
    6501                 Assert (!mFloppyDrive->data()->mFloppyImage.isNull());
    6502 
    6503                 Guid id;
    6504                 rc = mFloppyDrive->data()->mFloppyImage->COMGETTER(Id) (id.asOutParam());
    6505                 Assert (!id.isEmpty());
    6506 
    6507                 CFGNODE imageNode = 0;
    6508                 CFGLDRCreateChildNode (floppyNode, "Image", &imageNode);
    6509                 CFGLDRSetUUID (imageNode, "uuid", id.ptr());
    6510                 CFGLDRReleaseNode (imageNode);
    6511                 break;
    6512             }
    6513             case DriveState_HostDriveCaptured:
    6514             {
    6515                 Assert (!mFloppyDrive->data()->mHostDrive.isNull());
    6516 
    6517                 Bstr name;
    6518                 rc = mFloppyDrive->data()->mHostDrive->COMGETTER(Name) (name.asOutParam());
    6519                 Assert (!name.isEmpty());
    6520 
    6521                 CFGNODE hostDriveNode = 0;
    6522                 CFGLDRCreateChildNode (floppyNode, "HostDrive", &hostDriveNode);
    6523                 CFGLDRSetBSTR (hostDriveNode, "src", name);
    6524                 CFGLDRReleaseNode (hostDriveNode);
    6525                 break;
    6526             }
    6527             case DriveState_NotMounted:
    6528                 /* do nothing, i.e.leave the Floppy drive node empty */
    6529                 break;
    6530             default:
    6531                 ComAssertMsgFailedBreak (("Invalid Floppy drive state: %d\n",
    6532                                           mFloppyDrive->data()->mDriveState),
    6533                                           rc = E_FAIL);
    6534         }
    6535 
    6536         CFGLDRReleaseNode (floppyNode);
    6537     }
    6538     while (0);
    6539 
     5594    rc = mFloppyDrive->saveSettings (aNode);
    65405595    CheckComRCReturnRC (rc);
    6541 
    65425596
    65435597    /* USB Controller (required) */
     
    65465600
    65475601    /* Network adapters (required) */
    6548     do
    6549     {
    6550         CFGNODE nwNode = 0;
    6551         CFGLDRCreateChildNode (aNode, "Network", &nwNode);
    6552 
    6553         for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
    6554         {
    6555             CFGNODE networkAdapterNode = 0;
    6556             CFGLDRAppendChildNode (nwNode, "Adapter", &networkAdapterNode);
    6557 
    6558             CFGLDRSetUInt32 (networkAdapterNode, "slot", slot);
    6559             CFGLDRSetBool (networkAdapterNode, "enabled",
    6560                            !!mNetworkAdapters [slot]->data()->mEnabled);
    6561             CFGLDRSetBSTR (networkAdapterNode, "MACAddress",
    6562                            mNetworkAdapters [slot]->data()->mMACAddress);
    6563             CFGLDRSetBool (networkAdapterNode, "cable",
    6564                            !!mNetworkAdapters [slot]->data()->mCableConnected);
    6565 
    6566             CFGLDRSetUInt32 (networkAdapterNode, "speed",
    6567                              mNetworkAdapters [slot]->data()->mLineSpeed);
    6568 
    6569             if (mNetworkAdapters [slot]->data()->mTraceEnabled)
    6570                 CFGLDRSetBool (networkAdapterNode, "trace", true);
    6571 
    6572             CFGLDRSetBSTR (networkAdapterNode, "tracefile",
    6573                            mNetworkAdapters [slot]->data()->mTraceFile);
    6574 
    6575             switch (mNetworkAdapters [slot]->data()->mAdapterType)
    6576             {
    6577                 case NetworkAdapterType_NetworkAdapterAm79C970A:
    6578                     CFGLDRSetString (networkAdapterNode, "type", "Am79C970A");
    6579                     break;
    6580                 case NetworkAdapterType_NetworkAdapterAm79C973:
    6581                     CFGLDRSetString (networkAdapterNode, "type", "Am79C973");
    6582                     break;
    6583                 default:
    6584                     ComAssertMsgFailedBreak (("Invalid network adapter type: %d\n",
    6585                                               mNetworkAdapters [slot]->data()->mAdapterType),
    6586                                               rc = E_FAIL);
    6587             }
    6588 
    6589             CFGNODE attachmentNode = 0;
    6590             switch (mNetworkAdapters [slot]->data()->mAttachmentType)
    6591             {
    6592                 case NetworkAttachmentType_NoNetworkAttachment:
    6593                 {
    6594                     /* do nothing -- empty content */
    6595                     break;
    6596                 }
    6597                 case NetworkAttachmentType_NATNetworkAttachment:
    6598                 {
    6599                     CFGLDRAppendChildNode (networkAdapterNode, "NAT", &attachmentNode);
    6600                     break;
    6601                 }
    6602                 case NetworkAttachmentType_HostInterfaceNetworkAttachment:
    6603                 {
    6604                     CFGLDRAppendChildNode (networkAdapterNode, "HostInterface", &attachmentNode);
    6605                     const Bstr &name = mNetworkAdapters [slot]->data()->mHostInterface;
    6606 #ifdef RT_OS_WINDOWS
    6607                     Assert (!name.isNull());
    6608 #endif
    6609 #ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
    6610                     if (!name.isEmpty())
    6611 #endif
    6612                         CFGLDRSetBSTR (attachmentNode, "name", name);
    6613 #ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
    6614                     const Bstr &tapSetupApp =
    6615                         mNetworkAdapters [slot]->data()->mTAPSetupApplication;
    6616                     if (!tapSetupApp.isEmpty())
    6617                         CFGLDRSetBSTR (attachmentNode, "TAPSetup", tapSetupApp);
    6618                     const Bstr &tapTerminateApp =
    6619                         mNetworkAdapters [slot]->data()->mTAPTerminateApplication;
    6620                     if (!tapTerminateApp.isEmpty())
    6621                         CFGLDRSetBSTR (attachmentNode, "TAPTerminate", tapTerminateApp);
    6622 #endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */
    6623                     break;
    6624                 }
    6625                 case NetworkAttachmentType_InternalNetworkAttachment:
    6626                 {
    6627                     CFGLDRAppendChildNode (networkAdapterNode, "InternalNetwork", &attachmentNode);
    6628                     const Bstr &name = mNetworkAdapters[slot]->data()->mInternalNetwork;
    6629                     Assert(!name.isNull());
    6630                     CFGLDRSetBSTR (attachmentNode, "name", name);
    6631                     break;
    6632                 }
    6633                 default:
    6634                 {
    6635                     ComAssertFailedBreak (rc = E_FAIL);
    6636                     break;
    6637                 }
    6638             }
    6639             if (attachmentNode)
    6640                 CFGLDRReleaseNode (attachmentNode);
    6641 
    6642             CFGLDRReleaseNode (networkAdapterNode);
    6643         }
    6644 
    6645         CFGLDRReleaseNode (nwNode);
    6646     }
    6647     while (0);
    6648 
    6649     if (FAILED (rc))
    6650         return rc;
     5602    {
     5603        Key nwNode = aNode.createKey ("Network");
     5604
     5605        for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); ++ slot)
     5606        {
     5607            Key adapterNode = nwNode.appendKey ("Adapter");
     5608
     5609            adapterNode.setValue <ULONG> ("slot", slot);
     5610
     5611            rc = mNetworkAdapters [slot]->saveSettings (adapterNode);
     5612            CheckComRCReturnRC (rc);
     5613        }
     5614    }
    66515615
    66525616    /* Serial ports */
    6653     CFGNODE serialNode = 0;
    6654     CFGLDRCreateChildNode (aNode, "Uart", &serialNode);
    6655 
    6656     for (ULONG slot = 0; slot < ELEMENTS (mSerialPorts); slot++)
    6657     {
    6658         rc = mSerialPorts [slot]->saveSettings (serialNode);
    6659         CheckComRCReturnRC (rc);
    6660     }
    6661     CFGLDRReleaseNode (serialNode);
     5617    {
     5618        Key serialNode = aNode.createKey ("Uart");
     5619        for (ULONG slot = 0; slot < ELEMENTS (mSerialPorts); ++ slot)
     5620        {
     5621            Key portNode = serialNode.appendKey ("Port");
     5622
     5623            portNode.setValue <ULONG> ("slot", slot);
     5624
     5625            rc = mSerialPorts [slot]->saveSettings (portNode);
     5626            CheckComRCReturnRC (rc);
     5627        }
     5628    }
    66625629
    66635630    /* Parallel ports */
    6664     CFGNODE parallelNode = 0;
    6665     CFGLDRCreateChildNode (aNode, "Lpt", &parallelNode);
    6666 
    6667     for (ULONG slot = 0; slot < ELEMENTS (mParallelPorts); slot++)
    6668     {
    6669         rc = mParallelPorts [slot]->saveSettings (parallelNode);
    6670         CheckComRCReturnRC (rc);
    6671     }
    6672     CFGLDRReleaseNode (parallelNode);
     5631    {
     5632        Key parallelNode = aNode.createKey ("Lpt");
     5633        for (ULONG slot = 0; slot < ELEMENTS (mParallelPorts); ++ slot)
     5634        {
     5635            Key portNode = parallelNode.appendKey ("Port");
     5636
     5637            portNode.setValue <ULONG> ("slot", slot);
     5638
     5639            rc = mParallelPorts [slot]->saveSettings (portNode);
     5640            CheckComRCReturnRC (rc);
     5641        }
     5642    }
    66735643
    66745644    /* Audio adapter */
    6675     do
    6676     {
    6677         CFGNODE adapterNode = 0;
    6678         CFGLDRCreateChildNode (aNode, "AudioAdapter", &adapterNode);
    6679 
    6680         switch (mAudioAdapter->data()->mAudioDriver)
    6681         {
    6682             case AudioDriverType_NullAudioDriver:
    6683             {
    6684                 CFGLDRSetString (adapterNode, "driver", "null");
    6685                 break;
    6686             }
    6687 #ifdef RT_OS_WINDOWS
    6688             case AudioDriverType_WINMMAudioDriver:
    6689 # ifdef VBOX_WITH_WINMM
    6690             {
    6691                 CFGLDRSetString (adapterNode, "driver", "winmm");
    6692                 break;
    6693             }
    6694 # endif
    6695             case AudioDriverType_DSOUNDAudioDriver:
    6696             {
    6697                 CFGLDRSetString (adapterNode, "driver", "dsound");
    6698                 break;
    6699             }
    6700 #endif /* RT_OS_WINDOWS */
    6701 #ifdef RT_OS_LINUX
    6702             case AudioDriverType_ALSAAudioDriver:
    6703 # ifdef VBOX_WITH_ALSA
    6704             {
    6705                 CFGLDRSetString (adapterNode, "driver", "alsa");
    6706                 break;
    6707             }
    6708 # endif
    6709 # ifdef VBOX_WITH_PULSE
    6710             case AudioDriverType_PulseAudioDriver:
    6711             {
    6712                 CFGLDRSetString (adapterNode, "driver", "pulse");
    6713                 break;
    6714             }
    6715 # endif
    6716             case AudioDriverType_OSSAudioDriver:
    6717             {
    6718                 CFGLDRSetString (adapterNode, "driver", "oss");
    6719                 break;
    6720             }
    6721 #endif /* RT_OS_LINUX */
    6722 #ifdef RT_OS_DARWIN
    6723             case AudioDriverType_CoreAudioDriver:
    6724             {
    6725                 CFGLDRSetString (adapterNode, "driver", "coreaudio");
    6726                 break;
    6727             }
    6728 #endif
    6729 #ifdef RT_OS_OS2
    6730             case AudioDriverType_MMPMAudioDriver:
    6731             {
    6732                 CFGLDRSetString (adapterNode, "driver", "mmpm");
    6733                 break;
    6734             }
    6735 #endif
    6736             default:
    6737                 ComAssertMsgFailedBreak (("Wrong audio driver type! driver = %d\n",
    6738                                           mAudioAdapter->data()->mAudioDriver),
    6739                                           rc = E_FAIL);
    6740         }
    6741 
    6742         CFGLDRSetBool (adapterNode, "enabled", !!mAudioAdapter->data()->mEnabled);
    6743 
    6744         CFGLDRReleaseNode (adapterNode);
    6745     }
    6746     while (0);
    6747 
    6748     if (FAILED (rc))
    6749         return rc;
     5645    rc = mAudioAdapter->saveSettings (aNode);
     5646    CheckComRCReturnRC (rc);
    67505647
    67515648    /* Shared folders */
    6752     do
    6753     {
    6754         CFGNODE sharedFoldersNode = 0;
    6755         CFGLDRCreateChildNode (aNode, "SharedFolders", &sharedFoldersNode);
     5649    {
     5650        Key sharedFoldersNode = aNode.createKey ("SharedFolders");
    67565651
    67575652        for (HWData::SharedFolderList::const_iterator it = mHWData->mSharedFolders.begin();
     
    67615656            ComObjPtr <SharedFolder> folder = *it;
    67625657
    6763             CFGNODE folderNode = 0;
    6764             CFGLDRAppendChildNode (sharedFoldersNode, "SharedFolder", &folderNode);
     5658            Key folderNode = sharedFoldersNode.appendKey ("SharedFolder");
    67655659
    67665660            /* all are mandatory */
    6767             CFGLDRSetBSTR (folderNode, "name", folder->name());
    6768             CFGLDRSetBSTR (folderNode, "hostPath", folder->hostPath());
    6769 
    6770             CFGLDRReleaseNode (folderNode);
    6771         }
    6772 
    6773         CFGLDRReleaseNode (sharedFoldersNode);
    6774     }
    6775     while (0);
     5661            folderNode.setValue <Bstr> ("name", folder->name());
     5662            folderNode.setValue <Bstr> ("hostPath", folder->hostPath());
     5663        }
     5664    }
    67765665
    67775666    /* Clipboard */
    67785667    {
    6779         CFGNODE clipNode = 0;
    6780         CFGLDRCreateChildNode (aNode, "Clipboard", &clipNode);
    6781 
    6782         const char *mode = "Disabled";
     5668        Key clipNode = aNode.createKey ("Clipboard");
     5669
     5670        const char *modeStr = "Disabled";
    67835671        switch (mHWData->mClipboardMode)
    67845672        {
     
    67875675                break;
    67885676            case ClipboardMode_ClipHostToGuest:
    6789                 mode = "HostToGuest";
     5677                modeStr = "HostToGuest";
    67905678                break;
    67915679            case ClipboardMode_ClipGuestToHost:
    6792                 mode = "GuestToHost";
     5680                modeStr = "GuestToHost";
    67935681                break;
    67945682            case ClipboardMode_ClipBidirectional:
    6795                 mode = "Bidirectional";
     5683                modeStr = "Bidirectional";
    67965684                break;
    67975685            default:
    6798                 AssertMsgFailed (("Clipboard mode %d is invalid",
    6799                                   mHWData->mClipboardMode));
    6800                 break;
    6801         }
    6802         CFGLDRSetString (clipNode, "mode", mode);
    6803 
    6804         CFGLDRReleaseNode (clipNode);
     5686                ComAssertMsgFailedRet (("Clipboard mode %d is invalid",
     5687                                        mHWData->mClipboardMode),
     5688                                       E_FAIL);
     5689        }
     5690        clipNode.setStringValue ("mode", modeStr);
    68055691    }
    68065692
    68075693    /* Guest */
    68085694    {
    6809         CFGNODE guestNode = 0;
    6810         CFGLDRGetChildNode (aNode, "Guest", 0, &guestNode);
     5695        Key guestNode = aNode.findKey ("Guest");
    68115696        /* first, delete the entire node if exists */
    6812         if (guestNode)
    6813             CFGLDRDeleteNode (guestNode);
     5697        if (!guestNode.isNull())
     5698            guestNode.zap();
    68145699        /* then recreate it */
    6815         guestNode = 0;
    6816         CFGLDRCreateChildNode (aNode, "Guest", &guestNode);
    6817 
    6818         CFGLDRSetUInt32 (guestNode, "MemoryBalloonSize",
    6819                          mHWData->mMemoryBalloonSize);
    6820         CFGLDRSetUInt32 (guestNode, "StatisticsUpdateInterval",
    6821                          mHWData->mStatisticsUpdateInterval);
    6822 
    6823         CFGLDRReleaseNode (guestNode);
    6824     }
    6825 
     5700        guestNode = aNode.createKey ("Guest");
     5701
     5702        guestNode.setValue <ULONG> ("MemoryBalloonSize",
     5703                                    mHWData->mMemoryBalloonSize);
     5704        guestNode.setValue <ULONG> ("StatisticsUpdateInterval",
     5705                                    mHWData->mStatisticsUpdateInterval);
     5706    }
     5707
     5708    AssertComRC (rc);
    68265709    return rc;
    68275710}
     
    68315714 *  It is assumed that the given node is empty.
    68325715 *
    6833  *  @param aNode    <HardDiskAttachments> node to save the hard disk confguration to
     5716 *  @param aNode    <HardDiskAttachments> node to save the hard disk confguration to.
    68345717 */
    6835 HRESULT Machine::saveHardDisks (CFGNODE aNode)
    6836 {
    6837     AssertReturn (aNode, E_INVALIDARG);
    6838 
    6839     HRESULT rc = S_OK;
     5718HRESULT Machine::saveHardDisks (settings::Key &aNode)
     5719{
     5720    using namespace settings;
     5721
     5722    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    68405723
    68415724    for (HDData::HDAttachmentList::const_iterator it = mHDData->mHDAttachments.begin();
    6842          it != mHDData->mHDAttachments.end() && SUCCEEDED (rc);
     5725         it != mHDData->mHDAttachments.end();
    68435726         ++ it)
    68445727    {
    68455728        ComObjPtr <HardDiskAttachment> att = *it;
    68465729
    6847         CFGNODE hdNode = 0;
    6848         CFGLDRAppendChildNode (aNode, "HardDiskAttachment", &hdNode);
    6849 
    6850         do
     5730        Key hdNode = aNode.appendKey ("HardDiskAttachment");
     5731
    68515732        {
    68525733            const char *bus = NULL;
     
    68565737                case DiskControllerType_IDE1Controller: bus = "ide1"; break;
    68575738                default:
    6858                     ComAssertFailedBreak (rc = E_FAIL);
     5739                    ComAssertFailedRet (E_FAIL);
    68595740            }
    6860             if (FAILED (rc))
    6861                 break;
    68625741
    68635742            const char *dev = NULL;
     
    68675746                case 1: dev = "slave"; break;
    68685747                default:
    6869                     ComAssertFailedBreak (rc = E_FAIL);
     5748                    ComAssertFailedRet (E_FAIL);
    68705749            }
    6871             if (FAILED (rc))
    6872                 break;
    6873 
    6874             CFGLDRSetUUID (hdNode, "hardDisk", att->hardDisk()->id());
    6875             CFGLDRSetString (hdNode, "bus", bus);
    6876             CFGLDRSetString (hdNode, "device", dev);
    6877         }
    6878         while (0);
    6879 
    6880         CFGLDRReleaseNode (hdNode);
    6881     }
    6882 
    6883     return rc;
     5750
     5751            hdNode.setValue <Guid> ("hardDisk", att->hardDisk()->id());
     5752            hdNode.setStringValue ("bus", bus);
     5753            hdNode.setStringValue ("device", dev);
     5754        }
     5755    }
     5756
     5757    return S_OK;
    68845758}
    68855759
     
    68885762 *  (SaveSTS_* values).
    68895763 *
    6890  *  @param aFlags   a combination of SaveSTS_* flags
    6891  *
    6892  *  @note Locks objects!
     5764 *  @param aFlags   Combination of SaveSTS_* flags.
     5765 *
     5766 *  @note Locks objects for writing.
    68935767 */
    68945768HRESULT Machine::saveStateSettings (int aFlags)
     
    69025776    AutoLock alock (this);
    69035777
    6904     /* load the config file */
    6905     CFGHANDLE configLoader = 0;
    6906     HRESULT rc = openConfigLoader (&configLoader);
    6907     if (FAILED (rc))
    6908         return rc;
    6909 
    6910     CFGNODE machineNode = 0;
    6911     CFGLDRGetNode (configLoader, "VirtualBox/Machine", 0, &machineNode);
    6912 
    6913     do
    6914     {
    6915         ComAssertBreak (machineNode, rc = E_FAIL);
     5778    AssertReturn (isConfigLocked(), E_FAIL);
     5779
     5780    HRESULT rc = S_OK;
     5781
     5782    try
     5783    {
     5784        using namespace settings;
     5785
     5786        /* load the config file */
     5787        File file (File::ReadWrite, mData->mHandleCfgFile,
     5788                   Utf8Str (mData->mConfigFileFull));
     5789        XmlTreeBackend tree;
     5790
     5791        rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
     5792        CheckComRCReturnRC (rc);
     5793
     5794        Key machineNode = tree.rootKey().key ("Machine");
    69165795
    69175796        if (aFlags & SaveSTS_CurStateModified)
    69185797        {
    6919             if (!mData->mCurrentStateModified)
    6920                 CFGLDRSetBool (machineNode, "currentStateModified", false);
    6921             else
    6922                 CFGLDRDeleteAttribute (machineNode, "currentStateModified");
     5798            /* defaults to true */
     5799            machineNode.setValueOr <bool> ("currentStateModified",
     5800                                           !mData->mCurrentStateModified, true);
    69235801        }
    69245802
     
    69305808                Utf8Str stateFilePath = mSSData->mStateFilePath;
    69315809                calculateRelativePath (stateFilePath, stateFilePath);
    6932                 CFGLDRSetString (machineNode, "stateFile", stateFilePath);
     5810                machineNode.setStringValue ("stateFile", stateFilePath);
    69335811            }
    69345812            else
    6935                 CFGLDRDeleteAttribute (machineNode, "stateFile");
     5813                machineNode.zapValue ("stateFile");
    69365814        }
    69375815
     
    69415819                    mSSData->mStateFilePath.isNull());
    69425820
    6943             CFGLDRSetDateTime (machineNode, "lastStateChange",
    6944                                mData->mLastStateChange);
    6945 
    6946             // set the aborted attribute when appropriate
    6947             if (mData->mMachineState == MachineState_Aborted)
    6948                 CFGLDRSetBool (machineNode, "aborted", true);
    6949             else
    6950                 CFGLDRDeleteAttribute (machineNode, "aborted");
    6951         }
    6952     }
    6953     while (0);
    6954 
    6955     if (machineNode)
    6956         CFGLDRReleaseNode (machineNode);
    6957 
    6958     if (SUCCEEDED (rc))
    6959         rc = closeConfigLoader (configLoader, true /* aSaveBeforeClose */);
    6960     else
    6961         closeConfigLoader (configLoader, false /* aSaveBeforeClose */);
     5821            machineNode.setValue <RTTIMESPEC> ("lastStateChange",
     5822                                               mData->mLastStateChange);
     5823
     5824            /* set the aborted attribute when appropriate, defaults to false */
     5825            machineNode.setValueOr <bool> ("aborted",
     5826                                           mData->mMachineState == MachineState_Aborted,
     5827                                           false);
     5828        }
     5829
     5830        /* save settings on success */
     5831        rc = VirtualBox::saveSettingsTree (tree, file);
     5832        CheckComRCReturnRC (rc);
     5833    }
     5834    catch (...)
     5835    {
     5836        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     5837    }
    69625838
    69635839    return rc;
     
    89477823    snapshot.createObject();
    89487824    rc = snapshot->init (snapshotId, aName, aDescription,
    8949                          RTTimeSpecGetMilli (RTTimeNow (&time)),
    8950                          snapshotMachine, mData->mCurrentSnapshot);
    8951     AssertComRCReturn (rc, rc);
     7825                         *RTTimeNow (&time), snapshotMachine,
     7826                         mData->mCurrentSnapshot);
     7827    AssertComRCReturnRC (rc);
    89527828
    89537829    /*
     
    96318507    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    96328508
    9633     /* mParent->removeProgress() needs mParent lock */
     8509    /* mParent->removeProgress() and saveSettings() need mParent lock */
    96348510    AutoMultiLock <2> alock (mParent->wlock(), this->wlock());
    96358511
     
    98778753    ComObjPtr <SnapshotMachine> sm = aTask.snapshot->data().mMachine;
    98788754
    9879     /* mParent is locked because of Progress::notifyComplete(), etc. */
     8755    /* Progress::notifyComplete() et al., saveSettings() need mParent lock */
    98808756    AutoMultiLock <3> alock (mParent->wlock(), this->wlock(), sm->rlock());
    98818757
     
    102699145    }
    102709146
    10271     /* mParent is locked because of Progress::notifyComplete(), etc. */
     9147    /* Progress::notifyComplete() et al., saveSettings() need mParent lock */
    102729148    AutoMultiLock <2> alock (mParent->wlock(), this->wlock());
    102739149
     
    103289204        }
    103299205
    10330         LONG64 snapshotTimeStamp = 0;
     9206        RTTIMESPEC snapshotTimeStamp;
     9207        RTTimeSpecSetMilli (&snapshotTimeStamp, 0);
    103319208
    103329209        {
     
    104629339
    104639340        /* assign the timestamp from the snapshot */
    10464         Assert (snapshotTimeStamp != 0);
     9341        Assert (RTTimeSpecGetMilli (&snapshotTimeStamp) != 0);
    104659342        mData->mLastStateChange = snapshotTimeStamp;
    104669343
     
    108799756 *  @note Locks aMachine object for reading.
    108809757 */
    10881 HRESULT SnapshotMachine::init (Machine *aMachine, CFGNODE aHWNode, CFGNODE aHDAsNode,
     9758HRESULT SnapshotMachine::init (Machine *aMachine,
     9759                               const settings::Key &aHWNode,
     9760                               const settings::Key &aHDAsNode,
    108829761                               INPTR GUIDPARAM aSnapshotId, INPTR BSTR aStateFilePath)
    108839762{
     
    108859764    LogFlowThisFunc (("mName={%ls}\n", aMachine->mUserData->mName.raw()));
    108869765
    10887     AssertReturn (aMachine && aHWNode && aHDAsNode && !Guid (aSnapshotId).isEmpty(),
     9766    AssertReturn (aMachine && !aHWNode.isNull() && !aHDAsNode.isNull() &&
     9767                  !Guid (aSnapshotId).isEmpty(),
    108889768                  E_INVALIDARG);
    108899769
  • trunk/src/VBox/Main/Makefile.kmk

    r6056 r6076  
    11# $Id$
     2
    23## @file
    34# Makefile for the VBox Main module.
     
    2728
    2829LIBRARIES        = VBoxCOM
    29 DLLS             = VBoxXML VBoxC
     30DLLS             = VBoxXML VBoxSettings VBoxC
    3031PROGRAMS         = VBoxSVC
    3132ifneq ($(BUILD_TARGET),win)
     
    101102
    102103VBoxSVC_TEMPLATE = VBOXMAINEXE
    103 VBoxSVC_DEFS = CFGLDR_HAVE_COM IN_CFGLDR_R3
     104VBoxSVC_DEFS = CFGLDR_HAVE_COM IN_CFGLDR_R3 VBOX_MAIN_SETTINGS_ADDONS
    104105ifdef VBOX_WITH_VRDP
    105106VBoxSVC_DEFS += VBOX_VRDP
     
    139140        include \
    140141        $(PATH_VBoxSVC) \
    141         $(PATH_VBoxCOM) \
    142142        $(PATH_CURRENT)
     143VBoxSVC_INCS.win = \
     144        $(PATH_VBoxCOM)
    143145ifdef VBOX_WITH_USB
    144146 VBoxSVC_INCS.os2 = \
     
    149151 VBoxSVC_LIBS += \
    150152        $(PATH_LIB)/VBoxDDU$(VBOX_SUFF_LIB) \
    151         $(PATH_LIB)/VBoxXML$(VBOX_SUFF_LIB)
     153        $(PATH_LIB)/VBoxXML$(VBOX_SUFF_LIB) \
     154        $(PATH_LIB)/VBoxSettings$(VBOX_SUFF_LIB)
    152155else
    153156 VBoxSVC_LIBS += \
    154157        $(PATH_BIN)/VBoxDDU$(VBOX_SUFF_DLL) \
    155         $(PATH_BIN)/VBoxXML$(VBOX_SUFF_DLL)
     158        $(PATH_BIN)/VBoxXML$(VBOX_SUFF_DLL) \
     159        $(PATH_BIN)/VBoxSettings$(VBOX_SUFF_DLL)
    156160endif
    157161VBoxSVC_LIBS.darwin = \
     
    167171        USBProxyService.cpp \
    168172        VirtualBoxBase.cpp \
    169         VirtualBoxXMLUtil.cpp \
    170173        VirtualBoxErrorInfoImpl.cpp \
    171174        VirtualBoxImpl.cpp \
     175        VirtualBoxImplExtra.cpp \
    172176        MachineImpl.cpp \
    173177        SnapshotImpl.cpp \
     
    314318VBoxC_INCS          = \
    315319        include \
    316         $(PATH_VBoxC) \
    317         $(PATH_VBoxCOM)
    318 VBoxC_INCS.win     := \
     320        $(PATH_VBoxC)
     321VBoxC_INCS.win      = \
     322        $(PATH_VBoxCOM) \
    319323        $(PATH_SUB_CURRENT)
    320324
     
    323327        -exported_symbols_list $(PATH_TARGET)/VBoxC.def
    324328ifdef VBOX_USE_VCC80
    325 VBoxC_LDFLAGS.win = /MANIFEST
     329 VBoxC_LDFLAGS.win = /MANIFEST
    326330endif
    327331
     
    395399# VBoxXML
    396400#
     401
    397402VBoxXML_TEMPLATE   = VBOXMAINDLL
    398403VBoxXML_SDKS       = VBOX_XALAN VBOX_XERCES
     
    419424        $(call MSG_TOOL,bin2c,VBoxXML,$<,$@)
    420425        $(QUIET)$(VBOX_BIN2C) SettingsConverter_xsl $< $@
     426
     427
     428#
     429# VBoxSettings (will supercede VBoxXML when done)
     430#
     431
     432VBoxSettings_TEMPLATE   = VBOXMAINDLL
     433VBoxSettings_SDKS       = VBOX_LIBXML2 VBOX_ZLIB
     434VBoxSettings_DEFS       = IN_VBOXSETTINGS_R3
     435VBoxSettings_INCS       = \
     436        include \
     437        $(PATH_TARGET)
     438VBoxSettings_SOURCES    = \
     439        xml/Settings.cpp
     440VBoxSettings_LDFLAGS.darwin = -install_name @executable_path/VBoxSettings.dylib -Wl,-x # no debug info please.
    421441
    422442
     
    494514VBOX_XML_SCHEMA.solaris= xml/VirtualBox-settings-solaris.xsd
    495515
    496 VirtualBoxXMLUtil.cpp_DEPS = $(VBOX_XML_ENTITIES) $(VBOX_XML_ENTITIES_COMMON)
     516VirtualBoxImplExtra.cpp_DEPS = $(VBOX_XML_ENTITIES) $(VBOX_XML_ENTITIES_COMMON)
    497517
    498518$(VBOX_XML_ENTITIES_COMMON): $(VBOX_XML_SCHEMA_COMMON) $(VBOX_BIN2C)
    499         $(call MSG_TOOL,bin2c,VBoxXML,$<,$@)
     519        $(call MSG_TOOL,bin2c,VBoxSVC,$<,$@)
    500520        $(QUIET)$(VBOX_BIN2C) VirtualBox_settings_common_xsd $< $@
    501521
    502522$(VBOX_XML_ENTITIES): $(VBOX_XML_SCHEMA.$(BUILD_TARGET)) $(VBOX_BIN2C)
    503         $(call MSG_TOOL,bin2c,VBoxXML,$<,$@)
     523        $(call MSG_TOOL,bin2c,VBoxSVC,$<,$@)
    504524        $(QUIET)$(VBOX_BIN2C) VirtualBox_settings_xsd $< $@
    505525
     
    519539
    520540$(VBOX_XML_SCHEMADEFS_H): $(VBOX_XML_SCHEMADEFS_XSL) $(VBOX_XML_SCHEMA.$(BUILD_TARGET)) $(VBOX_XML_SCHEMA_COMMON)
    521         $(call MSG_TOOL,xsltproc,VBoxXML,$<,$@)
     541        $(call MSG_TOOL,xsltproc,VBoxSVC,$<,$@)
    522542        $(QUIET)$(VBOX_XSLTPROC) -o $@ $(filter-out $(VBOX_XML_SCHEMA_COMMON),$^)
    523543
     
    556576
    557577$(IDLFILE): idl/xpidl.xsl $(XIDLFILE) | $(call DIRDEP,$(dir $(IDLFILE)))
    558         $(call MSG_TOOL,xsltproc,VBoxXML,$<,$@)
     578        $(call MSG_TOOL,xsltproc,VBoxSVC,$<,$@)
    559579        $(QUIET)$(MKDIR) -p $(@D)
    560580        $(QUIET)$(VBOX_XSLTPROC) -o $@ $^
    561581
    562582$(IDLTYPELIB): $(IDLFILE) | $(call DIRDEP,$(dir $(IDLTYPELIB)))
    563         $(call MSG_TOOL,xpidl,VBoxXML,$<,$@)
     583        $(call MSG_TOOL,xpidl,VBoxSVC,$<,$@)
    564584        $(QUIET)$(VBOX_XPIDL) -m typelib -I $(VBOX_PATH_XPCOM_IDL) -e $@ $<
    565585
    566586$(IDLHEADER): $(IDLFILE) | $(call DIRDEP,$(dir $(IDLHEADER)))
    567         $(call MSG_TOOL,xpidl,VBoxXML,$<,$@)
     587        $(call MSG_TOOL,xpidl,VBoxSVC,$<,$@)
    568588        $(QUIET)$(VBOX_XPIDL) -m header  -I $(VBOX_PATH_XPCOM_IDL) -e $@ $<
    569589
     
    581601
    582602$(IDLFILE): idl/midl.xsl $(XIDLFILE)
    583         $(call MSG_TOOL,xsltproc,VBoxXML,$<,$@)
     603        $(call MSG_TOOL,xsltproc,VBoxSVC,$<,$@)
    584604        $(QUIET)$(MKDIR) -p $(VBOX_PATH_SDK)/idl
    585605        $(QUIET)$(VBOX_XSLTPROC) -o $@ $^
  • trunk/src/VBox/Main/NetworkAdapterImpl.cpp

    r5999 r6076  
    935935// public methods only for internal purposes
    936936////////////////////////////////////////////////////////////////////////////////
     937
     938/**
     939 *  Loads settings from the given adapter node.
     940 *  May be called once right after this object creation.
     941 *
     942 *  @param aAdapterNode <Adapter> node.
     943 *
     944 *  @note Locks this object for writing.
     945 */
     946HRESULT NetworkAdapter::loadSettings (const settings::Key &aAdapterNode)
     947{
     948    using namespace settings;
     949
     950    AssertReturn (!aAdapterNode.isNull(), E_FAIL);
     951
     952    AutoCaller autoCaller (this);
     953    AssertComRCReturnRC (autoCaller.rc());
     954
     955    AutoLock alock (this);
     956
     957    /* Note: we assume that the default values for attributes of optional
     958     * nodes are assigned in the Data::Data() constructor and don't do it
     959     * here. It implies that this method may only be called after constructing
     960     * a new BIOSSettings object while all its data fields are in the default
     961     * values. Exceptions are fields whose creation time defaults don't match
     962     * values that should be applied when these fields are not explicitly set
     963     * in the settings file (for backwards compatibility reasons). This takes
     964     * place when a setting of a newly created object must default to A while
     965     * the same setting of an object loaded from the old settings file must
     966     * default to B. */
     967
     968    HRESULT rc = S_OK;
     969
     970    /* type (optional, defaults to Am79C970A) */
     971    const char *adapterType = aAdapterNode.stringValue ("type");
     972
     973    if (strcmp (adapterType, "Am79C970A") == 0)
     974        mData->mAdapterType = NetworkAdapterType_NetworkAdapterAm79C970A;
     975    else if (strcmp (adapterType, "Am79C973") == 0)
     976        mData->mAdapterType = NetworkAdapterType_NetworkAdapterAm79C973;
     977    else
     978        ComAssertMsgFailedRet (("Invalid adapter type '%s'", adapterType),
     979                               E_FAIL);
     980
     981    /* enabled (required) */
     982    mData->mEnabled = aAdapterNode.value <bool> ("enabled");
     983    /* MAC address (can be null) */
     984    rc = COMSETTER(MACAddress) (Bstr (aAdapterNode.stringValue ("MACAddress")));
     985    CheckComRCReturnRC (rc);
     986    /* cable (required) */
     987    mData->mCableConnected = aAdapterNode.value <bool> ("cable");
     988    /* line speed (defaults to 100 Mbps) */
     989    mData->mLineSpeed = aAdapterNode.value <ULONG> ("speed");
     990    /* tracing (defaults to false) */
     991    mData->mTraceEnabled = aAdapterNode.value <bool> ("trace");
     992    mData->mTraceFile = aAdapterNode.stringValue ("tracefile");
     993
     994    /* One of NAT, HostInerface, Internal or nothing */
     995    Key attachmentNode;
     996
     997    if (!(attachmentNode = aAdapterNode.findKey ("NAT")).isNull())
     998    {
     999        /* NAT */
     1000
     1001        rc = AttachToNAT();
     1002        CheckComRCReturnRC (rc);
     1003    }
     1004    else
     1005    if (!(attachmentNode = aAdapterNode.findKey ("HostInerface")).isNull())
     1006    {
     1007        /* Host Interface Networking */
     1008
     1009        Bstr name = attachmentNode.stringValue ("name");
     1010#ifdef RT_OS_WINDOWS
     1011        /* name can be empty on Win32, but not null */
     1012        ComAssertRet (!name.isNull(), E_FAIL);
     1013#endif
     1014        rc = COMSETTER(HostInterface) (name);
     1015        CheckComRCReturnRC (rc);
     1016
     1017#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
     1018        /* optopnal */
     1019        mData->mTAPSetupApplication = attachmentNode.stringValue ("TAPSetup");
     1020        mData->mTAPTerminateApplication = attachmentNode.stringValue ("TAPTerminate");
     1021#endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */
     1022
     1023        rc = AttachToHostInterface();
     1024        CheckComRCReturnRC (rc);
     1025    }
     1026    else
     1027    if (!(attachmentNode = aAdapterNode.findKey ("InternalNetwork")).isNull())
     1028    {
     1029        /* Internal Networking */
     1030
     1031        /* required */
     1032        mData->mInternalNetwork = attachmentNode.stringValue ("name");
     1033
     1034        rc = AttachToInternalNetwork();
     1035        CheckComRCReturnRC (rc);
     1036    }
     1037    else
     1038    {
     1039        /* Adapter has no children */
     1040        rc = Detach();
     1041        CheckComRCReturnRC (rc);
     1042    }
     1043
     1044    return S_OK;
     1045}
     1046
     1047/**
     1048 *  Saves settings to the given adapter node.
     1049 *
     1050 *  Note that the given Adapter node is comletely empty on input.
     1051 *
     1052 *  @param aAdapterNode <Adapter> node.
     1053 *
     1054 *  @note Locks this object for reading.
     1055 */
     1056HRESULT NetworkAdapter::saveSettings (settings::Key &aAdapterNode)
     1057{
     1058    using namespace settings;
     1059
     1060    AssertReturn (!aAdapterNode.isNull(), E_FAIL);
     1061
     1062    AutoCaller autoCaller (this);
     1063    AssertComRCReturnRC (autoCaller.rc());
     1064
     1065    AutoReaderLock alock (this);
     1066
     1067    aAdapterNode.setValue <bool> ("enabled", !!mData->mEnabled);
     1068    aAdapterNode.setValue <Bstr> ("MACAddress", mData->mMACAddress);
     1069    aAdapterNode.setValue <bool> ("cable", !!mData->mCableConnected);
     1070
     1071    aAdapterNode.setValue <ULONG> ("speed", mData->mLineSpeed);
     1072
     1073    if (mData->mTraceEnabled)
     1074        aAdapterNode.setValue <bool> ("trace", true);
     1075
     1076    aAdapterNode.setValueOr <Bstr> ("tracefile", mData->mTraceFile, Bstr::Null);
     1077
     1078    const char *typeStr = NULL;
     1079    switch (mData->mAdapterType)
     1080    {
     1081        case NetworkAdapterType_NetworkAdapterAm79C970A:
     1082            typeStr = "Am79C970A";
     1083            break;
     1084        case NetworkAdapterType_NetworkAdapterAm79C973:
     1085            typeStr = "Am79C973";
     1086            break;
     1087        default:
     1088            ComAssertMsgFailedRet (("Invalid network adapter type: %d\n",
     1089                                    mData->mAdapterType),
     1090                                   E_FAIL);
     1091    }
     1092    aAdapterNode.setStringValue ("type", typeStr);
     1093
     1094    switch (mData->mAttachmentType)
     1095    {
     1096        case NetworkAttachmentType_NoNetworkAttachment:
     1097        {
     1098            /* do nothing -- empty content */
     1099            break;
     1100        }
     1101        case NetworkAttachmentType_NATNetworkAttachment:
     1102        {
     1103            Key attachmentNode = aAdapterNode.createKey ("NAT");
     1104            break;
     1105        }
     1106        case NetworkAttachmentType_HostInterfaceNetworkAttachment:
     1107        {
     1108            Key attachmentNode = aAdapterNode.createKey ("HostInterface");
     1109#ifdef RT_OS_WINDOWS
     1110            Assert (!mData->mHostInterface.isNull());
     1111#endif
     1112#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
     1113            if (!mData->mHostInterface.isEmpty())
     1114#endif
     1115                attachmentNode.setValue <Bstr> ("name", mData->mHostInterface);
     1116#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
     1117            if (!mData->mTAPSetupApplication.isEmpty())
     1118                attachmentNode.setValue <Bstr> ("TAPSetup",
     1119                                                mData->mTAPSetupApplication);
     1120            if (!mData->mTAPTerminateApplication.isEmpty())
     1121                attachmentNode.setValue <Bstr> ("TAPTerminate",
     1122                                                mData->mTAPTerminateApplication);
     1123#endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */
     1124            break;
     1125        }
     1126        case NetworkAttachmentType_InternalNetworkAttachment:
     1127        {
     1128            Key attachmentNode = aAdapterNode.createKey ("InternalNetwork");
     1129            Assert (!mData->mInternalNetwork.isNull());
     1130            attachmentNode.setValue <Bstr> ("name", mData->mInternalNetwork);
     1131            break;
     1132        }
     1133        default:
     1134        {
     1135            ComAssertFailedRet (E_FAIL);
     1136        }
     1137    }
     1138
     1139    return S_OK;
     1140}
    9371141
    9381142/**
  • trunk/src/VBox/Main/ParallelPortImpl.cpp

    r5999 r6076  
    161161
    162162/**
     163 *  Loads settings from the given port node.
     164 *  May be called once right after this object creation.
     165 *
     166 *  @param aPortNode <Port> node.
     167 *
     168 *  @note Locks this object for writing.
     169 */
     170HRESULT ParallelPort::loadSettings (const settings::Key &aPortNode)
     171{
     172    using namespace settings;
     173
     174    AssertReturn (!aPortNode.isNull(), E_FAIL);
     175
     176    AutoCaller autoCaller (this);
     177    AssertComRCReturnRC (autoCaller.rc());
     178
     179    AutoLock alock (this);
     180
     181    /* Note: we assume that the default values for attributes of optional
     182     * nodes are assigned in the Data::Data() constructor and don't do it
     183     * here. It implies that this method may only be called after constructing
     184     * a new BIOSSettings object while all its data fields are in the default
     185     * values. Exceptions are fields whose creation time defaults don't match
     186     * values that should be applied when these fields are not explicitly set
     187     * in the settings file (for backwards compatibility reasons). This takes
     188     * place when a setting of a newly created object must default to A while
     189     * the same setting of an object loaded from the old settings file must
     190     * default to B. */
     191
     192    /* enabled (required) */
     193    mData->mEnabled = aPortNode.value <bool> ("enabled");
     194    /* I/O base (required) */
     195    mData->mIOBase = aPortNode.value <ULONG> ("IOBase");
     196    /* IRQ (required) */
     197    mData->mIRQ = aPortNode.value <ULONG> ("IRQ");
     198    /* device path (may be null) */
     199    /// @todo report an error if enabled is true and path is empty or null!
     200    //  The same applies to COMSETTER(Path).
     201    mData->mPath = aPortNode.stringValue ("path");
     202
     203    return S_OK;
     204}
     205
     206/**
     207 *  Saves settings to the given port node.
     208 *
     209 *  Note that the given Port node is comletely empty on input.
     210 *
     211 *  @param aPortNode <Port> node.
     212 *
     213 *  @note Locks this object for reading.
     214 */
     215HRESULT ParallelPort::saveSettings (settings::Key &aPortNode)
     216{
     217    using namespace settings;
     218
     219    AssertReturn (!aPortNode.isNull(), E_FAIL);
     220
     221    AutoCaller autoCaller (this);
     222    AssertComRCReturnRC (autoCaller.rc());
     223
     224    AutoReaderLock alock (this);
     225
     226    aPortNode.setValue <bool> ("enabled", !!mData->mEnabled);
     227    aPortNode.setValue <ULONG> ("IOBase", mData->mIOBase, 16);
     228    aPortNode.setValue <ULONG> ("IRQ", mData->mIRQ);
     229
     230    /* 'path' is optional in XML */
     231    if (!mData->mPath.isEmpty())
     232        aPortNode.setValue <Bstr> ("path", mData->mPath);
     233
     234    return S_OK;
     235}
     236
     237/**
    163238 *  @note Locks this object for writing.
    164239 */
     
    233308    /* this will back up current data */
    234309    mData.assignCopy (aThat->mData);
    235 }
    236 
    237 HRESULT ParallelPort::loadSettings (CFGNODE aNode, ULONG aSlot)
    238 {
    239     LogFlowThisFunc (("aMachine=%p\n", aNode));
    240 
    241     AssertReturn (aNode, E_FAIL);
    242 
    243     AutoCaller autoCaller (this);
    244     AssertComRCReturnRC (autoCaller.rc());
    245 
    246     AutoLock alock (this);
    247 
    248     CFGNODE portNode = NULL;
    249     CFGLDRGetChildNode (aNode, "Port", aSlot, &portNode);
    250 
    251     /* slot number (required) */
    252     /* slot unicity is guaranteed by XML Schema */
    253     uint32_t uSlot = 0;
    254     CFGLDRQueryUInt32 (portNode, "slot", &uSlot);
    255     /* enabled (required) */
    256     bool fEnabled = false;
    257     CFGLDRQueryBool (portNode, "enabled", &fEnabled);
    258     /* I/O base (required) */
    259     uint32_t uIOBase;
    260     CFGLDRQueryUInt32 (portNode, "IOBase", &uIOBase);
    261     /* IRQ (required) */
    262     uint32_t uIRQ;
    263     CFGLDRQueryUInt32 (portNode, "IRQ", &uIRQ);
    264     /* device path */
    265     Bstr path;
    266     CFGLDRQueryBSTR   (portNode, "path", path.asOutParam());
    267 
    268     mData->mEnabled = fEnabled;
    269     mData->mSlot    = uSlot;
    270     mData->mIOBase  = uIOBase;
    271     mData->mIRQ     = uIRQ;
    272     mData->mPath    = path;
    273 
    274     return S_OK;
    275 }
    276 
    277 /**
    278  *  Saves the port settings to the given <Port> node.
    279  *
    280  *  Note that the given node is always empty so it is not necessary to delete
    281  *  old values.
    282  *
    283  *  @param aNode Node to save the settings to.
    284  *
    285  *  @return
    286  */
    287 HRESULT ParallelPort::saveSettings (CFGNODE aNode)
    288 {
    289     AssertReturn (aNode, E_FAIL);
    290 
    291     AutoCaller autoCaller (this);
    292     CheckComRCReturnRC (autoCaller.rc());
    293 
    294     AutoReaderLock alock (this);
    295 
    296     CFGNODE portNode = 0;
    297     int vrc = CFGLDRAppendChildNode (aNode, "Port", &portNode);
    298     ComAssertRCRet (vrc, E_FAIL);
    299 
    300     CFGLDRSetUInt32   (portNode, "slot",    mData->mSlot);
    301     CFGLDRSetBool     (portNode, "enabled", !!mData->mEnabled);
    302     CFGLDRSetUInt32Ex (portNode, "IOBase",  mData->mIOBase, 16);
    303     CFGLDRSetUInt32   (portNode, "IRQ",     mData->mIRQ);
    304 
    305     /* 'path' is optional in XML */
    306     if (!mData->mPath.isEmpty())
    307         CFGLDRSetBSTR (portNode, "path", mData->mPath);
    308 
    309     return S_OK;
    310310}
    311311
  • trunk/src/VBox/Main/SerialPortImpl.cpp

    r5999 r6076  
    161161
    162162/**
    163  *  @note Locks this object for writing.
    164  */
    165 bool SerialPort::rollback()
    166 {
    167     /* sanity */
    168     AutoCaller autoCaller (this);
    169     AssertComRCReturn (autoCaller.rc(), false);
    170 
    171     AutoLock alock (this);
    172 
    173     bool changed = false;
    174 
    175     if (mData.isBackedUp())
    176     {
    177         /* we need to check all data to see whether anything will be changed
    178          * after rollback */
    179         changed = mData.hasActualChanges();
    180         mData.rollback();
    181     }
    182 
    183     return changed;
    184 }
    185 
    186 /**
    187  *  @note Locks this object for writing, together with the peer object (also
    188  *  for writing) if there is one.
    189  */
    190 void SerialPort::commit()
    191 {
    192     /* sanity */
    193     AutoCaller autoCaller (this);
    194     AssertComRCReturnVoid (autoCaller.rc());
    195 
    196     /* sanity too */
    197     AutoCaller thatCaller (mPeer);
    198     AssertComRCReturnVoid (thatCaller.rc());
    199 
    200     /* lock both for writing since we modify both */
    201     AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
    202 
    203     if (mData.isBackedUp())
    204     {
    205         mData.commit();
    206         if (mPeer)
    207         {
    208             /* attach new data to the peer and reshare it */
    209             mPeer->mData.attach (mData);
    210         }
    211     }
    212 }
    213 
    214 /**
    215  *  @note Locks this object for writing, together with the peer object
    216  *  represented by @a aThat (locked for reading).
    217  */
    218 void SerialPort::copyFrom (SerialPort *aThat)
    219 {
    220     AssertReturnVoid (aThat != NULL);
    221 
    222     /* sanity */
    223     AutoCaller autoCaller (this);
    224     AssertComRCReturnVoid (autoCaller.rc());
    225 
    226     /* sanity too */
    227     AutoCaller thatCaller (mPeer);
    228     AssertComRCReturnVoid (thatCaller.rc());
    229 
    230     /* peer is not modified, lock it for reading */
    231     AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
    232 
    233     /* this will back up current data */
    234     mData.assignCopy (aThat->mData);
    235 }
    236 
    237 HRESULT SerialPort::loadSettings (CFGNODE aNode, ULONG aSlot)
    238 {
    239     LogFlowThisFunc (("aMachine=%p\n", aNode));
    240 
    241     AssertReturn (aNode, E_FAIL);
     163 *  Loads settings from the given port node.
     164 *  May be called once right after this object creation.
     165 *
     166 *  @param aPortNode <Port> node.
     167 *
     168 *  @note Locks this object for writing.
     169 */
     170HRESULT SerialPort::loadSettings (const settings::Key &aPortNode)
     171{
     172    using namespace settings;
     173
     174    AssertReturn (!aPortNode.isNull(), E_FAIL);
    242175
    243176    AutoCaller autoCaller (this);
     
    246179    AutoLock alock (this);
    247180
    248     HRESULT rc = S_OK;
    249 
    250     CFGNODE portNode = NULL;
    251     CFGLDRGetChildNode (aNode, "Port", aSlot, &portNode);
    252 
    253     /* slot number (required) */
    254     /* slot unicity is guaranteed by XML Schema */
    255     uint32_t uSlot = 0;
    256     CFGLDRQueryUInt32 (portNode, "slot", &uSlot);
     181    /* Note: we assume that the default values for attributes of optional
     182     * nodes are assigned in the Data::Data() constructor and don't do it
     183     * here. It implies that this method may only be called after constructing
     184     * a new BIOSSettings object while all its data fields are in the default
     185     * values. Exceptions are fields whose creation time defaults don't match
     186     * values that should be applied when these fields are not explicitly set
     187     * in the settings file (for backwards compatibility reasons). This takes
     188     * place when a setting of a newly created object must default to A while
     189     * the same setting of an object loaded from the old settings file must
     190     * default to B. */
     191
    257192    /* enabled (required) */
    258     bool fEnabled = false;
    259     CFGLDRQueryBool (portNode, "enabled", &fEnabled);
    260     uint32_t uIOBase;
     193    mData->mEnabled = aPortNode.value <bool> ("enabled");
    261194    /* I/O base (required) */
    262     CFGLDRQueryUInt32 (portNode, "IOBase", &uIOBase);
     195    mData->mIOBase = aPortNode.value <ULONG> ("IOBase");
    263196    /* IRQ (required) */
    264     uint32_t uIRQ;
    265     CFGLDRQueryUInt32 (portNode, "IRQ", &uIRQ);
     197    mData->mIRQ = aPortNode.value <ULONG> ("IRQ");
    266198    /* host mode (required) */
    267     Bstr mode;
    268     CFGLDRQueryBSTR (portNode, "hostMode", mode.asOutParam());
    269     if (mode == L"HostPipe")
     199    const char *mode = aPortNode.stringValue ("hostMode");
     200    if (strcmp (mode, "HostPipe") == 0)
    270201        mData->mHostMode = PortMode_HostPipePort;
    271     else if (mode == L"HostDevice")
     202    else if (strcmp (mode, "HostDevice") == 0)
    272203        mData->mHostMode = PortMode_HostDevicePort;
     204    else if (strcmp (mode, "Disconnected") == 0)
     205        mData->mHostMode = PortMode_DisconnectedPort;
    273206    else
    274         mData->mHostMode = PortMode_DisconnectedPort;
    275     /* pipe/device path */
    276     Bstr path;
    277     CFGLDRQueryBSTR (portNode, "path", path.asOutParam());
    278     /* server mode */
    279     bool fServer = true;
    280     CFGLDRQueryBool (portNode, "server", &fServer);
    281 
    282     mData->mEnabled  = fEnabled;
    283     mData->mSlot     = uSlot;
    284     mData->mIOBase   = uIOBase;
    285     mData->mIRQ      = uIRQ;
    286 
    287     rc = checkSetPath (path);
     207        ComAssertMsgFailedRet (("Invalid port mode '%s'\n", mode), E_FAIL);
     208
     209    /* pipe/device path (optional, defaults to null) */
     210    Bstr path = aPortNode.stringValue ("path");
     211    HRESULT rc = checkSetPath (path);
    288212    CheckComRCReturnRC (rc);
    289 
    290     mData->mPath     = path;
    291     mData->mServer   = fServer;
    292 
    293     return rc;
    294 }
    295 
    296 /**
    297  *  Saves the port settings to the given <Port> node.
    298  *
    299  *  Note that the given node is always empty so it is not necessary to delete
    300  *  old values.
     213    mData->mPath = path;
     214
     215    /* server mode (optional, defaults to false) */
     216    mData->mServer = aPortNode.value <bool> ("server");
     217
     218    return S_OK;
     219}
     220
     221/**
     222 *  Saves the port settings to the given port node.
     223 *
     224 *  Note that the given Port node is comletely empty on input.
     225 *
     226 *  @param aPortNode <Port> node.
    301227 *
    302  *  @param aNode Node to save the settings to.
    303  * 
    304  *  @return
    305  */
    306 HRESULT SerialPort::saveSettings (CFGNODE aNode)
    307 {
    308     AssertReturn (aNode, E_FAIL);
    309 
    310     AutoCaller autoCaller (this);
    311     CheckComRCReturnRC (autoCaller.rc());
    312 
    313     AutoReaderLock alock (this);
    314 
    315     CFGNODE portNode = 0;
    316     int vrc = CFGLDRAppendChildNode (aNode, "Port", &portNode);
    317     ComAssertRCRet (vrc, E_FAIL);
    318 
    319     const char *mode;
     228 *  @note Locks this object for reading.
     229 */
     230HRESULT SerialPort::saveSettings (settings::Key &aPortNode)
     231{
     232    using namespace settings;
     233
     234    AssertReturn (!aPortNode.isNull(), E_FAIL);
     235
     236    AutoCaller autoCaller (this);
     237    AssertComRCReturnRC (autoCaller.rc());
     238
     239    AutoReaderLock alock (this);
     240
     241    aPortNode.setValue <bool> ("enabled", !!mData->mEnabled);
     242    aPortNode.setValue <ULONG> ("IOBase", mData->mIOBase, 16);
     243    aPortNode.setValue <ULONG> ("IRQ", mData->mIRQ);
     244
     245    const char *mode = NULL;
    320246    switch (mData->mHostMode)
    321247    {
    322         default:
    323248        case PortMode_DisconnectedPort:
    324249            mode = "Disconnected";
     
    330255            mode = "HostDevice";
    331256            break;
    332     }
    333     CFGLDRSetUInt32   (portNode, "slot",     mData->mSlot);
    334     CFGLDRSetBool     (portNode, "enabled",  !!mData->mEnabled);
    335     CFGLDRSetUInt32Ex (portNode, "IOBase",   mData->mIOBase, 16);
    336     CFGLDRSetUInt32   (portNode, "IRQ",      mData->mIRQ);
    337     CFGLDRSetString   (portNode, "hostMode", mode);
    338 
     257        default:
     258            ComAssertMsgFailedRet (("Invalid serial port mode: %d\n",
     259                                    mData->mHostMode),
     260                                   E_FAIL);
     261    }
     262    aPortNode.setStringValue ("hostMode", mode);
     263   
    339264    /* Always save non-null mPath and mServer to preserve the user values for
    340265     * later use. Note that 'server' is false by default in XML so we don't
    341266     * save it when it's false. */
    342267    if (!mData->mPath.isEmpty())
    343         CFGLDRSetBSTR (portNode, "path", mData->mPath);
     268        aPortNode.setValue <Bstr> ("path", mData->mPath);
    344269    if (mData->mServer)
    345         CFGLDRSetBool (portNode, "server", !!mData->mServer);
    346 
    347     return S_OK;
     270        aPortNode.setValue <bool> ("server", !!mData->mServer);
     271
     272    return S_OK;
     273}
     274
     275/**
     276 *  @note Locks this object for writing.
     277 */
     278bool SerialPort::rollback()
     279{
     280    /* sanity */
     281    AutoCaller autoCaller (this);
     282    AssertComRCReturn (autoCaller.rc(), false);
     283
     284    AutoLock alock (this);
     285
     286    bool changed = false;
     287
     288    if (mData.isBackedUp())
     289    {
     290        /* we need to check all data to see whether anything will be changed
     291         * after rollback */
     292        changed = mData.hasActualChanges();
     293        mData.rollback();
     294    }
     295
     296    return changed;
     297}
     298
     299/**
     300 *  @note Locks this object for writing, together with the peer object (also
     301 *  for writing) if there is one.
     302 */
     303void SerialPort::commit()
     304{
     305    /* sanity */
     306    AutoCaller autoCaller (this);
     307    AssertComRCReturnVoid (autoCaller.rc());
     308
     309    /* sanity too */
     310    AutoCaller thatCaller (mPeer);
     311    AssertComRCReturnVoid (thatCaller.rc());
     312
     313    /* lock both for writing since we modify both */
     314    AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
     315
     316    if (mData.isBackedUp())
     317    {
     318        mData.commit();
     319        if (mPeer)
     320        {
     321            /* attach new data to the peer and reshare it */
     322            mPeer->mData.attach (mData);
     323        }
     324    }
     325}
     326
     327/**
     328 *  @note Locks this object for writing, together with the peer object
     329 *  represented by @a aThat (locked for reading).
     330 */
     331void SerialPort::copyFrom (SerialPort *aThat)
     332{
     333    AssertReturnVoid (aThat != NULL);
     334
     335    /* sanity */
     336    AutoCaller autoCaller (this);
     337    AssertComRCReturnVoid (autoCaller.rc());
     338
     339    /* sanity too */
     340    AutoCaller thatCaller (mPeer);
     341    AssertComRCReturnVoid (thatCaller.rc());
     342
     343    /* peer is not modified, lock it for reading */
     344    AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
     345
     346    /* this will back up current data */
     347    mData.assignCopy (aThat->mData);
    348348}
    349349
  • trunk/src/VBox/Main/SnapshotImpl.cpp

    r5999 r6076  
    3232Snapshot::Data::Data()
    3333{
    34     mTimeStamp = 0;
     34    RTTimeSpecSetMilli (&mTimeStamp, 0);
    3535};
    3636
     
    6262 */
    6363HRESULT Snapshot::init (const Guid &aId, INPTR BSTR aName, INPTR BSTR aDescription,
    64                         LONG64 aTimeStamp, SnapshotMachine *aMachine,
     64                        RTTIMESPEC aTimeStamp, SnapshotMachine *aMachine,
    6565                        Snapshot *aParent)
    6666{
     
    249249    CHECK_READY();
    250250
    251     *aTimeStamp = mData.mTimeStamp;
     251    *aTimeStamp = RTTimeSpecGetMilli (&mData.mTimeStamp);
    252252    return S_OK;
    253253}
  • trunk/src/VBox/Main/SystemPropertiesImpl.cpp

    r5999 r6076  
    378378/////////////////////////////////////////////////////////////////////////////
    379379
    380 HRESULT SystemProperties::loadSettings (CFGNODE aGlobal)
    381 {
     380HRESULT SystemProperties::loadSettings (const settings::Key &aGlobal)
     381{
     382    using namespace settings;
     383
    382384    AutoLock lock (this);
    383385    CHECK_READY();
    384386
    385     ComAssertRet (aGlobal, E_FAIL);
    386 
    387     CFGNODE properties = NULL;
    388     CFGLDRGetChildNode (aGlobal, "SystemProperties", 0, &properties);
    389     ComAssertRet (properties, E_FAIL);
    390 
    391     HRESULT rc = E_FAIL;
    392 
    393     do
    394     {
    395         Bstr bstr;
    396 
    397         CFGLDRQueryBSTR (properties, "defaultVDIFolder",
    398                          bstr.asOutParam());
    399         rc = setDefaultVDIFolder (bstr);
    400         if (FAILED (rc))
    401             break;
    402 
    403         CFGLDRQueryBSTR (properties, "defaultMachineFolder",
    404                          bstr.asOutParam());
    405         rc = setDefaultMachineFolder (bstr);
    406         if (FAILED (rc))
    407             break;
    408 
    409         CFGLDRQueryBSTR (properties, "remoteDisplayAuthLibrary",
    410                          bstr.asOutParam());
    411         rc = setRemoteDisplayAuthLibrary (bstr);
    412         if (FAILED (rc))
    413             break;
    414 
    415         CFGLDRQueryBSTR (properties, "webServiceAuthLibrary",
    416                          bstr.asOutParam());
    417         rc = setWebServiceAuthLibrary (bstr);
    418         if (FAILED (rc))
    419             break;
    420 
    421         CFGLDRQueryBool (properties, "HWVirtExEnabled", (bool*)&mHWVirtExEnabled);
    422 
    423         uint32_t u32Count = 3;
    424         CFGLDRQueryUInt32 (properties, "LogHistoryCount", &u32Count);
    425         mLogHistoryCount = u32Count;
    426     }
    427     while (0);
    428 
    429     CFGLDRReleaseNode (properties);
    430 
    431     return rc;
    432 }
    433 
    434 HRESULT SystemProperties::saveSettings (CFGNODE aGlobal)
    435 {
     387    AssertReturn (!aGlobal.isNull(), E_FAIL);
     388
     389    HRESULT rc = S_OK;
     390
     391    Key properties = aGlobal.key ("SystemProperties");
     392
     393    Bstr bstr;
     394
     395    bstr = properties.stringValue ("defaultVDIFolder");
     396    rc = setDefaultVDIFolder (bstr);
     397    CheckComRCReturnRC (rc);
     398
     399    bstr = properties.stringValue ("defaultMachineFolder");
     400    rc = setDefaultMachineFolder (bstr);
     401    CheckComRCReturnRC (rc);
     402
     403    bstr = properties.stringValue ("remoteDisplayAuthLibrary");
     404    rc = setRemoteDisplayAuthLibrary (bstr);
     405    CheckComRCReturnRC (rc);
     406
     407    bstr = properties.stringValue ("webServiceAuthLibrary");
     408    rc = setWebServiceAuthLibrary (bstr);
     409    CheckComRCReturnRC (rc);
     410
     411    /* Note: not <BOOL> because Win32 defines BOOL as int */
     412    mHWVirtExEnabled = properties.value <bool> ("HWVirtExEnabled");
     413
     414    mLogHistoryCount = properties.value <ULONG> ("LogHistoryCount");
     415
     416    return S_OK;
     417}
     418
     419HRESULT SystemProperties::saveSettings (settings::Key &aGlobal)
     420{
     421    using namespace settings;
     422
    436423    AutoLock lock (this);
    437424    CHECK_READY();
    438425
    439     ComAssertRet (aGlobal, E_FAIL);
    440 
    441     // first, delete the entry
    442     CFGNODE properties = NULL;
    443     int vrc = CFGLDRGetChildNode (aGlobal, "SystemProperties", 0, &properties);
    444     if (VBOX_SUCCESS (vrc))
    445     {
    446         vrc = CFGLDRDeleteNode (properties);
    447         ComAssertRCRet (vrc, E_FAIL);
    448     }
    449     // then, recreate it
    450     vrc = CFGLDRCreateChildNode (aGlobal, "SystemProperties", &properties);
    451     ComAssertRCRet (vrc, E_FAIL);
     426    ComAssertRet (!aGlobal.isNull(), E_FAIL);
     427
     428    /* first, delete the entry */
     429    Key properties = aGlobal.findKey ("SystemProperties");
     430    if (!properties.isNull())
     431        properties.zap();
     432    /* then, recreate it */
     433    properties = aGlobal.createKey ("SystemProperties");
    452434
    453435    if (mDefaultVDIFolder)
    454         CFGLDRSetBSTR (properties, "defaultVDIFolder",
    455                        mDefaultVDIFolder);
     436        properties.setValue <Bstr> ("defaultVDIFolder", mDefaultVDIFolder);
    456437
    457438    if (mDefaultMachineFolder)
    458         CFGLDRSetBSTR (properties, "defaultMachineFolder",
    459                        mDefaultMachineFolder);
     439        properties.setValue <Bstr> ("defaultMachineFolder", mDefaultMachineFolder);
    460440
    461441    if (mRemoteDisplayAuthLibrary)
    462         CFGLDRSetBSTR (properties, "remoteDisplayAuthLibrary",
    463                        mRemoteDisplayAuthLibrary);
     442        properties.setValue <Bstr> ("remoteDisplayAuthLibrary", mRemoteDisplayAuthLibrary);
    464443
    465444    if (mWebServiceAuthLibrary)
    466         CFGLDRSetBSTR (properties, "webServiceAuthLibrary",
    467                        mWebServiceAuthLibrary);
    468 
    469     CFGLDRSetBool (properties, "HWVirtExEnabled", !!mHWVirtExEnabled);
    470 
    471     CFGLDRSetUInt32 (properties, "LogHistoryCount", mLogHistoryCount);
     445        properties.setValue <Bstr> ("webServiceAuthLibrary", mWebServiceAuthLibrary);
     446
     447    properties.setValue <bool> ("HWVirtExEnabled", !!mHWVirtExEnabled);
     448
     449    properties.setValue <ULONG> ("LogHistoryCount", mLogHistoryCount);
    472450
    473451    return S_OK;
  • trunk/src/VBox/Main/USBControllerImpl.cpp

    r5999 r6076  
    481481/////////////////////////////////////////////////////////////////////////////
    482482
    483 /**
    484  *  Loads settings from the configuration node.
    485  *
    486  *  @note Locks objects for writing!
     483/**
     484 *  Loads settings from the given machine node.
     485 *  May be called once right after this object creation.
     486 *
     487 *  @param aMachineNode <Machine> node.
     488 *
     489 *  @note Locks this object for writing.
    487490 */
    488 HRESULT USBController::loadSettings (CFGNODE aMachine)
    489 {
    490     AssertReturn (aMachine, E_FAIL);
     491HRESULT USBController::loadSettings (const settings::Key &aMachineNode)
     492{
     493    using namespace settings;
     494
     495    AssertReturn (!aMachineNode.isNull(), E_FAIL);
    491496
    492497    AutoCaller autoCaller (this);
     
    495500    AutoLock alock (this);
    496501
    497     CFGNODE controller = NULL;
    498     CFGLDRGetChildNode (aMachine, "USBController", 0, &controller);
    499     Assert (controller);
    500 
    501     /* enabled */
    502     bool enabled;
    503     CFGLDRQueryBool (controller, "enabled", &enabled);
    504     mData->mEnabled = enabled;
    505 
    506     /* enabledEhci */
    507     CFGLDRQueryBool (controller, "enabledEhci", &enabled);
    508     mData->mEnabledEhci = enabled;
     502    /* Note: we assume that the default values for attributes of optional
     503     * nodes are assigned in the Data::Data() constructor and don't do it
     504     * here. It implies that this method may only be called after constructing
     505     * a new BIOSSettings object while all its data fields are in the default
     506     * values. Exceptions are fields whose creation time defaults don't match
     507     * values that should be applied when these fields are not explicitly set
     508     * in the settings file (for backwards compatibility reasons). This takes
     509     * place when a setting of a newly created object must default to A while
     510     * the same setting of an object loaded from the old settings file must
     511     * default to B. */
     512
     513    /* USB Controller node (required) */
     514    Key controller = aMachineNode.key ("USBController");
     515
     516    /* enabled (required) */
     517    mData->mEnabled = controller.value <bool> ("enabled");
     518
     519    /* enabledEhci (optiona, defaults to false) */
     520    mData->mEnabledEhci = controller.value <bool> ("enabledEhci");
    509521
    510522    HRESULT rc = S_OK;
    511523
    512     unsigned filterCount = 0;
    513     CFGLDRCountChildren (controller, "DeviceFilter", &filterCount);
    514     for (unsigned i = 0; i < filterCount && SUCCEEDED (rc); i++)
    515     {
    516         CFGNODE filter = NULL;
    517         CFGLDRGetChildNode (controller, "DeviceFilter", i, &filter);
    518         Assert (filter);
    519 
    520         Bstr name;
    521         CFGLDRQueryBSTR (filter, "name", name.asOutParam());
    522         bool active;
    523         CFGLDRQueryBool (filter, "active", &active);
    524 
    525         Bstr vendorId;
    526         CFGLDRQueryBSTR (filter, "vendorid", vendorId.asOutParam());
    527         Bstr productId;
    528         CFGLDRQueryBSTR (filter, "productid", productId.asOutParam());
    529         Bstr revision;
    530         CFGLDRQueryBSTR (filter, "revision", revision.asOutParam());
    531         Bstr manufacturer;
    532         CFGLDRQueryBSTR (filter, "manufacturer", manufacturer.asOutParam());
    533         Bstr product;
    534         CFGLDRQueryBSTR (filter, "product", product.asOutParam());
    535         Bstr serialNumber;
    536         CFGLDRQueryBSTR (filter, "serialnumber", serialNumber.asOutParam());
    537         Bstr port;
    538         CFGLDRQueryBSTR (filter, "port", port.asOutParam());
    539         Bstr remote;
    540         CFGLDRQueryBSTR (filter, "remote", remote.asOutParam());
    541         uint32_t maskedIfs;
    542         if (RT_FAILURE(CFGLDRQueryUInt32 (filter, "maskedInterfaces", &maskedIfs)))
    543             maskedIfs = 0;
     524    Key::List children = controller.keys ("DeviceFilter");
     525    for (Key::List::const_iterator it = children.begin();
     526         it != children.end(); ++ it)
     527    {
     528        /* required */
     529        Bstr name = (*it).stringValue ("name");
     530        bool active = (*it).value <bool> ("active");
     531
     532        /* optional */
     533        Bstr vendorId = (*it).stringValue ("vendorid");
     534        Bstr productId = (*it).stringValue ("productid");
     535        Bstr revision = (*it).stringValue ("revision");
     536        Bstr manufacturer = (*it).stringValue ("manufacturer");
     537        Bstr product = (*it).stringValue ("product");
     538        Bstr serialNumber = (*it).stringValue ("serialnumber");
     539        Bstr port = (*it).stringValue ("port");
     540        Bstr remote = (*it).stringValue ("remote");
     541        ULONG maskedIfs = (*it).value <ULONG> ("maskedInterfaces");
    544542
    545543        ComObjPtr <USBDeviceFilter> filterObj;
     
    550548                              port, remote, maskedIfs);
    551549        /* error info is set by init() when appropriate */
    552         if (SUCCEEDED (rc))
    553         {
    554             mDeviceFilters->push_back (filterObj);
    555             filterObj->mInList = true;
    556         }
    557 
    558         CFGLDRReleaseNode (filter);
    559     }
    560 
    561     CFGLDRReleaseNode (controller);
    562 
    563     return rc;
    564 }
    565 
    566 /**
    567  *  Saves settings to the configuration node.
    568  *
    569  *  @note Locks objects for reading!
     550        CheckComRCReturnRC (rc);
     551
     552        mDeviceFilters->push_back (filterObj);
     553        filterObj->mInList = true;
     554    }
     555
     556    return S_OK;
     557}
     558
     559/**
     560 *  Saves settings to the given machine node.
     561 *
     562 *  @param aMachineNode <Machine> node.
     563 *
     564 *  @note Locks this object for reading.
    570565 */
    571 HRESULT USBController::saveSettings (CFGNODE aMachine)
    572 {
    573     AssertReturn (aMachine, E_FAIL);
     566HRESULT USBController::saveSettings (settings::Key &aMachineNode)
     567{
     568    using namespace settings;
     569
     570    AssertReturn (!aMachineNode.isNull(), E_FAIL);
    574571
    575572    AutoCaller autoCaller (this);
     
    579576
    580577    /* first, delete the entry */
    581     CFGNODE controller = NULL;
    582     int vrc = CFGLDRGetChildNode (aMachine, "USBController", 0, &controller);
    583     if (VBOX_SUCCESS (vrc))
    584     {
    585         vrc = CFGLDRDeleteNode (controller);
    586         ComAssertRCRet (vrc, E_FAIL);
    587     }
     578    Key controller = aMachineNode.findKey ("USBController");
     579    if (!controller.isNull())
     580        controller.zap();
    588581    /* then, recreate it */
    589     vrc = CFGLDRCreateChildNode (aMachine, "USBController", &controller);
    590     ComAssertRCRet (vrc, E_FAIL);
     582    controller = aMachineNode.createKey ("USBController");
    591583
    592584    /* enabled */
    593     CFGLDRSetBool (controller, "enabled", !!mData->mEnabled);
     585    controller.setValue <bool> ("enabled", !!mData->mEnabled);
    594586
    595587    /* enabledEhci */
    596     CFGLDRSetBool (controller, "enabledEhci", !!mData->mEnabledEhci);
     588    controller.setValue <bool> ("enabledEhci", !!mData->mEnabledEhci);
    597589
    598590    DeviceFilterList::const_iterator it = mDeviceFilters->begin();
     
    602594        const USBDeviceFilter::Data &data = (*it)->data();
    603595
    604         CFGNODE filter = NULL;
    605         CFGLDRAppendChildNode (controller, "DeviceFilter",  &filter);
    606 
    607         CFGLDRSetBSTR (filter, "name", data.mName);
    608         CFGLDRSetBool (filter, "active", !!data.mActive);
     596        Key filter = controller.appendKey ("DeviceFilter");
     597
     598        filter.setValue <Bstr> ("name", data.mName);
     599        filter.setValue <bool> ("active", !!data.mActive);
    609600
    610601        /* all are optional */
    611602#ifndef VBOX_WITH_USBFILTER
     603
    612604        if (data.mVendorId.string())
    613             CFGLDRSetBSTR (filter, "vendorid", data.mVendorId.string());
     605            filter.setValue <Bstr> ("vendorid", data.mVendorId.string());
    614606        if (data.mProductId.string())
    615             CFGLDRSetBSTR (filter, "productid", data.mProductId.string());
     607            filter.setValue <Bstr> ("productid", data.mProductId.string());
    616608        if (data.mRevision.string())
    617             CFGLDRSetBSTR (filter, "revision", data.mRevision.string());
     609            filter.setValue <Bstr> ("revision", data.mRevision.string());
    618610        if (data.mManufacturer.string())
    619             CFGLDRSetBSTR (filter, "manufacturer", data.mManufacturer.string());
     611            filter.setValue <Bstr> ("manufacturer", data.mManufacturer.string());
    620612        if (data.mProduct.string())
    621             CFGLDRSetBSTR (filter, "product", data.mProduct.string());
     613            filter.setValue <Bstr> ("product", data.mProduct.string());
    622614        if (data.mSerialNumber.string())
    623             CFGLDRSetBSTR (filter, "serialnumber", data.mSerialNumber.string());
     615            filter.setValue <Bstr> ("serialnumber", data.mSerialNumber.string());
    624616        if (data.mPort.string())
    625             CFGLDRSetBSTR (filter, "port", data.mPort.string());
     617            filter.setValue <Bstr> ("port", data.mPort.string());
    626618        if (data.mRemote.string())
    627             CFGLDRSetBSTR (filter, "remote", data.mRemote.string());
     619            filter.setValue <Bstr> ("remote", data.mRemote.string());
    628620
    629621#else  /* VBOX_WITH_USBFILTER */
     622
    630623        Bstr str;
    631624        (*it)->COMGETTER (VendorId) (str.asOutParam());
    632625        if (!str.isNull())
    633             CFGLDRSetBSTR (filter, "vendorid", str);
     626            filter.setValue <Bstr> ("vendorid", str);
    634627
    635628        (*it)->COMGETTER (ProductId) (str.asOutParam());
    636629        if (!str.isNull())
    637             CFGLDRSetBSTR (filter, "productid", str);
     630            filter.setValue <Bstr> ("productid", str);
    638631
    639632        (*it)->COMGETTER (Revision) (str.asOutParam());
    640633        if (!str.isNull())
    641             CFGLDRSetBSTR (filter, "revision", str);
     634            filter.setValue <Bstr> ("revision", str);
    642635
    643636        (*it)->COMGETTER (Manufacturer) (str.asOutParam());
    644637        if (!str.isNull())
    645             CFGLDRSetBSTR (filter, "manufacturer", str);
     638            filter.setValue <Bstr> ("manufacturer", str);
    646639
    647640        (*it)->COMGETTER (Product) (str.asOutParam());
    648641        if (!str.isNull())
    649             CFGLDRSetBSTR (filter, "product", str);
     642            filter.setValue <Bstr> ("product", str);
    650643
    651644        (*it)->COMGETTER (SerialNumber) (str.asOutParam());
    652645        if (!str.isNull())
    653             CFGLDRSetBSTR (filter, "serialnumber", str);
     646            filter.setValue <Bstr> ("serialnumber", str);
    654647
    655648        (*it)->COMGETTER (Port) (str.asOutParam());
    656649        if (!str.isNull())
    657             CFGLDRSetBSTR (filter, "port", str);
     650            filter.setValue <Bstr> ("port", str);
    658651
    659652        if (data.mRemote.string())
    660             CFGLDRSetBSTR (filter, "remote", data.mRemote.string());
     653            filter.setValue <Bstr> ("remote", data.mRemote.string());
     654
    661655#endif /* VBOX_WITH_USBFILTER */
    662656
    663657        if (data.mMaskedIfs)
    664             CFGLDRSetUInt32 (filter, "maskedInterfaces", data.mMaskedIfs);
    665 
    666         CFGLDRReleaseNode (filter);
     658            filter.setValue <ULONG> ("maskedInterfaces", data.mMaskedIfs);
    667659
    668660        ++ it;
    669661    }
    670 
    671     CFGLDRReleaseNode (controller);
    672662
    673663    return S_OK;
  • trunk/src/VBox/Main/VBoxDll.cpp

    r5999 r6076  
    2121*******************************************************************************/
    2222#include <iprt/assert.h>
    23 #undef CFGLDR_HAVE_COM
    24 #include <VBox/cfgldr.h>
    2523
    2624void __reference_stuff(void);
  • trunk/src/VBox/Main/VirtualBoxBase.cpp

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    930932}
    931933
     934#if defined VBOX_MAIN_SETTINGS_ADDONS
     935
     936// Settings API additions
     937////////////////////////////////////////////////////////////////////////////////
     938
     939namespace settings
     940{
     941
     942template<> stdx::char_auto_ptr
     943ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra)
     944{
     945    stdx::char_auto_ptr result;
     946
     947    if (aValue.raw() == NULL)
     948        throw ENoValue();
     949
     950    /* The only way to cause RTUtf16ToUtf8Ex return a number of bytes needed
     951     * w/o allocating the result buffer itself is to provide that both cch
     952     * and *ppsz are not NULL. */
     953    char dummy [1];
     954    char *dummy2 = dummy;
     955    size_t strLen = 1;
     956
     957    int vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX,
     958                               &dummy2, strLen, &strLen);
     959    if (RT_SUCCESS (vrc))
     960    {
     961        /* the string only contains '\0' :) */
     962        result.reset (new char [1]);
     963        result.get() [0] = '\0';
     964        return result;
     965    }
     966
     967    if (vrc == VERR_BUFFER_OVERFLOW)
     968    {
     969        result.reset (new char [strLen + 1]);
     970        char *buf = result.get();
     971        vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX, &buf, strLen + 1, NULL);
     972    }
     973
     974    if (RT_FAILURE (vrc))
     975        throw LogicError (RT_SRC_POS);
     976
     977    return result;
     978}
     979
     980template<> com::Guid FromString <com::Guid> (const char *aValue)
     981{
     982    if (aValue == NULL)
     983        throw ENoValue();
     984
     985    /* For settings, the format is always {XXX...XXX} */
     986    char buf [RTUUID_STR_LENGTH];
     987    if (aValue == NULL || *aValue != '{' ||
     988        strlen (aValue) != RTUUID_STR_LENGTH + 1 ||
     989        aValue [RTUUID_STR_LENGTH] != '}')
     990        throw ENoConversion (FmtStr ("'%s' is not Guid", aValue));
     991
     992    /* strip { and } */
     993    memcpy (buf, aValue + 1, RTUUID_STR_LENGTH - 1);
     994    buf [RTUUID_STR_LENGTH - 1] = '\0';
     995    /* we don't use Guid (const char *) because we want to throw
     996     * ENoConversion on format error */
     997    RTUUID uuid;
     998    int vrc = RTUuidFromStr (&uuid, buf);
     999    if (RT_FAILURE (vrc))
     1000        throw ENoConversion (FmtStr ("'%s' is not Guid (%Vrc)", aValue, vrc));
     1001       
     1002    return com::Guid (uuid);
     1003}
     1004
     1005template<> stdx::char_auto_ptr
     1006ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra)
     1007{
     1008    /* For settings, the format is always {XXX...XXX} */
     1009    stdx::char_auto_ptr result (new char [RTUUID_STR_LENGTH + 2]);
     1010
     1011    int vrc = RTUuidToStr (aValue.raw(), result.get() + 1, RTUUID_STR_LENGTH);
     1012    if (RT_FAILURE (vrc))
     1013        throw LogicError (RT_SRC_POS);
     1014
     1015    result.get() [0] = '{';
     1016    result.get() [RTUUID_STR_LENGTH] = '}';
     1017    result.get() [RTUUID_STR_LENGTH + 1] = '\0';
     1018
     1019    return result;
     1020}
     1021
     1022} /* namespace settings */
     1023
     1024#endif /* VBOX_MAIN_SETTINGS_ADDONS */
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r5999 r6076  
    2626#include "USBControllerImpl.h"
    2727#include "SystemPropertiesImpl.h"
     28#include "GuestOSTypeImpl.h"
     29
     30#include "VirtualBoxXMLUtil.h"
     31
    2832#include "Logging.h"
    29 
    30 #include "GuestOSTypeImpl.h"
    3133
    3234#ifdef RT_OS_WINDOWS
     
    5961#include <set>
    6062#include <memory> // for auto_ptr
     63
     64#include <typeinfo>
    6165
    6266// defines
     
    187191    }
    188192
    189     /* initialize our Xerces XML subsystem */
    190193    if (SUCCEEDED (rc))
    191194    {
    192         int vrc = CFGLDRInitialize();
    193         if (VBOX_FAILURE (vrc))
    194             rc = setError (E_FAIL, tr ("Could not initialize the XML parser (%Vrc)"),
    195                                    vrc);
    196     }
    197 
    198     if (SUCCEEDED (rc))
    199     {
    200         CFGHANDLE configLoader = NULL;
    201         char *loaderError = NULL;
    202 
    203         /* load the config file */
    204         int vrc = CFGLDRLoad (&configLoader, vboxConfigFile, mData.mCfgFile.mHandle,
    205                               XmlSchemaNS, true, cfgLdrEntityResolver,
    206                               &loaderError);
    207         if (VBOX_SUCCESS (vrc))
    208         {
    209             CFGNODE global = NULL;
    210             CFGLDRGetNode (configLoader, "VirtualBox/Global", 0, &global);
    211             Assert (global);
    212 
    213             do
    214             {
    215                 /* create the host object early, machines will need it */
    216                 unconst (mData.mHost).createObject();
    217                 rc = mData.mHost->init (this);
    218                 ComAssertComRCBreak (rc, rc = rc);
    219 
    220                 unconst (mData.mSystemProperties).createObject();
    221                 rc = mData.mSystemProperties->init (this);
    222                 ComAssertComRCBreak (rc, rc = rc);
    223 
    224                 rc = loadDisks (global);
    225                 CheckComRCBreakRC ((rc));
    226 
    227                 /* guest OS type objects, needed by the machines */
    228                 rc = registerGuestOSTypes();
    229                 ComAssertComRCBreak (rc, rc = rc);
    230 
    231                 /* machines */
    232                 rc = loadMachines (global);
    233                 CheckComRCBreakRC ((rc));
    234 
    235                 /* host data (USB filters) */
    236                 rc = mData.mHost->loadSettings (global);
    237                 CheckComRCBreakRC ((rc));
    238 
    239                 rc = mData.mSystemProperties->loadSettings (global);
    240                 CheckComRCBreakRC ((rc));
    241 
    242                 /* check hard disk consistency */
     195        try
     196        {
     197            using namespace settings;
     198
     199            File file (File::ReadWrite, mData.mCfgFile.mHandle, vboxConfigFile);
     200            XmlTreeBackend tree;
     201
     202            rc = VirtualBox::loadSettingsTree_FirstTime (tree, file);
     203            CheckComRCThrowRC (rc);
     204
     205            Key global = tree.rootKey().key ("Global");
     206
     207            /* create the host object early, machines will need it */
     208            unconst (mData.mHost).createObject();
     209            rc = mData.mHost->init (this);
     210            ComAssertComRCThrowRC (rc);
     211
     212            rc = mData.mHost->loadSettings (global);
     213            CheckComRCThrowRC (rc);
     214
     215            /* create the system properties object */
     216            unconst (mData.mSystemProperties).createObject();
     217            rc = mData.mSystemProperties->init (this);
     218            ComAssertComRCThrowRC (rc);
     219
     220            rc = mData.mSystemProperties->loadSettings (global);
     221            CheckComRCThrowRC (rc);
     222
     223            /* guest OS type objects, needed by machines */
     224            rc = registerGuestOSTypes();
     225            ComAssertComRCThrowRC (rc);
     226
     227            /* hard disks, needed by machines */
     228            rc = loadDisks (global);
     229            CheckComRCThrowRC (rc);
     230
     231            /* machines */
     232            rc = loadMachines (global);
     233            CheckComRCThrowRC (rc);
     234
     235            /* check hard disk consistency */
    243236/// @todo (r=dmik) add IVirtualBox::cleanupHardDisks() instead or similar
    244 //                for (HardDiskList::const_iterator it = mData.mHardDisks.begin();
    245 //                     it != mData.mHardDisks.end() && SUCCEEDED (rc);
    246 //                     ++ it)
    247 //                {
    248 //                    rc = (*it)->checkConsistency();
    249 //                }
    250 //                CheckComRCBreakRC ((rc));
    251             }
    252             while (0);
     237//            for (HardDiskList::const_iterator it = mData.mHardDisks.begin();
     238//                 it != mData.mHardDisks.end() && SUCCEEDED (rc);
     239//                 ++ it)
     240//            {
     241//                rc = (*it)->checkConsistency();
     242//            }
     243//            CheckComRCBreakRC ((rc));
    253244
    254245            /// @todo (dmik) if successful, check for orphan (unused) diffs
    255             //  that might be left because of the server crash, and remove them.
    256 
    257             CFGLDRReleaseNode (global);
    258             CFGLDRFree(configLoader);
    259         }
    260         else
    261         {
    262             rc = setError (E_FAIL,
    263                 tr ("Could not load the settings file '%ls' (%Vrc)%s%s"),
    264                 mData.mCfgFile.mName.raw(), vrc,
    265                 loaderError ? ".\n" : "", loaderError ? loaderError : "");
    266         }
    267 
    268         if (loaderError)
    269             RTMemTmpFree (loaderError);
     246            //  that might be left because of the server crash, and remove
     247            //  Hmm, is it the same remark as above?..
     248        }
     249        catch (HRESULT err)
     250        {
     251            /* we assume that error info is set by the thrower */
     252            rc = err;
     253        }
     254        catch (...)
     255        {
     256            rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     257        }
    270258    }
    271259
     
    436424#endif
    437425
    438     /* uninitialize the Xerces XML subsystem */
    439     CFGLDRShutdown();
    440 
    441426    LogFlowThisFuncLeave();
    442427    LogFlow (("===========================================================\n"));
     
    914899
    915900    /* save the global registry */
    916     rc = saveConfig();
     901    rc = saveSettings();
    917902
    918903    /* return the unregistered machine to the caller */
     
    13651350
    13661351        /* save the global config file */
    1367         rc = saveConfig();
     1352        rc = saveSettings();
    13681353
    13691354        if (SUCCEEDED (rc))
     
    15341519
    15351520        /* save the global config file */
    1536         rc = saveConfig();
     1521        rc = saveSettings();
    15371522        if (SUCCEEDED (rc))
    15381523        {
     
    16041589}
    16051590
    1606 /** @note Locks this object for reading. */
     1591/**
     1592 *  @note Locks this object for reading.
     1593 */
    16071594STDMETHODIMP VirtualBox::
    16081595GetNextExtraDataKey (INPTR BSTR aKey, BSTR *aNextKey, BSTR *aNextValue)
     
    16161603    /* start with nothing found */
    16171604    *aNextKey = NULL;
     1605    if (aNextValue)
     1606        *aNextValue = NULL;
    16181607
    16191608    HRESULT rc = S_OK;
    16201609
    1621     /* serialize file access */
     1610    /* serialize config file access */
    16221611    AutoReaderLock alock (this);
    16231612
    1624     CFGHANDLE configLoader;
    1625 
    1626     /* load the config file */
    1627     int vrc = CFGLDRLoad (&configLoader, Utf8Str (mData.mCfgFile.mName),
    1628                           mData.mCfgFile.mHandle,
    1629                           XmlSchemaNS, true, cfgLdrEntityResolver, NULL);
    1630     ComAssertRCRet (vrc, E_FAIL);
    1631 
    1632     CFGNODE extraDataNode;
    1633 
    1634     /* navigate to the right position */
    1635     if (VBOX_SUCCESS (CFGLDRGetNode (configLoader,
    1636                                      "VirtualBox/Global/ExtraData", 0,
    1637                                      &extraDataNode)))
    1638     {
    1639         /* check if it exists */
    1640         bool found = false;
    1641         unsigned count;
    1642         CFGNODE extraDataItemNode;
    1643         CFGLDRCountChildren (extraDataNode, "ExtraDataItem", &count);
    1644         for (unsigned i = 0; (i < count) && (found == false); i++)
    1645         {
    1646             Bstr name;
    1647             CFGLDRGetChildNode (extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    1648             CFGLDRQueryBSTR (extraDataItemNode, "name", name.asOutParam());
    1649 
    1650             /* if we're supposed to return the first one */
    1651             if (aKey == NULL)
     1613    try
     1614    {
     1615        using namespace settings;
     1616
     1617        /* load the config file */
     1618        File file (File::ReadWrite, mData.mCfgFile.mHandle,
     1619                   Utf8Str (mData.mCfgFile.mName));
     1620        XmlTreeBackend tree;
     1621
     1622        rc = VirtualBox::loadSettingsTree_Again (tree, file);
     1623        CheckComRCReturnRC (rc);
     1624
     1625        Key globalNode = tree.rootKey().key ("Global");
     1626        Key extraDataNode = tree.rootKey().findKey ("ExtraData");
     1627
     1628        if (!extraDataNode.isNull())
     1629        {
     1630            Key::List items = extraDataNode.keys ("ExtraDataItem");
     1631            if (items.size())
    16521632            {
    1653                 name.cloneTo (aNextKey);
    1654                 if (aNextValue)
    1655                     CFGLDRQueryBSTR (extraDataItemNode, "value", aNextValue);
    1656                 found = true;
    1657             }
    1658             /* did we find the key we're looking for? */
    1659             else if (name == aKey)
    1660             {
    1661                 found = true;
    1662                 /* is there another item? */
    1663                 if (i + 1 < count)
     1633                for (Key::List::const_iterator it = items.begin();
     1634                     it != items.end(); ++ it)
    16641635                {
    1665                     CFGLDRGetChildNode (extraDataNode, "ExtraDataItem", i + 1,
    1666                                         &extraDataItemNode);
    1667                     CFGLDRQueryBSTR (extraDataItemNode, "name", name.asOutParam());
    1668                     name.cloneTo (aNextKey);
    1669                     if (aNextValue)
    1670                         CFGLDRQueryBSTR (extraDataItemNode, "value", aNextValue);
    1671                     found = true;
    1672                 }
    1673                 else
    1674                 {
    1675                     /* it's the last one */
    1676                     *aNextKey = NULL;
     1636                    Bstr key = (*it).stringValue ("name");
     1637
     1638                    /* if we're supposed to return the first one */
     1639                    if (aKey == NULL)
     1640                    {
     1641                        key.cloneTo (aNextKey);
     1642                        if (aNextValue)
     1643                        {
     1644                            Bstr val = (*it).stringValue ("value");
     1645                            val.cloneTo (aNextValue);
     1646                        }
     1647                        return S_OK;
     1648                    }
     1649
     1650                    /* did we find the key we're looking for? */
     1651                    if (key == aKey)
     1652                    {
     1653                        ++ it;
     1654                        /* is there another item? */
     1655                        if (it != items.end())
     1656                        {
     1657                            Bstr key = (*it).stringValue ("name");
     1658                            key.cloneTo (aNextKey);
     1659                            if (aNextValue)
     1660                            {
     1661                                Bstr val = (*it).stringValue ("value");
     1662                                val.cloneTo (aNextValue);
     1663                            }
     1664                        }
     1665                        /* else it's the last one, arguments are already NULL */
     1666                        return S_OK;
     1667                    }
    16771668                }
    16781669            }
    1679             CFGLDRReleaseNode (extraDataItemNode);
    1680         }
    1681 
    1682         /* if we haven't found the key, it's an error */
    1683         if (!found)
    1684             rc = setError (E_FAIL,
    1685                 tr ("Could not find extra data key '%ls'"), aKey);
    1686 
    1687         CFGLDRReleaseNode (extraDataNode);
    1688     }
    1689 
    1690     CFGLDRFree (configLoader);
    1691 
    1692     return rc;
    1693 }
    1694 
    1695 /** @note Locks this object for reading. */
     1670        }
     1671
     1672        /* Here we are when a) there are no items at all or b) there are items
     1673         * but none of them equals to the requested non-NULL key. b) is an
     1674         * error as well as a) if the key is non-NULL. When the key is NULL
     1675         * (which is the case only when there are no items), we just fall
     1676         * through to return NULLs and S_OK. */
     1677
     1678        if (aKey != NULL)
     1679            return setError (E_FAIL,
     1680                tr ("Could not find the extra data key '%ls'"), aKey);
     1681    }
     1682    catch (...)
     1683    {
     1684        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     1685    }
     1686
     1687    return rc;
     1688}
     1689
     1690/**
     1691 *  @note Locks this object for reading.
     1692 */
    16961693STDMETHODIMP VirtualBox::GetExtraData (INPTR BSTR aKey, BSTR *aValue)
    16971694{
    1698     if (!aKey || !(*aKey))
     1695    if (!aKey)
    16991696        return E_INVALIDARG;
    17001697    if (!aValue)
     
    17121709    AutoReaderLock alock (this);
    17131710
    1714     CFGHANDLE configLoader;
    1715 
    1716     /* load the config file */
    1717     int vrc = CFGLDRLoad (&configLoader, Utf8Str (mData.mCfgFile.mName),
    1718                           mData.mCfgFile.mHandle,
    1719                           XmlSchemaNS, true, cfgLdrEntityResolver, NULL);
    1720     ComAssertRCRet (vrc, E_FAIL);
    1721 
    1722     CFGNODE extraDataNode;
    1723 
    1724     /* navigate to the right position */
    1725     if (VBOX_SUCCESS (CFGLDRGetNode (configLoader,
    1726                                      "VirtualBox/Global/ExtraData", 0,
    1727                                      &extraDataNode)))
    1728     {
    1729         /* check if it exists */
    1730         bool found = false;
    1731         unsigned count;
    1732         CFGNODE extraDataItemNode;
    1733         CFGLDRCountChildren (extraDataNode, "ExtraDataItem", &count);
    1734         for (unsigned i = 0; (i < count) && (found == false); i++)
    1735         {
    1736             Bstr name;
    1737             CFGLDRGetChildNode (extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    1738             CFGLDRQueryBSTR (extraDataItemNode, "name", name.asOutParam());
    1739             if (name == aKey)
     1711    try
     1712    {
     1713        using namespace settings;
     1714
     1715        /* load the config file */
     1716        File file (File::ReadWrite, mData.mCfgFile.mHandle,
     1717                   Utf8Str (mData.mCfgFile.mName));
     1718        XmlTreeBackend tree;
     1719
     1720        rc = VirtualBox::loadSettingsTree_Again (tree, file);
     1721        CheckComRCReturnRC (rc);
     1722
     1723        const Utf8Str key = aKey;
     1724
     1725        Key globalNode = tree.rootKey().key ("Global");
     1726        Key extraDataNode = globalNode.findKey ("ExtraData");
     1727
     1728        if (!extraDataNode.isNull())
     1729        {
     1730            /* check if the key exists */
     1731            Key::List items = extraDataNode.keys ("ExtraDataItem");
     1732            for (Key::List::const_iterator it = items.begin();
     1733                 it != items.end(); ++ it)
    17401734            {
    1741                 found = true;
    1742                 CFGLDRQueryBSTR (extraDataItemNode, "value", aValue);
     1735                if (key == (*it).stringValue ("name"))
     1736                {
     1737                    Bstr val = (*it).stringValue ("value");
     1738                    val.cloneTo (aValue);
     1739                    break;
     1740                }
    17431741            }
    1744             CFGLDRReleaseNode (extraDataItemNode);
    1745         }
    1746 
    1747         CFGLDRReleaseNode (extraDataNode);
    1748     }
    1749 
    1750     CFGLDRFree (configLoader);
    1751 
    1752     return rc;
    1753 }
    1754 
    1755 /** @note Locks this object for writing. */
    1756 STDMETHODIMP VirtualBox::SetExtraData(INPTR BSTR aKey, INPTR BSTR aValue)
     1742        }
     1743    }
     1744    catch (...)
     1745    {
     1746        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     1747    }
     1748
     1749    return rc;
     1750}
     1751
     1752/**
     1753 *  @note Locks this object for writing.
     1754 */
     1755STDMETHODIMP VirtualBox::SetExtraData (INPTR BSTR aKey, INPTR BSTR aValue)
    17571756{
    17581757    if (!aKey)
    1759         return E_POINTER;
     1758        return E_INVALIDARG;
    17601759
    17611760    AutoCaller autoCaller (this);
     
    17701769    AutoLock alock (this);
    17711770
    1772     CFGHANDLE configLoader;
    1773 
    1774     /* load the config file */
    1775     int vrc = CFGLDRLoad (&configLoader, Utf8Str (mData.mCfgFile.mName),
    1776                           mData.mCfgFile.mHandle,
    1777                           XmlSchemaNS, true, cfgLdrEntityResolver, NULL);
    1778     ComAssertRCRet (vrc, E_FAIL);
    1779 
    1780     CFGNODE extraDataNode = 0;
    1781 
    1782     vrc = CFGLDRGetNode (configLoader, "VirtualBox/Global/ExtraData", 0,
    1783                          &extraDataNode);
    1784     if (VBOX_FAILURE (vrc) && aValue)
    1785         vrc = CFGLDRCreateNode (configLoader, "VirtualBox/Global/ExtraData",
    1786                                 &extraDataNode);
    1787 
    1788     if (extraDataNode)
    1789     {
    1790         CFGNODE extraDataItemNode = 0;
     1771    try
     1772    {
     1773        using namespace settings;
     1774
     1775        /* load the config file */
     1776        File file (File::ReadWrite, mData.mCfgFile.mHandle,
     1777                   Utf8Str (mData.mCfgFile.mName));
     1778        XmlTreeBackend tree;
     1779
     1780        rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
     1781        CheckComRCReturnRC (rc);
     1782
     1783        const Utf8Str key = aKey;
    17911784        Bstr oldVal;
    17921785
    1793         unsigned count;
    1794         CFGLDRCountChildren (extraDataNode, "ExtraDataItem", &count);
    1795 
    1796         for (unsigned i = 0; i < count; i++)
    1797         {
    1798             CFGLDRGetChildNode (extraDataNode, "ExtraDataItem", i, &extraDataItemNode);
    1799             Bstr name;
    1800             CFGLDRQueryBSTR (extraDataItemNode, "name", name.asOutParam());
    1801             if (name == aKey)
     1786        Key globalNode = tree.rootKey().key ("Global");
     1787        Key extraDataNode = globalNode.createKey ("ExtraData");
     1788        Key extraDataItemNode;
     1789
     1790        Key::List items = extraDataNode.keys ("ExtraDataItem");
     1791        for (Key::List::const_iterator it = items.begin();
     1792             it != items.end(); ++ it)
     1793        {
     1794            if (key == (*it).stringValue ("name"))
    18021795            {
    1803                 CFGLDRQueryBSTR (extraDataItemNode, "value", oldVal.asOutParam());
     1796                extraDataItemNode = *it;
     1797                oldVal = (*it).stringValue ("value");
    18041798                break;
    18051799            }
    1806             CFGLDRReleaseNode (extraDataItemNode);
    1807             extraDataItemNode = 0;
    1808         }
    1809 
    1810         /*
    1811          *  When no key is found, oldVal is null. Note:
    1812          *  1. when oldVal is null, |oldVal == (BSTR) NULL| is true
    1813          *  2. we cannot do |oldVal != value| because it will compare
    1814          *  BSTR pointers instead of strings (due to type conversion ops)
    1815          */
    1816         changed = !(oldVal == aValue);
     1800        }
     1801
     1802        /* When no key is found, oldVal is null */
     1803        changed = oldVal != aValue;
    18171804
    18181805        if (changed)
     
    18201807            /* ask for permission from all listeners */
    18211808            Bstr error;
    1822             if (!onExtraDataCanChange (emptyGuid, aKey, aValue, error))
     1809            if (!onExtraDataCanChange (Guid::Empty, aKey, aValue, error))
    18231810            {
    18241811                const char *sep = error.isEmpty() ? "" : ": ";
     
    18261813                LogWarningFunc (("Someone vetoed! Change refused%s%ls\n",
    18271814                                 sep, err));
    1828                 rc = setError (E_ACCESSDENIED,
     1815                return setError (E_ACCESSDENIED,
    18291816                    tr ("Could not set extra data because someone refused "
    18301817                        "the requested change of '%ls' to '%ls'%s%ls"),
    18311818                    aKey, aValue, sep, err);
    18321819            }
     1820
     1821            if (aValue != NULL)
     1822            {
     1823                if (extraDataItemNode.isNull())
     1824                {
     1825                    extraDataItemNode = extraDataNode.appendKey ("ExtraDataItem");
     1826                    extraDataItemNode.setStringValue ("name", key);
     1827                }
     1828                extraDataItemNode.setStringValue ("value", Utf8Str (aValue));
     1829            }
    18331830            else
    18341831            {
    1835                 if (aValue)
    1836                 {
    1837                     if (!extraDataItemNode)
    1838                     {
    1839                         /* create a new item */
    1840                         CFGLDRAppendChildNode (extraDataNode, "ExtraDataItem",
    1841                                                &extraDataItemNode);
    1842                         CFGLDRSetBSTR (extraDataItemNode, "name", aKey);
    1843                     }
    1844                     CFGLDRSetBSTR (extraDataItemNode, "value", aValue);
    1845                 }
    1846                 else
    1847                 {
    1848                     /* an old value does for sure exist here */
    1849                     CFGLDRDeleteNode (extraDataItemNode);
    1850                     extraDataItemNode = 0;
    1851                 }
     1832                /* an old value does for sure exist here (XML schema
     1833                 * guarantees that "value" may not absent in the
     1834                 * <ExtraDataItem> element) */
     1835                Assert (!extraDataItemNode.isNull());
     1836                extraDataItemNode.zap();
    18521837            }
    1853         }
    1854 
    1855         if (extraDataItemNode)
    1856             CFGLDRReleaseNode (extraDataItemNode);
    1857 
    1858         CFGLDRReleaseNode (extraDataNode);
    1859 
    1860         if (SUCCEEDED (rc) && changed)
    1861         {
    1862             char *loaderError = NULL;
    1863             vrc = CFGLDRSave (configLoader, &loaderError);
    1864             if (VBOX_FAILURE (vrc))
    1865             {
    1866                 rc = setError (E_FAIL,
    1867                     tr ("Could not save the settings file '%ls' (%Vrc)%s%s"),
    1868                     mData.mCfgFile.mName.raw(), vrc,
    1869                     loaderError ? ".\n" : "", loaderError ? loaderError : "");
    1870                 if (loaderError)
    1871                     RTMemTmpFree (loaderError);
    1872             }
    1873         }
    1874     }
    1875 
    1876     CFGLDRFree (configLoader);
    1877 
    1878     /* notification handling */
     1838
     1839            /* save settings on success */
     1840            rc = VirtualBox::saveSettingsTree (tree, file);
     1841            CheckComRCReturnRC (rc);
     1842        }
     1843    }
     1844    catch (...)
     1845    {
     1846        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     1847    }
     1848
     1849    /* fire a notification */
    18791850    if (SUCCEEDED (rc) && changed)
    1880         onExtraDataChange (emptyGuid, aKey, aValue);
     1851        onExtraDataChange (Guid::Empty, aKey, aValue);
    18811852
    18821853    return rc;
     
    33983369 *  and creates the relevant objects.
    33993370 *
     3371 *  @param aGlobal  <Global> node.
     3372 *
    34003373 *  @note Can be called only from #init().
    34013374 *  @note Doesn't lock anything.
    34023375 */
    3403 HRESULT VirtualBox::loadMachines (CFGNODE aGlobal)
    3404 {
     3376HRESULT VirtualBox::loadMachines (const settings::Key &aGlobal)
     3377{
     3378    using namespace settings;
     3379
    34053380    AutoCaller autoCaller (this);
    34063381    AssertReturn (autoCaller.state() == InInit, E_FAIL);
    34073382
    34083383    HRESULT rc = S_OK;
    3409     CFGNODE machineRegistry = 0;
    3410     unsigned count = 0;
    3411 
    3412     CFGLDRGetChildNode (aGlobal, "MachineRegistry", 0, &machineRegistry);
    3413     Assert (machineRegistry);
    3414 
    3415     CFGLDRCountChildren(machineRegistry, "MachineEntry", &count);
    3416     for (unsigned i = 0; i < count && SUCCEEDED (rc); i++)
    3417     {
    3418         CFGNODE vm = 0;
    3419         CFGLDRGetChildNode(machineRegistry, "MachineEntry", i, &vm);
    3420         /* get the UUID */
    3421         Guid uuid;
    3422         CFGLDRQueryUUID(vm, "uuid", uuid.ptr());
    3423         /* get the machine configuration file name */
    3424         Bstr src;
    3425         CFGLDRQueryBSTR(vm, "src", src.asOutParam());
    3426 
    3427         /* create a new object */
     3384
     3385    Key::List machines = aGlobal.key ("MachineRegistry").keys ("MachineEntry");
     3386    for (Key::List::const_iterator it = machines.begin();
     3387         it != machines.end(); ++ it)
     3388    {
     3389        /* required */
     3390        Guid uuid = (*it).value <Guid> ("uuid");
     3391        /* required */
     3392        Bstr src = (*it).stringValue ("src");
     3393
     3394        /* create a new machine object */
    34283395        ComObjPtr <Machine> machine;
    34293396        rc = machine.createObject();
     
    34363403                rc = registerMachine (machine);
    34373404        }
    3438 
    3439         CFGLDRReleaseNode(vm);
    3440     }
    3441 
    3442     CFGLDRReleaseNode(machineRegistry);
     3405    }
    34433406
    34443407    return rc;
     
    34543417 *  @note Doesn't lock anything.
    34553418 */
    3456 HRESULT VirtualBox::loadDisks (CFGNODE aGlobal)
    3457 {
     3419HRESULT VirtualBox::loadDisks (const settings::Key &aGlobal)
     3420{
     3421    using namespace settings;
     3422
    34583423    AutoCaller autoCaller (this);
    34593424    AssertReturn (autoCaller.state() == InInit, E_FAIL);
    34603425
    34613426    HRESULT rc = S_OK;
    3462     CFGNODE registryNode = 0;
    3463 
    3464     CFGLDRGetChildNode (aGlobal, "DiskRegistry", 0, &registryNode);
    3465     ComAssertRet (registryNode, E_FAIL);
    3466 
    3467     const char *ImagesNodes[] = { "HardDisks", "DVDImages", "FloppyImages" };
    3468 
    3469     for (size_t node = 0; node < ELEMENTS (ImagesNodes) && SUCCEEDED (rc); node ++)
    3470     {
    3471         CFGNODE imagesNode = 0;
    3472         CFGLDRGetChildNode (registryNode, ImagesNodes [node], 0, &imagesNode);
    3473 
    3474         // all three nodes are optional
    3475         if (!imagesNode)
     3427
     3428    Key registry = aGlobal.key ("DiskRegistry");
     3429
     3430    const char *kMediaNodes[] = { "HardDisks", "DVDImages", "FloppyImages" };
     3431
     3432    for (size_t n = 0; n < ELEMENTS (kMediaNodes); ++ n)
     3433    {
     3434        /* All three media nodes are optional */
     3435        Key node = registry.findKey (kMediaNodes [n]);
     3436        if (node.isNull())
    34763437            continue;
    34773438
    3478         if (node == 0) // HardDisks node
    3479             rc = loadHardDisks (imagesNode);
    3480         else
    3481         {
    3482             unsigned count = 0;
    3483             CFGLDRCountChildren (imagesNode, "Image", &count);
    3484             for (unsigned i = 0; i < count && SUCCEEDED (rc); ++ i)
     3439        if (n == 0)
     3440        {
     3441            /* HardDisks node */
     3442            rc = loadHardDisks (node);
     3443            continue;
     3444        }
     3445
     3446        Key::List images = node.keys ("Image");
     3447        for (Key::List::const_iterator it = images.begin();
     3448             it != images.end(); ++ it)
     3449        {
     3450            /* required */
     3451            Guid uuid = (*it).value <Guid> ("uuid");
     3452            /* required */
     3453            Bstr src = (*it).stringValue ("src");
     3454
     3455            switch (n)
    34853456            {
    3486                 CFGNODE imageNode = 0;
    3487                 CFGLDRGetChildNode (imagesNode, "Image", i, &imageNode);
    3488                 ComAssertBreak (imageNode, rc = E_FAIL);
    3489 
    3490                 Guid uuid; // uuid (required)
    3491                 CFGLDRQueryUUID (imageNode, "uuid", uuid.ptr());
    3492                 Bstr src; // source (required)
    3493                 CFGLDRQueryBSTR (imageNode, "src", src.asOutParam());
    3494 
    3495                 switch (node)
     3457                case 1: /* DVDImages */
    34963458                {
    3497                     case 1: // DVDImages
    3498                     {
    3499                         ComObjPtr <DVDImage> dvdImage;
    3500                         dvdImage.createObject();
    3501                         rc = dvdImage->init (this, src, TRUE /* isRegistered */, uuid);
    3502                         if (SUCCEEDED (rc))
    3503                             rc = registerDVDImage (dvdImage, TRUE /* aOnStartUp */);
    3504 
    3505                         break;
    3506                     }
    3507                     case 2: // FloppyImages
    3508                     {
    3509                         ComObjPtr <FloppyImage> floppyImage;
    3510                         floppyImage.createObject();
    3511                         rc = floppyImage->init (this, src, TRUE /* isRegistered */, uuid);
    3512                         if (SUCCEEDED (rc))
    3513                             rc = registerFloppyImage (floppyImage, TRUE /* aOnStartUp */);
    3514 
    3515                         break;
    3516                     }
    3517                     default:
    3518                         AssertFailed();
     3459                    ComObjPtr <DVDImage> image;
     3460                    image.createObject();
     3461                    rc = image->init (this, src, TRUE /* isRegistered */, uuid);
     3462                    if (SUCCEEDED (rc))
     3463                        rc = registerDVDImage (image, TRUE /* aOnStartUp */);
     3464
     3465                    break;
    35193466                }
    3520 
    3521                 CFGLDRReleaseNode (imageNode);
     3467                case 2: /* FloppyImages */
     3468                {
     3469                    ComObjPtr <FloppyImage> image;
     3470                    image.createObject();
     3471                    rc = image->init (this, src, TRUE /* isRegistered */, uuid);
     3472                    if (SUCCEEDED (rc))
     3473                        rc = registerFloppyImage (image, TRUE /* aOnStartUp */);
     3474
     3475                    break;
     3476                }
     3477                default:
     3478                    AssertFailed();
    35223479            }
    3523         }
    3524 
    3525         CFGLDRReleaseNode (imagesNode);
    3526     }
    3527 
    3528     CFGLDRReleaseNode (registryNode);
     3480
     3481            CheckComRCBreakRC (rc);
     3482        }
     3483
     3484        CheckComRCBreakRC (rc);
     3485    }
    35293486
    35303487    return rc;
     
    35353492 *  Note that all loaded hard disks register themselves within this VirtualBox.
    35363493 *
    3537  *  @param aNode        <HardDisks> node
     3494 *  @param aNode        <HardDisks> node.
    35383495 *
    35393496 *  @note Can be called only from #init().
    35403497 *  @note Doesn't lock anything.
    35413498 */
    3542 HRESULT VirtualBox::loadHardDisks (CFGNODE aNode)
    3543 {
     3499HRESULT VirtualBox::loadHardDisks (const settings::Key &aNode)
     3500{
     3501    using namespace settings;
     3502
    35443503    AutoCaller autoCaller (this);
    35453504    AssertReturn (autoCaller.state() == InInit, E_FAIL);
    35463505
    3547     AssertReturn (aNode, E_INVALIDARG);
     3506    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    35483507
    35493508    HRESULT rc = S_OK;
    35503509
    3551     unsigned count = 0;
    3552     CFGLDRCountChildren (aNode, "HardDisk", &count);
    3553     for (unsigned i = 0; i < count && SUCCEEDED (rc); ++ i)
    3554     {
    3555         CFGNODE hdNode = 0;
    3556 
    3557         CFGLDRGetChildNode (aNode, "HardDisk", i, &hdNode);
    3558         ComAssertBreak (hdNode, rc = E_FAIL);
    3559 
    3560         {
    3561             CFGNODE storageNode = 0;
    3562 
    3563             // detect the type of the hard disk
    3564             // (either one of HVirtualDiskImage, HISCSIHardDisk or HPhysicalVolume
    3565             do
     3510    Key::List disks = aNode.keys ("HardDisk");
     3511    for (Key::List::const_iterator it = disks.begin();
     3512         it != disks.end(); ++ it)
     3513    {
     3514        Key storageNode;
     3515
     3516        /* detect the type of the hard disk (either one of VirtualDiskImage,
     3517         * ISCSIHardDisk, VMDKImage or HCustomHardDisk) */
     3518
     3519        do
     3520        {
     3521            storageNode = (*it).findKey ("VirtualDiskImage");
     3522            if (!storageNode.isNull())
    35663523            {
    3567                 CFGLDRGetChildNode (hdNode, "VirtualDiskImage", 0, &storageNode);
    3568                 if (storageNode)
    3569                 {
    3570                     ComObjPtr <HVirtualDiskImage> vdi;
    3571                     vdi.createObject();
    3572                     rc = vdi->init (this, NULL, hdNode, storageNode);
    3573                     break;
    3574                 }
    3575 
    3576                 CFGLDRGetChildNode (hdNode, "ISCSIHardDisk", 0, &storageNode);
    3577                 if (storageNode)
    3578                 {
    3579                     ComObjPtr <HISCSIHardDisk> iscsi;
    3580                     iscsi.createObject();
    3581                     rc = iscsi->init (this, hdNode, storageNode);
    3582                     break;
    3583                 }
    3584 
    3585                 CFGLDRGetChildNode (hdNode, "VMDKImage", 0, &storageNode);
    3586                 if (storageNode)
    3587                 {
    3588                     ComObjPtr <HVMDKImage> vmdk;
    3589                     vmdk.createObject();
    3590                     rc = vmdk->init (this, NULL, hdNode, storageNode);
    3591                     break;
    3592                 }
    3593                 CFGLDRGetChildNode (hdNode, "CustomHardDisk", 0, &storageNode);
    3594                 if (storageNode)
    3595                 {
    3596                     ComObjPtr <HCustomHardDisk> custom;
    3597                     custom.createObject();
    3598                     rc = custom->init (this, NULL, hdNode, storageNode);
    3599                     break;
    3600                 }
    3601 
    3602                 /// @todo (dmik) later
    3603 //                CFGLDRGetChildNode (hdNode, "PhysicalVolume", 0, &storageNode);
    3604 //                if (storageNode)
    3605 //                {
    3606 //                    break;
    3607 //                }
    3608 
    3609                 ComAssertMsgFailedBreak (("No valid hard disk storage node!\n"),
    3610                                          rc = E_FAIL);
     3524                ComObjPtr <HVirtualDiskImage> vdi;
     3525                vdi.createObject();
     3526                rc = vdi->init (this, NULL, (*it), storageNode);
     3527                break;
    36113528            }
    3612             while (0);
    3613 
    3614             if (storageNode)
    3615                 CFGLDRReleaseNode (storageNode);
    3616         }
    3617 
    3618         CFGLDRReleaseNode (hdNode);
    3619     }
    3620 
    3621     return rc;
    3622 }
    3623 
    3624 /**
    3625  *  Helper function to write out the configuration to XML.
    3626  *
    3627  *  @note Locks objects!
    3628  */
    3629 HRESULT VirtualBox::saveConfig()
     3529
     3530            storageNode = (*it).findKey ("ISCSIHardDisk");
     3531            if (!storageNode.isNull())
     3532            {
     3533                ComObjPtr <HISCSIHardDisk> iscsi;
     3534                iscsi.createObject();
     3535                rc = iscsi->init (this, (*it), storageNode);
     3536                break;
     3537            }
     3538
     3539            storageNode = (*it).findKey ("VMDKImage");
     3540            if (!storageNode.isNull())
     3541            {
     3542                ComObjPtr <HVMDKImage> vmdk;
     3543                vmdk.createObject();
     3544                rc = vmdk->init (this, NULL, (*it), storageNode);
     3545                break;
     3546            }
     3547
     3548            storageNode = (*it).findKey ("CustomHardDisk");
     3549            if (!storageNode.isNull())
     3550            {
     3551                ComObjPtr <HCustomHardDisk> custom;
     3552                custom.createObject();
     3553                rc = custom->init (this, NULL, (*it), storageNode);
     3554                break;
     3555            }
     3556
     3557            ComAssertMsgFailedBreak (("No valid hard disk storage node!\n"),
     3558                                     rc = E_FAIL);
     3559        }
     3560        while (0);
     3561    }
     3562
     3563    return rc;
     3564}
     3565
     3566/**
     3567 *  Helper function to write out the configuration tree.
     3568 *
     3569 *  @note Locks objects for reading!
     3570 */
     3571HRESULT VirtualBox::saveSettings()
    36303572{
    36313573    AutoCaller autoCaller (this);
    36323574    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    36333575
    3634     ComAssertRet (!!mData.mCfgFile.mName, E_FAIL);
     3576    AssertReturn (!!mData.mCfgFile.mName, E_FAIL);
    36353577
    36363578    HRESULT rc = S_OK;
    36373579
    3638     AutoLock alock (this);
    3639 
    3640     CFGHANDLE configLoader;
    3641 
    3642     /* load the config file */
    3643     int vrc = CFGLDRLoad (&configLoader, Utf8Str (mData.mCfgFile.mName),
    3644                           mData.mCfgFile.mHandle,
    3645                           XmlSchemaNS, true, cfgLdrEntityResolver, NULL);
    3646     ComAssertRCRet (vrc, E_FAIL);
    3647 
    3648     const char * Global = "VirtualBox/Global";
    3649     CFGNODE global;
    3650 
    3651     vrc = CFGLDRGetNode(configLoader, Global, 0, &global);
    3652     if (VBOX_FAILURE (vrc))
    3653         CFGLDRCreateNode (configLoader, Global, &global);
    3654 
    3655     do
    3656     {
    3657         ComAssertBreak (global, rc = E_FAIL);
     3580    AutoReaderLock alock (this);
     3581
     3582    try
     3583    {
     3584        using namespace settings;
     3585
     3586        File file (File::ReadWrite, mData.mCfgFile.mHandle,
     3587                   Utf8Str (mData.mCfgFile.mName));
     3588        XmlTreeBackend tree;
     3589
     3590        rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
     3591        CheckComRCThrowRC (rc);
     3592
     3593        Key global = tree.rootKey().createKey ("Global");
    36583594
    36593595        /* machines */
    3660         do
    3661         {
    3662             const char *Registry = "MachineRegistry";
    3663             const char *Entry = "MachineEntry";
    3664             CFGNODE registryNode = NULL;
    3665 
     3596        {
    36663597            /* first, delete the entire machine registry */
    3667             if (VBOX_SUCCESS (CFGLDRGetChildNode (global, Registry, 0, &registryNode)))
    3668                 CFGLDRDeleteNode (registryNode);
    3669 
     3598            Key registryNode = global.findKey ("MachineRegistry");
     3599            if (!registryNode.isNull())
     3600                registryNode.zap();
    36703601            /* then, recreate it */
    3671             CFGLDRCreateChildNode (global, Registry, &registryNode);
     3602            registryNode = global.createKey ("MachineRegistry");
    36723603
    36733604            /* write out the machines */
     
    36763607                 ++ it)
    36773608            {
    3678                 /// @todo (dmik) move this part to Machine for better incapsulation
    3679 
    3680                 CFGNODE entryNode = NULL;
    3681                 CFGLDRAppendChildNode (registryNode, Entry, &entryNode);
     3609                Key entryNode = registryNode.appendKey ("MachineEntry");
    36823610                rc = (*it)->saveRegistryEntry (entryNode);
    3683                 CFGLDRReleaseNode (entryNode);
    3684                 CheckComRCBreakRC (rc);
     3611                CheckComRCThrowRC (rc);
    36853612            }
    3686 
    3687             CFGLDRReleaseNode (registryNode);
    3688         }
    3689         while (0);
    3690         CheckComRCBreakRC (rc);
     3613        }
    36913614
    36923615        /* disk images */
    3693         do
    3694         {
    3695             CFGNODE registryNode = 0;
    3696             CFGLDRGetChildNode (global, "DiskRegistry", 0, &registryNode);
     3616        {
    36973617            /* first, delete the entire disk image registr */
    3698             if (registryNode)
    3699                 CFGLDRDeleteNode (registryNode);
     3618            Key registryNode = global.findKey ("DiskRegistry");
     3619            if (!registryNode.isNull())
     3620                registryNode.zap();
    37003621            /* then, recreate it */
    3701             CFGLDRCreateChildNode (global, "DiskRegistry", &registryNode);
    3702             ComAssertBreak (registryNode, rc = E_FAIL);
     3622            registryNode = global.createKey ("DiskRegistry");
    37033623
    37043624            /* write out the hard disks */
    37053625            {
    3706                 CFGNODE imagesNode = 0;
    3707                 CFGLDRCreateChildNode (registryNode, "HardDisks", &imagesNode);
     3626                Key imagesNode = registryNode.createKey ("HardDisks");
    37083627                rc = saveHardDisks (imagesNode);
    3709                 CFGLDRReleaseNode (imagesNode);
    3710                 CheckComRCBreakRC (rc);
     3628                CheckComRCThrowRC (rc);
    37113629            }
    37123630
    37133631            /* write out the CD/DVD images */
    37143632            {
    3715                 CFGNODE imagesNode = 0;
    3716                 CFGLDRCreateChildNode (registryNode, "DVDImages", &imagesNode);
     3633                Key imagesNode = registryNode.createKey ("DVDImages");
    37173634
    37183635                for (DVDImageList::iterator it = mData.mDVDImages.begin();
     
    37223639                    ComObjPtr <DVDImage> dvd = *it;
    37233640                    /* no need to lock: fields are constant */
    3724                     CFGNODE imageNode = 0;
    3725                     CFGLDRAppendChildNode (imagesNode, "Image", &imageNode);
    3726                     CFGLDRSetUUID (imageNode, "uuid", dvd->id());
    3727                     CFGLDRSetBSTR (imageNode, "src", dvd->filePath());
    3728                     CFGLDRReleaseNode (imageNode);
     3641                    Key imageNode = imagesNode.appendKey ("Image");
     3642                    imageNode.setValue <Guid> ("uuid", dvd->id());
     3643                    imageNode.setValue <Bstr> ("src", dvd->filePath());
    37293644                }
    3730 
    3731                 CFGLDRReleaseNode (imagesNode);
    37323645            }
    37333646
    37343647            /* write out the floppy images */
    37353648            {
    3736                 CFGNODE imagesNode = 0;
    3737                 CFGLDRCreateChildNode (registryNode, "FloppyImages", &imagesNode);
     3649                Key imagesNode = registryNode.createKey ("FloppyImages");
    37383650
    37393651                for (FloppyImageList::iterator it = mData.mFloppyImages.begin();
     
    37433655                    ComObjPtr <FloppyImage> fd = *it;
    37443656                    /* no need to lock: fields are constant */
    3745                     CFGNODE imageNode = 0;
    3746                     CFGLDRAppendChildNode (imagesNode, "Image", &imageNode);
    3747                     CFGLDRSetUUID (imageNode, "uuid", fd->id());
    3748                     CFGLDRSetBSTR (imageNode, "src", fd->filePath());
    3749                     CFGLDRReleaseNode (imageNode);
     3657                    Key imageNode = imagesNode.appendKey ("Image");
     3658                    imageNode.setValue <Guid> ("uuid", fd->id());
     3659                    imageNode.setValue <Bstr> ("src", fd->filePath());
    37503660                }
    3751 
    3752                 CFGLDRReleaseNode (imagesNode);
    37533661            }
    3754 
    3755             CFGLDRReleaseNode (registryNode);
    3756         }
    3757         while (0);
    3758         CheckComRCBreakRC (rc);
    3759 
    3760         do
    3761         {
    3762             /* host data (USB filters) */
    3763             rc = mData.mHost->saveSettings (global);
    3764             CheckComRCBreakRC (rc);
    3765 
    3766             rc = mData.mSystemProperties->saveSettings (global);
    3767             CheckComRCBreakRC (rc);
    3768         }
    3769         while (0);
    3770     }
    3771     while (0);
    3772 
    3773     if (global)
    3774         CFGLDRReleaseNode (global);
    3775 
    3776     if (SUCCEEDED (rc))
    3777     {
    3778         char *loaderError = NULL;
    3779         vrc = CFGLDRSave (configLoader, &loaderError);
    3780         if (VBOX_FAILURE (vrc))
    3781         {
    3782             rc = setError (E_FAIL,
    3783                 tr ("Could not save the settings file '%ls' (%Vrc)%s%s"),
    3784                 mData.mCfgFile.mName.raw(), vrc,
    3785                 loaderError ? ".\n" : "", loaderError ? loaderError : "");
    3786             if (loaderError)
    3787                 RTMemTmpFree (loaderError);
    3788         }
    3789     }
    3790 
    3791     CFGLDRFree(configLoader);
     3662        }
     3663
     3664        /* host data (USB filters) */
     3665        rc = mData.mHost->saveSettings (global);
     3666        CheckComRCThrowRC (rc);
     3667
     3668        rc = mData.mSystemProperties->saveSettings (global);
     3669        CheckComRCThrowRC (rc);
     3670
     3671        /* save the settings on success */
     3672        rc = VirtualBox::saveSettingsTree (tree, file);
     3673        CheckComRCThrowRC (rc);
     3674    }
     3675    catch (HRESULT err)
     3676    {
     3677        /* we assume that error info is set by the thrower */
     3678        rc = err;
     3679    }
     3680    catch (...)
     3681    {
     3682        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     3683    }
    37923684
    37933685    return rc;
     
    37973689 *  Saves all hard disks to the given <HardDisks> node.
    37983690 *
    3799  *  @param aNode        <HardDisks> node
     3691 *  @param aNode        <HardDisks> node.
    38003692 *
    38013693 *  @note Locks this object for reding.
    38023694 */
    3803 HRESULT VirtualBox::saveHardDisks (CFGNODE aNode)
    3804 {
    3805     AssertReturn (aNode, E_INVALIDARG);
     3695HRESULT VirtualBox::saveHardDisks (settings::Key &aNode)
     3696{
     3697    using namespace settings;
     3698
     3699    AssertReturn (!aNode.isNull(), E_INVALIDARG);
    38063700
    38073701    HRESULT rc = S_OK;
     
    38103704
    38113705    for (HardDiskList::const_iterator it = mData.mHardDisks.begin();
    3812          it != mData.mHardDisks.end() && SUCCEEDED (rc);
     3706         it != mData.mHardDisks.end();
    38133707         ++ it)
    38143708    {
     
    38163710        AutoReaderLock hdLock (hd);
    38173711
    3818         CFGNODE hdNode = 0;
    3819         CFGLDRAppendChildNode (aNode, "HardDisk", &hdNode);
    3820         ComAssertBreak (hdNode, rc = E_FAIL);
    3821 
    3822         CFGNODE storageNode = 0;
     3712        Key hdNode = aNode.appendKey ("HardDisk");
    38233713
    38243714        switch (hd->storageType())
     
    38263716            case HardDiskStorageType_VirtualDiskImage:
    38273717            {
    3828                 CFGLDRAppendChildNode (hdNode, "VirtualDiskImage", &storageNode);
    3829                 ComAssertBreak (storageNode, rc = E_FAIL);
     3718                Key storageNode = hdNode.createKey ("VirtualDiskImage");
    38303719                rc = hd->saveSettings (hdNode, storageNode);
    38313720                break;
     
    38343723            case HardDiskStorageType_ISCSIHardDisk:
    38353724            {
    3836                 CFGLDRAppendChildNode (hdNode, "ISCSIHardDisk", &storageNode);
    3837                 ComAssertBreak (storageNode, rc = E_FAIL);
     3725                Key storageNode = hdNode.createKey ("ISCSIHardDisk");
    38383726                rc = hd->saveSettings (hdNode, storageNode);
    38393727                break;
     
    38423730            case HardDiskStorageType_VMDKImage:
    38433731            {
    3844                 CFGLDRAppendChildNode (hdNode, "VMDKImage", &storageNode);
    3845                 ComAssertBreak (storageNode, rc = E_FAIL);
     3732                Key storageNode = hdNode.createKey ("VMDKImage");
    38463733                rc = hd->saveSettings (hdNode, storageNode);
    38473734                break;
     
    38493736            case HardDiskStorageType_CustomHardDisk:
    38503737            {
    3851                 CFGLDRAppendChildNode (hdNode, "CustomHardDisk", &storageNode);
    3852                 ComAssertBreak (storageNode, rc = E_FAIL);
     3738                Key storageNode = hdNode.createKey ("CustomHardDisk");
    38533739                rc = hd->saveSettings (hdNode, storageNode);
    38543740                break;
    38553741            }
    3856 
    3857             /// @todo (dmik) later
    3858 //            case HardDiskStorageType_PhysicalVolume:
    3859 //            {
    3860 //                break;
    3861 //            }
    3862         }
    3863 
    3864         if (storageNode)
    3865             CFGLDRReleaseNode (storageNode);
    3866 
    3867         CFGLDRReleaseNode (hdNode);
     3742        }
     3743
     3744        CheckComRCBreakRC (rc);
    38683745    }
    38693746
     
    39263803
    39273804    if (autoCaller.state() != InInit)
    3928         rc = saveConfig();
     3805        rc = saveSettings();
    39293806
    39303807    return rc;
     
    39713848    /// @todo (dmik) optimize later to save only the <HardDisks> node
    39723849    if (aFlags != RHD_OnStartUp)
    3973         rc = saveConfig();
     3850        rc = saveSettings();
    39743851
    39753852    return rc;
     
    40313908    /* save the global config file anyway (already unregistered) */
    40323909    /// @todo (dmik) optimize later to save only the <HardDisks> node
    4033     HRESULT rc2 = saveConfig();
     3910    HRESULT rc2 = saveSettings();
    40343911    if (SUCCEEDED (rc))
    40353912        rc = rc2;
     
    41544031    }
    41554032
    4156     HRESULT rc = saveConfig();
    4157 
    4158     return rc;
     4033    HRESULT rc = saveSettings();
     4034
     4035    return rc;
     4036}
     4037
     4038/**
     4039 * Helper method to load the setting tree and turn expected exceptions into
     4040 * COM errors, according to arguments.
     4041 *
     4042 * Note that this method will not catch unexpected errors so it may still
     4043 * throw something.
     4044 *
     4045 * @param aTree             Tree to load into settings.
     4046 * @param aFile             File to load settings from.
     4047 * @param aValidate         @c @true to enable tree validation.
     4048 * @param aCatchLoadErrors  @c true to catch exceptions caused by file
     4049 *                          access or validation errors.
     4050 * @param aAddDefaults      @c true to cause the substitution of default
     4051 *                          values for for missing attributes that have
     4052 *                          defaults in the XML schema.
     4053 */
     4054/* static */
     4055HRESULT VirtualBox::loadSettingsTree (settings::XmlTreeBackend &aTree,
     4056                                      settings::File &aFile,
     4057                                      bool aValidate,
     4058                                      bool aCatchLoadErrors,
     4059                                      bool aAddDefaults)
     4060{
     4061    using namespace settings;
     4062
     4063    try
     4064    {
     4065        SettingsInputResolver resolver = SettingsInputResolver();
     4066
     4067        aTree.setInputResolver (resolver);
     4068        aTree.read (aFile, aValidate ? VBOX_XML_SCHEMA : NULL,
     4069                    aAddDefaults ? XmlTreeBackend::Read_AddDefaults : 0);
     4070        aTree.resetInputResolver();
     4071    }
     4072    catch (const EIPRTFailure &err)
     4073    {
     4074        if (!aCatchLoadErrors)
     4075            throw;
     4076
     4077        return setError (E_FAIL,
     4078                         tr ("Could not load the settings file '%s' (%Vrc)"),
     4079                         aFile.uri(), err.rc());
     4080    }
     4081    catch (const XmlTreeBackend::Error &err)
     4082    {
     4083        Assert (err.what() != NULL);
     4084
     4085        if (!aCatchLoadErrors)
     4086            throw;
     4087
     4088        return setError (E_FAIL,
     4089                         tr ("Could not load the settings file '%s'.\n%s"),
     4090                         aFile.uri(),
     4091                         err.what() ? err.what() : "Unknown error");
     4092    }
     4093
     4094    return S_OK;
     4095}
     4096
     4097/**
     4098 * Helper method to save the settings tree and turn expected exceptions to COM
     4099 * errors.
     4100 *
     4101 * Note that this method will not catch unexpected errors so it may still
     4102 * throw something.
     4103 *
     4104 * @param aTree Tree to save.
     4105 * @param aFile File to save the tree to.
     4106 */
     4107/* static */
     4108HRESULT VirtualBox::saveSettingsTree (settings::TreeBackend &aTree,
     4109                                             settings::File &aFile)
     4110{
     4111    using namespace settings;
     4112
     4113    try
     4114    {
     4115        aTree.write (aFile);
     4116    }
     4117    catch (const EIPRTFailure &err)
     4118    {
     4119        /* this is the only expected exception for now */
     4120        return setError (E_FAIL,
     4121                         tr ("Could not save the settings file '%s' (%Vrc)"),
     4122                         aFile.uri(), err.rc());
     4123    }
     4124
     4125    return S_OK;
     4126}
     4127
     4128/**
     4129 * Handles unexpected exceptions by turning them into COM errors in release
     4130 * builds or by hitting a breakpoint in the release builds.
     4131 *
     4132 * Usage pattern:
     4133 * @code
     4134        try
     4135        {
     4136            // ...
     4137        }
     4138        catch (LaLalA)
     4139        {
     4140            // ...
     4141        }
     4142        catch (...)
     4143        {
     4144            rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     4145        }
     4146 * @endcode
     4147 *
     4148 * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation.
     4149 */
     4150/* static */
     4151HRESULT VirtualBox::handleUnexpectedExceptions (RT_SRC_POS_DECL)
     4152{
     4153    try
     4154    {
     4155        /* rethrow the current exception */
     4156        throw;
     4157    }
     4158    catch (const std::exception &err)
     4159    {
     4160        ComAssertMsgFailedPos (("Unexpected exception '%s' (%s)\n",
     4161                                typeid (err).name(), err.what()),
     4162                               pszFile, iLine, pszFunction);
     4163        return E_FAIL;
     4164    }
     4165    catch (...)
     4166    {
     4167        ComAssertMsgFailedPos (("Unknown exception\n"),
     4168                               pszFile, iLine, pszFunction);
     4169        return E_FAIL;
     4170    }
     4171
     4172    /* should not get here */
     4173    AssertFailed();
     4174    return E_FAIL;
    41594175}
    41604176
     
    41874203    /* save global config file if we're supposed to */
    41884204    if (!aOnStartUp)
    4189         rc = saveConfig();
     4205        rc = saveSettings();
    41904206
    41914207    return rc;
     
    42204236    /* save global config file if we're supposed to */
    42214237    if (!aOnStartUp)
    4222         rc = saveConfig();
     4238        rc = saveSettings();
    42234239
    42244240    return rc;
  • trunk/src/VBox/Main/glue/com.cpp

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 * MS COM / XPCOM Abstraction Layer
     
    4143#include "VBox/com/com.h"
    4244#include "VBox/com/assert.h"
     45
     46#include <VBox/com/Guid.h>
    4347
    4448
     
    182186}
    183187
     188/* static */
     189const Guid Guid::Empty; /* default ctor is OK */
     190
    184191} /* namespace com */
  • trunk/src/VBox/Main/glue/string.cpp

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    1921#include "VBox/com/string.h"
    2022
     23#include <iprt/err.h>
     24
    2125namespace com
    2226{
     27
     28/* static */
     29const Bstr Bstr::Null; /* default ctor is OK */
     30
     31/* static */
     32const Utf8Str Utf8Str::Null; /* default ctor is OK */
    2333
    2434struct FormatData
     
    8696
    8797} /* namespace com */
    88 
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r6056 r6076  
    15881588    <method name="getNextExtraDataKey">
    15891589      <desc>
    1590         Returns the extra data key name following the supplied key.
    1591         An error is returned if the supplied key does not exist.
    1592         @c NULL is returned if the supplied key is the last key.
    1593         When supplying @c NULL for the key, the first item is returned.
    1594         @a nextValue is an optional parameter and if supplied, the next
    1595         key's value is returned in it.
     1590        Returns the global extra data key name following the supplied key.
     1591
     1592        An error is returned if the supplied @a key does not exist. @c NULL is
     1593        returned in @a nextKey if the supplied key is the last key. When
     1594        supplying @c NULL for the @a key, the first key item is returned in @a
     1595        nextKey (if there is any). @a nextValue is an optional parameter and
     1596        if supplied, the next key's value is returned in it.
    15961597      </desc>
    15971598      <param name="key" type="wstring" dir="in">
     
    16081609    <method name="getExtraData">
    16091610      <desc>
    1610         Returns associated extra data.
    1611         If the reuqested key does not exist, this function will
    1612         succeed and return @c null in the @a value argument.
     1611        Returns associated global extra data.
     1612
     1613        If the reuqested data @a key does not exist, this function will
     1614        succeed and return @c NULL in the @a value argument.
    16131615      </desc>
    16141616      <param name="key" type="wstring" dir="in">
     
    16221624    <method name="setExtraData">
    16231625      <desc>
    1624         Sets associated extra data.
    1625         If you pass @c NULL as a key @a vaule, the given key will be
     1626        Sets associated global extra data.
     1627
     1628        If you pass @c NULL as a key @a vaule, the given @a key will be
    16261629        deleted.
    1627         <note>
    1628           This method can be called outside a machine session and
    1629           therefore it's a caller's responsibility to handle race
    1630           condition when several clients change the same key at the
    1631           same time.
     1630
     1631        <note>
     1632          Before performing the actual data change, this method will ask all
     1633          registered callbacks using the
     1634          <link to="IVirtualBoxCallback::onExtraDataCanChange()"/>
     1635          notification for a permission. If one of the callbacks refuses the
     1636          new value, the change will not be performed.
     1637        </note>
     1638        <note>
     1639          On success, the
     1640          <link to="IVirtualBoxCallback::onExtraDataChange()"/> notification
     1641          is called to inform all registered callbacks about a successful data
     1642          change.
    16321643        </note>
    16331644      </desc>
     
    28502861    <method name="getNextExtraDataKey">
    28512862      <desc>
    2852         Returns the extra data key name following the supplied key.
    2853         An error is returned if the supplied key does not exist.
    2854         NULL is returned if the supplied key is the last key.
    2855         When supplying NULL for the key, the first item is returned.
    2856         NextValue is an optional parameter and if supplied, the next
    2857         key's value is returned as well.
    2858       </desc>
    2859       <param name="key" type="wstring" dir="in"/>
    2860       <param name="nextKey" type="wstring" dir="out"/>
    2861       <param name="nextValue" type="wstring" dir="out"/>
     2863        Returns the machine-specific extra data key name following the
     2864        supplied key.
     2865
     2866        An error is returned if the supplied @a key does not exist. @c NULL is
     2867        returned in @a nextKey if the supplied key is the last key. When
     2868        supplying @c NULL for the @a key, the first key item is returned in @a
     2869        nextKey (if there is any). @a nextValue is an optional parameter and
     2870        if supplied, the next key's value is returned in it.
     2871      </desc>
     2872      <param name="key" type="wstring" dir="in">
     2873        <desc>Name of the data key to follow.</desc>
     2874      </param>
     2875      <param name="nextKey" type="wstring" dir="out">
     2876        <desc>Name of the next data key.</desc>
     2877      </param>
     2878      <param name="nextValue" type="wstring" dir="out">
     2879        <desc>Value of the next data key.</desc>
     2880      </param>
    28622881    </method>
    28632882
    28642883    <method name="getExtraData">
    2865       <desc>Returns associated extra data.</desc>
    2866       <param name="key" type="wstring" dir="in"/>
    2867       <param name="value" type="wstring" dir="return"/>
     2884      <desc>
     2885        Returns associated machine-specific extra data.
     2886
     2887        If the reuqested data @a key does not exist, this function will
     2888        succeed and return @c NULL in the @a value argument.
     2889      </desc>
     2890      <param name="key" type="wstring" dir="in">
     2891        <desc>Name of the data key to get.</desc>
     2892      </param>
     2893      <param name="value" type="wstring" dir="return">
     2894        <desc>Value of the requested data key.</desc>
     2895      </param>
    28682896    </method>
    28692897
    28702898    <method name="setExtraData">
    2871       <desc>Sets associated extra data.</desc>
    2872       <param name="key" type="wstring" dir="in"/>
    2873       <param name="value" type="wstring" dir="in"/>
     2899      <desc>
     2900        Sets associated machine-specific extra data.
     2901
     2902        If you pass @c NULL as a key @a vaule, the given @a key will be
     2903        deleted.
     2904
     2905        <note>
     2906          Before performing the actual data change, this method will ask all
     2907          registered callbacks using the
     2908          <link to="IVirtualBoxCallback::onExtraDataCanChange()"/>
     2909          notification for a permission. If one of the callbacks refuses the
     2910          new value, the change will not be performed.
     2911        </note>
     2912        <note>
     2913          On success, the
     2914          <link to="IVirtualBoxCallback::onExtraDataChange()"/> notification
     2915          is called to inform all registered callbacks about a successful data
     2916          change.
     2917        </note>
     2918        <note>
     2919          This method can be called outside the machine session and therefore
     2920          it's a caller's responsibility to handle possible race conditions
     2921          when several clients change the same key at the same time.
     2922        </note>
     2923      </desc>
     2924      <param name="key" type="wstring" dir="in">
     2925        <desc>Name of the data key to set.</desc>
     2926      </param>
     2927      <param name="value" type="wstring" dir="in">
     2928        <desc>Value to assign to the key.</desc>
     2929      </param>
    28742930    </method>
    28752931
  • trunk/src/VBox/Main/include/AudioAdapterImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    8082    // public methods only for internal purposes
    8183
     84    HRESULT loadSettings (const settings::Key &aMachineNode);
     85    HRESULT saveSettings (settings::Key &aMachineNode);
     86
    8287    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    8388    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
  • trunk/src/VBox/Main/include/BIOSSettingsImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    116118    // public methods only for internal purposes
    117119
     120    HRESULT loadSettings (const settings::Key &aMachineNode);
     121    HRESULT saveSettings (settings::Key &aMachineNode);
     122
    118123    const Backupable <Data> &data() const { return mData; }
    119124
  • trunk/src/VBox/Main/include/DVDDriveImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    9092    // public methods only for internal purposes
    9193
     94    HRESULT loadSettings (const settings::Key &aMachineNode);
     95    HRESULT saveSettings (settings::Key &aMachineNode);
     96
    9297    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    9398    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
  • trunk/src/VBox/Main/include/FloppyDriveImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    9193    // public methods only for internal purposes
    9294
     95    HRESULT loadSettings (const settings::Key &aMachineNode);
     96    HRESULT saveSettings (settings::Key &aMachineNode);
     97
    9398    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    9499    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
  • trunk/src/VBox/Main/include/HardDiskImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2224#include "Collection.h"
    2325
    24 #include <VBox/cfgldr.h>
    2526#include <VBox/VBoxHDD-new.h>
    2627
     
    134135    virtual HRESULT getAccessible (Bstr &aAccessError) = 0;
    135136
    136     virtual HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode) = 0;
     137    virtual HRESULT saveSettings (settings::Key &aHDNode, settings::Key &aStorageNode) = 0;
    137138
    138139    virtual void updatePath (const char *aOldPath, const char *aNewPath) {}
     
    180181protected:
    181182
    182     HRESULT loadSettings (CFGNODE aHDNode);
    183     HRESULT saveSettings (CFGNODE aHDNode);
     183    HRESULT loadSettings (const settings::Key &aHDNode);
     184    HRESULT saveSettings (settings::Key &aHDNode);
    184185
    185186    /** weak VirualBox parent */
     
    234235
    235236    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    236                   CFGNODE aHDNode, CFGNODE aVDINode);
     237                  const settings::Key &aHDNode, const settings::Key &aVDINode);
    237238    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    238239                  const BSTR aFilePath, BOOL aRegistered = FALSE);
     
    263264    HRESULT getAccessible (Bstr &aAccessError);
    264265
    265     HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode);
     266    HRESULT saveSettings (settings::Key &aHDNode, settings::Key &aStorageNode);
    266267
    267268    void updatePath (const char *aOldPath, const char *aNewPath);
     
    359360
    360361    HRESULT init (VirtualBox *aVirtualBox,
    361                   CFGNODE aHDNode, CFGNODE aISCSINode);
     362                  const settings::Key &aHDNode, const settings::Key &aISCSINode);
    362363    HRESULT init (VirtualBox *aVirtualBox);
    363364    void uninit();
     
    395396    HRESULT getAccessible (Bstr &aAccessError);
    396397
    397     HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode);
     398    HRESULT saveSettings (settings::Key &aHDNode, settings::Key &aStorageNode);
    398399
    399400    Bstr toString (bool aShort = false);
     
    456457
    457458    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    458                   CFGNODE aHDNode, CFGNODE aVMDKNode);
     459                  const settings::Key &aHDNode, const settings::Key &aVMDKNode);
    459460    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    460461                  INPTR BSTR aFilePath, BOOL aRegistered = FALSE);
     
    485486    HRESULT getAccessible (Bstr &aAccessError);
    486487
    487     HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode);
     488    HRESULT saveSettings (settings::Key &aHDNode, settings::Key &aStorageNode);
    488489
    489490    void updatePath (const char *aOldPath, const char *aNewPath);
     
    569570
    570571    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    571                   CFGNODE aHDNode, CFGNODE aCustomNode);
     572                  const settings::Key &aHDNode, const settings::Key &aCustomNode);
    572573    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
    573574                  INPTR BSTR aLocation, BOOL aRegistered = FALSE);
     
    598599    HRESULT getAccessible (Bstr &aAccessError);
    599600
    600     HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode);
     601    HRESULT saveSettings (settings::Key &aHDNode, settings::Key &aStorageNode);
    601602
    602603    Bstr toString (bool aShort = false);
  • trunk/src/VBox/Main/include/HostImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2628#include "win32/svchlp.h"
    2729#endif
    28 
    29 #include <VBox/cfgldr.h>
    3030
    3131class VirtualBox;
     
    9898                                     BOOL aActiveChanged = FALSE);
    9999
    100     HRESULT loadSettings (CFGNODE aGlobal);
    101     HRESULT saveSettings (CFGNODE aGlobal);
     100    HRESULT loadSettings (const settings::Key &aGlobal);
     101    HRESULT saveSettings (settings::Key &aGlobal);
    102102
    103103    HRESULT captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId);
  • trunk/src/VBox/Main/include/MachineImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2022
    2123#include "VirtualBoxBase.h"
    22 #include "VirtualBoxXMLUtil.h"
    2324#include "ProgressImpl.h"
    2425#include "SnapshotImpl.h"
     
    3839
    3940#include <VBox/types.h>
    40 #include <VBox/cfgldr.h>
     41
    4142#include <iprt/file.h>
    4243#include <iprt/thread.h>
     44#include <iprt/time.h>
    4345
    4446#include <list>
     
    6971class ATL_NO_VTABLE Machine :
    7072    public VirtualBoxBaseWithChildrenNEXT,
    71     public VirtualBoxXMLUtil,
    7273    public VirtualBoxSupportErrorInfoImpl <Machine, IMachine>,
    7374    public VirtualBoxSupportTranslation <Machine>,
     
    141142
    142143        MachineState_T mMachineState;
    143         LONG64 mLastStateChange;
     144        RTTIMESPEC mLastStateChange;
    144145
    145146        uint32_t mMachineStateDeps;
     
    557558    virtual HRESULT onSharedFolderChange() { return S_OK; }
    558559
    559     HRESULT saveRegistryEntry (CFGNODE aEntryNode);
     560    HRESULT saveRegistryEntry (settings::Key &aEntryNode);
    560561
    561562    int calculateFullPath (const char *aPath, Utf8Str &aResult);
     
    613614
    614615    HRESULT loadSettings (bool aRegistered);
    615     HRESULT loadSnapshot (CFGNODE aNode, const Guid &aCurSnapshotId,
     616    HRESULT loadSnapshot (const settings::Key &aNode, const Guid &aCurSnapshotId,
    616617                          Snapshot *aParentSnapshot);
    617     HRESULT loadHardware (CFGNODE aNode);
    618     HRESULT loadHardDisks (CFGNODE aNode, bool aRegistered,
     618    HRESULT loadHardware (const settings::Key &aNode);
     619    HRESULT loadHardDisks (const settings::Key &aNode, bool aRegistered,
    619620                           const Guid *aSnapshotId = NULL);
    620621
    621     HRESULT openConfigLoader (CFGHANDLE *aLoader, bool aIsNew = false);
    622     HRESULT closeConfigLoader (CFGHANDLE aLoader, bool aSaveBeforeClose);
    623 
    624     HRESULT findSnapshotNode (Snapshot *aSnapshot, CFGNODE aMachineNode,
    625                               CFGNODE *aSnapshotsNode, CFGNODE *aSnapshotNode);
     622    HRESULT findSnapshotNode (Snapshot *aSnapshot, settings::Key &aMachineNode,
     623                              settings::Key *aSnapshotsNode,
     624                              settings::Key *aSnapshotNode);
    626625
    627626    HRESULT findSnapshot (const Guid &aId, ComObjPtr <Snapshot> &aSnapshot,
     
    655654
    656655    HRESULT saveSnapshotSettings (Snapshot *aSnapshot, int aOpFlags);
    657     HRESULT saveSnapshotSettingsWorker (CFGNODE aMachineNode,
     656    HRESULT saveSnapshotSettingsWorker (settings::Key &aMachineNode,
    658657                                        Snapshot *aSnapshot, int aOpFlags);
    659658
    660     HRESULT saveSnapshot (CFGNODE aNode, Snapshot *aSnapshot, bool aAttrsOnly);
    661     HRESULT saveHardware (CFGNODE aNode);
    662     HRESULT saveHardDisks (CFGNODE aNode);
     659    HRESULT saveSnapshot (settings::Key &aNode, Snapshot *aSnapshot, bool aAttrsOnly);
     660    HRESULT saveHardware (settings::Key &aNode);
     661    HRESULT saveHardDisks (settings::Key &aNode);
    663662
    664663    HRESULT saveStateSettings (int aFlags);
     
    919918    HRESULT init (SessionMachine *aSessionMachine,
    920919                  INPTR GUIDPARAM aSnapshotId, INPTR BSTR aStateFilePath);
    921     HRESULT init (Machine *aMachine, CFGNODE aHWNode, CFGNODE aHDAsNode,
     920    HRESULT init (Machine *aMachine,
     921                  const settings::Key &aHWNode, const settings::Key &aHDAsNode,
    922922                  INPTR GUIDPARAM aSnapshotId, INPTR BSTR aStateFilePath);
    923923    void uninit();
  • trunk/src/VBox/Main/include/NetworkAdapterImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    146148    // public methods only for internal purposes
    147149
     150    HRESULT loadSettings (const settings::Key &aAdapterNode);
     151    HRESULT saveSettings (settings::Key &aAdapterNode);
     152
    148153    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    149154    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
  • trunk/src/VBox/Main/include/ParallelPortImpl.h

    r5999 r6076  
    11/* $Id$ */
     2
    23/** @file
    34 * VirtualBox COM class implementation.
     
    2021
    2122#include "VirtualBoxBase.h"
    22 
    23 #include <VBox/cfgldr.h>
    2423
    2524class Machine;
     
    9594
    9695    // public methods only for internal purposes
     96
     97    HRESULT loadSettings (const settings::Key &aPortNode);
     98    HRESULT saveSettings (settings::Key &aPortNode);
     99
    97100    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    98101    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
     
    103106    // public methods for internal purposes only
    104107    // (ensure there is a caller and a read lock before calling them!)
    105 
    106     HRESULT loadSettings (CFGNODE aMachine, ULONG aSlot);
    107     HRESULT saveSettings (CFGNODE aMachine);
    108108
    109109    // for VirtualBoxSupportErrorInfoImpl
  • trunk/src/VBox/Main/include/SerialPortImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2022
    2123#include "VirtualBoxBase.h"
    22 
    23 #include <VBox/cfgldr.h>
    2424
    2525class Machine;
     
    105105
    106106    // public methods only for internal purposes
     107
     108    HRESULT loadSettings (const settings::Key &aPortNode);
     109    HRESULT saveSettings (settings::Key &aPortNode);
     110
    107111    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
    108112    bool isReallyModified() { AutoLock alock (this); return mData.hasActualChanges(); }
     
    113117    // public methods for internal purposes only
    114118    // (ensure there is a caller and a read lock before calling them!)
    115 
    116     HRESULT loadSettings (CFGNODE aMachine, ULONG aSlot);
    117     HRESULT saveSettings (CFGNODE aMachine);
    118119
    119120    // for VirtualBoxSupportErrorInfoImpl
  • trunk/src/VBox/Main/include/SnapshotImpl.h

    r5999 r6076  
    2222#include "Collection.h"
    2323
     24#include <iprt/time.h>
     25
    2426#include <list>
    2527
     
    4244        Bstr mName;
    4345        Bstr mDescription;
    44         LONG64 mTimeStamp;
     46        RTTIMESPEC mTimeStamp;
    4547        ComObjPtr <SnapshotMachine> mMachine;
    4648    };
     
    6567    // public initializer/uninitializer only for internal purposes
    6668    HRESULT init (const Guid &aId, INPTR BSTR aName, INPTR BSTR aDescription,
    67                   LONG64 aTimeStamp, SnapshotMachine *aMachine,
     69                  RTTIMESPEC aTimeStamp, SnapshotMachine *aMachine,
    6870                  Snapshot *aParent);
    6971    void uninit();
  • trunk/src/VBox/Main/include/SystemPropertiesImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2022
    2123#include "VirtualBoxBase.h"
    22 
    23 #include <VBox/cfgldr.h>
    2424
    2525class VirtualBox;
     
    7777    // public methods only for internal purposes
    7878
    79     HRESULT loadSettings (CFGNODE aGlobal);
    80     HRESULT saveSettings (CFGNODE aGlobal);
     79    HRESULT loadSettings (const settings::Key &aGlobal);
     80    HRESULT saveSettings (settings::Key &aGlobal);
    8181
    8282    /** Default VDI path (as is, not full). Not thread safe (use object lock). */
  • trunk/src/VBox/Main/include/USBControllerImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2123#include "VirtualBoxBase.h"
    2224#include "USBDeviceFilterImpl.h"
    23 
    24 #include <VBox/cfgldr.h>
    2525
    2626#include <list>
     
    102102    // public methods only for internal purposes
    103103
    104     HRESULT loadSettings (CFGNODE aMachine);
    105     HRESULT saveSettings (CFGNODE aMachine);
     104    HRESULT loadSettings (const settings::Key &aMachineNode);
     105    HRESULT saveSettings (settings::Key &aMachineNode);
    106106
    107107    bool isModified();
  • trunk/src/VBox/Main/include/VRDPServerImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2224
    2325#include <VBox/VRDPAuth.h>
    24 #include <VBox/cfgldr.h>
    2526
    2627class Machine;
     
    9798    // public methods only for internal purposes
    9899
    99     HRESULT loadSettings (CFGNODE aNode);
    100     HRESULT saveSettings (CFGNODE aNode);
     100    HRESULT loadSettings (const settings::Key &aMachineNode);
     101    HRESULT saveSettings (settings::Key &aMachineNode);
    101102
    102103    bool isModified() { AutoLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/VirtualBoxBase.h

    r5999 r6076  
    2525
    2626#include "VBox/com/VirtualBox.h"
     27
     28#include <VBox/settings.h>
    2729
    2830#include "AutoLock.h"
     
    121123
    122124/**
    123  *  A special version of the Assert macro to be used within VirtualBoxBase
     125 *  Special version of the Assert macro to be used within VirtualBoxBase
    124126 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    125127 *
     
    145147
    146148/**
    147  *  A special version of the AssertMsg macro to be used within VirtualBoxBase
     149 *  Special version of the AssertMsg macro to be used within VirtualBoxBase
    148150 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    149151 *
     
    167169
    168170/**
    169  *  A special version of the AssertRC macro to be used within VirtualBoxBase
     171 *  Special version of the AssertRC macro to be used within VirtualBoxBase
    170172 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    171173 *
     
    181183
    182184/**
    183  *  A special version of the AssertMsgRC macro to be used within VirtualBoxBase
     185 *  Special version of the AssertMsgRC macro to be used within VirtualBoxBase
    184186 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    185187 *
     
    197199
    198200/**
    199  *  A special version of the AssertFailed macro to be used within VirtualBoxBase
     201 *  Special version of the AssertFailed macro to be used within VirtualBoxBase
    200202 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    201203 *
     
    214216
    215217/**
    216  *  A special version of the AssertMsgFailed macro to be used within VirtualBoxBase
     218 *  Special version of the AssertMsgFailed macro to be used within VirtualBoxBase
    217219 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    218220 *
     
    234236
    235237/**
    236  *  A special version of the AssertComRC macro to be used within VirtualBoxBase
     238 *  Special version of the ComAssertMsgFailed macro that additionally takes
     239 *  line number, file and function arguments to inject an assertion position
     240 *  that differs from the position where this macro is instantiated.
     241 *
     242 *  @param   a                  printf argument list (in parenthesis).
     243 *  @param   file, line, func   Line number (int), file and function (const char *).
     244 */
     245#if defined (DEBUG)
     246#define ComAssertMsgFailedPos(a, file, line, func)              \
     247    do {                                                        \
     248        AssertMsg1 ((const char *) 0, line, file, func);        \
     249        AssertMsg2 a;                                           \
     250        AssertBreakpoint();                                     \
     251    } while (0)
     252#else
     253#define ComAssertMsgFailedPos(a, file, line, func)              \
     254    do {                                                        \
     255        setError (E_FAIL,                                       \
     256                  "Assertion failed at '%s' (%d) in %s.\n"      \
     257                  "%s.\n"                                       \
     258                  "Please contact the product vendor!",         \
     259                  file, line, func, Utf8StrFmt a .raw());       \
     260    } while (0)
     261#endif
     262
     263/**
     264 *  Special version of the AssertComRC macro to be used within VirtualBoxBase
    237265 *  subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
    238266 *
     
    299327    if (1)  { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { break; } } else do {} while (0)
    300328
     329
     330/** Special version of ComAssert that evaulates eval and throws it if expr fails */
     331#define ComAssertThrow(expr, eval)                \
     332    if (1) { ComAssert (expr); if (!(expr)) { throw (eval); } } else do {} while (0)
     333/** Special version of ComAssertMsg that evaulates eval and throws it if expr fails */
     334#define ComAssertMsgThrow(expr, a, eval)          \
     335    if (1)  { ComAssertMsg (expr, a); if (!(expr)) { throw (eval); } } else do {} while (0)
     336/** Special version of ComAssertRC that evaulates eval and throws it if vrc does not succeed */
     337#define ComAssertRCThrow(vrc, eval)               \
     338    if (1)  { ComAssertRC (vrc); if (!VBOX_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
     339/** Special version of ComAssertMsgRC that evaulates eval and throws it if vrc does not succeed */
     340#define ComAssertMsgRCThrow(vrc, msg, eval)       \
     341    if (1)  { ComAssertMsgRC (vrc, msg); if (!VBOX_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
     342/** Special version of ComAssertFailed that evaulates eval and throws it */
     343#define ComAssertFailedThrow(eval)                \
     344    if (1)  { ComAssertFailed(); { throw (eval); } } else do {} while (0)
     345/** Special version of ComAssertMsgFailed that evaulates eval and throws it */
     346#define ComAssertMsgFailedThrow(msg, eval)        \
     347    if (1)  { ComAssertMsgFailed (msg); { throw (eval); } } else do {} while (0)
     348/** Special version of ComAssertComRC that evaulates eval and throws it if rc does not succeed */
     349#define ComAssertComRCThrow(rc, eval)             \
     350    if (1)  { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw (eval); } } else do {} while (0)
     351/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
     352#define ComAssertComRCThrowRC(rc)                 \
     353    if (1)  { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw rc; } } else do {} while (0)
     354
     355
    301356/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
    302357/**
     
    19241979};
    19251980
     1981#if defined VBOX_MAIN_SETTINGS_ADDONS
     1982
     1983/**
     1984 * Settinsg API additions.
     1985 */
     1986namespace settings
     1987{
     1988
     1989/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
     1990/// code below
     1991
     1992#if 0
     1993
     1994/** Specialization of FromString for Bstr. */
     1995template<> com::Bstr FromString <com::Bstr> (const char *aValue);
     1996
     1997#endif
     1998
     1999/** Specialization of ToString for Bstr. */
     2000template<> stdx::char_auto_ptr
     2001ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
     2002
     2003/** Specialization of FromString for Guid. */
     2004template<> com::Guid FromString <com::Guid> (const char *aValue);
     2005
     2006/** Specialization of ToString for Guid. */
     2007template<> stdx::char_auto_ptr
     2008ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
     2009
     2010} /* namespace settings */
     2011
     2012#endif /* VBOX_MAIN_SETTINGS_ADDONS */
     2013
    19262014#endif // ____H_VIRTUALBOXBASEIMPL
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
     
    2022
    2123#include "VirtualBoxBase.h"
    22 #include "VirtualBoxXMLUtil.h"
    2324
    2425#include "VBox/com/EventQueue.h"
    25 
    26 #include <VBox/cfgldr.h>
    2726
    2827#include <list>
     
    6059class ATL_NO_VTABLE VirtualBox :
    6160    public VirtualBoxBaseWithChildrenNEXT,
    62     public VirtualBoxXMLUtil,
    6361    public VirtualBoxSupportErrorInfoImpl <VirtualBox, IVirtualBox>,
    6462    public VirtualBoxSupportTranslation <VirtualBox>,
     
    253251    HRESULT unregisterDiffHardDisk (HardDisk *aHardDisk);
    254252
    255     HRESULT saveSettings() { return saveConfig(); }
     253    HRESULT saveSettings();
    256254    HRESULT updateSettings (const char *aOldPath, const char *aNewPath);
    257255
    258256    const Bstr &settingsFileName() { return mData.mCfgFile.mName; }
     257
     258    class SettingsInputResolver : public settings::XmlTreeBackend::InputResolver
     259    {
     260    public:
     261
     262        settings::Input *resolveEntity (const char *aURI, const char *aID);
     263    };
     264
     265    static HRESULT loadSettingsTree (settings::XmlTreeBackend &aTree,
     266                                     settings::File &aFile,
     267                                     bool aValidate,
     268                                     bool aCatchLoadErrors,
     269                                     bool aAddDefaults);
     270
     271    /**
     272     * Shortcut to loadSettingsTree (aTree, aFile, true, true, true).
     273     *
     274     * Used when the settings file is to be loaded for the first time for the
     275     * given object in order to recreate it from the stored settings.
     276     */
     277    static HRESULT loadSettingsTree_FirstTime (settings::XmlTreeBackend &aTree,
     278                                               settings::File &aFile)
     279    {
     280        return loadSettingsTree (aTree, aFile, true, true, true);
     281    }
     282
     283    /**
     284     * Shortcut to loadSettingsTree (aTree, aFile, true, false, true).
     285     *
     286     * Used when the settings file is loaded again (after it has been fully
     287     * checked and validated by #loadSettingsTree_FirstTime()) in order to
     288     * look at settings that don't have any representation within object's
     289     * data fields.
     290     */
     291    static HRESULT loadSettingsTree_Again (settings::XmlTreeBackend &aTree,
     292                                           settings::File &aFile)
     293    {
     294        return loadSettingsTree (aTree, aFile, true, false, true);
     295    }
     296
     297    /**
     298     * Shortcut to loadSettingsTree (aTree, aFile, true, false, false).
     299     *
     300     * Used when the settings file is loaded again (after it has been fully
     301     * checked and validated by #loadSettingsTree_FirstTime()) in order to
     302     * update some settings and then save them back.
     303     */
     304    static HRESULT loadSettingsTree_ForUpdate (settings::XmlTreeBackend &aTree,
     305                                               settings::File &aFile)
     306    {
     307        return loadSettingsTree (aTree, aFile, true, false, false);
     308    }
     309
     310    static HRESULT saveSettingsTree (settings::TreeBackend &aTree,
     311                                     settings::File &aFile);
     312
     313    static HRESULT handleUnexpectedExceptions (RT_SRC_POS_DECL);
    259314
    260315    /* for VirtualBoxSupportErrorInfoImpl */
     
    290345                                    const Guid *aId, const BSTR aFilePathFull);
    291346
    292     HRESULT loadMachines (CFGNODE aGlobal);
    293     HRESULT loadDisks (CFGNODE aGlobal);
    294     HRESULT loadHardDisks (CFGNODE aNode);
    295 
    296     HRESULT saveConfig();
    297     HRESULT saveHardDisks (CFGNODE aNode);
     347    HRESULT loadMachines (const settings::Key &aGlobal);
     348    HRESULT loadDisks (const settings::Key &aGlobal);
     349    HRESULT loadHardDisks (const settings::Key &aNode);
     350
     351    HRESULT saveHardDisks (settings::Key &aNode);
    298352
    299353    HRESULT registerMachine (Machine *aMachine);
  • trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h

    r5999 r6076  
     1/* $Id$ */
     2
    13/** @file
    24 *
    3  * VirtualBox XML utility class declaration
     5 * VirtualBox XML/Settings API utility declarations
    46 */
    57
     
    1820#ifndef ____H_VIRTUALBOXXMLUTIL
    1921#define ____H_VIRTUALBOXXMLUTIL
    20 
    21 // for BSTR referred from VBox/cfgldr.h
    22 #include "VBox/com/defs.h"
    23 
    24 #include <VBox/cdefs.h>
    25 #include <VBox/cfgldr.h>
    26 #include <iprt/file.h>
    2722
    2823/** VirtualBox XML settings namespace */
     
    5954#define VBOX_XML_SCHEMA_COMMON  "VirtualBox-settings-" VBOX_XML_PLATFORM_COMMON ".xsd"
    6055
    61 class VirtualBoxXMLUtil
    62 {
    63 protected:
    64 
    65     static DECLCALLBACK(int) cfgLdrEntityResolver (const char *pcszPublicId,
    66                                                    const char *pcszSystemId,
    67                                                    const char *pcszBaseURI,
    68                                                    PCFGLDRENTITY pEntity);
    69 
    70     /** VirtualBox XML settings "namespace schema" pair */
    71     static const char *XmlSchemaNS;
    72 };
    73 
    74 
    75 #endif // ____H_VIRTUALBOXXMLUTIL
    76 
     56#endif /* ____H_VIRTUALBOXXMLUTIL */
  • trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd

    r5999 r6076  
    303303  <xsd:attribute name="port" type="xsd:token"/>
    304304  <xsd:attribute name="remote" type="xsd:token"/>
    305   <xsd:attribute name="maskedInterfaces" type="xsd:unsignedInt"/>
     305  <xsd:attribute name="maskedInterfaces" type="xsd:unsignedInt" default="0"/>
    306306</xsd:complexType>
    307307
     
    437437
    438438<xsd:complexType name="TRemoteDisplay">
    439   <xsd:attribute name="enabled" type="xsd:boolean"/>
     439  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    440440  <xsd:attribute name="port" type="xsd:unsignedInt" default="0"/>
    441441  <xsd:attribute name="netAddress" type="xsd:token" default=""/>
     
    644644<xsd:complexType name="THardware">
    645645  <xsd:all>
    646     <xsd:element name="CPU" type="TCPU" minOccurs = "0"/>
     646    <xsd:element name="CPU" type="TCPU" minOccurs="0"/>
    647647    <xsd:element name="Memory" type="TMemory"/>
    648648    <xsd:element name="Boot" type="TBoot">
     
    708708  <!--- @todo (dmik) make lastStateChange required on next format change! -->
    709709  <xsd:attribute name="lastStateChange" type="TPresentDateTimeUTC"/>
    710   <xsd:attribute name="aborted" type="xsd:boolean"/>
     710  <xsd:attribute name="aborted" type="xsd:boolean" default="false"/>
    711711  <xsd:attribute name="currentStateModified" type="xsd:boolean" default="true"/>
    712712</xsd:complexType>
  • trunk/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd

    r5999 r6076  
    8686
    8787<xsd:complexType name="TAudioAdapter">
    88   <xsd:attribute name="enabled" type="xsd:boolean"/>
     88  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8989  <xsd:attribute name="driver" use="required">
    9090    <!--- @todo (dmik) capitalize enum values on next format change! -->
  • trunk/src/VBox/Main/xml/VirtualBox-settings-linux.xsd

    r6056 r6076  
    8686
    8787<xsd:complexType name="TAudioAdapter">
    88   <xsd:attribute name="enabled" type="xsd:boolean"/>
     88  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8989  <xsd:attribute name="driver" use="required">
    9090    <!--- @todo (dmik) capitalize enum values on next format change! -->
  • trunk/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd

    r5999 r6076  
    8686
    8787<xsd:complexType name="TAudioAdapter">
    88   <xsd:attribute name="enabled" type="xsd:boolean"/>
     88  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8989  <xsd:attribute name="driver" use="required">
    9090    <!--- @todo (dmik) capitalize enum values on next format change! -->
  • trunk/src/VBox/Main/xml/VirtualBox-settings-os2.xsd

    r5999 r6076  
    8686
    8787<xsd:complexType name="TAudioAdapter">
    88   <xsd:attribute name="enabled" type="xsd:boolean"/>
     88  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8989  <xsd:attribute name="driver" use="required">
    9090    <!--- @todo (dmik) capitalize enum values on next format change! -->
  • trunk/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd

    r5999 r6076  
    8686
    8787<xsd:complexType name="TAudioAdapter">
    88   <xsd:attribute name="enabled" type="xsd:boolean"/>
     88  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8989  <xsd:attribute name="driver" use="required">
    9090    <!--- @todo (dmik) capitalize enum values on next format change! -->
  • trunk/src/VBox/Main/xml/VirtualBox-settings-windows.xsd

    r5999 r6076  
    8484
    8585<xsd:complexType name="TAudioAdapter">
    86   <xsd:attribute name="enabled" type="xsd:boolean"/>
     86  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
    8787  <xsd:attribute name="driver" use="required">
    8888    <!--- @todo (dmik) capitalize enum values on next format change! -->
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette