VirtualBox

Changeset 22173 in vbox for trunk/src


Ignore:
Timestamp:
Aug 11, 2009 3:38:59 PM (15 years ago)
Author:
vboxsync
Message:

Main: the big XML settings rework. Move XML reading/writing out of interface implementation code into separate layer so it can handle individual settings versions in the future.

Location:
trunk/src/VBox
Files:
61 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r21806 r22173  
    474474    HRESULT hrc = NewUniqueKey(machine, "VBoxInternal/DBGF/loadsyms", KeyStr);
    475475    if (SUCCEEDED(hrc))
    476         hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Filename", pszFilename);
     476        hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Filename", pszFilename);
    477477    if (SUCCEEDED(hrc) && argc >= 3)
    478         hrc = SetInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Delta", offDelta);
     478        hrc = SetInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Delta", offDelta);
    479479    if (SUCCEEDED(hrc) && argc >= 4)
    480         hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Module", pszModule);
     480        hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Module", pszModule);
    481481    if (SUCCEEDED(hrc) && argc >= 5)
    482         hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "ModuleAddress", ModuleAddress);
     482        hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "ModuleAddress", ModuleAddress);
    483483    if (SUCCEEDED(hrc) && argc >= 6)
    484         hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "ModuleSize", ModuleSize);
     484        hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "ModuleSize", ModuleSize);
    485485
    486486    return FAILED(hrc);
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r21769 r22173  
    12671267        if (!strcmp(a->argv[1], "enumerate"))
    12681268        {
    1269             Bstr extraDataKey;
    1270 
    1271             do
    1272             {
    1273                 Bstr nextExtraDataKey;
    1274                 Bstr nextExtraDataValue;
    1275                 HRESULT rcEnum = a->virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1276                                                                     nextExtraDataValue.asOutParam());
    1277                 extraDataKey = nextExtraDataKey;
    1278 
    1279                 if (SUCCEEDED(rcEnum) && !extraDataKey.isEmpty())
    1280                     RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1281             } while (!extraDataKey.isEmpty());
     1269            SafeArray<BSTR> aKeys;
     1270            CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
     1271
     1272            for (size_t i = 0;
     1273                 i < aKeys.size();
     1274                 ++i)
     1275            {
     1276                Bstr bstrKey(aKeys[i]);
     1277                Bstr bstrValue;
     1278                CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey, bstrValue.asOutParam()));
     1279
     1280                RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
     1281            }
    12821282        }
    12831283        else
     
    13061306            if (!strcmp(a->argv[1], "enumerate"))
    13071307            {
    1308                 Bstr extraDataKey;
    1309 
    1310                 do
    1311                 {
    1312                     Bstr nextExtraDataKey;
    1313                     Bstr nextExtraDataValue;
    1314                     HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1315                                                                   nextExtraDataValue.asOutParam());
    1316                     extraDataKey = nextExtraDataKey;
    1317 
    1318                     if (SUCCEEDED(rcEnum) && !extraDataKey.isEmpty())
    1319                     {
    1320                         RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1321                     }
    1322                 } while (!extraDataKey.isEmpty());
     1308                SafeArray<BSTR> aKeys;
     1309                CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
     1310
     1311                for (size_t i = 0;
     1312                    i < aKeys.size();
     1313                    ++i)
     1314                {
     1315                    Bstr bstrKey(aKeys[i]);
     1316                    Bstr bstrValue;
     1317                    CHECK_ERROR(machine, GetExtraData(bstrKey, bstrValue.asOutParam()));
     1318
     1319                    RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
     1320                }
    13231321            }
    13241322            else
     
    16971695#endif /* !VBOX_ONLY_DOCS */
    16981696
    1699 enum ConvertSettings
    1700 {
    1701     ConvertSettings_No      = 0,
    1702     ConvertSettings_Yes     = 1,
    1703     ConvertSettings_Backup  = 2,
    1704     ConvertSettings_Ignore  = 3,
    1705 };
    1706 
    1707 #ifndef VBOX_ONLY_DOCS
    1708 /**
    1709  * Checks if any of the settings files were auto-converted and informs the
    1710  * user if so.
    1711  *
    1712  * @return @false if the program should terminate and @true otherwise.
    1713  */
    1714 static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
    1715                                            ComPtr<ISession> session,
    1716                                            ConvertSettings fConvertSettings)
    1717 {
    1718     /* return early if nothing to do */
    1719     if (fConvertSettings == ConvertSettings_Ignore)
    1720         return true;
    1721 
    1722     HRESULT rc;
    1723 
    1724     do
    1725     {
    1726         Bstr formatVersion;
    1727         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
    1728 
    1729         bool isGlobalConverted = false;
    1730         std::list <ComPtr <IMachine> > cvtMachines;
    1731         std::list <Utf8Str> fileList;
    1732         Bstr version;
    1733         Bstr filePath;
    1734 
    1735         com::SafeIfaceArray <IMachine> machines;
    1736         CHECK_ERROR_BREAK(virtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam (machines)));
    1737 
    1738         for (size_t i = 0; i < machines.size(); ++ i)
    1739         {
    1740             BOOL accessible;
    1741             CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible) (&accessible));
    1742             if (!accessible)
    1743                 continue;
    1744 
    1745             CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFileVersion) (version.asOutParam()));
    1746 
    1747             if (version != formatVersion)
    1748             {
    1749                 cvtMachines.push_back (machines [i]);
    1750                 Bstr filePath;
    1751                 CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    1752                 fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    1753                                                 version.raw()));
    1754             }
    1755         }
    1756 
    1757         if (FAILED(rc))
    1758             break;
    1759 
    1760         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFileVersion) (version.asOutParam()));
    1761         if (version != formatVersion)
    1762         {
    1763             isGlobalConverted = true;
    1764             CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    1765             fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    1766                                             version.raw()));
    1767         }
    1768 
    1769         if (fileList.size() > 0)
    1770         {
    1771             switch (fConvertSettings)
    1772             {
    1773                 case ConvertSettings_No:
    1774                 {
    1775                     RTPrintf (
    1776 "WARNING! The following VirtualBox settings files have been automatically\n"
    1777 "converted to the new settings file format version '%ls':\n"
    1778 "\n",
    1779                               formatVersion.raw());
    1780 
    1781                     for (std::list <Utf8Str>::const_iterator f = fileList.begin();
    1782                          f != fileList.end(); ++ f)
    1783                         RTPrintf ("  %S\n", (*f).raw());
    1784                     RTPrintf (
    1785 "\n"
    1786 "The current command was aborted to prevent overwriting the above settings\n"
    1787 "files with the results of the auto-conversion without your permission.\n"
    1788 "Please put one of the following command line switches to the beginning of\n"
    1789 "the VBoxManage command line and repeat the command:\n"
    1790 "\n"
    1791 "  --convertSettings       - to save all auto-converted files (it will not\n"
    1792 "                            be possible to use these settings files with an\n"
    1793 "                            older version of VirtualBox in the future);\n"
    1794 "  --convertSettingsBackup - to create backup copies of the settings files in\n"
    1795 "                            the old format before saving them in the new format;\n"
    1796 "  --convertSettingsIgnore - to not save the auto-converted settings files.\n"
    1797 "\n"
    1798 "Note that if you use --convertSettingsIgnore, the auto-converted settings files\n"
    1799 "will be implicitly saved in the new format anyway once you change a setting or\n"
    1800 "start a virtual machine, but NO backup copies will be created in this case.\n");
    1801                     return false;
    1802                 }
    1803                 case ConvertSettings_Yes:
    1804                 case ConvertSettings_Backup:
    1805                 {
    1806                     break;
    1807                 }
    1808                 default:
    1809                     AssertFailedReturn (false);
    1810             }
    1811 
    1812             for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
    1813                  m != cvtMachines.end(); ++ m)
    1814             {
    1815                 Bstr id;
    1816                 CHECK_ERROR_BREAK((*m), COMGETTER(Id) (id.asOutParam()));
    1817 
    1818                 /* open a session for the VM */
    1819                 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
    1820 
    1821                 ComPtr <IMachine> sm;
    1822                 CHECK_ERROR_BREAK(session, COMGETTER(Machine) (sm.asOutParam()));
    1823 
    1824                 Bstr bakFileName;
    1825                 if (fConvertSettings == ConvertSettings_Backup)
    1826                     CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
    1827                 else
    1828                     CHECK_ERROR (sm, SaveSettings());
    1829 
    1830                 session->Close();
    1831 
    1832                 if (FAILED(rc))
    1833                     break;
    1834             }
    1835 
    1836             if (FAILED(rc))
    1837                 break;
    1838 
    1839             if (isGlobalConverted)
    1840             {
    1841                 Bstr bakFileName;
    1842                 if (fConvertSettings == ConvertSettings_Backup)
    1843                     CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
    1844                 else
    1845                     CHECK_ERROR (virtualBox, SaveSettings());
    1846             }
    1847 
    1848             if (FAILED(rc))
    1849                 break;
    1850         }
    1851     }
    1852     while (0);
    1853 
    1854     return SUCCEEDED (rc);
    1855 }
    1856 #endif /* !VBOX_ONLY_DOCS */
    1857 
    18581697// main
    18591698///////////////////////////////////////////////////////////////////////////////
     
    18711710    int  iCmdArg;
    18721711
    1873     ConvertSettings fConvertSettings = ConvertSettings_No;
    1874 
    18751712    /* global options */
    18761713    for (int i = 1; i < argc || argc <= iCmd; i++)
     
    19121749            iCmd++;
    19131750        }
    1914         else if (   !strcmp(argv[i], "--convertSettings")
    1915                  || !strcmp(argv[i], "-convertSettings"))
    1916         {
    1917             fConvertSettings = ConvertSettings_Yes;
    1918             iCmd++;
    1919         }
    1920         else if (   !strcmp(argv[i], "--convertSettingsBackup")
    1921                  || !strcmp(argv[i], "-convertSettingsBackup"))
    1922         {
    1923             fConvertSettings = ConvertSettings_Backup;
    1924             iCmd++;
    1925         }
    1926         else if (   !strcmp(argv[i], "--convertSettingsIgnore")
    1927                  || !strcmp(argv[i], "-convertSettingsIgnore"))
    1928         {
    1929             fConvertSettings = ConvertSettings_Ignore;
    1930             iCmd++;
    1931         }
    19321751        else
    19331752        {
     
    20131832    NS_GetMainEventQ(getter_AddRefs(eventQ));
    20141833#endif
    2015 
    2016     if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
    2017         break;
    20181834
    20191835#ifdef USE_XPCOM_QUEUE
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

    r21806 r22173  
    616616        {
    617617            char szFilenameAbs[RTPATH_MAX] = "";
    618             int vrc = RTPathAbs(Utf8Str(src), szFilenameAbs, sizeof(szFilenameAbs));
     618            int vrc = RTPathAbs(Utf8Str(src).c_str(), szFilenameAbs, sizeof(szFilenameAbs));
    619619            if (RT_FAILURE(vrc))
    620620            {
     
    650650                {
    651651                    char szFilenameAbs[RTPATH_MAX] = "";
    652                     int vrc = RTPathAbs(Utf8Str(dst), szFilenameAbs, sizeof(szFilenameAbs));
     652                    int vrc = RTPathAbs(Utf8Str(dst).c_str(), szFilenameAbs, sizeof(szFilenameAbs));
    653653                    if (RT_FAILURE(vrc))
    654654                    {
  • trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp

    r21520 r22173  
    771771}
    772772#endif /* VBOXSDL_WITH_X11 */
    773 
    774 enum ConvertSettings
    775 {
    776     ConvertSettings_No      = 0,
    777     ConvertSettings_Yes     = 1,
    778     ConvertSettings_Backup  = 2,
    779     ConvertSettings_Ignore  = 3,
    780 };
    781 
    782 /**
    783  * Checks if any of the settings files were auto-converted and informs the
    784  * user if so.
    785  *
    786  * @return @false if the program should terminate and @true otherwise.
    787  *
    788  * @note The function is taken from VBoxManage.cpp almost unchanged (except the
    789  *       help text).
    790  */
    791 static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
    792                                            ComPtr<ISession> session,
    793                                            ConvertSettings fConvertSettings)
    794 {
    795     /* return early if nothing to do */
    796     if (fConvertSettings == ConvertSettings_Ignore)
    797         return true;
    798 
    799     HRESULT rc;
    800 
    801     do
    802     {
    803         Bstr formatVersion;
    804         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
    805 
    806         bool isGlobalConverted = false;
    807         std::list <ComPtr <IMachine> > cvtMachines;
    808         std::list <Utf8Str> fileList;
    809         Bstr version;
    810         Bstr filePath;
    811 
    812         com::SafeIfaceArray <IMachine> machines;
    813         CHECK_ERROR_BREAK(virtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam (machines)));
    814 
    815         for (size_t i = 0; i < machines.size(); ++ i)
    816         {
    817             BOOL accessible;
    818             CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible) (&accessible));
    819             if (!accessible)
    820                 continue;
    821 
    822             CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFileVersion) (version.asOutParam()));
    823 
    824             if (version != formatVersion)
    825             {
    826                 cvtMachines.push_back (machines[i]);
    827                 Bstr filePath;
    828                 CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    829                 fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    830                                                 version.raw()));
    831             }
    832         }
    833 
    834         if (FAILED(rc))
    835             break;
    836 
    837         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFileVersion) (version.asOutParam()));
    838         if (version != formatVersion)
    839         {
    840             isGlobalConverted = true;
    841             CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    842             fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    843                                             version.raw()));
    844         }
    845 
    846         if (fileList.size() > 0)
    847         {
    848             switch (fConvertSettings)
    849             {
    850                 case ConvertSettings_No:
    851                 {
    852                     RTPrintf (
    853 "WARNING! The following VirtualBox settings files have been automatically\n"
    854 "converted to the new settings file format version '%ls':\n"
    855 "\n",
    856                               formatVersion.raw());
    857 
    858                     for (std::list <Utf8Str>::const_iterator f = fileList.begin();
    859                          f != fileList.end(); ++ f)
    860                         RTPrintf ("  %S\n", (*f).raw());
    861                     RTPrintf (
    862 "\n"
    863 "The current command was aborted to prevent overwriting the above settings\n"
    864 "files with the results of the auto-conversion without your permission.\n"
    865 "Please add one of the following command line switches to the VBoxSDL command\n"
    866 "line and repeat the command:\n"
    867 "\n"
    868 "  --convertSettings       - to save all auto-converted files (it will not\n"
    869 "                            be possible to use these settings files with an\n"
    870 "                            older version of VirtualBox in the future);\n"
    871 "  --convertSettingsBackup - to create backup copies of the settings files in\n"
    872 "                            the old format before saving them in the new format;\n"
    873 "  --convertSettingsIgnore - to not save the auto-converted settings files.\n"
    874 "\n"
    875 "Note that if you use --convertSettingsIgnore, the auto-converted settings files\n"
    876 "will be implicitly saved in the new format anyway once you change a setting or\n"
    877 "start a virtual machine, but NO backup copies will be created in this case.\n");
    878                     return false;
    879                 }
    880                 case ConvertSettings_Yes:
    881                 case ConvertSettings_Backup:
    882                 {
    883                     break;
    884                 }
    885                 default:
    886                     AssertFailedReturn (false);
    887             }
    888 
    889             for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
    890                  m != cvtMachines.end(); ++ m)
    891             {
    892                 Bstr id;
    893                 CHECK_ERROR_BREAK((*m), COMGETTER(Id) (id.asOutParam()));
    894 
    895                 /* open a session for the VM */
    896                 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
    897 
    898                 ComPtr <IMachine> sm;
    899                 CHECK_ERROR_BREAK(session, COMGETTER(Machine) (sm.asOutParam()));
    900 
    901                 Bstr bakFileName;
    902                 if (fConvertSettings == ConvertSettings_Backup)
    903                     CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
    904                 else
    905                     CHECK_ERROR (sm, SaveSettings());
    906 
    907                 session->Close();
    908 
    909                 if (FAILED(rc))
    910                     break;
    911             }
    912 
    913             if (FAILED(rc))
    914                 break;
    915 
    916             if (isGlobalConverted)
    917             {
    918                 Bstr bakFileName;
    919                 if (fConvertSettings == ConvertSettings_Backup)
    920                     CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
    921                 else
    922                     CHECK_ERROR (virtualBox, SaveSettings());
    923             }
    924 
    925             if (FAILED(rc))
    926                 break;
    927         }
    928     }
    929     while (0);
    930 
    931     return SUCCEEDED (rc);
    932 }
    933773
    934774/** entry point */
     
    11841024    sysInfo->COMGETTER (NetworkAdapterCount) (&NetworkAdapterCount);
    11851025
    1186     ConvertSettings fConvertSettings = ConvertSettings_No;
    1187 
    11881026    // command line argument parsing stuff
    11891027    for (int curArg = 1; curArg < argc; curArg++)
     
    16021440            gHostKeyMod = atoi(argv[curArg]);
    16031441        }
    1604         else if (   !strcmp(argv[curArg], "--convertSettings")
    1605                  || !strcmp(argv[curArg], "-convertSettings"))
    1606             fConvertSettings = ConvertSettings_Yes;
    1607         else if (   !strcmp(argv[curArg], "--convertSettingsBackup")
    1608                  || !strcmp(argv[curArg], "-convertSettingsBackup"))
    1609             fConvertSettings = ConvertSettings_Backup;
    1610         else if (   !strcmp(argv[curArg], "--convertSettingsIgnore")
    1611                  || !strcmp(argv[curArg], "-convertSettingsIgnore"))
    1612             fConvertSettings = ConvertSettings_Ignore;
    16131442        /* just show the help screen */
    16141443        else
     
    16231452    }
    16241453    if (FAILED (rc))
    1625         break;
    1626 
    1627     if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
    16281454        break;
    16291455
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h

    r22157 r22173  
    610610#endif
    611611
    612     bool checkForSettingsAutoConversion (bool aAfterRefresh = false);
    613 
    614     bool checkForSettingsAutoConversionAfterRefresh() { return checkForSettingsAutoConversion (true); }
    615 
    616612    CSession openSession (const QString &aId, bool aExisting = false);
    617613
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp

    r22157 r22173  
    21112111
    21122112/**
    2113  * Checks if any of the settings files were auto-converted and informs the user
    2114  * if so. Returns @c false if the user select to exit the application.
    2115  *
    2116  * @param aAfterRefresh @c true to suppress the first simple dialog aExit
    2117  *                      button. Used when calling after the VM refresh.
    2118  */
    2119 bool VBoxGlobal::checkForSettingsAutoConversion (bool aAfterRefresh /* = false */)
    2120 {
    2121     QString currentVersion = mVBox.GetSettingsFormatVersion();
    2122     QList <CMachine> machines;
    2123     bool isGlobalToBeConverted = false;
    2124     QString fileList;
    2125     int maxIndex = 0;
    2126 
    2127     /* Check if VM files need to be converted */
    2128     CMachineVector vec = mVBox.GetMachines();
    2129     for (CMachineVector::ConstIterator m = vec.begin(); m != vec.end(); ++ m)
    2130     {
    2131         if (!m->GetAccessible())
    2132             continue;
    2133 
    2134         QString version = m->GetSettingsFileVersion();
    2135         if (version != currentVersion)
    2136         {
    2137             ++ maxIndex;
    2138             machines.append (*m);
    2139             fileList += QString ("<tr><td><nobr>%1</nobr></td><td>&nbsp;&nbsp;</td>"
    2140                                  "</td><td><nobr><i>%2</i></nobr></td></tr>")
    2141                 .arg (m->GetSettingsFilePath())
    2142                 .arg (version);
    2143         }
    2144     }
    2145 
    2146     /* Check if global file need to be converted */
    2147     if (!aAfterRefresh)
    2148     {
    2149         QString version = mVBox.GetSettingsFileVersion();
    2150         if (version != currentVersion)
    2151         {
    2152             ++ maxIndex;
    2153             isGlobalToBeConverted = true;
    2154             fileList += QString ("<tr><td><nobr>%1</nobr></td><td>&nbsp;&nbsp;</td>"
    2155                                  "</td><td><nobr><i>%2</i></nobr></td></tr>")
    2156                 .arg (mVBox.GetSettingsFilePath())
    2157                 .arg (version);
    2158         }
    2159     }
    2160 
    2161     if (!fileList.isNull())
    2162     {
    2163         fileList = QString ("<table cellspacing=0 cellpadding=0>%1</table>")
    2164                             .arg (fileList);
    2165 
    2166         /* Asking the user about he wants to convert the
    2167          * configuration files or leave it as already is. */
    2168         if (vboxProblem().warnAboutSettingsAutoConversion (
    2169             fileList, aAfterRefresh) == QIMessageBox::Cancel)
    2170             return false;
    2171 
    2172         /* Composing progress dialog */
    2173         QProgressDialog dlg (mainWindow());
    2174         dlg.setCancelButton (0);
    2175         dlg.setWindowModality (Qt::WindowModal);
    2176         dlg.setMinimum (0);
    2177         dlg.setMaximum (maxIndex);
    2178         dlg.setMinimumDuration (2000);
    2179         dlg.setAutoReset (false);
    2180 
    2181         /* Converting VM configuration files */
    2182         foreach (CMachine m, machines)
    2183         {
    2184             dlg.setValue (machines.indexOf (m));
    2185             dlg.setLabelText (tr ("Converting file... (%1/%2)")
    2186                               .arg (machines.indexOf (m) + 1).arg (maxIndex));
    2187 
    2188             CSession session = openSession (m.GetId());
    2189             if (!session.isNull())
    2190             {
    2191                 CMachine sm = session.GetMachine();
    2192                 sm.SaveSettingsWithBackup();
    2193                 if (!sm.isOk())
    2194                     vboxProblem().cannotSaveMachineSettings (sm);
    2195                 session.Close();
    2196             }
    2197         }
    2198 
    2199         /* Converting global configuration file */
    2200         if (isGlobalToBeConverted)
    2201         {
    2202             dlg.setValue (machines.size());
    2203             dlg.setLabelText (tr ("Converting file... (%1/%2)")
    2204                               .arg (machines.size() + 1).arg (maxIndex));
    2205 
    2206             mVBox.SaveSettingsWithBackup();
    2207             if (!mVBox.isOk())
    2208                 vboxProblem().cannotSaveGlobalSettings (mVBox);
    2209         }
    2210 
    2211         dlg.setValue (maxIndex);
    2212         dlg.setLabelText (tr ("Conversion finished!"));
    2213     }
    2214 
    2215     return true;
    2216 }
    2217 
    2218 /**
    22192113 *  Opens a direct session for a machine with the given ID.
    22202114 *  This method does user-friendly error handling (display error messages, etc.).
     
    44844378
    44854379    retranslateUi();
    4486 
    4487     /* Note: the settings conversion check must be done before anything else
    4488      * that may unconditionally overwrite settings files in the new format (like
    4489      * SetExtraData()). But after loading the proper the language. */
    4490     if (!checkForSettingsAutoConversion())
    4491         return;
    44924380
    44934381#ifdef VBOX_GUI_WITH_SYSTRAY
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxSelectorWnd.cpp

    r21833 r22173  
    11151115                   true /* aDescription */);
    11161116
    1117     if (!oldAccessible && item->accessible() &&
    1118         !vboxGlobal().checkForSettingsAutoConversionAfterRefresh())
     1117    if (!oldAccessible && item->accessible())
    11191118        fileExit();
    11201119}
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r21878 r22173  
    994994
    995995        /* The temporary name of the target OVF file */
    996         strTmpOvf = Utf8StrFmt("%s/%s", pszTmpDir, RTPathFilename(tmpPath));
     996        strTmpOvf = Utf8StrFmt("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
    997997
    998998        /* Next we have to download the OVF */
     
    15541554                        VirtualSystemDescriptionEntry *vsdeHD = *itHD;
    15551555
    1556                         const char *pcszDstFilePath = vsdeHD->strVbox.c_str();
    15571556                        /* Check if the destination file exists already or the
    15581557                         * destination path is empty. */
    1559                         if (    !(*pcszDstFilePath)
    1560                              || RTPathExists(pcszDstFilePath)
     1558                        if (    vsdeHD->strVbox.isEmpty()
     1559                             || RTPathExists(vsdeHD->strVbox.c_str())
    15611560                           )
    15621561                            /* This isn't allowed */
    15631562                            throw setError(VBOX_E_FILE_ERROR,
    15641563                                           tr("Destination file '%s' exists",
    1565                                               pcszDstFilePath));
     1564                                              vsdeHD->strVbox.c_str()));
    15661565
    15671566                        /* Find the disk from the OVF's disk list */
     
    15811580
    15821581                        /* Make sure all target directories exists */
    1583                         rc = VirtualBox::ensureFilePathExists(pcszDstFilePath);
     1582                        rc = VirtualBox::ensureFilePathExists(vsdeHD->strVbox.c_str());
    15841583                        if (FAILED(rc))
    15851584                            throw rc;
     
    15981597                                srcFormat = L"VMDK";
    15991598                            /* Create an empty hard disk */
    1600                             rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(pcszDstFilePath), dstHdVBox.asOutParam());
     1599                            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam());
    16011600                            if (FAILED(rc)) throw rc;
    16021601
     
    16071606                            /* Advance to the next operation */
    16081607                            if (!pTask->progress.isNull())
    1609                                 pTask->progress->setNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), pcszDstFilePath),
     1608                                pTask->progress->setNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), vsdeHD->strVbox.c_str()),
    16101609                                                                 vsdeHD->ulSizeMB);     // operation's weight, as set up with the IProgress originally
    16111610                        }
     
    16381637                            if (FAILED(rc)) throw rc;
    16391638                            /* Create a new hard disk interface for the destination disk image */
    1640                             rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(pcszDstFilePath), dstHdVBox.asOutParam());
     1639                            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam());
    16411640                            if (FAILED(rc)) throw rc;
    16421641                            /* Clone the source disk image */
     
    17251724                        }
    17261725
    1727                         Log(("Attaching disk %s to channel %d on device %d\n", pcszDstFilePath, mhda.lChannel, mhda.lDevice));
     1726                        Log(("Attaching disk %s to channel %d on device %d\n", vsdeHD->strVbox.c_str(), mhda.lChannel, mhda.lDevice));
    17281727
    17291728                        rc = sMachine->AttachHardDisk(hdId,
     
    18821881                {
    18831882                    /* The temporary name of the target disk file */
    1884                     Utf8StrFmt strTmpDisk("%s/%s", pszTmpDir, RTPathFilename(strTargetFile));
     1883                    Utf8StrFmt strTmpDisk("%s/%s", pszTmpDir, RTPathFilename(strTargetFile.c_str()));
    18851884                    filesList.push_back(pair<Utf8Str, ULONG>(strTmpDisk, (*itH)->ulSizeMB));
    18861885                }
     
    19251924        /* Provide a OVF file (haven't to exist) so the import routine can
    19261925         * figure out where the disk images/manifest file are located. */
    1927         Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath));
     1926        Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
    19281927        /* Now check if there is an manifest file. This is optional. */
    19291928        Utf8Str strManifestFile = manifestFileName(strTmpOvf);
     
    29762975
    29772976        /* The temporary name of the target OVF file */
    2978         Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath));
     2977        Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
    29792978
    29802979        /* Prepare the temporary writing of the OVF */
  • trunk/src/VBox/Main/AudioAdapterImpl.cpp

    r21878 r22173  
    361361 *  @note Locks this object for writing.
    362362 */
    363 HRESULT AudioAdapter::loadSettings (const settings::Key &aMachineNode)
    364 {
    365     using namespace settings;
    366 
    367     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    368 
     363HRESULT AudioAdapter::loadSettings(const settings::AudioAdapter &data)
     364{
    369365    AutoCaller autoCaller(this);
    370366    AssertComRCReturnRC(autoCaller.rc());
     
    383379     * default to B. */
    384380
    385     /* AudioAdapter node (required) */
    386     Key audioAdapterNode = aMachineNode.key ("AudioAdapter");
    387 
    388     /* is the adapter enabled? (required) */
    389     mData->mEnabled = audioAdapterNode.value <bool> ("enabled");
    390 
    391     /* now check the audio adapter */
    392     const char *controller = audioAdapterNode.stringValue ("controller");
    393     if (strcmp (controller, "SB16") == 0)
    394         mData->mAudioController = AudioControllerType_SB16;
    395     else if (strcmp (controller, "AC97") == 0)
    396         mData->mAudioController = AudioControllerType_AC97;
    397 
    398     /* now check the audio driver (required) */
    399     const char *driver = audioAdapterNode.stringValue ("driver");
    400     if      (strcmp (driver, "Null") == 0)
    401         mData->mAudioDriver = AudioDriverType_Null;
    402 #ifdef RT_OS_WINDOWS
    403     else if (strcmp (driver, "WinMM") == 0)
    404 #ifdef VBOX_WITH_WINMM
    405         mData->mAudioDriver = AudioDriverType_WinMM;
    406 #else
    407         /* fall back to dsound */
    408         mData->mAudioDriver = AudioDriverType_DirectSound;
    409 #endif
    410     else if (strcmp (driver, "DirectSound") == 0)
    411         mData->mAudioDriver = AudioDriverType_DirectSound;
    412 #endif // RT_OS_WINDOWS
    413 #ifdef RT_OS_SOLARIS
    414     else if (strcmp (driver, "SolAudio") == 0)
    415         mData->mAudioDriver = AudioDriverType_SolAudio;
    416 #endif // RT_OS_SOLARIS
    417 #ifdef RT_OS_LINUX
    418     else if (strcmp (driver, "ALSA") == 0)
    419 # ifdef VBOX_WITH_ALSA
    420         mData->mAudioDriver = AudioDriverType_ALSA;
    421 # else
    422         /* fall back to OSS */
    423         mData->mAudioDriver = AudioDriverType_OSS;
    424 # endif
    425     else if (strcmp (driver, "Pulse") == 0)
    426 # ifdef VBOX_WITH_PULSE
    427         mData->mAudioDriver = AudioDriverType_Pulse;
    428 # else
    429         /* fall back to OSS */
    430         mData->mAudioDriver = AudioDriverType_OSS;
    431 # endif
    432 #endif // RT_OS_LINUX
    433 #if defined (RT_OS_LINUX) || defined (RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
    434     else if (strcmp (driver, "OSS") == 0)
    435         mData->mAudioDriver = AudioDriverType_OSS;
    436 #endif // RT_OS_LINUX || RT_OS_FREEBSD
    437 #ifdef RT_OS_DARWIN
    438     else if (strcmp (driver, "CoreAudio") == 0)
    439         mData->mAudioDriver = AudioDriverType_CoreAudio;
    440 #endif
    441 #ifdef RT_OS_OS2
    442     else if (strcmp (driver, "MMPM") == 0)
    443         mData->mAudioDriver = AudioDriverType_MMPM;
    444 #endif
    445     else
    446         AssertMsgFailed (("Invalid driver '%s'\n", driver));
     381    mData->mEnabled = data.fEnabled;
     382    mData->mAudioController = data.controllerType;
     383    mData->mAudioDriver = data.driverType;
    447384
    448385    return S_OK;
     
    456393 *  @note Locks this object for reading.
    457394 */
    458 HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode)
    459 {
    460     using namespace settings;
    461 
    462     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    463 
     395HRESULT AudioAdapter::saveSettings(settings::AudioAdapter &data)
     396{
    464397    AutoCaller autoCaller(this);
    465398    AssertComRCReturnRC(autoCaller.rc());
     
    467400    AutoReadLock alock(this);
    468401
    469     Key node = aMachineNode.createKey ("AudioAdapter");
    470 
    471     const char *controllerStr = NULL;
    472     switch (mData->mAudioController)
    473     {
    474         case AudioControllerType_SB16:
    475         {
    476             controllerStr = "SB16";
    477             break;
    478         }
    479         default:
    480         {
    481             controllerStr = "AC97";
    482             break;
    483         }
    484     }
    485     node.setStringValue ("controller", controllerStr);
    486 
    487     const char *driverStr = NULL;
    488     switch (mData->mAudioDriver)
    489     {
    490         case AudioDriverType_Null:
    491         {
    492             driverStr = "Null";
    493             break;
    494         }
    495 #ifdef RT_OS_WINDOWS
    496             case AudioDriverType_WinMM:
    497 # ifdef VBOX_WITH_WINMM
    498             {
    499                 driverStr = "WinMM";
    500                 break;
    501             }
    502 # endif
    503             case AudioDriverType_DirectSound:
    504             {
    505                 driverStr = "DirectSound";
    506                 break;
    507             }
    508 #endif /* RT_OS_WINDOWS */
    509 #ifdef RT_OS_SOLARIS
    510             case AudioDriverType_SolAudio:
    511             {
    512                 driverStr = "SolAudio";
    513                 break;
    514             }
    515 #endif
    516 #ifdef RT_OS_LINUX
    517             case AudioDriverType_ALSA:
    518 # ifdef VBOX_WITH_ALSA
    519             {
    520                 driverStr = "ALSA";
    521                 break;
    522             }
    523 # endif
    524             case AudioDriverType_Pulse:
    525 # ifdef VBOX_WITH_PULSE
    526             {
    527                 driverStr = "Pulse";
    528                 break;
    529             }
    530 # endif
    531 #endif /* RT_OS_LINUX */
    532 #if defined (RT_OS_LINUX) || defined (RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
    533             case AudioDriverType_OSS:
    534             {
    535                 driverStr = "OSS";
    536                 break;
    537             }
    538 #endif /* RT_OS_LINUX || RT_OS_FREEBSD */
    539 #ifdef RT_OS_DARWIN
    540             case AudioDriverType_CoreAudio:
    541             {
    542                 driverStr = "CoreAudio";
    543                 break;
    544             }
    545 #endif
    546 #ifdef RT_OS_OS2
    547             case AudioDriverType_MMPM:
    548             {
    549                 driverStr = "MMPM";
    550                 break;
    551             }
    552 #endif
    553             default:
    554                 ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d",
    555                                         mData->mAudioDriver),
    556                                        E_FAIL);
    557     }
    558     node.setStringValue ("driver", driverStr);
    559 
    560     node.setValue <bool> ("enabled", !!mData->mEnabled);
    561 
     402    data.fEnabled = mData->mEnabled;
     403    data.controllerType = mData->mAudioController;
     404    data.driverType = mData->mAudioDriver;
    562405    return S_OK;
    563406}
  • trunk/src/VBox/Main/BIOSSettingsImpl.cpp

    r21878 r22173  
    459459 *  @note Locks this object for writing.
    460460 */
    461 HRESULT BIOSSettings::loadSettings (const settings::Key &aMachineNode)
    462 {
    463     using namespace settings;
    464 
    465     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    466 
     461HRESULT BIOSSettings::loadSettings(const settings::BIOSSettings &data)
     462{
    467463    AutoCaller autoCaller(this);
    468464    AssertComRCReturnRC(autoCaller.rc());
     
    470466    AutoWriteLock alock(this);
    471467
    472     /* Note: we assume that the default values for attributes of optional
    473      * nodes are assigned in the Data::Data() constructor and don't do it
    474      * here. It implies that this method may only be called after constructing
    475      * a new BIOSSettings object while all its data fields are in the default
    476      * values. Exceptions are fields whose creation time defaults don't match
    477      * values that should be applied when these fields are not explicitly set
    478      * in the settings file (for backwards compatibility reasons). This takes
    479      * place when a setting of a newly created object must default to A while
    480      * the same setting of an object loaded from the old settings file must
    481      * default to B. */
    482 
    483     /* BIOS node (required) */
    484     Key biosNode = aMachineNode.key ("BIOS");
    485 
    486     /* ACPI (required) */
    487     {
    488         Key acpiNode = biosNode.key ("ACPI");
    489 
    490         mData->mACPIEnabled = acpiNode.value <bool> ("enabled");
    491     }
    492 
    493     /* IOAPIC (optional) */
    494     {
    495         Key ioapicNode = biosNode.findKey ("IOAPIC");
    496         if (!ioapicNode.isNull())
    497             mData->mIOAPICEnabled = ioapicNode.value <bool> ("enabled");
    498     }
    499 
    500     /* Logo (optional) */
    501     {
    502         Key logoNode = biosNode.findKey ("Logo");
    503         if (!logoNode.isNull())
    504         {
    505             mData->mLogoFadeIn = logoNode.value <bool> ("fadeIn");
    506             mData->mLogoFadeOut = logoNode.value <bool> ("fadeOut");
    507             mData->mLogoDisplayTime = logoNode.value <ULONG> ("displayTime");
    508             mData->mLogoImagePath = logoNode.stringValue ("imagePath");
    509         }
    510     }
    511 
    512     /* boot menu (optional) */
    513     {
    514         Key bootMenuNode = biosNode.findKey ("BootMenu");
    515         if (!bootMenuNode.isNull())
    516         {
    517             mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
    518             const char *modeStr = bootMenuNode.stringValue ("mode");
    519 
    520             if (strcmp (modeStr, "Disabled") == 0)
    521                 mData->mBootMenuMode = BIOSBootMenuMode_Disabled;
    522             else if (strcmp (modeStr, "MenuOnly") == 0)
    523                 mData->mBootMenuMode = BIOSBootMenuMode_MenuOnly;
    524             else if (strcmp (modeStr, "MessageAndMenu") == 0)
    525                 mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
    526             else
    527                 ComAssertMsgFailedRet (("Invalid boot menu mode '%s'", modeStr),
    528                                        E_FAIL);
    529         }
    530     }
    531 
    532     /* PXE debug logging (optional) */
    533     {
    534         Key pxedebugNode = biosNode.findKey ("PXEDebug");
    535         if (!pxedebugNode.isNull())
    536             mData->mPXEDebugEnabled = pxedebugNode.value <bool> ("enabled");
    537     }
    538 
    539     /* time offset (optional) */
    540     {
    541         Key timeOffsetNode = biosNode.findKey ("TimeOffset");
    542         if (!timeOffsetNode.isNull())
    543             mData->mTimeOffset = timeOffsetNode.value <LONG64> ("value");
    544     }
     468    mData->mACPIEnabled = data.fACPIEnabled;
     469    mData->mIOAPICEnabled = data.fIOAPICEnabled;
     470
     471    mData->mLogoFadeIn = data.fLogoFadeIn;
     472    mData->mLogoFadeOut = data.fLogoFadeOut;
     473    mData->mLogoDisplayTime = data.ulLogoDisplayTime;
     474    mData->mLogoImagePath = data.strLogoImagePath;
     475
     476    mData->mBootMenuMode = data.biosBootMenuMode;
     477
     478    mData->mPXEDebugEnabled = data.fPXEDebugEnabled;
     479    mData->mTimeOffset = data.llTimeOffset;
    545480
    546481    return S_OK;
     
    554489 *  @note Locks this object for reading.
    555490 */
    556 HRESULT BIOSSettings::saveSettings (settings::Key &aMachineNode)
    557 {
    558     using namespace settings;
    559 
    560     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    561 
     491HRESULT BIOSSettings::saveSettings(settings::BIOSSettings &data)
     492{
    562493    AutoCaller autoCaller(this);
    563494    AssertComRCReturnRC(autoCaller.rc());
     
    565496    AutoReadLock alock(this);
    566497
    567     Key biosNode = aMachineNode.createKey ("BIOS");
    568 
    569     /* ACPI */
    570     {
    571         Key acpiNode = biosNode.createKey ("ACPI");
    572         acpiNode.setValue <bool> ("enabled", !!mData->mACPIEnabled);
    573     }
    574 
    575     /* IOAPIC */
    576     {
    577         Key ioapicNode = biosNode.createKey ("IOAPIC");
    578         ioapicNode.setValue <bool> ("enabled", !!mData->mIOAPICEnabled);
    579     }
    580 
    581     /* BIOS logo (optional) **/
    582     {
    583         Key logoNode = biosNode.createKey ("Logo");
    584         logoNode.setValue <bool> ("fadeIn", !!mData->mLogoFadeIn);
    585         logoNode.setValue <bool> ("fadeOut", !!mData->mLogoFadeOut);
    586         logoNode.setValue <ULONG> ("displayTime", mData->mLogoDisplayTime);
    587         logoNode.setValueOr <Bstr> ("imagePath", mData->mLogoImagePath, Bstr::Null);
    588     }
    589 
    590     /* boot menu (optional) */
    591     {
    592         Key bootMenuNode = biosNode.createKey ("BootMenu");
    593         const char *modeStr = NULL;
    594         switch (mData->mBootMenuMode)
    595         {
    596             case BIOSBootMenuMode_Disabled:
    597                 modeStr = "Disabled";
    598                 break;
    599             case BIOSBootMenuMode_MenuOnly:
    600                 modeStr = "MenuOnly";
    601                 break;
    602             case BIOSBootMenuMode_MessageAndMenu:
    603                 modeStr = "MessageAndMenu";
    604                 break;
    605             default:
    606                 ComAssertMsgFailedRet (("Invalid boot menu type: %d",
    607                                         mData->mBootMenuMode),
    608                                        E_FAIL);
    609         }
    610         bootMenuNode.setStringValue ("mode", modeStr);
    611     }
    612 
    613     /* time offset (optional) */
    614     {
    615         Key timeOffsetNode = biosNode.createKey ("TimeOffset");
    616         timeOffsetNode.setValue <LONG64> ("value", mData->mTimeOffset);
    617     }
    618 
    619     /* PXE debug flag (optional) */
    620     {
    621         Key pxedebugNode = biosNode.createKey ("PXEDebug");
    622         pxedebugNode.setValue <bool> ("enabled", !!mData->mPXEDebugEnabled);
    623     }
     498    data.fACPIEnabled = !!mData->mACPIEnabled;
     499    data.fIOAPICEnabled = !!mData->mIOAPICEnabled;
     500
     501    data.fLogoFadeIn = !!mData->mLogoFadeIn;
     502    data.fLogoFadeOut = !!mData->mLogoFadeOut;
     503    data.ulLogoDisplayTime = mData->mLogoDisplayTime;
     504    data.strLogoImagePath = mData->mLogoImagePath;
     505
     506    data.biosBootMenuMode = mData->mBootMenuMode;
     507    data.fPXEDebugEnabled = !!mData->mPXEDebugEnabled;
     508    data.llTimeOffset = mData->mTimeOffset;
    624509
    625510    return S_OK;
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r21984 r22173  
    956956
    957957    PSSMHANDLE ssm;
    958     int vrc = SSMR3Open (Utf8Str(savedStateFile), 0, &ssm);
     958    int vrc = SSMR3Open(Utf8Str(savedStateFile).c_str(), 0, &ssm);
    959959    if (VBOX_SUCCESS (vrc))
    960960    {
     
    10201020        vrc = SSMR3PutU32 (pSSM, (uint32_t)name.length() + 1 /* term. 0 */);
    10211021        AssertRC (vrc);
    1022         vrc = SSMR3PutStrZ (pSSM, name);
     1022        vrc = SSMR3PutStrZ(pSSM, name.c_str());
    10231023        AssertRC (vrc);
    10241024
     
    10261026        vrc = SSMR3PutU32 (pSSM, (uint32_t)hostPath.length() + 1 /* term. 0 */);
    10271027        AssertRC (vrc);
    1028         vrc = SSMR3PutStrZ (pSSM, hostPath);
     1028        vrc = SSMR3PutStrZ (pSSM, hostPath.c_str());
    10291029        AssertRC (vrc);
    10301030
     
    18461846            Utf8Str dir = stateFilePath;
    18471847            dir.stripFilename();
    1848             if (!RTDirExists(dir))
     1848            if (!RTDirExists(dir.c_str()))
    18491849            {
    1850                 int vrc = RTDirCreateFullPath (dir, 0777);
     1850                int vrc = RTDirCreateFullPath(dir.c_str(), 0777);
    18511851                if (VBOX_FAILURE (vrc))
    18521852                {
     
    33223322                                           (unsigned) ulInstance, 0, &pBase);
    33233323            ComAssertRC (vrc);
    3324             if (VBOX_SUCCESS (vrc))
     3324            if (VBOX_SUCCESS(vrc))
    33253325            {
    33263326                Assert(pBase);
     
    33343334                                                     fCableConnected ? PDMNETWORKLINKSTATE_UP
    33353335                                                                     : PDMNETWORKLINKSTATE_DOWN);
    3336                     ComAssertRC (vrc);
     3336                    ComAssertRC(vrc);
    33373337                }
    33383338            }
     
    45074507    /* make sure the Logs folder exists */
    45084508    Assert(logDir.length());
    4509     if (!RTDirExists (logDir))
    4510         RTDirCreateFullPath (logDir, 0777);
    4511 
    4512     Utf8Str logFile = Utf8StrFmt ("%s%cVBox.log",
    4513                                   logDir.raw(), RTPATH_DELIMITER);
    4514     Utf8Str pngFile = Utf8StrFmt ("%s%cVBox.png",
    4515                                   logDir.raw(), RTPATH_DELIMITER);
     4509    if (!RTDirExists(logDir.c_str()))
     4510        RTDirCreateFullPath(logDir.c_str(), 0777);
     4511
     4512    Utf8Str logFile = Utf8StrFmt("%s%cVBox.log",
     4513                                 logDir.raw(), RTPATH_DELIMITER);
     4514    Utf8Str pngFile = Utf8StrFmt("%s%cVBox.png",
     4515                                 logDir.raw(), RTPATH_DELIMITER);
    45164516
    45174517    /*
     
    45484548                 * exists) to provide correct rotation even if the sequence is
    45494549                 * broken */
    4550                 if (   RTFileRename (oldName, newName, RTFILEMOVE_FLAGS_REPLACE)
     4550                if (   RTFileRename(oldName.c_str(), newName.c_str(), RTFILEMOVE_FLAGS_REPLACE)
    45514551                    == VERR_FILE_NOT_FOUND)
    4552                     RTFileDelete (newName);
     4552                    RTFileDelete(newName.c_str());
    45534553            }
    45544554        }
     
    47264726        CheckComRCReturnRC(rc);
    47274727        ComAssertRet (!!savedStateFile, E_FAIL);
    4728         int vrc = SSMR3ValidateFile (Utf8Str (savedStateFile), false /* fChecksumIt */);
    4729         if (VBOX_FAILURE (vrc))
    4730             return setError (VBOX_E_FILE_ERROR,
    4731                 tr ("VM cannot start because the saved state file '%ls' is invalid (%Rrc). "
    4732                     "Discard the saved state prior to starting the VM"),
    4733                     savedStateFile.raw(), vrc);
     4728        int vrc = SSMR3ValidateFile(Utf8Str(savedStateFile).c_str(), false /* fChecksumIt */);
     4729        if (VBOX_FAILURE(vrc))
     4730            return setError(VBOX_E_FILE_ERROR,
     4731                            tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). "
     4732                               "Discard the saved state prior to starting the VM"),
     4733                            savedStateFile.raw(), vrc);
    47344734    }
    47354735
     
    66856685            LogRel (("Failed to launch VRDP server (%Rrc), error message: '%s'\n",
    66866686                     vrc, errMsg.raw()));
    6687             throw setError (E_FAIL, errMsg);
     6687            throw setError(E_FAIL, errMsg.c_str());
    66886688        }
    66896689
     
    67856785                                  task->mSavedStateFile.raw()));
    67866786
    6787                     vrc = VMR3Load (pVM, task->mSavedStateFile,
    6788                                     Console::stateProgressCallback,
    6789                                     static_cast <VMProgressTask *> (task.get()));
     6787                    vrc = VMR3Load(pVM,
     6788                                   task->mSavedStateFile.c_str(),
     6789                                   Console::stateProgressCallback,
     6790                                   static_cast<VMProgressTask*>(task.get()));
    67906791
    67916792                    if (VBOX_SUCCESS (vrc))
     
    68786879            /* Set the error message as the COM error.
    68796880             * Progress::notifyComplete() will pick it up later. */
    6880             throw setError (E_FAIL, task->mErrorMsg);
     6881            throw setError(E_FAIL, task->mErrorMsg.c_str());
    68816882        }
    68826883    }
     
    70947095    hrc = hardDisk->COMGETTER(Location)(bstr.asOutParam());                     H();
    70957096    LogFlowFunc (("LUN#%d: leaf location '%ls'\n", iLUN, bstr.raw()));
    7096     rc = CFGMR3InsertString(pCfg, "Path", Utf8Str(bstr));                       RC_CHECK();
     7097    rc = CFGMR3InsertString(pCfg, "Path", Utf8Str(bstr).c_str());                       RC_CHECK();
    70977098    hrc = hardDisk->COMGETTER(Format)(bstr.asOutParam());                       H();
    70987099    LogFlowFunc (("LUN#%d: leaf format '%ls'\n", iLUN, bstr.raw()));
    7099     rc = CFGMR3InsertString(pCfg, "Format", Utf8Str(bstr));                     RC_CHECK();
     7100    rc = CFGMR3InsertString(pCfg, "Format", Utf8Str(bstr).c_str());                     RC_CHECK();
    71007101
    71017102    /* Pass all custom parameters. */
     
    71157116            if (values [i])
    71167117            {
    7117                 Utf8Str name = names [i];
    7118                 Utf8Str value = values [i];
    7119                 rc = CFGMR3InsertString (pVDC, name, value);
     7118                Utf8Str name = names[i];
     7119                Utf8Str value = values[i];
     7120                rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str());
    71207121                if (    !(name.compare("HostIPStack"))
    71217122                    &&  !(value.compare("0")))
     
    71367137        rc = CFGMR3InsertNode(pParent, "Parent", &pCur);                        RC_CHECK();
    71377138        hrc = hardDisk->COMGETTER(Location)(bstr.asOutParam());                 H();
    7138         rc = CFGMR3InsertString(pCur,  "Path", Utf8Str(bstr));                  RC_CHECK();
     7139        rc = CFGMR3InsertString(pCur,  "Path", Utf8Str(bstr).c_str());          RC_CHECK();
    71397140
    71407141        hrc = hardDisk->COMGETTER(Format)(bstr.asOutParam());                   H();
    7141         rc = CFGMR3InsertString(pCur,  "Format", Utf8Str(bstr));                RC_CHECK();
     7142        rc = CFGMR3InsertString(pCur,  "Format", Utf8Str(bstr).c_str());        RC_CHECK();
    71427143
    71437144        /* Pass all custom parameters. */
     
    71587159                    Utf8Str name = names [i];
    71597160                    Utf8Str value = values [i];
    7160                     rc = CFGMR3InsertString (pVDC, name, value);
     7161                    rc = CFGMR3InsertString (pVDC, name.c_str(), value.c_str());
    71617162                    if (    !(name.compare("HostIPStack"))
    71627163                        &&  !(value.compare("0")))
     
    72417242        LogFlowFunc (("Saving the state to '%s'...\n", task->mSavedStateFile.raw()));
    72427243
    7243         int vrc = VMR3Save (that->mpVM, task->mSavedStateFile,
    7244                             Console::stateProgressCallback,
    7245                             static_cast <VMProgressTask *> (task.get()));
     7244        int vrc = VMR3Save(that->mpVM,
     7245                           task->mSavedStateFile.c_str(),
     7246                           Console::stateProgressCallback,
     7247                           static_cast<VMProgressTask*>(task.get()));
    72467248        if (VBOX_FAILURE (vrc))
    72477249        {
     
    73707372                                            COM_IIDOF(IConsole),
    73717373                                            Console::getComponentName(),
    7372                                             errMsg);
     7374                                            errMsg.c_str());
    73737375        else
    73747376            task->mProgress->notifyComplete (rc);
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r22171 r22173  
    227227    rc = CFGMR3InsertInteger(pRoot, "RamHoleSize",          cbRamHole);             RC_CHECK();
    228228    rc = CFGMR3InsertInteger(pRoot, "NumCPUs",              cCpus);                 RC_CHECK();
    229     rc = CFGMR3InsertString (pRoot, "OSType",               Utf8Str(osTypeId));    RC_CHECK();
     229    rc = CFGMR3InsertString (pRoot, "OSType",               Utf8Str(osTypeId).c_str()); RC_CHECK();
    230230    rc = CFGMR3InsertInteger(pRoot, "TimerMillies",         10);                    RC_CHECK();
    231231    rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled",         1);     /* boolean */   RC_CHECK();
     
    779779    Bstr logoImagePath;
    780780    hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam());       H();
    781     rc = CFGMR3InsertString(pCfg,   "LogoFile", logoImagePath ? Utf8Str(logoImagePath) : ""); RC_CHECK();
     781    rc = CFGMR3InsertString(pCfg,   "LogoFile", logoImagePath ? Utf8Str(logoImagePath).c_str() : ""); RC_CHECK();
    782782
    783783    /*
     
    11021102                        Utf8Str name = names[ii];
    11031103                        Utf8Str value = values[ii];
    1104                         rc = CFGMR3InsertString(pVDC, name, value);
     1104                        rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str());
    11051105                        if (    name.compare("HostIPStack") == 0
    11061106                            &&  value.compare("0") == 0)
     
    11451145                            Utf8Str name = names[ii];
    11461146                            Utf8Str value = values[ii];
    1147                             rc = CFGMR3InsertString(pVDC, name, value);
     1147                            rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str());
    11481148                            if (    name.compare("HostIPStack") == 0
    11491149                                &&  value.compare("0") == 0)
     
    19071907     */
    19081908    /** @todo add support for removing nodes and byte blobs. */
    1909     Bstr strExtraDataKey;
    1910     bool fGlobalExtraData = true;
    1911     for (;;)
    1912     {
     1909    SafeArray<BSTR> aGlobalExtraDataKeys;
     1910    SafeArray<BSTR> aMachineExtraDataKeys;
     1911    /*
     1912        * Get the next key
     1913        */
     1914    if (FAILED(hrc = virtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys))))
     1915        AssertMsgFailed(("VirtualBox::GetExtraDataKeys failed with %Rrc\n", hrc));
     1916    size_t cGlobalValues = aGlobalExtraDataKeys.size();
     1917    if (FAILED(hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys))))
     1918        AssertMsgFailed(("IMachine::GetExtraDataKeys failed with %Rrc\n", hrc));
     1919
     1920    // build a combined list, prefix global keys with "G:"...
     1921    std::list<Utf8Str> llExtraDataKeys;
     1922    size_t i;
     1923    for (i = 0; i < aGlobalExtraDataKeys.size(); ++i)
     1924        llExtraDataKeys.push_back(Utf8Str(aGlobalExtraDataKeys[i]));
     1925    // ... and machine keys with "M:" (so we know below which method to call)
     1926    for (i = 0; i < aMachineExtraDataKeys.size(); ++i)
     1927        llExtraDataKeys.push_back(Utf8Str(aMachineExtraDataKeys[i]));
     1928    i = 0;
     1929    for (std::list<Utf8Str>::const_iterator it = llExtraDataKeys.begin();
     1930         it != llExtraDataKeys.end();
     1931         ++it, ++i)
     1932    {
     1933        const Utf8Str &strKey = *it;
     1934
    19131935        /*
    1914          * Get the next key
     1936         * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:")
    19151937         */
    1916         Bstr strNextExtraDataKey;
     1938        if (!strKey.startsWith("VBoxInternal/"))
     1939            continue;
     1940
     1941        const char *pszExtraDataKey = strKey.raw() + sizeof("VBoxInternal/") - 1;
     1942
     1943        // get the value
    19171944        Bstr strExtraDataValue;
    1918         if (fGlobalExtraData)
    1919             hrc = virtualBox->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
    1920                                                   strExtraDataValue.asOutParam());
     1945        if (i < cGlobalValues)
     1946            // this is still one of the global values:
     1947            hrc = virtualBox->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());
    19211948        else
    1922             hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
    1923                                                 strExtraDataValue.asOutParam());
    1924 
    1925         /* stop if for some reason there's nothing more to request */
    1926         if (FAILED(hrc) || strNextExtraDataKey.isEmpty())
    1927         {
    1928             /* if we're out of global keys, continue with machine, otherwise we're done */
    1929             if (fGlobalExtraData)
    1930             {
    1931                 fGlobalExtraData = false;
    1932                 strExtraDataKey.setNull();
    1933                 continue;
    1934             }
    1935             break;
    1936         }
    1937         strExtraDataKey = strNextExtraDataKey;
    1938 
    1939         /*
    1940          * We only care about keys starting with "VBoxInternal/"
    1941          */
    1942         Utf8Str strExtraDataKeyUtf8(strExtraDataKey);
    1943         char *pszExtraDataKey = (char *)strExtraDataKeyUtf8.raw();
    1944         if (strncmp(pszExtraDataKey, "VBoxInternal/", sizeof("VBoxInternal/") - 1) != 0)
    1945             continue;
    1946         pszExtraDataKey += sizeof("VBoxInternal/") - 1;
     1949            hrc = pMachine->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());
     1950        if (FAILED(hrc))
     1951            LogRel(("Warning: Cannot get extra data key %s, rc = %Rrc\n", strKey.raw(), hrc));
    19471952
    19481953        /*
     
    19521957         */
    19531958        PCFGMNODE pNode;
    1954         char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
     1959        const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
    19551960        if (pszCFGMValueName)
    19561961        {
    19571962            /* terminate the node and advance to the value (Utf8Str might not
    19581963               offically like this but wtf) */
    1959             *pszCFGMValueName = '\0';
     1964            *(char*)pszCFGMValueName = '\0';
    19601965            pszCFGMValueName++;
    19611966
  • trunk/src/VBox/Main/DHCPServerImpl.cpp

    r21878 r22173  
    8686}
    8787
    88 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, const settings::Key &aNode)
    89 {
    90     using namespace settings;
    91 
     88HRESULT DHCPServer::init(VirtualBox *aVirtualBox,
     89                         const settings::DHCPServer &data)
     90{
    9291    /* Enclose the state transition NotReady->InInit->Ready */
    9392    AutoInitSpan autoInitSpan(this);
     
    9998    aVirtualBox->addDependentChild (this);
    10099
    101     unconst(mName) = aNode.stringValue ("networkName");
    102     m.IPAddress = aNode.stringValue ("IPAddress");
    103     m.networkMask = aNode.stringValue ("networkMask");
    104     m.enabled = aNode.value <bool> ("enabled");
    105     m.lowerIP = aNode.stringValue ("lowerIP");
    106     m.upperIP = aNode.stringValue ("upperIP");
     100    unconst(mName) = data.strNetworkName;
     101    m.IPAddress = data.strIPAddress;
     102    m.networkMask = data.strIPNetworkMask;
     103    m.enabled = data.fEnabled;
     104    m.lowerIP = data.strIPLower;
     105    m.upperIP = data.strIPUpper;
    107106
    108107    autoInitSpan.setSucceeded();
     
    111110}
    112111
    113 HRESULT DHCPServer::saveSettings (settings::Key &aParentNode)
    114 {
    115     using namespace settings;
    116 
    117     AssertReturn(!aParentNode.isNull(), E_FAIL);
    118 
     112HRESULT DHCPServer::saveSettings(settings::DHCPServer &data)
     113{
    119114    AutoCaller autoCaller(this);
    120115    CheckComRCReturnRC(autoCaller.rc());
     
    122117    AutoReadLock alock(this);
    123118
    124     Key aNode = aParentNode.appendKey ("DHCPServer");
    125     /* required */
    126     aNode.setValue <Bstr> ("networkName", mName);
    127     aNode.setValue <Bstr> ("IPAddress", m.IPAddress);
    128     aNode.setValue <Bstr> ("networkMask", m.networkMask);
    129     aNode.setValue <Bstr> ("lowerIP", m.lowerIP);
    130     aNode.setValue <Bstr> ("upperIP", m.upperIP);
    131     /* To force it back to a numeric value; will otherwise break for 2.2.x. */
    132     aNode.setValue <ULONG> ("enabled", m.enabled);
     119    data.strNetworkName = mName;
     120    data.strIPAddress = m.IPAddress;
     121    data.strIPNetworkMask = m.networkMask;
     122    data.fEnabled = m.enabled;
     123    data.strIPLower = m.lowerIP;
     124    data.strIPUpper = m.upperIP;
    133125
    134126    return S_OK;
     
    243235}
    244236
    245 STDMETHODIMP DHCPServer::Start (IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType)
     237STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType)
    246238{
    247239    /* Silently ignore attepmts to run disabled servers. */
  • trunk/src/VBox/Main/DVDDriveImpl.cpp

    r21945 r22173  
    411411 * @note Locks this object for writing.
    412412 */
    413 HRESULT DVDDrive::loadSettings (const settings::Key &aMachineNode)
    414 {
    415     using namespace settings;
    416 
    417     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    418 
     413HRESULT DVDDrive::loadSettings(const settings::DVDDrive &data)
     414{
    419415    AutoCaller autoCaller(this);
    420416    AssertComRCReturnRC(autoCaller.rc());
     
    435431    HRESULT rc = S_OK;
    436432
    437     /* DVD drive (required, contains either Image or HostDrive or nothing) */
    438     Key dvdDriveNode = aMachineNode.key ("DVDDrive");
    439 
    440433    /* optional, defaults to false */
    441     m->passthrough = dvdDriveNode.value <bool> ("passthrough");
    442 
    443     Key typeNode;
    444 
    445     if (!(typeNode = dvdDriveNode.findKey ("Image")).isNull())
    446     {
    447         Guid uuid = typeNode.value <Guid> ("uuid");
    448         rc = MountImage (uuid.toUtf16());
    449         CheckComRCReturnRC(rc);
    450     }
    451     else if (!(typeNode = dvdDriveNode.findKey ("HostDrive")).isNull())
    452     {
    453 
    454         Bstr src = typeNode.stringValue ("src");
     434    m->passthrough = data.fPassThrough;
     435
     436    if (!data.uuid.isEmpty())
     437    {
     438        rc = MountImage(data.uuid.toUtf16());
     439        CheckComRCReturnRC (rc);
     440    }
     441    else if (!data.strHostDriveSrc.isEmpty())
     442    {
     443        Bstr src = data.strHostDriveSrc;
    455444
    456445        /* find the corresponding object */
     
    458447
    459448        com::SafeIfaceArray<IHostDVDDrive> coll;
    460         rc = host->COMGETTER(DVDDrives) (ComSafeArrayAsOutParam(coll));
     449        rc = host->COMGETTER(DVDDrives)(ComSafeArrayAsOutParam(coll));
    461450        AssertComRC (rc);
    462451
    463452        ComPtr<IHostDVDDrive> drive;
    464         rc = host->FindHostDVDDrive (src, drive.asOutParam());
     453        rc = host->FindHostDVDDrive(src, drive.asOutParam());
    465454
    466455        if (SUCCEEDED(rc))
    467456        {
    468             rc = CaptureHostDrive (drive);
     457            rc = CaptureHostDrive(drive);
    469458            CheckComRCReturnRC(rc);
    470459        }
     
    477466            hostDrive.createObject();
    478467            rc = hostDrive->init (src);
    479             AssertComRC (rc);
     468            AssertComRC(rc);
    480469            rc = CaptureHostDrive (hostDrive);
    481470            CheckComRCReturnRC(rc);
     
    489478        }
    490479        else
    491             AssertComRC (rc);
     480            AssertComRC(rc);
    492481    }
    493482
     
    502491 * @note Locks this object for reading.
    503492 */
    504 HRESULT DVDDrive::saveSettings (settings::Key &aMachineNode)
    505 {
    506     using namespace settings;
    507 
    508     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    509 
     493HRESULT DVDDrive::saveSettings(settings::DVDDrive &data)
     494{
    510495    AutoCaller autoCaller(this);
    511496    AssertComRCReturnRC(autoCaller.rc());
     
    513498    AutoReadLock alock(this);
    514499
    515     Key node = aMachineNode.createKey ("DVDDrive");
    516 
    517     node.setValue <bool> ("passthrough", !!m->passthrough);
     500    data.fPassThrough = !!m->passthrough;
     501
     502    HRESULT  rc = S_OK;
    518503
    519504    switch (m->state)
     
    524509
    525510            Bstr id;
    526             HRESULT rc = m->image->COMGETTER(Id) (id.asOutParam());
     511            rc = m->image->COMGETTER(Id) (id.asOutParam());
    527512            AssertComRC (rc);
    528513            Assert (!id.isEmpty());
    529514
    530             Key imageNode = node.createKey ("Image");
    531             imageNode.setValue <Guid> ("uuid", Guid(id));
     515            data.uuid = Guid(id);
     516            data.strHostDriveSrc.setNull();
    532517            break;
    533518        }
     
    537522
    538523            Bstr name;
    539             HRESULT  rc = m->hostDrive->COMGETTER(Name) (name.asOutParam());
     524            rc = m->hostDrive->COMGETTER(Name)(name.asOutParam());
    540525            AssertComRC (rc);
    541526            Assert (!name.isEmpty());
    542527
    543             Key hostDriveNode = node.createKey ("HostDrive");
    544             hostDriveNode.setValue <Bstr> ("src", name);
     528            data.uuid.clear();
     529            data.strHostDriveSrc = name;
    545530            break;
    546531        }
    547532        case DriveState_NotMounted:
    548533            /* do nothing, i.e.leave the drive node empty */
    549             break;
     534            data.uuid.clear();
     535            data.strHostDriveSrc.setNull();
     536        break;
    550537        default:
    551538            ComAssertMsgFailedRet (("Invalid drive state: %d", m->state),
  • trunk/src/VBox/Main/FloppyDriveImpl.cpp

    r21878 r22173  
    418418 * @note Locks this object for writing.
    419419 */
    420 HRESULT FloppyDrive::loadSettings (const settings::Key &aMachineNode)
    421 {
    422     using namespace settings;
    423 
    424     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    425 
     420HRESULT FloppyDrive::loadSettings(const settings::FloppyDrive &data)
     421{
    426422    AutoCaller autoCaller(this);
    427423    AssertComRCReturnRC(autoCaller.rc());
     
    442438    HRESULT rc = S_OK;
    443439
    444     /* Floppy drive (required, contains either Image or HostDrive or nothing) */
    445     Key floppyDriveNode = aMachineNode.key ("FloppyDrive");
    446 
    447440    /* optional, defaults to true */
    448     m->enabled = floppyDriveNode.value <bool> ("enabled");
    449 
    450     Key typeNode;
    451 
    452     if (!(typeNode = floppyDriveNode.findKey ("Image")).isNull())
    453     {
    454         Guid uuid = typeNode.value <Guid> ("uuid");
    455         rc = MountImage (uuid.toUtf16());
     441    m->enabled = data.fEnabled;
     442
     443    if (!data.uuid.isEmpty())
     444    {
     445        rc = MountImage(data.uuid.toUtf16());
    456446        CheckComRCReturnRC(rc);
    457447    }
    458     else if (!(typeNode = floppyDriveNode.findKey ("HostDrive")).isNull())
    459     {
    460 
    461         Bstr src = typeNode.stringValue ("src");
     448    else if (!data.strHostDriveSrc.isEmpty())
     449    {
     450        Bstr src = data.strHostDriveSrc;
    462451
    463452        /* find the corresponding object */
     
    502491 * @note Locks this object for reading.
    503492 */
    504 HRESULT FloppyDrive::saveSettings (settings::Key &aMachineNode)
    505 {
    506     using namespace settings;
    507 
    508     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    509 
     493HRESULT FloppyDrive::saveSettings(settings::FloppyDrive &data)
     494{
    510495    AutoCaller autoCaller(this);
    511496    AssertComRCReturnRC(autoCaller.rc());
     
    513498    AutoReadLock alock(this);
    514499
    515     Key node = aMachineNode.createKey ("FloppyDrive");
    516 
    517     node.setValue <bool> ("enabled", !!m->enabled);
     500    data.fEnabled = !!m->enabled;
    518501
    519502    switch (m->state)
     
    528511            Assert (!id.isEmpty());
    529512
    530             Key imageNode = node.createKey ("Image");
    531             imageNode.setValue <Guid> ("uuid", Guid(id));
     513            data.uuid = Guid(id);
     514            data.strHostDriveSrc.setNull();
    532515            break;
    533516        }
     
    541524            Assert (!name.isEmpty());
    542525
    543             Key hostDriveNode = node.createKey ("HostDrive");
    544             hostDriveNode.setValue <Bstr> ("src", name);
     526            data.uuid.clear();
     527            data.strHostDriveSrc = name;
    545528            break;
    546529        }
    547530        case DriveState_NotMounted:
    548531            /* do nothing, i.e.leave the drive node empty */
    549             break;
     532            data.uuid.clear();
     533            data.strHostDriveSrc.setNull();
     534        break;
    550535        default:
    551536            ComAssertMsgFailedRet (("Invalid drive state: %d", m->state),
  • trunk/src/VBox/Main/HardDiskImpl.cpp

    r21878 r22173  
    2222 */
    2323
    24 #include "HardDiskImpl.h"
    25 
    26 #include "ProgressImpl.h"
    27 #include "SystemPropertiesImpl.h"
    28 
    29 #include "Logging.h"
    30 
    31 #include <VBox/com/array.h>
    32 #include <VBox/com/SupportErrorInfo.h>
    33 
    34 #include <VBox/err.h>
    35 #include <VBox/settings.h>
    36 
    3724#include <iprt/param.h>
    3825#include <iprt/path.h>
     
    4027#include <iprt/tcp.h>
    4128
     29#include <VBox/com/array.h>
     30#include <VBox/com/SupportErrorInfo.h>
     31
     32#include <VBox/err.h>
     33#include <VBox/settings.h>
     34
    4235#include <list>
    4336#include <memory>
     37
     38#include "HardDiskImpl.h"
     39#include "SystemPropertiesImpl.h"
     40#include "ProgressImpl.h"
     41
     42#include "Logging.h"
    4443
    4544////////////////////////////////////////////////////////////////////////////////
     
    878877        {
    879878            Assert (!m.lastAccessError.isEmpty());
    880             rc = setError (E_FAIL, Utf8Str (m.lastAccessError));
     879            rc = setError(E_FAIL, Utf8Str(m.lastAccessError).c_str());
    881880        }
    882881        else
     
    906905 * @note Locks VirtualBox lock for writing, treeLock() for writing.
    907906 */
    908 HRESULT HardDisk::init (VirtualBox *aVirtualBox,
    909                         HardDisk *aParent,
    910                         const settings::Key &aNode)
    911 {
    912     using namespace settings;
    913 
     907HRESULT HardDisk::init(VirtualBox *aVirtualBox,
     908                       HardDisk *aParent,
     909                       const settings::Medium &data)
     910{
    914911    AssertReturn(aVirtualBox, E_INVALIDARG);
    915912
     
    930927    {
    931928        /* we set mParent */
    932         AutoWriteLock treeLock (this->treeLock());
     929        AutoWriteLock treeLock(this->treeLock());
    933930
    934931        mParent = aParent;
     
    939936     * as inaccessible for now */
    940937    m.state = MediaState_Inaccessible;
    941     m.lastAccessError = tr ("Accessibility check was not yet performed");
     938    m.lastAccessError = tr("Accessibility check was not yet performed");
    942939
    943940    /* required */
    944     unconst(m.id) = aNode.value <Guid> ("uuid");
     941    unconst(m.id) = data.uuid;
    945942
    946943    /* optional */
    947     {
    948         settings::Key descNode = aNode.findKey ("Description");
    949         if (!descNode.isNull())
    950             m.description = descNode.keyStringValue();
    951     }
     944    m.description = data.strDescription;
    952945
    953946    /* required */
    954     Bstr format = aNode.stringValue ("format");
    955     AssertReturn(!format.isNull(), E_FAIL);
    956     rc = setFormat (format);
     947    AssertReturn(!data.strFormat.isEmpty(), E_FAIL);
     948    rc = setFormat(Bstr(data.strFormat));
    957949    CheckComRCReturnRC(rc);
    958950
    959951    /* optional, only for diffs, default is false */
    960952    if (aParent != NULL)
    961         mm.autoReset = aNode.value <bool> ("autoReset");
     953        mm.autoReset = data.fAutoReset;
    962954    else
    963955        mm.autoReset = false;
     
    968960     * compatibility; we can also clean them up from the XML upon next
    969961     * XML format version change if we wish) */
    970     Key::List properties = aNode.keys ("Property");
    971     for (Key::List::const_iterator it = properties.begin();
    972          it != properties.end(); ++ it)
    973     {
    974         mm.properties [Bstr (it->stringValue ("name"))] =
    975             Bstr (it->stringValue ("value"));
     962    for (settings::PropertiesMap::const_iterator it = data.properties.begin();
     963         it != data.properties.end();
     964         ++it)
     965    {
     966        const Utf8Str &name = it->first;
     967        const Utf8Str &value = it->second;
     968        mm.properties[Bstr(name)] = Bstr(value);
    976969    }
    977970
    978971    /* required */
    979     Bstr location = aNode.stringValue ("location");
    980     rc = setLocation (location);
     972    rc = setLocation(data.strLocation);
    981973    CheckComRCReturnRC(rc);
    982974
    983975    /* type is only for base hard disks */
    984976    if (mParent.isNull())
    985     {
    986         const char *type = aNode.stringValue ("type");
    987         if      (strcmp (type, "Normal") == 0)
    988             mm.type = HardDiskType_Normal;
    989         else if (strcmp (type, "Immutable") == 0)
    990             mm.type = HardDiskType_Immutable;
    991         else if (strcmp (type, "Writethrough") == 0)
    992             mm.type = HardDiskType_Writethrough;
    993         else
    994             AssertFailed();
    995     }
     977        mm.type = data.hdType;
    996978
    997979    LogFlowThisFunc(("m.locationFull='%ls', mm.format=%ls, m.id={%RTuuid}\n",
     
    1006988
    1007989    /* load all children */
    1008     Key::List hardDisks = aNode.keys ("HardDisk");
    1009     for (Key::List::const_iterator it = hardDisks.begin();
    1010          it != hardDisks.end(); ++ it)
    1011     {
    1012         ComObjPtr<HardDisk> hardDisk;
    1013         hardDisk.createObject();
    1014         rc = hardDisk->init(aVirtualBox, this, *it);
     990    for (settings::MediaList::const_iterator it = data.llChildren.begin();
     991         it != data.llChildren.end();
     992         ++it)
     993    {
     994        const settings::Medium &m = *it;
     995
     996        ComObjPtr<HardDisk> pHD;
     997        pHD.createObject();
     998        rc = pHD->init(aVirtualBox,
     999                       this,            // parent
     1000                       m);              // child data
    10151001        CheckComRCBreakRC (rc);
    10161002
    1017         rc = mVirtualBox->registerHardDisk(hardDisk, false /* aSaveRegistry */);
     1003        rc = mVirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */);
    10181004        CheckComRCBreakRC (rc);
    10191005    }
     
    19651951 * @note Locks this object, treeLock() and children for reading.
    19661952 */
    1967 HRESULT HardDisk::saveSettings (settings::Key &aParentNode)
    1968 {
    1969     using namespace settings;
    1970 
    1971     AssertReturn(!aParentNode.isNull(), E_FAIL);
    1972 
     1953HRESULT HardDisk::saveSettings(settings::Medium &data)
     1954{
    19731955    AutoCaller autoCaller(this);
    19741956    CheckComRCReturnRC(autoCaller.rc());
     
    19791961    AutoReadLock treeLock (this->treeLock());
    19801962
    1981     Key diskNode = aParentNode.appendKey ("HardDisk");
    1982     /* required */
    1983     diskNode.setValue <Guid> ("uuid", m.id);
    1984     /* required (note: the original locaiton, not full) */
    1985     diskNode.setValue <Bstr> ("location", m.location);
    1986     /* required */
    1987     diskNode.setValue <Bstr> ("format", mm.format);
     1963    data.uuid = m.id;
     1964    data.strLocation = m.location;
     1965    data.strFormat = mm.format;
     1966
    19881967    /* optional, only for diffs, default is false */
    19891968    if (!mParent.isNull())
    1990         diskNode.setValueOr <bool> ("autoReset", !!mm.autoReset, false);
     1969        data.fAutoReset = !!mm.autoReset;
     1970    else
     1971        data.fAutoReset = false;
     1972
    19911973    /* optional */
    1992     if (!m.description.isNull())
    1993     {
    1994         Key descNode = diskNode.createKey ("Description");
    1995         descNode.setKeyValue <Bstr> (m.description);
    1996     }
     1974    data.strDescription = m.description;
    19971975
    19981976    /* optional properties */
     1977    data.properties.clear();
    19991978    for (Data::PropertyMap::const_iterator it = mm.properties.begin();
    2000          it != mm.properties.end(); ++ it)
     1979         it != mm.properties.end();
     1980         ++it)
    20011981    {
    20021982        /* only save properties that have non-default values */
    20031983        if (!it->second.isNull())
    20041984        {
    2005             Key propNode = diskNode.appendKey ("Property");
    2006             propNode.setValue <Bstr> ("name", it->first);
    2007             propNode.setValue <Bstr> ("value", it->second);
     1985            Utf8Str name = it->first;
     1986            Utf8Str value = it->second;
     1987            data.properties[name] = value;
    20081988        }
    20091989    }
     
    20111991    /* only for base hard disks */
    20121992    if (mParent.isNull())
    2013     {
    2014         const char *type =
    2015             mm.type == HardDiskType_Normal ? "Normal" :
    2016             mm.type == HardDiskType_Immutable ? "Immutable" :
    2017             mm.type == HardDiskType_Writethrough ? "Writethrough" : NULL;
    2018         Assert (type != NULL);
    2019         diskNode.setStringValue ("type", type);
    2020     }
     1993        data.hdType = mm.type;
    20211994
    20221995    /* save all children */
    20231996    for (List::const_iterator it = children().begin();
    20241997         it != children().end();
    2025          ++ it)
    2026     {
    2027         HRESULT rc = (*it)->saveSettings (diskNode);
    2028         AssertComRCReturnRC(rc);
     1998         ++it)
     1999    {
     2000        settings::Medium m;
     2001        HRESULT rc = (*it)->saveSettings(m);
     2002        AssertComRCReturnRC (rc);
     2003        data.llChildren.push_back(m);
    20292004    }
    20302005
     
    20442019 *                      the specified location, and -1 otherwise.
    20452020 */
    2046 HRESULT HardDisk::compareLocationTo (const char *aLocation, int &aResult)
     2021HRESULT HardDisk::compareLocationTo(const Utf8Str &strLocation, int &aResult)
    20472022{
    20482023    AutoCaller autoCaller(this);
     
    20572032    if (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File)
    20582033    {
    2059         Utf8Str location (aLocation);
     2034        Utf8Str location(strLocation);
    20602035
    20612036        /* For locations represented by files, append the default path if
    20622037         * only the name is given, and then get the full path. */
    2063         if (!RTPathHavePath (aLocation))
    2064         {
    2065             AutoReadLock propsLock (mVirtualBox->systemProperties());
    2066             location = Utf8StrFmt ("%ls%c%s",
    2067                 mVirtualBox->systemProperties()->defaultHardDiskFolder().raw(),
    2068                 RTPATH_DELIMITER, aLocation);
    2069         }
    2070 
    2071         int vrc = mVirtualBox->calculateFullPath (location, location);
     2038        if (!RTPathHavePath(strLocation.c_str()))
     2039            location = Utf8StrFmt("%s%c%s",
     2040                                  mVirtualBox->getDefaultHardDiskFolder().raw(),
     2041                                  RTPATH_DELIMITER,
     2042                                  strLocation.c_str());
     2043
     2044        int vrc = mVirtualBox->calculateFullPath(location, location);
    20722045        if (RT_FAILURE(vrc))
    2073             return setError (E_FAIL,
    2074                 tr ("Invalid hard disk storage file location '%s' (%Rrc)"),
    2075                 location.raw(), vrc);
    2076 
    2077         aResult = RTPathCompare (locationFull, location);
     2046            return setError(E_FAIL,
     2047                            tr("Invalid hard disk storage file location '%s' (%Rrc)"),
     2048                            location.raw(),
     2049                            vrc);
     2050
     2051        aResult = RTPathCompare(locationFull.c_str(), location.c_str());
    20782052    }
    20792053    else
    2080         aResult = locationFull.compare (aLocation);
     2054        aResult = locationFull.compare(strLocation);
    20812055
    20822056    return S_OK;
     
    20972071    Utf8Str location (m.locationFull);
    20982072
    2099     Utf8Str name = RTPathFilename (location);
     2073    Utf8Str name = RTPathFilename(location.c_str());
    21002074    return name;
    21012075}
     
    23622336Bstr HardDisk::preferredDiffFormat()
    23632337{
    2364     Bstr format;
    2365 
    23662338    AutoCaller autoCaller(this);
    2367     AssertComRCReturn (autoCaller.rc(), format);
     2339    AssertReturn(autoCaller.rc(), "");
    23682340
    23692341    /* mm.format is const, no need to lock */
    2370     format = mm.format;
     2342    Bstr bstrFormat = mm.format;
    23712343
    23722344    /* check that our own format supports diffs */
    23732345    if (!(mm.formatObj->capabilities() & HardDiskFormatCapabilities_Differencing))
    2374     {
    23752346        /* use the default format if not */
    2376         AutoReadLock propsLock (mVirtualBox->systemProperties());
    2377         format = mVirtualBox->systemProperties()->defaultHardDiskFormat();
    2378     }
    2379 
    2380     return format;
     2347        bstrFormat = mVirtualBox->getDefaultHardDiskFormat();
     2348
     2349    return bstrFormat;
    23812350}
    23822351
     
    29512920 * @note Must be called from under this object's write lock.
    29522921 */
    2953 HRESULT HardDisk::setLocation (CBSTR aLocation)
    2954 {
    2955     /// @todo so far, we assert but later it makes sense to support null
    2956     /// locations for hard disks that are not yet created fail to create a
    2957     /// storage unit instead
    2958     CheckComArgStrNotEmptyOrNull (aLocation);
     2922HRESULT HardDisk::setLocation(const Utf8Str &aLocation)
     2923{
     2924    AssertReturn(!aLocation.isEmpty(), E_FAIL);
    29592925
    29602926    AutoCaller autoCaller(this);
     
    29782944        Guid id;
    29792945
    2980         Utf8Str location (aLocation);
     2946        Utf8Str location(aLocation);
    29812947
    29822948        if (m.state == MediaState_NotCreated)
     
    29852951            Assert (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File);
    29862952
    2987             if (RTPathFilename (location) == NULL)
     2953            if (RTPathFilename(location.c_str()) == NULL)
    29882954            {
    29892955                /* no file name is given (either an empty string or ends with a
     
    29912957                 * this */
    29922958
    2993                 ComAssertMsgRet (!mm.formatObj->fileExtensions().empty(),
    2994                                  ("Must be at least one extension if it is HardDiskFormatCapabilities_File\n"),
    2995                                  E_FAIL);
     2959                ComAssertMsgRet(!mm.formatObj->fileExtensions().empty(),
     2960                                ("Must be at least one extension if it is HardDiskFormatCapabilities_File\n"),
     2961                                E_FAIL);
    29962962
    29972963                Bstr ext = mm.formatObj->fileExtensions().front();
    2998                 ComAssertMsgRet (!ext.isEmpty(),
    2999                                  ("Default extension must not be empty\n"),
    3000                                  E_FAIL);
     2964                ComAssertMsgRet(!ext.isEmpty(),
     2965                                ("Default extension must not be empty\n"),
     2966                                E_FAIL);
    30012967
    30022968                id.create();
    30032969
    3004                 location = Utf8StrFmt ("%s{%RTuuid}.%ls",
    3005                                        location.raw(), id.raw(), ext.raw());
     2970                location = Utf8StrFmt("%s{%RTuuid}.%ls",
     2971                                      location.raw(),
     2972                                      id.raw(),
     2973                                      ext.raw());
    30062974            }
    30072975        }
    30082976
    30092977        /* append the default folder if no path is given */
    3010         if (!RTPathHavePath (location))
    3011         {
    3012             AutoReadLock propsLock (mVirtualBox->systemProperties());
    3013             location = Utf8StrFmt ("%ls%c%s",
    3014                 mVirtualBox->systemProperties()->defaultHardDiskFolder().raw(),
    3015                 RTPATH_DELIMITER,
    3016                 location.raw());
    3017         }
     2978        if (!RTPathHavePath(location.c_str()))
     2979            location = Utf8StrFmt("%s%c%s",
     2980                                  mVirtualBox->getDefaultHardDiskFolder().raw(),
     2981                                  RTPATH_DELIMITER,
     2982                                  location.raw());
    30182983
    30192984        /* get the full file name */
     
    30332998            {
    30342999                RTFILE file;
    3035                 vrc = RTFileOpen (&file, locationFull, RTFILE_O_READ);
     3000                vrc = RTFileOpen(&file, locationFull.c_str(), RTFILE_O_READ);
    30363001                if (RT_SUCCESS(vrc))
    30373002                    RTFileClose (file);
     
    30393004            if (RT_SUCCESS(vrc))
    30403005            {
    3041                 vrc = VDGetFormat (locationFull, &backendName);
     3006                vrc = VDGetFormat(locationFull.c_str(), &backendName);
    30423007            }
    30433008            else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND)
     
    30453010                /* assume it's not a file, restore the original location */
    30463011                location = locationFull = aLocation;
    3047                 vrc = VDGetFormat (locationFull, &backendName);
     3012                vrc = VDGetFormat(locationFull.c_str(), &backendName);
    30483013            }
    30493014
     
    31133078    /* get the format object first */
    31143079    {
    3115         AutoReadLock propsLock (mVirtualBox->systemProperties());
     3080        AutoReadLock propsLock(mVirtualBox->systemProperties());
    31163081
    31173082        unconst(mm.formatObj)
     
    32533218             * images can be opened as base images. Should be fixed ASAP. */
    32543219            vrc = VDOpen(hdd,
    3255                          Utf8Str(mm.format),
    3256                          location,
     3220                         Utf8Str(mm.format).c_str(),
     3221                         location.c_str(),
    32573222                         flags,
    32583223                         mm.vdDiskIfaces);
     
    33043269                    {
    33053270                        lastAccessError = Utf8StrFmt (
    3306                             tr ("UUID {%RTuuid} of the hard disk '%ls' does not match the value {%RTuuid} stored in the media registry ('%ls')"),
     3271                            tr ("UUID {%RTuuid} of the hard disk '%ls' does not match the value {%RTuuid} stored in the media registry ('%s')"),
    33073272                            &uuid, m.locationFull.raw(), m.id.raw(),
    3308                             mVirtualBox->settingsFileName().raw());
     3273                            mVirtualBox->settingsFilePath().raw());
    33093274                        throw S_OK;
    33103275                    }
     
    33543319                    {
    33553320                        lastAccessError = Utf8StrFmt (
    3356                             tr ("Parent hard disk with UUID {%RTuuid} of the hard disk '%ls' is not found in the media registry ('%ls')"),
     3321                            tr ("Parent hard disk with UUID {%RTuuid} of the hard disk '%ls' is not found in the media registry ('%s')"),
    33573322                            &parentId, m.locationFull.raw(),
    3358                             mVirtualBox->settingsFileName().raw());
     3323                            mVirtualBox->settingsFilePath().raw());
    33593324                        throw S_OK;
    33603325                    }
     
    33833348                    {
    33843349                        lastAccessError = Utf8StrFmt (
    3385                             tr ("Hard disk '%ls' is differencing but it is not associated with any parent hard disk in the media registry ('%ls')"),
     3350                            tr ("Hard disk '%ls' is differencing but it is not associated with any parent hard disk in the media registry ('%s')"),
    33863351                            m.locationFull.raw(),
    3387                             mVirtualBox->settingsFileName().raw());
     3352                            mVirtualBox->settingsFilePath().raw());
    33883353                        throw S_OK;
    33893354                    }
     
    33943359                    {
    33953360                        lastAccessError = Utf8StrFmt (
    3396                             tr ("Parent UUID {%RTuuid} of the hard disk '%ls' does not match UUID {%RTuuid} of its parent hard disk stored in the media registry ('%ls')"),
     3361                            tr ("Parent UUID {%RTuuid} of the hard disk '%ls' does not match UUID {%RTuuid} of its parent hard disk stored in the media registry ('%s')"),
    33973362                            &parentId, m.locationFull.raw(),
    33983363                            mParent->id().raw(),
    3399                             mVirtualBox->settingsFileName().raw());
     3364                            mVirtualBox->settingsFilePath().raw());
    34003365                        throw S_OK;
    34013366                    }
     
    36783643
    36793644/* static */
    3680 DECLCALLBACK(int) HardDisk::vdConfigQuery (void *pvUser, const char *pszName,
    3681                                             char *pszValue, size_t cchValue)
     3645DECLCALLBACK(int) HardDisk::vdConfigQuery(void *pvUser, const char *pszName,
     3646                                          char *pszValue, size_t cchValue)
    36823647{
    36833648    AssertReturn(VALID_PTR (pszValue), VERR_INVALID_POINTER);
     
    36993664        return VERR_CFGM_VALUE_NOT_FOUND;
    37003665
    3701     memcpy (pszValue, value, value.length() + 1);
     3666    memcpy(pszValue, value.c_str(), value.length() + 1);
    37023667
    37033668    return VINF_SUCCESS;
     
    37733738                {
    37743739                    /* ensure the directory exists */
    3775                     rc = VirtualBox::ensureFilePathExists (location);
     3740                    rc = VirtualBox::ensureFilePathExists(location.c_str());
    37763741                    CheckComRCThrowRC (rc);
    37773742
     
    37813746                    that->mm.vdProgress = task->progress;
    37823747
    3783                     vrc = VDCreateBase (hdd, format, location,
    3784                                         task->d.size * _1M,
    3785                                         task->d.variant,
    3786                                         NULL, &geo, &geo, id.raw(),
    3787                                         VD_OPEN_FLAGS_NORMAL,
    3788                                         NULL, that->mm.vdDiskIfaces);
     3748                    vrc = VDCreateBase(hdd,
     3749                                       format.c_str(),
     3750                                       location.c_str(),
     3751                                       task->d.size * _1M,
     3752                                       task->d.variant,
     3753                                       NULL,
     3754                                       &geo,
     3755                                       &geo,
     3756                                       id.raw(),
     3757                                       VD_OPEN_FLAGS_NORMAL,
     3758                                       NULL,
     3759                                       that->mm.vdDiskIfaces);
    37893760
    37903761                    if (RT_FAILURE(vrc))
     
    38833854                try
    38843855                {
    3885                     vrc = VDOpen (hdd, format, location,
    3886                                   VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    3887                                   that->mm.vdDiskIfaces);
     3856                    vrc = VDOpen(hdd,
     3857                                 format.c_str(),
     3858                                 location.c_str(),
     3859                                 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     3860                                 that->mm.vdDiskIfaces);
    38883861                    if (RT_FAILURE(vrc))
    38893862                    {
    3890                         throw setError (E_FAIL,
    3891                             tr ("Could not open the hard disk storage unit '%s'%s"),
    3892                             location.raw(), that->vdError (vrc).raw());
     3863                        throw setError(E_FAIL,
     3864                                       tr("Could not open the hard disk storage unit '%s'%s"),
     3865                                       location.raw(), that->vdError (vrc).raw());
    38933866                    }
    38943867
     
    39023875                    /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to
    39033876                     * be on the safe side. */
    3904                     vrc = VDCreateDiff (hdd, targetFormat, targetLocation,
    3905                                         task->d.variant,
    3906                                         NULL, targetId.raw(),
    3907                                         id.raw(),
    3908                                         VD_OPEN_FLAGS_NORMAL,
    3909                                         target->mm.vdDiskIfaces,
    3910                                         that->mm.vdDiskIfaces);
     3877                    vrc = VDCreateDiff(hdd,
     3878                                       targetFormat.c_str(),
     3879                                       targetLocation.c_str(),
     3880                                       task->d.variant,
     3881                                       NULL,
     3882                                       targetId.raw(),
     3883                                       id.raw(),
     3884                                       VD_OPEN_FLAGS_NORMAL,
     3885                                       target->mm.vdDiskIfaces,
     3886                                       that->mm.vdDiskIfaces);
    39113887
    39123888                    that->mm.vdProgress = NULL;
     
    40574033                        /* open the first image with VDOPEN_FLAGS_INFO because
    40584034                         * it's not necessarily the base one */
    4059                         vrc = VDOpen (hdd, Utf8Str ((*it)->mm.format),
    4060                                       Utf8Str ((*it)->m.locationFull),
    4061                                       it == chain->begin() ?
     4035                        vrc = VDOpen(hdd,
     4036                                     Utf8Str((*it)->mm.format).c_str(),
     4037                                     Utf8Str((*it)->m.locationFull).c_str(),
     4038                                     it == chain->begin() ?
    40624039                                          VD_OPEN_FLAGS_INFO : 0,
    4063                                       (*it)->mm.vdDiskIfaces);
     4040                                     (*it)->mm.vdDiskIfaces);
    40644041                        if (RT_FAILURE(vrc))
    40654042                            throw vrc;
     
    41094086                            {
    41104087                                /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
    4111                                 vrc = VDOpen (hdd, Utf8Str ((*it)->mm.format),
    4112                                               Utf8Str ((*it)->m.locationFull),
    4113                                               VD_OPEN_FLAGS_INFO,
    4114                                               (*it)->mm.vdDiskIfaces);
     4088                                vrc = VDOpen(hdd,
     4089                                             Utf8Str((*it)->mm.format).c_str(),
     4090                                             Utf8Str((*it)->m.locationFull).c_str(),
     4091                                             VD_OPEN_FLAGS_INFO,
     4092                                             (*it)->mm.vdDiskIfaces);
    41154093                                if (RT_FAILURE(vrc))
    41164094                                    throw vrc;
     
    43494327
    43504328                        /** Open all images in read-only mode. */
    4351                         vrc = VDOpen (hdd, Utf8Str ((*it)->mm.format),
    4352                                       Utf8Str ((*it)->m.locationFull),
    4353                                       VD_OPEN_FLAGS_READONLY,
    4354                                       (*it)->mm.vdDiskIfaces);
     4329                        vrc = VDOpen(hdd,
     4330                                     Utf8Str((*it)->mm.format).c_str(),
     4331                                     Utf8Str((*it)->m.locationFull).c_str(),
     4332                                     VD_OPEN_FLAGS_READONLY,
     4333                                     (*it)->mm.vdDiskIfaces);
    43554334                        if (RT_FAILURE(vrc))
    43564335                        {
     
    43954374
    43964375                            /* Open all images in appropriate mode. */
    4397                             vrc = VDOpen (targetHdd, Utf8Str ((*it)->mm.format),
    4398                                           Utf8Str ((*it)->m.locationFull),
    4399                                           ((*it)->m.state == MediaState_LockedWrite) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
    4400                                           (*it)->mm.vdDiskIfaces);
     4376                            vrc = VDOpen(targetHdd,
     4377                                         Utf8Str((*it)->mm.format).c_str(),
     4378                                         Utf8Str((*it)->m.locationFull).c_str(),
     4379                                         ((*it)->m.state == MediaState_LockedWrite) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
     4380                                         (*it)->mm.vdDiskIfaces);
    44014381                            if (RT_FAILURE(vrc))
    44024382                            {
     
    44084388                        }
    44094389
    4410                         vrc = VDCopy (hdd, VD_LAST_IMAGE, targetHdd,
    4411                                       targetFormat,
    4412                                       target->m.state == MediaState_Creating ? targetLocation.raw() : (char *)NULL,
    4413                                       false, 0,
    4414                                       task->d.variant, targetId.raw(), NULL,
    4415                                       target->mm.vdDiskIfaces,
    4416                                       that->mm.vdDiskIfaces);
     4390                        vrc = VDCopy(hdd,
     4391                                     VD_LAST_IMAGE,
     4392                                     targetHdd,
     4393                                     targetFormat.c_str(),
     4394                                     target->m.state == MediaState_Creating ? targetLocation.raw() : (char *)NULL,
     4395                                     false, 0,
     4396                                     task->d.variant, targetId.raw(), NULL,
     4397                                     target->mm.vdDiskIfaces,
     4398                                     that->mm.vdDiskIfaces);
    44174399
    44184400                        that->mm.vdProgress = NULL;
     
    45334515                try
    45344516                {
    4535                     vrc = VDOpen (hdd, format, location,
    4536                                   VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    4537                                   that->mm.vdDiskIfaces);
     4517                    vrc = VDOpen(hdd,
     4518                                 format.c_str(),
     4519                                 location.c_str(),
     4520                                 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     4521                                 that->mm.vdDiskIfaces);
    45384522                    if (RT_SUCCESS(vrc))
    45394523                        vrc = VDClose (hdd, true /* fDelete */);
     
    46014585                {
    46024586                    /* first, delete the storage unit */
    4603                     vrc = VDOpen (hdd, format, location,
    4604                                   VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    4605                                   that->mm.vdDiskIfaces);
     4587                    vrc = VDOpen(hdd,
     4588                                 format.c_str(),
     4589                                 location.c_str(),
     4590                                 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     4591                                 that->mm.vdDiskIfaces);
    46064592                    if (RT_SUCCESS(vrc))
    46074593                        vrc = VDClose (hdd, true /* fDelete */);
     
    46154601
    46164602                    /* next, create it again */
    4617                     vrc = VDOpen (hdd, parentFormat, parentLocation,
    4618                                   VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    4619                                   that->mm.vdDiskIfaces);
     4603                    vrc = VDOpen(hdd,
     4604                                 parentFormat.c_str(),
     4605                                 parentLocation.c_str(),
     4606                                 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     4607                                 that->mm.vdDiskIfaces);
    46204608                    if (RT_FAILURE(vrc))
    46214609                    {
     
    46284616                    that->mm.vdProgress = task->progress;
    46294617
    4630                     vrc = VDCreateDiff (hdd, format, location,
    4631                                         /// @todo use the same image variant as before
    4632                                         VD_IMAGE_FLAGS_NONE,
    4633                                         NULL, id.raw(),
    4634                                         parentId.raw(),
    4635                                         VD_OPEN_FLAGS_NORMAL,
    4636                                         that->mm.vdDiskIfaces,
    4637                                         that->mm.vdDiskIfaces);
     4618                    vrc = VDCreateDiff(hdd,
     4619                                       format.c_str(),
     4620                                       location.c_str(),
     4621                                       /// @todo use the same image variant as before
     4622                                       VD_IMAGE_FLAGS_NONE,
     4623                                       NULL,
     4624                                       id.raw(),
     4625                                       parentId.raw(),
     4626                                       VD_OPEN_FLAGS_NORMAL,
     4627                                       that->mm.vdDiskIfaces,
     4628                                       that->mm.vdDiskIfaces);
    46384629
    46394630                    that->mm.vdProgress = NULL;
     
    47054696
    47064697                        /** Open all images but last in read-only mode. */
    4707                         vrc = VDOpen (hdd, Utf8Str ((*it)->mm.format),
    4708                                       Utf8Str ((*it)->m.locationFull),
    4709                                       (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
    4710                                       (*it)->mm.vdDiskIfaces);
     4698                        vrc = VDOpen(hdd,
     4699                                     Utf8Str((*it)->mm.format).c_str(),
     4700                                     Utf8Str((*it)->m.locationFull).c_str(),
     4701                                     (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
     4702                                     (*it)->mm.vdDiskIfaces);
    47114703                        if (RT_FAILURE(vrc))
    47124704                        {
  • trunk/src/VBox/Main/HostImpl.cpp

    r21885 r22173  
    13451345////////////////////////////////////////////////////////////////////////////////
    13461346
    1347 HRESULT Host::loadSettings (const settings::Key &aGlobal)
    1348 {
    1349     using namespace settings;
    1350 
     1347HRESULT Host::loadSettings(const settings::Host &data)
     1348{
    13511349    AutoCaller autoCaller(this);
    13521350    CheckComRCReturnRC(autoCaller.rc());
     
    13541352    AutoWriteLock alock(this);
    13551353
    1356     AssertReturn(!aGlobal.isNull(), E_FAIL);
    1357 
    13581354    HRESULT rc = S_OK;
    13591355
    13601356#ifdef VBOX_WITH_USB
    1361     Key::List filters = aGlobal.key ("USBDeviceFilters").keys ("DeviceFilter");
    1362     for (Key::List::const_iterator it = filters.begin();
    1363          it != filters.end(); ++ it)
    1364     {
    1365         Bstr name = (*it).stringValue ("name");
    1366         bool active = (*it).value <bool> ("active");
    1367 
    1368         Bstr vendorId = (*it).stringValue ("vendorId");
    1369         Bstr productId = (*it).stringValue ("productId");
    1370         Bstr revision = (*it).stringValue ("revision");
    1371         Bstr manufacturer = (*it).stringValue ("manufacturer");
    1372         Bstr product = (*it).stringValue ("product");
    1373         Bstr serialNumber = (*it).stringValue ("serialNumber");
    1374         Bstr port = (*it).stringValue ("port");
    1375 
    1376         USBDeviceFilterAction_T action;
    1377         action = USBDeviceFilterAction_Ignore;
    1378         const char *actionStr = (*it).stringValue ("action");
    1379         if (strcmp (actionStr, "Ignore") == 0)
    1380             action = USBDeviceFilterAction_Ignore;
    1381         else
    1382         if (strcmp (actionStr, "Hold") == 0)
    1383             action = USBDeviceFilterAction_Hold;
    1384         else
    1385             AssertMsgFailed (("Invalid action: '%s'\n", actionStr));
    1386 
    1387         ComObjPtr<HostUSBDeviceFilter> filterObj;
    1388         filterObj.createObject();
    1389         rc = filterObj->init (this,
    1390                               name, active, vendorId, productId, revision,
    1391                               manufacturer, product, serialNumber, port,
    1392                               action);
    1393         /* error info is set by init() when appropriate */
     1357    for (settings::USBDeviceFiltersList::const_iterator it = data.llUSBDeviceFilters.begin();
     1358         it != data.llUSBDeviceFilters.end();
     1359         ++it)
     1360    {
     1361        const settings::USBDeviceFilter &f = *it;
     1362        ComObjPtr<HostUSBDeviceFilter> pFilter;
     1363        pFilter.createObject();
     1364        rc = pFilter->init(this, f);
    13941365        CheckComRCBreakRC (rc);
    13951366
    1396         mUSBDeviceFilters.push_back (filterObj);
    1397         filterObj->mInList = true;
     1367        mUSBDeviceFilters.push_back(pFilter);
     1368        pFilter->mInList = true;
    13981369
    13991370        /* notify the proxy (only when the filter is active) */
    1400         if (filterObj->data().mActive)
    1401         {
    1402             HostUSBDeviceFilter *flt = filterObj; /* resolve ambiguity */
    1403             flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
     1371        if (pFilter->data().mActive)
     1372        {
     1373            HostUSBDeviceFilter *flt = pFilter; /* resolve ambiguity */
     1374            flt->id() = mUSBProxyService->insertFilter(&pFilter->data().mUSBFilter);
    14041375        }
    14051376    }
     
    14091380}
    14101381
    1411 HRESULT Host::saveSettings (settings::Key &aGlobal)
    1412 {
    1413     using namespace settings;
    1414 
     1382HRESULT Host::saveSettings(settings::Host &data)
     1383{
    14151384    AutoCaller autoCaller(this);
    14161385    CheckComRCReturnRC(autoCaller.rc());
     
    14181387    AutoWriteLock alock(this);
    14191388
    1420     ComAssertRet (!aGlobal.isNull(), E_FAIL);
    1421 
    14221389#ifdef VBOX_WITH_USB
    1423     /* first, delete the entry */
    1424     Key filters = aGlobal.findKey ("USBDeviceFilters");
    1425     if (!filters.isNull())
    1426         filters.zap();
    1427     /* then, recreate it */
    1428     filters = aGlobal.createKey ("USBDeviceFilters");
    1429 
    1430     USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
    1431     while (it != mUSBDeviceFilters.end())
    1432     {
    1433         AutoWriteLock filterLock (*it);
    1434         const HostUSBDeviceFilter::Data &data = (*it)->data();
    1435 
    1436         Key filter = filters.appendKey ("DeviceFilter");
    1437 
    1438         filter.setValue <Bstr> ("name", data.mName);
    1439         filter.setValue <bool> ("active", !!data.mActive);
    1440 
    1441         /* all are optional */
    1442         Bstr str;
    1443         (*it)->COMGETTER (VendorId) (str.asOutParam());
    1444         if (!str.isNull())
    1445             filter.setValue <Bstr> ("vendorId", str);
    1446 
    1447         (*it)->COMGETTER (ProductId) (str.asOutParam());
    1448         if (!str.isNull())
    1449             filter.setValue <Bstr> ("productId", str);
    1450 
    1451         (*it)->COMGETTER (Revision) (str.asOutParam());
    1452         if (!str.isNull())
    1453             filter.setValue <Bstr> ("revision", str);
    1454 
    1455         (*it)->COMGETTER (Manufacturer) (str.asOutParam());
    1456         if (!str.isNull())
    1457             filter.setValue <Bstr> ("manufacturer", str);
    1458 
    1459         (*it)->COMGETTER (Product) (str.asOutParam());
    1460         if (!str.isNull())
    1461             filter.setValue <Bstr> ("product", str);
    1462 
    1463         (*it)->COMGETTER (SerialNumber) (str.asOutParam());
    1464         if (!str.isNull())
    1465             filter.setValue <Bstr> ("serialNumber", str);
    1466 
    1467         (*it)->COMGETTER (Port) (str.asOutParam());
    1468         if (!str.isNull())
    1469             filter.setValue <Bstr> ("port", str);
    1470 
    1471         /* action is mandatory */
    1472         USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;
    1473         (*it)->COMGETTER (Action) (&action);
    1474         if (action == USBDeviceFilterAction_Ignore)
    1475             filter.setStringValue ("action", "Ignore");
    1476         else if (action == USBDeviceFilterAction_Hold)
    1477             filter.setStringValue ("action", "Hold");
    1478         else
    1479             AssertMsgFailed (("Invalid action: %d\n", action));
    1480 
    1481         ++ it;
     1390    data.llUSBDeviceFilters.clear();
     1391
     1392    for (USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
     1393         it != mUSBDeviceFilters.end();
     1394         ++it)
     1395    {
     1396        ComObjPtr<HostUSBDeviceFilter> pFilter = *it;
     1397        settings::USBDeviceFilter f;
     1398        pFilter->saveSettings(f);
     1399        data.llUSBDeviceFilters.push_back(f);
    14821400    }
    14831401#endif /* VBOX_WITH_USB */
  • trunk/src/VBox/Main/MachineImpl.cpp

    r22143 r22173  
    4343#include "USBControllerImpl.h"
    4444#include "HostImpl.h"
    45 #include "SystemPropertiesImpl.h"
    4645#include "SharedFolderImpl.h"
    4746#include "GuestOSTypeImpl.h"
     
    9695// globals
    9796/////////////////////////////////////////////////////////////////////////////
    98 
    99 /**
    100  *  @note The template is NOT completely valid according to VBOX_XML_SCHEMA
    101  *  (when loading a newly created settings file, validation will be turned off)
    102  */
    103 static const char gDefaultMachineConfig[] =
    104 {
    105     "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" RTFILE_LINEFEED
    106     "<!-- Sun VirtualBox Machine Configuration -->" RTFILE_LINEFEED
    107     "<VirtualBox xmlns=\"" VBOX_XML_NAMESPACE "\" "
    108         "version=\"" VBOX_XML_VERSION_FULL "\">" RTFILE_LINEFEED
    109     "</VirtualBox>" RTFILE_LINEFEED
    110 };
    11197
    11298/**
     
    258244        while (thatIt != thatFolders.end())
    259245        {
    260             if ((*it)->name() == (*thatIt)->name() &&
    261                 RTPathCompare (Utf8Str ((*it)->hostPath()),
    262                                Utf8Str ((*thatIt)->hostPath())) == 0)
     246            if (    (*it)->name() == (*thatIt)->name()
     247                 && RTPathCompare(Utf8Str((*it)->hostPath()).c_str(),
     248                                  Utf8Str((*thatIt)->hostPath()).c_str()
     249                                 ) == 0)
    263250            {
    264251                thatFolders.erase (thatIt);
     
    383370 *  @return  Success indicator. if not S_OK, the machine object is invalid
    384371 */
    385 HRESULT Machine::init (VirtualBox *aParent, CBSTR aConfigFile,
    386                        InitMode aMode, CBSTR aName /* = NULL */,
    387                        GuestOSType *aOsType /* = NULL */,
    388                        BOOL aNameSync /* = TRUE */,
    389                        const Guid *aId /* = NULL */)
     372HRESULT Machine::init(VirtualBox *aParent,
     373                      const Utf8Str &strConfigFile,
     374                      InitMode aMode,
     375                      CBSTR aName /* = NULL */,
     376                      GuestOSType *aOsType /* = NULL */,
     377                      BOOL aNameSync /* = TRUE */,
     378                      const Guid *aId /* = NULL */)
    390379{
    391380    LogFlowThisFuncEnter();
    392     LogFlowThisFunc(("aConfigFile='%ls', aMode=%d\n", aConfigFile, aMode));
    393 
    394     AssertReturn(aParent, E_INVALIDARG);
    395     AssertReturn(aConfigFile, E_INVALIDARG);
     381    LogFlowThisFunc (("aConfigFile='%s', aMode=%d\n", strConfigFile.raw(), aMode));
     382
     383    AssertReturn (aParent, E_INVALIDARG);
     384    AssertReturn (!strConfigFile.isEmpty(), E_INVALIDARG);
    396385    AssertReturn(aMode != Init_New || (aName != NULL && *aName != '\0'),
    397386                  E_INVALIDARG);
     
    415404    mData.allocate();
    416405
     406    mData->m_pMachineConfigFile = NULL;
     407
    417408    /* memorize the config file name (as provided) */
    418     mData->mConfigFile = aConfigFile;
     409    mData->m_strConfigFile = strConfigFile;
    419410
    420411    /* get the full file name */
    421     Utf8Str configFileFull;
    422     int vrc = mParent->calculateFullPath (Utf8Str (aConfigFile), configFileFull);
     412    int vrc = mParent->calculateFullPath(strConfigFile, mData->m_strConfigFileFull);
    423413    if (RT_FAILURE(vrc))
    424         return setError (VBOX_E_FILE_ERROR,
    425             tr ("Invalid machine settings file name '%ls' (%Rrc)"),
    426             aConfigFile, vrc);
    427 
    428     mData->mConfigFileFull = configFileFull;
     414        return setError(VBOX_E_FILE_ERROR,
     415                        tr("Invalid machine settings file name '%s' (%Rrc)"),
     416                        strConfigFile.raw(),
     417                        vrc);
    429418
    430419    if (aMode == Init_Registered)
     
    435424         * in loadSettings() */
    436425        unconst(mData->mUuid) = *aId;
     426
     427        // now load the settings from XML:
    437428        rc = registeredInit();
    438429    }
    439430    else
    440431    {
    441         if (aMode == Init_Existing)
    442         {
    443             /* lock the settings file */
    444             rc = lockConfig();
     432        if (aMode == Init_Import)
     433        {
     434            // we're reading the settings file below
    445435        }
    446436        else if (aMode == Init_New)
     
    448438            /* check for the file existence */
    449439            RTFILE f = NIL_RTFILE;
    450             int vrc = RTFileOpen (&f, configFileFull, RTFILE_O_READ);
    451             if (RT_SUCCESS(vrc) || vrc == VERR_SHARING_VIOLATION)
     440            int vrc = RTFileOpen(&f, mData->m_strConfigFileFull.c_str(), RTFILE_O_READ);
     441            if (    RT_SUCCESS(vrc)
     442                 || vrc == VERR_SHARING_VIOLATION
     443               )
    452444            {
    453                 rc = setError (VBOX_E_FILE_ERROR,
    454                     tr ("Machine settings file '%s' already exists"),
    455                     configFileFull.raw());
     445                rc = setError(VBOX_E_FILE_ERROR,
     446                              tr("Machine settings file '%s' already exists"),
     447                              mData->m_strConfigFileFull.raw());
    456448                if (RT_SUCCESS(vrc))
    457                     RTFileClose (f);
     449                    RTFileClose(f);
    458450            }
    459451            else
    460452            {
    461                 if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND)
    462                     rc = setError (VBOX_E_FILE_ERROR,
    463                         tr ("Invalid machine settings file name '%ls' (%Rrc)"),
    464                         mData->mConfigFileFull.raw(), vrc);
     453                if (     vrc != VERR_FILE_NOT_FOUND
     454                      && vrc != VERR_PATH_NOT_FOUND
     455                   )
     456                    rc = setError(VBOX_E_FILE_ERROR,
     457                                  tr("Invalid machine settings file name '%s' (%Rrc)"),
     458                                  mData->m_strConfigFileFull.raw(),
     459                                  vrc);
    465460            }
     461
     462            // create an empty machine config
     463            mData->m_pMachineConfigFile = new settings::MachineConfigFile(NULL);
    466464        }
    467465        else
     
    479477            if (aMode != Init_New)
    480478            {
    481                 rc = loadSettings (false /* aRegistered */);
     479                rc = loadSettings(false /* aRegistered */);
    482480            }
    483481            else
     
    495493                /* initialize the default snapshots folder
    496494                 * (note: depends on the name value set above!) */
    497                 rc = COMSETTER(SnapshotFolder) (NULL);
    498                 AssertComRC (rc);
     495                rc = COMSETTER(SnapshotFolder)(NULL);
     496                AssertComRC(rc);
    499497
    500498                if (aOsType)
     
    571569    AssertReturn(!mData->mAccessible, E_FAIL);
    572570
    573     HRESULT rc = lockConfig();
    574 
    575     if (SUCCEEDED(rc))
    576         rc = initDataAndChildObjects();
     571    HRESULT rc = initDataAndChildObjects();
    577572
    578573    if (SUCCEEDED(rc))
     
    584579        mData->mRegistered = FALSE;
    585580
    586         rc = loadSettings (true /* aRegistered */);
     581        rc = loadSettings(true /* aRegistered */);
    587582
    588583        /* Restore the registered flag (even on failure) */
    589584        mData->mRegistered = TRUE;
    590 
    591         if (FAILED (rc))
    592             unlockConfig();
    593585    }
    594586
     
    610602        /* fetch the current error info */
    611603        mData->mAccessError = com::ErrorInfo();
    612         LogWarning (("Machine {%RTuuid} is inaccessible! [%ls]\n",
    613                      mData->mUuid.raw(),
    614                      mData->mAccessError.getText().raw()));
     604        LogWarning(("Machine {%RTuuid} is inaccessible! [%ls]\n",
     605                    mData->mUuid.raw(),
     606                    mData->mAccessError.getText().raw()));
    615607
    616608        /* rollback all changes */
     
    701693    alock.leave();
    702694
    703     /* make sure the configuration is unlocked */
    704     unlockConfig();
    705 
    706695    if (isModified())
    707696    {
     
    721710}
    722711
     712/**
     713 * Helper to initialize all associated child objects and allocate data
     714 * structures.
     715 *
     716 * This method must be called as a part of the object's initialization procedure
     717 * (usually done in the #init() method).
     718 *
     719 * @note Must be called only from #init() or from #registeredInit().
     720 */
     721HRESULT Machine::initDataAndChildObjects()
     722{
     723    AutoCaller autoCaller (this);
     724    AssertComRCReturnRC (autoCaller.rc());
     725    AssertComRCReturn (autoCaller.state() == InInit ||
     726                       autoCaller.state() == Limited, E_FAIL);
     727
     728    AssertReturn (!mData->mAccessible, E_FAIL);
     729
     730    /* allocate data structures */
     731    mSSData.allocate();
     732    mUserData.allocate();
     733    mHWData.allocate();
     734    mHDData.allocate();
     735    mStorageControllers.allocate();
     736
     737    /* initialize mOSTypeId */
     738    mUserData->mOSTypeId = mParent->getUnknownOSType()->id();
     739
     740    /* create associated BIOS settings object */
     741    unconst (mBIOSSettings).createObject();
     742    mBIOSSettings->init (this);
     743
     744#ifdef VBOX_WITH_VRDP
     745    /* create an associated VRDPServer object (default is disabled) */
     746    unconst (mVRDPServer).createObject();
     747    mVRDPServer->init (this);
     748#endif
     749
     750    /* create an associated DVD drive object */
     751    unconst (mDVDDrive).createObject();
     752    mDVDDrive->init (this);
     753
     754    /* create an associated floppy drive object */
     755    unconst (mFloppyDrive).createObject();
     756    mFloppyDrive->init (this);
     757
     758    /* create associated serial port objects */
     759    for (ULONG slot = 0; slot < RT_ELEMENTS (mSerialPorts); slot ++)
     760    {
     761        unconst (mSerialPorts [slot]).createObject();
     762        mSerialPorts [slot]->init (this, slot);
     763    }
     764
     765    /* create associated parallel port objects */
     766    for (ULONG slot = 0; slot < RT_ELEMENTS (mParallelPorts); slot ++)
     767    {
     768        unconst (mParallelPorts [slot]).createObject();
     769        mParallelPorts [slot]->init (this, slot);
     770    }
     771
     772    /* create the audio adapter object (always present, default is disabled) */
     773    unconst (mAudioAdapter).createObject();
     774    mAudioAdapter->init (this);
     775
     776    /* create the USB controller object (always present, default is disabled) */
     777    unconst (mUSBController).createObject();
     778    mUSBController->init (this);
     779
     780    /* create associated network adapter objects */
     781    for (ULONG slot = 0; slot < RT_ELEMENTS (mNetworkAdapters); slot ++)
     782    {
     783        unconst (mNetworkAdapters [slot]).createObject();
     784        mNetworkAdapters [slot]->init (this, slot);
     785    }
     786
     787    return S_OK;
     788}
     789
     790/**
     791 * Helper to uninitialize all associated child objects and to free all data
     792 * structures.
     793 *
     794 * This method must be called as a part of the object's uninitialization
     795 * procedure (usually done in the #uninit() method).
     796 *
     797 * @note Must be called only from #uninit() or from #registeredInit().
     798 */
     799void Machine::uninitDataAndChildObjects()
     800{
     801    AutoCaller autoCaller (this);
     802    AssertComRCReturnVoid (autoCaller.rc());
     803    AssertComRCReturnVoid (autoCaller.state() == InUninit ||
     804                           autoCaller.state() == Limited);
     805
     806    /* uninit all children using addDependentChild()/removeDependentChild()
     807     * in their init()/uninit() methods */
     808    uninitDependentChildren();
     809
     810    /* tell all our other child objects we've been uninitialized */
     811
     812    for (ULONG slot = 0; slot < RT_ELEMENTS (mNetworkAdapters); slot ++)
     813    {
     814        if (mNetworkAdapters [slot])
     815        {
     816            mNetworkAdapters [slot]->uninit();
     817            unconst (mNetworkAdapters [slot]).setNull();
     818        }
     819    }
     820
     821    if (mUSBController)
     822    {
     823        mUSBController->uninit();
     824        unconst (mUSBController).setNull();
     825    }
     826
     827    if (mAudioAdapter)
     828    {
     829        mAudioAdapter->uninit();
     830        unconst (mAudioAdapter).setNull();
     831    }
     832
     833    for (ULONG slot = 0; slot < RT_ELEMENTS (mParallelPorts); slot ++)
     834    {
     835        if (mParallelPorts [slot])
     836        {
     837            mParallelPorts [slot]->uninit();
     838            unconst (mParallelPorts [slot]).setNull();
     839        }
     840    }
     841
     842    for (ULONG slot = 0; slot < RT_ELEMENTS (mSerialPorts); slot ++)
     843    {
     844        if (mSerialPorts [slot])
     845        {
     846            mSerialPorts [slot]->uninit();
     847            unconst (mSerialPorts [slot]).setNull();
     848        }
     849    }
     850
     851    if (mFloppyDrive)
     852    {
     853        mFloppyDrive->uninit();
     854        unconst (mFloppyDrive).setNull();
     855    }
     856
     857    if (mDVDDrive)
     858    {
     859        mDVDDrive->uninit();
     860        unconst (mDVDDrive).setNull();
     861    }
     862
     863#ifdef VBOX_WITH_VRDP
     864    if (mVRDPServer)
     865    {
     866        mVRDPServer->uninit();
     867        unconst (mVRDPServer).setNull();
     868    }
     869#endif
     870
     871    if (mBIOSSettings)
     872    {
     873        mBIOSSettings->uninit();
     874        unconst (mBIOSSettings).setNull();
     875    }
     876
     877    /* Deassociate hard disks (only when a real Machine or a SnapshotMachine
     878     * instance is uninitialized; SessionMachine instances refer to real
     879     * Machine hard disks). This is necessary for a clean re-initialization of
     880     * the VM after successfully re-checking the accessibility state. Note
     881     * that in case of normal Machine or SnapshotMachine uninitialization (as
     882     * a result of unregistering or discarding the snapshot), outdated hard
     883     * disk attachments will already be uninitialized and deleted, so this
     884     * code will not affect them. */
     885    if (!!mHDData && (mType == IsMachine || mType == IsSnapshotMachine))
     886    {
     887        for (HDData::AttachmentList::const_iterator it =
     888                 mHDData->mAttachments.begin();
     889             it != mHDData->mAttachments.end();
     890             ++ it)
     891        {
     892            HRESULT rc = (*it)->hardDisk()->detachFrom (mData->mUuid,
     893                                                        snapshotId());
     894            AssertComRC(rc);
     895        }
     896    }
     897
     898    if (mType == IsMachine)
     899    {
     900        /* reset some important fields of mData */
     901        mData->mCurrentSnapshot.setNull();
     902        mData->mFirstSnapshot.setNull();
     903    }
     904
     905    /* free data structures (the essential mData structure is not freed here
     906     * since it may be still in use) */
     907    mHDData.free();
     908    mStorageControllers.free();
     909    mHWData.free();
     910    mUserData.free();
     911    mSSData.free();
     912}
     913
    723914// IMachine properties
    724915/////////////////////////////////////////////////////////////////////////////
     
    754945        AutoReinitSpan autoReinitSpan(this);
    755946        AssertReturn(autoReinitSpan.isOk(), E_FAIL);
     947
     948        if (mData->m_pMachineConfigFile)
     949        {
     950            // @todo why are we parsing this several times?
     951            // this is hugely inefficient
     952            delete mData->m_pMachineConfigFile;
     953            mData->m_pMachineConfigFile = NULL;
     954        }
    756955
    757956        rc = registeredInit();
     
    8251024
    8261025    if (!*aName)
    827         return setError (E_INVALIDARG,
    828             tr ("Machine name cannot be empty"));
     1026        return setError(E_INVALIDARG,
     1027                        tr("Machine name cannot be empty"));
    8291028
    8301029    AutoCaller autoCaller(this);
     
    9511150    if (    hwVersion.compare ("1") != 0
    9521151        &&  hwVersion.compare ("2") != 0)
    953         return setError (E_INVALIDARG,
    954             tr ("Invalid hardware version: %ls\n"), aHWVersion);
     1152        return setError(E_INVALIDARG,
     1153                        tr("Invalid hardware version: %ls\n"), aHWVersion);
    9551154
    9561155    AutoCaller autoCaller(this);
     
    9861185{
    9871186    /* check RAM limits */
    988     if (memorySize < MM_RAM_MIN_IN_MB ||
    989         memorySize > MM_RAM_MAX_IN_MB)
    990         return setError (E_INVALIDARG,
    991             tr ("Invalid RAM size: %lu MB (must be in range [%lu, %lu] MB)"),
    992                 memorySize, MM_RAM_MIN_IN_MB, MM_RAM_MAX_IN_MB);
     1187    if (    memorySize < MM_RAM_MIN_IN_MB
     1188         || memorySize > MM_RAM_MAX_IN_MB
     1189       )
     1190        return setError(E_INVALIDARG,
     1191                        tr("Invalid RAM size: %lu MB (must be in range [%lu, %lu] MB)"),
     1192                        memorySize, MM_RAM_MIN_IN_MB, MM_RAM_MAX_IN_MB);
    9931193
    9941194    AutoCaller autoCaller(this);
     
    10241224{
    10251225    /* check RAM limits */
    1026     if (CPUCount < SchemaDefs::MinCPUCount ||
    1027         CPUCount > SchemaDefs::MaxCPUCount)
    1028         return setError (E_INVALIDARG,
    1029             tr ("Invalid virtual CPU count: %lu (must be in range [%lu, %lu])"),
    1030                 CPUCount, SchemaDefs::MinCPUCount, SchemaDefs::MaxCPUCount);
     1226    if (    CPUCount < SchemaDefs::MinCPUCount
     1227         || CPUCount > SchemaDefs::MaxCPUCount
     1228       )
     1229        return setError(E_INVALIDARG,
     1230                        tr("Invalid virtual CPU count: %lu (must be in range [%lu, %lu])"),
     1231                        CPUCount, SchemaDefs::MinCPUCount, SchemaDefs::MaxCPUCount);
    10311232
    10321233    AutoCaller autoCaller(this);
     
    10641265    if (memorySize < SchemaDefs::MinGuestVRAM ||
    10651266        memorySize > SchemaDefs::MaxGuestVRAM)
    1066         return setError (E_INVALIDARG,
    1067             tr ("Invalid VRAM size: %lu MB (must be in range [%lu, %lu] MB)"),
    1068                 memorySize, SchemaDefs::MinGuestVRAM, SchemaDefs::MaxGuestVRAM);
     1267        return setError(E_INVALIDARG,
     1268                        tr("Invalid VRAM size: %lu MB (must be in range [%lu, %lu] MB)"),
     1269                        memorySize, SchemaDefs::MinGuestVRAM, SchemaDefs::MaxGuestVRAM);
    10691270
    10701271    AutoCaller autoCaller(this);
     
    11031304    /* check limits */
    11041305    if (memoryBalloonSize >= VMMDEV_MAX_MEMORY_BALLOON (mHWData->mMemorySize))
    1105         return setError (E_INVALIDARG,
    1106             tr ("Invalid memory balloon size: %lu MB (must be in range [%lu, %lu] MB)"),
    1107                 memoryBalloonSize, 0, VMMDEV_MAX_MEMORY_BALLOON (mHWData->mMemorySize));
     1306        return setError(E_INVALIDARG,
     1307                        tr("Invalid memory balloon size: %lu MB (must be in range [%lu, %lu] MB)"),
     1308                        memoryBalloonSize, 0, VMMDEV_MAX_MEMORY_BALLOON (mHWData->mMemorySize));
    11081309
    11091310    AutoCaller autoCaller(this);
     
    12411442    /* make sure monitor count is a sensible number */
    12421443    if (monitorCount < 1 || monitorCount > SchemaDefs::MaxGuestMonitors)
    1243         return setError (E_INVALIDARG,
    1244             tr ("Invalid monitor count: %lu (must be in range [%lu, %lu])"),
    1245                 monitorCount, 1, SchemaDefs::MaxGuestMonitors);
     1444        return setError(E_INVALIDARG,
     1445                        tr("Invalid monitor count: %lu (must be in range [%lu, %lu])"),
     1446                        monitorCount, 1, SchemaDefs::MaxGuestMonitors);
    12461447
    12471448    AutoCaller autoCaller(this);
     
    14381639
    14391640    if (!mData->mCurrentSnapshot.isNull())
    1440         return setError (E_FAIL,
    1441             tr ("The snapshot folder of a machine with snapshots cannot "
    1442                 "be changed (please discard all snapshots first)"));
     1641        return setError(E_FAIL,
     1642                        tr("The snapshot folder of a machine with snapshots cannot be changed (please discard all snapshots first)"));
    14431643
    14441644    Utf8Str snapshotFolder = aSnapshotFolder;
     
    14591659    }
    14601660
    1461     int vrc = calculateFullPath (snapshotFolder, snapshotFolder);
     1661    int vrc = calculateFullPath(snapshotFolder, snapshotFolder);
    14621662    if (RT_FAILURE(vrc))
    1463         return setError (E_FAIL,
    1464             tr ("Invalid snapshot folder '%ls' (%Rrc)"),
    1465                 aSnapshotFolder, vrc);
     1663        return setError(E_FAIL,
     1664                        tr("Invalid snapshot folder '%ls' (%Rrc)"),
     1665                        aSnapshotFolder, vrc);
    14661666
    14671667    mUserData.backup();
     
    15861786    AutoReadLock alock(this);
    15871787
    1588     mData->mConfigFileFull.cloneTo(aFilePath);
    1589     return S_OK;
    1590 }
    1591 
    1592 STDMETHODIMP Machine::
    1593 COMGETTER(SettingsFileVersion) (BSTR *aSettingsFileVersion)
    1594 {
    1595     CheckComArgOutPointerValid(aSettingsFileVersion);
    1596 
    1597     AutoCaller autoCaller(this);
    1598     CheckComRCReturnRC(autoCaller.rc());
    1599 
    1600     AutoReadLock alock(this);
    1601 
    1602     mData->mSettingsFileVersion.cloneTo(aSettingsFileVersion);
     1788    mData->m_strConfigFileFull.cloneTo(aFilePath);
    16031789    return S_OK;
    16041790}
     
    16161802    CheckComRCReturnRC(rc);
    16171803
    1618     if (!isConfigLocked())
    1619     {
    1620         /*
    1621          *  if we're ready and isConfigLocked() is FALSE then it means
    1622          *  that no config file exists yet, so always return TRUE
    1623          */
     1804    if (mData->mInitMode == Init_New)
     1805          /*
     1806           *  if this is a new machine then no config file exists yet, so always return TRUE
     1807           */
    16241808        *aModified = TRUE;
    1625     }
    16261809    else
    1627     {
    16281810        *aModified = isModified();
    1629     }
    16301811
    16311812    return S_OK;
     
    17891970}
    17901971
    1791 STDMETHODIMP
    1792 Machine::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders))
     1972STDMETHODIMP Machine::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders))
    17931973{
    17941974    CheckComArgOutSafeArrayPointerValid(aSharedFolders);
     
    18051985}
    18061986
    1807 STDMETHODIMP
    1808 Machine::COMGETTER(ClipboardMode) (ClipboardMode_T *aClipboardMode)
     1987STDMETHODIMP Machine::COMGETTER(ClipboardMode) (ClipboardMode_T *aClipboardMode)
    18091988{
    18101989    CheckComArgOutPointerValid(aClipboardMode);
     
    18932072{
    18942073    if (aPosition < 1 || aPosition > SchemaDefs::MaxBootPosition)
    1895         return setError (E_INVALIDARG,
    1896             tr ("Invalid boot position: %lu (must be in range [1, %lu])"),
    1897                 aPosition, SchemaDefs::MaxBootPosition);
     2074        return setError(E_INVALIDARG,
     2075                        tr ("Invalid boot position: %lu (must be in range [1, %lu])"),
     2076                        aPosition, SchemaDefs::MaxBootPosition);
    18982077
    18992078    if (aDevice == DeviceType_USB)
    1900         return setError (E_NOTIMPL,
    1901             tr ("Booting from USB device is currently not supported"));
     2079        return setError(E_NOTIMPL,
     2080                        tr("Booting from USB device is currently not supported"));
    19022081
    19032082    AutoCaller autoCaller(this);
     
    19182097{
    19192098    if (aPosition < 1 || aPosition > SchemaDefs::MaxBootPosition)
    1920         return setError (E_INVALIDARG,
    1921             tr ("Invalid boot position: %lu (must be in range [1, %lu])"),
    1922                 aPosition, SchemaDefs::MaxBootPosition);
     2099        return setError(E_INVALIDARG,
     2100                       tr("Invalid boot position: %lu (must be in range [1, %lu])"),
     2101                       aPosition, SchemaDefs::MaxBootPosition);
    19232102
    19242103    AutoCaller autoCaller(this);
     
    19362115                                     LONG aDevice)
    19372116{
    1938     LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%ld aDevice=%ld\n",
     2117    LogFlowThisFunc (("aControllerName=\"%ls\" aControllerPort=%ld aDevice=%ld\n",
    19392118                     aControllerName, aControllerPort, aDevice));
    19402119
     
    19932172        ComObjPtr<HardDisk> hd = (*it)->hardDisk();
    19942173        AutoReadLock hdLock (hd);
    1995         return setError (VBOX_E_OBJECT_IN_USE,
    1996             tr ("Hard disk '%ls' is already attached to device slot %d on "
    1997                 "port %d of controller '%ls' of this virtual machine"),
    1998             hd->locationFull().raw(), aDevice, aControllerPort, aControllerName);
     2174        return setError(VBOX_E_OBJECT_IN_USE,
     2175                        tr ("Hard disk '%ls' is already attached to device slot %d on port %d of controller '%ls' of this virtual machine"),
     2176                        hd->locationFull().raw(), aDevice, aControllerPort, aControllerName);
    19992177    }
    20002178
     
    20162194            mHDData->mAttachments.end())
    20172195    {
    2018         return setError (VBOX_E_OBJECT_IN_USE,
    2019             tr ("Hard disk '%ls' is already attached to this virtual machine"),
    2020             hd->locationFull().raw());
     2196        return setError(VBOX_E_OBJECT_IN_USE,
     2197                        tr("Hard disk '%ls' is already attached to this virtual machine"),
     2198                        hd->locationFull().raw());
    20212199    }
    20222200
     
    23162494
    23172495    if (it == mHDData->mAttachments.end())
    2318         return setError (VBOX_E_OBJECT_NOT_FOUND,
    2319             tr ("No hard disk attached to device slot %d on port %d of controller '%ls'"),
    2320             aDevice, aControllerPort, aControllerName);
     2496        return setError(VBOX_E_OBJECT_NOT_FOUND,
     2497                        tr("No hard disk attached to device slot %d on port %d of controller '%ls'"),
     2498                        aDevice, aControllerPort, aControllerName);
    23212499
    23222500    ComObjPtr<HardDiskAttachment> hda = *it;
     
    23992577    AutoReadLock alock(this);
    24002578
    2401     mNetworkAdapters [slot].queryInterfaceTo(adapter);
    2402 
    2403     return S_OK;
    2404 }
    2405 
    2406 /**
    2407  *  @note Locks this object for reading.
    2408  */
    2409 STDMETHODIMP Machine::GetNextExtraDataKey (IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue)
    2410 {
    2411     CheckComArgOutPointerValid(aNextKey);
    2412 
    2413     AutoCaller autoCaller(this);
    2414     CheckComRCReturnRC(autoCaller.rc());
    2415 
    2416     /* start with nothing found */
    2417     Bstr("").cloneTo(aNextKey);
    2418     if (aNextValue)
    2419         Bstr("").cloneTo(aNextValue);
    2420 
    2421     /* if we're ready and isConfigLocked() is FALSE then it means
    2422      * that no config file exists yet, so return shortly */
    2423     if (!isConfigLocked())
    2424         return S_OK;
    2425 
    2426     HRESULT rc = S_OK;
    2427 
    2428     Bstr bstrInKey(aKey);
    2429 
    2430     /* serialize file access (prevent writes) */
    2431     AutoReadLock alock(this);
    2432 
    2433     try
    2434     {
    2435         using namespace settings;
    2436         using namespace xml;
    2437 
    2438         /* load the settings file (we don't reuse the existing handle but
    2439          * request a new one to allow for concurrent multithreaded reads) */
    2440         File file (File::Mode_Read, Utf8Str (mData->mConfigFileFull));
    2441         XmlTreeBackend tree;
    2442 
    2443         rc = VirtualBox::loadSettingsTree_Again (tree, file);
    2444         CheckComRCReturnRC(rc);
    2445 
    2446         Key machineNode = tree.rootKey().key ("Machine");
    2447         Key extraDataNode = machineNode.findKey ("ExtraData");
    2448 
    2449         if (!extraDataNode.isNull())
    2450         {
    2451             Key::List items = extraDataNode.keys ("ExtraDataItem");
    2452             if (items.size())
    2453             {
    2454                 for (Key::List::const_iterator it = items.begin();
    2455                      it != items.end(); ++ it)
    2456                 {
    2457                     Bstr key = (*it).stringValue ("name");
    2458 
    2459                     /* if we're supposed to return the first one */
    2460                     if (bstrInKey.isEmpty())
    2461                     {
    2462                         key.cloneTo(aNextKey);
    2463                         if (aNextValue)
    2464                         {
    2465                             Bstr val = (*it).stringValue ("value");
    2466                             val.cloneTo(aNextValue);
    2467                         }
    2468                         return S_OK;
    2469                     }
    2470 
    2471                     /* did we find the key we're looking for? */
    2472                     if (key == bstrInKey)
    2473                     {
    2474                         ++ it;
    2475                         /* is there another item? */
    2476                         if (it != items.end())
    2477                         {
    2478                             Bstr key = (*it).stringValue ("name");
    2479                             key.cloneTo(aNextKey);
    2480                             if (aNextValue)
    2481                             {
    2482                                 Bstr val = (*it).stringValue ("value");
    2483                                 val.cloneTo(aNextValue);
    2484                             }
    2485                         }
    2486                         /* else it's the last one, arguments are already NULL */
    2487                         return S_OK;
    2488                     }
    2489                 }
    2490             }
    2491         }
    2492 
    2493         /* Here we are when a) there are no items at all or b) there are items
    2494          * but none of them equals the requested non-NULL key. b) is an
    2495          * error as well as a) if the key is non-NULL. When the key is NULL
    2496          * (which is the case only when there are no items), we just fall
    2497          * through to return NULLs and S_OK. */
    2498 
    2499         if (!bstrInKey.isEmpty())
    2500             return setError (VBOX_E_OBJECT_NOT_FOUND,
    2501                 tr ("Could not find the extra data key '%ls'"), bstrInKey.raw());
    2502     }
    2503     catch (...)
    2504     {
    2505         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    2506     }
    2507 
    2508     return rc;
    2509 }
    2510 
    2511 /**
    2512  *  @note Locks this object for reading.
    2513  */
    2514 STDMETHODIMP Machine::GetExtraData (IN_BSTR aKey, BSTR *aValue)
    2515 {
    2516     CheckComArgNotNull (aKey);
     2579    mNetworkAdapters[slot].queryInterfaceTo(adapter);
     2580
     2581    return S_OK;
     2582}
     2583
     2584STDMETHODIMP Machine::GetExtraDataKeys(ComSafeArrayOut(BSTR, aKeys))
     2585{
     2586    if (ComSafeArrayOutIsNull(aKeys))
     2587        return E_POINTER;
     2588
     2589    AutoCaller autoCaller (this);
     2590    CheckComRCReturnRC (autoCaller.rc());
     2591
     2592    AutoReadLock alock (this);
     2593
     2594    com::SafeArray<BSTR> saKeys(mData->m_pMachineConfigFile->mapExtraDataItems.size());
     2595    int i = 0;
     2596    for (settings::ExtraDataItemsMap::const_iterator it = mData->m_pMachineConfigFile->mapExtraDataItems.begin();
     2597         it != mData->m_pMachineConfigFile->mapExtraDataItems.end();
     2598         ++it, ++i)
     2599    {
     2600        const Utf8Str &strKey = it->first;
     2601        strKey.cloneTo(&saKeys[i]);
     2602    }
     2603    saKeys.detachTo(ComSafeArrayOutArg(aKeys));
     2604
     2605    return S_OK;
     2606  }
     2607
     2608  /**
     2609   *  @note Locks this object for reading.
     2610   */
     2611STDMETHODIMP Machine::GetExtraData(IN_BSTR aKey,
     2612                                   BSTR *aValue)
     2613{
     2614    CheckComArgNotNull(aKey);
    25172615    CheckComArgOutPointerValid(aValue);
    25182616
    2519     AutoCaller autoCaller(this);
    2520     CheckComRCReturnRC(autoCaller.rc());
    2521 
    2522     /* serialize file access (prevent writes) */
    2523     AutoReadLock alock(this);
     2617    AutoCaller autoCaller (this);
     2618    CheckComRCReturnRC (autoCaller.rc());
    25242619
    25252620    /* start with nothing found */
    25262621    Bstr("").cloneTo(aValue);
    25272622
    2528     /* if we're ready and isConfigLocked() is FALSE then it means
    2529      * that no config file exists yet, so return shortly */
    2530     if (!isConfigLocked())
    2531         return S_OK;
    2532 
    2533     Utf8Str val;
    2534     HRESULT rc = getExtraData(Utf8Str(aKey), val);
    2535     if (SUCCEEDED(rc))
    2536         val.cloneTo(aValue);
    2537 
    2538     return rc;
    2539 }
    2540 
    2541 HRESULT Machine::getExtraData(const Utf8Str &aKey, Utf8Str &aValue)
    2542 {
    2543     HRESULT rc = S_OK;
    2544 
    2545     try
    2546     {
    2547         using namespace settings;
    2548         using namespace xml;
    2549 
    2550         /* load the settings file (we don't reuse the existing handle but
    2551          * request a new one to allow for concurrent multithreaded reads) */
    2552         File file (File::Mode_Read, Utf8Str (mData->mConfigFileFull));
    2553         XmlTreeBackend tree;
    2554 
    2555         rc = VirtualBox::loadSettingsTree_Again (tree, file);
    2556         CheckComRCReturnRC(rc);
    2557 
    2558         Key machineNode = tree.rootKey().key ("Machine");
    2559         Key extraDataNode = machineNode.findKey ("ExtraData");
    2560 
    2561         if (!extraDataNode.isNull())
    2562         {
    2563             /* check if the key exists */
    2564             Key::List items = extraDataNode.keys ("ExtraDataItem");
    2565             for (Key::List::const_iterator it = items.begin();
    2566                  it != items.end(); ++ it)
    2567             {
    2568                 if (aKey == (*it).stringValue ("name"))
    2569                 {
    2570                     aValue = (*it).stringValue ("value");
    2571                     break;
    2572                 }
    2573             }
    2574         }
    2575     }
    2576     catch (...)
    2577     {
    2578         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    2579     }
    2580 
    2581     return rc;
    2582 }
    2583 
    2584 /**
    2585  *  @note Locks mParent for writing + this object for writing.
    2586  */
    2587 STDMETHODIMP Machine::SetExtraData (IN_BSTR aKey, IN_BSTR aValue)
    2588 {
    2589     CheckComArgNotNull (aKey);
    2590 
    2591     AutoCaller autoCaller(this);
    2592     CheckComRCReturnRC(autoCaller.rc());
    2593 
    2594     /* VirtualBox::onExtraDataCanChange() and saveSettings() need mParent
    2595      * lock (saveSettings() needs a write one). This object's write lock is
    2596      * also necessary to serialize file access (prevent concurrent reads and
    2597      * writes). */
    2598     AutoMultiWriteLock2 alock (mParent, this);
    2599 
    2600     if (mType == IsSnapshotMachine)
    2601     {
    2602         HRESULT rc = checkStateDependency(MutableStateDep);
    2603         CheckComRCReturnRC(rc);
    2604     }
     2623    AutoReadLock alock (this);
     2624
     2625    settings::ExtraDataItemsMap::const_iterator it = mData->m_pMachineConfigFile->mapExtraDataItems.find(Utf8Str(aKey));
     2626    if (it != mData->m_pMachineConfigFile->mapExtraDataItems.end())
     2627    {
     2628        // found:
     2629        const Utf8Str &strValue = it->second;
     2630        strValue.cloneTo(aValue);
     2631    }
     2632
     2633    return S_OK;
     2634}
     2635
     2636  /**
     2637   *  @note Locks mParent for writing + this object for writing.
     2638   */
     2639STDMETHODIMP Machine::SetExtraData(IN_BSTR aKey, IN_BSTR aValue)
     2640{
     2641    CheckComArgNotNull(aKey);
     2642
     2643    AutoCaller autoCaller (this);
     2644    CheckComRCReturnRC (autoCaller.rc());
    26052645
    26062646    Bstr val;
     
    26102650        val = aValue;
    26112651
    2612 
    2613     bool changed = false;
    2614     HRESULT rc = S_OK;
    2615 
    2616     /* If we're ready and isConfigLocked() is FALSE then it means that no
    2617      * config file exists yet, so call saveSettings() to create one. */
    2618     if (!isConfigLocked())
    2619     {
    2620         rc = saveSettings();
    2621         CheckComRCReturnRC(rc);
    2622     }
    2623 
    2624     try
    2625     {
    2626         using namespace settings;
    2627         using namespace xml;
    2628 
    2629         /* load the settings file */
    2630         File file (mData->mHandleCfgFile, Utf8Str (mData->mConfigFileFull));
    2631         XmlTreeBackend tree;
    2632 
    2633         rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
    2634         CheckComRCReturnRC(rc);
    2635 
    2636         const Utf8Str key = aKey;
    2637         Bstr oldVal("");
    2638 
    2639         Key machineNode = tree.rootKey().key ("Machine");
    2640         Key extraDataNode = machineNode.createKey ("ExtraData");
    2641         Key extraDataItemNode;
    2642 
    2643         Key::List items = extraDataNode.keys ("ExtraDataItem");
    2644         for (Key::List::const_iterator it = items.begin();
    2645              it != items.end(); ++ it)
    2646         {
    2647             if (key == (*it).stringValue ("name"))
    2648             {
    2649                 extraDataItemNode = *it;
    2650                 oldVal = (*it).stringValue ("value");
    2651                 break;
    2652             }
    2653         }
    2654 
    2655         /* When no key is found, oldVal is empty string */
    2656         changed = oldVal != val;
    2657 
    2658         if (changed)
    2659         {
    2660             /* ask for permission from all listeners */
    2661             Bstr error;
    2662             if (!mParent->onExtraDataCanChange (mData->mUuid, aKey, val, error))
    2663             {
    2664                 const char *sep = error.isEmpty() ? "" : ": ";
    2665                 CBSTR err = error.isNull() ? (CBSTR) L"" : error.raw();
    2666                 LogWarningFunc (("Someone vetoed! Change refused%s%ls\n",
    2667                                  sep, err));
    2668                 return setError (E_ACCESSDENIED,
    2669                     tr ("Could not set extra data because someone refused "
    2670                         "the requested change of '%ls' to '%ls'%s%ls"),
    2671                     aKey, val.raw(), sep, err);
    2672             }
    2673 
    2674             if (!val.isEmpty())
    2675             {
    2676                 if (extraDataItemNode.isNull())
    2677                 {
    2678                     extraDataItemNode = extraDataNode.appendKey ("ExtraDataItem");
    2679                     extraDataItemNode.setStringValue ("name", key);
    2680                 }
    2681                 extraDataItemNode.setStringValue ("value", Utf8Str (aValue));
    2682             }
    2683             else
    2684             {
    2685                 /* an old value does for sure exist here (XML schema
    2686                  * guarantees that "value" may not absent in the
    2687                  * <ExtraDataItem> element) */
    2688                 Assert (!extraDataItemNode.isNull());
    2689                 extraDataItemNode.zap();
    2690             }
    2691 
    2692             /* save settings on success */
    2693             rc = VirtualBox::saveSettingsTree (tree, file,
    2694                                                mData->mSettingsFileVersion);
    2695             CheckComRCReturnRC(rc);
    2696         }
    2697     }
    2698     catch (...)
    2699     {
    2700         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     2652    Utf8Str strKey(aKey);
     2653    Bstr oldVal("");
     2654
     2655    /* VirtualBox::onExtraDataCanChange() and saveSettings() need mParent
     2656     * lock (saveSettings() needs a write one). This object's write lock is
     2657     * also necessary to serialize file access (prevent concurrent reads and
     2658     * writes). */
     2659    AutoMultiWriteLock2 alock(mParent, this);
     2660
     2661    if (mType == IsSnapshotMachine)
     2662    {
     2663        HRESULT rc = checkStateDependency(MutableStateDep);
     2664        CheckComRCReturnRC (rc);
     2665    }
     2666
     2667    settings::ExtraDataItemsMap::const_iterator it = mData->m_pMachineConfigFile->mapExtraDataItems.find(strKey);
     2668    if (it != mData->m_pMachineConfigFile->mapExtraDataItems.end())
     2669    {
     2670        // key exists:
     2671        const Utf8Str &strValue = it->second;
     2672        oldVal = strValue;
     2673    }
     2674
     2675    bool fChanged = (oldVal != val);
     2676    if (fChanged)
     2677    {
     2678        /* ask for permission from all listeners */
     2679        Bstr error;
     2680        if (!mParent->onExtraDataCanChange(mData->mUuid, aKey, val, error))
     2681        {
     2682            const char *sep = error.isEmpty() ? "" : ": ";
     2683            CBSTR err = error.isNull() ? (CBSTR) L"" : error.raw();
     2684            LogWarningFunc(("Someone vetoed! Change refused%s%ls\n",
     2685                            sep, err));
     2686            return setError(E_ACCESSDENIED,
     2687                            tr("Could not set extra data because someone refused the requested change of '%ls' to '%ls'%s%ls"),
     2688                            aKey,
     2689                            val.raw(),
     2690                            sep,
     2691                            err);
     2692        }
     2693
     2694        mData->m_pMachineConfigFile->mapExtraDataItems[strKey] = val;
     2695
     2696        /* save settings on success */
     2697        HRESULT rc = saveSettings();
     2698        CheckComRCReturnRC (rc);
    27012699    }
    27022700
    27032701    /* fire a notification */
    2704     if (SUCCEEDED(rc) && changed)
    2705         mParent->onExtraDataChange (mData->mUuid, aKey, aValue);
    2706 
    2707     return rc;
     2702    if (fChanged)
     2703        mParent->onExtraDataChange(mData->mUuid, aKey, aValue);
     2704
     2705    return S_OK;
    27082706}
    27092707
     
    27142712
    27152713    /* saveSettings() needs mParent lock */
    2716     AutoMultiWriteLock2 alock (mParent, this);
     2714    AutoMultiWriteLock2 alock(mParent, this);
    27172715
    27182716    /* when there was auto-conversion, we want to save the file even if
    27192717     * the VM is saved */
    2720     StateDependency dep = mData->mSettingsFileVersion != VBOX_XML_VERSION_FULL ?
    2721         MutableOrSavedStateDep : MutableStateDep;
    2722 
    2723     HRESULT rc = checkStateDependency(dep);
     2718    HRESULT rc = checkStateDependency(MutableStateDep);
    27242719    CheckComRCReturnRC(rc);
    27252720
    27262721    /* the settings file path may never be null */
    2727     ComAssertRet (mData->mConfigFileFull, E_FAIL);
    2728 
    2729     /* save all VM data excluding snapshots */
    2730     return saveSettings();
    2731 }
    2732 
    2733 STDMETHODIMP Machine::SaveSettingsWithBackup (BSTR *aBakFileName)
    2734 {
    2735     CheckComArgOutPointerValid(aBakFileName);
    2736 
    2737     AutoCaller autoCaller(this);
    2738     CheckComRCReturnRC(autoCaller.rc());
    2739 
    2740     /* saveSettings() needs mParent lock */
    2741     AutoMultiWriteLock2 alock (mParent, this);
    2742 
    2743     /* when there was auto-conversion, we want to save the file even if
    2744      * the VM is saved */
    2745     StateDependency dep = mData->mSettingsFileVersion != VBOX_XML_VERSION_FULL ?
    2746         MutableOrSavedStateDep : MutableStateDep;
    2747 
    2748     HRESULT rc = checkStateDependency(dep);
    2749     CheckComRCReturnRC(rc);
    2750 
    2751     /* the settings file path may never be null */
    2752     ComAssertRet (mData->mConfigFileFull, E_FAIL);
    2753 
    2754     /* perform backup only when there was auto-conversion */
    2755     if (mData->mSettingsFileVersion != VBOX_XML_VERSION_FULL)
    2756     {
    2757         Bstr bakFileName;
    2758 
    2759         HRESULT rc = VirtualBox::backupSettingsFile (mData->mConfigFileFull,
    2760                                                      mData->mSettingsFileVersion,
    2761                                                      bakFileName);
    2762         CheckComRCReturnRC(rc);
    2763 
    2764         bakFileName.cloneTo(aBakFileName);
    2765     }
     2722    ComAssertRet(!mData->m_strConfigFileFull.isEmpty(), E_FAIL);
    27662723
    27672724    /* save all VM data excluding snapshots */
     
    27992756
    28002757    if (mData->mRegistered)
    2801         return setError (VBOX_E_INVALID_VM_STATE,
    2802             tr ("Cannot delete settings of a registered machine"));
     2758        return setError(VBOX_E_INVALID_VM_STATE,
     2759                        tr("Cannot delete settings of a registered machine"));
    28032760
    28042761    /* delete the settings only when the file actually exists */
    2805     if (isConfigLocked())
    2806     {
    2807         unlockConfig();
    2808         int vrc = RTFileDelete (Utf8Str (mData->mConfigFileFull));
     2762    if (mData->m_pMachineConfigFile->fileExists())
     2763    {
     2764        int vrc = RTFileDelete(mData->m_strConfigFileFull.c_str());
    28092765        if (RT_FAILURE(vrc))
    2810             return setError (VBOX_E_IPRT_ERROR,
    2811                 tr ("Could not delete the settings file '%ls' (%Rrc)"),
    2812                 mData->mConfigFileFull.raw(), vrc);
     2766            return setError(VBOX_E_IPRT_ERROR,
     2767                            tr("Could not delete the settings file '%s' (%Rrc)"),
     2768                            mData->m_strConfigFileFull.raw(),
     2769                            vrc);
    28132770
    28142771        /* delete the Logs folder, nothing important should be left
     
    28162773         * some private files there that we don't want to delete) */
    28172774        Utf8Str logFolder;
    2818         getLogFolder (logFolder);
     2775        getLogFolder(logFolder);
    28192776        Assert(logFolder.length());
    2820         if (RTDirExists(logFolder))
     2777        if (RTDirExists(logFolder.c_str()))
    28212778        {
    28222779            /* Delete all VBox.log[.N] files from the Logs folder
     
    28242781             * Console::powerUpThread()). Also, delete the VBox.png[.N]
    28252782             * files that may have been created by the GUI. */
    2826             Utf8Str log = Utf8StrFmt ("%s/VBox.log", logFolder.raw());
    2827             RTFileDelete (log);
    2828             log = Utf8StrFmt ("%s/VBox.png", logFolder.raw());
    2829             RTFileDelete (log);
     2783            Utf8Str log = Utf8StrFmt("%s/VBox.log", logFolder.raw());
     2784            RTFileDelete(log.c_str());
     2785            log = Utf8StrFmt("%s/VBox.png", logFolder.raw());
     2786            RTFileDelete(log.c_str());
    28302787            for (int i = 3; i >= 0; i--)
    28312788            {
    2832                 log = Utf8StrFmt ("%s/VBox.log.%d", logFolder.raw(), i);
    2833                 RTFileDelete (log);
    2834                 log = Utf8StrFmt ("%s/VBox.png.%d", logFolder.raw(), i);
    2835                 RTFileDelete (log);
     2789                log = Utf8StrFmt("%s/VBox.log.%d", logFolder.raw(), i);
     2790                RTFileDelete(log.c_str());
     2791                log = Utf8StrFmt("%s/VBox.png.%d", logFolder.raw(), i);
     2792                RTFileDelete(log.c_str());
    28362793            }
    28372794
    2838             RTDirRemove (logFolder);
     2795            RTDirRemove(logFolder.c_str());
    28392796        }
    28402797
     
    28442801        Utf8Str snapshotFolder(mUserData->mSnapshotFolderFull);
    28452802        Assert(snapshotFolder.length());
    2846         if (RTDirExists(snapshotFolder))
    2847             RTDirRemove(snapshotFolder);
     2803        if (RTDirExists(snapshotFolder.c_str()))
     2804            RTDirRemove(snapshotFolder.c_str());
    28482805
    28492806        /* delete the directory that contains the settings file, but only
     
    28522809        {
    28532810            Utf8Str settingsDir;
    2854             if (isInOwnDir (&settingsDir))
    2855                 RTDirRemove (settingsDir);
     2811            if (isInOwnDir(&settingsDir))
     2812                RTDirRemove(settingsDir.c_str());
    28562813        }
    28572814    }
     
    29042861}
    29052862
    2906 STDMETHODIMP
    2907 Machine::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable)
    2908 {
    2909     CheckComArgNotNull (aName);
    2910     CheckComArgNotNull (aHostPath);
     2863STDMETHODIMP Machine::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable)
     2864{
     2865    CheckComArgNotNull(aName);
     2866    CheckComArgNotNull(aHostPath);
    29112867
    29122868    AutoCaller autoCaller(this);
     
    29212877    rc = findSharedFolder (aName, sharedFolder, false /* aSetError */);
    29222878    if (SUCCEEDED(rc))
    2923         return setError (VBOX_E_OBJECT_IN_USE,
    2924             tr ("Shared folder named '%ls' already exists"), aName);
     2879        return setError(VBOX_E_OBJECT_IN_USE,
     2880                        tr("Shared folder named '%ls' already exists"),
     2881                        aName);
    29252882
    29262883    sharedFolder.createObject();
     
    29792936
    29802937        if (mData->mSession.mState != SessionState_Open)
    2981             return setError (VBOX_E_INVALID_VM_STATE,
    2982                 tr ("Machine session is not open (session state: %d)"),
    2983                 mData->mSession.mState);
     2938            return setError(VBOX_E_INVALID_VM_STATE,
     2939                            tr("Machine session is not open (session state: %d)"),
     2940                            mData->mSession.mState);
    29842941
    29852942        directControl = mData->mSession.mDirectControl;
     
    30062963
    30072964        if (mData->mSession.mState != SessionState_Open)
    3008             return setError (E_FAIL,
    3009                 tr ("Machine session is not open (session state: %d)"),
    3010                 mData->mSession.mState);
     2965            return setError(E_FAIL,
     2966                            tr("Machine session is not open (session state: %d)"),
     2967                            mData->mSession.mState);
    30112968
    30122969        directControl = mData->mSession.mDirectControl;
     
    30212978}
    30222979
    3023 STDMETHODIMP Machine::GetGuestProperty (IN_BSTR aName, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags)
     2980STDMETHODIMP Machine::GetGuestProperty(IN_BSTR aName,
     2981                                       BSTR *aValue,
     2982                                       ULONG64 *aTimestamp,
     2983                                       BSTR *aFlags)
    30242984{
    30252985#if !defined (VBOX_WITH_GUEST_PROPS)
    30262986    ReturnComNotImplemented();
    30272987#else
    3028     CheckComArgNotNull (aName);
     2988    CheckComArgNotNull(aName);
    30292989    CheckComArgOutPointerValid(aValue);
    30302990    CheckComArgOutPointerValid(aTimestamp);
     
    30392999    HRESULT rc = E_FAIL;
    30403000
     3001    Utf8Str strName(aName);
     3002
    30413003    if (!mHWData->mPropertyServiceActive)
    30423004    {
    30433005        bool found = false;
    30443006        for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
    3045              (it != mHWData->mGuestProperties.end()) && !found; ++it)
    3046         {
    3047             if (it->mName == aName)
     3007             (it != mHWData->mGuestProperties.end()) && !found;
     3008             ++it)
     3009        {
     3010            if (it->strName == strName)
    30483011            {
    30493012                char szFlags[MAX_FLAGS_LEN + 1];
    3050                 it->mValue.cloneTo(aValue);
     3013                it->strValue.cloneTo(aValue);
    30513014                *aTimestamp = it->mTimestamp;
    3052                 writeFlags (it->mFlags, szFlags);
    3053                 Bstr (szFlags).cloneTo(aFlags);
     3015                writeFlags(it->mFlags, szFlags);
     3016                Bstr(szFlags).cloneTo(aFlags);
    30543017                found = true;
    30553018            }
     
    31023065    using namespace guestProp;
    31033066
    3104     CheckComArgNotNull (aName);
    3105     CheckComArgNotNull (aValue);
     3067    CheckComArgNotNull(aName);
     3068    CheckComArgNotNull(aValue);
    31063069    if ((aFlags != NULL) && !VALID_PTR (aFlags))
    31073070        return E_INVALIDARG;
     
    31483111            if (SUCCEEDED(rc))
    31493112            {
    3150                 for (HWData::GuestPropertyList::iterator it =
    3151                         mHWData->mGuestProperties.begin();
    3152                     it != mHWData->mGuestProperties.end(); ++ it)
    3153                     if (it->mName == aName)
     3113                for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
     3114                     it != mHWData->mGuestProperties.end();
     3115                     ++it)
     3116                    if (it->strName == utf8Name)
    31543117                    {
    31553118                        property = *it;
    31563119                        if (it->mFlags & (RDONLYHOST))
    3157                             rc = setError (E_ACCESSDENIED,
    3158                                 tr ("The property '%ls' cannot be changed by the host"),
    3159                                 aName);
     3120                            rc = setError(E_ACCESSDENIED,
     3121                                          tr("The property '%ls' cannot be changed by the host"),
     3122                                          aName);
    31603123                        else
    31613124                        {
     
    31643127                            * get a new one. */
    31653128                            for (it = mHWData->mGuestProperties.begin();
    3166                                 it->mName != aName; ++ it)
     3129                                 it->strName != utf8Name;
     3130                                 ++it)
    31673131                                ;
    31683132                            mHWData->mGuestProperties.erase (it);
     
    31773141                {
    31783142                    RTTIMESPEC time;
    3179                     property.mValue = aValue;
    3180                     property.mTimestamp = RTTimeSpecGetNano(RTTimeNow (&time));
     3143                    property.strValue = aValue;
     3144                    property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
    31813145                    if (aFlags != NULL)
    31823146                        property.mFlags = fFlags;
     
    31883152                RTTIMESPEC time;
    31893153                mHWData.backup();
    3190                 property.mName = aName;
    3191                 property.mValue = aValue;
    3192                 property.mTimestamp = RTTimeSpecGetNano(RTTimeNow (&time));
     3154                property.strName = aName;
     3155                property.strValue = aValue;
     3156                property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
    31933157                property.mFlags = fFlags;
    31943158                mHWData->mGuestProperties.push_back (property);
     
    32343198}
    32353199
    3236 STDMETHODIMP Machine::
    3237 EnumerateGuestProperties (IN_BSTR aPatterns, ComSafeArrayOut(BSTR, aNames),
    3238                           ComSafeArrayOut(BSTR, aValues),
    3239                           ComSafeArrayOut(ULONG64, aTimestamps),
    3240                           ComSafeArrayOut(BSTR, aFlags))
     3200STDMETHODIMP Machine::EnumerateGuestProperties(IN_BSTR aPatterns,
     3201                                              ComSafeArrayOut(BSTR, aNames),
     3202                                               ComSafeArrayOut(BSTR, aValues),
     3203                                               ComSafeArrayOut(ULONG64, aTimestamps),
     3204                                               ComSafeArrayOut(BSTR, aFlags))
    32413205{
    32423206#if !defined (VBOX_WITH_GUEST_PROPS)
     
    32593223    HRESULT rc = E_FAIL;
    32603224
     3225    Utf8Str strPatterns(aPatterns);
     3226
    32613227    bool matchAll = false;
    32623228    if ((NULL == aPatterns) || (0 == aPatterns[0]))
     
    32653231    {
    32663232
    3267 /*
    3268  * Look for matching patterns and build up a list.
    3269  */
     3233        /*
     3234         * Look for matching patterns and build up a list.
     3235         */
    32703236        HWData::GuestPropertyList propList;
    32713237        for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
    3272              it != mHWData->mGuestProperties.end(); ++it)
     3238             it != mHWData->mGuestProperties.end();
     3239             ++it)
    32733240            if (   matchAll
    3274                 || RTStrSimplePatternMultiMatch (Utf8Str (aPatterns).raw(),
    3275                                                  RTSTR_MAX,
    3276                                                  Utf8Str (it->mName).raw(),
    3277                                                  RTSTR_MAX, NULL)
     3241                || RTStrSimplePatternMultiMatch(strPatterns.raw(),
     3242                                                RTSTR_MAX,
     3243                                                it->strName.raw(),
     3244                                                RTSTR_MAX, NULL)
    32783245               )
    3279                 propList.push_back (*it);
    3280 
    3281 /*
    3282  * And build up the arrays for returning the property information.
    3283  */
     3246                propList.push_back(*it);
     3247
     3248        /*
     3249         * And build up the arrays for returning the property information.
     3250         */
    32843251        size_t cEntries = propList.size();
    32853252        SafeArray<BSTR> names (cEntries);
     
    32893256        size_t iProp = 0;
    32903257        for (HWData::GuestPropertyList::iterator it = propList.begin();
    3291              it != propList.end(); ++it)
     3258             it != propList.end();
     3259             ++it)
    32923260        {
    32933261             char szFlags[MAX_FLAGS_LEN + 1];
    3294              it->mName.cloneTo(&names[iProp]);
    3295              it->mValue.cloneTo(&values[iProp]);
     3262             it->strName.cloneTo(&names[iProp]);
     3263             it->strValue.cloneTo(&values[iProp]);
    32963264             timestamps[iProp] = it->mTimestamp;
    3297              writeFlags (it->mFlags, szFlags);
    3298              Bstr (szFlags).cloneTo(&flags[iProp]);
     3265             writeFlags(it->mFlags, szFlags);
     3266             Bstr(szFlags).cloneTo(&flags[iProp]);
    32993267             ++iProp;
    33003268        }
     
    33073275    else
    33083276    {
    3309         ComPtr<IInternalSessionControl> directControl =
    3310             mData->mSession.mDirectControl;
     3277        ComPtr<IInternalSessionControl> directControl = mData->mSession.mDirectControl;
    33113278
    33123279        /* just be on the safe side when calling another process */
     
    33163283            rc = E_FAIL;
    33173284        else
    3318             rc = directControl->EnumerateGuestProperties (aPatterns,
    3319                                                           ComSafeArrayOutArg(aNames),
    3320                                                           ComSafeArrayOutArg(aValues),
    3321                                                           ComSafeArrayOutArg(aTimestamps),
    3322                                                           ComSafeArrayOutArg(aFlags));
     3285            rc = directControl->EnumerateGuestProperties(aPatterns,
     3286                                                         ComSafeArrayOutArg(aNames),
     3287                                                         ComSafeArrayOutArg(aValues),
     3288                                                         ComSafeArrayOutArg(aTimestamps),
     3289                                                         ComSafeArrayOutArg(aFlags));
    33233290    }
    33243291    return rc;
     
    33263293}
    33273294
    3328 STDMETHODIMP Machine::
    3329 GetHardDiskAttachmentsOfController(IN_BSTR aName, ComSafeArrayOut(IHardDiskAttachment *, aAttachments))
     3295STDMETHODIMP Machine:: GetHardDiskAttachmentsOfController(IN_BSTR aName,
     3296                                                          ComSafeArrayOut(IHardDiskAttachment*, aAttachments))
    33303297{
    33313298    HDData::AttachmentList atts;
     
    33403307}
    33413308
    3342 STDMETHODIMP Machine::
    3343 AddStorageController(IN_BSTR aName,
    3344                      StorageBus_T aConnectionType,
    3345                      IStorageController **controller)
     3309STDMETHODIMP Machine::AddStorageController(IN_BSTR aName,
     3310                                           StorageBus_T aConnectionType,
     3311                                           IStorageController **controller)
    33463312{
    33473313    CheckComArgStrNotEmptyOrNull(aName);
     
    33853351}
    33863352
    3387 STDMETHODIMP Machine::
    3388 GetStorageControllerByName(IN_BSTR aName, IStorageController **aStorageController)
     3353STDMETHODIMP Machine::GetStorageControllerByName(IN_BSTR aName,
     3354                                                IStorageController **aStorageController)
    33893355{
    33903356    CheckComArgStrNotEmptyOrNull(aName);
     
    34313397        {
    34323398            if ((*it)->controller() == aName)
    3433                 return setError (VBOX_E_OBJECT_IN_USE,
    3434                     tr ("Storage controller named '%ls' has still devices attached"), aName);
     3399                return setError(VBOX_E_OBJECT_IN_USE,
     3400                                tr("Storage controller named '%ls' has still devices attached"),
     3401                                aName);
    34353402        }
    34363403    }
     
    34603427 *  @note locks this object for reading.
    34613428 */
    3462 HRESULT Machine::saveRegistryEntry (settings::Key &aEntryNode)
    3463 {
    3464     AssertReturn(!aEntryNode.isNull(), E_FAIL);
    3465 
     3429HRESULT Machine::saveRegistryEntry(settings::MachineRegistryEntry &data)
     3430{
    34663431    AutoLimitedCaller autoCaller(this);
    34673432    AssertComRCReturnRC(autoCaller.rc());
     
    34693434    AutoReadLock alock(this);
    34703435
    3471     /* UUID */
    3472     aEntryNode.setValue <Guid> ("uuid", mData->mUuid);
    3473     /* settings file name (possibly, relative) */
    3474     aEntryNode.setValue <Bstr> ("src", mData->mConfigFile);
     3436    data.uuid = mData->mUuid;
     3437    data.strSettingsFile = mData->m_strConfigFile;
    34753438
    34763439    return S_OK;
     
    34883451 * @note Locks this object for reading.
    34893452 */
    3490 int Machine::calculateFullPath (const char *aPath, Utf8Str &aResult)
     3453int Machine::calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult)
    34913454{
    34923455    AutoCaller autoCaller(this);
     
    34953458    AutoReadLock alock(this);
    34963459
    3497     AssertReturn(!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE);
    3498 
    3499     Utf8Str strSettingsDir = mData->mConfigFileFull;
     3460    AssertReturn (!mData->m_strConfigFileFull.isEmpty(), VERR_GENERAL_FAILURE);
     3461
     3462    Utf8Str strSettingsDir = mData->m_strConfigFileFull;
    35003463
    35013464    strSettingsDir.stripFilename();
    35023465    char folder[RTPATH_MAX];
    3503     int vrc = RTPathAbsEx(strSettingsDir, aPath, folder, sizeof(folder));
     3466    int vrc = RTPathAbsEx(strSettingsDir.c_str(), strPath.c_str(), folder, sizeof(folder));
    35043467    if (RT_SUCCESS(vrc))
    35053468        aResult = folder;
     
    35193482 * @note Locks this object for reading.
    35203483 */
    3521 void Machine::calculateRelativePath (const char *aPath, Utf8Str &aResult)
     3484void Machine::calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult)
    35223485{
    35233486    AutoCaller autoCaller(this);
     
    35263489    AutoReadLock alock(this);
    35273490
    3528     AssertReturnVoid (!mData->mConfigFileFull.isNull());
    3529 
    3530     Utf8Str settingsDir = mData->mConfigFileFull;
     3491    AssertReturnVoid (!mData->m_strConfigFileFull.isEmpty());
     3492
     3493    Utf8Str settingsDir = mData->m_strConfigFileFull;
    35313494
    35323495    settingsDir.stripFilename();
    3533     if (RTPathStartsWith(aPath, settingsDir))
     3496    if (RTPathStartsWith(strPath.c_str(), settingsDir.c_str()))
    35343497    {
    35353498        /* when assigning, we create a separate Utf8Str instance because both
     
    35383501         * first, and since its the same as aPath, an attempt to copy garbage
    35393502         * will be made. */
    3540         aResult = Utf8Str(aPath + settingsDir.length() + 1);
     3503        aResult = Utf8Str(strPath.c_str() + settingsDir.length() + 1);
    35413504    }
    35423505}
     
    35723535 *        lock).
    35733536 */
    3574 HRESULT Machine::openSession (IInternalSessionControl *aControl)
     3537HRESULT Machine::openSession(IInternalSessionControl *aControl)
    35753538{
    35763539    LogFlowThisFuncEnter();
     
    35843547
    35853548    if (!mData->mRegistered)
    3586         return setError (E_UNEXPECTED,
    3587             tr ("The machine '%ls' is not registered"), mUserData->mName.raw());
     3549        return setError(E_UNEXPECTED,
     3550                        tr("The machine '%ls' is not registered"),
     3551                        mUserData->mName.raw());
    35883552
    35893553    LogFlowThisFunc(("mSession.mState=%d\n", mData->mSession.mState));
     
    35913555    if (mData->mSession.mState == SessionState_Open ||
    35923556        mData->mSession.mState == SessionState_Closing)
    3593         return setError (VBOX_E_INVALID_OBJECT_STATE,
    3594             tr ("A session for the machine '%ls' is currently open "
    3595                 "(or being closed)"),
    3596             mUserData->mName.raw());
     3557        return setError(VBOX_E_INVALID_OBJECT_STATE,
     3558                        tr("A session for the machine '%ls' is currently open (or being closed)"),
     3559                        mUserData->mName.raw());
    35973560
    35983561    /* may not be busy */
     
    36163579
    36173580        if (mData->mSession.mPid != pid)
    3618             return setError (E_ACCESSDENIED,
    3619                 tr ("An unexpected process (PID=0x%08X) has tried to open a direct "
    3620                     "session with the machine named '%ls', while only a process "
    3621                     "started by OpenRemoteSession (PID=0x%08X) is allowed"),
    3622                 pid, mUserData->mName.raw(), mData->mSession.mPid);
     3581            return setError(E_ACCESSDENIED,
     3582                            tr("An unexpected process (PID=0x%08X) has tried to open a direct "
     3583                               "session with the machine named '%ls', while only a process "
     3584                               "started by OpenRemoteSession (PID=0x%08X) is allowed"),
     3585                            pid, mUserData->mName.raw(), mData->mSession.mPid);
    36233586    }
    36243587
     
    36983661
    36993662                /* The failure may occur w/o any error info (from RPC), so provide one */
    3700                 if (FAILED (rc))
    3701                     setError (VBOX_E_VM_ERROR,
    3702                         tr ("Failed to assign the machine to the remote session (%Rrc)"), rc);
     3663                if (FAILED(rc))
     3664                    setError(VBOX_E_VM_ERROR,
     3665                             tr("Failed to assign the machine to the remote session (%Rrc)"), rc);
    37033666            }
    37043667
    3705             if (FAILED (rc))
     3668            if (FAILED(rc))
    37063669                aControl->Uninitialize();
    37073670        }
     
    37223685         * SessionMachine::uninit() to reap the child process later. */
    37233686
    3724         if (FAILED (rc))
     3687        if (FAILED(rc))
    37253688        {
    37263689            /* Close the remote session, remove the remote control from the list
     
    37733736
    37743737    /* uninitialize the created session machine on failure */
    3775     if (FAILED (rc))
     3738    if (FAILED(rc))
    37763739        sessionMachine->uninit();
    37773740
     
    37853748 *        (inside the lock).
    37863749 */
    3787 HRESULT Machine::openRemoteSession (IInternalSessionControl *aControl,
    3788                                     IN_BSTR aType, IN_BSTR aEnvironment,
    3789                                     Progress *aProgress)
     3750HRESULT Machine::openRemoteSession(IInternalSessionControl *aControl,
     3751                                   IN_BSTR aType,
     3752                                   IN_BSTR aEnvironment,
     3753                                   Progress *aProgress)
    37903754{
    37913755    LogFlowThisFuncEnter();
     
    38003764
    38013765    if (!mData->mRegistered)
    3802         return setError (E_UNEXPECTED,
    3803             tr ("The machine '%ls' is not registered"), mUserData->mName.raw());
     3766        return setError(E_UNEXPECTED,
     3767                        tr("The machine '%ls' is not registered"),
     3768                        mUserData->mName.raw());
    38043769
    38053770    LogFlowThisFunc(("mSession.mState=%d\n", mData->mSession.mState));
     
    38083773        mData->mSession.mState == SessionState_Spawning ||
    38093774        mData->mSession.mState == SessionState_Closing)
    3810         return setError (VBOX_E_INVALID_OBJECT_STATE,
    3811             tr ("A session for the machine '%ls' is currently open "
    3812                 "(or being opened or closed)"),
    3813             mUserData->mName.raw());
     3775        return setError(VBOX_E_INVALID_OBJECT_STATE,
     3776                        tr("A session for the machine '%ls' is currently open (or being opened or closed)"),
     3777                        mUserData->mName.raw());
    38143778
    38153779    /* may not be busy */
     
    38173781
    38183782    /* get the path to the executable */
    3819     char path [RTPATH_MAX];
    3820     RTPathAppPrivateArch (path, RTPATH_MAX);
    3821     size_t sz = strlen (path);
    3822     path [sz++] = RTPATH_DELIMITER;
    3823     path [sz] = 0;
    3824     char *cmd = path + sz;
     3783    char szPath[RTPATH_MAX];
     3784    RTPathAppPrivateArch(szPath, RTPATH_MAX);
     3785    size_t sz = strlen(szPath);
     3786    szPath[sz++] = RTPATH_DELIMITER;
     3787    szPath[sz] = 0;
     3788    char *cmd = szPath + sz;
    38253789    sz = RTPATH_MAX - sz;
    38263790
     
    38373801        {
    38383802            /* clone the current environment */
    3839             int vrc2 = RTEnvClone (&env, RTENV_DEFAULT);
    3840             AssertRCBreakStmt (vrc2, vrc = vrc2);
    3841 
    3842             newEnvStr = RTStrDup (Utf8Str (aEnvironment));
    3843             AssertPtrBreakStmt (newEnvStr, vrc = vrc2);
     3803            int vrc2 = RTEnvClone(&env, RTENV_DEFAULT);
     3804            AssertRCBreakStmt(vrc2, vrc = vrc2);
     3805
     3806            newEnvStr = RTStrDup(Utf8Str(aEnvironment).c_str());
     3807            AssertPtrBreakStmt(newEnvStr, vrc = vrc2);
    38443808
    38453809            /* put new variables to the environment
     
    38763840
    38773841        if (newEnvStr != NULL)
    3878             RTStrFree (newEnvStr);
     3842            RTStrFree(newEnvStr);
    38793843    }
    38803844
     
    38953859        Utf8Str idStr = mData->mUuid.toString();
    38963860# ifdef RT_OS_WINDOWS /** @todo drop this once the RTProcCreate bug has been fixed */
    3897         const char * args[] = {path, "--startvm", idStr, 0 };
     3861        const char * args[] = {szPath, "--startvm", idStr.c_str(), 0 };
    38983862# else
    38993863        Utf8Str name = mUserData->mName;
    3900         const char * args[] = {path, "--comment", name, "--startvm", idStr, 0 };
     3864        const char * args[] = {szPath, "--comment", name.c_str(), "--startvm", idStr.c_str(), 0 };
    39013865# endif
    3902         vrc = RTProcCreate (path, args, env, 0, &pid);
     3866        vrc = RTProcCreate(szPath, args, env, 0, &pid);
    39033867    }
    39043868#else /* !VBOX_WITH_QTGUI */
     
    39183882        Utf8Str idStr = mData->mUuid.toString();
    39193883# ifdef RT_OS_WINDOWS
    3920         const char * args[] = {path, "--startvm", idStr, 0 };
     3884        const char * args[] = {szPath, "--startvm", idStr.c_str(), 0 };
    39213885# else
    39223886        Utf8Str name = mUserData->mName;
    3923         const char * args[] = {path, "--comment", name, "--startvm", idStr, 0 };
     3887        const char * args[] = {szPath, "--comment", name.c_str(), "--startvm", idStr.c_str(), 0 };
    39243888# endif
    3925         vrc = RTProcCreate (path, args, env, 0, &pid);
     3889        vrc = RTProcCreate(szPath, args, env, 0, &pid);
    39263890    }
    39273891#else /* !VBOX_WITH_VBOXSDL */
     
    39473911        /* Leave space for 2 args, as "headless" needs --vrdp off on non-OSE. */
    39483912# ifdef RT_OS_WINDOWS
    3949         const char * args[] = {path, "--startvm", idStr, 0, 0, 0 };
     3913        const char * args[] = {szPath, "--startvm", idStr.c_str(), 0, 0, 0 };
    39503914# else
    39513915        Utf8Str name = mUserData->mName;
    3952         const char * args[] = {path, "--comment", name, "--startvm", idStr, 0, 0, 0 };
     3916        const char * args[] ={szPath, "--comment", name.c_str(), "--startvm", idStr.c_str(), 0, 0, 0 };
    39533917# endif
    39543918#ifdef VBOX_WITH_VRDP
     
    39653929            args[pos] = "--capture";
    39663930        }
    3967         vrc = RTProcCreate (path, args, env, 0, &pid);
     3931        vrc = RTProcCreate(szPath, args, env, 0, &pid);
    39683932    }
    39693933#else /* !VBOX_WITH_HEADLESS */
     
    40013965    LogFlowThisFunc(("AssignMachine (NULL) returned %08X\n", rc));
    40023966
    4003     if (FAILED (rc))
     3967    if (FAILED(rc))
    40043968    {
    40053969        /* restore the session state */
    40063970        mData->mSession.mState = SessionState_Closed;
    40073971        /* The failure may occur w/o any error info (from RPC), so provide one */
    4008         return setError (VBOX_E_VM_ERROR,
    4009             tr ("Failed to assign the machine to the session (%Rrc)"), rc);
     3972        return setError(VBOX_E_VM_ERROR,
     3973                        tr("Failed to assign the machine to the session (%Rrc)"), rc);
    40103974    }
    40113975
     
    40834047
    40844048    /* The failure may occur w/o any error info (from RPC), so provide one */
    4085     if (FAILED (rc))
    4086         return setError (VBOX_E_VM_ERROR,
    4087             tr ("Failed to assign the machine to the session (%Rrc)"), rc);
     4049    if (FAILED(rc))
     4050        return setError(VBOX_E_VM_ERROR,
     4051                        tr("Failed to assign the machine to the session (%Rrc)"),
     4052                        rc);
    40884053
    40894054    alock.enter();
     
    40944059        aControl->Uninitialize();
    40954060
    4096         return setError (VBOX_E_INVALID_SESSION_STATE,
    4097             tr ("The machine '%ls' does not have an open session"),
    4098             mUserData->mName.raw());
     4061        return setError(VBOX_E_INVALID_SESSION_STATE,
     4062                        tr("The machine '%ls' does not have an open session"),
     4063                        mUserData->mName.raw());
    40994064    }
    41004065
     
    42464211    /* the process was already unexpectedly terminated, we just need to set an
    42474212     * error and finalize session spawning */
    4248     rc = setError (E_FAIL,
    4249                    tr ("Virtual machine '%ls' has terminated unexpectedly "
    4250                        "during startup"),
    4251                    name().raw());
     4213    rc = setError(E_FAIL,
     4214                  tr("Virtual machine '%ls' has terminated unexpectedly during startup"),
     4215                  name().raw());
    42524216#else
    42534217
     
    42574221
    42584222    if (vrc != VERR_PROCESS_RUNNING)
    4259         rc = setError (E_FAIL,
    4260                        tr ("Virtual machine '%ls' has terminated unexpectedly "
    4261                            "during startup"),
    4262                        name().raw());
     4223        rc = setError(E_FAIL,
     4224                      tr("Virtual machine '%ls' has terminated unexpectedly during startup"),
     4225                      name().raw());
    42634226#endif
    42644227
    4265     if (FAILED (rc))
     4228    if (FAILED(rc))
    42664229    {
    42674230        /* Close the remote session, remove the remote control from the list
     
    43514314    {
    43524315        if (mData->mRegistered)
    4353             return setError (VBOX_E_INVALID_OBJECT_STATE,
    4354                 tr ("The machine '%ls' with UUID {%s} is already registered"),
    4355                 mUserData->mName.raw(),
    4356                 mData->mUuid.toString().raw());
     4316            return setError(VBOX_E_INVALID_OBJECT_STATE,
     4317                            tr("The machine '%ls' with UUID {%s} is already registered"),
     4318                            mUserData->mName.raw(),
     4319                            mData->mUuid.toString().raw());
    43574320    }
    43584321    else
    43594322    {
    43604323        if (mData->mMachineState == MachineState_Saved)
    4361             return setError (VBOX_E_INVALID_VM_STATE,
    4362                 tr ("Cannot unregister the machine '%ls' because it "
    4363                     "is in the Saved state"),
    4364                 mUserData->mName.raw());
     4324            return setError(VBOX_E_INVALID_VM_STATE,
     4325                            tr("Cannot unregister the machine '%ls' because it is in the Saved state"),
     4326                            mUserData->mName.raw());
    43654327
    43664328        size_t snapshotCount = 0;
     
    43684330            snapshotCount = mData->mFirstSnapshot->getAllChildrenCount() + 1;
    43694331        if (snapshotCount)
    4370             return setError (VBOX_E_INVALID_OBJECT_STATE,
    4371                 tr ("Cannot unregister the machine '%ls' because it "
    4372                     "has %d snapshots"),
    4373                 mUserData->mName.raw(), snapshotCount);
     4332            return setError(VBOX_E_INVALID_OBJECT_STATE,
     4333                            tr("Cannot unregister the machine '%ls' because it has %d snapshots"),
     4334                            mUserData->mName.raw(), snapshotCount);
    43744335
    43754336        if (mData->mSession.mState != SessionState_Closed)
    4376             return setError (VBOX_E_INVALID_OBJECT_STATE,
    4377                 tr ("Cannot unregister the machine '%ls' because it has an "
    4378                     "open session"),
    4379                 mUserData->mName.raw());
     4337            return setError(VBOX_E_INVALID_OBJECT_STATE,
     4338                            tr("Cannot unregister the machine '%ls' because it has an open session"),
     4339                            mUserData->mName.raw());
    43804340
    43814341        if (mHDData->mAttachments.size() != 0)
    4382             return setError (VBOX_E_INVALID_OBJECT_STATE,
    4383                 tr ("Cannot unregister the machine '%ls' because it "
    4384                     "has %d hard disks attached"),
    4385                 mUserData->mName.raw(), mHDData->mAttachments.size());
     4342            return setError(VBOX_E_INVALID_OBJECT_STATE,
     4343                            tr("Cannot unregister the machine '%ls' because it has %d hard disks attached"),
     4344                            mUserData->mName.raw(),
     4345                            mHDData->mAttachments.size());
    43864346
    43874347        /* Note that we do not prevent unregistration of a DVD or Floppy image
     
    43964356     * isConfigLocked() is FALSE then it means that no config file exists yet,
    43974357     * so create it by calling saveSettings() too. */
    4398     if (isModified() || (aRegistered && !isConfigLocked()))
     4358    if (    isModified()
     4359         || (aRegistered && !mData->m_pMachineConfigFile->fileExists())
     4360       )
    43994361    {
    44004362        rc = saveSettings();
     
    44654427            AssertFailed();
    44664428
    4467             return setError (E_ACCESSDENIED,
    4468                 tr ("Machine state change is in progress. "
    4469                     "Please retry the operation later."));
     4429            return setError(E_ACCESSDENIED,
     4430                            tr("Machine state change is in progress. Please retry the operation later."));
    44704431        }
    44714432
     
    45544515                 mData->mMachineState > MachineState_Paused ||
    45554516                 mData->mMachineState == MachineState_Saved))
    4556                 return setError (VBOX_E_INVALID_VM_STATE,
    4557                     tr ("The machine is not mutable (state is %d)"),
    4558                     mData->mMachineState);
     4517                return setError(VBOX_E_INVALID_VM_STATE,
     4518                                tr("The machine is not mutable (state is %d)"),
     4519                                mData->mMachineState);
    45594520            break;
    45604521        }
     
    45644525                (mType != IsSessionMachine ||
    45654526                 mData->mMachineState > MachineState_Paused))
    4566                 return setError (VBOX_E_INVALID_VM_STATE,
    4567                     tr ("The machine is not mutable (state is %d)"),
    4568                     mData->mMachineState);
     4527                return setError(VBOX_E_INVALID_VM_STATE,
     4528                                tr("The machine is not mutable (state is %d)"),
     4529                                mData->mMachineState);
    45694530            break;
    45704531        }
     
    45724533
    45734534    return S_OK;
    4574 }
    4575 
    4576 /**
    4577  * Helper to initialize all associated child objects and allocate data
    4578  * structures.
    4579  *
    4580  * This method must be called as a part of the object's initialization procedure
    4581  * (usually done in the #init() method).
    4582  *
    4583  * @note Must be called only from #init() or from #registeredInit().
    4584  */
    4585 HRESULT Machine::initDataAndChildObjects()
    4586 {
    4587     AutoCaller autoCaller(this);
    4588     AssertComRCReturnRC(autoCaller.rc());
    4589     AssertComRCReturn (autoCaller.state() == InInit ||
    4590                        autoCaller.state() == Limited, E_FAIL);
    4591 
    4592     AssertReturn(!mData->mAccessible, E_FAIL);
    4593 
    4594     /* allocate data structures */
    4595     mSSData.allocate();
    4596     mUserData.allocate();
    4597     mHWData.allocate();
    4598     mHDData.allocate();
    4599     mStorageControllers.allocate();
    4600 
    4601     /* initialize mOSTypeId */
    4602     mUserData->mOSTypeId = mParent->getUnknownOSType()->id();
    4603 
    4604     /* create associated BIOS settings object */
    4605     unconst(mBIOSSettings).createObject();
    4606     mBIOSSettings->init (this);
    4607 
    4608 #ifdef VBOX_WITH_VRDP
    4609     /* create an associated VRDPServer object (default is disabled) */
    4610     unconst(mVRDPServer).createObject();
    4611     mVRDPServer->init (this);
    4612 #endif
    4613 
    4614     /* create an associated DVD drive object */
    4615     unconst(mDVDDrive).createObject();
    4616     mDVDDrive->init (this);
    4617 
    4618     /* create an associated floppy drive object */
    4619     unconst(mFloppyDrive).createObject();
    4620     mFloppyDrive->init (this);
    4621 
    4622     /* create associated serial port objects */
    4623     for (ULONG slot = 0; slot < RT_ELEMENTS (mSerialPorts); slot ++)
    4624     {
    4625         unconst(mSerialPorts [slot]).createObject();
    4626         mSerialPorts [slot]->init (this, slot);
    4627     }
    4628 
    4629     /* create associated parallel port objects */
    4630     for (ULONG slot = 0; slot < RT_ELEMENTS (mParallelPorts); slot ++)
    4631     {
    4632         unconst(mParallelPorts [slot]).createObject();
    4633         mParallelPorts [slot]->init (this, slot);
    4634     }
    4635 
    4636     /* create the audio adapter object (always present, default is disabled) */
    4637     unconst(mAudioAdapter).createObject();
    4638     mAudioAdapter->init (this);
    4639 
    4640     /* create the USB controller object (always present, default is disabled) */
    4641     unconst(mUSBController).createObject();
    4642     mUSBController->init (this);
    4643 
    4644     /* create associated network adapter objects */
    4645     for (ULONG slot = 0; slot < RT_ELEMENTS (mNetworkAdapters); slot ++)
    4646     {
    4647         unconst(mNetworkAdapters [slot]).createObject();
    4648         mNetworkAdapters [slot]->init (this, slot);
    4649     }
    4650 
    4651     return S_OK;
    4652 }
    4653 
    4654 /**
    4655  * Helper to uninitialize all associated child objects and to free all data
    4656  * structures.
    4657  *
    4658  * This method must be called as a part of the object's uninitialization
    4659  * procedure (usually done in the #uninit() method).
    4660  *
    4661  * @note Must be called only from #uninit() or from #registeredInit().
    4662  */
    4663 void Machine::uninitDataAndChildObjects()
    4664 {
    4665     AutoCaller autoCaller(this);
    4666     AssertComRCReturnVoid (autoCaller.rc());
    4667     AssertComRCReturnVoid (autoCaller.state() == InUninit ||
    4668                            autoCaller.state() == Limited);
    4669 
    4670     /* uninit all children using addDependentChild()/removeDependentChild()
    4671      * in their init()/uninit() methods */
    4672     uninitDependentChildren();
    4673 
    4674     /* tell all our other child objects we've been uninitialized */
    4675 
    4676     for (ULONG slot = 0; slot < RT_ELEMENTS (mNetworkAdapters); slot ++)
    4677     {
    4678         if (mNetworkAdapters [slot])
    4679         {
    4680             mNetworkAdapters [slot]->uninit();
    4681             unconst(mNetworkAdapters [slot]).setNull();
    4682         }
    4683     }
    4684 
    4685     if (mUSBController)
    4686     {
    4687         mUSBController->uninit();
    4688         unconst(mUSBController).setNull();
    4689     }
    4690 
    4691     if (mAudioAdapter)
    4692     {
    4693         mAudioAdapter->uninit();
    4694         unconst(mAudioAdapter).setNull();
    4695     }
    4696 
    4697     for (ULONG slot = 0; slot < RT_ELEMENTS (mParallelPorts); slot ++)
    4698     {
    4699         if (mParallelPorts [slot])
    4700         {
    4701             mParallelPorts [slot]->uninit();
    4702             unconst(mParallelPorts [slot]).setNull();
    4703         }
    4704     }
    4705 
    4706     for (ULONG slot = 0; slot < RT_ELEMENTS (mSerialPorts); slot ++)
    4707     {
    4708         if (mSerialPorts [slot])
    4709         {
    4710             mSerialPorts [slot]->uninit();
    4711             unconst(mSerialPorts [slot]).setNull();
    4712         }
    4713     }
    4714 
    4715     if (mFloppyDrive)
    4716     {
    4717         mFloppyDrive->uninit();
    4718         unconst(mFloppyDrive).setNull();
    4719     }
    4720 
    4721     if (mDVDDrive)
    4722     {
    4723         mDVDDrive->uninit();
    4724         unconst(mDVDDrive).setNull();
    4725     }
    4726 
    4727 #ifdef VBOX_WITH_VRDP
    4728     if (mVRDPServer)
    4729     {
    4730         mVRDPServer->uninit();
    4731         unconst(mVRDPServer).setNull();
    4732     }
    4733 #endif
    4734 
    4735     if (mBIOSSettings)
    4736     {
    4737         mBIOSSettings->uninit();
    4738         unconst(mBIOSSettings).setNull();
    4739     }
    4740 
    4741     /* Deassociate hard disks (only when a real Machine or a SnapshotMachine
    4742      * instance is uninitialized; SessionMachine instances refer to real
    4743      * Machine hard disks). This is necessary for a clean re-initialization of
    4744      * the VM after successfully re-checking the accessibility state. Note
    4745      * that in case of normal Machine or SnapshotMachine uninitialization (as
    4746      * a result of unregistering or discarding the snapshot), outdated hard
    4747      * disk attachments will already be uninitialized and deleted, so this
    4748      * code will not affect them. */
    4749     if (!!mHDData && (mType == IsMachine || mType == IsSnapshotMachine))
    4750     {
    4751         for (HDData::AttachmentList::const_iterator it =
    4752                  mHDData->mAttachments.begin();
    4753              it != mHDData->mAttachments.end();
    4754              ++ it)
    4755         {
    4756             HRESULT rc = (*it)->hardDisk()->detachFrom (mData->mUuid,
    4757                                                         snapshotId());
    4758             AssertComRC (rc);
    4759         }
    4760     }
    4761 
    4762     if (mType == IsMachine)
    4763     {
    4764         /* reset some important fields of mData */
    4765         mData->mCurrentSnapshot.setNull();
    4766         mData->mFirstSnapshot.setNull();
    4767     }
    4768 
    4769     /* free data structures (the essential mData structure is not freed here
    4770      * since it may be still in use) */
    4771     mHDData.free();
    4772     mStorageControllers.free();
    4773     mHWData.free();
    4774     mUserData.free();
    4775     mSSData.free();
    47764535}
    47774536
     
    48874646
    48884647    if (aSetError && !found)
    4889         setError (rc, tr ("Could not find a shared folder named '%ls'"), aName);
     4648        setError(rc, tr("Could not find a shared folder named '%ls'"), aName);
    48904649
    48914650    return rc;
     
    49034662 *  @note Doesn't lock any objects.
    49044663 */
    4905 HRESULT Machine::loadSettings (bool aRegistered)
     4664HRESULT Machine::loadSettings(bool aRegistered)
    49064665{
    49074666    LogFlowThisFuncEnter();
     
    49154674    try
    49164675    {
    4917         using namespace settings;
    4918         using namespace xml;
    4919 
    4920         /* no concurrent file access is possible in init() so open by handle */
    4921         File file (mData->mHandleCfgFile, Utf8Str (mData->mConfigFileFull));
    4922         XmlTreeBackend tree;
    4923 
    4924         rc = VirtualBox::loadSettingsTree_FirstTime (tree, file,
    4925                                                      mData->mSettingsFileVersion);
    4926         CheckComRCThrowRC (rc);
    4927 
    4928         Key machineNode = tree.rootKey().key ("Machine");
    4929 
    4930         /* uuid (required) */
    4931         Guid id = machineNode.value <Guid> ("uuid");
     4676        Assert(mData->m_pMachineConfigFile == NULL);
     4677
     4678        // load and parse machine XML; this will throw on XML or logic errors
     4679        mData->m_pMachineConfigFile = new settings::MachineConfigFile(&mData->m_strConfigFileFull);
    49324680
    49334681        /* If the stored UUID is not empty, it means the registered machine
     
    49364684        if (!mData->mUuid.isEmpty())
    49374685        {
    4938             if (mData->mUuid != id)
     4686            if (mData->mUuid != mData->m_pMachineConfigFile->uuid)
    49394687            {
    4940                 throw setError (E_FAIL,
    4941                     tr ("Machine UUID {%RTuuid} in '%ls' doesn't match its "
    4942                         "UUID {%s} in the registry file '%ls'"),
    4943                     id.raw(), mData->mConfigFileFull.raw(),
    4944                     mData->mUuid.toString().raw(),
    4945                     mParent->settingsFileName().raw());
     4688                throw setError(E_FAIL,
     4689                               tr("Machine UUID {%RTuuid} in '%s' doesn't match its UUID {%s} in the registry file '%s'"),
     4690                               mData->m_pMachineConfigFile->uuid.raw(),
     4691                               mData->m_strConfigFileFull.raw(),
     4692                               mData->mUuid.toString().raw(),
     4693                               mParent->settingsFilePath().raw());
    49464694            }
    49474695        }
    49484696        else
    4949             unconst(mData->mUuid) = id;
     4697            unconst (mData->mUuid) = mData->m_pMachineConfigFile->uuid;
    49504698
    49514699        /* name (required) */
    4952         mUserData->mName = machineNode.stringValue ("name");
     4700        mUserData->mName = mData->m_pMachineConfigFile->strName;
    49534701
    49544702        /* nameSync (optional, default is true) */
    4955         mUserData->mNameSync = machineNode.value <bool> ("nameSync");
    4956 
    4957         /* Description (optional, default is null) */
    4958         {
    4959             Key descNode = machineNode.findKey ("Description");
    4960             if (!descNode.isNull())
    4961                 mUserData->mDescription = descNode.keyStringValue();
    4962             else
    4963                 mUserData->mDescription.setNull();
    4964         }
    4965 
    4966         /* OSType (required) */
    4967         {
    4968             mUserData->mOSTypeId = machineNode.stringValue ("OSType");
    4969 
    4970             /* look up the object by Id to check it is valid */
    4971             ComPtr<IGuestOSType> guestOSType;
    4972             rc = mParent->GetGuestOSType (mUserData->mOSTypeId,
    4973                                           guestOSType.asOutParam());
    4974             CheckComRCThrowRC (rc);
    4975         }
    4976 
    4977         /* stateFile (optional) */
    4978         {
    4979             Bstr stateFilePath = machineNode.stringValue ("stateFile");
    4980             if (stateFilePath)
    4981             {
    4982                 Utf8Str stateFilePathFull = stateFilePath;
    4983                 int vrc = calculateFullPath (stateFilePathFull, stateFilePathFull);
    4984                 if (RT_FAILURE(vrc))
    4985                 {
    4986                     throw setError (E_FAIL,
    4987                         tr ("Invalid saved state file path '%ls' (%Rrc)"),
    4988                         stateFilePath.raw(), vrc);
    4989                 }
    4990                 mSSData->mStateFilePath = stateFilePathFull;
    4991             }
    4992             else
    4993                 mSSData->mStateFilePath.setNull();
    4994         }
    4995 
    4996         /*
    4997          *  currentSnapshot ID (optional)
    4998          *
    4999          *  Note that due to XML Schema constaraints, this attribute, when
    5000          *  present, will guaranteedly refer to an existing snapshot
    5001          *  definition in XML
    5002          */
    5003         Guid currentSnapshotId = machineNode.valueOr <Guid> ("currentSnapshot",
    5004                                                              Guid());
     4703        mUserData->mNameSync = mData->m_pMachineConfigFile->fNameSync;
     4704
     4705        mUserData->mDescription = mData->m_pMachineConfigFile->strDescription;
     4706
     4707        // guest OS type
     4708        mUserData->mOSTypeId = mData->m_pMachineConfigFile->strOsType;
     4709        /* look up the object by Id to check it is valid */
     4710        ComPtr<IGuestOSType> guestOSType;
     4711        rc = mParent->GetGuestOSType(mUserData->mOSTypeId,
     4712                                     guestOSType.asOutParam());
     4713        CheckComRCThrowRC(rc);
     4714
     4715        // stateFile (optional)
     4716        if (mData->m_pMachineConfigFile->strStateFile.isEmpty())
     4717            mSSData->mStateFilePath.setNull();
     4718        else
     4719        {
     4720            Utf8Str stateFilePathFull(mData->m_pMachineConfigFile->strStateFile);
     4721            int vrc = calculateFullPath(stateFilePathFull, stateFilePathFull);
     4722            if (RT_FAILURE(vrc))
     4723                throw setError(E_FAIL,
     4724                                tr("Invalid saved state file path '%s' (%Rrc)"),
     4725                                mData->m_pMachineConfigFile->strStateFile.raw(),
     4726                                vrc);
     4727            mSSData->mStateFilePath = stateFilePathFull;
     4728        }
    50054729
    50064730        /* snapshotFolder (optional) */
    5007         {
    5008             Bstr folder = machineNode.stringValue ("snapshotFolder");
    5009             rc = COMSETTER (SnapshotFolder) (folder);
    5010             CheckComRCThrowRC (rc);
    5011         }
     4731        rc = COMSETTER(SnapshotFolder)(Bstr(mData->m_pMachineConfigFile->strSnapshotFolder));
     4732        CheckComRCThrowRC(rc);
    50124733
    50134734        /* currentStateModified (optional, default is true) */
    5014         mData->mCurrentStateModified = machineNode.value <bool> ("currentStateModified");
    5015 
    5016         /* lastStateChange (optional, defaults to now) */
    5017         {
    5018             RTTIMESPEC now;
    5019             RTTimeNow (&now);
    5020             mData->mLastStateChange =
    5021                 machineNode.valueOr <RTTIMESPEC> ("lastStateChange", now);
    5022         }
    5023 
    5024         /* aborted (optional, default is false) */
    5025         bool aborted = machineNode.value <bool> ("aborted");
     4735        mData->mCurrentStateModified = mData->m_pMachineConfigFile->fCurrentStateModified;
     4736
     4737        mData->mLastStateChange = mData->m_pMachineConfigFile->timeLastStateChange;
    50264738
    50274739        /*
     
    50334745
    50344746        /* Snapshot node (optional) */
    5035         {
    5036             Key snapshotNode = machineNode.findKey ("Snapshot");
    5037             if (!snapshotNode.isNull())
    5038             {
    5039                 /* read all snapshots recursively */
    5040                 rc = loadSnapshot (snapshotNode, currentSnapshotId, NULL);
    5041                 CheckComRCThrowRC (rc);
    5042             }
    5043         }
    5044 
    5045         Key hardwareNode = machineNode.key("Hardware");
     4747        if (mData->m_pMachineConfigFile->llFirstSnapshot.size())
     4748        {
     4749            // there can only be one root snapshot
     4750            Assert(mData->m_pMachineConfigFile->llFirstSnapshot.size() == 1);
     4751
     4752            settings::Snapshot &snap = mData->m_pMachineConfigFile->llFirstSnapshot.front();
     4753
     4754            rc = loadSnapshot(snap,
     4755                              mData->m_pMachineConfigFile->uuidCurrentSnapshot,
     4756                              NULL);        // no parent == first snapshot
     4757            CheckComRCThrowRC(rc);
     4758        }
    50464759
    50474760        /* Hardware node (required) */
    5048         rc = loadHardware (hardwareNode);
    5049         CheckComRCThrowRC (rc);
     4761        rc = loadHardware(mData->m_pMachineConfigFile->hardwareMachine);
     4762        CheckComRCThrowRC(rc);
    50504763
    50514764        /* Load storage controllers */
    5052         rc = loadStorageControllers (machineNode.key ("StorageControllers"), aRegistered);
    5053         CheckComRCThrowRC (rc);
     4765        rc = loadStorageControllers(mData->m_pMachineConfigFile->storageMachine, aRegistered);
     4766        CheckComRCThrowRC(rc);
    50544767
    50554768        /*
     
    50614774
    50624775        /* set the machine state to Aborted or Saved when appropriate */
    5063         if (aborted)
    5064         {
    5065             Assert (!mSSData->mStateFilePath);
     4776        if (mData->m_pMachineConfigFile->fAborted)
     4777        {
     4778            Assert(!mSSData->mStateFilePath);
    50664779            mSSData->mStateFilePath.setNull();
    50674780
     
    50964809 *  @param aParentSnapshot  Parent snapshot.
    50974810 */
    5098 HRESULT Machine::loadSnapshot (const settings::Key &aNode,
    5099                                const Guid &aCurSnapshotId,
    5100                                Snapshot *aParentSnapshot)
    5101 {
    5102     using namespace settings;
    5103 
    5104     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    5105     AssertReturn(mType == IsMachine, E_FAIL);
     4811HRESULT Machine::loadSnapshot(const settings::Snapshot &data,
     4812                              const Guid &aCurSnapshotId,
     4813                              Snapshot *aParentSnapshot)
     4814{
     4815    AssertReturn (mType == IsMachine, E_FAIL);
     4816
     4817    HRESULT rc = S_OK;
     4818
     4819    Utf8Str strStateFile;
     4820    if (!data.strStateFile.isEmpty())
     4821    {
     4822        /* optional */
     4823        strStateFile = data.strStateFile;
     4824        int vrc = calculateFullPath(strStateFile, strStateFile);
     4825        if (RT_FAILURE(vrc))
     4826            return setError(E_FAIL,
     4827                            tr("Invalid saved state file path '%s' (%Rrc)"),
     4828                            strStateFile.raw(),
     4829                            vrc);
     4830    }
    51064831
    51074832    /* create a snapshot machine object */
    5108     ComObjPtr<SnapshotMachine> snapshotMachine;
    5109     snapshotMachine.createObject();
    5110 
    5111     HRESULT rc = S_OK;
    5112 
    5113     /* required */
    5114     Guid uuid = aNode.value <Guid> ("uuid");
    5115 
    5116     {
    5117         /* optional */
    5118         Bstr stateFilePath = aNode.stringValue ("stateFile");
    5119         if (stateFilePath)
    5120         {
    5121             Utf8Str stateFilePathFull = stateFilePath;
    5122             int vrc = calculateFullPath (stateFilePathFull, stateFilePathFull);
    5123             if (RT_FAILURE(vrc))
    5124                 return setError (E_FAIL,
    5125                                  tr ("Invalid saved state file path '%ls' (%Rrc)"),
    5126                                  stateFilePath.raw(), vrc);
    5127 
    5128             stateFilePath = stateFilePathFull;
    5129         }
    5130 
    5131         /* Hardware node (required) */
    5132         Key hardwareNode = aNode.key ("Hardware");
    5133 
    5134         /* StorageControllers node (required) */
    5135         Key storageNode = aNode.key ("StorageControllers");
    5136 
    5137         /* initialize the snapshot machine */
    5138         rc = snapshotMachine->init (this, hardwareNode, storageNode,
    5139                                     uuid, stateFilePath);
    5140         CheckComRCReturnRC(rc);
    5141     }
     4833    ComObjPtr<SnapshotMachine> pSnapshotMachine;
     4834    pSnapshotMachine.createObject();
     4835    rc = pSnapshotMachine->init(this,
     4836                                data.hardware,
     4837                                data.storage,
     4838                                data.uuid,
     4839                                strStateFile);
     4840    CheckComRCReturnRC (rc);
    51424841
    51434842    /* create a snapshot object */
    5144     ComObjPtr<Snapshot> snapshot;
    5145     snapshot.createObject();
    5146 
    5147     {
    5148         /* required */
    5149         Bstr name = aNode.stringValue ("name");
    5150 
    5151         /* required */
    5152         RTTIMESPEC timeStamp = aNode.value <RTTIMESPEC> ("timeStamp");
    5153 
    5154         /* optional */
    5155         Bstr description;
    5156         {
    5157             Key descNode = aNode.findKey ("Description");
    5158             if (!descNode.isNull())
    5159                 description = descNode.keyStringValue();
    5160         }
    5161 
    5162         /* initialize the snapshot */
    5163         rc = snapshot->init(mParent, // VirtualBox object
    5164                             uuid,
    5165                             name,
    5166                             description,
    5167                             timeStamp,
    5168                             snapshotMachine,
    5169                             aParentSnapshot);
    5170         CheckComRCReturnRC(rc);
    5171     }
     4843    ComObjPtr<Snapshot> pSnapshot;
     4844    pSnapshot.createObject();
     4845    /* initialize the snapshot */
     4846    rc = pSnapshot->init(mParent, // VirtualBox object
     4847                         data.uuid,
     4848                         data.strName,
     4849                         data.strDescription,
     4850                         data.timestamp,
     4851                         pSnapshotMachine,
     4852                         aParentSnapshot);
     4853    CheckComRCReturnRC (rc);
    51724854
    51734855    /* memorize the first snapshot if necessary */
    51744856    if (!mData->mFirstSnapshot)
    5175         mData->mFirstSnapshot = snapshot;
     4857        mData->mFirstSnapshot = pSnapshot;
    51764858
    51774859    /* memorize the current snapshot when appropriate */
    51784860    if (    !mData->mCurrentSnapshot
    5179          && snapshot->getId() == aCurSnapshotId
     4861         && pSnapshot->getId() == aCurSnapshotId
    51804862       )
    5181         mData->mCurrentSnapshot = snapshot;
    5182 
    5183     /* Snapshots node (optional) */
    5184     {
    5185         Key snapshotsNode = aNode.findKey ("Snapshots");
    5186         if (!snapshotsNode.isNull())
    5187         {
    5188             Key::List children = snapshotsNode.keys ("Snapshot");
    5189             for (Key::List::const_iterator it = children.begin();
    5190                  it != children.end(); ++ it)
    5191             {
    5192                 rc = loadSnapshot ((*it), aCurSnapshotId, snapshot);
    5193                 CheckComRCBreakRC (rc);
    5194             }
    5195         }
     4863        mData->mCurrentSnapshot = pSnapshot;
     4864
     4865    // now create the children
     4866    for (settings::SnapshotsList::const_iterator it = data.llChildSnapshots.begin();
     4867         it != data.llChildSnapshots.end();
     4868         ++it)
     4869    {
     4870        const settings::Snapshot &childData = *it;
     4871        // recurse
     4872        rc = loadSnapshot(childData,
     4873                          aCurSnapshotId,
     4874                          pSnapshot);       // parent = the one we created above
     4875        CheckComRCBreakRC(rc);
    51964876    }
    51974877
     
    52024882 *  @param aNode    <Hardware> node.
    52034883 */
    5204 HRESULT Machine::loadHardware (const settings::Key &aNode)
    5205 {
    5206     using namespace settings;
    5207 
    5208     AssertReturn(!aNode.isNull(), E_INVALIDARG);
     4884HRESULT Machine::loadHardware(const settings::Hardware &data)
     4885{
    52094886    AssertReturn(mType == IsMachine || mType == IsSnapshotMachine, E_FAIL);
    52104887
    52114888    HRESULT rc = S_OK;
    52124889
    5213     /* The hardware version attribute (optional). */
    5214     mHWData->mHWVersion = aNode.stringValue ("version");
    5215 
    5216     /* CPU node (currently not required) */
    5217     {
    5218         /* default value in case the node is not there */
    5219         mHWData->mHWVirtExEnabled             = true;
    5220         mHWData->mHWVirtExNestedPagingEnabled = false;
    5221         mHWData->mHWVirtExVPIDEnabled         = false;
    5222         mHWData->mPAEEnabled                  = false;
    5223 
    5224         Key cpuNode = aNode.findKey ("CPU");
    5225         if (!cpuNode.isNull())
    5226         {
    5227             Key hwVirtExNode = cpuNode.key ("HardwareVirtEx");
    5228             if (!hwVirtExNode.isNull())
    5229             {
    5230                 const char *enabled = hwVirtExNode.stringValue ("enabled");
    5231                 if      (strcmp (enabled, "true") == 0)
    5232                     mHWData->mHWVirtExEnabled = true;
    5233                 else
    5234                     mHWData->mHWVirtExEnabled = false;
    5235             }
    5236             /* HardwareVirtExNestedPaging (optional, default is false) */
    5237             Key HWVirtExNestedPagingNode = cpuNode.findKey ("HardwareVirtExNestedPaging");
    5238             if (!HWVirtExNestedPagingNode.isNull())
    5239             {
    5240                 mHWData->mHWVirtExNestedPagingEnabled = HWVirtExNestedPagingNode.value <bool> ("enabled");
    5241             }
    5242 
    5243             /* HardwareVirtExVPID (optional, default is false) */
    5244             Key HWVirtExVPIDNode = cpuNode.findKey ("HardwareVirtExVPID");
    5245             if (!HWVirtExVPIDNode.isNull())
    5246             {
    5247                 mHWData->mHWVirtExVPIDEnabled = HWVirtExVPIDNode.value <bool> ("enabled");
    5248             }
    5249 
    5250             /* PAE (optional, default is false) */
    5251             Key PAENode = cpuNode.findKey ("PAE");
    5252             if (!PAENode.isNull())
    5253             {
    5254                 mHWData->mPAEEnabled = PAENode.value <bool> ("enabled");
    5255             }
    5256 
    5257             /* CPUCount (optional, default is 1) */
    5258             mHWData->mCPUCount = cpuNode.value <ULONG> ("count");
    5259         }
    5260     }
    5261 
    5262     /* Memory node (required) */
    5263     {
    5264         Key memoryNode = aNode.key ("Memory");
    5265 
    5266         mHWData->mMemorySize = memoryNode.value <ULONG> ("RAMSize");
    5267     }
    5268 
    5269     /* Boot node (required) */
    5270     {
    5271         /* reset all boot order positions to NoDevice */
    5272         for (size_t i = 0; i < RT_ELEMENTS (mHWData->mBootOrder); i++)
    5273             mHWData->mBootOrder [i] = DeviceType_Null;
    5274 
    5275         Key bootNode = aNode.key ("Boot");
    5276 
    5277         Key::List orderNodes = bootNode.keys ("Order");
    5278         for (Key::List::const_iterator it = orderNodes.begin();
    5279              it != orderNodes.end(); ++ it)
    5280         {
    5281             /* position (required) */
    5282             /* position unicity is guaranteed by XML Schema */
    5283             uint32_t position = (*it).value <uint32_t> ("position");
    5284             -- position;
    5285             Assert (position < RT_ELEMENTS (mHWData->mBootOrder));
    5286 
    5287             /* device (required) */
    5288             const char *device = (*it).stringValue ("device");
    5289             if      (strcmp (device, "None") == 0)
    5290                 mHWData->mBootOrder [position] = DeviceType_Null;
    5291             else if (strcmp (device, "Floppy") == 0)
    5292                 mHWData->mBootOrder [position] = DeviceType_Floppy;
    5293             else if (strcmp (device, "DVD") == 0)
    5294                 mHWData->mBootOrder [position] = DeviceType_DVD;
    5295             else if (strcmp (device, "HardDisk") == 0)
    5296                 mHWData->mBootOrder [position] = DeviceType_HardDisk;
    5297             else if (strcmp (device, "Network") == 0)
    5298                 mHWData->mBootOrder [position] = DeviceType_Network;
     4890    try
     4891    {
     4892        /* The hardware version attribute (optional). */
     4893        mHWData->mHWVersion = data.strVersion;
     4894
     4895        mHWData->mHWVirtExEnabled             = data.fHardwareVirt;
     4896        mHWData->mHWVirtExNestedPagingEnabled = data.fNestedPaging;
     4897        mHWData->mHWVirtExVPIDEnabled         = data.fVPID;
     4898        mHWData->mPAEEnabled                  = data.fPAE;
     4899
     4900        mHWData->mCPUCount = data.cCPUs;
     4901
     4902        mHWData->mMemorySize = data.ulMemorySizeMB;
     4903
     4904        // boot order
     4905        for (size_t i = 0;
     4906             i < RT_ELEMENTS(mHWData->mBootOrder);
     4907             i++)
     4908        {
     4909            settings::BootOrderMap::const_iterator it = data.mapBootOrder.find(i);
     4910            if (it == data.mapBootOrder.end())
     4911                mHWData->mBootOrder[i] = DeviceType_Null;
    52994912            else
    5300                 ComAssertMsgFailed (("Invalid device: %s", device));
    5301         }
    5302     }
    5303 
    5304     /* Display node (required) */
    5305     {
    5306         Key displayNode = aNode.key ("Display");
    5307 
    5308         mHWData->mVRAMSize      = displayNode.value <ULONG> ("VRAMSize");
    5309         mHWData->mMonitorCount  = displayNode.value <ULONG> ("monitorCount");
    5310         mHWData->mAccelerate3DEnabled = displayNode.value <bool> ("accelerate3D");
    5311         mHWData->mAccelerate2DVideoEnabled = displayNode.value <bool> ("accelerate2DVideo");
    5312     }
     4913                mHWData->mBootOrder[i] = it->second;
     4914        }
     4915
     4916        mHWData->mVRAMSize      = data.ulVRAMSizeMB;
     4917        mHWData->mMonitorCount  = data.cMonitors;
     4918        mHWData->mAccelerate3DEnabled = data.fAccelerate3D;
     4919        mHWData->mAccelerate2DVideoEnabled = data.fAccelerate2DVideo;
    53134920
    53144921#ifdef VBOX_WITH_VRDP
    5315     /* RemoteDisplay */
    5316     rc = mVRDPServer->loadSettings (aNode);
    5317     CheckComRCReturnRC(rc);
     4922        /* RemoteDisplay */
     4923        rc = mVRDPServer->loadSettings(data.vrdpSettings);
     4924        CheckComRCReturnRC (rc);
    53184925#endif
    53194926
    5320     /* BIOS */
    5321     rc = mBIOSSettings->loadSettings (aNode);
    5322     CheckComRCReturnRC(rc);
    5323 
    5324     /* DVD drive */
    5325     rc = mDVDDrive->loadSettings (aNode);
    5326     CheckComRCReturnRC(rc);
    5327 
    5328     /* Floppy drive */
    5329     rc = mFloppyDrive->loadSettings (aNode);
    5330     CheckComRCReturnRC(rc);
    5331 
    5332     /* USB Controller */
    5333     rc = mUSBController->loadSettings (aNode);
    5334     CheckComRCReturnRC(rc);
    5335 
    5336     /* Network node (required) */
    5337     {
    5338         /* we assume that all network adapters are initially disabled
    5339          * and detached */
    5340 
    5341         Key networkNode = aNode.key ("Network");
    5342 
    5343         rc = S_OK;
    5344 
    5345         Key::List adapters = networkNode.keys ("Adapter");
    5346         for (Key::List::const_iterator it = adapters.begin();
    5347              it != adapters.end(); ++ it)
    5348         {
    5349             /* slot number (required) */
     4927        /* BIOS */
     4928        rc = mBIOSSettings->loadSettings(data.biosSettings);
     4929        CheckComRCReturnRC (rc);
     4930
     4931        /* DVD drive */
     4932        rc = mDVDDrive->loadSettings(data.dvdDrive);
     4933        CheckComRCReturnRC (rc);
     4934
     4935        /* Floppy drive */
     4936        rc = mFloppyDrive->loadSettings(data.floppyDrive);
     4937        CheckComRCReturnRC (rc);
     4938
     4939        /* USB Controller */
     4940        rc = mUSBController->loadSettings(data.usbController);
     4941        CheckComRCReturnRC (rc);
     4942
     4943        // network adapters
     4944        for (settings::NetworkAdaptersList::const_iterator it = data.llNetworkAdapters.begin();
     4945            it != data.llNetworkAdapters.end();
     4946            ++it)
     4947        {
     4948            const settings::NetworkAdapter &nic = *it;
     4949
    53504950            /* slot unicity is guaranteed by XML Schema */
    5351             uint32_t slot = (*it).value <uint32_t> ("slot");
    5352             AssertBreak (slot < RT_ELEMENTS (mNetworkAdapters));
    5353 
    5354             rc = mNetworkAdapters [slot]->loadSettings (*it);
    5355             CheckComRCReturnRC(rc);
    5356         }
    5357     }
    5358 
    5359     /* Serial node (required) */
    5360     {
    5361         Key serialNode = aNode.key ("UART");
    5362 
    5363         rc = S_OK;
    5364 
    5365         Key::List ports = serialNode.keys ("Port");
    5366         for (Key::List::const_iterator it = ports.begin();
    5367              it != ports.end(); ++ it)
    5368         {
    5369             /* slot number (required) */
    5370             /* slot unicity is guaranteed by XML Schema */
    5371             uint32_t slot = (*it).value <uint32_t> ("slot");
    5372             AssertBreak (slot < RT_ELEMENTS (mSerialPorts));
    5373 
    5374             rc = mSerialPorts [slot]->loadSettings (*it);
    5375             CheckComRCReturnRC(rc);
    5376         }
    5377     }
    5378 
    5379     /* Parallel node (optional) */
    5380     {
    5381         Key parallelNode = aNode.key ("LPT");
    5382 
    5383         rc = S_OK;
    5384 
    5385         Key::List ports = parallelNode.keys ("Port");
    5386         for (Key::List::const_iterator it = ports.begin();
    5387              it != ports.end(); ++ it)
    5388         {
    5389             /* slot number (required) */
    5390             /* slot unicity is guaranteed by XML Schema */
    5391             uint32_t slot = (*it).value <uint32_t> ("slot");
    5392             AssertBreak (slot < RT_ELEMENTS (mSerialPorts));
    5393 
    5394             rc = mParallelPorts [slot]->loadSettings (*it);
    5395             CheckComRCReturnRC(rc);
    5396         }
    5397     }
    5398 
    5399     /* AudioAdapter */
    5400     rc = mAudioAdapter->loadSettings (aNode);
    5401     CheckComRCReturnRC(rc);
    5402 
    5403     /* Shared folders (required) */
    5404     {
    5405         Key sharedFoldersNode = aNode.key ("SharedFolders");
    5406 
    5407         rc = S_OK;
    5408 
    5409         Key::List folders = sharedFoldersNode.keys ("SharedFolder");
    5410         for (Key::List::const_iterator it = folders.begin();
    5411              it != folders.end(); ++ it)
    5412         {
    5413             /* folder logical name (required) */
    5414             Bstr name = (*it).stringValue ("name");
    5415             /* folder host path (required) */
    5416             Bstr hostPath = (*it).stringValue ("hostPath");
    5417 
    5418             bool writable = (*it).value <bool> ("writable");
    5419 
    5420             rc = CreateSharedFolder (name, hostPath, writable);
    5421             CheckComRCReturnRC(rc);
    5422         }
    5423     }
    5424 
    5425     /* Clipboard node (required) */
    5426     {
    5427         Key clipNode = aNode.key ("Clipboard");
    5428 
    5429         const char *mode = clipNode.stringValue ("mode");
    5430         if      (strcmp (mode, "Disabled") == 0)
    5431             mHWData->mClipboardMode = ClipboardMode_Disabled;
    5432         else if (strcmp (mode, "HostToGuest") == 0)
    5433             mHWData->mClipboardMode = ClipboardMode_HostToGuest;
    5434         else if (strcmp (mode, "GuestToHost") == 0)
    5435             mHWData->mClipboardMode = ClipboardMode_GuestToHost;
    5436         else if (strcmp (mode, "Bidirectional") == 0)
    5437             mHWData->mClipboardMode = ClipboardMode_Bidirectional;
    5438         else
    5439             AssertMsgFailed (("Invalid clipboard mode '%s'\n", mode));
    5440     }
    5441 
    5442     /* Guest node (required) */
    5443     {
    5444         Key guestNode = aNode.key ("Guest");
    5445 
    5446         /* optional, defaults to 0 */
    5447         mHWData->mMemoryBalloonSize =
    5448             guestNode.value <ULONG> ("memoryBalloonSize");
    5449         /* optional, defaults to 0 */
    5450         mHWData->mStatisticsUpdateInterval =
    5451             guestNode.value <ULONG> ("statisticsUpdateInterval");
    5452     }
     4951            AssertBreak(nic.ulSlot < RT_ELEMENTS(mNetworkAdapters));
     4952            rc = mNetworkAdapters[nic.ulSlot]->loadSettings(nic);
     4953            CheckComRCReturnRC (rc);
     4954        }
     4955
     4956        // serial ports
     4957        for (settings::SerialPortsList::const_iterator it = data.llSerialPorts.begin();
     4958            it != data.llSerialPorts.end();
     4959            ++it)
     4960        {
     4961            const settings::SerialPort &s = *it;
     4962
     4963            AssertBreak(s.ulSlot < RT_ELEMENTS(mSerialPorts));
     4964            rc = mSerialPorts[s.ulSlot]->loadSettings(s);
     4965            CheckComRCReturnRC (rc);
     4966        }
     4967
     4968        // parallel ports (optional)
     4969        for (settings::ParallelPortsList::const_iterator it = data.llParallelPorts.begin();
     4970            it != data.llParallelPorts.end();
     4971            ++it)
     4972        {
     4973            const settings::ParallelPort &p = *it;
     4974
     4975            AssertBreak(p.ulSlot < RT_ELEMENTS(mParallelPorts));
     4976            rc = mParallelPorts[p.ulSlot]->loadSettings(p);
     4977            CheckComRCReturnRC (rc);
     4978        }
     4979
     4980        /* AudioAdapter */
     4981        rc = mAudioAdapter->loadSettings(data.audioAdapter);
     4982        CheckComRCReturnRC (rc);
     4983
     4984        for (settings::SharedFoldersList::const_iterator it = data.llSharedFolders.begin();
     4985             it != data.llSharedFolders.end();
     4986             ++it)
     4987        {
     4988            const settings::SharedFolder &sf = *it;
     4989            rc = CreateSharedFolder(Bstr(sf.strName), Bstr(sf.strHostPath), sf.fWritable);
     4990            CheckComRCReturnRC (rc);
     4991        }
     4992
     4993        // Clipboard
     4994        mHWData->mClipboardMode = data.clipboardMode;
     4995
     4996        // guest settings
     4997        mHWData->mMemoryBalloonSize = data.ulMemoryBalloonSize;
     4998        mHWData->mStatisticsUpdateInterval = data.ulStatisticsUpdateInterval;
    54534999
    54545000#ifdef VBOX_WITH_GUEST_PROPS
    5455     /* Guest properties (optional) */
    5456     try
    5457     {
    5458         using namespace guestProp;
    5459 
    5460         Key guestPropertiesNode = aNode.findKey ("GuestProperties");
    5461         Bstr notificationPatterns ("");  /* We catch allocation failure below. */
    5462         if (!guestPropertiesNode.isNull())
    5463         {
    5464             Key::List properties = guestPropertiesNode.keys ("GuestProperty");
    5465             for (Key::List::const_iterator it = properties.begin();
    5466                  it != properties.end(); ++ it)
    5467             {
    5468                 uint32_t fFlags = NILFLAG;
    5469 
    5470                 /* property name (required) */
    5471                 Bstr name = (*it).stringValue ("name");
    5472                 /* property value (required) */
    5473                 Bstr value = (*it).stringValue ("value");
    5474                 /* property timestamp (optional, defaults to 0) */
    5475                 ULONG64 timestamp = (*it).value<ULONG64> ("timestamp");
    5476                 /* property flags (optional, defaults to empty) */
    5477                 Bstr flags = (*it).stringValue ("flags");
    5478                 Utf8Str utf8Flags(flags);
    5479                 validateFlags (utf8Flags.raw(), &fFlags);
    5480                 HWData::GuestProperty property = { name, value, timestamp, fFlags };
    5481                 mHWData->mGuestProperties.push_back (property);
    5482                 /* This is just sanity, as the push_back() will probably have thrown
    5483                  * an exception if we are out of memory.  Note that if we run out
    5484                  * allocating the Bstrs above, this will be caught here as well. */
    5485                 if (   mHWData->mGuestProperties.back().mName.isNull ()
    5486                     || mHWData->mGuestProperties.back().mValue.isNull ()
    5487                    )
    5488                     return E_OUTOFMEMORY;
    5489             }
    5490             notificationPatterns = guestPropertiesNode.stringValue ("notificationPatterns");
    5491         }
     5001        /* Guest properties (optional) */
     5002        for (settings::GuestPropertiesList::const_iterator it = data.llGuestProperties.begin();
     5003            it != data.llGuestProperties.end();
     5004            ++it)
     5005        {
     5006            const settings::GuestProperty &prop = *it;
     5007            uint32_t fFlags = guestProp::NILFLAG;
     5008            guestProp::validateFlags(prop.strFlags.c_str(), &fFlags);
     5009            HWData::GuestProperty property = { prop.strName, prop.strValue, prop.timestamp, fFlags };
     5010            mHWData->mGuestProperties.push_back(property);
     5011        }
     5012
    54925013        mHWData->mPropertyServiceActive = false;
    5493         mHWData->mGuestPropertyNotificationPatterns = notificationPatterns;
    5494         if (mHWData->mGuestPropertyNotificationPatterns.isNull ())
    5495             return E_OUTOFMEMORY;
     5014        mHWData->mGuestPropertyNotificationPatterns = data.strNotificationPatterns;
     5015#endif /* VBOX_WITH_GUEST_PROPS defined */
    54965016    }
    54975017    catch(std::bad_alloc &e)
     
    54995019        return E_OUTOFMEMORY;
    55005020    }
    5501 #endif /* VBOX_WITH_GUEST_PROPS defined */
    5502 
    5503     AssertComRC (rc);
     5021
     5022    AssertComRC(rc);
    55045023    return rc;
    55055024}
    55065025
    5507 /**
    5508  *  @param aNode    <StorageControllers> node.
    5509  */
    5510 HRESULT Machine::loadStorageControllers (const settings::Key &aNode, bool aRegistered,
    5511                                          const Guid *aSnapshotId /* = NULL */)
    5512 {
    5513     using namespace settings;
    5514 
    5515     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    5516     AssertReturn(mType == IsMachine || mType == IsSnapshotMachine, E_FAIL);
     5026  /**
     5027   *  @param aNode    <StorageControllers> node.
     5028   */
     5029HRESULT Machine::loadStorageControllers(const settings::Storage &data,
     5030                                        bool aRegistered,
     5031                                        const Guid *aSnapshotId /* = NULL */)
     5032{
     5033    AssertReturn (mType == IsMachine || mType == IsSnapshotMachine, E_FAIL);
    55175034
    55185035    HRESULT rc = S_OK;
    5519 
    5520     Key::List children = aNode.keys ("StorageController");
    55215036
    55225037    /* Make sure the attached hard disks don't get unregistered until we
    55235038     * associate them with tis machine (important for VMs loaded (opened) after
    55245039     * VirtualBox startup) */
    5525     AutoReadLock vboxLock (mParent);
    5526 
    5527     for (Key::List::const_iterator it = children.begin();
    5528          it != children.end(); ++ it)
    5529     {
    5530         Bstr controllerName = (*it).stringValue ("name");
    5531         const char *controllerType = (*it).stringValue ("type");
    5532         ULONG portCount = (*it).value <ULONG> ("PortCount");
    5533         StorageControllerType_T controller;
    5534         StorageBus_T connection;
    5535 
    5536         if (strcmp (controllerType, "AHCI") == 0)
    5537         {
    5538             connection = StorageBus_SATA;
    5539             controller = StorageControllerType_IntelAhci;
    5540         }
    5541         else if (strcmp (controllerType, "LsiLogic") == 0)
    5542         {
    5543             connection = StorageBus_SCSI;
    5544             controller = StorageControllerType_LsiLogic;
    5545         }
    5546         else if (strcmp (controllerType, "BusLogic") == 0)
    5547         {
    5548             connection = StorageBus_SCSI;
    5549             controller = StorageControllerType_BusLogic;
    5550         }
    5551         else if (strcmp (controllerType, "PIIX3") == 0)
    5552         {
    5553             connection = StorageBus_IDE;
    5554             controller = StorageControllerType_PIIX3;
    5555         }
    5556         else if (strcmp (controllerType, "PIIX4") == 0)
    5557         {
    5558             connection = StorageBus_IDE;
    5559             controller = StorageControllerType_PIIX4;
    5560         }
    5561         else if (strcmp (controllerType, "ICH6") == 0)
    5562         {
    5563             connection = StorageBus_IDE;
    5564             controller = StorageControllerType_ICH6;
    5565         }
    5566         else
    5567             AssertFailedReturn (E_FAIL);
    5568 
    5569         ComObjPtr<StorageController> ctl;
     5040    AutoReadLock vboxLock(mParent);
     5041
     5042    for (settings::StorageControllersList::const_iterator it = data.llStorageControllers.begin();
     5043         it != data.llStorageControllers.end();
     5044         ++it)
     5045    {
     5046        const settings::StorageController &ctlData = *it;
     5047
     5048        ComObjPtr<StorageController> pCtl;
    55705049        /* Try to find one with the name first. */
    5571         rc = getStorageControllerByName (controllerName, ctl, false /* aSetError */);
     5050        rc = getStorageControllerByName(ctlData.strName, pCtl, false /* aSetError */);
    55725051        if (SUCCEEDED(rc))
    5573             return setError (VBOX_E_OBJECT_IN_USE,
    5574                 tr ("Storage controller named '%ls' already exists"), controllerName.raw());
    5575 
    5576         ctl.createObject();
    5577         rc = ctl->init (this, controllerName, connection);
    5578         CheckComRCReturnRC(rc);
    5579 
    5580         mStorageControllers->push_back (ctl);
    5581 
    5582         rc = ctl->COMSETTER(ControllerType)(controller);
    5583         CheckComRCReturnRC(rc);
    5584 
    5585         rc = ctl->COMSETTER(PortCount)(portCount);
    5586         CheckComRCReturnRC(rc);
     5052            return setError(VBOX_E_OBJECT_IN_USE,
     5053                            tr("Storage controller named '%s' already exists"),
     5054                            ctlData.strName.raw());
     5055
     5056        pCtl.createObject();
     5057        rc = pCtl->init(this,
     5058                        ctlData.strName,
     5059                        ctlData.storageBus);
     5060        CheckComRCReturnRC (rc);
     5061
     5062        mStorageControllers->push_back(pCtl);
     5063
     5064        rc = pCtl->COMSETTER(ControllerType)(ctlData.controllerType);
     5065        CheckComRCReturnRC (rc);
     5066
     5067        rc = pCtl->COMSETTER(PortCount)(ctlData.ulPortCount);
     5068        CheckComRCReturnRC (rc);
    55875069
    55885070        /* Set IDE emulation settings (only for AHCI controller). */
    5589         if (controller == StorageControllerType_IntelAhci)
    5590         {
    5591             ULONG val;
    5592 
    5593             /* ide emulation settings (optional, default to 0,1,2,3 respectively) */
    5594             val = (*it).valueOr <ULONG> ("IDE0MasterEmulationPort", 0);
    5595             rc = ctl->SetIDEEmulationPort(0, val);
    5596             CheckComRCReturnRC(rc);
    5597             val = (*it).valueOr <ULONG> ("IDE0SlaveEmulationPort", 1);
    5598             rc = ctl->SetIDEEmulationPort(1, val);
    5599             CheckComRCReturnRC(rc);
    5600             val = (*it).valueOr <ULONG> ("IDE1MasterEmulationPort", 2);
    5601             rc = ctl->SetIDEEmulationPort(2, val);
    5602             CheckComRCReturnRC(rc);
    5603             val = (*it).valueOr <ULONG> ("IDE1SlaveEmulationPort", 3);
    5604             rc = ctl->SetIDEEmulationPort(3, val);
    5605             CheckComRCReturnRC(rc);
     5071        if (ctlData.controllerType == StorageControllerType_IntelAhci)
     5072        {
     5073            if (    (FAILED(rc = pCtl->SetIDEEmulationPort(0, ctlData.lIDE0MasterEmulationPort)))
     5074                 || (FAILED(rc = pCtl->SetIDEEmulationPort(1, ctlData.lIDE0SlaveEmulationPort)))
     5075                 || (FAILED(rc = pCtl->SetIDEEmulationPort(2, ctlData.lIDE1MasterEmulationPort)))
     5076                 || (FAILED(rc = pCtl->SetIDEEmulationPort(3, ctlData.lIDE1SlaveEmulationPort)))
     5077               )
     5078                return rc;
    56065079        }
    56075080
    56085081        /* Load the attached devices now. */
    5609         rc = loadStorageDevices(ctl, (*it),
    5610                                 aRegistered, aSnapshotId);
    5611         CheckComRCReturnRC(rc);
     5082        rc = loadStorageDevices(pCtl, ctlData,
     5083                                aRegistered,
     5084                                aSnapshotId);
     5085        CheckComRCReturnRC (rc);
    56125086    }
    56135087
     
    56245098 * @note Lock mParent for reading and hard disks for writing before calling.
    56255099 */
    5626 HRESULT Machine::loadStorageDevices (ComObjPtr<StorageController> aStorageController,
    5627                                      const settings::Key &aNode, bool aRegistered,
    5628                                      const Guid *aSnapshotId /* = NULL */)
    5629 {
    5630     using namespace settings;
    5631 
    5632     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    5633     AssertReturn((mType == IsMachine && aSnapshotId == NULL) ||
     5100HRESULT Machine::loadStorageDevices(StorageController *aStorageController,
     5101                                    const settings::StorageController &data,
     5102                                    bool aRegistered,
     5103                                    const Guid *aSnapshotId /*= NULL*/)
     5104{
     5105    AssertReturn ((mType == IsMachine && aSnapshotId == NULL) ||
    56345106                  (mType == IsSnapshotMachine && aSnapshotId != NULL), E_FAIL);
    56355107
    56365108    HRESULT rc = S_OK;
    56375109
    5638     Key::List children = aNode.keys ("AttachedDevice");
    5639 
    5640     if (!aRegistered && children.size() > 0)
    5641     {
     5110    if (!aRegistered && data.llAttachedDevices.size() > 0)
    56425111        /* when the machine is being loaded (opened) from a file, it cannot
    56435112         * have hard disks attached (this should not happen normally,
    56445113         * because we don't allow to attach hard disks to an unregistered
    56455114         * VM at all */
    5646         return setError (E_FAIL,
    5647             tr ("Unregistered machine '%ls' cannot have hard disks attached "
    5648                 "(found %d hard disk attachments)"),
    5649             mUserData->mName.raw(), children.size());
    5650     }
    5651 
    5652     for (Key::List::const_iterator it = children.begin();
    5653          it != children.end(); ++ it)
    5654     {
    5655         Key idKey = (*it).key ("Image");
    5656         /* hard disk uuid (required) */
    5657         Guid uuid = idKey.value <Guid> ("uuid");
    5658         /* device type (required) */
    5659         const char *deviceType = (*it).stringValue ("type");
    5660         /* channel (required) */
    5661         LONG port = (*it).value <LONG> ("port");
    5662         /* device (required) */
    5663         LONG device = (*it).value <LONG> ("device");
    5664 
    5665         /* We support only hard disk types at the moment.
    5666          * @todo: Implement support for CD/DVD drives.
    5667          */
    5668         if (strcmp(deviceType, "HardDisk") != 0)
    5669             return setError (E_FAIL,
    5670                 tr ("Device at position %lu:%lu is not a hard disk: %s"),
    5671                 port, device, deviceType);
     5115        return setError(E_FAIL,
     5116                        tr("Unregistered machine '%ls' cannot have hard disks attached (found %d hard disk attachments)"),
     5117                        mUserData->mName.raw(),
     5118                        data.llAttachedDevices.size());
     5119
     5120    for (settings::AttachedDevicesList::const_iterator it = data.llAttachedDevices.begin();
     5121         it != data.llAttachedDevices.end();
     5122         ++it)
     5123    {
     5124        const settings::AttachedDevice &dev = *it;
    56725125
    56735126        /* find a hard disk by UUID */
    5674         ComObjPtr<HardDisk> hd;
    5675         rc = mParent->findHardDisk(&uuid, NULL, true /* aDoSetError */, &hd);
    5676         CheckComRCReturnRC(rc);
    5677 
    5678         AutoWriteLock hdLock (hd);
    5679 
    5680         if (hd->type() == HardDiskType_Immutable)
     5127        ComObjPtr<HardDisk> pDisk;
     5128        rc = mParent->findHardDisk(&dev.uuid, NULL, true /* aDoSetError */, &pDisk);
     5129        CheckComRCReturnRC (rc);
     5130
     5131        AutoWriteLock hdLock(pDisk);
     5132
     5133        if (pDisk->type() == HardDiskType_Immutable)
    56815134        {
    56825135            if (mType == IsSnapshotMachine)
    5683                 return setError (E_FAIL,
    5684                     tr ("Immutable hard disk '%ls' with UUID {%RTuuid} cannot be "
    5685                         "directly attached to snapshot with UUID {%RTuuid} "
    5686                         "of the virtual machine '%ls' ('%ls')"),
    5687                     hd->locationFull().raw(), uuid.raw(),
    5688                     aSnapshotId->raw(),
    5689                     mUserData->mName.raw(), mData->mConfigFileFull.raw());
    5690 
    5691             return setError (E_FAIL,
    5692                 tr ("Immutable hard disk '%ls' with UUID {%RTuuid} cannot be "
    5693                     "directly attached to the virtual machine '%ls' ('%ls')"),
    5694                 hd->locationFull().raw(), uuid.raw(),
    5695                 mUserData->mName.raw(), mData->mConfigFileFull.raw());
    5696         }
    5697 
    5698         if (mType != IsSnapshotMachine && hd->children().size() != 0)
    5699             return setError (E_FAIL,
    5700                 tr ("Hard disk '%ls' with UUID {%RTuuid} cannot be directly "
    5701                     "attached to the virtual machine '%ls' ('%ls') "
    5702                     "because it has %d differencing child hard disks"),
    5703                 hd->locationFull().raw(), uuid.raw(),
    5704                 mUserData->mName.raw(), mData->mConfigFileFull.raw(),
    5705                 hd->children().size());
    5706 
    5707         if (std::find_if (mHDData->mAttachments.begin(),
    5708                           mHDData->mAttachments.end(),
    5709                           HardDiskAttachment::RefersTo (hd)) !=
    5710                 mHDData->mAttachments.end())
    5711         {
    5712             return setError (E_FAIL,
    5713                 tr ("Hard disk '%ls' with UUID {%RTuuid} is already attached "
    5714                     "to the virtual machine '%ls' ('%ls')"),
    5715                 hd->locationFull().raw(), uuid.raw(),
    5716                 mUserData->mName.raw(), mData->mConfigFileFull.raw());
     5136                return setError(E_FAIL,
     5137                                tr("Immutable hard disk '%ls' with UUID {%RTuuid} cannot be directly attached to snapshot with UUID {%RTuuid} "
     5138                                   "of the virtual machine '%ls' ('%s')"),
     5139                                pDisk->locationFull().raw(),
     5140                                dev.uuid.raw(),
     5141                                aSnapshotId->raw(),
     5142                                mUserData->mName.raw(),
     5143                                mData->m_strConfigFileFull.raw());
     5144
     5145            return setError(E_FAIL,
     5146                            tr("Immutable hard disk '%ls' with UUID {%RTuuid} cannot be directly attached to the virtual machine '%ls' ('%s')"),
     5147                            pDisk->locationFull().raw(),
     5148                            dev.uuid.raw(),
     5149                            mUserData->mName.raw(),
     5150                            mData->m_strConfigFileFull.raw());
     5151        }
     5152
     5153        if (    mType != IsSnapshotMachine
     5154             && pDisk->children().size() != 0
     5155           )
     5156            return setError(E_FAIL,
     5157                            tr("Hard disk '%ls' with UUID {%RTuuid} cannot be directly attached to the virtual machine '%ls' ('%s') "
     5158                               "because it has %d differencing child hard disks"),
     5159                            pDisk->locationFull().raw(),
     5160                            dev.uuid.raw(),
     5161                            mUserData->mName.raw(),
     5162                            mData->m_strConfigFileFull.raw(),
     5163                            pDisk->children().size());
     5164
     5165        if (std::find_if(mHDData->mAttachments.begin(),
     5166                         mHDData->mAttachments.end(),
     5167                         HardDiskAttachment::RefersTo(pDisk))
     5168            != mHDData->mAttachments.end())
     5169        {
     5170            return setError(E_FAIL,
     5171                            tr("Hard disk '%ls' with UUID {%RTuuid} is already attached to the virtual machine '%ls' ('%s')"),
     5172                            pDisk->locationFull().raw(),
     5173                            dev.uuid.raw(),
     5174                            mUserData->mName.raw(),
     5175                            mData->m_strConfigFileFull.raw());
    57175176        }
    57185177
    57195178        const Bstr controllerName = aStorageController->name();
    5720         ComObjPtr<HardDiskAttachment> attachment;
    5721         attachment.createObject();
    5722         rc = attachment->init (hd, controllerName, port, device);
    5723         CheckComRCBreakRC (rc);
     5179        ComObjPtr<HardDiskAttachment> pAttachment;
     5180        pAttachment.createObject();
     5181        rc = pAttachment->init(pDisk,
     5182                               controllerName,
     5183                               dev.lPort,
     5184                               dev.lDevice);
     5185        CheckComRCBreakRC(rc);
    57245186
    57255187        /* associate the hard disk with this machine and snapshot */
    57265188        if (mType == IsSnapshotMachine)
    5727             rc = hd->attachTo (mData->mUuid, *aSnapshotId);
     5189            rc = pDisk->attachTo(mData->mUuid, *aSnapshotId);
    57285190        else
    5729             rc = hd->attachTo (mData->mUuid);
     5191            rc = pDisk->attachTo(mData->mUuid);
    57305192
    57315193        AssertComRCBreakRC (rc);
     
    57355197
    57365198        mHDData.backup();
    5737         mHDData->mAttachments.push_back (attachment);
     5199        mHDData->mAttachments.push_back(pAttachment);
    57385200    }
    57395201
     
    57425204
    57435205/**
    5744  *  Searches for a <Snapshot> node for the given snapshot.
    5745  *  If the search is successful, \a aSnapshotNode will contain the found node.
    5746  *  In this case, \a aSnapshotsNode can be NULL meaning the found node is a
    5747  *  direct child of \a aMachineNode.
    5748  *
    5749  *  If the search fails, a failure is returned and both \a aSnapshotsNode and
    5750  *  \a aSnapshotNode are set to 0.
    5751  *
    5752  *  @param aSnapshot        Snapshot to search for.
    5753  *  @param aMachineNode     <Machine> node to start from.
    5754  *  @param aSnapshotsNode   <Snapshots> node containing the found <Snapshot> node
    5755  *                          (may be NULL if the caller is not interested).
    5756  *  @param aSnapshotNode    Found <Snapshot> node.
    5757  */
    5758 HRESULT Machine::findSnapshotNode (Snapshot *aSnapshot, settings::Key &aMachineNode,
    5759                                    settings::Key *aSnapshotsNode,
    5760                                    settings::Key *aSnapshotNode)
    5761 {
    5762     using namespace settings;
    5763 
    5764     AssertReturn(aSnapshot && !aMachineNode.isNull()
    5765                   && aSnapshotNode != NULL, E_FAIL);
    5766 
    5767     if (aSnapshotsNode)
    5768         aSnapshotsNode->setNull();
    5769     aSnapshotNode->setNull();
    5770 
    5771     // build the full uuid path (from the top parent to the given snapshot)
    5772     std::list<Guid> path;
    5773     {
    5774         ComObjPtr<Snapshot> parent = aSnapshot;
    5775         while (parent)
    5776         {
    5777             path.push_front(parent->getId());
    5778             parent = parent->parent();
    5779         }
    5780     }
    5781 
    5782     Key snapshotsNode = aMachineNode;
    5783     Key snapshotNode;
    5784 
    5785     for (std::list <Guid>::const_iterator it = path.begin();
    5786          it != path.end();
    5787          ++ it)
    5788     {
    5789         if (!snapshotNode.isNull())
    5790         {
    5791             /* proceed to the nested <Snapshots> node */
    5792             snapshotsNode = snapshotNode.key ("Snapshots");
    5793             snapshotNode.setNull();
    5794         }
    5795 
    5796         AssertReturn(!snapshotsNode.isNull(), E_FAIL);
    5797 
    5798         Key::List children = snapshotsNode.keys ("Snapshot");
    5799         for (Key::List::const_iterator ch = children.begin();
    5800              ch != children.end();
    5801              ++ ch)
    5802         {
    5803             Guid id = (*ch).value <Guid> ("uuid");
    5804             if (id == (*it))
    5805             {
    5806                 /* pass over to the outer loop */
    5807                 snapshotNode = *ch;
    5808                 break;
    5809             }
    5810         }
    5811 
    5812         if (!snapshotNode.isNull())
    5813             continue;
    5814 
    5815         /* the next uuid is not found, no need to continue... */
    5816         AssertFailedBreak();
    5817     }
    5818 
    5819     // we must always succesfully find the node
    5820     AssertReturn(!snapshotNode.isNull(), E_FAIL);
    5821     AssertReturn(!snapshotsNode.isNull(), E_FAIL);
    5822 
    5823     if (aSnapshotsNode && (snapshotsNode != aMachineNode))
    5824         *aSnapshotsNode = snapshotsNode;
    5825     *aSnapshotNode = snapshotNode;
    5826 
    5827     return S_OK;
    5828 }
    5829 
    5830 /**
    5831  *  Returns the snapshot with the given UUID or fails of no such snapshot.
     5206 *  Returns the snapshot with the given UUID or fails of no such snapshot exists.
    58325207 *
    58335208 *  @param aId          snapshot UUID to find (empty UUID refers the first snapshot)
     
    58445219    {
    58455220        if (aSetError)
    5846             return setError (E_FAIL,
    5847                 tr ("This machine does not have any snapshots"));
     5221            return setError(E_FAIL,
     5222                            tr("This machine does not have any snapshots"));
    58485223        return E_FAIL;
    58495224    }
     
    58525227        aSnapshot = mData->mFirstSnapshot;
    58535228    else
    5854         aSnapshot = mData->mFirstSnapshot->findChildOrSelf (aId);
     5229        aSnapshot = mData->mFirstSnapshot->findChildOrSelf(aId);
    58555230
    58565231    if (!aSnapshot)
    58575232    {
    58585233        if (aSetError)
    5859             return setError (E_FAIL,
    5860                 tr ("Could not find a snapshot with UUID {%s}"),
    5861                 aId.toString().raw());
     5234            return setError(E_FAIL,
     5235                            tr("Could not find a snapshot with UUID {%s}"),
     5236                            aId.toString().raw());
    58625237        return E_FAIL;
    58635238    }
     
    58845259    {
    58855260        if (aSetError)
    5886             return setError (VBOX_E_OBJECT_NOT_FOUND,
    5887                 tr ("This machine does not have any snapshots"));
     5261            return setError(VBOX_E_OBJECT_NOT_FOUND,
     5262                            tr("This machine does not have any snapshots"));
    58885263        return VBOX_E_OBJECT_NOT_FOUND;
    58895264    }
     
    58945269    {
    58955270        if (aSetError)
    5896             return setError (VBOX_E_OBJECT_NOT_FOUND,
    5897                 tr ("Could not find a snapshot named '%ls'"), aName);
     5271            return setError(VBOX_E_OBJECT_NOT_FOUND,
     5272                            tr("Could not find a snapshot named '%ls'"), aName);
    58985273        return VBOX_E_OBJECT_NOT_FOUND;
    58995274    }
     
    59095284 *  @param aSetError             true to set extended error info on failure
    59105285 */
    5911 HRESULT Machine::getStorageControllerByName(CBSTR aName,
     5286HRESULT Machine::getStorageControllerByName(const Utf8Str &aName,
    59125287                                            ComObjPtr<StorageController> &aStorageController,
    59135288                                            bool aSetError /* = false */)
    59145289{
    5915     AssertReturn(aName, E_INVALIDARG);
    5916 
    5917     for (StorageControllerList::const_iterator it =
    5918                 mStorageControllers->begin();
    5919             it != mStorageControllers->end();
    5920             ++ it)
     5290    AssertReturn (!aName.isEmpty(), E_INVALIDARG);
     5291
     5292    for (StorageControllerList::const_iterator it = mStorageControllers->begin();
     5293         it != mStorageControllers->end();
     5294         ++it)
    59215295    {
    59225296        if ((*it)->name() == aName)
     
    59285302
    59295303    if (aSetError)
    5930         return setError (VBOX_E_OBJECT_NOT_FOUND,
    5931             tr ("Could not find a storage controller named '%ls'"), aName);
     5304        return setError(VBOX_E_OBJECT_NOT_FOUND,
     5305                        tr("Could not find a storage controller named '%s'"),
     5306                        aName.raw());
    59325307    return VBOX_E_OBJECT_NOT_FOUND;
    59335308}
     
    59635338 *  @param aNew     receives |true| if a virgin settings file was created.
    59645339 */
    5965 HRESULT Machine::prepareSaveSettings (bool &aRenamed, bool &aNew)
     5340HRESULT Machine::prepareSaveSettings(bool &aRenamed,
     5341                                     bool &aNew)
    59665342{
    59675343    /* Note: tecnhically, mParent needs to be locked only when the machine is
     
    59785354    /* if we're ready and isConfigLocked() is FALSE then it means
    59795355     * that no config file exists yet (we will create a virgin one) */
    5980     aNew = !isConfigLocked();
     5356    aNew = !mData->m_pMachineConfigFile->fileExists();
    59815357
    59825358    /* attempt to rename the settings file if machine name is changed */
    5983     if (mUserData->mNameSync &&
    5984         mUserData.isBackedUp() &&
    5985         mUserData.backedUpData()->mName != mUserData->mName)
     5359    if (    mUserData->mNameSync
     5360         && mUserData.isBackedUp()
     5361         && mUserData.backedUpData()->mName != mUserData->mName
     5362       )
    59865363    {
    59875364        aRenamed = true;
    5988 
    5989         if (!aNew)
    5990         {
    5991             /* unlock the old config file */
    5992             rc = unlockConfig();
    5993             CheckComRCReturnRC(rc);
    5994         }
    59955365
    59965366        bool dirRenamed = false;
     
    60075377            Utf8Str newName = mUserData->mName;
    60085378
    6009             configFile = mData->mConfigFileFull;
     5379            configFile = mData->m_strConfigFileFull;
    60105380
    60115381            /* first, rename the directory if it matches the machine name */
     
    60135383            configDir.stripFilename();
    60145384            newConfigDir = configDir;
    6015             if (RTPathFilename(configDir) == name)
     5385            if (!strcmp(RTPathFilename(configDir.c_str()), name.c_str()))
    60165386            {
    60175387                newConfigDir.stripFilename();
     
    60275397                    if (RT_FAILURE(vrc))
    60285398                    {
    6029                         rc = setError (E_FAIL,
    6030                             tr ("Could not rename the directory '%s' to '%s' "
    6031                                 "to save the settings file (%Rrc)"),
    6032                             configDir.raw(), newConfigDir.raw(), vrc);
     5399                        rc = setError(E_FAIL,
     5400                                      tr("Could not rename the directory '%s' to '%s' to save the settings file (%Rrc)"),
     5401                                      configDir.raw(),
     5402                                      newConfigDir.raw(),
     5403                                      vrc);
    60335404                        break;
    60345405                    }
     
    60445415            {
    60455416                /* get the path to old settings file in renamed directory */
    6046                 configFile = Utf8StrFmt ("%s%c%s",
    6047                         newConfigDir.raw(), RTPATH_DELIMITER,
    6048                         RTPathFilename (configFile));
     5417                configFile = Utf8StrFmt("%s%c%s",
     5418                                        newConfigDir.raw(),
     5419                                        RTPATH_DELIMITER,
     5420                                        RTPathFilename(configFile.c_str()));
    60495421                if (!aNew)
    60505422                {
     
    60535425                    if (RT_FAILURE(vrc))
    60545426                    {
    6055                         rc = setError (E_FAIL,
    6056                             tr ("Could not rename the settings file '%s' to '%s' "
    6057                                 "(%Rrc)"),
    6058                             configFile.raw(), newConfigFile.raw(), vrc);
     5427                        rc = setError(E_FAIL,
     5428                                      tr("Could not rename the settings file '%s' to '%s' (%Rrc)"),
     5429                                      configFile.raw(),
     5430                                      newConfigFile.raw(),
     5431                                      vrc);
    60595432                        break;
    60605433                    }
     
    60645437
    60655438            /* update mConfigFileFull amd mConfigFile */
    6066             Bstr oldConfigFileFull = mData->mConfigFileFull;
    6067             Bstr oldConfigFile = mData->mConfigFile;
    6068             mData->mConfigFileFull = newConfigFile;
     5439            Utf8Str oldConfigFileFull = mData->m_strConfigFileFull;
     5440            Utf8Str oldConfigFile = mData->m_strConfigFile;
     5441            mData->m_strConfigFileFull = newConfigFile;
    60695442            /* try to get the relative path for mConfigFile */
    60705443            Utf8Str path = newConfigFile;
    60715444            mParent->calculateRelativePath (path, path);
    6072             mData->mConfigFile = path;
     5445            mData->m_strConfigFile = path;
    60735446
    60745447            /* last, try to update the global settings with the new path */
    60755448            if (mData->mRegistered)
    60765449            {
    6077                 rc = mParent->updateSettings (configDir, newConfigDir);
    6078                 if (FAILED (rc))
     5450                rc = mParent->updateSettings(configDir.c_str(), newConfigDir.c_str());
     5451                if (FAILED(rc))
    60795452                {
    60805453                    /* revert to old values */
    6081                     mData->mConfigFileFull = oldConfigFileFull;
    6082                     mData->mConfigFile = oldConfigFile;
     5454                    mData->m_strConfigFileFull = oldConfigFileFull;
     5455                    mData->m_strConfigFile = oldConfigFile;
    60835456                    break;
    60845457                }
     
    60875460            /* update the snapshot folder */
    60885461            path = mUserData->mSnapshotFolderFull;
    6089             if (RTPathStartsWith (path, configDir))
     5462            if (RTPathStartsWith(path.c_str(), configDir.c_str()))
    60905463            {
    6091                 path = Utf8StrFmt ("%s%s", newConfigDir.raw(),
    6092                                    path.raw() + configDir.length());
     5464                path = Utf8StrFmt("%s%s", newConfigDir.raw(),
     5465                                  path.raw() + configDir.length());
    60935466                mUserData->mSnapshotFolderFull = path;
    60945467                calculateRelativePath (path, path);
     
    60985471            /* update the saved state file path */
    60995472            path = mSSData->mStateFilePath;
    6100             if (RTPathStartsWith (path, configDir))
     5473            if (RTPathStartsWith(path.c_str(), configDir.c_str()))
    61015474            {
    6102                 path = Utf8StrFmt ("%s%s", newConfigDir.raw(),
    6103                                    path.raw() + configDir.length());
     5475                path = Utf8StrFmt("%s%s", newConfigDir.raw(),
     5476                                  path.raw() + configDir.length());
    61045477                mSSData->mStateFilePath = path;
    61055478            }
     
    61095482             * and will save all snapshots in this case. */
    61105483            if (mData->mFirstSnapshot)
    6111                 mData->mFirstSnapshot->updateSavedStatePaths (configDir,
    6112                                                               newConfigDir);
     5484                mData->mFirstSnapshot->updateSavedStatePaths(configDir.c_str(),
     5485                                                             newConfigDir.c_str());
    61135486        }
    61145487        while (0);
    61155488
    6116         if (FAILED (rc))
     5489        if (FAILED(rc))
    61175490        {
    61185491            /* silently try to rename everything back */
    61195492            if (fileRenamed)
    6120                 RTFileRename (newConfigFile.raw(), configFile.raw(), 0);
     5493                RTFileRename(newConfigFile.raw(), configFile.raw(), 0);
    61215494            if (dirRenamed)
    6122                 RTPathRename (newConfigDir.raw(), configDir.raw(), 0);
    6123         }
    6124 
    6125         if (!aNew)
    6126         {
    6127             /* lock the config again */
    6128             HRESULT rc2 = lockConfig();
    6129             if (SUCCEEDED(rc))
    6130                 rc = rc2;
     5495                RTPathRename(newConfigDir.raw(), configDir.raw(), 0);
    61315496        }
    61325497
     
    61405505
    61415506        /* ensure the settings directory exists */
    6142         Utf8Str path(mData->mConfigFileFull);
     5507        Utf8Str path(mData->m_strConfigFileFull);
    61435508        path.stripFilename();
    6144         if (!RTDirExists(path))
    6145         {
    6146             vrc = RTDirCreateFullPath(path, 0777);
     5509        if (!RTDirExists(path.c_str()))
     5510        {
     5511            vrc = RTDirCreateFullPath(path.c_str(), 0777);
    61475512            if (RT_FAILURE(vrc))
    61485513            {
    6149                 return setError (E_FAIL,
    6150                     tr ("Could not create a directory '%s' "
    6151                         "to save the settings file (%Rrc)"),
    6152                     path.raw(), vrc);
     5514                return setError(E_FAIL,
     5515                                tr("Could not create a directory '%s' to save the settings file (%Rrc)"),
     5516                                path.raw(),
     5517                                vrc);
    61535518            }
    61545519        }
    61555520
    61565521        /* Note: open flags must correlate with RTFileOpen() in lockConfig() */
    6157         path = Utf8Str (mData->mConfigFileFull);
    6158         vrc = RTFileOpen (&mData->mHandleCfgFile, path,
    6159                           RTFILE_O_READWRITE | RTFILE_O_CREATE |
    6160                           RTFILE_O_DENY_WRITE);
    6161         if (RT_SUCCESS(vrc))
    6162         {
    6163             vrc = RTFileWrite (mData->mHandleCfgFile,
    6164                                (void *) gDefaultMachineConfig,
    6165                                strlen (gDefaultMachineConfig), NULL);
    6166         }
     5522        path = Utf8Str(mData->m_strConfigFileFull);
     5523        vrc = RTFileOpen(&mData->mHandleCfgFile, path.c_str(),
     5524                         RTFILE_O_READWRITE | RTFILE_O_CREATE |
     5525                         RTFILE_O_DENY_WRITE);
    61675526        if (RT_FAILURE(vrc))
    61685527        {
    61695528            mData->mHandleCfgFile = NIL_RTFILE;
    6170             return setError (E_FAIL,
    6171                 tr ("Could not create the settings file '%s' (%Rrc)"),
    6172                 path.raw(), vrc);
    6173         }
    6174         /* we do not close the file to simulate lockConfig() */
     5529            return setError(E_FAIL,
     5530                            tr("Could not create the settings file '%s' (%Rrc)"),
     5531                            path.raw(),
     5532                            vrc);
     5533        }
     5534        RTFileClose(mData->mHandleCfgFile);
    61755535    }
    61765536
     
    61975557 * left unlocked: if this machine is an unregistered one.
    61985558 */
    6199 HRESULT Machine::saveSettings (int aFlags /*= 0*/)
     5559HRESULT Machine::saveSettings(int aFlags /*= 0*/)
    62005560{
    62015561    LogFlowThisFuncEnter();
     
    62405600    bool isRenamed = false;
    62415601    bool isNew = false;
    6242     rc = prepareSaveSettings (isRenamed, isNew);
     5602    rc = prepareSaveSettings(isRenamed, isNew);
    62435603    CheckComRCReturnRC(rc);
    62445604
    62455605    try
    62465606    {
    6247         using namespace settings;
    6248         using namespace xml;
    6249 
    6250         /* this object is locked for writing to prevent concurrent reads and writes */
    6251         File file (mData->mHandleCfgFile, Utf8Str (mData->mConfigFileFull));
    6252         XmlTreeBackend tree;
    6253 
    6254         /* The newly created settings file is incomplete therefore we turn off
    6255          * validation. The rest is like in loadSettingsTree_ForUpdate().*/
    6256         rc = VirtualBox::loadSettingsTree (tree, file,
    6257                                            !isNew /* aValidate */,
    6258                                            false /* aCatchLoadErrors */,
    6259                                            false /* aAddDefaults */);
    6260         CheckComRCThrowRC (rc);
    6261 
    6262         Key machineNode = tree.rootKey().createKey ("Machine");
    6263 
    6264         /* uuid (required) */
    6265         Assert (!mData->mUuid.isEmpty());
    6266         machineNode.setValue <Guid> ("uuid", mData->mUuid);
    6267 
    6268         /* name (required) */
    6269         Assert (!mUserData->mName.isEmpty());
    6270         machineNode.setValue <Bstr> ("name", mUserData->mName);
    6271 
    6272         /* nameSync (optional, default is true) */
    6273         machineNode.setValueOr <bool> ("nameSync", !!mUserData->mNameSync, true);
    6274 
    6275         /* Description node (optional) */
    6276         if (!mUserData->mDescription.isNull())
    6277         {
    6278             Key descNode = machineNode.createKey ("Description");
    6279             descNode.setKeyValue <Bstr> (mUserData->mDescription);
    6280         }
    6281         else
    6282         {
    6283             Key descNode = machineNode.findKey ("Description");
    6284             if (!descNode.isNull())
    6285                 descNode.zap();
    6286         }
    6287 
    6288         /* OSType (required) */
    6289         machineNode.setValue <Bstr> ("OSType", mUserData->mOSTypeId);
    6290 
    6291         /* stateFile (optional) */
    6292         /// @todo The reason for MachineState_Restoring below:
    6293         /// PushGuestProperties() is always called from Console::powerDown()
    6294         /// (including the case when restoring from the saved state fails) and
    6295         /// calls SaveSettings() to save guest properties. Since the saved state
    6296         /// file is still present there (and should be kept), we must save it
    6297         /// while in Restoring state too. However, calling SaveSettings() from
    6298         /// PushGuestProperties() is wrong in the first place. A proper way is
    6299         /// to only save guest properties node and not involve the whole save
    6300         /// process.
    6301         if (mData->mMachineState == MachineState_Saved ||
    6302             mData->mMachineState == MachineState_Restoring)
    6303         {
    6304             Assert (!mSSData->mStateFilePath.isEmpty());
     5607        mData->m_pMachineConfigFile->uuid = mData->mUuid;
     5608        mData->m_pMachineConfigFile->strName = mUserData->mName;
     5609        mData->m_pMachineConfigFile->fNameSync = !!mUserData->mNameSync;
     5610        mData->m_pMachineConfigFile->strDescription = mUserData->mDescription;
     5611        mData->m_pMachineConfigFile->strOsType = mUserData->mOSTypeId;
     5612
     5613        if (    mData->mMachineState == MachineState_Saved
     5614             || mData->mMachineState == MachineState_Restoring
     5615           )
     5616        {
     5617            Assert(!mSSData->mStateFilePath.isEmpty());
    63055618            /* try to make the file name relative to the settings file dir */
    63065619            Utf8Str stateFilePath = mSSData->mStateFilePath;
    6307             calculateRelativePath (stateFilePath, stateFilePath);
    6308             machineNode.setStringValue ("stateFile", stateFilePath);
     5620            calculateRelativePath(stateFilePath, stateFilePath);
     5621
     5622            mData->m_pMachineConfigFile->strStateFile = stateFilePath;
    63095623        }
    63105624        else
    63115625        {
    6312             Assert (mSSData->mStateFilePath.isNull());
    6313             machineNode.zapValue ("stateFile");
    6314         }
    6315 
    6316         /* currentSnapshot ID (optional) */
    6317         if (!mData->mCurrentSnapshot.isNull())
    6318         {
    6319             Assert (!mData->mFirstSnapshot.isNull());
    6320             machineNode.setValue<Guid>("currentSnapshot",
    6321                                        mData->mCurrentSnapshot->getId());
    6322         }
     5626            Assert(mSSData->mStateFilePath.isNull());
     5627            mData->m_pMachineConfigFile->strStateFile.setNull();
     5628        }
     5629
     5630        if (mData->mCurrentSnapshot)
     5631            mData->m_pMachineConfigFile->uuidCurrentSnapshot = mData->mCurrentSnapshot->getId();
    63235632        else
    6324         {
    6325             Assert (mData->mFirstSnapshot.isNull());
    6326             machineNode.zapValue ("currentSnapshot");
    6327         }
    6328 
    6329         /* snapshotFolder (optional) */
    6330         /// @todo use the Bstr::NullOrEmpty constant and setValueOr
    6331         if (!mUserData->mSnapshotFolder.isEmpty())
    6332             machineNode.setValue <Bstr> ("snapshotFolder", mUserData->mSnapshotFolder);
    6333         else
    6334             machineNode.zapValue ("snapshotFolder");
    6335 
    6336         /* currentStateModified (optional, default is true) */
    6337         machineNode.setValueOr <bool> ("currentStateModified",
    6338                                        !!currentStateModified, true);
    6339 
    6340         /* lastStateChange */
    6341         machineNode.setValue <RTTIMESPEC> ("lastStateChange",
    6342                                            mData->mLastStateChange);
    6343 
    6344         /* set the aborted attribute when appropriate, defaults to false */
    6345         machineNode.setValueOr <bool> ("aborted",
    6346                                        mData->mMachineState == MachineState_Aborted,
    6347                                        false);
    6348 
    6349         /* Hardware node (required) */
    6350         {
    6351             /* first, delete the entire node if exists */
    6352             Key hwNode = machineNode.findKey ("Hardware");
    6353             if (!hwNode.isNull())
    6354                 hwNode.zap();
    6355             /* then recreate it */
    6356             hwNode = machineNode.createKey ("Hardware");
    6357 
    6358             rc = saveHardware (hwNode);
    6359             CheckComRCThrowRC (rc);
    6360         }
    6361 
    6362         /* StorageControllers node (required) */
    6363         {
    6364             /* first, delete the entire node if exists */
    6365             Key storageNode = machineNode.findKey ("StorageControllers");
    6366             if (!storageNode.isNull())
    6367                 storageNode.zap();
    6368             /* then recreate it */
    6369             storageNode = machineNode.createKey ("StorageControllers");
    6370 
    6371             rc = saveStorageControllers (storageNode);
    6372             CheckComRCThrowRC (rc);
    6373         }
    6374 
    6375         /* ask to save all snapshots when the machine name was changed since
    6376          * it may affect saved state file paths for online snapshots (see
    6377          * #openConfigLoader() for details) */
    6378         if (isRenamed)
    6379         {
    6380             rc = saveSnapshotSettingsWorker (machineNode, NULL,
    6381                                              SaveSS_UpdateAllOp);
    6382             CheckComRCThrowRC (rc);
    6383         }
    6384 
    6385         /* save the settings on success */
    6386         rc = VirtualBox::saveSettingsTree (tree, file,
    6387                                            mData->mSettingsFileVersion);
    6388         CheckComRCThrowRC (rc);
     5633            mData->m_pMachineConfigFile->uuidCurrentSnapshot.clear();
     5634
     5635        mData->m_pMachineConfigFile->strSnapshotFolder = mUserData->mSnapshotFolder;
     5636        mData->m_pMachineConfigFile->fCurrentStateModified = !!currentStateModified;
     5637        mData->m_pMachineConfigFile->timeLastStateChange = mData->mLastStateChange;
     5638        mData->m_pMachineConfigFile->fAborted = (mData->mMachineState == MachineState_Aborted);
     5639
     5640        rc = saveHardware(mData->m_pMachineConfigFile->hardwareMachine);
     5641        CheckComRCThrowRC(rc);
     5642
     5643        rc = saveStorageControllers(mData->m_pMachineConfigFile->storageMachine);
     5644        CheckComRCThrowRC(rc);
     5645
     5646        // save snapshots
     5647        rc = saveAllSnapshots();
     5648        CheckComRCThrowRC(rc);
     5649
     5650        // now spit it all out
     5651        mData->m_pMachineConfigFile->write(mData->m_strConfigFileFull);
    63895652    }
    63905653    catch (HRESULT err)
     
    64225685}
    64235686
     5687HRESULT Machine::saveAllSnapshots()
     5688{
     5689    AssertReturn (isWriteLockOnCurrentThread(), E_FAIL);
     5690
     5691    HRESULT rc = S_OK;
     5692
     5693    try
     5694    {
     5695        mData->m_pMachineConfigFile->llFirstSnapshot.clear();
     5696
     5697        if (mData->mFirstSnapshot)
     5698        {
     5699            settings::Snapshot snapNew;
     5700            mData->m_pMachineConfigFile->llFirstSnapshot.push_back(snapNew);
     5701
     5702            // get reference to the fresh copy of the snapshot on the list and
     5703            // work on that copy directly to avoid excessive copying later
     5704            settings::Snapshot &snap = mData->m_pMachineConfigFile->llFirstSnapshot.front();
     5705
     5706            rc = mData->mFirstSnapshot->saveSnapshot(snap, false /*aAttrsOnly*/);
     5707            CheckComRCThrowRC(rc);
     5708        }
     5709
     5710//         if (mType == IsSessionMachine)
     5711//             mParent->onMachineDataChange(mData->mUuid);          @todo is this necessary?
     5712
     5713    }
     5714    catch (HRESULT err)
     5715    {
     5716        /* we assume that error info is set by the thrower */
     5717        rc = err;
     5718    }
     5719    catch (...)
     5720    {
     5721        rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     5722    }
     5723
     5724    return rc;
     5725}
     5726
    64245727/**
    6425  *  Wrapper for #saveSnapshotSettingsWorker() that opens the settings file
    6426  *  and locates the <Machine> node in there. See #saveSnapshotSettingsWorker()
    6427  *  for more details.
    6428  *
    6429  *  @param aSnapshot    Snapshot to operate on
    6430  *  @param aOpFlags     Operation to perform, one of SaveSS_NoOp, SaveSS_AddOp
    6431  *                      or SaveSS_UpdateAttrsOp possibly combined with
    6432  *                      SaveSS_UpdateCurrentId.
    6433  *
    6434  *  @note Locks this object for writing + other child objects.
     5728 *  Saves the VM hardware configuration. It is assumed that the
     5729 *  given node is empty.
     5730 *
     5731 *  @param aNode    <Hardware> node to save the VM hardware confguration to.
    64355732 */
    6436 HRESULT Machine::saveSnapshotSettings (Snapshot *aSnapshot, int aOpFlags)
    6437 {
    6438     AutoCaller autoCaller(this);
    6439     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    6440 
    6441     AssertReturn(mType == IsMachine || mType == IsSessionMachine, E_FAIL);
     5733HRESULT Machine::saveHardware(settings::Hardware &data)
     5734{
     5735    HRESULT rc = S_OK;
     5736
     5737    try
     5738    {
     5739        /* The hardware version attribute (optional).
     5740            Automatically upgrade from 1 to 2 when there is no saved state. (ugly!) */
     5741        if (    mHWData->mHWVersion == "1"
     5742             && mSSData->mStateFilePath.isEmpty()
     5743           )
     5744            mHWData->mHWVersion = "2";  /** @todo Is this safe, to update mHWVersion here? If not some other point needs to be found where this can be done. */
     5745
     5746        data.strVersion = mHWData->mHWVersion;
     5747
     5748        // CPU
     5749        data.fHardwareVirt = mHWData->mHWVirtExEnabled;
     5750        data.fNestedPaging = mHWData->mHWVirtExNestedPagingEnabled;
     5751        data.fVPID = mHWData->mHWVirtExVPIDEnabled;
     5752        data.fPAE = mHWData->mPAEEnabled;
     5753
     5754        data.cCPUs = mHWData->mCPUCount;
     5755
     5756        // memory
     5757        data.ulMemorySizeMB = mHWData->mMemorySize;
     5758
     5759        // boot order
     5760        data.mapBootOrder.clear();
     5761        for (size_t i = 0;
     5762             i < RT_ELEMENTS(mHWData->mBootOrder);
     5763             ++i)
     5764            data.mapBootOrder[i] = mHWData->mBootOrder[i];
     5765
     5766        // display
     5767        data.ulVRAMSizeMB = mHWData->mVRAMSize;
     5768        data.cMonitors = mHWData->mMonitorCount;
     5769        data.fAccelerate3D = !!mHWData->mAccelerate3DEnabled;
     5770        data.fAccelerate2DVideo = !!mHWData->mAccelerate2DVideoEnabled;
     5771
     5772#ifdef VBOX_WITH_VRDP
     5773        /* VRDP settings (optional) */
     5774        rc = mVRDPServer->saveSettings(data.vrdpSettings);
     5775        CheckComRCThrowRC(rc);
     5776#endif
     5777
     5778        /* BIOS (required) */
     5779        rc = mBIOSSettings->saveSettings(data.biosSettings);
     5780        CheckComRCThrowRC(rc);
     5781
     5782        /* DVD drive (required) */
     5783        rc = mDVDDrive->saveSettings(data.dvdDrive);
     5784        CheckComRCThrowRC(rc);
     5785
     5786        /* Flooppy drive (required) */
     5787        rc = mFloppyDrive->saveSettings(data.floppyDrive);
     5788        CheckComRCThrowRC(rc);
     5789
     5790        /* USB Controller (required) */
     5791        rc = mUSBController->saveSettings(data.usbController);
     5792        CheckComRCThrowRC(rc);
     5793
     5794        /* Network adapters (required) */
     5795        data.llNetworkAdapters.clear();
     5796        for (ULONG slot = 0;
     5797             slot < RT_ELEMENTS(mNetworkAdapters);
     5798             ++slot)
     5799        {
     5800            settings::NetworkAdapter nic;
     5801            nic.ulSlot = slot;
     5802            rc = mNetworkAdapters[slot]->saveSettings(nic);
     5803            CheckComRCThrowRC(rc);
     5804
     5805            data.llNetworkAdapters.push_back(nic);
     5806        }
     5807
     5808        /* Serial ports */
     5809        data.llSerialPorts.clear();
     5810        for (ULONG slot = 0;
     5811             slot < RT_ELEMENTS(mSerialPorts);
     5812             ++slot)
     5813        {
     5814            settings::SerialPort s;
     5815            s.ulSlot = slot;
     5816            rc = mSerialPorts[slot]->saveSettings(s);
     5817            CheckComRCReturnRC (rc);
     5818        }
     5819
     5820        /* Parallel ports */
     5821        data.llParallelPorts.clear();
     5822        for (ULONG slot = 0;
     5823             slot < RT_ELEMENTS(mParallelPorts);
     5824             ++slot)
     5825        {
     5826            settings::ParallelPort p;
     5827            p.ulSlot = slot;
     5828            rc = mParallelPorts[slot]->saveSettings(p);
     5829            CheckComRCReturnRC (rc);
     5830        }
     5831
     5832        /* Audio adapter */
     5833        rc = mAudioAdapter->saveSettings(data.audioAdapter);
     5834        CheckComRCReturnRC (rc);
     5835
     5836        /* Shared folders */
     5837        data.llSharedFolders.clear();
     5838        for (HWData::SharedFolderList::const_iterator it = mHWData->mSharedFolders.begin();
     5839            it != mHWData->mSharedFolders.end();
     5840            ++it)
     5841        {
     5842            ComObjPtr<SharedFolder> pFolder = *it;
     5843            settings::SharedFolder sf;
     5844            sf.strName = pFolder->name();
     5845            sf.strHostPath = pFolder->hostPath();
     5846            sf.fWritable = !!pFolder->writable();
     5847        }
     5848
     5849        // clipboard
     5850        data.clipboardMode = mHWData->mClipboardMode;
     5851
     5852        /* Guest */
     5853        data.ulMemoryBalloonSize = mHWData->mMemoryBalloonSize;
     5854        data.ulStatisticsUpdateInterval = mHWData->mStatisticsUpdateInterval;
     5855
     5856        // guest properties
     5857        data.llGuestProperties.clear();
     5858#ifdef VBOX_WITH_GUEST_PROPS
     5859        for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
     5860             it != mHWData->mGuestProperties.end();
     5861             ++it)
     5862        {
     5863            HWData::GuestProperty property = *it;
     5864
     5865            settings::GuestProperty prop;
     5866            prop.strName = property.strName;
     5867            prop.strValue = property.strValue;
     5868            prop.timestamp = property.mTimestamp;
     5869            char szFlags[guestProp::MAX_FLAGS_LEN + 1];
     5870            guestProp::writeFlags(property.mFlags, szFlags);
     5871            prop.strFlags = szFlags;
     5872
     5873            data.llGuestProperties.push_back(prop);
     5874        }
     5875
     5876        data.strNotificationPatterns = mHWData->mGuestPropertyNotificationPatterns;
     5877    }
     5878    catch(std::bad_alloc &e)
     5879    {
     5880        return E_OUTOFMEMORY;
     5881    }
     5882#endif /* VBOX_WITH_GUEST_PROPS defined */
     5883
     5884    AssertComRC(rc);
     5885    return rc;
     5886}
     5887
     5888/**
     5889 *  Saves the storage controller configuration.
     5890 *
     5891 *  @param aNode    <StorageControllers> node to save the VM hardware confguration to.
     5892 */
     5893HRESULT Machine::saveStorageControllers(settings::Storage &data)
     5894{
     5895    data.llStorageControllers.clear();
     5896
     5897    for (StorageControllerList::const_iterator it = mStorageControllers->begin();
     5898         it != mStorageControllers->end();
     5899         ++it)
     5900    {
     5901        HRESULT rc;
     5902        ComObjPtr<StorageController> pCtl = *it;
     5903
     5904        settings::StorageController ctl;
     5905        ctl.strName = pCtl->name();
     5906        ctl.controllerType = pCtl->controllerType();
     5907        ctl.storageBus = pCtl->storageBus();
     5908
     5909        /* Save the port count. */
     5910        ULONG portCount;
     5911        rc = pCtl->COMGETTER(PortCount)(&portCount);
     5912        ComAssertRCRet(rc, rc);
     5913        ctl.ulPortCount = portCount;
     5914
     5915        /* Save IDE emulation settings. */
     5916        if (ctl.controllerType == StorageControllerType_IntelAhci)
     5917        {
     5918            if (    (FAILED(rc = pCtl->GetIDEEmulationPort(0, &ctl.lIDE0MasterEmulationPort)))
     5919                 || (FAILED(rc = pCtl->GetIDEEmulationPort(1, &ctl.lIDE0SlaveEmulationPort)))
     5920                 || (FAILED(rc = pCtl->GetIDEEmulationPort(2, &ctl.lIDE1MasterEmulationPort)))
     5921                 || (FAILED(rc = pCtl->GetIDEEmulationPort(3, &ctl.lIDE1SlaveEmulationPort)))
     5922               )
     5923                ComAssertRCRet(rc, rc);
     5924        }
     5925
     5926        /* save the devices now. */
     5927        rc = saveStorageDevices(pCtl, ctl);
     5928        ComAssertRCRet(rc, rc);
     5929
     5930        data.llStorageControllers.push_back(ctl);
     5931    }
     5932
     5933    return S_OK;
     5934}
     5935
     5936/**
     5937 *  Saves the hard disk confguration.
     5938 *  It is assumed that the given node is empty.
     5939 *
     5940 *  @param aNode    <HardDiskAttachments> node to save the hard disk confguration to.
     5941 */
     5942HRESULT Machine::saveStorageDevices(ComObjPtr<StorageController> aStorageController,
     5943                                    settings::StorageController &data)
     5944{
     5945    using namespace settings;
     5946
     5947    HDData::AttachmentList atts;
     5948
     5949    HRESULT rc = getHardDiskAttachmentsOfController(Bstr(aStorageController->name()), atts);
     5950    CheckComRCReturnRC (rc);
     5951
     5952    data.llAttachedDevices.clear();
     5953    for (HDData::AttachmentList::const_iterator it = atts.begin();
     5954         it != atts.end();
     5955         ++it)
     5956    {
     5957        settings::AttachedDevice dev;
     5958
     5959        dev.type = settings::AttachedDevice::HardDisk;
     5960        dev.lPort = (*it)->port();
     5961        dev.lDevice = (*it)->device();
     5962        dev.uuid = (*it)->hardDisk()->id();
     5963
     5964        data.llAttachedDevices.push_back(dev);
     5965    }
     5966
     5967    return S_OK;
     5968}
     5969
     5970/**
     5971 *  Saves machine state settings as defined by aFlags
     5972 *  (SaveSTS_* values).
     5973 *
     5974 *  @param aFlags   Combination of SaveSTS_* flags.
     5975 *
     5976 *  @note Locks objects for writing.
     5977 */
     5978HRESULT Machine::saveStateSettings(int aFlags)
     5979{
     5980    if (aFlags == 0)
     5981        return S_OK;
     5982
     5983    AutoCaller autoCaller (this);
     5984    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    64425985
    64435986    /* This object's write lock is also necessary to serialize file access
     
    64455988    AutoWriteLock alock(this);
    64465989
    6447     AssertReturn(isConfigLocked(), E_FAIL);
    6448 
    64495990    HRESULT rc = S_OK;
    64505991
     5992    Assert(mData->m_pMachineConfigFile);
     5993
    64515994    try
    64525995    {
    6453         using namespace settings;
    6454         using namespace xml;
    6455 
    6456         /* load the settings file */
    6457         File file (mData->mHandleCfgFile, Utf8Str (mData->mConfigFileFull));
    6458         XmlTreeBackend tree;
    6459 
    6460         rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
    6461         CheckComRCReturnRC(rc);
    6462 
    6463         Key machineNode = tree.rootKey().key ("Machine");
    6464 
    6465         rc = saveSnapshotSettingsWorker (machineNode, aSnapshot, aOpFlags);
    6466         CheckComRCReturnRC(rc);
    6467 
    6468         /* save settings on success */
    6469         rc = VirtualBox::saveSettingsTree (tree, file,
    6470                                            mData->mSettingsFileVersion);
    6471         CheckComRCReturnRC(rc);
    6472     }
    6473     catch (...)
    6474     {
    6475         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    6476     }
    6477 
    6478     return rc;
    6479 }
    6480 
    6481 /**
    6482  *  Performs the specified operation on the given snapshot
    6483  *  in the settings file represented by \a aMachineNode.
    6484  *
    6485  *  If \a aOpFlags = SaveSS_UpdateAllOp, \a aSnapshot can be NULL to indicate
    6486  *  that the whole tree of the snapshots should be updated in <Machine>.
    6487  *  One particular case is when the last (and the only) snapshot should be
    6488  *  removed (it is so when both mCurrentSnapshot and mFirstSnapshot are NULL).
    6489  *
    6490  *  \a aOp may be just SaveSS_UpdateCurrentId if only the currentSnapshot
    6491  *  attribute of <Machine> needs to be updated.
    6492  *
    6493  *  @param aMachineNode <Machine> node in the opened settings file.
    6494  *  @param aSnapshot    Snapshot to operate on.
    6495  *  @param aOpFlags     Operation to perform, one of SaveSS_NoOp, SaveSS_AddOp
    6496  *                      or SaveSS_UpdateAttrsOp possibly combined with
    6497  *                      SaveSS_UpdateCurrentId.
    6498  *
    6499  *  @note Must be called with this object locked for writing.
    6500  *        Locks child objects.
    6501  */
    6502 HRESULT Machine::saveSnapshotSettingsWorker (settings::Key &aMachineNode,
    6503                                              Snapshot *aSnapshot, int aOpFlags)
    6504 {
    6505     using namespace settings;
    6506 
    6507     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    6508 
    6509     AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
    6510 
    6511     int op = aOpFlags & SaveSS_OpMask;
    6512     AssertReturn(
    6513         (aSnapshot && (op == SaveSS_AddOp || op == SaveSS_UpdateAttrsOp ||
    6514                        op == SaveSS_UpdateAllOp)) ||
    6515         (!aSnapshot && ((op == SaveSS_NoOp && (aOpFlags & SaveSS_CurrentId)) ||
    6516                         op == SaveSS_UpdateAllOp)),
    6517         E_FAIL);
    6518 
    6519     HRESULT rc = S_OK;
    6520 
    6521     bool recreateWholeTree = false;
    6522 
    6523     do
    6524     {
    6525         if (op == SaveSS_NoOp)
    6526             break;
    6527 
    6528         /* quick path: recreate the whole tree of the snapshots */
    6529         if (op == SaveSS_UpdateAllOp && aSnapshot == NULL)
    6530         {
    6531             /* first, delete the entire root snapshot node if it exists */
    6532             Key snapshotNode = aMachineNode.findKey ("Snapshot");
    6533             if (!snapshotNode.isNull())
    6534                 snapshotNode.zap();
    6535 
    6536             /* second, if we have any snapshots left, substitute aSnapshot
    6537              * with the first snapshot to recreate the whole tree, otherwise
    6538              * break */
    6539             if (mData->mFirstSnapshot)
    6540             {
    6541                 aSnapshot = mData->mFirstSnapshot;
    6542                 recreateWholeTree = true;
    6543             }
    6544             else
    6545                 break;
    6546         }
    6547 
    6548         Assert (!!aSnapshot);
    6549         ComObjPtr<Snapshot> parent = aSnapshot->parent();
    6550 
    6551         if (op == SaveSS_AddOp)
    6552         {
    6553             Key parentNode;
    6554 
    6555             if (parent)
    6556             {
    6557                 rc = findSnapshotNode (parent, aMachineNode, NULL, &parentNode);
    6558                 CheckComRCBreakRC (rc);
    6559 
    6560                 ComAssertBreak (!parentNode.isNull(), rc = E_FAIL);
    6561             }
    6562 
    6563             do
    6564             {
    6565                 Key snapshotsNode;
    6566 
    6567                 if (!parentNode.isNull())
    6568                     snapshotsNode = parentNode.createKey ("Snapshots");
    6569                 else
    6570                     snapshotsNode = aMachineNode;
    6571                 do
    6572                 {
    6573                     Key snapshotNode = snapshotsNode.appendKey ("Snapshot");
    6574                     rc = aSnapshot->saveSnapshot(snapshotNode, false /* aAttrsOnly */);
    6575                     CheckComRCBreakRC (rc);
    6576 
    6577                     /* when a new snapshot is added, this means diffs were created
    6578                      * for every normal/immutable hard disk of the VM, so we need to
    6579                      * save the current hard disk attachments */
    6580 
    6581                     Key storageNode = aMachineNode.findKey ("StorageControllers");
    6582                     if (!storageNode.isNull())
    6583                         storageNode.zap();
    6584                     storageNode = aMachineNode.createKey ("StorageControllers");
    6585 
    6586                     rc = saveStorageControllers (storageNode);
    6587                     CheckComRCBreakRC (rc);
    6588 
    6589                     if (mHDData->mAttachments.size() != 0)
    6590                     {
    6591                         /* If we have one or more attachments then we definitely
    6592                          * created diffs for them and associated new diffs with
    6593                          * current settngs. So, since we don't use saveSettings(),
    6594                          * we need to inform callbacks manually. */
    6595                         if (mType == IsSessionMachine)
    6596                             mParent->onMachineDataChange(mData->mUuid);
    6597                     }
    6598                 }
    6599                 while (0);
    6600             }
    6601             while (0);
    6602 
    6603             break;
    6604         }
    6605 
    6606         Assert ((op == SaveSS_UpdateAttrsOp && !recreateWholeTree) ||
    6607                 op == SaveSS_UpdateAllOp);
    6608 
    6609         Key snapshotsNode;
    6610         Key snapshotNode;
    6611 
    6612         if (!recreateWholeTree)
    6613         {
    6614             rc = findSnapshotNode (aSnapshot, aMachineNode,
    6615                                    &snapshotsNode, &snapshotNode);
    6616             CheckComRCBreakRC (rc);
    6617         }
    6618 
    6619         if (snapshotsNode.isNull())
    6620             snapshotsNode = aMachineNode;
    6621 
    6622         if (op == SaveSS_UpdateAttrsOp)
    6623             rc = aSnapshot->saveSnapshot(snapshotNode, true /* aAttrsOnly */);
    6624         else
    6625         {
    6626             if (!snapshotNode.isNull())
    6627                 snapshotNode.zap();
    6628 
    6629             snapshotNode = snapshotsNode.appendKey ("Snapshot");
    6630             rc = aSnapshot->saveSnapshot(snapshotNode, false /* aAttrsOnly */);
    6631             CheckComRCBreakRC (rc);
    6632         }
    6633     }
    6634     while (0);
    6635 
    6636     if (SUCCEEDED(rc))
    6637     {
    6638         /* update currentSnapshot when appropriate */
    6639         if (aOpFlags & SaveSS_CurrentId)
    6640         {
    6641             if (!mData->mCurrentSnapshot.isNull())
    6642                 aMachineNode.setValue<Guid>("currentSnapshot",
    6643                                             mData->mCurrentSnapshot->getId());
    6644             else
    6645                 aMachineNode.zapValue ("currentSnapshot");
    6646         }
    6647         if (aOpFlags & SaveSS_CurStateModified)
    6648         {
    6649             /* defaults to true */
    6650             aMachineNode.setValueOr <bool> ("currentStateModified",
    6651                                             !!mData->mCurrentStateModified, true);
    6652         }
    6653     }
    6654 
    6655     return rc;
    6656 }
    6657 
    6658 /**
    6659  *  Saves the VM hardware configuration. It is assumed that the
    6660  *  given node is empty.
    6661  *
    6662  *  @param aNode    <Hardware> node to save the VM hardware confguration to.
    6663  */
    6664 HRESULT Machine::saveHardware (settings::Key &aNode)
    6665 {
    6666     using namespace settings;
    6667 
    6668     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    6669 
    6670     HRESULT rc = S_OK;
    6671 
    6672     /* The hardware version attribute (optional).
    6673        Automatically upgrade from 1 to 2 when there is no saved state. (ugly!) */
    6674     {
    6675         Utf8Str hwVersion = mHWData->mHWVersion;
    6676         if (   hwVersion.compare ("1") == 0
    6677             && mSSData->mStateFilePath.isEmpty())
    6678             mHWData->mHWVersion = hwVersion = "2";  /** @todo Is this safe, to update mHWVersion here? If not some other point needs to be found where this can be done. */
    6679         if (hwVersion.compare ("2") == 0)           /** @todo get the default from the schema if possible. */
    6680             aNode.zapValue ("version");
    6681         else
    6682             aNode.setStringValue ("version", hwVersion.raw());
    6683     }
    6684 
    6685     /* CPU (optional, but always created atm) */
    6686     {
    6687         Key cpuNode = aNode.createKey ("CPU");
    6688         Key hwVirtExNode = cpuNode.createKey ("HardwareVirtEx");
    6689         const char *value = NULL;
    6690         if (mHWData->mHWVirtExEnabled)
    6691             value = "true";
    6692         else
    6693             value = "false";
    6694         hwVirtExNode.setStringValue ("enabled", value);
    6695 
    6696         /* Nested paging (optional, default is false) */
    6697         if (mHWData->mHWVirtExNestedPagingEnabled)
    6698         {
    6699             Key HWVirtExNestedPagingNode = cpuNode.createKey ("HardwareVirtExNestedPaging");
    6700             HWVirtExNestedPagingNode.setValue <bool> ("enabled", true);
    6701         }
    6702 
    6703         /* VPID (optional, default is false) */
    6704         if (mHWData->mHWVirtExVPIDEnabled)
    6705         {
    6706             Key HWVirtExVPIDNode = cpuNode.createKey ("HardwareVirtExVPID");
    6707             HWVirtExVPIDNode.setValue <bool> ("enabled", true);
    6708         }
    6709 
    6710         /* PAE (optional, default is false) */
    6711         if (mHWData->mPAEEnabled)
    6712         {
    6713             Key PAENode = cpuNode.createKey ("PAE");
    6714             PAENode.setValue <bool> ("enabled", true);
    6715         }
    6716 
    6717         /* CPU count */
    6718         cpuNode.setValue <ULONG> ("count", mHWData->mCPUCount);
    6719     }
    6720 
    6721     /* memory (required) */
    6722     {
    6723         Key memoryNode = aNode.createKey ("Memory");
    6724         memoryNode.setValue <ULONG> ("RAMSize", mHWData->mMemorySize);
    6725     }
    6726 
    6727     /* boot (required) */
    6728     {
    6729         Key bootNode = aNode.createKey ("Boot");
    6730 
    6731         for (ULONG pos = 0; pos < RT_ELEMENTS (mHWData->mBootOrder); ++ pos)
    6732         {
    6733             const char *device = NULL;
    6734             switch (mHWData->mBootOrder [pos])
    6735             {
    6736                 case DeviceType_Null:
    6737                     /* skip, this is allowed for <Order> nodes
    6738                      * when loading, the default value NoDevice will remain */
    6739                     continue;
    6740                 case DeviceType_Floppy:         device = "Floppy"; break;
    6741                 case DeviceType_DVD:            device = "DVD"; break;
    6742                 case DeviceType_HardDisk:       device = "HardDisk"; break;
    6743                 case DeviceType_Network:        device = "Network"; break;
    6744                 default:
    6745                 {
    6746                     ComAssertMsgFailedRet (("Invalid boot device: %d",
    6747                                             mHWData->mBootOrder [pos]),
    6748                                             E_FAIL);
    6749                 }
    6750             }
    6751 
    6752             Key orderNode = bootNode.appendKey ("Order");
    6753             orderNode.setValue <ULONG> ("position", pos + 1);
    6754             orderNode.setStringValue ("device", device);
    6755         }
    6756     }
    6757 
    6758     /* display (required) */
    6759     {
    6760         Key displayNode = aNode.createKey ("Display");
    6761         displayNode.setValue <ULONG> ("VRAMSize", mHWData->mVRAMSize);
    6762         displayNode.setValue <ULONG> ("monitorCount", mHWData->mMonitorCount);
    6763         displayNode.setValue <bool> ("accelerate3D", !!mHWData->mAccelerate3DEnabled);
    6764         displayNode.setValue <bool> ("accelerate2DVideo", !!mHWData->mAccelerate2DVideoEnabled);
    6765     }
    6766 
    6767 #ifdef VBOX_WITH_VRDP
    6768     /* VRDP settings (optional) */
    6769     rc = mVRDPServer->saveSettings (aNode);
    6770     CheckComRCReturnRC(rc);
    6771 #endif
    6772 
    6773     /* BIOS (required) */
    6774     rc = mBIOSSettings->saveSettings (aNode);
    6775     CheckComRCReturnRC(rc);
    6776 
    6777     /* DVD drive (required) */
    6778     rc = mDVDDrive->saveSettings (aNode);
    6779     CheckComRCReturnRC(rc);
    6780 
    6781     /* Flooppy drive (required) */
    6782     rc = mFloppyDrive->saveSettings (aNode);
    6783     CheckComRCReturnRC(rc);
    6784 
    6785     /* USB Controller (required) */
    6786     rc = mUSBController->saveSettings (aNode);
    6787     CheckComRCReturnRC(rc);
    6788 
    6789     /* Network adapters (required) */
    6790     {
    6791         Key nwNode = aNode.createKey ("Network");
    6792 
    6793         for (ULONG slot = 0; slot < RT_ELEMENTS (mNetworkAdapters); ++ slot)
    6794         {
    6795             Key adapterNode = nwNode.appendKey ("Adapter");
    6796 
    6797             adapterNode.setValue <ULONG> ("slot", slot);
    6798 
    6799             rc = mNetworkAdapters [slot]->saveSettings (adapterNode);
    6800             CheckComRCReturnRC(rc);
    6801         }
    6802     }
    6803 
    6804     /* Serial ports */
    6805     {
    6806         Key serialNode = aNode.createKey ("UART");
    6807 
    6808         for (ULONG slot = 0; slot < RT_ELEMENTS (mSerialPorts); ++ slot)
    6809         {
    6810             Key portNode = serialNode.appendKey ("Port");
    6811 
    6812             portNode.setValue <ULONG> ("slot", slot);
    6813 
    6814             rc = mSerialPorts [slot]->saveSettings (portNode);
    6815             CheckComRCReturnRC(rc);
    6816         }
    6817     }
    6818 
    6819     /* Parallel ports */
    6820     {
    6821         Key parallelNode = aNode.createKey ("LPT");
    6822 
    6823         for (ULONG slot = 0; slot < RT_ELEMENTS (mParallelPorts); ++ slot)
    6824         {
    6825             Key portNode = parallelNode.appendKey ("Port");
    6826 
    6827             portNode.setValue <ULONG> ("slot", slot);
    6828 
    6829             rc = mParallelPorts [slot]->saveSettings (portNode);
    6830             CheckComRCReturnRC(rc);
    6831         }
    6832     }
    6833 
    6834     /* Audio adapter */
    6835     rc = mAudioAdapter->saveSettings (aNode);
    6836     CheckComRCReturnRC(rc);
    6837 
    6838     /* Shared folders */
    6839     {
    6840         Key sharedFoldersNode = aNode.createKey ("SharedFolders");
    6841 
    6842         for (HWData::SharedFolderList::const_iterator it = mHWData->mSharedFolders.begin();
    6843              it != mHWData->mSharedFolders.end();
    6844              ++ it)
    6845         {
    6846             ComObjPtr<SharedFolder> folder = *it;
    6847 
    6848             Key folderNode = sharedFoldersNode.appendKey ("SharedFolder");
    6849 
    6850             /* all are mandatory */
    6851             folderNode.setValue <Bstr> ("name", folder->name());
    6852             folderNode.setValue <Bstr> ("hostPath", folder->hostPath());
    6853             folderNode.setValue <bool> ("writable", !!folder->writable());
    6854         }
    6855     }
    6856 
    6857     /* Clipboard */
    6858     {
    6859         Key clipNode = aNode.createKey ("Clipboard");
    6860 
    6861         const char *modeStr = "Disabled";
    6862         switch (mHWData->mClipboardMode)
    6863         {
    6864             case ClipboardMode_Disabled:
    6865                 /* already assigned */
    6866                 break;
    6867             case ClipboardMode_HostToGuest:
    6868                 modeStr = "HostToGuest";
    6869                 break;
    6870             case ClipboardMode_GuestToHost:
    6871                 modeStr = "GuestToHost";
    6872                 break;
    6873             case ClipboardMode_Bidirectional:
    6874                 modeStr = "Bidirectional";
    6875                 break;
    6876             default:
    6877                 ComAssertMsgFailedRet (("Clipboard mode %d is invalid",
    6878                                         mHWData->mClipboardMode),
    6879                                        E_FAIL);
    6880         }
    6881         clipNode.setStringValue ("mode", modeStr);
    6882     }
    6883 
    6884     /* Guest */
    6885     {
    6886         Key guestNode = aNode.createKey ("Guest");
    6887 
    6888         guestNode.setValue <ULONG> ("memoryBalloonSize",
    6889                                     mHWData->mMemoryBalloonSize);
    6890         guestNode.setValue <ULONG> ("statisticsUpdateInterval",
    6891                                     mHWData->mStatisticsUpdateInterval);
    6892     }
    6893 
    6894 #ifdef VBOX_WITH_GUEST_PROPS
    6895     /* Guest properties */
    6896     try
    6897     {
    6898         using namespace guestProp;
    6899 
    6900         Key guestPropertiesNode = aNode.createKey ("GuestProperties");
    6901 
    6902         for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
    6903              it != mHWData->mGuestProperties.end(); ++it)
    6904         {
    6905             HWData::GuestProperty property = *it;
    6906 
    6907             Key propertyNode = guestPropertiesNode.appendKey ("GuestProperty");
    6908             char szFlags[MAX_FLAGS_LEN + 1];
    6909 
    6910             propertyNode.setValue <Bstr> ("name", property.mName);
    6911             propertyNode.setValue <Bstr> ("value", property.mValue);
    6912             propertyNode.setValue <ULONG64> ("timestamp", property.mTimestamp);
    6913             writeFlags (property.mFlags, szFlags);
    6914             Bstr flags (szFlags);
    6915             if (flags.isNull())
    6916                 return E_OUTOFMEMORY;
    6917             propertyNode.setValue <Bstr> ("flags", flags);
    6918         }
    6919         Bstr emptyStr ("");
    6920         if (emptyStr.isNull())
    6921             return E_OUTOFMEMORY;
    6922         guestPropertiesNode.setValueOr <Bstr> ("notificationPatterns",
    6923                                                mHWData->mGuestPropertyNotificationPatterns,
    6924                                                emptyStr);
    6925     }
    6926     catch(std::bad_alloc &e)
    6927     {
    6928         return E_OUTOFMEMORY;
    6929     }
    6930 #endif /* VBOX_WITH_GUEST_PROPS defined */
    6931 
    6932     AssertComRC (rc);
    6933     return rc;
    6934 }
    6935 
    6936 /**
    6937  *  Saves the storage controller configuration.
    6938  *
    6939  *  @param aNode    <StorageControllers> node to save the VM hardware confguration to.
    6940  */
    6941 HRESULT Machine::saveStorageControllers (settings::Key &aNode)
    6942 {
    6943     using namespace settings;
    6944 
    6945     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    6946 
    6947     for (StorageControllerList::const_iterator
    6948          it = mStorageControllers->begin();
    6949          it != mStorageControllers->end();
    6950          ++ it)
    6951     {
    6952         HRESULT rc;
    6953         const char *type = NULL;
    6954         ComObjPtr<StorageController> ctl = *it;
    6955 
    6956         Key ctlNode = aNode.appendKey ("StorageController");
    6957 
    6958         ctlNode.setValue <Bstr> ("name", ctl->name());
    6959 
    6960         switch (ctl->controllerType())
    6961         {
    6962             case StorageControllerType_IntelAhci: type = "AHCI"; break;
    6963             case StorageControllerType_LsiLogic: type = "LsiLogic"; break;
    6964             case StorageControllerType_BusLogic: type = "BusLogic"; break;
    6965             case StorageControllerType_PIIX3: type = "PIIX3"; break;
    6966             case StorageControllerType_PIIX4: type = "PIIX4"; break;
    6967             case StorageControllerType_ICH6: type = "ICH6"; break;
    6968             default:
    6969                 ComAssertFailedRet (E_FAIL);
    6970         }
    6971 
    6972         ctlNode.setStringValue ("type", type);
    6973 
    6974         /* Save the port count. */
    6975         ULONG portCount;
    6976         rc = ctl->COMGETTER(PortCount)(&portCount);
    6977         ComAssertRCRet(rc, rc);
    6978         ctlNode.setValue <ULONG> ("PortCount", portCount);
    6979 
    6980         /* Save IDE emulation settings. */
    6981         if (ctl->controllerType() == StorageControllerType_IntelAhci)
    6982         {
    6983             LONG uVal;
    6984 
    6985             rc = ctl->GetIDEEmulationPort(0, &uVal);
    6986             ComAssertRCRet(rc, rc);
    6987             ctlNode.setValue <LONG> ("IDE0MasterEmulationPort", uVal);
    6988 
    6989             rc = ctl->GetIDEEmulationPort(1, &uVal);
    6990             ComAssertRCRet(rc, rc);
    6991             ctlNode.setValue <LONG> ("IDE0SlaveEmulationPort", uVal);
    6992 
    6993             rc = ctl->GetIDEEmulationPort(2, &uVal);
    6994             ComAssertRCRet(rc, rc);
    6995             ctlNode.setValue <LONG> ("IDE1MasterEmulationPort", uVal);
    6996 
    6997             rc = ctl->GetIDEEmulationPort(3, &uVal);
    6998             ComAssertRCRet(rc, rc);
    6999             ctlNode.setValue <LONG> ("IDE1SlaveEmulationPort", uVal);
    7000         }
    7001 
    7002         /* save the devices now. */
    7003         rc = saveStorageDevices(ctl, ctlNode);
    7004         ComAssertRCRet(rc, rc);
    7005     }
    7006 
    7007     return S_OK;
    7008 }
    7009 
    7010 /**
    7011  *  Saves the hard disk confguration.
    7012  *  It is assumed that the given node is empty.
    7013  *
    7014  *  @param aNode    <HardDiskAttachments> node to save the hard disk confguration to.
    7015  */
    7016 HRESULT Machine::saveStorageDevices (ComObjPtr<StorageController> aStorageController,
    7017                                      settings::Key &aNode)
    7018 {
    7019     using namespace settings;
    7020 
    7021     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    7022 
    7023     HDData::AttachmentList atts;
    7024 
    7025     HRESULT rc = getHardDiskAttachmentsOfController(aStorageController->name(), atts);
    7026     CheckComRCReturnRC(rc);
    7027 
    7028     for (HDData::AttachmentList::const_iterator
    7029          it = atts.begin();
    7030          it != atts.end();
    7031          ++ it)
    7032     {
    7033         Key hdNode = aNode.appendKey ("AttachedDevice");
    7034 
    7035         {
    7036             /* device type. Only hard disk allowed atm. */
    7037             hdNode.setStringValue ("type", "HardDisk");
    7038             /* channel (required) */
    7039             hdNode.setValue <LONG> ("port", (*it)->port());
    7040             /* device (required) */
    7041             hdNode.setValue <LONG> ("device", (*it)->device());
    7042             /* ID of the image. */
    7043             Key idNode = hdNode.appendKey ("Image");
    7044             idNode.setValue <Guid> ("uuid", (*it)->hardDisk()->id());
    7045         }
    7046     }
    7047 
    7048     return S_OK;
    7049 }
    7050 
    7051 /**
    7052  *  Saves machine state settings as defined by aFlags
    7053  *  (SaveSTS_* values).
    7054  *
    7055  *  @param aFlags   Combination of SaveSTS_* flags.
    7056  *
    7057  *  @note Locks objects for writing.
    7058  */
    7059 HRESULT Machine::saveStateSettings (int aFlags)
    7060 {
    7061     if (aFlags == 0)
    7062         return S_OK;
    7063 
    7064     AutoCaller autoCaller(this);
    7065     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    7066 
    7067     /* This object's write lock is also necessary to serialize file access
    7068      * (prevent concurrent reads and writes) */
    7069     AutoWriteLock alock(this);
    7070 
    7071     AssertReturn(isConfigLocked(), E_FAIL);
    7072 
    7073     HRESULT rc = S_OK;
    7074 
    7075     try
    7076     {
    7077         using namespace settings;
    7078         using namespace xml;
    7079 
    7080         /* load the settings file */
    7081         File file (mData->mHandleCfgFile, Utf8Str (mData->mConfigFileFull));
    7082         XmlTreeBackend tree;
    7083 
    7084         rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
    7085         CheckComRCReturnRC(rc);
    7086 
    7087         Key machineNode = tree.rootKey().key ("Machine");
    7088 
    70895996        if (aFlags & SaveSTS_CurStateModified)
    7090         {
    7091             /* defaults to true */
    7092             machineNode.setValueOr <bool> ("currentStateModified",
    7093                                            !!mData->mCurrentStateModified, true);
    7094         }
     5997            mData->m_pMachineConfigFile->fCurrentStateModified = true;
    70955998
    70965999        if (aFlags & SaveSTS_StateFilePath)
    7097         {
    70986000            if (mSSData->mStateFilePath)
    70996001            {
    71006002                /* try to make the file name relative to the settings file dir */
    71016003                Utf8Str stateFilePath = mSSData->mStateFilePath;
    7102                 calculateRelativePath (stateFilePath, stateFilePath);
    7103                 machineNode.setStringValue ("stateFile", stateFilePath);
     6004                calculateRelativePath(stateFilePath, stateFilePath);
     6005                mData->m_pMachineConfigFile->strStateFile = stateFilePath;
    71046006            }
    71056007            else
    7106                 machineNode.zapValue ("stateFile");
    7107         }
     6008                mData->m_pMachineConfigFile->strStateFile.setNull();
    71086009
    71096010        if (aFlags & SaveSTS_StateTimeStamp)
    71106011        {
    7111             Assert (mData->mMachineState != MachineState_Aborted ||
    7112                     mSSData->mStateFilePath.isNull());
    7113 
    7114             machineNode.setValue <RTTIMESPEC> ("lastStateChange",
    7115                                                mData->mLastStateChange);
    7116 
    7117             /* set the aborted attribute when appropriate, defaults to false */
    7118             machineNode.setValueOr <bool> ("aborted",
    7119                                            mData->mMachineState == MachineState_Aborted,
    7120                                            false);
    7121         }
    7122 
    7123         /* save settings on success */
    7124         rc = VirtualBox::saveSettingsTree (tree, file,
    7125                                            mData->mSettingsFileVersion);
    7126         CheckComRCReturnRC(rc);
     6012            Assert(    mData->mMachineState != MachineState_Aborted
     6013                    || mSSData->mStateFilePath.isNull());
     6014
     6015            mData->m_pMachineConfigFile->timeLastStateChange = mData->mLastStateChange;
     6016
     6017            mData->m_pMachineConfigFile->fAborted = (mData->mMachineState == MachineState_Aborted);
     6018        }
     6019
     6020        mData->m_pMachineConfigFile->write(mData->m_strConfigFileFull);
    71276021    }
    71286022    catch (...)
     
    72006094
    72016095                rc = hd->LockRead (NULL);
    7202                 CheckComRCThrowRC (rc);
     6096                CheckComRCThrowRC(rc);
    72036097
    72046098                lockedMedia.push_back (hd);
     
    72326126                                                         hd->root()->name().raw()),
    72336127                                                 1);        // weight
    7234                 CheckComRCThrowRC (rc);
     6128                CheckComRCThrowRC(rc);
    72356129
    72366130                mHDData->mAttachments.push_back (hda);
     
    72436137                                                     hd->root()->name().raw()),
    72446138                                             1);        // weight
    7245             CheckComRCThrowRC (rc);
     6139            CheckComRCThrowRC(rc);
    72466140
    72476141            ComObjPtr<HardDisk> diff;
    72486142            diff.createObject();
    7249             rc = diff->init (mParent, hd->preferredDiffFormat(),
    7250                              BstrFmt ("%ls"RTPATH_SLASH_STR,
    7251                                       mUserData->mSnapshotFolderFull.raw()));
    7252             CheckComRCThrowRC (rc);
     6143            rc = diff->init(mParent,
     6144                            hd->preferredDiffFormat(),
     6145                            BstrFmt("%ls"RTPATH_SLASH_STR,
     6146                                    mUserData->mSnapshotFolderFull.raw()));
     6147            CheckComRCThrowRC(rc);
    72536148
    72546149            /* leave the lock before the potentially lengthy operation */
     
    72606155            alock.enter();
    72616156
    7262             CheckComRCThrowRC (rc);
     6157            CheckComRCThrowRC(rc);
    72636158
    72646159            rc = diff->attachTo (mData->mUuid);
     
    72706165            rc = attachment->init (diff, hda->controller(), hda->port(),
    72716166                                   hda->device(), true /* aImplicit */);
    7272             CheckComRCThrowRC (rc);
     6167            CheckComRCThrowRC(rc);
    72736168
    72746169            mHDData->mAttachments.push_back (attachment);
     
    72866181        {
    72876182            HRESULT rc2 = (*it)->UnlockRead (NULL);
    7288             AssertComRC (rc2);
    7289         }
    7290     }
    7291 
    7292     if (FAILED (rc))
     6183            AssertComRC(rc2);
     6184        }
     6185    }
     6186
     6187    if (FAILED(rc))
    72936188    {
    72946189        MultiResultRef mrc (rc);
     
    73366231            /* deassociate and mark for deletion */
    73376232            rc = hd->detachFrom (mData->mUuid);
    7338             AssertComRC (rc);
     6233            AssertComRC(rc);
    73396234            implicitAtts.push_back (*it);
    73406235            continue;
     
    73496244            /* no: de-associate */
    73506245            rc = hd->detachFrom (mData->mUuid);
    7351             AssertComRC (rc);
     6246            AssertComRC(rc);
    73526247            continue;
    73536248        }
     
    74476342                {
    74486343                    rc = hd->LockWrite (NULL);
    7449                     AssertComRC (rc);
     6344                    AssertComRC(rc);
    74506345
    74516346                    mData->mSession.mLockedMedia.push_back (
     
    74606355                    AutoWriteLock parentLock (parent);
    74616356                    rc = parent->UnlockWrite (NULL);
    7462                     AssertComRC (rc);
     6357                    AssertComRC(rc);
    74636358                    rc = parent->LockRead (NULL);
    7464                     AssertComRC (rc);
     6359                    AssertComRC(rc);
    74656360
    74666361                    /* XXX actually we should replace the old entry in that
     
    74966391            /* now de-associate from the current machine state */
    74976392            rc = hd->detachFrom (mData->mUuid);
    7498             AssertComRC (rc);
     6393            AssertComRC(rc);
    74996394
    75006395            if (aOnline)
     
    75266421
    75276422/**
    7528  *  Helper to lock the machine configuration for write access.
    7529  *
    7530  *  @return S_OK or E_FAIL and sets error info on failure
    7531  *
    7532  *  @note Doesn't lock anything (must be called from this object's lock)
    7533  */
    7534 HRESULT Machine::lockConfig()
    7535 {
    7536     HRESULT rc = S_OK;
    7537 
    7538     if (!isConfigLocked())
    7539     {
    7540         /* open the associated config file */
    7541         int vrc = RTFileOpen (&mData->mHandleCfgFile,
    7542                               Utf8Str (mData->mConfigFileFull),
    7543                               RTFILE_O_READWRITE | RTFILE_O_OPEN |
    7544                               RTFILE_O_DENY_WRITE);
    7545         if (RT_FAILURE(vrc) && (vrc != VERR_FILE_NOT_FOUND))
    7546         {
    7547             /* Open the associated config file only with read access. */
    7548             vrc = RTFileOpen (&mData->mHandleCfgFile,
    7549                               Utf8Str (mData->mConfigFileFull),
    7550                               RTFILE_O_READ | RTFILE_O_OPEN |
    7551                               RTFILE_O_DENY_NONE);
    7552             if (RT_FAILURE(vrc))
    7553             {
    7554                 /* We even cannot open it in read mode, so there's seriously
    7555                    something wrong. */
    7556                 rc = setError (E_FAIL,
    7557                         tr ("Could not even open settings file '%ls' in read mode (%Rrc)"),
    7558                         mData->mConfigFile.raw(), vrc);
    7559             }
    7560             else
    7561             {
    7562                 mData->mConfigFileReadonly = TRUE;
    7563             }
    7564         }
    7565         else
    7566         {
    7567             mData->mConfigFileReadonly = FALSE;
    7568         }
    7569 
    7570         if (RT_FAILURE(vrc))
    7571         {
    7572             mData->mHandleCfgFile = NIL_RTFILE;
    7573             mData->mConfigFileReadonly = FALSE;
    7574         }
    7575     }
    7576 
    7577     LogFlowThisFunc(("mConfigFile={%ls}, mHandleCfgFile=%d, rc=%08X\n",
    7578                       mData->mConfigFileFull.raw(), mData->mHandleCfgFile, rc));
    7579     return rc;
    7580 }
    7581 
    7582 /**
    7583  *  Helper to unlock the machine configuration from write access
    7584  *
    7585  *  @return S_OK
    7586  *
    7587  *  @note Doesn't lock anything.
    7588  *  @note Not thread safe (must be called from this object's lock).
    7589  */
    7590 HRESULT Machine::unlockConfig()
    7591 {
    7592     HRESULT rc = S_OK;
    7593 
    7594     if (isConfigLocked())
    7595     {
    7596         RTFileFlush (mData->mHandleCfgFile);
    7597         RTFileClose (mData->mHandleCfgFile);
    7598         /** @todo flush the directory. */
    7599         mData->mHandleCfgFile = NIL_RTFILE;
    7600         mData->mConfigFileReadonly = FALSE;
    7601     }
    7602 
    7603     LogFlowThisFunc(("\n"));
    7604 
    7605     return rc;
    7606 }
    7607 
    7608 /**
    76096423 *  Returns true if the settings file is located in the directory named exactly
    76106424 *  as the machine. This will be true if the machine settings structure was
     
    76196433bool Machine::isInOwnDir(Utf8Str *aSettingsDir /* = NULL */)
    76206434{
    7621     Utf8Str settingsDir = mData->mConfigFileFull;
     6435    Utf8Str settingsDir = mData->m_strConfigFileFull;
    76226436    settingsDir.stripFilename();
    7623     char *dirName = RTPathFilename(settingsDir);
     6437    char *dirName = RTPathFilename(settingsDir.c_str());
    76246438
    76256439    AssertReturn(dirName, false);
     
    83177131    if (mIPCSem < 0 && errnoSave == ENOSYS)
    83187132    {
    8319         setError (E_FAIL,
    8320                   tr ("Cannot create IPC semaphore. Most likely your host kernel lacks "
    8321                       "support for SysV IPC. Check the host kernel configuration for "
    8322                       "CONFIG_SYSVIPC=y"));
     7133        setError(E_FAIL,
     7134                 tr("Cannot create IPC semaphore. Most likely your host kernel lacks "
     7135                    "support for SysV IPC. Check the host kernel configuration for "
     7136                    "CONFIG_SYSVIPC=y"));
    83237137        return E_FAIL;
    83247138    }
     
    85237337         * for the aAbnormal argument. */
    85247338        HRESULT rc = mUSBController->notifyProxy (false /* aInsertFilters */);
    8525         AssertComRC (rc);
     7339        AssertComRC(rc);
    85267340        NOREF (rc);
    85277341
     
    88037617#ifdef VBOX_WITH_USB
    88047618    HRESULT rc = mUSBController->notifyProxy (true /* aInsertFilters */);
    8805     AssertComRC (rc);
     7619    AssertComRC(rc);
    88067620    NOREF (rc);
    88077621
     
    88337647#ifdef VBOX_WITH_USB
    88347648    HRESULT rc = mUSBController->notifyProxy (false /* aInsertFilters */);
    8835     AssertComRC (rc);
     7649    AssertComRC(rc);
    88367650    NOREF (rc);
    88377651
     
    90217835
    90227836    Utf8Str stateFilePathFull = aSavedStateFile;
    9023     int vrc = calculateFullPath (stateFilePathFull, stateFilePathFull);
     7837    int vrc = calculateFullPath(stateFilePathFull, stateFilePathFull);
    90247838    if (RT_FAILURE(vrc))
    9025         return setError (VBOX_E_FILE_ERROR,
    9026             tr ("Invalid saved state file path '%ls' (%Rrc)"),
    9027                 aSavedStateFile, vrc);
     7839        return setError(VBOX_E_FILE_ERROR,
     7840                        tr("Invalid saved state file path '%ls' (%Rrc)"),
     7841                        aSavedStateFile,
     7842                        vrc);
    90287843
    90297844    mSSData->mStateFilePath = stateFilePathFull;
     
    91107925    if (stateFilePath)
    91117926    {
    9112         HRESULT rc = VirtualBox::ensureFilePathExists (Utf8Str (stateFilePath));
     7927        HRESULT rc = VirtualBox::ensureFilePathExists(Utf8Str(stateFilePath));
    91137928        CheckComRCReturnRC(rc);
    91147929    }
     
    92778092            AutoWriteLock vboxLock(mParent);
    92788093            rc = saveSettings();
    9279             CheckComRCReturnRC(rc);
     8094            CheckComRCReturnRC (rc);
    92808095            vboxLock.unlock();
    92818096
     
    93398154
    93408155    if (mData->mCurrentSnapshot.isNull())
    9341         return setError (VBOX_E_INVALID_OBJECT_STATE,
    9342             tr ("Could not discard the current state of the machine '%ls' "
    9343                 "because it doesn't have any snapshots"),
    9344             mUserData->mName.raw());
     8156        return setError(VBOX_E_INVALID_OBJECT_STATE,
     8157                        tr("Could not discard the current state of the machine '%ls' because it doesn't have any snapshots"),
     8158                        mUserData->mName.raw());
    93458159
    93468160    /* create a progress object. The number of operations is: 1 (preparing) + #
     
    94038217
    94048218    if (mData->mCurrentSnapshot.isNull())
    9405         return setError (VBOX_E_INVALID_OBJECT_STATE,
    9406             tr ("Could not discard the current state of the machine '%ls' "
    9407                 "because it doesn't have any snapshots"),
    9408             mUserData->mName.raw());
     8219        return setError(VBOX_E_INVALID_OBJECT_STATE,
     8220                        tr("Could not discard the current state of the machine '%ls' "
     8221                           "because it doesn't have any snapshots"),
     8222                        mUserData->mName.raw());
    94098223
    94108224    /* create a progress object. The number of operations is:
     
    94718285}
    94728286
    9473 STDMETHODIMP SessionMachine::
    9474 PullGuestProperties (ComSafeArrayOut(BSTR, aNames),
    9475                      ComSafeArrayOut(BSTR, aValues),
    9476                      ComSafeArrayOut(ULONG64, aTimestamps),
    9477                      ComSafeArrayOut(BSTR, aFlags))
     8287STDMETHODIMP SessionMachine::PullGuestProperties(ComSafeArrayOut(BSTR, aNames),
     8288                                                 ComSafeArrayOut(BSTR, aValues),
     8289                                                 ComSafeArrayOut(ULONG64, aTimestamps),
     8290                                                 ComSafeArrayOut(BSTR, aFlags))
    94788291{
    94798292    LogFlowThisFunc(("\n"));
     
    94998312    unsigned i = 0;
    95008313    for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
    9501          it != mHWData->mGuestProperties.end(); ++it)
     8314         it != mHWData->mGuestProperties.end();
     8315         ++it)
    95028316    {
    95038317        char szFlags[MAX_FLAGS_LEN + 1];
    9504         it->mName.cloneTo(&names[i]);
    9505         it->mValue.cloneTo(&values[i]);
     8318        it->strName.cloneTo(&names[i]);
     8319        it->strValue.cloneTo(&values[i]);
    95068320        timestamps[i] = it->mTimestamp;
    9507         writeFlags (it->mFlags, szFlags);
    9508         Bstr (szFlags).cloneTo(&flags[i]);
     8321        writeFlags(it->mFlags, szFlags);
     8322        Bstr(szFlags).cloneTo(&flags[i]);
    95098323        ++i;
    95108324    }
     
    95208334}
    95218335
    9522 STDMETHODIMP SessionMachine::PushGuestProperties (ComSafeArrayIn (IN_BSTR, aNames),
    9523                                                   ComSafeArrayIn (IN_BSTR, aValues),
    9524                                                   ComSafeArrayIn (ULONG64, aTimestamps),
    9525                                                   ComSafeArrayIn (IN_BSTR, aFlags))
     8336STDMETHODIMP SessionMachine::PushGuestProperties(ComSafeArrayIn (IN_BSTR, aNames),
     8337                                                 ComSafeArrayIn (IN_BSTR, aValues),
     8338                                                 ComSafeArrayIn (ULONG64, aTimestamps),
     8339                                                 ComSafeArrayIn (IN_BSTR, aFlags))
    95268340{
    95278341    LogFlowThisFunc(("\n"));
     
    95788392}
    95798393
    9580 STDMETHODIMP SessionMachine::PushGuestProperty (IN_BSTR aName, IN_BSTR aValue,
    9581                                                 ULONG64 aTimestamp, IN_BSTR aFlags)
     8394STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName,
     8395                                               IN_BSTR aValue,
     8396                                               ULONG64 aTimestamp,
     8397                                               IN_BSTR aFlags)
    95828398{
    95838399    LogFlowThisFunc(("\n"));
     
    96148430        mHWData.backup();
    96158431        for (HWData::GuestPropertyList::iterator iter = mHWData->mGuestProperties.begin();
    9616             iter != mHWData->mGuestProperties.end(); ++iter)
    9617             if (aName == iter->mName)
     8432             iter != mHWData->mGuestProperties.end();
     8433             ++iter)
     8434            if (utf8Name == iter->strName)
    96188435            {
    9619                 mHWData->mGuestProperties.erase (iter);
     8436                mHWData->mGuestProperties.erase(iter);
    96208437                break;
    96218438            }
     
    96288445        /* send a callback notification if appropriate */
    96298446        alock.leave();
    9630         if (   matchAll
    9631             || RTStrSimplePatternMultiMatch (utf8Patterns.raw(), RTSTR_MAX,
    9632                                             utf8Name.raw(), RTSTR_MAX, NULL)
     8447        if (    matchAll
     8448             || RTStrSimplePatternMultiMatch(utf8Patterns.raw(),
     8449                                             RTSTR_MAX,
     8450                                             utf8Name.raw(),
     8451                                             RTSTR_MAX, NULL)
    96338452        )
    9634             mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags);
     8453            mParent->onGuestPropertyChange(mData->mUuid,
     8454                                           aName,
     8455                                           aValue,
     8456                                           aFlags);
    96358457    }
    96368458    catch(std::bad_alloc &e)
     
    100728894    {
    100738895        /* delete the saved state file (it might have been already created) */
    10074         RTFileDelete (Utf8Str (mSnapshotData.mStateFilePath));
     8896        RTFileDelete(Utf8Str(mSnapshotData.mStateFilePath).c_str());
    100758897    }
    100768898
     
    101228944            mData->mFirstSnapshot = mData->mCurrentSnapshot;
    101238945
    10124         int opFlags = SaveSS_AddOp | SaveSS_CurrentId;
    101258946        if (!Global::IsOnline (mSnapshotData.mLastState))
    10126         {
    101278947            /* the machine was powered off or saved when taking a snapshot, so
    101288948             * reset the mCurrentStateModified flag */
    101298949            mData->mCurrentStateModified = FALSE;
    10130             opFlags |= SaveSS_CurStateModified;
    10131         }
    10132 
    10133         rc = saveSnapshotSettings (mSnapshotData.mSnapshot, opFlags);
     8950
     8951        rc = saveSettings();
    101348952    }
    101358953
     
    101588976        /* delete the saved state file (it might have been already created) */
    101598977        if (mSnapshotData.mSnapshot->stateFilePath())
    10160             RTFileDelete (Utf8Str (mSnapshotData.mSnapshot->stateFilePath()));
     8978            RTFileDelete(Utf8Str(mSnapshotData.mSnapshot->stateFilePath()).c_str());
    101618979
    101628980        mSnapshotData.mSnapshot->uninit();
     
    102379055
    102389056        /* copy the state file */
    10239         int vrc = RTFileCopyEx (stateFrom, stateTo, 0, progressCallback,
    10240                                 static_cast <Progress *> (mSnapshotData.mServerProgress));
     9057        int vrc = RTFileCopyEx(stateFrom.c_str(),
     9058                               stateTo.c_str(),
     9059                               0,
     9060                               progressCallback,
     9061                               static_cast<Progress*>(mSnapshotData.mServerProgress));
    102419062
    102429063        alock.enter();
    102439064
    102449065        if (RT_FAILURE(vrc))
    10245             rc = setError (E_FAIL,
    10246                 tr ("Could not copy the state file '%s' to '%s' (%Rrc)"),
    10247                 stateFrom.raw(), stateTo.raw(), vrc);
     9066            rc = setError(E_FAIL,
     9067                          tr("Could not copy the state file '%s' to '%s' (%Rrc)"),
     9068                          stateFrom.raw(),
     9069                          stateTo.raw(),
     9070                          vrc);
    102489071    }
    102499072
     
    103859208             * prerequisites */
    103869209            rc = hd->prepareDiscard (chain);
    10387             CheckComRCThrowRC (rc);
     9210            CheckComRCThrowRC(rc);
    103889211
    103899212            if (hd->parent().isNull() && chain != NULL)
     
    104159238                /* adjust back references */
    104169239                rc2 = replaceHd->detachFrom (mData->mUuid, snapshotId);
    10417                 AssertComRC (rc2);
     9240                AssertComRC(rc2);
    104189241
    104199242                rc2 = hd->attachTo (mData->mUuid, snapshotId);
    10420                 AssertComRC (rc2);
     9243                AssertComRC(rc2);
    104219244
    104229245                /* replace the hard disk in the attachment object */
     
    104759298            aTask.snapshot->uninit();
    104769299
    10477             rc = saveSnapshotSettings(parentSnapshot,
    10478                                       SaveSS_UpdateAllOp | SaveSS_CurrentId | SaveSS_CurStateModified);
    10479             CheckComRCThrowRC (rc);
     9300            rc = saveAllSnapshots();
     9301            CheckComRCThrowRC(rc);
    104809302
    104819303            /// @todo (dmik)
     
    104879309                                                 1);        // weight
    104889310
    10489                 RTFileDelete(Utf8Str(stateFilePath));
     9311                RTFileDelete(Utf8Str(stateFilePath).c_str());
    104909312            }
    104919313
     
    105199341        {
    105209342            rc = it->hd->discard (aTask.progress, it->chain);
    10521             CheckComRCBreakRC (rc);
     9343            CheckComRCBreakRC(rc);
    105229344
    105239345            /* prevent from calling cancelDiscard() */
     
    105279349        alock.enter();
    105289350
    10529         CheckComRCThrowRC (rc);
     9351        CheckComRCThrowRC(rc);
    105309352    }
    105319353    catch (HRESULT aRC) { rc = aRC; }
    105329354
    10533     if FAILED (rc)
     9355    if FAILED(rc)
    105349356    {
    105359357        HRESULT rc2 = S_OK;
     
    105469368
    105479369                rc2 = it->replaceHd->attachTo (mData->mUuid, it->snapshotId);
    10548                 AssertComRC (rc2);
     9370                AssertComRC(rc2);
    105499371
    105509372                rc2 = it->hd->detachFrom (mData->mUuid, it->snapshotId);
    10551                 AssertComRC (rc2);
     9373                AssertComRC(rc2);
    105529374
    105539375                AutoWriteLock attLock (it->replaceHda);
     
    105579379    }
    105589380
    10559     if (!aTask.subTask || FAILED (rc))
     9381    if (!aTask.subTask || FAILED(rc))
    105609382    {
    105619383        if (!aTask.subTask)
     
    106479469        {
    106489470            Assert (!mSSData->mStateFilePath.isEmpty());
    10649             RTFileDelete (Utf8Str (mSSData->mStateFilePath));
     9471            RTFileDelete(Utf8Str(mSSData->mStateFilePath).c_str());
    106509472            mSSData->mStateFilePath.setNull();
    106519473            aTask.modifyLastState (MachineState_PoweredOff);
    106529474            rc = saveStateSettings (SaveSTS_StateFilePath);
    10653             CheckComRCThrowRC (rc);
     9475            CheckComRCThrowRC(rc);
    106549476        }
    106559477
     
    106719493                 * a failure */
    106729494                rc = aTask.progress->resultCode();
    10673                 Assert (FAILED (rc));
     9495                Assert (FAILED(rc));
    106749496                errorInSubtask = true;
    106759497                throw rc;
     
    107109532            snapshotLock.lock();
    107119533
    10712             CheckComRCThrowRC (rc);
     9534            CheckComRCThrowRC(rc);
    107139535
    107149536            /* Note: on success, current (old) hard disks will be
     
    107399561
    107409562                /* copy the state file */
    10741                 int vrc = RTFileCopyEx (snapStateFilePath, stateFilePath,
    10742                                         0, progressCallback, aTask.progress);
     9563                int vrc = RTFileCopyEx(snapStateFilePath.c_str(),
     9564                                       stateFilePath.c_str(),
     9565                                       0,
     9566                                       progressCallback,
     9567                                       aTask.progress);
    107439568
    107449569                alock.enter();
     
    107519576                else
    107529577                {
    10753                     throw setError (E_FAIL,
    10754                         tr ("Could not copy the state file '%s' to '%s' (%Rrc)"),
    10755                         snapStateFilePath.raw(), stateFilePath.raw(), vrc);
     9578                    throw setError(E_FAIL,
     9579                                   tr("Could not copy the state file '%s' to '%s' (%Rrc)"),
     9580                                   snapStateFilePath.raw(),
     9581                                   stateFilePath.raw(),
     9582                                   vrc);
    107569583                }
    107579584            }
     
    108159642                 * was a failure */
    108169643                rc = aTask.progress->resultCode();
    10817                 Assert (FAILED (rc));
     9644                Assert (FAILED(rc));
    108189645                errorInSubtask = true;
    108199646            }
     
    108529679         * already committed machine data and deleted old diffs before
    108539680         * discarding the current snapshot so there is no way to rollback */
    10854         HRESULT rc2 = saveSettings (SaveS_ResetCurStateModified | saveFlags);
     9681        HRESULT rc2 = saveSettings(SaveS_ResetCurStateModified | saveFlags);
    108559682
    108569683        /// @todo NEWMEDIA return multiple errors
     
    109649791                {
    109659792                    rc = hd->LockWrite (&mediaState);
    10966                     CheckComRCThrowRC (rc);
     9793                    CheckComRCThrowRC(rc);
    109679794
    109689795                    mData->mSession.mLockedMedia.push_back (
     
    109759802                {
    109769803                    rc = hd->LockRead (&mediaState);
    10977                     CheckComRCThrowRC (rc);
     9804                    CheckComRCThrowRC(rc);
    109789805
    109799806                    mData->mSession.mLockedMedia.push_back (
     
    110429869            MediaState_T mediaState;
    110439870            rc = (*it)->COMGETTER(State) (&mediaState);
    11044             CheckComRCThrowRC (rc);
     9871            CheckComRCThrowRC(rc);
    110459872
    110469873            Assert (mediaState == MediaState_LockedRead ||
     
    110529879            Bstr error;
    110539880            rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam());
    11054             CheckComRCThrowRC (rc);
     9881            CheckComRCThrowRC(rc);
    110559882
    110569883            if (!error.isEmpty())
     
    110589885                Bstr loc;
    110599886                rc = (*it)->COMGETTER(Location) (loc.asOutParam());
    11060                 CheckComRCThrowRC (rc);
     9887                CheckComRCThrowRC(rc);
    110619888
    110629889                /* collect multiple errors */
     
    110659892                /* be in sync with MediumBase::setStateError() */
    110669893                Assert (!error.isEmpty());
    11067                 mrc = setError (E_FAIL,
    11068                     tr ("Medium '%ls' is not accessible. %ls"),
    11069                     loc.raw(), error.raw());
     9894                mrc = setError(E_FAIL,
     9895                               tr("Medium '%ls' is not accessible. %ls"),
     9896                               loc.raw(),
     9897                               error.raw());
    110709898
    110719899                eik.fetch();
     
    110749902
    110759903        eik.restore();
    11076         CheckComRCThrowRC ((HRESULT) mrc);
     9904        CheckComRCThrowRC((HRESULT) mrc);
    110779905    }
    110789906    catch (HRESULT aRC)
     
    1123710065        {
    1123810066            Assert (!mSSData->mStateFilePath.isEmpty());
    11239             RTFileDelete (Utf8Str (mSSData->mStateFilePath));
     10067            RTFileDelete(Utf8Str(mSSData->mStateFilePath).c_str());
    1124010068        }
    1124110069        mSSData->mStateFilePath.setNull();
     
    1136310191HRESULT SnapshotMachine::init (SessionMachine *aSessionMachine,
    1136410192                               IN_GUID aSnapshotId,
    11365                                IN_BSTR aStateFilePath)
     10193                               const Utf8Str &aStateFilePath)
    1136610194{
    1136710195    LogFlowThisFuncEnter();
     
    1142110249    {
    1142210250        rc = (*it)->hardDisk()->attachTo (mData->mUuid, mSnapshotId);
    11423         AssertComRC (rc);
     10251        AssertComRC(rc);
    1142410252    }
    1142510253
     
    1149710325 *  @note Doesn't lock anything.
    1149810326 */
    11499 HRESULT SnapshotMachine::init (Machine *aMachine,
    11500                                const settings::Key &aHWNode,
    11501                                const settings::Key &aHDAsNode,
    11502                                IN_GUID aSnapshotId, IN_BSTR aStateFilePath)
     10327HRESULT SnapshotMachine::init(Machine *aMachine,
     10328                              const settings::Hardware &hardware,
     10329                              const settings::Storage &storage,
     10330                              IN_GUID aSnapshotId,
     10331                              const Utf8Str &aStateFilePath)
    1150310332{
    1150410333    LogFlowThisFuncEnter();
    1150510334    LogFlowThisFunc(("mName={%ls}\n", aMachine->mUserData->mName.raw()));
    1150610335
    11507     AssertReturn(aMachine && !aHWNode.isNull() && !aHDAsNode.isNull() &&
    11508                   !Guid (aSnapshotId).isEmpty(),
    11509                   E_INVALIDARG);
     10336    AssertReturn(aMachine &&  !Guid(aSnapshotId).isEmpty(), E_INVALIDARG);
    1151010337
    1151110338    /* Enclose the state transition NotReady->InInit->Ready */
     
    1158010407    /* load hardware and harddisk settings */
    1158110408
    11582     HRESULT rc = loadHardware (aHWNode);
     10409    HRESULT rc = loadHardware(hardware);
    1158310410    if (SUCCEEDED(rc))
    11584         rc = loadStorageControllers (aHDAsNode, true /* aRegistered */, &mSnapshotId);
     10411        rc = loadStorageControllers(storage, true /* aRegistered */, &mSnapshotId);
    1158510412
    1158610413    if (SUCCEEDED(rc))
    11587     {
    1158810414        /* commit all changes made during the initialization */
    1158910415        commit();
    11590     }
    1159110416
    1159210417    /* Confirm a successful initialization when it's the case */
     
    1164710472    AutoWriteLock alock(this);
    1164810473
    11649     mPeer->saveSnapshotSettings (aSnapshot, SaveSS_UpdateAttrsOp);
     10474    //     mPeer->saveAllSnapshots();  @todo
    1165010475
    1165110476    /* inform callbacks */
  • trunk/src/VBox/Main/MediumImpl.cpp

    r21878 r22173  
    552552    Utf8Str path = m.locationFull;
    553553
    554     if (RTPathStartsWith (path, aOldPath))
     554    if (RTPathStartsWith(path.c_str(), aOldPath))
    555555    {
    556556        Utf8Str newPath = Utf8StrFmt ("%s%s", aNewPath,
     
    688688    Utf8Str location (m.locationFull);
    689689
    690     Utf8Str name = RTPathFilename (location);
     690    Utf8Str name = RTPathFilename(location.c_str());
    691691    return name;
    692692}
     
    700700 * @note Must be called from under this object's write lock.
    701701 */
    702 HRESULT MediumBase::setLocation (CBSTR aLocation)
     702HRESULT MediumBase::setLocation(const Utf8Str &aLocation)
    703703{
    704704    /* get the full file name */
    705705    Utf8Str locationFull;
    706     int vrc = mVirtualBox->calculateFullPath (Utf8Str (aLocation), locationFull);
     706    int vrc = mVirtualBox->calculateFullPath(aLocation, locationFull);
    707707    if (RT_FAILURE(vrc))
    708         return setError (E_FAIL,
    709             tr ("Invalid image file location '%ls' (%Rrc)"),
    710             aLocation, vrc);
     708        return setError(E_FAIL,
     709                        tr("Invalid image file location '%s' (%Rrc)"),
     710                        aLocation.raw(),
     711                        vrc);
    711712
    712713    m.location = aLocation;
     
    790791    {
    791792        RTFILE file;
    792         vrc = RTFileOpen (&file, Utf8Str (m.locationFull), RTFILE_O_READ);
     793        vrc = RTFileOpen(&file, Utf8Str(m.locationFull).c_str(), RTFILE_O_READ);
    793794        if (RT_SUCCESS(vrc))
    794795        {
     
    976977         * newly opened media so convert this into an error */
    977978        if (!m.lastAccessError.isEmpty())
    978             rc = setError (VBOX_E_FILE_ERROR, Utf8Str (m.lastAccessError));
     979            rc = setError(VBOX_E_FILE_ERROR, Utf8Str(m.lastAccessError).c_str());
    979980    }
    980981
     
    995996 * @param aImageNode    Either <DVDImage> or <FloppyImage> settings node.
    996997 */
    997 HRESULT ImageMediumBase::protectedInit (VirtualBox *aVirtualBox,
    998                                         const settings::Key &aImageNode)
     998HRESULT ImageMediumBase::protectedInit(VirtualBox *aVirtualBox,
     999                                       const settings::Medium &data)
    9991000{
    10001001    AssertReturn(aVirtualBox, E_INVALIDARG);
     
    10181019
    10191020    /* required */
    1020     unconst(m.id) = aImageNode.value <Guid> ("uuid");
     1021    unconst(m.id) = data.uuid;
    10211022    /* required */
    1022     Bstr location = aImageNode.stringValue ("location");
    1023     rc = setLocation (location);
    1024     CheckComRCReturnRC(rc);
    1025     /* optional */
    1026     {
    1027         settings::Key descNode = aImageNode.findKey ("Description");
    1028         if (!descNode.isNull())
    1029             m.description = descNode.keyStringValue();
    1030     }
     1023    rc = setLocation(data.strLocation);
     1024    CheckComRCReturnRC (rc);
     1025
     1026    m.description = data.strDescription;
    10311027
    10321028    LogFlowThisFunc(("m.locationFull='%ls', m.id={%RTuuid}\n",
     
    10771073 * @note Locks this object for reading.
    10781074 */
    1079 HRESULT ImageMediumBase::saveSettings (settings::Key &aImagesNode)
    1080 {
    1081     using namespace settings;
    1082 
    1083     AssertReturn(!aImagesNode.isNull(), E_FAIL);
    1084 
    1085     AutoCaller autoCaller(this);
    1086     CheckComRCReturnRC(autoCaller.rc());
    1087 
    1088     AutoReadLock alock(this);
    1089 
    1090     Key imageNode = aImagesNode.appendKey ("Image");
    1091     /* required */
    1092     imageNode.setValue <Guid> ("uuid", m.id);
    1093     /* required */
    1094     imageNode.setValue <Bstr> ("location", m.locationFull);
    1095     /* optional */
    1096     if (!m.description.isNull())
    1097     {
    1098         Key descNode = aImagesNode.createKey ("Description");
    1099         descNode.setKeyValue <Bstr> (m.description);
    1100     }
     1075HRESULT ImageMediumBase::saveSettings(settings::Medium &data)
     1076{
     1077    AutoCaller autoCaller (this);
     1078    CheckComRCReturnRC (autoCaller.rc());
     1079
     1080    AutoReadLock alock (this);
     1081
     1082    data.uuid = m.id;
     1083    data.strLocation = m.locationFull;
     1084    data.strDescription = m.description;
     1085
     1086    data.llChildren.clear();
    11011087
    11021088    return S_OK;
  • trunk/src/VBox/Main/NetworkAdapterImpl.cpp

    r21961 r22173  
    897897 *  @note Locks this object for writing.
    898898 */
    899 HRESULT NetworkAdapter::loadSettings (const settings::Key &aAdapterNode)
    900 {
    901     using namespace settings;
    902 
    903     AssertReturn(!aAdapterNode.isNull(), E_FAIL);
    904 
     899HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
     900{
    905901    AutoCaller autoCaller(this);
    906902    AssertComRCReturnRC(autoCaller.rc());
     
    921917    HRESULT rc = S_OK;
    922918
    923     /* type (optional, defaults to Am79C970A) */
    924     const char *adapterType = aAdapterNode.stringValue ("type");
    925 
    926     if (strcmp (adapterType, "Am79C970A") == 0)
    927         mData->mAdapterType = NetworkAdapterType_Am79C970A;
    928     else if (strcmp (adapterType, "Am79C973") == 0)
    929         mData->mAdapterType = NetworkAdapterType_Am79C973;
    930     else if (strcmp (adapterType, "82540EM") == 0)
    931         mData->mAdapterType = NetworkAdapterType_I82540EM;
    932     else if (strcmp (adapterType, "82543GC") == 0)
    933         mData->mAdapterType = NetworkAdapterType_I82543GC;
    934     else if (strcmp (adapterType, "82545EM") == 0)
    935         mData->mAdapterType = NetworkAdapterType_I82545EM;
    936     else
    937         ComAssertMsgFailedRet (("Invalid adapter type '%s'", adapterType),
    938                                E_FAIL);
    939 
    940     /* enabled (required) */
    941     mData->mEnabled = aAdapterNode.value <bool> ("enabled");
     919    mData->mAdapterType = data.type;
     920    mData->mEnabled = data.fEnabled;
    942921    /* MAC address (can be null) */
    943     rc = COMSETTER(MACAddress) (Bstr (aAdapterNode.stringValue ("MACAddress")));
     922    rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress));
    944923    CheckComRCReturnRC(rc);
    945924    /* cable (required) */
    946     mData->mCableConnected = aAdapterNode.value <bool> ("cable");
     925    mData->mCableConnected = data.fCableConnected;
    947926    /* line speed (defaults to 100 Mbps) */
    948     mData->mLineSpeed = aAdapterNode.value <ULONG> ("speed");
     927    mData->mLineSpeed = data.ulLineSpeed;
    949928    /* tracing (defaults to false) */
    950     mData->mTraceEnabled = aAdapterNode.value <bool> ("trace");
    951     mData->mTraceFile = aAdapterNode.stringValue ("tracefile");
    952 
    953     /* One of NAT, HostInerface, Internal or nothing */
    954     Key attachmentNode;
    955 
    956     if (!(attachmentNode = aAdapterNode.findKey ("NAT")).isNull())
    957     {
    958         /* NAT */
    959 
    960         /* optional */
    961         mData->mNATNetwork = attachmentNode.stringValue ("network");
    962 
    963         rc = AttachToNAT();
    964         CheckComRCReturnRC(rc);
    965     }
    966     else
    967     if (!(attachmentNode = aAdapterNode.findKey ("HostInterface")).isNull() /* backwards compatibility */
    968             || !(attachmentNode = aAdapterNode.findKey ("BridgedInterface")).isNull())
    969     {
    970         /* Host Interface Networking */
    971 
    972         Bstr name = attachmentNode.stringValue ("name");
    973         /* name can be empty, but not null */
    974         ComAssertRet (!name.isNull(), E_FAIL);
    975 
    976         rc = COMSETTER(HostInterface) (name);
    977         CheckComRCReturnRC(rc);
    978 
    979         rc = AttachToBridgedInterface();
    980         CheckComRCReturnRC(rc);
    981     }
    982     else
    983     if (!(attachmentNode = aAdapterNode.findKey ("InternalNetwork")).isNull())
    984     {
    985         /* Internal Networking */
    986 
    987         /* required */
    988         mData->mInternalNetwork = attachmentNode.stringValue ("name");
    989         Assert (!mData->mInternalNetwork.isNull());
    990 
    991         rc = AttachToInternalNetwork();
    992         CheckComRCReturnRC(rc);
    993     }
    994     else
    995     if (!(attachmentNode = aAdapterNode.findKey ("HostOnlyInterface")).isNull())
    996     {
     929    mData->mTraceEnabled = data.fTraceEnabled;
     930    mData->mTraceFile = data.strTraceFile;
     931
     932    switch (data.mode)
     933    {
     934        case NetworkAttachmentType_NAT:
     935            mData->mNATNetwork = data.strName;
     936            rc = AttachToNAT();
     937            CheckComRCReturnRC(rc);
     938        break;
     939
     940        case NetworkAttachmentType_Bridged:
     941            rc = COMSETTER(HostInterface)(Bstr(data.strName));
     942            CheckComRCReturnRC(rc);
     943            rc = AttachToBridgedInterface();
     944            CheckComRCReturnRC(rc);
     945        break;
     946
     947        case NetworkAttachmentType_Internal:
     948            mData->mInternalNetwork = data.strName;
     949            Assert(!mData->mInternalNetwork.isNull());
     950
     951            rc = AttachToInternalNetwork();
     952            CheckComRCReturnRC(rc);
     953        break;
     954
     955        case NetworkAttachmentType_HostOnly:
    997956#if defined(VBOX_WITH_NETFLT)
    998         Bstr name = attachmentNode.stringValue ("name");
    999         /* name can be empty, but not null */
    1000         ComAssertRet (!name.isNull(), E_FAIL);
    1001 
    1002         rc = COMSETTER(HostInterface) (name);
    1003         CheckComRCReturnRC(rc);
     957            rc = COMSETTER(HostInterface)(Bstr(data.strName));
     958            CheckComRCReturnRC(rc);
    1004959#endif
    1005 
    1006         /* Host Interface Networking */
    1007         rc = AttachToHostOnlyInterface();
    1008         CheckComRCReturnRC(rc);
    1009     }
    1010     else
    1011     {
    1012         /* Adapter has no children */
    1013         rc = Detach();
    1014         CheckComRCReturnRC(rc);
     960            rc = AttachToHostOnlyInterface();
     961            CheckComRCReturnRC(rc);
     962        break;
     963
     964        case NetworkAttachmentType_Null:
     965            rc = Detach();
     966            CheckComRCReturnRC(rc);
     967        break;
    1015968    }
    1016969
     
    1027980 *  @note Locks this object for reading.
    1028981 */
    1029 HRESULT NetworkAdapter::saveSettings (settings::Key &aAdapterNode)
    1030 {
    1031     using namespace settings;
    1032 
    1033     AssertReturn(!aAdapterNode.isNull(), E_FAIL);
    1034 
     982HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
     983{
    1035984    AutoCaller autoCaller(this);
    1036985    AssertComRCReturnRC(autoCaller.rc());
     
    1038987    AutoReadLock alock(this);
    1039988
    1040     aAdapterNode.setValue <bool> ("enabled", !!mData->mEnabled);
    1041     aAdapterNode.setValue <Bstr> ("MACAddress", mData->mMACAddress);
    1042     aAdapterNode.setValue <bool> ("cable", !!mData->mCableConnected);
    1043 
    1044     aAdapterNode.setValue <ULONG> ("speed", mData->mLineSpeed);
    1045 
    1046     if (mData->mTraceEnabled)
    1047         aAdapterNode.setValue <bool> ("trace", true);
    1048 
    1049     aAdapterNode.setValueOr <Bstr> ("tracefile", mData->mTraceFile, Bstr::Null);
    1050 
    1051     const char *typeStr = NULL;
    1052     switch (mData->mAdapterType)
    1053     {
    1054         case NetworkAdapterType_Am79C970A:
    1055             typeStr = "Am79C970A";
    1056             break;
    1057         case NetworkAdapterType_Am79C973:
    1058             typeStr = "Am79C973";
    1059             break;
    1060         case NetworkAdapterType_I82540EM:
    1061             typeStr = "82540EM";
    1062             break;
    1063         case NetworkAdapterType_I82543GC:
    1064             typeStr = "82543GC";
    1065             break;
    1066         case NetworkAdapterType_I82545EM:
    1067             typeStr = "82545EM";
    1068             break;
    1069         default:
    1070             ComAssertMsgFailedRet (("Invalid network adapter type: %d",
    1071                                     mData->mAdapterType),
    1072                                    E_FAIL);
    1073     }
    1074     aAdapterNode.setStringValue ("type", typeStr);
    1075 
    1076     switch (mData->mAttachmentType)
     989    data.fEnabled = !!mData->mEnabled;
     990    data.strMACAddress = mData->mMACAddress;
     991    data.fCableConnected = !!mData->mCableConnected;
     992
     993    data.ulLineSpeed = mData->mLineSpeed;
     994
     995    data.fTraceEnabled = mData->mTraceEnabled;
     996
     997    data.strTraceFile = mData->mTraceFile;
     998
     999    data.type = mData->mAdapterType;
     1000
     1001    switch (data.mode = mData->mAttachmentType)
    10771002    {
    10781003        case NetworkAttachmentType_Null:
    1079         {
    1080             /* do nothing -- empty content */
    1081             break;
    1082         }
     1004            data.strName.setNull();
     1005        break;
     1006
    10831007        case NetworkAttachmentType_NAT:
    1084         {
    1085             Key attachmentNode = aAdapterNode.createKey ("NAT");
    1086             if (!mData->mNATNetwork.isEmpty())
    1087                 attachmentNode.setValue <Bstr> ("network",
    1088                                                 mData->mNATNetwork);
    1089             break;
    1090         }
     1008            data.strName = mData->mNATNetwork;
     1009        break;
     1010
    10911011        case NetworkAttachmentType_Bridged:
    1092         {
    1093             Key attachmentNode = aAdapterNode.createKey ("BridgedInterface");
    1094             Assert (!mData->mHostInterface.isNull());
    1095             attachmentNode.setValue <Bstr> ("name", mData->mHostInterface);
    1096             break;
    1097         }
     1012            data.strName = mData->mHostInterface;
     1013        break;
     1014
    10981015        case NetworkAttachmentType_Internal:
    1099         {
    1100             Key attachmentNode = aAdapterNode.createKey ("InternalNetwork");
    1101             Assert (!mData->mInternalNetwork.isEmpty());
    1102             attachmentNode.setValue <Bstr> ("name", mData->mInternalNetwork);
    1103             break;
    1104         }
     1016            data.strName = mData->mInternalNetwork;
     1017        break;
     1018
    11051019        case NetworkAttachmentType_HostOnly:
    1106         {
    1107             Key attachmentNode = aAdapterNode.createKey ("HostOnlyInterface");
    1108 #if defined(VBOX_WITH_NETFLT)
    1109             Assert (!mData->mHostInterface.isNull());
    1110             attachmentNode.setValue <Bstr> ("name", mData->mHostInterface);
    1111 #endif
    1112             break;
    1113         }
    1114         default:
    1115         {
    1116             ComAssertFailedRet (E_FAIL);
    1117         }
     1020            data.strName = mData->mHostInterface;
     1021        break;
    11181022    }
    11191023
  • trunk/src/VBox/Main/ParallelPortImpl.cpp

    r21878 r22173  
    174174 *  @note Locks this object for writing.
    175175 */
    176 HRESULT ParallelPort::loadSettings (const settings::Key &aPortNode)
    177 {
    178     using namespace settings;
    179 
    180     AssertReturn(!aPortNode.isNull(), E_FAIL);
    181 
     176HRESULT ParallelPort::loadSettings(const settings::ParallelPort &data)
     177{
    182178    AutoCaller autoCaller(this);
    183179    AssertComRCReturnRC(autoCaller.rc());
     
    197193
    198194    /* enabled (required) */
    199     mData->mEnabled = aPortNode.value <bool> ("enabled");
     195    mData->mEnabled = data.fEnabled;
    200196    /* I/O base (required) */
    201     mData->mIOBase = aPortNode.value <ULONG> ("IOBase");
     197    mData->mIOBase = data.ulIOBase;
    202198    /* IRQ (required) */
    203     mData->mIRQ = aPortNode.value <ULONG> ("IRQ");
     199    mData->mIRQ = data.ulIRQ;
    204200    /* device path (optional, defaults to null) */
    205     Bstr path = aPortNode.stringValue ("path");
    206 
     201    Bstr path(data.strPath);
    207202    HRESULT rc = checkSetPath (path);
    208203    CheckComRCReturnRC(rc);
     
    221216 *  @note Locks this object for reading.
    222217 */
    223 HRESULT ParallelPort::saveSettings (settings::Key &aPortNode)
    224 {
    225     using namespace settings;
    226 
    227     AssertReturn(!aPortNode.isNull(), E_FAIL);
    228 
     218HRESULT ParallelPort::saveSettings(settings::ParallelPort &data)
     219{
    229220    AutoCaller autoCaller(this);
    230221    AssertComRCReturnRC(autoCaller.rc());
     
    232223    AutoReadLock alock(this);
    233224
    234     aPortNode.setValue <bool> ("enabled", !!mData->mEnabled);
    235     aPortNode.setValue <ULONG> ("IOBase", mData->mIOBase, 16);
    236     aPortNode.setValue <ULONG> ("IRQ", mData->mIRQ);
    237 
    238     /* 'path' is optional in XML */
    239     if (!mData->mPath.isEmpty())
    240         aPortNode.setValue <Bstr> ("path", mData->mPath);
     225    data.fEnabled = !!mData->mEnabled;
     226    data.ulIOBase = mData->mIOBase;
     227    data.ulIRQ = mData->mIRQ;
     228    data.strPath = mData->mPath;
    241229
    242230    return S_OK;
  • trunk/src/VBox/Main/Performance.cpp

    r21878 r22173  
    477477        {
    478478            for (size_t i = 0; i < nameArray.size(); ++i)
    479                 processMetricList(std::string(com::Utf8Str(nameArray[i])), ComPtr<IUnknown>());
     479                processMetricList(com::Utf8Str(nameArray[i]), ComPtr<IUnknown>());
    480480        }
    481481        else
    482             processMetricList(std::string("*"), ComPtr<IUnknown>());
     482            processMetricList("*", ComPtr<IUnknown>());
    483483    }
    484484    else
     
    488488            {
    489489                case 0:
    490                     processMetricList(std::string("*"), objectArray[i]);
     490                    processMetricList("*", objectArray[i]);
    491491                    break;
    492492                case 1:
    493                     processMetricList(std::string(com::Utf8Str(nameArray[0])), objectArray[i]);
     493                    processMetricList(com::Utf8Str(nameArray[0]), objectArray[i]);
    494494                    break;
    495495                default:
    496                     processMetricList(std::string(com::Utf8Str(nameArray[i])), objectArray[i]);
     496                    processMetricList(com::Utf8Str(nameArray[i]), objectArray[i]);
    497497                    break;
    498498            }
     
    500500}
    501501
    502 void Filter::processMetricList(const std::string &name, const ComPtr<IUnknown> object)
    503 {
    504     std::string::size_type startPos = 0;
    505 
    506     for (std::string::size_type pos = name.find(",");
     502void Filter::processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object)
     503{
     504    size_t startPos = 0;
     505
     506    for (size_t pos = name.find(",");
    507507         pos != std::string::npos;
    508508         pos = name.find(",", startPos))
    509509    {
    510         mElements.push_back(std::make_pair(object, name.substr(startPos, pos - startPos)));
     510        mElements.push_back(std::make_pair(object, std::string(name.substr(startPos, pos - startPos).c_str())));
    511511        startPos = pos + 1;
    512512    }
    513     mElements.push_back(std::make_pair(object, name.substr(startPos)));
     513    mElements.push_back(std::make_pair(object, std::string(name.substr(startPos).c_str())));
    514514}
    515515
  • trunk/src/VBox/Main/SerialPortImpl.cpp

    r21878 r22173  
    175175 *  @note Locks this object for writing.
    176176 */
    177 HRESULT SerialPort::loadSettings (const settings::Key &aPortNode)
    178 {
    179     using namespace settings;
    180 
    181     AssertReturn(!aPortNode.isNull(), E_FAIL);
    182 
     177HRESULT SerialPort::loadSettings(const settings::SerialPort &data)
     178{
    183179    AutoCaller autoCaller(this);
    184180    AssertComRCReturnRC(autoCaller.rc());
     
    198194
    199195    /* enabled (required) */
    200     mData->mEnabled = aPortNode.value <bool> ("enabled");
     196    mData->mEnabled = data.fEnabled;
    201197    /* I/O base (required) */
    202     mData->mIOBase = aPortNode.value <ULONG> ("IOBase");
     198    mData->mIOBase = data.ulIOBase;
    203199    /* IRQ (required) */
    204     mData->mIRQ = aPortNode.value <ULONG> ("IRQ");
     200    mData->mIRQ = data.ulIRQ;
    205201    /* host mode (required) */
    206     const char *mode = aPortNode.stringValue ("hostMode");
    207     if (strcmp (mode, "RawFile") == 0)
    208         mData->mHostMode = PortMode_RawFile;
    209     else if (strcmp (mode, "HostPipe") == 0)
    210         mData->mHostMode = PortMode_HostPipe;
    211     else if (strcmp (mode, "HostDevice") == 0)
    212         mData->mHostMode = PortMode_HostDevice;
    213     else if (strcmp (mode, "Disconnected") == 0)
    214         mData->mHostMode = PortMode_Disconnected;
    215     else
    216         ComAssertMsgFailedRet (("Invalid port mode '%s'", mode), E_FAIL);
     202    mData->mHostMode = data.portMode;
    217203
    218204    /* pipe/device path (optional, defaults to null) */
    219     Bstr path = aPortNode.stringValue ("path");
    220     HRESULT rc = checkSetPath (path);
     205    Bstr path(data.strPath);
     206    HRESULT rc = checkSetPath(path);
    221207    CheckComRCReturnRC(rc);
    222208    mData->mPath = path;
    223209
    224210    /* server mode (optional, defaults to false) */
    225     mData->mServer = aPortNode.value <bool> ("server");
     211    mData->mServer = data.fServer;
    226212
    227213    return S_OK;
     
    237223 *  @note Locks this object for reading.
    238224 */
    239 HRESULT SerialPort::saveSettings (settings::Key &aPortNode)
    240 {
    241     using namespace settings;
    242 
    243     AssertReturn(!aPortNode.isNull(), E_FAIL);
    244 
     225HRESULT SerialPort::saveSettings(settings::SerialPort &data)
     226{
    245227    AutoCaller autoCaller(this);
    246228    AssertComRCReturnRC(autoCaller.rc());
     
    248230    AutoReadLock alock(this);
    249231
    250     aPortNode.setValue <bool> ("enabled", !!mData->mEnabled);
    251     aPortNode.setValue <ULONG> ("IOBase", mData->mIOBase, 16);
    252     aPortNode.setValue <ULONG> ("IRQ", mData->mIRQ);
    253 
    254     const char *mode = NULL;
    255     switch (mData->mHostMode)
    256     {
    257         case PortMode_Disconnected:
    258             mode = "Disconnected";
    259             break;
    260         case PortMode_HostPipe:
    261             mode = "HostPipe";
    262             break;
    263         case PortMode_HostDevice:
    264             mode = "HostDevice";
    265             break;
    266         case PortMode_RawFile:
    267             mode = "RawFile";
    268             break;
    269         default:
    270             ComAssertMsgFailedRet (("Invalid serial port mode: %d",
    271                                     mData->mHostMode),
    272                                    E_FAIL);
    273     }
    274     aPortNode.setStringValue ("hostMode", mode);
     232    data.fEnabled = !!mData->mEnabled;
     233    data.ulIOBase = mData->mIOBase;
     234    data.ulIRQ = mData->mIRQ;
     235    data.portMode = mData->mHostMode;
    275236
    276237    /* Always save non-null mPath and mServer to preserve the user values for
    277238     * later use. Note that 'server' is false by default in XML so we don't
    278239     * save it when it's false. */
    279     if (!mData->mPath.isEmpty())
    280         aPortNode.setValue <Bstr> ("path", mData->mPath);
    281     if (mData->mServer)
    282         aPortNode.setValue <bool> ("server", !!mData->mServer);
     240    data.strPath = mData->mPath;
     241    data.fServer = !!mData->mServer;
    283242
    284243    return S_OK;
  • trunk/src/VBox/Main/SharedFolderImpl.cpp

    r21878 r22173  
    207207    /* Check whether the path is full (absolute) */
    208208    char hostPathFull [RTPATH_MAX];
    209     int vrc = RTPathAbsEx (NULL, hostPath,
    210                            hostPathFull, sizeof (hostPathFull));
     209    int vrc = RTPathAbsEx(NULL,
     210                          hostPath.c_str(),
     211                          hostPathFull,
     212                          sizeof (hostPathFull));
    211213    if (RT_FAILURE(vrc))
    212214        return setError (E_INVALIDARG,
    213215            tr ("Invalid shared folder path: '%s' (%Rrc)"), hostPath.raw(), vrc);
    214216
    215     if (RTPathCompare (hostPath, hostPathFull) != 0)
     217    if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0)
    216218        return setError (E_INVALIDARG,
    217219            tr ("Shared folder path '%s' is not absolute"), hostPath.raw());
     
    291293
    292294    /* check whether the host path exists */
    293     Utf8Str hostPath = Utf8Str (m.hostPath);
    294     char hostPathFull [RTPATH_MAX];
    295     int vrc = RTPathExists (hostPath) ? RTPathReal (hostPath, hostPathFull,
    296                                                     sizeof (hostPathFull))
     295    Utf8Str hostPath = Utf8Str(m.hostPath);
     296    char hostPathFull[RTPATH_MAX];
     297    int vrc = RTPathExists(hostPath.c_str()) ? RTPathReal(hostPath.c_str(),
     298                                                          hostPathFull,
     299                                                          sizeof(hostPathFull))
    297300                                      : VERR_PATH_NOT_FOUND;
    298301    if (RT_SUCCESS(vrc))
  • trunk/src/VBox/Main/SnapshotImpl.cpp

    r21878 r22173  
    4848    {}
    4949
    50     Guid                        id;
    51     Bstr                        name;
    52     Bstr                        description;
     50    Guid                        uuid;
     51    Utf8Str                     strName;
     52    Utf8Str                     strDescription;
    5353    RTTIMESPEC                  timeStamp;
    5454    ComObjPtr<SnapshotMachine>  pMachine;
     
    8484HRESULT Snapshot::init(VirtualBox *aVirtualBox,
    8585                       const Guid &aId,
    86                        IN_BSTR aName,
    87                        IN_BSTR aDescription,
    88                        RTTIMESPEC aTimeStamp,
     86                       const Utf8Str &aName,
     87                       const Utf8Str &aDescription,
     88                       const RTTIMESPEC &aTimeStamp,
    8989                       SnapshotMachine *aMachine,
    9090                       Snapshot *aParent)
    9191{
    92     LogFlowMember (("Snapshot::init(aParent=%p)\n", aParent));
    93 
    94     ComAssertRet (!aId.isEmpty() && aName && aMachine, E_INVALIDARG);
     92    LogFlowMember(("Snapshot::init(uuid: %s, aParent->uuid=%s)\n", aId.toString().c_str(), (aParent) ? aParent->m->uuid.toString().c_str() : ""));
     93
     94    ComAssertRet (!aId.isEmpty() && !aName.isEmpty() && aMachine, E_INVALIDARG);
    9595
    9696    /* Enclose the state transition NotReady->InInit->Ready */
     
    105105    mParent = aParent;
    106106
    107     m->id = aId;
    108     m->name = aName;
    109     m->description = aDescription;
     107    m->uuid = aId;
     108    m->strName = aName;
     109    m->strDescription = aDescription;
    110110    m->timeStamp = aTimeStamp;
    111111    m->pMachine = aMachine;
     
    253253    AutoReadLock alock(this);
    254254
    255     m->id.toUtf16().cloneTo(aId);
     255    m->uuid.toUtf16().cloneTo(aId);
    256256    return S_OK;
    257257}
     
    266266    AutoReadLock alock(this);
    267267
    268     m->name.cloneTo(aName);
     268    m->strName.cloneTo(aName);
    269269    return S_OK;
    270270}
     
    274274 *  (see its lock requirements).
    275275 */
    276 STDMETHODIMP Snapshot::COMSETTER(Name) (IN_BSTR aName)
     276STDMETHODIMP Snapshot::COMSETTER(Name)(IN_BSTR aName)
    277277{
    278278    CheckComArgNotNull(aName);
     
    281281    CheckComRCReturnRC(autoCaller.rc());
    282282
     283    Utf8Str strName(aName);
     284
    283285    AutoWriteLock alock(this);
    284286
    285     if (m->name != aName)
    286     {
    287         m->name = aName;
     287    if (m->strName != strName)
     288    {
     289        m->strName = strName;
    288290
    289291        alock.leave(); /* Important! (child->parent locks are forbidden) */
     
    304306    AutoReadLock alock(this);
    305307
    306     m->description.cloneTo(aDescription);
     308    m->strDescription.cloneTo(aDescription);
    307309    return S_OK;
    308310}
     
    315317    CheckComRCReturnRC(autoCaller.rc());
    316318
     319    Utf8Str strDescription(aDescription);
     320
    317321    AutoWriteLock alock(this);
    318322
    319     if (m->description != aDescription)
    320     {
    321         m->description = aDescription;
     323    if (m->strDescription != strDescription)
     324    {
     325        m->strDescription = strDescription;
    322326
    323327        alock.leave(); /* Important! (child->parent locks are forbidden) */
     
    475479Guid Snapshot::getId() const
    476480{
    477     return m->id;
     481    return m->uuid;
    478482}
    479483
     
    483487 * @return
    484488 */
    485 Bstr Snapshot::getName() const
    486 {
    487     return m->name;
     489const Utf8Str& Snapshot::getName() const
     490{
     491    return m->strName;
    488492}
    489493
     
    512516    AutoReadLock alock(this);
    513517
    514     if (m->id == aId)
     518    if (m->uuid == aId)
    515519        child = this;
    516520    else
     
    535539 *  Caller must hold the snapshots tree lock!
    536540 */
    537 ComObjPtr<Snapshot> Snapshot::findChildOrSelf(IN_BSTR aName)
     541ComObjPtr<Snapshot> Snapshot::findChildOrSelf(const Utf8Str &aName)
    538542{
    539543    ComObjPtr<Snapshot> child;
    540     AssertReturn(aName, child);
     544    AssertReturn(!aName.isEmpty(), child);
    541545
    542546    AutoCaller autoCaller(this);
    543547    AssertComRC(autoCaller.rc());
    544548
    545     AutoReadLock alock(this);
    546 
    547     if (m->name == aName)
     549    AutoReadLock alock (this);
     550
     551    if (m->strName == aName)
    548552        child = this;
    549553    else
     
    572576
    573577    Utf8Str path = m->pMachine->mSSData->mStateFilePath;
    574     LogFlowThisFunc(("Snap[%ls].statePath={%s}\n", m->name.raw(), path.raw()));
     578    LogFlowThisFunc(("Snap[%s].statePath={%s}\n", m->strName.raw(), path.raw()));
    575579
    576580    /* state file may be NULL (for offline snapshots) */
    577581    if (    path.length()
    578          && RTPathStartsWith(path, aOldPath)
     582         && RTPathStartsWith(path.c_str(), aOldPath)
    579583       )
    580584    {
     
    625629 * @return
    626630 */
    627 HRESULT Snapshot::saveSnapshotImpl(settings::Key &aNode, bool aAttrsOnly)
    628 {
    629     using namespace settings;
    630 
    631     AutoReadLock alock(this);
    632 
    633     /* uuid (required) */
    634     if (!aAttrsOnly)
    635         aNode.setValue<Guid>("uuid", m->id);
    636 
    637     /* name (required) */
    638     aNode.setValue<Bstr>("name", m->name);
    639 
    640     /* timeStamp (required) */
    641     aNode.setValue<RTTIMESPEC>("timeStamp", m->timeStamp);
    642 
    643     /* Description node (optional) */
    644     if (!m->description.isNull())
    645     {
    646         Key descNode = aNode.createKey("Description");
    647         descNode.setKeyValue<Bstr>(m->description);
    648     }
    649     else
    650     {
    651         Key descNode = aNode.findKey ("Description");
    652         if (!descNode.isNull())
    653             descNode.zap();
    654     }
     631HRESULT Snapshot::saveSnapshotImpl(settings::Snapshot &data, bool aAttrsOnly)
     632{
     633    AutoReadLock alock(this);
     634
     635    data.uuid = m->uuid;
     636    data.strName = m->strName;
     637    data.timestamp = m->timeStamp;
     638    data.strDescription = m->strDescription;
    655639
    656640    if (aAttrsOnly)
     
    663647        Utf8Str strStateFilePath = stateFilePath();
    664648        m->pMachine->calculateRelativePath(strStateFilePath, strStateFilePath);
    665         aNode.setStringValue ("stateFile", strStateFilePath);
    666     }
    667 
    668     {
    669         ComObjPtr<SnapshotMachine> snapshotMachine = m->pMachine;
    670 
    671         /* save hardware */
    672         {
    673             Key hwNode = aNode.createKey ("Hardware");
    674             HRESULT rc = snapshotMachine->saveHardware(hwNode);
    675             CheckComRCReturnRC(rc);
    676         }
    677 
    678         /* save hard disks. */
    679         {
    680             Key storageNode = aNode.createKey ("StorageControllers");
    681             HRESULT rc = snapshotMachine->saveStorageControllers(storageNode);
    682             CheckComRCReturnRC(rc);
    683         }
    684     }
     649        data.strStateFile = strStateFilePath;
     650    }
     651    else
     652        data.strStateFile.setNull();
     653
     654    HRESULT rc = m->pMachine->saveHardware(data.hardware);
     655    CheckComRCReturnRC (rc);
     656
     657    rc = m->pMachine->saveStorageControllers(data.storage);
     658    CheckComRCReturnRC (rc);
    685659
    686660    alock.unlock();
    687661
     662    data.llChildSnapshots.clear();
     663
    688664    if (m->llChildren.size())
    689665    {
    690         Key snapshotsNode = aNode.createKey ("Snapshots");
    691 
    692         HRESULT rc = S_OK;
    693 
    694666        for (SnapshotsList::const_iterator it = m->llChildren.begin();
    695667             it != m->llChildren.end();
    696668             ++it)
    697669        {
    698             Key snapshotNode = snapshotsNode.createKey("Snapshot");
    699             rc = (*it)->saveSnapshotImpl(snapshotNode, aAttrsOnly);
    700             CheckComRCReturnRC(rc);
     670            settings::Snapshot snap;
     671            rc = (*it)->saveSnapshotImpl(snap, aAttrsOnly);
     672            CheckComRCReturnRC (rc);
     673
     674            data.llChildSnapshots.push_back(snap);
    701675        }
    702676    }
     
    713687 *  @param aAttrsOnly   If true, only updatge user-changeable attrs.
    714688 */
    715 HRESULT Snapshot::saveSnapshot(settings::Key &aNode, bool aAttrsOnly)
    716 {
    717     AssertReturn(!aNode.isNull(), E_INVALIDARG);
    718 
     689HRESULT Snapshot::saveSnapshot(settings::Snapshot &data, bool aAttrsOnly)
     690{
    719691    AutoWriteLock listLock(m->pMachine->snapshotsTreeLockHandle());
    720692
    721     return saveSnapshotImpl(aNode, aAttrsOnly);
    722 }
    723 
     693    return saveSnapshotImpl(data, aAttrsOnly);
     694}
     695
  • trunk/src/VBox/Main/StorageControllerImpl.cpp

    r21878 r22173  
    6363 * @param aName         Name of the storage controller.
    6464 */
    65 HRESULT StorageController::init (Machine *aParent, IN_BSTR aName,
    66                                  StorageBus_T aStorageBus)
    67 {
    68     LogFlowThisFunc(("aParent=%p aName=\"%ls\"\n", aParent, aName));
    69 
    70     ComAssertRet (aParent && aName, E_INVALIDARG);
     65HRESULT StorageController::init(Machine *aParent,
     66                                const Utf8Str &aName,
     67                                StorageBus_T aStorageBus)
     68{
     69    LogFlowThisFunc(("aParent=%p aName=\"%s\"\n", aParent, aName.raw()));
     70
     71    ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
    7172    if (   (aStorageBus <= StorageBus_Null)
    7273        || (aStorageBus >  StorageBus_SCSI))
     
    8788    mData.allocate();
    8889
    89     mData->mName = aName;
     90    mData->strName = aName;
    9091    mData->mStorageBus = aStorageBus;
    9192
     
    237238
    238239    /* mName is constant during life time, no need to lock */
    239     mData.data()->mName.cloneTo(aName);
     240    mData.data()->strName.cloneTo(aName);
    240241
    241242    return S_OK;
     
    461462        {
    462463            /*
    463              * The port count is fixed to 2. 
     464             * The port count is fixed to 2.
    464465             */
    465466            if (aPortCount != 2)
  • trunk/src/VBox/Main/SystemPropertiesImpl.cpp

    r21878 r22173  
    7777    unconst(mParent) = aParent;
    7878
    79     setDefaultMachineFolder (NULL);
    80     setDefaultHardDiskFolder (NULL);
    81     setDefaultHardDiskFormat (NULL);
    82 
    83     setRemoteDisplayAuthLibrary (NULL);
     79    setDefaultMachineFolder(Utf8Str::Null);
     80    setDefaultHardDiskFolder(Utf8Str::Null);
     81    setDefaultHardDiskFormat(Utf8Str::Null);
     82
     83    setRemoteDisplayAuthLibrary(Utf8Str::Null);
    8484
    8585    mLogHistoryCount = 3;
     
    362362    AutoReadLock alock(this);
    363363
    364     mDefaultMachineFolderFull.cloneTo(aDefaultMachineFolder);
     364    m_strDefaultMachineFolderFull.cloneTo(aDefaultMachineFolder);
    365365
    366366    return S_OK;
     
    391391    AutoReadLock alock(this);
    392392
    393     mDefaultHardDiskFolderFull.cloneTo(aDefaultHardDiskFolder);
     393    m_strDefaultHardDiskFolderFull.cloneTo(aDefaultHardDiskFolder);
    394394
    395395    return S_OK;
     
    437437    AutoReadLock alock(this);
    438438
    439     mDefaultHardDiskFormat.cloneTo(aDefaultHardDiskFormat);
     439    m_strDefaultHardDiskFormat.cloneTo(aDefaultHardDiskFormat);
    440440
    441441    return S_OK;
     
    466466    AutoReadLock alock(this);
    467467
    468     mRemoteDisplayAuthLibrary.cloneTo(aRemoteDisplayAuthLibrary);
     468    m_strRemoteDisplayAuthLibrary.cloneTo(aRemoteDisplayAuthLibrary);
    469469
    470470    return S_OK;
     
    495495    AutoReadLock alock(this);
    496496
    497     mWebServiceAuthLibrary.cloneTo(aWebServiceAuthLibrary);
     497    m_strWebServiceAuthLibrary.cloneTo(aWebServiceAuthLibrary);
    498498
    499499    return S_OK;
     
    563563/////////////////////////////////////////////////////////////////////////////
    564564
    565 HRESULT SystemProperties::loadSettings (const settings::Key &aGlobal)
    566 {
    567     using namespace settings;
    568 
     565HRESULT SystemProperties::loadSettings(const settings::SystemProperties &data)
     566{
    569567    AutoCaller autoCaller(this);
    570568    CheckComRCReturnRC(autoCaller.rc());
     
    572570    AutoWriteLock alock(this);
    573571
    574     AssertReturn(!aGlobal.isNull(), E_FAIL);
    575 
    576572    HRESULT rc = S_OK;
    577573
    578     Key properties = aGlobal.key ("SystemProperties");
    579 
    580     Bstr bstr;
    581 
    582     bstr = properties.stringValue ("defaultMachineFolder");
    583     rc = setDefaultMachineFolder (bstr);
     574    rc = setDefaultMachineFolder(data.strDefaultMachineFolder);
    584575    CheckComRCReturnRC(rc);
    585576
    586     bstr = properties.stringValue ("defaultHardDiskFolder");
    587     rc = setDefaultHardDiskFolder (bstr);
     577    rc = setDefaultHardDiskFolder(data.strDefaultHardDiskFolder);
    588578    CheckComRCReturnRC(rc);
    589579
    590     bstr = properties.stringValue ("defaultHardDiskFormat");
    591     rc = setDefaultHardDiskFormat (bstr);
     580    rc = setDefaultHardDiskFormat(data.strDefaultHardDiskFormat);
    592581    CheckComRCReturnRC(rc);
    593582
    594     bstr = properties.stringValue ("remoteDisplayAuthLibrary");
    595     rc = setRemoteDisplayAuthLibrary (bstr);
     583    rc = setRemoteDisplayAuthLibrary(data.strRemoteDisplayAuthLibrary);
    596584    CheckComRCReturnRC(rc);
    597585
    598     bstr = properties.stringValue ("webServiceAuthLibrary");
    599     rc = setWebServiceAuthLibrary (bstr);
     586    rc = setWebServiceAuthLibrary(data.strWebServiceAuthLibrary);
    600587    CheckComRCReturnRC(rc);
    601588
    602     mLogHistoryCount = properties.valueOr <ULONG> ("LogHistoryCount", 3);
    603 
    604     return S_OK;
    605 }
    606 
    607 HRESULT SystemProperties::saveSettings (settings::Key &aGlobal)
    608 {
    609     using namespace settings;
    610 
    611     AutoCaller autoCaller(this);
    612     CheckComRCReturnRC(autoCaller.rc());
    613 
    614     AutoReadLock alock(this);
    615 
    616     ComAssertRet (!aGlobal.isNull(), E_FAIL);
    617 
    618     /* first, delete the entry */
    619     Key properties = aGlobal.findKey ("SystemProperties");
    620     if (!properties.isNull())
    621         properties.zap();
    622     /* then, recreate it */
    623     properties = aGlobal.createKey ("SystemProperties");
    624 
    625     if (mDefaultMachineFolder)
    626         properties.setValue <Bstr> ("defaultMachineFolder", mDefaultMachineFolder);
    627 
    628     if (mDefaultHardDiskFolder)
    629         properties.setValue <Bstr> ("defaultHardDiskFolder", mDefaultHardDiskFolder);
    630 
    631     if (mDefaultHardDiskFormat)
    632         properties.setValue <Bstr> ("defaultHardDiskFormat", mDefaultHardDiskFormat);
    633 
    634     if (mRemoteDisplayAuthLibrary)
    635         properties.setValue <Bstr> ("remoteDisplayAuthLibrary", mRemoteDisplayAuthLibrary);
    636 
    637     if (mWebServiceAuthLibrary)
    638         properties.setValue <Bstr> ("webServiceAuthLibrary", mWebServiceAuthLibrary);
    639 
    640     properties.setValue <ULONG> ("LogHistoryCount", mLogHistoryCount);
     589    mLogHistoryCount = data.ulLogHistoryCount;
     590
     591    return S_OK;
     592}
     593
     594HRESULT SystemProperties::saveSettings(settings::SystemProperties &data)
     595{
     596    AutoCaller autoCaller(this);
     597    CheckComRCReturnRC(autoCaller.rc());
     598
     599    AutoReadLock alock(this);
     600
     601    data.strDefaultMachineFolder = m_strDefaultMachineFolder;
     602    data.strDefaultHardDiskFolder = m_strDefaultHardDiskFolder;
     603    data.strDefaultHardDiskFormat = m_strDefaultHardDiskFormat;
     604    data.strRemoteDisplayAuthLibrary = m_strRemoteDisplayAuthLibrary;
     605    data.strWebServiceAuthLibrary = m_strWebServiceAuthLibrary;
     606    data.ulLogHistoryCount = mLogHistoryCount;
    641607
    642608    return S_OK;
     
    678644/////////////////////////////////////////////////////////////////////////////
    679645
    680 HRESULT SystemProperties::setDefaultMachineFolder (CBSTR aPath)
    681 {
    682     Utf8Str path;
    683     if (aPath && *aPath)
    684         path = aPath;
    685     else
     646HRESULT SystemProperties::setDefaultMachineFolder(const Utf8Str &aPath)
     647{
     648    Utf8Str path(aPath);
     649    if (path.isEmpty())
    686650        path = "Machines";
    687651
    688652    /* get the full file name */
    689653    Utf8Str folder;
    690     int vrc = mParent->calculateFullPath (path, folder);
     654    int vrc = mParent->calculateFullPath(path, folder);
    691655    if (RT_FAILURE(vrc))
    692         return setError (E_FAIL,
    693             tr ("Invalid default machine folder '%ls' (%Rrc)"),
    694             path.raw(), vrc);
    695 
    696     mDefaultMachineFolder = path;
    697     mDefaultMachineFolderFull = folder;
    698 
    699     return S_OK;
    700 }
    701 
    702 HRESULT SystemProperties::setDefaultHardDiskFolder (CBSTR aPath)
    703 {
    704     Utf8Str path;
    705     if (aPath && *aPath)
    706         path = aPath;
    707     else
     656        return setError(E_FAIL,
     657                        tr("Invalid default machine folder '%s' (%Rrc)"),
     658                        path.raw(),
     659                        vrc);
     660
     661    m_strDefaultMachineFolder = path;
     662    m_strDefaultMachineFolderFull = folder;
     663
     664    return S_OK;
     665}
     666
     667HRESULT SystemProperties::setDefaultHardDiskFolder(const Utf8Str &aPath)
     668{
     669    Utf8Str path(aPath);
     670    if (path.isEmpty())
    708671        path = "HardDisks";
    709672
    710673    /* get the full file name */
    711674    Utf8Str folder;
    712     int vrc = mParent->calculateFullPath (path, folder);
     675    int vrc = mParent->calculateFullPath(path, folder);
    713676    if (RT_FAILURE(vrc))
    714         return setError (E_FAIL,
    715             tr ("Invalid default hard disk folder '%ls' (%Rrc)"),
    716             path.raw(), vrc);
    717 
    718     mDefaultHardDiskFolder = path;
    719     mDefaultHardDiskFolderFull = folder;
    720 
    721     return S_OK;
    722 }
    723 
    724 HRESULT SystemProperties::setDefaultHardDiskFormat (CBSTR aFormat)
    725 {
    726     if (aFormat && *aFormat)
    727         mDefaultHardDiskFormat = aFormat;
     677        return setError(E_FAIL,
     678                        tr("Invalid default hard disk folder '%s' (%Rrc)"),
     679                        path.raw(),
     680                        vrc);
     681
     682    m_strDefaultHardDiskFolder = path;
     683    m_strDefaultHardDiskFolderFull = folder;
     684
     685    return S_OK;
     686}
     687
     688HRESULT SystemProperties::setDefaultHardDiskFormat(const Utf8Str &aFormat)
     689{
     690    if (!aFormat.isEmpty())
     691        m_strDefaultHardDiskFormat = aFormat;
    728692    else
    729         mDefaultHardDiskFormat = "VDI";
    730 
    731     return S_OK;
    732 }
    733 
    734 HRESULT SystemProperties::setRemoteDisplayAuthLibrary (CBSTR aPath)
    735 {
    736     if (aPath && *aPath)
    737         mRemoteDisplayAuthLibrary = aPath;
     693        m_strDefaultHardDiskFormat = "VDI";
     694
     695    return S_OK;
     696}
     697
     698HRESULT SystemProperties::setRemoteDisplayAuthLibrary(const Utf8Str &aPath)
     699{
     700    if (!aPath.isEmpty())
     701        m_strRemoteDisplayAuthLibrary = aPath;
    738702    else
    739         mRemoteDisplayAuthLibrary = "VRDPAuth";
    740 
    741     return S_OK;
    742 }
    743 
    744 HRESULT SystemProperties::setWebServiceAuthLibrary (CBSTR aPath)
    745 {
    746     if (aPath && *aPath)
    747         mWebServiceAuthLibrary = aPath;
     703        m_strRemoteDisplayAuthLibrary = "VRDPAuth";
     704
     705    return S_OK;
     706}
     707
     708HRESULT SystemProperties::setWebServiceAuthLibrary(const Utf8Str &aPath)
     709{
     710    if (!aPath.isEmpty())
     711        m_strWebServiceAuthLibrary = aPath;
    748712    else
    749         mWebServiceAuthLibrary = "VRDPAuth";
    750 
    751     return S_OK;
    752 }
    753 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
     713        m_strWebServiceAuthLibrary = "VRDPAuth";
     714
     715    return S_OK;
     716}
     717
  • trunk/src/VBox/Main/USBControllerImpl.cpp

    r21878 r22173  
    559559 *  @note Locks this object for writing.
    560560 */
    561 HRESULT USBController::loadSettings (const settings::Key &aMachineNode)
    562 {
    563     using namespace settings;
    564 
    565     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    566 
     561HRESULT USBController::loadSettings(const settings::USBController &data)
     562{
    567563    AutoCaller autoCaller(this);
    568564    AssertComRCReturnRC(autoCaller.rc());
     
    581577     * default to B. */
    582578
    583     /* USB Controller node (required) */
    584     Key controller = aMachineNode.key ("USBController");
    585 
    586     /* enabled (required) */
    587     mData->mEnabled = controller.value <bool> ("enabled");
    588 
    589     /* enabledEhci (optiona, defaults to false) */
    590     mData->mEnabledEhci = controller.value <bool> ("enabledEhci");
    591 
    592 #ifdef VBOX_WITH_USB
    593     HRESULT rc = S_OK;
    594 
    595     Key::List children = controller.keys ("DeviceFilter");
    596     for (Key::List::const_iterator it = children.begin();
    597          it != children.end(); ++ it)
    598     {
    599         /* required */
    600         Bstr name = (*it).stringValue ("name");
    601         bool active = (*it).value <bool> ("active");
    602 
    603         /* optional */
    604         Bstr vendorId = (*it).stringValue ("vendorId");
    605         Bstr productId = (*it).stringValue ("productId");
    606         Bstr revision = (*it).stringValue ("revision");
    607         Bstr manufacturer = (*it).stringValue ("manufacturer");
    608         Bstr product = (*it).stringValue ("product");
    609         Bstr serialNumber = (*it).stringValue ("serialNumber");
    610         Bstr port = (*it).stringValue ("port");
    611         Bstr remote = (*it).stringValue ("remote");
    612         ULONG maskedIfs = (*it).value <ULONG> ("maskedInterfaces");
    613 
    614         ComObjPtr<USBDeviceFilter> filterObj;
    615         filterObj.createObject();
    616         rc = filterObj->init (this,
    617                               name, active, vendorId, productId, revision,
    618                               manufacturer, product, serialNumber,
    619                               port, remote, maskedIfs);
    620         /* error info is set by init() when appropriate */
     579    mData->mEnabled = data.fEnabled;
     580    mData->mEnabledEhci = data.fEnabledEHCI;
     581
     582#ifdef VBOX_WITH_USB
     583    for (settings::USBDeviceFiltersList::const_iterator it = data.llDeviceFilters.begin();
     584         it != data.llDeviceFilters.end();
     585         ++it)
     586    {
     587        const settings::USBDeviceFilter &f = *it;
     588        ComObjPtr<USBDeviceFilter> pFilter;
     589        pFilter.createObject();
     590        HRESULT rc = pFilter->init(this,        // parent
     591                                   f);
    621592        CheckComRCReturnRC(rc);
    622593
    623         mDeviceFilters->push_back (filterObj);
    624         filterObj->mInList = true;
     594        mDeviceFilters->push_back(pFilter);
     595        pFilter->mInList = true;
    625596    }
    626597#endif /* VBOX_WITH_USB */
     
    636607 *  @note Locks this object for reading.
    637608 */
    638 HRESULT USBController::saveSettings (settings::Key &aMachineNode)
    639 {
    640     using namespace settings;
    641 
    642     AssertReturn(!aMachineNode.isNull(), E_FAIL);
    643 
     609HRESULT USBController::saveSettings(settings::USBController &data)
     610{
    644611    AutoCaller autoCaller(this);
    645612    CheckComRCReturnRC(autoCaller.rc());
     
    647614    AutoReadLock alock(this);
    648615
    649     /* first, delete the entry */
    650     Key controller = aMachineNode.findKey ("USBController");
    651 #ifdef VBOX_WITH_USB
    652     if (!controller.isNull())
    653         controller.zap();
    654     /* then, recreate it */
    655     controller = aMachineNode.createKey ("USBController");
    656 #else
    657     /* don't zap it. */
    658     if (controller.isNull())
    659         controller = aMachineNode.createKey ("USBController");
    660 #endif
    661 
    662     /* enabled */
    663     controller.setValue <bool> ("enabled", !!mData->mEnabled);
    664 
    665     /* enabledEhci */
    666     controller.setValue <bool> ("enabledEhci", !!mData->mEnabledEhci);
    667 
    668 #ifdef VBOX_WITH_USB
    669     DeviceFilterList::const_iterator it = mDeviceFilters->begin();
    670     while (it != mDeviceFilters->end())
     616    data.fEnabled = !!mData->mEnabled;
     617    data.fEnabledEHCI = !!mData->mEnabledEhci;
     618
     619#ifdef VBOX_WITH_USB
     620    data.llDeviceFilters.clear();
     621
     622    for (DeviceFilterList::const_iterator it = mDeviceFilters->begin();
     623         it != mDeviceFilters->end();
     624         ++it)
    671625    {
    672626        AutoWriteLock filterLock (*it);
    673627        const USBDeviceFilter::Data &data = (*it)->data();
    674628
    675         Key filter = controller.appendKey ("DeviceFilter");
    676 
    677         filter.setValue <Bstr> ("name", data.mName);
    678         filter.setValue <bool> ("active", !!data.mActive);
    679 
    680         /* all are optional */
    681629        Bstr str;
    682         (*it)->COMGETTER (VendorId) (str.asOutParam());
    683         if (!str.isNull())
    684             filter.setValue <Bstr> ("vendorId", str);
    685 
    686         (*it)->COMGETTER (ProductId) (str.asOutParam());
    687         if (!str.isNull())
    688             filter.setValue <Bstr> ("productId", str);
    689 
     630
     631        settings::USBDeviceFilter f;
     632        f.strName = data.mName;
     633        f.fActive = !!data.mActive;
     634        (*it)->COMGETTER(VendorId)(str.asOutParam());
     635        f.strVendorId = str;
     636        (*it)->COMGETTER(ProductId)(str.asOutParam());
     637        f.strProductId = str;
    690638        (*it)->COMGETTER (Revision) (str.asOutParam());
    691         if (!str.isNull())
    692             filter.setValue <Bstr> ("revision", str);
    693 
     639        f.strRevision = str;
    694640        (*it)->COMGETTER (Manufacturer) (str.asOutParam());
    695         if (!str.isNull())
    696             filter.setValue <Bstr> ("manufacturer", str);
    697 
     641        f.strManufacturer = str;
    698642        (*it)->COMGETTER (Product) (str.asOutParam());
    699         if (!str.isNull())
    700             filter.setValue <Bstr> ("product", str);
    701 
     643        f.strProduct = str;
    702644        (*it)->COMGETTER (SerialNumber) (str.asOutParam());
    703         if (!str.isNull())
    704             filter.setValue <Bstr> ("serialNumber", str);
    705 
     645        f.strSerialNumber = str;
    706646        (*it)->COMGETTER (Port) (str.asOutParam());
    707         if (!str.isNull())
    708             filter.setValue <Bstr> ("port", str);
    709 
    710         if (data.mRemote.string())
    711             filter.setValue <Bstr> ("remote", data.mRemote.string());
    712 
    713         if (data.mMaskedIfs)
    714             filter.setValue <ULONG> ("maskedInterfaces", data.mMaskedIfs);
    715 
    716         ++ it;
     647        f.strPort = str;
     648        f.strRemote = data.mRemote.string();
     649        f.ulMaskedInterfaces = data.mMaskedIfs;
    717650    }
    718651#endif /* VBOX_WITH_USB */
     
    12151148    ComAssertComRCRet (rc, false);
    12161149    if (!manufacturer.isNull())
    1217         USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer), true);
     1150        USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true);
    12181151
    12191152    Bstr product;
     
    12211154    ComAssertComRCRet (rc, false);
    12221155    if (!product.isNull())
    1223         USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product), true);
     1156        USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true);
    12241157
    12251158    Bstr serialNumber;
     
    12271160    ComAssertComRCRet (rc, false);
    12281161    if (!serialNumber.isNull())
    1229         USBFilterSetStringExact (&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber), true);
     1162        USBFilterSetStringExact (&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber).c_str(), true);
    12301163
    12311164    Bstr address;
  • trunk/src/VBox/Main/VFSExplorerImpl.cpp

    r21811 r22173  
    421421        {
    422422            PCRTS3KEYENTRY pKeys = NULL;
    423             vrc = RTS3GetBucketKeys(hS3, m->strBucket, &pKeys);
     423            vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
    424424            if (RT_FAILURE(vrc))
    425425                throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
     
    623623        for (size_t a=0; a < sfaNames.size(); ++a)
    624624        {
    625             if (entry.name == RTPathFilename(Utf8Str(sfaNames[a])))
     625            if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
    626626            {
    627627                BSTR name;
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r21878 r22173  
    2626#include <iprt/string.h>
    2727#include <iprt/uuid.h>
     28#include <iprt/stream.h>
    2829#include <iprt/thread.h>
    2930#include <iprt/process.h>
     
    8485/////////////////////////////////////////////////////////////////////////////
    8586
    86 static const char gDefaultGlobalConfig [] =
    87 {
    88     "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" RTFILE_LINEFEED
    89     "<!-- Sun VirtualBox Global Configuration -->" RTFILE_LINEFEED
    90     "<VirtualBox xmlns=\"" VBOX_XML_NAMESPACE "\" "
    91         "version=\"" VBOX_XML_VERSION_FULL "\">" RTFILE_LINEFEED
    92     "  <Global>"RTFILE_LINEFEED
    93     "    <MachineRegistry/>"RTFILE_LINEFEED
    94     "    <MediaRegistry/>"RTFILE_LINEFEED
    95     "    <NetserviceRegistry>"RTFILE_LINEFEED
    96     "       <DHCPServers>"RTFILE_LINEFEED
    97     "          <DHCPServer "
    98 #ifdef RT_OS_WINDOWS
    99                           "networkName=\"HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter\" "
    100 #else
    101                           "networkName=\"HostInterfaceNetworking-vboxnet0\" "
    102 #endif
    103                           "IPAddress=\"192.168.56.100\" networkMask=\"255.255.255.0\" "
    104                           "lowerIP=\"192.168.56.101\" upperIP=\"192.168.56.254\" "
    105                           "enabled=\"1\"/>"RTFILE_LINEFEED
    106     "       </DHCPServers>"RTFILE_LINEFEED
    107     "    </NetserviceRegistry>"RTFILE_LINEFEED
    108     "    <USBDeviceFilters/>"RTFILE_LINEFEED
    109     "    <SystemProperties/>"RTFILE_LINEFEED
    110     "  </Global>"RTFILE_LINEFEED
    111     "</VirtualBox>"RTFILE_LINEFEED
    112 };
    113 
    11487// static
    11588Bstr VirtualBox::sVersion;
     
    12093// static
    12194Bstr VirtualBox::sPackageType;
    122 
    123 // static
    124 Bstr VirtualBox::sSettingsFormatVersion;
    12595
    12696// constructor / destructor
     
    176146    LogFlowThisFunc(("Version: %ls, Package: %ls\n", sVersion.raw(), sPackageType.raw()));
    177147
    178     if (sSettingsFormatVersion.isNull())
    179         sSettingsFormatVersion = VBOX_XML_VERSION_FULL;
    180     LogFlowThisFunc(("Settings Format Version: %ls\n",
    181                       sSettingsFormatVersion.raw()));
    182 
    183148    /* Get the VirtualBox home directory. */
    184149    {
    185         char homeDir [RTPATH_MAX];
    186         int vrc = com::GetVBoxUserHomeDirectory (homeDir, sizeof (homeDir));
     150        char homeDir[RTPATH_MAX];
     151        int vrc = com::GetVBoxUserHomeDirectory(homeDir, sizeof(homeDir));
    187152        if (RT_FAILURE(vrc))
    188153            return setError (E_FAIL,
     
    194159    }
    195160
    196     /* compose the global config file name (always full path) */
    197     Utf8StrFmt vboxConfigFile ("%s%c%s", mData.mHomeDir.raw(),
    198                                RTPATH_DELIMITER, VBOX_GLOBAL_SETTINGS_FILE);
    199 
    200     /* store the config file name */
    201     unconst(mData.mCfgFile.mName) = vboxConfigFile;
    202 
    203     /* lock the config file */
    204     HRESULT rc = lockConfig();
    205     if (SUCCEEDED(rc))
    206     {
    207         if (!isConfigLocked())
    208         {
    209             /*
    210              *  This means the config file not found. This is not fatal --
    211              *  we just create an empty one.
    212              */
    213             RTFILE handle = NIL_RTFILE;
    214             int vrc = RTFileOpen (&handle, vboxConfigFile,
    215                                   RTFILE_O_READWRITE | RTFILE_O_CREATE |
    216                                   RTFILE_O_DENY_WRITE);
    217             if (RT_SUCCESS(vrc))
    218                 vrc = RTFileWrite (handle,
    219                                    (void *) gDefaultGlobalConfig,
    220                                    strlen (gDefaultGlobalConfig), NULL);
    221             if (RT_FAILURE(vrc))
     161    /* compose the VirtualBox.xml file name */
     162    unconst(m_strSettingsFilePath) = Utf8StrFmt("%s%c%s",
     163                                                mData.mHomeDir.raw(),
     164                                                RTPATH_DELIMITER,
     165                                                VBOX_GLOBAL_SETTINGS_FILE);
     166    HRESULT rc = S_OK;
     167    try
     168    {
     169        // load and parse VirtualBox.xml; this will throw on XML or logic errors
     170        m_pMainConfigFile = new settings::MainConfigFile(&m_strSettingsFilePath);
     171
     172        // either a) valid XML file loaded or b) file not found and defaults loaded:
     173        // now construct our global objects from that data
     174
     175#ifdef VBOX_WITH_RESOURCE_USAGE_API
     176        /* create the performance collector object BEFORE host */
     177        unconst (mData.mPerformanceCollector).createObject();
     178        rc = mData.mPerformanceCollector->init();
     179        ComAssertComRCThrowRC(rc);
     180#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     181
     182        /* create the host object early, machines will need it */
     183        unconst (mData.mHost).createObject();
     184        rc = mData.mHost->init(this);
     185        ComAssertComRCThrowRC(rc);
     186
     187        rc = mData.mHost->loadSettings(m_pMainConfigFile->host);
     188        CheckComRCThrowRC(rc);
     189
     190        /* create the system properties object, someone may need it too */
     191        unconst (mData.mSystemProperties).createObject();
     192        rc = mData.mSystemProperties->init(this);
     193        ComAssertComRCThrowRC (rc);
     194
     195        rc = mData.mSystemProperties->loadSettings(m_pMainConfigFile->systemProperties);
     196        CheckComRCThrowRC(rc);
     197
     198        /* guest OS type objects, needed by machines */
     199        for (size_t i = 0; i < RT_ELEMENTS (Global::sOSTypes); ++ i)
     200        {
     201            ComObjPtr <GuestOSType> guestOSTypeObj;
     202            rc = guestOSTypeObj.createObject();
     203            if (SUCCEEDED(rc))
    222204            {
    223                 rc = setError (E_FAIL, tr ("Could not create the default settings file "
    224                                            "'%s' (%Rrc)"),
    225                                        vboxConfigFile.raw(), vrc);
     205                rc = guestOSTypeObj->init(Global::sOSTypes [i].familyId,
     206                                          Global::sOSTypes [i].familyDescription,
     207                                          Global::sOSTypes [i].id,
     208                                          Global::sOSTypes [i].description,
     209                                          Global::sOSTypes [i].osType,
     210                                          Global::sOSTypes [i].osHint,
     211                                          Global::sOSTypes [i].recommendedRAM,
     212                                          Global::sOSTypes [i].recommendedVRAM,
     213                                          Global::sOSTypes [i].recommendedHDD,
     214                                          Global::sOSTypes [i].networkAdapterType,
     215                                          Global::sOSTypes [i].numSerialEnabled);
     216                if (SUCCEEDED(rc))
     217                    mData.mGuestOSTypes.push_back (guestOSTypeObj);
    226218            }
    227             else
    228             {
    229                 mData.mCfgFile.mHandle = handle;
    230                 /* we do not close the file to simulate lockConfig() */
    231             }
    232         }
    233     }
    234 
    235     if (SUCCEEDED(rc))
    236     {
    237         try
    238         {
    239             using namespace settings;
    240             using namespace xml;
    241 
    242             /* no concurrent file access is possible in init() so open by handle */
    243             File file (mData.mCfgFile.mHandle, vboxConfigFile);
    244             XmlTreeBackend tree;
    245 
    246             rc = VirtualBox::loadSettingsTree_FirstTime (tree, file,
    247                                                          mData.mSettingsFileVersion);
    248             CheckComRCThrowRC (rc);
    249 
    250             Key global = tree.rootKey().key ("Global");
    251 
    252 #ifdef VBOX_WITH_RESOURCE_USAGE_API
    253             /* create the performance collector object BEFORE host */
    254             unconst(mData.mPerformanceCollector).createObject();
    255             rc = mData.mPerformanceCollector->init();
    256219            ComAssertComRCThrowRC (rc);
    257 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
    258 
    259             /* create the host object early, machines will need it */
    260             unconst(mData.mHost).createObject();
    261             rc = mData.mHost->init (this);
    262             ComAssertComRCThrowRC (rc);
    263 
    264             rc = mData.mHost->loadSettings (global);
    265             CheckComRCThrowRC (rc);
    266 
    267             /* create the system properties object, someone may need it too */
    268             unconst(mData.mSystemProperties).createObject();
    269             rc = mData.mSystemProperties->init (this);
    270             ComAssertComRCThrowRC (rc);
    271 
    272             rc = mData.mSystemProperties->loadSettings (global);
    273             CheckComRCThrowRC (rc);
    274 
    275             /* guest OS type objects, needed by machines */
    276             for (size_t i = 0; i < RT_ELEMENTS (Global::sOSTypes); ++ i)
    277             {
    278                 ComObjPtr<GuestOSType> guestOSTypeObj;
    279                 rc = guestOSTypeObj.createObject();
    280                 if (SUCCEEDED(rc))
    281                 {
    282                     rc = guestOSTypeObj->init (Global::sOSTypes [i].familyId,
    283                                                Global::sOSTypes [i].familyDescription,
    284                                                Global::sOSTypes [i].id,
    285                                                Global::sOSTypes [i].description,
    286                                                Global::sOSTypes [i].osType,
    287                                                Global::sOSTypes [i].osHint,
    288                                                Global::sOSTypes [i].recommendedRAM,
    289                                                Global::sOSTypes [i].recommendedVRAM,
    290                                                Global::sOSTypes [i].recommendedHDD,
    291                                                Global::sOSTypes [i].networkAdapterType,
    292                                                Global::sOSTypes [i].numSerialEnabled);
    293                     if (SUCCEEDED(rc))
    294                         mData.mGuestOSTypes.push_back (guestOSTypeObj);
    295                 }
    296                 ComAssertComRCThrowRC (rc);
    297             }
    298 
    299             /* all registered media, needed by machines */
    300             rc = loadMedia (global);
    301             CheckComRCThrowRC (rc);
    302 
    303             /* machines */
    304             rc = loadMachines (global);
    305             CheckComRCThrowRC (rc);
    306 
    307             /* net services */
    308             rc = loadNetservices(global);
    309             CheckComRCThrowRC (rc);
    310 
    311             /* check hard disk consistency */
    312 /// @todo (r=dmik) add IVirtualBox::cleanupHardDisks() instead or similar
    313 //            for (HardDiskList::const_iterator it = mData.mHardDisks.begin();
    314 //                 it != mData.mHardDisks.end() && SUCCEEDED(rc);
    315 //                 ++ it)
    316 //            {
    317 //                rc = (*it)->checkConsistency();
    318 //            }
    319 //            CheckComRCBreakRC ((rc));
    320 
    321             /// @todo (dmik) if successful, check for orphan (unused) diffs
    322             //  that might be left because of the server crash, and remove
    323             //  Hmm, is it the same remark as above?..
    324         }
    325         catch (HRESULT err)
    326         {
    327             /* we assume that error info is set by the thrower */
    328             rc = err;
    329         }
    330         catch (...)
    331         {
    332             rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    333         }
     220        }
     221
     222        /* all registered media, needed by machines */
     223        if (FAILED(rc = initMedia()))
     224            throw rc;
     225
     226        /* machines */
     227        if (FAILED(rc = initMachines()))
     228            throw rc;
     229
     230        /* net services */
     231        for (settings::DHCPServersList::const_iterator it = m_pMainConfigFile->llDhcpServers.begin();
     232             it != m_pMainConfigFile->llDhcpServers.end();
     233             ++it)
     234        {
     235            const settings::DHCPServer &data = *it;
     236
     237            ComObjPtr<DHCPServer> pDhcpServer;
     238            if (SUCCEEDED(rc = pDhcpServer.createObject()))
     239                rc = pDhcpServer->init(this, data);
     240            CheckComRCThrowRC(rc);
     241
     242            rc = registerDHCPServer(pDhcpServer, false /* aSaveRegistry */);
     243            CheckComRCThrowRC(rc);
     244        }
     245    }
     246    catch (HRESULT err)
     247    {
     248        /* we assume that error info is set by the thrower */
     249        rc = err;
     250    }
     251    catch (...)
     252    {
     253        rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
    334254    }
    335255
     
    380300}
    381301
     302HRESULT VirtualBox::initMachines()
     303{
     304    for (settings::MachinesRegistry::const_iterator it = m_pMainConfigFile->llMachines.begin();
     305         it != m_pMainConfigFile->llMachines.end();
     306         ++it)
     307    {
     308        HRESULT rc = S_OK;
     309        const settings::MachineRegistryEntry &xmlMachine = *it;
     310        Guid uuid = xmlMachine.uuid;
     311
     312        ComObjPtr<Machine> pMachine;
     313        if (SUCCEEDED(rc = pMachine.createObject()))
     314        {
     315            rc = pMachine->init(this,
     316                                xmlMachine.strSettingsFile,
     317                                Machine::Init_Registered,
     318                                NULL,
     319                                NULL,
     320                                FALSE,
     321                                &uuid);
     322            if (SUCCEEDED(rc))
     323                rc = registerMachine(pMachine);
     324            if (FAILED(rc))
     325                return rc;
     326        }
     327    }
     328
     329    return S_OK;
     330}
     331
     332HRESULT VirtualBox::initMedia()
     333{
     334    HRESULT rc = S_OK;
     335    settings::MediaList::const_iterator it;
     336    for (it = m_pMainConfigFile->llHardDisks.begin();
     337         it != m_pMainConfigFile->llHardDisks.end();
     338         ++it)
     339    {
     340        const settings::Medium &xmlHD = *it;
     341
     342        ComObjPtr<HardDisk> pHardDisk;
     343        if (SUCCEEDED(rc = pHardDisk.createObject()))
     344            rc = pHardDisk->init(this,
     345                                 NULL,           // parent
     346                                 xmlHD);         // XML data; this recurses to processes the children
     347        CheckComRCReturnRC(rc);
     348
     349        rc = registerHardDisk(pHardDisk, false /* aSaveRegistry */);
     350        CheckComRCReturnRC(rc);
     351    }
     352
     353    for (it = m_pMainConfigFile->llDvdImages.begin();
     354         it != m_pMainConfigFile->llDvdImages.end();
     355         ++it)
     356    {
     357        const settings::Medium &xmlDvd = *it;
     358
     359        ComObjPtr<DVDImage> pImage;
     360        if (SUCCEEDED(pImage.createObject()))
     361            rc = pImage->init(this, xmlDvd);
     362        CheckComRCReturnRC(rc);
     363
     364        rc = registerDVDImage(pImage, false /* aSaveRegistry */);
     365        CheckComRCReturnRC(rc);
     366    }
     367
     368    for (it = m_pMainConfigFile->llFloppyImages.begin();
     369         it != m_pMainConfigFile->llFloppyImages.end();
     370         ++it)
     371    {
     372        const settings::Medium &xmlFloppy = *it;
     373
     374        ComObjPtr<FloppyImage> pImage;
     375        if (SUCCEEDED(pImage.createObject()))
     376            rc = pImage->init(this, xmlFloppy);
     377        CheckComRCReturnRC(rc);
     378
     379        rc = registerFloppyImage(pImage, false /* aSaveRegistry */);
     380        CheckComRCReturnRC(rc);
     381    }
     382
     383    return S_OK;
     384}
     385
    382386void VirtualBox::uninit()
    383387{
     
    442446    }
    443447#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    444 
    445     /* unlock the config file */
    446     unlockConfig();
    447448
    448449    LogFlowThisFunc(("Releasing callbacks...\n"));
     
    575576
    576577    /* mCfgFile.mName is const and doesn't need a lock */
    577     mData.mCfgFile.mName.cloneTo(aSettingsFilePath);
    578     return S_OK;
    579 }
    580 
    581 STDMETHODIMP VirtualBox::
    582 COMGETTER(SettingsFileVersion) (BSTR *aSettingsFileVersion)
    583 {
    584     CheckComArgNotNull(aSettingsFileVersion);
    585 
    586     AutoCaller autoCaller(this);
    587     CheckComRCReturnRC(autoCaller.rc());
    588 
    589     AutoReadLock alock(this);
    590 
    591     mData.mSettingsFileVersion.cloneTo(aSettingsFileVersion);
    592     return S_OK;
    593 }
    594 
    595 STDMETHODIMP VirtualBox::
    596 COMGETTER(SettingsFormatVersion) (BSTR *aSettingsFormatVersion)
    597 {
    598     CheckComArgNotNull(aSettingsFormatVersion);
    599 
    600     AutoCaller autoCaller(this);
    601     CheckComRCReturnRC(autoCaller.rc());
    602 
    603     sSettingsFormatVersion.cloneTo(aSettingsFormatVersion);
     578    m_strSettingsFilePath.cloneTo(aSettingsFilePath);
    604579    return S_OK;
    605580}
     
    782757
    783758/** @note Locks mSystemProperties object for reading. */
    784 STDMETHODIMP VirtualBox::CreateMachine (IN_BSTR aName,
    785                                         IN_BSTR aOsTypeId,
    786                                         IN_BSTR aBaseFolder,
    787                                         IN_BSTR aId,
    788                                         IMachine **aMachine)
     759STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aName,
     760                                       IN_BSTR aOsTypeId,
     761                                       IN_BSTR aBaseFolder,
     762                                       IN_BSTR aId,
     763                                       IMachine **aMachine)
    789764{
    790765    LogFlowThisFuncEnter();
     
    805780     * machine folder will be used as a base folder.
    806781     */
    807     Bstr settingsFile = aBaseFolder;
    808     if (settingsFile.isEmpty())
    809     {
    810         AutoReadLock propsLock (systemProperties());
     782    Utf8Str strSettingsFile = aBaseFolder;
     783    if (strSettingsFile.isEmpty())
    811784        /* we use the non-full folder value below to keep the path relative */
    812         settingsFile = systemProperties()->defaultMachineFolder();
    813     }
    814     settingsFile = Utf8StrFmt ("%ls%c%ls%c%ls.xml",
    815                                settingsFile.raw(), RTPATH_DELIMITER,
    816                                aName, RTPATH_DELIMITER, aName);
     785        strSettingsFile = getDefaultMachineFolder();
     786
     787    strSettingsFile = Utf8StrFmt("%s%c%ls%c%ls.xml",
     788                                 strSettingsFile.raw(),
     789                                 RTPATH_DELIMITER,
     790                                 aName,
     791                                 RTPATH_DELIMITER,
     792                                 aName);
    817793
    818794    HRESULT rc = E_FAIL;
     
    836812    {
    837813        for (GuestOSTypeList::const_iterator it = mData.mGuestOSTypes.begin();
    838              it != mData.mGuestOSTypes.end(); ++ it)
     814             it != mData.mGuestOSTypes.end();
     815             ++ it)
    839816        {
    840817            if ((*it)->id() == aOsTypeId)
     
    846823
    847824        if (osType == NULL)
    848             return setError (VBOX_E_OBJECT_NOT_FOUND,
    849                 tr ("Guest OS type '%ls' is invalid"), aOsTypeId);
     825            return setError(VBOX_E_OBJECT_NOT_FOUND,
     826                            tr("Guest OS type '%ls' is invalid"),
     827                            aOsTypeId);
    850828    }
    851829
    852830    /* initialize the machine object */
    853     rc = machine->init (this, settingsFile, Machine::Init_New, aName, osType,
    854                         TRUE /* aNameSync */, &id);
     831    rc = machine->init(this,
     832                       strSettingsFile,
     833                       Machine::Init_New,
     834                       aName,
     835                       osType,
     836                       TRUE /* aNameSync */,
     837                       &id);
    855838    if (SUCCEEDED(rc))
    856839    {
     
    865848}
    866849
    867 STDMETHODIMP VirtualBox::CreateLegacyMachine (IN_BSTR aName,
    868                                               IN_BSTR aOsTypeId,
    869                                               IN_BSTR aSettingsFile,
    870                                               IN_BSTR aId,
    871                                               IMachine **aMachine)
     850STDMETHODIMP VirtualBox::CreateLegacyMachine(IN_BSTR aName,
     851                                             IN_BSTR aOsTypeId,
     852                                             IN_BSTR aSettingsFile,
     853                                             IN_BSTR aId,
     854                                             IMachine **aMachine)
    872855{
    873856    CheckComArgStrNotEmptyOrNull (aName);
     
    883866    Utf8Str settingsFile = aSettingsFile;
    884867    /* append the default extension if none */
    885     if (!RTPathHaveExt (settingsFile))
    886         settingsFile = Utf8StrFmt ("%s.xml", settingsFile.raw());
     868    if (!RTPathHaveExt(settingsFile.c_str()))
     869        settingsFile = Utf8StrFmt("%s.xml", settingsFile.raw());
    887870
    888871    /* create a new object */
     
    919902
    920903    /* initialize the machine object */
    921     rc = machine->init (this, Bstr (settingsFile), Machine::Init_New,
    922                         aName, osType, FALSE /* aNameSync */, &id);
     904    rc = machine->init(this,
     905                       settingsFile,
     906                       Machine::Init_New,
     907                       aName,
     908                       osType,
     909                       FALSE /* aNameSync */,
     910                       &id);
    923911    if (SUCCEEDED(rc))
    924912    {
     
    931919}
    932920
    933 STDMETHODIMP VirtualBox::OpenMachine (IN_BSTR aSettingsFile,
    934                                       IMachine **aMachine)
     921STDMETHODIMP VirtualBox::OpenMachine(IN_BSTR aSettingsFile,
     922                                     IMachine **aMachine)
    935923{
    936924    CheckComArgStrNotEmptyOrNull(aSettingsFile);
     
    948936    {
    949937        /* initialize the machine object */
    950         rc = machine->init (this, aSettingsFile, Machine::Init_Existing);
     938        rc = machine->init(this,
     939                           aSettingsFile,
     940                           Machine::Init_Import);
    951941        if (SUCCEEDED(rc))
    952942        {
     
    11191109    Bstr format = aFormat;
    11201110    if (format.isEmpty())
    1121     {
    1122         AutoReadLock propsLock (systemProperties());
    1123         format = systemProperties()->defaultHardDiskFormat();
    1124     }
     1111        format = getDefaultHardDiskFormat();
    11251112
    11261113    HRESULT rc = E_FAIL;
     
    14471434 *  @note Locks this object for reading.
    14481435 */
    1449 STDMETHODIMP VirtualBox::
    1450 GetNextExtraDataKey (IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue)
    1451 {
    1452     CheckComArgNotNull(aNextKey);
    1453 
    1454     AutoCaller autoCaller(this);
    1455     CheckComRCReturnRC(autoCaller.rc());
    1456 
    1457     /* start with nothing found */
    1458     Bstr("").cloneTo(aNextKey);
    1459     if (aNextValue)
    1460         Bstr("").cloneTo(aNextValue);
    1461 
    1462     HRESULT rc = S_OK;
    1463 
    1464     Bstr bstrInKey(aKey);
    1465 
    1466     /* serialize file access (prevent writes) */
    1467     AutoReadLock alock(this);
    1468 
    1469     try
    1470     {
    1471         using namespace settings;
    1472         using namespace xml;
    1473 
    1474         /* load the settings file (we don't reuse the existing handle but
    1475          * request a new one to allow for concurrent multi-threaded reads) */
    1476         File file (File::Mode_Read, Utf8Str (mData.mCfgFile.mName));
    1477         XmlTreeBackend tree;
    1478 
    1479         rc = VirtualBox::loadSettingsTree_Again (tree, file);
    1480         CheckComRCReturnRC(rc);
    1481 
    1482         Key globalNode = tree.rootKey().key ("Global");
    1483         Key extraDataNode = globalNode.findKey ("ExtraData");
    1484 
    1485         if (!extraDataNode.isNull())
    1486         {
    1487             Key::List items = extraDataNode.keys ("ExtraDataItem");
    1488             if (items.size())
    1489             {
    1490                 for (Key::List::const_iterator it = items.begin();
    1491                      it != items.end(); ++ it)
    1492                 {
    1493                     Bstr key = (*it).stringValue ("name");
    1494 
    1495                     /* if we're supposed to return the first one */
    1496                     if (bstrInKey.isEmpty())
    1497                     {
    1498                         key.cloneTo(aNextKey);
    1499                         if (aNextValue)
    1500                         {
    1501                             Bstr val = (*it).stringValue ("value");
    1502                             val.cloneTo(aNextValue);
    1503                         }
    1504                         return S_OK;
    1505                     }
    1506 
    1507                     /* did we find the key we're looking for? */
    1508                     if (key == bstrInKey)
    1509                     {
    1510                         ++ it;
    1511                         /* is there another item? */
    1512                         if (it != items.end())
    1513                         {
    1514                             Bstr key = (*it).stringValue ("name");
    1515                             key.cloneTo(aNextKey);
    1516                             if (aNextValue)
    1517                             {
    1518                                 Bstr val = (*it).stringValue ("value");
    1519                                 val.cloneTo(aNextValue);
    1520                             }
    1521                         }
    1522                         /* else it's the last one, arguments are already NULL */
    1523                         return S_OK;
    1524                     }
    1525                 }
    1526             }
    1527         }
    1528 
    1529         /* Here we are when a) there are no items at all or b) there are items
    1530          * but none of them equals to the requested non-NULL key. b) is an
    1531          * error as well as a) if the key is non-NULL. When the key is NULL
    1532          * (which is the case only when there are no items), we just fall
    1533          * through to return NULLs and S_OK. */
    1534 
    1535         if (!bstrInKey.isEmpty())
    1536             return setError (VBOX_E_OBJECT_NOT_FOUND,
    1537                 tr("Could not find the extra data key '%ls'"), bstrInKey.raw());
    1538     }
    1539     catch (...)
    1540     {
    1541         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    1542     }
    1543 
    1544     return rc;
     1436STDMETHODIMP VirtualBox::GetExtraDataKeys(ComSafeArrayOut(BSTR, aKeys))
     1437{
     1438    using namespace settings;
     1439
     1440    if (ComSafeArrayOutIsNull(aKeys))
     1441        return E_POINTER;
     1442
     1443    AutoCaller autoCaller (this);
     1444    CheckComRCReturnRC (autoCaller.rc());
     1445
     1446    AutoReadLock alock (this);
     1447
     1448    com::SafeArray<BSTR> saKeys(m_pMainConfigFile->mapExtraDataItems.size());
     1449    int i = 0;
     1450    for (ExtraDataItemsMap::const_iterator it = m_pMainConfigFile->mapExtraDataItems.begin();
     1451         it != m_pMainConfigFile->mapExtraDataItems.end();
     1452         ++it, ++i)
     1453    {
     1454        const Utf8Str &strName = it->first;     // the key
     1455        strName.cloneTo(&saKeys[i]);
     1456    }
     1457    saKeys.detachTo(ComSafeArrayOutArg(aKeys));
     1458
     1459    return S_OK;
    15451460}
    15461461
     
    15481463 *  @note Locks this object for reading.
    15491464 */
    1550 STDMETHODIMP VirtualBox::GetExtraData (IN_BSTR aKey, BSTR *aValue)
     1465STDMETHODIMP VirtualBox::GetExtraData(IN_BSTR aKey,
     1466                                      BSTR *aValue)
    15511467{
    15521468    CheckComArgNotNull(aKey);
     
    15591475    Bstr("").cloneTo(aValue);
    15601476
    1561     HRESULT rc = S_OK;
    1562 
    1563     /* serialize file access (prevent writes) */
    1564     AutoReadLock alock(this);
    1565 
    1566     try
    1567     {
    1568         using namespace settings;
    1569         using namespace xml;
    1570 
    1571         /* load the settings file (we don't reuse the existing handle but
    1572          * request a new one to allow for concurrent multi-threaded reads) */
    1573         File file (File::Mode_Read, Utf8Str (mData.mCfgFile.mName));
    1574         XmlTreeBackend tree;
    1575 
    1576         rc = VirtualBox::loadSettingsTree_Again (tree, file);
    1577         CheckComRCReturnRC(rc);
    1578 
    1579         const Utf8Str key = aKey;
    1580 
    1581         Key globalNode = tree.rootKey().key ("Global");
    1582         Key extraDataNode = globalNode.findKey ("ExtraData");
    1583 
    1584         if (!extraDataNode.isNull())
    1585         {
    1586             /* check if the key exists */
    1587             Key::List items = extraDataNode.keys ("ExtraDataItem");
    1588             for (Key::List::const_iterator it = items.begin();
    1589                  it != items.end(); ++ it)
    1590             {
    1591                 if (key == (*it).stringValue ("name"))
    1592                 {
    1593                     Bstr val = (*it).stringValue ("value");
    1594                     val.cloneTo(aValue);
    1595                     break;
    1596                 }
    1597             }
    1598         }
    1599     }
    1600     catch (...)
    1601     {
    1602         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
    1603     }
    1604 
    1605     return rc;
     1477    settings::ExtraDataItemsMap::const_iterator it = m_pMainConfigFile->mapExtraDataItems.find(Utf8Str(aKey));
     1478    if (it != m_pMainConfigFile->mapExtraDataItems.end())
     1479    {
     1480        // found:
     1481        const Utf8Str &strValue = it->second;
     1482        strValue.cloneTo(aValue);
     1483    }
     1484
     1485    return S_OK;
    16061486}
    16071487
     
    16091489 *  @note Locks this object for writing.
    16101490 */
    1611 STDMETHODIMP VirtualBox::SetExtraData (IN_BSTR aKey, IN_BSTR aValue)
     1491STDMETHODIMP VirtualBox::SetExtraData(IN_BSTR aKey,
     1492                                      IN_BSTR aValue)
    16121493{
    16131494    CheckComArgNotNull(aKey);
     
    16231504        val = aValue;
    16241505
    1625     bool changed = false;
    1626     HRESULT rc = S_OK;
     1506    Utf8Str strKey(aKey);
     1507    Bstr oldVal("");
    16271508
    16281509    /* serialize file access (prevent concurrent reads and writes) */
    16291510    AutoWriteLock alock(this);
    16301511
    1631     try
    1632     {
    1633         using namespace settings;
    1634         using namespace xml;
    1635 
    1636         /* load the settings file */
    1637         File file (mData.mCfgFile.mHandle, Utf8Str (mData.mCfgFile.mName));
    1638         XmlTreeBackend tree;
    1639 
    1640         rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
    1641         CheckComRCReturnRC(rc);
    1642 
    1643         const Utf8Str key = aKey;
    1644         Bstr oldVal("");
    1645 
    1646         Key globalNode = tree.rootKey().key ("Global");
    1647         Key extraDataNode = globalNode.createKey ("ExtraData");
    1648         Key extraDataItemNode;
    1649 
    1650         Key::List items = extraDataNode.keys ("ExtraDataItem");
    1651         for (Key::List::const_iterator it = items.begin();
    1652              it != items.end(); ++ it)
    1653         {
    1654             if (key == (*it).stringValue ("name"))
    1655             {
    1656                 extraDataItemNode = *it;
    1657                 oldVal = (*it).stringValue ("value");
    1658                 break;
    1659             }
    1660         }
    1661 
    1662         /* When no key is found, oldVal is empty string */
    1663         changed = oldVal != val;
    1664 
    1665         if (changed)
    1666         {
    1667             /* ask for permission from all listeners */
    1668             Bstr error;
    1669             if (!onExtraDataCanChange (Guid::Empty, aKey, val, error))
    1670             {
    1671                 const char *sep = error.isEmpty() ? "" : ": ";
    1672                 CBSTR err = error.isNull() ? (CBSTR) L"" : error.raw();
    1673                 LogWarningFunc (("Someone vetoed! Change refused%s%ls\n",
    1674                                  sep, err));
    1675                 return setError (E_ACCESSDENIED,
    1676                     tr ("Could not set extra data because someone refused "
    1677                         "the requested change of '%ls' to '%ls'%s%ls"),
    1678                     aKey, val.raw(), sep, err);
    1679             }
    1680 
    1681             if (!val.isEmpty())
    1682             {
    1683                 if (extraDataItemNode.isNull())
    1684                 {
    1685                     extraDataItemNode = extraDataNode.appendKey ("ExtraDataItem");
    1686                     extraDataItemNode.setStringValue ("name", key);
    1687                 }
    1688                 extraDataItemNode.setStringValue ("value", Utf8Str (aValue));
    1689             }
    1690             else
    1691             {
    1692                 /* An old value does for sure exist here (XML schema
    1693                  * guarantees that "value" may not be absent in the
    1694                  * <ExtraDataItem> element). */
    1695                 Assert (!extraDataItemNode.isNull());
    1696                 extraDataItemNode.zap();
    1697             }
    1698 
    1699             /* save settings on success */
    1700             rc = VirtualBox::saveSettingsTree (tree, file,
    1701                                                mData.mSettingsFileVersion);
    1702             CheckComRCReturnRC(rc);
    1703         }
    1704     }
    1705     catch (...)
    1706     {
    1707         rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
     1512    settings::ExtraDataItemsMap::const_iterator it = m_pMainConfigFile->mapExtraDataItems.find(strKey);
     1513    if (it != m_pMainConfigFile->mapExtraDataItems.end())
     1514    {
     1515        // key exists:
     1516        const Utf8Str &strValue = it->second;
     1517        oldVal = strValue;
     1518    }
     1519
     1520    bool fChanged = (oldVal != val);
     1521    if (fChanged)
     1522    {
     1523        /* ask for permission from all listeners */
     1524        Bstr error;
     1525        if (!onExtraDataCanChange(Guid::Empty, aKey, val, error))
     1526        {
     1527            const char *sep = error.isEmpty() ? "" : ": ";
     1528            CBSTR err = error.isNull() ? (CBSTR) L"" : error.raw();
     1529            LogWarningFunc(("Someone vetoed! Change refused%s%ls\n",
     1530                            sep, err));
     1531            return setError(E_ACCESSDENIED,
     1532                            tr("Could not set extra data because someone refused the requested change of '%ls' to '%ls'%s%ls"),
     1533                            aKey,
     1534                            val.raw(),
     1535                            sep,
     1536                            err);
     1537        }
     1538
     1539        m_pMainConfigFile->mapExtraDataItems[strKey] = val;
     1540
     1541        /* save settings on success */
     1542        HRESULT rc = saveSettings();
     1543        CheckComRCReturnRC (rc);
    17081544    }
    17091545
    17101546    /* fire a notification */
    1711     if (SUCCEEDED(rc) && changed)
    1712         onExtraDataChange (Guid::Empty, aKey, aValue);
    1713 
    1714     return rc;
     1547    if (fChanged)
     1548        onExtraDataChange(Guid::Empty, aKey, aValue);
     1549
     1550    return S_OK;
    17151551}
    17161552
     
    19181754{
    19191755    ReturnComNotImplemented();
    1920 }
    1921 
    1922 STDMETHODIMP VirtualBox::SaveSettings()
    1923 {
    1924     AutoCaller autoCaller(this);
    1925     CheckComRCReturnRC(autoCaller.rc());
    1926 
    1927     return saveSettings();
    1928 }
    1929 
    1930 STDMETHODIMP VirtualBox::SaveSettingsWithBackup (BSTR *aBakFileName)
    1931 {
    1932     CheckComArgNotNull(aBakFileName);
    1933 
    1934     AutoCaller autoCaller(this);
    1935     CheckComRCReturnRC(autoCaller.rc());
    1936 
    1937     /* saveSettings() needs write lock */
    1938     AutoWriteLock alock(this);
    1939 
    1940     /* perform backup only when there was auto-conversion */
    1941     if (mData.mSettingsFileVersion != VBOX_XML_VERSION_FULL)
    1942     {
    1943         Bstr bakFileName;
    1944 
    1945         HRESULT rc = backupSettingsFile (mData.mCfgFile.mName,
    1946                                          mData.mSettingsFileVersion,
    1947                                          bakFileName);
    1948         CheckComRCReturnRC(rc);
    1949 
    1950         bakFileName.cloneTo(aBakFileName);
    1951     }
    1952 
    1953     return saveSettings();
    19541756}
    19551757
     
    27182520 * @note Locks this object and hard disk objects for reading.
    27192521 */
    2720 HRESULT VirtualBox::
    2721 findHardDisk(const Guid *aId, CBSTR aLocation,
    2722              bool aSetError, ComObjPtr<HardDisk> *aHardDisk /*= NULL*/)
     2522HRESULT VirtualBox::findHardDisk(const Guid *aId,
     2523                                 CBSTR aLocation,
     2524                                 bool aSetError,
     2525                                 ComObjPtr<HardDisk> *aHardDisk /*= NULL*/)
    27232526{
    27242527    AssertReturn(aId || aLocation, E_INVALIDARG);
     
    27502553            const ComObjPtr<HardDisk> &hd = (*it).second;
    27512554
    2752             HRESULT rc = hd->compareLocationTo (location, result);
     2555            HRESULT rc = hd->compareLocationTo(location, result);
    27532556            CheckComRCReturnRC(rc);
    27542557
     
    27672570    {
    27682571        if (aId)
    2769             setError (rc, tr ("Could not find a hard disk with UUID {%RTuuid} "
    2770                               "in the media registry ('%ls')"),
    2771                       aId->raw(), mData.mCfgFile.mName.raw());
     2572            setError(rc,
     2573                     tr("Could not find a hard disk with UUID {%RTuuid} in the media registry ('%s')"),
     2574                     aId->raw(),
     2575                     m_strSettingsFilePath.raw());
    27722576        else
    2773             setError (rc, tr ("Could not find a hard disk with location '%ls' "
    2774                               "in the media registry ('%ls')"),
    2775                       aLocation, mData.mCfgFile.mName.raw());
     2577            setError(rc,
     2578                     tr("Could not find a hard disk with location '%ls' in the media registry ('%s')"),
     2579                     aLocation,
     2580                     m_strSettingsFilePath.raw());
    27762581    }
    27772582
     
    27942599 * @note Locks this object and image objects for reading.
    27952600 */
    2796 HRESULT VirtualBox::findDVDImage(const Guid *aId, CBSTR aLocation,
     2601HRESULT VirtualBox::findDVDImage(const Guid *aId,
     2602                                 CBSTR aLocation,
    27972603                                 bool aSetError,
    27982604                                 ComObjPtr<DVDImage> *aImage /* = NULL */)
     
    28042610    if (aLocation != NULL)
    28052611    {
    2806         int vrc = calculateFullPath (Utf8Str (aLocation), location);
     2612        int vrc = calculateFullPath(Utf8Str(aLocation), location);
    28072613        if (RT_FAILURE(vrc))
    2808             return setError (VBOX_E_FILE_ERROR,
    2809                 tr ("Invalid image file location '%ls' (%Rrc)"),
    2810                 aLocation, vrc);
     2614            return setError(VBOX_E_FILE_ERROR,
     2615                            tr("Invalid image file location '%ls' (%Rrc)"),
     2616                            aLocation,
     2617                            vrc);
    28112618    }
    28122619
     
    28242631        found = (aId && (*it)->id() == *aId) ||
    28252632                (aLocation != NULL &&
    2826                  RTPathCompare (location, Utf8Str ((*it)->locationFull())) == 0);
     2633                 RTPathCompare(location.c_str(),
     2634                               Utf8Str((*it)->locationFull()).c_str()
     2635                              ) == 0);
    28272636        if (found)
    28282637        {
     
    28382647    {
    28392648        if (aId)
    2840             setError (rc, tr ("Could not find a CD/DVD image with UUID {%RTuuid} "
    2841                               "in the media registry ('%ls')"),
    2842                       aId->raw(), mData.mCfgFile.mName.raw());
     2649            setError(rc,
     2650                     tr("Could not find a CD/DVD image with UUID {%RTuuid} in the media registry ('%s')"),
     2651                     aId->raw(),
     2652                     m_strSettingsFilePath.raw());
    28432653        else
    2844             setError (rc, tr ("Could not find a CD/DVD image with location '%ls' "
    2845                               "in the media registry ('%ls')"),
    2846                       aLocation, mData.mCfgFile.mName.raw());
     2654            setError(rc,
     2655                     tr("Could not find a CD/DVD image with location '%ls' in the media registry ('%s')"),
     2656                     aLocation,
     2657                     m_strSettingsFilePath.raw());
    28472658    }
    28482659
     
    28762687    if (aLocation != NULL)
    28772688    {
    2878         int vrc = calculateFullPath (Utf8Str (aLocation), location);
     2689        int vrc = calculateFullPath(Utf8Str(aLocation), location);
    28792690        if (RT_FAILURE(vrc))
    28802691            return setError (VBOX_E_FILE_ERROR,
     
    28962707        found = (aId && (*it)->id() == *aId) ||
    28972708                (aLocation != NULL &&
    2898                  RTPathCompare (location, Utf8Str ((*it)->locationFull())) == 0);
     2709                 RTPathCompare(location.c_str(),
     2710                               Utf8Str((*it)->locationFull()).c_str()
     2711                              ) == 0);
    28992712        if (found)
    29002713        {
     
    29102723    {
    29112724        if (aId)
    2912             setError (rc, tr ("Could not find a floppy image with UUID {%RTuuid} "
    2913                               "in the media registry ('%ls')"),
    2914                       aId->raw(), mData.mCfgFile.mName.raw());
     2725            setError(rc,
     2726                     tr("Could not find a floppy image with UUID {%RTuuid} in the media registry ('%s')"),
     2727                     aId->raw(),
     2728                     m_strSettingsFilePath.raw());
    29152729        else
    2916             setError (rc, tr ("Could not find a floppy image with location '%ls' "
    2917                               "in the media registry ('%ls')"),
    2918                       aLocation, mData.mCfgFile.mName.raw());
     2730            setError(rc,
     2731                     tr("Could not find a floppy image with location '%ls' in the media registry ('%s')"),
     2732                     aLocation,
     2733                     m_strSettingsFilePath.raw());
    29192734    }
    29202735
    29212736    return rc;
     2737}
     2738
     2739/**
     2740 * Returns the default machine folder from the system properties
     2741 * with proper locking.
     2742 * @return
     2743 */
     2744const Utf8Str& VirtualBox::getDefaultMachineFolder() const
     2745{
     2746    AutoReadLock propsLock(mData.mSystemProperties);
     2747    return mData.mSystemProperties->m_strDefaultMachineFolder;
     2748}
     2749
     2750/**
     2751 * Returns the default hard disk folder from the system properties
     2752 * with proper locking.
     2753 * @return
     2754 */
     2755const Utf8Str& VirtualBox::getDefaultHardDiskFolder() const
     2756{
     2757    AutoReadLock propsLock(mData.mSystemProperties);
     2758    return mData.mSystemProperties->m_strDefaultHardDiskFolder;
     2759}
     2760
     2761/**
     2762 * Returns the default hard disk format from the system properties
     2763 * with proper locking.
     2764 * @return
     2765 */
     2766const Utf8Str& VirtualBox::getDefaultHardDiskFormat() const
     2767{
     2768    AutoReadLock propsLock(mData.mSystemProperties);
     2769    return mData.mSystemProperties->m_strDefaultHardDiskFormat;
    29222770}
    29232771
     
    29332781 * @note Doesn't lock any object.
    29342782 */
    2935 int VirtualBox::calculateFullPath (const char *aPath, Utf8Str &aResult)
     2783int VirtualBox::calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult)
    29362784{
    29372785    AutoCaller autoCaller(this);
     
    29402788    /* no need to lock since mHomeDir is const */
    29412789
    2942     char folder [RTPATH_MAX];
    2943     int vrc = RTPathAbsEx (mData.mHomeDir, aPath, folder, sizeof (folder));
     2790    char folder[RTPATH_MAX];
     2791    int vrc = RTPathAbsEx(mData.mHomeDir.c_str(), strPath.c_str(), folder, sizeof(folder));
    29442792    if (RT_SUCCESS(vrc))
    29452793        aResult = folder;
     
    29592807 * @note Doesn't lock any object.
    29602808 */
    2961 void VirtualBox::calculateRelativePath (const char *aPath, Utf8Str &aResult)
     2809void VirtualBox::calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult)
    29622810{
    29632811    AutoCaller autoCaller(this);
     
    29682816    Utf8Str settingsDir = mData.mHomeDir;
    29692817
    2970     if (RTPathStartsWith (aPath, settingsDir))
     2818    if (RTPathStartsWith(strPath.c_str(), settingsDir.c_str()))
    29712819    {
    29722820        /* when assigning, we create a separate Utf8Str instance because both
     
    29752823         * first, and since its the same as aPath, an attempt to copy garbage
    29762824         * will be made. */
    2977         aResult = Utf8Str (aPath + settingsDir.length() + 1);
     2825        aResult = Utf8Str(strPath.c_str() + settingsDir.length() + 1);
    29782826    }
    29792827}
     
    30542902
    30552903/**
    3056  *  Reads in the machine definitions from the configuration loader
    3057  *  and creates the relevant objects.
    3058  *
    3059  *  @param aGlobal  <Global> node.
    3060  *
    3061  *  @note Can be called only from #init().
    3062  *  @note Doesn't lock anything.
    3063  */
    3064 HRESULT VirtualBox::loadMachines (const settings::Key &aGlobal)
    3065 {
    3066     using namespace settings;
    3067 
    3068     AutoCaller autoCaller(this);
    3069     AssertReturn(autoCaller.state() == InInit, E_FAIL);
    3070 
    3071     HRESULT rc = S_OK;
    3072 
    3073     Key::List machines = aGlobal.key ("MachineRegistry").keys ("MachineEntry");
    3074     for (Key::List::const_iterator it = machines.begin();
    3075          it != machines.end(); ++ it)
    3076     {
    3077         /* required */
    3078         Guid uuid = (*it).value <Guid> ("uuid");
    3079         /* required */
    3080         Bstr src = (*it).stringValue ("src");
    3081 
    3082         /* create a new machine object */
    3083         ComObjPtr<Machine> machine;
    3084         rc = machine.createObject();
    3085         if (SUCCEEDED(rc))
    3086         {
    3087             /* initialize the machine object and register it */
    3088             rc = machine->init (this, src, Machine::Init_Registered,
    3089                                 NULL, NULL, FALSE, &uuid);
    3090             if (SUCCEEDED(rc))
    3091                 rc = registerMachine (machine);
    3092         }
    3093     }
    3094 
    3095     return rc;
    3096 }
    3097 
    3098 /**
    3099  *  Reads in the media registration entries from the global settings file
    3100  *  and creates the relevant objects.
    3101  *
    3102  *  @param aGlobal  <Global> node
    3103  *
    3104  *  @note Can be called only from #init().
    3105  *  @note Doesn't lock anything.
    3106  */
    3107 HRESULT VirtualBox::loadMedia (const settings::Key &aGlobal)
    3108 {
    3109     using namespace settings;
    3110 
    3111     AutoCaller autoCaller(this);
    3112     AssertReturn(autoCaller.state() == InInit, E_FAIL);
    3113 
    3114     HRESULT rc = S_OK;
    3115 
    3116     Key registry = aGlobal.key ("MediaRegistry");
    3117 
    3118     const char *kMediaNodes[] = { "HardDisks", "DVDImages", "FloppyImages" };
    3119 
    3120     for (size_t n = 0; n < RT_ELEMENTS (kMediaNodes); ++ n)
    3121     {
    3122         /* All three media nodes are optional */
    3123         Key node = registry.findKey (kMediaNodes [n]);
    3124         if (node.isNull())
    3125             continue;
    3126 
    3127         if (n == 0)
    3128         {
    3129             Key::List hardDisks = node.keys ("HardDisk");
    3130             for (Key::List::const_iterator it = hardDisks.begin();
    3131                  it != hardDisks.end(); ++ it)
    3132             {
    3133                 ComObjPtr<HardDisk> hardDisk;
    3134                 hardDisk.createObject();
    3135                 rc = hardDisk->init(this, NULL, *it);
    3136                 CheckComRCBreakRC (rc);
    3137 
    3138                 rc = registerHardDisk(hardDisk, false /* aSaveRegistry */);
    3139                 CheckComRCBreakRC (rc);
    3140             }
    3141 
    3142             continue;
    3143         }
    3144 
    3145         CheckComRCBreakRC (rc);
    3146 
    3147         Key::List images = node.keys ("Image");
    3148         for (Key::List::const_iterator it = images.begin();
    3149              it != images.end(); ++ it)
    3150         {
    3151             switch (n)
    3152             {
    3153                 case 1: /* DVDImages */
    3154                 {
    3155                     ComObjPtr<DVDImage> image;
    3156                     image.createObject();
    3157                     rc = image->init (this, *it);
    3158                     CheckComRCBreakRC (rc);
    3159 
    3160                     rc = registerDVDImage (image, false /* aSaveRegistry */);
    3161                     CheckComRCBreakRC (rc);
    3162 
    3163                     break;
    3164                 }
    3165                 case 2: /* FloppyImages */
    3166                 {
    3167                     ComObjPtr<FloppyImage> image;
    3168                     image.createObject();
    3169                     rc = image->init (this, *it);
    3170                     CheckComRCBreakRC (rc);
    3171 
    3172                     rc = registerFloppyImage (image, false /* aSaveRegistry */);
    3173                     CheckComRCBreakRC (rc);
    3174 
    3175                     break;
    3176                 }
    3177                 default:
    3178                     AssertFailed();
    3179             }
    3180 
    3181             CheckComRCBreakRC (rc);
    3182         }
    3183 
    3184         CheckComRCBreakRC (rc);
    3185     }
    3186 
    3187     return rc;
    3188 }
    3189 
    3190 /**
    3191  *  Reads in the network service registration entries from the global settings file
    3192  *  and creates the relevant objects.
    3193  *
    3194  *  @param aGlobal  <Global> node
    3195  *
    3196  *  @note Can be called only from #init().
    3197  *  @note Doesn't lock anything.
    3198  */
    3199 HRESULT VirtualBox::loadNetservices (const settings::Key &aGlobal)
    3200 {
    3201     using namespace settings;
    3202 
    3203     AutoCaller autoCaller(this);
    3204     AssertReturn(autoCaller.state() == InInit, E_FAIL);
    3205 
    3206     HRESULT rc = S_OK;
    3207 
    3208     Key registry = aGlobal.findKey ("NetserviceRegistry");
    3209     if(registry.isNull())
    3210         return S_OK;
    3211 
    3212     const char *kMediaNodes[] = { "DHCPServers" };
    3213 
    3214     for (size_t n = 0; n < RT_ELEMENTS (kMediaNodes); ++ n)
    3215     {
    3216         /* All three media nodes are optional */
    3217         Key node = registry.findKey (kMediaNodes [n]);
    3218         if (node.isNull())
    3219             continue;
    3220 
    3221         if (n == 0)
    3222         {
    3223             Key::List dhcpServers = node.keys ("DHCPServer");
    3224             for (Key::List::const_iterator it = dhcpServers.begin();
    3225                  it != dhcpServers.end(); ++ it)
    3226             {
    3227                 ComObjPtr<DHCPServer> dhcpServer;
    3228                 dhcpServer.createObject();
    3229                 rc = dhcpServer->init (this, *it);
    3230                 CheckComRCBreakRC (rc);
    3231 
    3232                 rc = registerDHCPServer(dhcpServer, false /* aSaveRegistry */);
    3233                 CheckComRCBreakRC (rc);
    3234             }
    3235 
    3236             continue;
    3237         }
    3238     }
    3239    return rc;
    3240 }
    3241 
    3242 /**
    32432904 *  Helper function to write out the configuration tree.
    32442905 *
     
    32472908HRESULT VirtualBox::saveSettings()
    32482909{
    3249     AutoCaller autoCaller(this);
    3250     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    3251 
    3252     AssertReturn(!!mData.mCfgFile.mName, E_FAIL);
     2910    AutoCaller autoCaller (this);
     2911    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
     2912
     2913    AssertReturn(!m_strSettingsFilePath.isEmpty(), E_FAIL);
    32532914
    32542915    HRESULT rc = S_OK;
     
    32592920    try
    32602921    {
    3261         using namespace settings;
    3262         using namespace xml;
    3263 
    3264         /* load the settings file */
    3265         File file (mData.mCfgFile.mHandle, Utf8Str (mData.mCfgFile.mName));
    3266         XmlTreeBackend tree;
    3267 
    3268         rc = VirtualBox::loadSettingsTree_ForUpdate (tree, file);
    3269         CheckComRCThrowRC (rc);
    3270 
    3271         Key global = tree.rootKey().createKey ("Global");
    3272 
    3273         /* machines */
    3274         {
    3275             /* first, delete the entire machine registry */
    3276             Key registryNode = global.findKey ("MachineRegistry");
    3277             if (!registryNode.isNull())
    3278                 registryNode.zap();
    3279             /* then, recreate it */
    3280             registryNode = global.createKey ("MachineRegistry");
    3281 
    3282             /* write out the machines */
    3283             for (MachineList::iterator it = mData.mMachines.begin();
    3284                  it != mData.mMachines.end();
    3285                  ++ it)
    3286             {
    3287                 Key entryNode = registryNode.appendKey ("MachineEntry");
    3288                 rc = (*it)->saveRegistryEntry (entryNode);
    3289                 CheckComRCThrowRC (rc);
    3290             }
    3291         }
    3292 
    3293         /* media */
    3294         {
    3295             /* first, delete the entire media registry */
    3296             Key registryNode = global.findKey ("MediaRegistry");
    3297             if (!registryNode.isNull())
    3298                 registryNode.zap();
    3299             /* then, recreate it */
    3300             registryNode = global.createKey ("MediaRegistry");
    3301 
    3302             /* hard disks */
    3303             {
    3304                 Key hardDisksNode = registryNode.createKey ("HardDisks");
    3305 
    3306                 for (HardDiskList::const_iterator it =
    3307                         mData.mHardDisks.begin();
    3308                      it != mData.mHardDisks.end();
    3309                      ++ it)
    3310                 {
    3311                     rc = (*it)->saveSettings (hardDisksNode);
    3312                     CheckComRCThrowRC (rc);
    3313                 }
    3314             }
    3315 
    3316             /* CD/DVD images */
    3317             {
    3318                 Key imagesNode = registryNode.createKey ("DVDImages");
    3319 
    3320                 for (DVDImageList::const_iterator it =
    3321                         mData.mDVDImages.begin();
    3322                      it != mData.mDVDImages.end();
    3323                      ++ it)
    3324                 {
    3325                     rc = (*it)->saveSettings (imagesNode);
    3326                     CheckComRCThrowRC (rc);
    3327                 }
    3328             }
    3329 
    3330             /* floppy images */
    3331             {
    3332                 Key imagesNode = registryNode.createKey ("FloppyImages");
    3333 
    3334                 for (FloppyImageList::const_iterator it =
    3335                         mData.mFloppyImages.begin();
    3336                      it != mData.mFloppyImages.end();
    3337                      ++ it)
    3338                 {
    3339                     rc = (*it)->saveSettings (imagesNode);
    3340                     CheckComRCThrowRC (rc);
    3341                 }
    3342             }
    3343         }
    3344 
    3345         /* netservices */
    3346         {
    3347             /* first, delete the entire netservice registry */
    3348             Key registryNode = global.findKey ("NetserviceRegistry");
    3349             if (!registryNode.isNull())
    3350                 registryNode.zap();
    3351             /* then, recreate it */
    3352             registryNode = global.createKey ("NetserviceRegistry");
    3353 
    3354             /* hard disks */
    3355             {
    3356                 Key dhcpServersNode = registryNode.createKey ("DHCPServers");
    3357 
    3358                 for (DHCPServerList::const_iterator it =
    3359                         mData.mDHCPServers.begin();
    3360                      it != mData.mDHCPServers.end();
    3361                      ++ it)
    3362                 {
    3363                     rc = (*it)->saveSettings (dhcpServersNode);
    3364                     CheckComRCThrowRC (rc);
    3365                 }
    3366             }
     2922        // machines
     2923        m_pMainConfigFile->llMachines.clear();
     2924        for (MachineList::iterator it = mData.mMachines.begin();
     2925             it != mData.mMachines.end();
     2926             ++it)
     2927        {
     2928            settings::MachineRegistryEntry mre;
     2929            rc = (*it)->saveRegistryEntry(mre);
     2930            m_pMainConfigFile->llMachines.push_back(mre);
     2931        }
     2932
     2933        // hard disks
     2934        m_pMainConfigFile->llHardDisks.clear();
     2935        for (HardDiskList::const_iterator it = mData.mHardDisks.begin();
     2936             it != mData.mHardDisks.end();
     2937             ++it)
     2938        {
     2939            settings::Medium m;
     2940            rc = (*it)->saveSettings(m);
     2941            m_pMainConfigFile->llHardDisks.push_back(m);
     2942            CheckComRCThrowRC(rc);
     2943        }
     2944
     2945        /* CD/DVD images */
     2946        m_pMainConfigFile->llDvdImages.clear();
     2947        for (DVDImageList::const_iterator it = mData.mDVDImages.begin();
     2948             it != mData.mDVDImages.end();
     2949             ++it)
     2950        {
     2951            settings::Medium m;
     2952            rc = (*it)->saveSettings(m);
     2953            CheckComRCThrowRC(rc);
     2954            m_pMainConfigFile->llDvdImages.push_back(m);
     2955        }
     2956
     2957        /* floppy images */
     2958        m_pMainConfigFile->llFloppyImages.clear();
     2959        for (FloppyImageList::const_iterator it = mData.mFloppyImages.begin();
     2960             it != mData.mFloppyImages.end();
     2961             ++it)
     2962        {
     2963            settings::Medium m;
     2964            rc = (*it)->saveSettings(m);
     2965            CheckComRCThrowRC(rc);
     2966            m_pMainConfigFile->llFloppyImages.push_back(m);
     2967        }
     2968
     2969        m_pMainConfigFile->llDhcpServers.clear();
     2970        for (DHCPServerList::const_iterator it =
     2971                mData.mDHCPServers.begin();
     2972                it != mData.mDHCPServers.end();
     2973                ++ it)
     2974        {
     2975            settings::DHCPServer d;
     2976            rc = (*it)->saveSettings(d);
     2977            CheckComRCThrowRC(rc);
     2978            m_pMainConfigFile->llDhcpServers.push_back(d);
    33672979        }
    33682980
    33692981        /* host data (USB filters) */
    3370         rc = mData.mHost->saveSettings (global);
    3371         CheckComRCThrowRC (rc);
    3372 
    3373         rc = mData.mSystemProperties->saveSettings (global);
    3374         CheckComRCThrowRC (rc);
    3375 
    3376         /* save the settings on success */
    3377         rc = VirtualBox::saveSettingsTree (tree, file,
    3378                                            mData.mSettingsFileVersion);
    3379         CheckComRCThrowRC (rc);
     2982        rc = mData.mHost->saveSettings(m_pMainConfigFile->host);
     2983        CheckComRCThrowRC(rc);
     2984
     2985        rc = mData.mSystemProperties->saveSettings(m_pMainConfigFile->systemProperties);
     2986        CheckComRCThrowRC(rc);
     2987
     2988        // now write out the XML
     2989        m_pMainConfigFile->write();
    33802990    }
    33812991    catch (HRESULT err)
     
    34443054
    34453055    /* add to the collection of registered machines */
    3446     mData.mMachines.push_back (aMachine);
     3056    mData.mMachines.push_back(aMachine);
    34473057
    34483058    if (autoCaller.state() != InInit)
     
    34913101    {
    34923102        return setError(E_INVALIDARG,
    3493                         tr("Cannot register the hard disk '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%ls')"),
     3103                        tr("Cannot register the hard disk '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    34943104                        aHardDisk->locationFull().raw(),
    34953105                        aHardDisk->id().raw(),
    34963106                        strConflict.raw(),
    3497                         mData.mCfgFile.mName.raw());
     3107                        m_strSettingsFilePath.raw());
    34983108    }
    34993109
     
    36093219    {
    36103220        return setError(VBOX_E_INVALID_OBJECT_STATE,
    3611                         tr("Cannot register the CD/DVD image '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%ls')"),
     3221                        tr("Cannot register the CD/DVD image '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    36123222                        aImage->locationFull().raw(),
    36133223                        aImage->id().raw(),
    36143224                        strConflict.raw(),
    3615                         mData.mCfgFile.mName.raw());
     3225                        m_strSettingsFilePath.raw());
    36163226    }
    36173227
     
    37123322    {
    37133323        return setError(VBOX_E_INVALID_OBJECT_STATE,
    3714                         tr("Cannot register the floppy image '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%ls')"),
     3324                        tr("Cannot register the floppy image '%ls' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    37153325                        aImage->locationFull().raw(),
    37163326                        aImage->id().raw(),
    37173327                        strConflict.raw(),
    3718                         mData.mCfgFile.mName.raw());
     3328                        m_strSettingsFilePath.raw());
    37193329    }
    37203330
     
    37263336        rc = saveSettings();
    37273337        if (FAILED (rc))
    3728             unregisterFloppyImage (aImage, false /* aSaveRegistry */);
     3338            unregisterFloppyImage(aImage, false /* aSaveRegistry */);
    37293339    }
    37303340
     
    38743484 */
    38753485/* static */
    3876 HRESULT VirtualBox::ensureFilePathExists (const char *aFileName)
    3877 {
    3878     Utf8Str strDir(aFileName);
     3486HRESULT VirtualBox::ensureFilePathExists(const Utf8Str &strFileName)
     3487{
     3488    Utf8Str strDir(strFileName);
    38793489    strDir.stripFilename();
    3880     if (!RTDirExists(strDir))
    3881     {
    3882         int vrc = RTDirCreateFullPath(strDir, 0777);
     3490    if (!RTDirExists(strDir.c_str()))
     3491    {
     3492        int vrc = RTDirCreateFullPath(strDir.c_str(), 0777);
    38833493        if (RT_FAILURE(vrc))
    3884         {
    3885             return setError (E_FAIL,
    3886                 tr ("Could not create the directory '%s' (%Rrc)"),
    3887                 strDir.c_str(), vrc);
    3888         }
    3889     }
    3890 
    3891     return S_OK;
    3892 }
    3893 
    3894 /**
    3895  * Helper method to load the setting tree and turn expected exceptions into
    3896  * COM errors, according to arguments.
    3897  *
    3898  * Note that this method will not catch unexpected errors so it may still
    3899  * throw something.
    3900  *
    3901  * @param aTree             Tree to load into settings.
    3902  * @param aFile             File to load settings from.
    3903  * @param aValidate         @c @true to enable tree validation.
    3904  * @param aCatchLoadErrors  @c true to catch exceptions caused by file
    3905  *                          access or validation errors.
    3906  * @param aAddDefaults      @c true to cause the substitution of default
    3907  *                          values for missing attributes that have
    3908  *                          defaults in the XML schema.
    3909  * @param aFormatVersion    Where to store the current format version of the
    3910  *                          loaded settings tree (optional, may be NULL).
    3911  */
    3912 /* static */
    3913 HRESULT VirtualBox::loadSettingsTree (settings::XmlTreeBackend &aTree,
    3914                                       xml::File &aFile,
    3915                                       bool aValidate,
    3916                                       bool aCatchLoadErrors,
    3917                                       bool aAddDefaults,
    3918                                       Utf8Str *aFormatVersion /* = NULL */)
    3919 {
    3920     using namespace settings;
    3921 
    3922     try
    3923     {
    3924         SettingsTreeHelper helper = SettingsTreeHelper();
    3925 
    3926         aTree.setInputResolver (helper);
    3927         aTree.setAutoConverter (helper);
    3928 
    3929         aTree.read (aFile, aValidate ? VBOX_XML_SCHEMA : NULL,
    3930                     aAddDefaults ? XmlTreeBackend::Read_AddDefaults : 0);
    3931 
    3932         aTree.resetAutoConverter();
    3933         aTree.resetInputResolver();
    3934 
    3935         /* on success, memorize the current settings file version or set it to
    3936          * the most recent version if no settings conversion took place. Note
    3937          * that it's not necessary to do it every time we load the settings file
    3938          * (i.e. only loadSettingsTree_FirstTime() passes a non-NULL
    3939          * aFormatVersion value) because currently we keep the settings
    3940          * files locked so that the only legal way to change the format version
    3941          * while VirtualBox is running is saveSettingsTree(). */
    3942         if (aFormatVersion != NULL)
    3943         {
    3944             *aFormatVersion = aTree.oldVersion();
    3945             if (!aFormatVersion->length())
    3946                 *aFormatVersion = VBOX_XML_VERSION_FULL;
    3947         }
    3948     }
    3949     catch (const xml::EIPRTFailure &err)
    3950     {
    3951         if (!aCatchLoadErrors)
    3952             throw;
    3953 
    3954         return setError (VBOX_E_FILE_ERROR,
    3955                          tr ("Could not load the settings file '%s' (%Rrc)"),
    3956                          aFile.uri(), err.rc());
    3957     }
    3958     catch (const xml::RuntimeError &err)
    3959     {
    3960         Assert (err.what() != NULL);
    3961 
    3962         if (!aCatchLoadErrors)
    3963             throw;
    3964 
    3965         return setError (VBOX_E_XML_ERROR,
    3966                          tr ("Could not load the settings file '%s'.\n%s"),
    3967                          aFile.uri(),
    3968                          err.what() ? err.what() : "Unknown error");
    3969     }
    3970 
    3971     return S_OK;
    3972 }
    3973 
    3974 /**
    3975  * Helper method to save the settings tree and turn expected exceptions to COM
    3976  * errors.
    3977  *
    3978  * Note that this method will not catch unexpected errors so it may still
    3979  * throw something.
    3980  *
    3981  * @param aTree             Tree to save.
    3982  * @param aFile             File to save the tree to.
    3983  * @param aFormatVersion    Where to store the (recent) format version of the
    3984  *                          saved settings tree on success.
    3985  */
    3986 /* static */
    3987 HRESULT VirtualBox::saveSettingsTree (settings::TreeBackend &aTree,
    3988                                       xml::File &aFile,
    3989                                       Utf8Str &aFormatVersion)
    3990 {
    3991     using namespace settings;
    3992 
    3993     try
    3994     {
    3995         aTree.write (aFile);
    3996 
    3997         /* set the current settings file version to the most recent version on
    3998          * success. See also VirtualBox::loadSettingsTree(). */
    3999         if (aFormatVersion != VBOX_XML_VERSION_FULL)
    4000             aFormatVersion = VBOX_XML_VERSION_FULL;
    4001     }
    4002     catch (const xml::EIPRTFailure &err)
    4003     {
    4004         /* this is the only expected exception for now */
    4005         return setError (VBOX_E_FILE_ERROR,
    4006                          tr ("Could not save the settings file '%s' (%Rrc)"),
    4007                          aFile.uri(), err.rc());
    4008     }
    4009 
    4010     return S_OK;
    4011 }
    4012 
    4013 /**
    4014  * Creates a backup copy of the given settings file by suffixing it with the
    4015  * supplied version format string and optionally with numbers from .0 to .9
    4016  * if the backup file already exists.
    4017  *
    4018  * @param aFileName     Original settings file name.
    4019  * @param aOldFormat    Version of the original format.
    4020  * @param aBakFileName  File name of the created backup copy (only on success).
    4021  */
    4022 /* static */
    4023 HRESULT VirtualBox::backupSettingsFile (const Bstr &aFileName,
    4024                                         const Utf8Str &aOldFormat,
    4025                                         Bstr &aBakFileName)
    4026 {
    4027     Utf8Str of = aFileName;
    4028     Utf8Str nf = Utf8StrFmt ("%s.%s.bak", of.raw(), aOldFormat.raw());
    4029 
    4030     int vrc = RTFileCopyEx (of, nf, RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE,
    4031                             NULL, NULL);
    4032 
    4033     /* try progressive suffix from .0 to .9 on failure */
    4034     if (vrc == VERR_ALREADY_EXISTS)
    4035     {
    4036         Utf8Str tmp = nf;
    4037         for (int i = 0; i <= 9 && RT_FAILURE(vrc); ++ i)
    4038         {
    4039             nf = Utf8StrFmt ("%s.%d", tmp.raw(), i);
    4040             vrc = RTFileCopyEx (of, nf, RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE,
    4041                                 NULL, NULL);
    4042         }
    4043     }
    4044 
    4045     if (RT_FAILURE(vrc))
    4046         return setError (VBOX_E_IPRT_ERROR,
    4047             tr ("Could not copy the settings file '%s' to '%s' (%Rrc)"),
    4048             of.raw(), nf.raw(), vrc);
    4049 
    4050     aBakFileName = nf;
     3494            return setError(E_FAIL,
     3495                            tr("Could not create the directory '%s' (%Rrc)"),
     3496                            strDir.c_str(),
     3497                            vrc);
     3498    }
    40513499
    40523500    return S_OK;
     
    40763524 */
    40773525/* static */
    4078 HRESULT VirtualBox::handleUnexpectedExceptions (RT_SRC_POS_DECL)
     3526HRESULT VirtualBox::handleUnexpectedExceptions(RT_SRC_POS_DECL)
    40793527{
    40803528    try
     
    40853533    catch (const std::exception &err)
    40863534    {
    4087         ComAssertMsgFailedPos (("Unexpected exception '%s' (%s)",
    4088                                 typeid (err).name(), err.what()),
    4089                                pszFile, iLine, pszFunction);
    4090         return E_FAIL;
     3535        return setError(E_FAIL, tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
     3536                                err.what(), typeid(err).name(),
     3537                                pszFile, iLine, pszFunction);
    40913538    }
    40923539    catch (...)
    40933540    {
    4094         ComAssertMsgFailedPos (("Unknown exception"),
    4095                                pszFile, iLine, pszFunction);
    4096         return E_FAIL;
     3541        return setError(E_FAIL, tr("Unknown exception\n%s[%d] (%s)"),
     3542                                pszFile, iLine, pszFunction);
    40973543    }
    40983544
     
    41003546    AssertFailed();
    41013547    return E_FAIL;
    4102 }
    4103 
    4104 /**
    4105  *  Helper to lock the VirtualBox configuration for write access.
    4106  *
    4107  *  @note This method is not thread safe (must be called only from #init()
    4108  *  or #uninit()).
    4109  *
    4110  *  @note If the configuration file is not found, the method returns
    4111  *  S_OK, but subsequent #isConfigLocked() will return FALSE. This is used
    4112  *  in some places to determine the (valid) situation when no config file
    4113  *  exists yet, and therefore a new one should be created from scratch.
    4114  */
    4115 HRESULT VirtualBox::lockConfig()
    4116 {
    4117     AutoCaller autoCaller(this);
    4118     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    4119     AssertReturn(autoCaller.state() == InInit, E_FAIL);
    4120 
    4121     HRESULT rc = S_OK;
    4122 
    4123     Assert (!isConfigLocked());
    4124     if (!isConfigLocked())
    4125     {
    4126         /* Open the associated config file. */
    4127         int vrc = RTFileOpen (&mData.mCfgFile.mHandle,
    4128                               Utf8Str (mData.mCfgFile.mName),
    4129                               RTFILE_O_READWRITE | RTFILE_O_OPEN |
    4130                               RTFILE_O_DENY_WRITE);
    4131         if (RT_FAILURE(vrc) && (vrc != VERR_FILE_NOT_FOUND))
    4132         {
    4133             /* Open the associated config file only with read access. */
    4134             vrc = RTFileOpen (&mData.mCfgFile.mHandle,
    4135                               Utf8Str (mData.mCfgFile.mName),
    4136                               RTFILE_O_READ | RTFILE_O_OPEN |
    4137                               RTFILE_O_DENY_NONE);
    4138             if (RT_FAILURE(vrc))
    4139             {
    4140                 /* We even cannot open it in read mode, so there's seriously
    4141                    something wrong. */
    4142                 rc = setError (E_FAIL,
    4143                         tr ("Could not even open settings file '%ls' in read mode (%Rrc)"),
    4144                         mData.mCfgFile.mName.raw(), vrc);
    4145             }
    4146             else
    4147             {
    4148                 mData.mCfgFile.mReadonly = TRUE;
    4149             }
    4150         }
    4151         else
    4152         {
    4153             mData.mCfgFile.mReadonly = FALSE;
    4154         }
    4155 
    4156         if (RT_FAILURE(vrc))
    4157         {
    4158             mData.mCfgFile.mHandle = NIL_RTFILE;
    4159             mData.mCfgFile.mReadonly = FALSE;
    4160         }
    4161 
    4162         LogFlowThisFunc(("mCfgFile.mName='%ls', mCfgFile.mHandle=%d, rc=%08X\n",
    4163                           mData.mCfgFile.mName.raw(), mData.mCfgFile.mHandle, rc));
    4164     }
    4165     return rc;
    4166 }
    4167 
    4168 /**
    4169  *  Helper to unlock the VirtualBox configuration from write access.
    4170  *
    4171  *  @note This method is not thread safe (must be called only from #init()
    4172  *  or #uninit()).
    4173  */
    4174 HRESULT VirtualBox::unlockConfig()
    4175 {
    4176     AutoCaller autoCaller(this);
    4177     AssertComRCReturn (autoCaller.rc(), E_FAIL);
    4178     AssertReturn(autoCaller.state() == InUninit, E_FAIL);
    4179 
    4180     HRESULT rc = S_OK;
    4181 
    4182     if (isConfigLocked())
    4183     {
    4184         RTFileFlush (mData.mCfgFile.mHandle);
    4185         RTFileClose (mData.mCfgFile.mHandle);
    4186         /** @todo flush the directory too. */
    4187         mData.mCfgFile.mHandle = NIL_RTFILE;
    4188         mData.mCfgFile.mReadonly = FALSE;
    4189         LogFlowThisFunc(("\n"));
    4190     }
    4191 
    4192     return rc;
    41933548}
    41943549
     
    47934148    {
    47944149        rc = (*it)->COMGETTER(NetworkName) (bstr.asOutParam());
    4795         CheckComRCThrowRC (rc);
     4150        CheckComRCThrowRC(rc);
    47964151
    47974152        if(bstr == aName)
  • trunk/src/VBox/Main/VirtualBoxImplExtra.cpp

    r21878 r22173  
    2424 */
    2525
    26 #include <VBox/settings.h>
    27 
    28 #include "VirtualBoxImpl.h"
    29 #include "VirtualBoxImplExtra.h"
    30 
    31 #include "VirtualBoxXMLUtil.h"
    32 
    33 /* embedded XML Schema documents for validating XML settings files */
    34 #include "xml_VirtualBox_settings_xsd.h"
    35 #include "xml_VirtualBox_settings_common_xsd.h"
    36 
    37 /* embedded settings converter template for updating settings files */
    38 #include "xml_SettingsConverter_xsl.h"
    39 
    40 /* embedded VirtualBox element definition that contains a proper 'version'
    41  * attribute constraint */
    42 static const unsigned char g_ab_xml_VirtualBox_settings_root_xsd[] =
    43 "<xsd:schema"
    44 "  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
    45 "  xmlns=\"http://www.innotek.de/VirtualBox-settings\""
    46 "  xmlns:vb=\"http://www.innotek.de/VirtualBox-settings\""
    47 "  targetNamespace=\"http://www.innotek.de/VirtualBox-settings\""
    48 "  elementFormDefault=\"qualified\""
    49 ">"
    50 "<xsd:element name=\"VirtualBox\">"
    51 "  <xsd:complexType>"
    52 "    <xsd:complexContent>"
    53 "      <xsd:extension base=\"TVirtualBox\">"
    54 "        <xsd:attribute name=\"version\" type=\"xsd:token\" fixed=\"" VBOX_XML_VERSION_FULL "\" use=\"required\"/>"
    55 "      </xsd:extension>"
    56 "    </xsd:complexContent>"
    57 "  </xsd:complexType>"
    58 "</xsd:element>"
    59 "</xsd:schema>";
    60 
    61 static const unsigned g_cb_xml_VirtualBox_settings_root_xsd =
    62     sizeof (g_ab_xml_VirtualBox_settings_root_xsd);
    63 
    64 /**
    65  * Resolves external entities while parting and validating XML settings files.
    66  *
    67  * @param aURI  URI of the external entity.
    68  * @param aID   ID of the external entity (may be NULL).
    69  *
    70  * @return      Input stream created using @c new or NULL to indicate
    71  *              a wrong URI/ID pair.
    72  */
    73 xml::Input *
    74 SettingsTreeHelper::resolveEntity (const char *aURI, const char * /* aID */)
    75 {
    76     if (strcmp (aURI, VBOX_XML_SCHEMA_COMMON) == 0)
    77     {
    78         return new xml::
    79             MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_common_xsd,
    80                        g_cb_xml_VirtualBox_settings_common_xsd, aURI);
    81     }
    82 
    83     if (strcmp (aURI, VBOX_XML_SCHEMA_ROOT) == 0)
    84     {
    85         return new xml::
    86             MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_root_xsd,
    87                        g_cb_xml_VirtualBox_settings_root_xsd, aURI);
    88     }
    89 
    90     if (strcmp (aURI, VBOX_XML_SCHEMA) == 0)
    91     {
    92         return new xml::
    93             MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_xsd,
    94                        g_cb_xml_VirtualBox_settings_xsd, aURI);
    95     }
    96 
    97     if (strcmp (aURI, VBOX_XML_SETTINGS_CONVERTER) == 0)
    98     {
    99         return new xml::
    100             MemoryBuf ((const char *) g_ab_xml_SettingsConverter_xsl,
    101                        g_cb_xml_SettingsConverter_xsl, aURI);
    102     }
    103 
    104     AssertMsgFailed (("Unexpected entity: '%s' - knows: '%s' and '%s'\n", aURI,
    105                       VBOX_XML_SCHEMA_COMMON, VBOX_XML_SCHEMA));
    106     return NULL;
    107 }
    108 
    109 /**
    110  * Returns @true if the given tree needs to be converted using the XSLT
    111  * template identified by #templateUri(), or @false if no conversion is
    112  * required.
    113  *
    114  * The implementation normally checks for the "version" value of the
    115  * root key to determine if the conversion is necessary. When the
    116  * @a aOldVersion argument is not NULL, the implementation must return a
    117  * non-NULL non-empty string representing the old version (before
    118  * conversion) in it this string is used by XmlTreeBackend::oldVersion()
    119  * and must be non-NULL to indicate that the conversion has been
    120  * performed on the tree. The returned string must be allocated using
    121  * RTStrDup() or such.
    122  *
    123  * This method is called again after the successful transformation to
    124  * let the implementation retry the version check and request another
    125  * transformation if necessary. This may be used to perform multi-step
    126  * conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3)
    127  * which saves from the need to update all previous conversion
    128  * templates to make each of them convert directly to the recent
    129  * version.
    130  *
    131  * @note Multi-step transformations are performed in a loop that exits
    132  *       only when this method returns @false. It's up to the
    133  *       implementation to detect cycling (repeated requests to convert
    134  *       from the same version) wrong version order, etc. and throw an
    135  *       EConversionCycle exception to break the loop without returning
    136  *       @false (which means the transformation succeeded).
    137  *
    138  * @param aRoot                 Root settings key.
    139  * @param aOldVersionString     Where to store old version string
    140  *                              pointer. May be NULL. Allocated memory is
    141  *                              freed by the caller using RTStrFree().
    142  */
    143 bool SettingsTreeHelper::
    144 needsConversion (const settings::Key &aRoot, char **aOldVersion) const
    145 {
    146     if (strcmp (aRoot.name(), "VirtualBox") == 0)
    147     {
    148         const char *version = aRoot.stringValue ("version");
    149         const char *dash = strchr (version, '-');
    150         if (dash != NULL && strcmp (dash + 1, VBOX_XML_PLATFORM) == 0)
    151         {
    152             if (strcmp (version, VBOX_XML_VERSION_FULL) != 0)
    153             {
    154                 /* version mismatch */
    155                 if (aOldVersion != NULL)
    156                     *aOldVersion = RTStrDup (version);
    157 
    158                 return true;
    159             }
    160         }
    161     }
    162 
    163     /* either the tree is invalid, or it's the other platform, or it's the same
    164      * version */
    165     return false;
    166 }
    167 
    168 /**
    169  * Returns the URI of the XSLT template to perform the conversion.
    170  * This template will be applied to the tree if #needsConversion()
    171  * returns @c true for this tree.
    172  */
    173 const char* SettingsTreeHelper::templateUri() const
    174 {
    175     return VBOX_XML_SETTINGS_CONVERTER;
    176 }
    177 
    178 #if defined VBOX_MAIN_SETTINGS_ADDONS
    179 
    180 // Settings API additions
    181 ////////////////////////////////////////////////////////////////////////////////
    182 
    183 namespace settings
    184 {
    185 
    186 template<> stdx::char_auto_ptr
    187 ToString <com::Bstr> (const com::Bstr &aValue, unsigned int /* aExtra */)
    188 {
    189     stdx::char_auto_ptr result;
    190 
    191     if (aValue.raw() == NULL)
    192         throw ENoValue();
    193 
    194     /* The only way to cause RTUtf16ToUtf8Ex return a number of bytes needed
    195      * w/o allocating the result buffer itself is to provide that both cch
    196      * and *ppsz are not NULL. */
    197     char dummy [1];
    198     char *dummy2 = dummy;
    199     size_t strLen = 1;
    200 
    201     int vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX,
    202                                &dummy2, strLen, &strLen);
    203     if (RT_SUCCESS(vrc))
    204     {
    205         /* the string only contains '\0' :) */
    206         result.reset (new char [1]);
    207         result.get() [0] = '\0';
    208         return result;
    209     }
    210 
    211     if (vrc == VERR_BUFFER_OVERFLOW)
    212     {
    213         result.reset (new char [strLen + 1]);
    214         char *buf = result.get();
    215         vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX, &buf, strLen + 1, NULL);
    216     }
    217 
    218     if (RT_FAILURE(vrc))
    219         throw xml::LogicError (RT_SRC_POS);
    220 
    221     return result;
    222 }
    223 
    224 template<> com::Guid FromString <com::Guid> (const char *aValue)
    225 {
    226     if (aValue == NULL)
    227         throw ENoValue();
    228 
    229     /* For settings, the format is always {XXX...XXX} */
    230     char buf [RTUUID_STR_LENGTH];
    231     if (aValue == NULL || *aValue != '{' ||
    232         strlen (aValue) != RTUUID_STR_LENGTH + 1 ||
    233         aValue [RTUUID_STR_LENGTH] != '}')
    234         throw ENoConversion(com::Utf8StrFmt("'%s' is not Guid", aValue));
    235 
    236     /* strip { and } */
    237     memcpy (buf, aValue + 1, RTUUID_STR_LENGTH - 1);
    238     buf [RTUUID_STR_LENGTH - 1] = '\0';
    239     /* we don't use Guid (const char *) because we want to throw
    240      * ENoConversion on format error */
    241     RTUUID uuid;
    242     int vrc = RTUuidFromStr (&uuid, buf);
    243     if (RT_FAILURE(vrc))
    244         throw ENoConversion(com::Utf8StrFmt("'%s' is not Guid (%Rrc)", aValue, vrc));
    245 
    246     return com::Guid (uuid);
    247 }
    248 
    249 template<> stdx::char_auto_ptr
    250 ToString <com::Guid> (const com::Guid &aValue, unsigned int /* aExtra */)
    251 {
    252     /* For settings, the format is always {XXX...XXX} */
    253     stdx::char_auto_ptr result (new char [RTUUID_STR_LENGTH + 2]);
    254 
    255     int vrc = RTUuidToStr (aValue.raw(), result.get() + 1, RTUUID_STR_LENGTH);
    256     if (RT_FAILURE(vrc))
    257         throw xml::LogicError (RT_SRC_POS);
    258 
    259     result.get() [0] = '{';
    260     result.get() [RTUUID_STR_LENGTH] = '}';
    261     result.get() [RTUUID_STR_LENGTH + 1] = '\0';
    262 
    263     return result;
    264 }
    265 
    266 #endif // VBOX_MAIN_SETTINGS_ADDONS
    267 
    268 } /* namespace settings */
    269 
    270 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/generic/NetIf-generic.cpp

    r21886 r22173  
    8080    pIf->COMGETTER(Name)(interfaceName.asOutParam());
    8181    Utf8Str strName(interfaceName);
    82     return NetIfAdpCtl(strName, pszAddr, pszOption, pszMask);
     82    return NetIfAdpCtl(strName.c_str(), pszAddr, pszOption, pszMask);
    8383}
    8484
     
    242242            progress.queryInterfaceTo(aProgress);
    243243            iface.queryInterfaceTo(aHostNetworkInterface);
    244             rc = NetIfAdpCtl(Utf8Str(ifname), "remove", NULL, NULL);
     244            rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL);
    245245            if (RT_FAILURE(rc))
    246246                progress->notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getComponentName(), "Failed to execute '"VBOXNETADPCTL_NAME "' (exit status: %d)", rc);
  • trunk/src/VBox/Main/glue/SupportErrorInfo.cpp

    r21878 r22173  
    9898 */
    9999/* static */
    100 HRESULT SupportErrorInfoBase::setErrorInternal (
    101     HRESULT aResultCode, const GUID *aIID,
    102     const char *aComponent, const char *aText,
    103     bool aWarning, IVirtualBoxErrorInfo *aInfo /*= NULL*/)
     100HRESULT SupportErrorInfoBase::setErrorInternal(HRESULT aResultCode,
     101                                               const GUID *aIID,
     102                                               const char *aComponent,
     103                                               const Utf8Str &strText,
     104                                               bool aWarning,
     105                                               IVirtualBoxErrorInfo *aInfo /*= NULL*/)
    104106{
    105107    /* whether multi-error mode is turned on */
    106108    bool preserve = ((uintptr_t) RTTlsGet (MultiResult::sCounter)) > 0;
    107109
    108     LogRel (("ERROR [COM]: aRC=%#08x aIID={%Vuuid} aComponent={%s} aText={%s} "
    109              "aWarning=%RTbool, aInfo=%p, preserve=%RTbool\n",
    110              aResultCode, aIID, aComponent, aText, aWarning, aInfo,
    111              preserve));
     110    LogRel(("ERROR [COM]: aRC=%#08x aIID={%Vuuid} aComponent={%s} aText={%s} aWarning=%RTbool, aInfo=%p, preserve=%RTbool\n",
     111            aResultCode,
     112            aIID,
     113            aComponent,
     114            strText.c_str(),
     115            aWarning,
     116            aInfo,
     117            preserve));
    112118
    113119    if (aInfo == NULL)
     
    117123                      (aWarning && aResultCode != S_OK),
    118124                      E_FAIL);
    119         AssertReturn(aText != NULL, E_FAIL);
    120         AssertReturn(*aText != '\0', E_FAIL);
     125        AssertReturn(!strText.isEmpty(), E_FAIL);
    121126
    122127        /* reset the error severity bit if it's a warning */
     
    263268                CheckComRCBreakRC (rc);
    264269
    265                 rc = infoObj->init (aResultCode, aIID, aComponent, aText, curInfo);
     270                rc = infoObj->init(aResultCode, aIID, aComponent, strText, curInfo);
    266271                CheckComRCBreakRC (rc);
    267272
     
    335340}
    336341
     342HRESULT SupportErrorInfoBase::setError (HRESULT aResultCode, const Utf8Str &strText)
     343{
     344    HRESULT rc = setError(aResultCode,
     345                          mainInterfaceID(),
     346                          componentName(),
     347                          strText);
     348    return rc;
     349}
     350
    337351HRESULT SupportErrorInfoBase::setWarning (HRESULT aResultCode, const char *aText, ...)
    338352{
  • trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp

    r21878 r22173  
    4141 * Initializes the error info object with the given error details.
    4242 */
    43 HRESULT VirtualBoxErrorInfo::init (HRESULT aResultCode, const GUID *aIID,
    44                                    const char *aComponent, const char *aText,
    45                                    IVirtualBoxErrorInfo *aNext)
     43HRESULT VirtualBoxErrorInfo::init(HRESULT aResultCode,
     44                                  const GUID *aIID,
     45                                  const char *aComponent,
     46                                  const Utf8Str &strText,
     47                                  IVirtualBoxErrorInfo *aNext)
    4648{
    4749    mResultCode = aResultCode;
     
    5153
    5254    mComponent = aComponent;
    53     mText = aText;
     55    mText = strText;
    5456    mNext = aNext;
    5557
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r22165 r22173  
    347347
    348348  <enum
     349       name="SettingsVersion"
     350       uuid="6e151282-c338-428a-989d-5f2402d87e6f"
     351       >
     352      <desc>
     353          Settings version of VirtualBox settings files. This is written to
     354          the "version" attribute of the root "VirtualBox" element in the settings
     355          file XML and indicates which VirtualBox version wrote the file.
     356      </desc>
     357
     358      <const name="Null"    value="0">
     359          <desc>Null value, indicates invalid version.</desc>
     360      </const>
     361      <const name="v1_0"     value="1">
     362          <desc>Settings version "1.0", understood by VirtualBox 3.0 and above.</desc>
     363      </const>
     364      <const name="v1_1"     value="2">
     365          <desc>Settings version "1.7", understood by VirtualBox 3.0 and above.</desc>
     366      </const>
     367      <const name="v1_2"     value="3">
     368          <desc>Settings version "1.2", understood by VirtualBox 3.0 and above.</desc>
     369      </const>
     370      <const name="v1_3pre"  value="4">
     371          <desc>Settings version "1.3pre", understood by VirtualBox 3.0 and above.</desc>
     372      </const>
     373      <const name="v1_3"     value="5">
     374          <desc>Settings version "1.3", understood by VirtualBox 3.0 and above.</desc>
     375      </const>
     376      <const name="v1_4"     value="6">
     377          <desc>Settings version "1.4", understood by VirtualBox 3.0 and above.</desc>
     378      </const>
     379      <const name="v1_5"     value="7">
     380          <desc>Settings version "1.5", understood by VirtualBox 3.0 and above.</desc>
     381      </const>
     382      <const name="v1_6"     value="8">
     383          <desc>Settings version "1.6", understood by VirtualBox 3.0 and above.</desc>
     384      </const>
     385      <const name="v1_7"     value="9">
     386          <desc>Settings version "1.7", understood by VirtualBox 3.0 and above.</desc>
     387      </const>
     388      <const name="v1_8"     value="10">
     389          <desc>Settings version "1.8", understood by VirtualBox 3.1 and above.</desc>
     390      </const>
     391  </enum>
     392
     393  <enum
    349394       name="AccessMode"
    350395       uuid="1da0007c-ddf7-4be8-bcac-d84a1558785f"
     
    14011446    </attribute>
    14021447
    1403     <attribute name="settingsFileVersion" type="wstring" readonly="yes">
    1404       <desc>
    1405         Current version of the format of the global VirtualBox settings file
    1406         (<tt>VirtualBox.xml</tt>).
    1407 
    1408         The version string has the following format:
    1409         <pre>
    1410           x.y-platform
    1411         </pre>
    1412         where @c x and @c y are the major and the minor format
    1413         versions, and @c platform is the platform identifier.
    1414 
    1415         The current version usually matches the value of the
    1416         <link to="#settingsFormatVersion"/> attribute unless the
    1417         settings file was created by an older version of VirtualBox and there
    1418         was a change of the settings file format since then.
    1419 
    1420         Note that VirtualBox automatically converts settings files from older
    1421         versions to the most recent version when reading them (usually at
    1422         VirtualBox startup) but it doesn't save the changes back until
    1423         you call a method that implicitly saves settings (such as
    1424         <link to="#setExtraData"/>) or call <link to="#saveSettings"/>
    1425         explicitly. Therefore, if the value of this attribute differs from the
    1426         value of <link to="#settingsFormatVersion"/>, then it
    1427         means that the settings file was converted but the result of the
    1428         conversion is not yet saved to disk.
    1429 
    1430         The above feature may be used by interactive front-ends to inform users
    1431         about the settings file format change and offer them to explicitly save
    1432         all converted settings files (the global and VM-specific ones),
    1433         optionally create backup copies of the old settings files before saving,
    1434         etc.
    1435 
    1436         <see>settingsFormatVersion, saveSettingsWithBackup()</see>
    1437       </desc>
    1438     </attribute>
    1439 
    1440     <attribute name="settingsFormatVersion" type="wstring" readonly="yes">
    1441       <desc>
    1442         Most recent version of the settings file format.
    1443 
    1444         The version string has the following format:
    1445         <pre>
    1446           x.y-platform
    1447         </pre>
    1448         where @c x and @c y are the major and the minor format
    1449         versions, and @c platform is the platform identifier.
    1450 
    1451         VirtualBox uses this version of the format when saving settings files
    1452         (either as a result of method calls that require to save settings or as
    1453         a result of an explicit call to <link to="#saveSettings"/>).
    1454 
    1455         <see>settingsFileVersion</see>
    1456       </desc>
    1457     </attribute>
    1458 
    14591448    <attribute name="host" type="IHost" readonly="yes">
    14601449      <desc>Associated host object.</desc>
     
    22972286    </method>
    22982287
    2299     <method name="getNextExtraDataKey">
    2300       <desc>
    2301         Returns the global extra data key name following the supplied key.
    2302 
    2303         An error is returned if the supplied @a key does not exist. An empty
    2304         string is returned in @a nextKey if the supplied key is the last key. When
    2305         supplying @c null or an empty string for the @a key, the first key item
    2306         is returned in @a nextKey (if there is any). @a nextValue is an optional
    2307         parameter and if supplied, the next key's value is returned in it.
    2308 
    2309         <result name="VBOX_E_OBJECT_NOT_FOUND">
    2310           Extra data @a key not found.
    2311         </result>
    2312 
    2313       </desc>
    2314       <param name="key" type="wstring" dir="in">
    2315         <desc>Name of the data key to follow.</desc>
    2316       </param>
    2317       <param name="nextKey" type="wstring" dir="out">
    2318         <desc>Name of the next data key.</desc>
    2319       </param>
    2320       <param name="nextValue" type="wstring" dir="out">
    2321         <desc>Value of the next data key.</desc>
     2288    <method name="getExtraDataKeys">
     2289      <desc>
     2290        Returns an array representing the global extra data keys which currently
     2291        have values defined.
     2292      </desc>
     2293      <param name="value" type="wstring" dir="return" safearray="yes">
     2294        <desc>Array of extra data keys.</desc>
    23222295      </param>
    23232296    </method>
     
    27502723      <param name="values" type="wstring" dir="out">
    27512724        <desc>Reserved, not currently used.</desc>
    2752       </param>
    2753     </method>
    2754 
    2755     <method name="saveSettings">
    2756       <desc>
    2757         Saves the global settings to the global settings file
    2758         (<link to="#settingsFilePath"/>).
    2759 
    2760         This method is only useful for explicitly saving the global settings
    2761         file after it has been auto-converted from the old format to the most
    2762         recent format (see <link to="#settingsFileVersion"/> for details).
    2763         Normally, the global settings file is implicitly saved when a global
    2764         setting is changed.
    2765 
    2766         <result name="VBOX_E_FILE_ERROR">
    2767           Settings file not accessible.
    2768         </result>
    2769         <result name="VBOX_E_XML_ERROR">
    2770           Could not parse the settings file.
    2771         </result>
    2772 
    2773       </desc>
    2774     </method>
    2775 
    2776     <method name="saveSettingsWithBackup">
    2777       <desc>
    2778         Creates a backup copy of the global settings file
    2779         (<link to="IVirtualBox::settingsFilePath"/>) in case of auto-conversion,
    2780         and then calls <link to="IVirtualBox::saveSettings"/>.
    2781 
    2782         Note that the backup copy is created <b>only</b> if the settings file
    2783         auto-conversion took place (see <link to="#settingsFileVersion"/> for
    2784         details). Otherwise, this call is fully equivalent to
    2785         <link to="IVirtualBox::saveSettings"/> and no backup copying is done.
    2786 
    2787         The backup copy is created in the same directory where the original
    2788         settings file is located. It is given the following file name:
    2789         <pre>
    2790           original.xml.x.y-platform.bak
    2791         </pre>
    2792         where <tt>original.xml</tt> is the original settings file name
    2793         (excluding path), and <tt>x.y-platform</tt> is the version of the old
    2794         format of the settings file (before auto-conversion).
    2795 
    2796         If the given backup file already exists, this method will try to add the
    2797         <tt>.N</tt> suffix to the backup file name (where @c N counts from
    2798         0 to 9) and copy it again until it succeeds. If all suffixes are
    2799         occupied, or if any other copy error occurs, this method will return a
    2800         failure.
    2801 
    2802         If the copy operation succeeds, the @a bakFileName return argument will
    2803         receive a full path to the created backup file (for informational
    2804         purposes). Note that this will happen even if the subsequent
    2805         <link to="#saveSettings"/> call performed by this method after the
    2806         copy operation, fails.
    2807 
    2808         <note>
    2809           The VirtualBox API never calls this method. It is intended purely for
    2810           the purposes of creating backup copies of the settings files by
    2811           front-ends before saving the results of the automatically performed
    2812           settings conversion to disk.
    2813         </note>
    2814 
    2815         <see>settingsFileVersion</see>
    2816 
    2817         <result name="VBOX_E_FILE_ERROR">
    2818           Settings file not accessible.
    2819         </result>
    2820         <result name="VBOX_E_XML_ERROR">
    2821           Could not parse the settings file.
    2822         </result>
    2823         <result name="VBOX_E_IPRT_ERROR">
    2824           Could not copy the settings file.
    2825         </result>
    2826 
    2827       </desc>
    2828       <param name="bakFileName" type="wstring" dir="return">
    2829         <desc>Full path to the created backup copy.</desc>
    28302725      </param>
    28312726    </method>
     
    42244119        to OpenGL only. </desc>
    42254120    </attribute>
    4226    
     4121
    42274122    <attribute name="accelerate2DVideoEnabled" type="boolean" default="false">
    42284123      <desc>
     
    43504245      <desc>
    43514246        Full name of the file containing machine settings data.
    4352       </desc>
    4353     </attribute>
    4354 
    4355     <attribute name="settingsFileVersion" type="wstring" readonly="yes">
    4356       <desc>
    4357         Current version of the format of the settings file of this machine
    4358         (<link to="IMachine::settingsFilePath"/>).
    4359 
    4360         The version string has the following format:
    4361         <pre>
    4362           x.y-platform
    4363         </pre>
    4364         where @c x and @c y are the major and the minor format
    4365         versions, and @c platform is the platform identifier.
    4366 
    4367         The current version usually matches the value of the
    4368         <link to="IVirtualBox::settingsFormatVersion"/> attribute unless the
    4369         settings file was created by an older version of VirtualBox and there
    4370         was a change of the settings file format since then.
    4371 
    4372         Note that VirtualBox automatically converts settings files from older
    4373         versions to the most recent version when reading them (usually at
    4374         VirtualBox startup) but it doesn't save the changes back until
    4375         you call a method that implicitly saves settings (such as
    4376         <link to="#setExtraData"/>) or call <link to="#saveSettings"/>
    4377         explicitly. Therefore, if the value of this attribute differs from the
    4378         value of <link to="IVirtualBox::settingsFormatVersion"/>, then it
    4379         means that the settings file was converted but the result of the
    4380         conversion is not yet saved to disk.
    4381 
    4382         The above feature may be used by interactive front-ends to inform users
    4383         about the settings file format change and offer them to explicitly save
    4384         all converted settings files (the global and VM-specific ones),
    4385         optionally create backup copies of the old settings files before saving,
    4386         etc.
    4387 
    4388         <see>IVirtualBox::settingsFormatVersion, saveSettingsWithBackup()</see>
    43894247      </desc>
    43904248    </attribute>
     
    48784736    </method>
    48794737
    4880     <method name="getNextExtraDataKey">
    4881       <desc>
    4882         Returns the machine-specific extra data key name following the
    4883         supplied key.
    4884 
    4885         An error is returned if the supplied @a key does not exist. An empty
    4886         string is returned in @a nextKey if the supplied key is the last key.
    4887         When supplying @c null or an empty string for the @a key, the first key
    4888         item is returned in @a nextKey (if there is any). @a nextValue is an
    4889         optional parameter and if supplied, the next key's value is returned in
    4890         it.
    4891 
    4892         <result name="VBOX_E_OBJECT_NOT_FOUND">
    4893           Extra data @a key not found.
    4894         </result>
    4895 
    4896       </desc>
    4897       <param name="key" type="wstring" dir="in">
    4898         <desc>Name of the data key to follow.</desc>
    4899       </param>
    4900       <param name="nextKey" type="wstring" dir="out">
    4901         <desc>Name of the next data key.</desc>
    4902       </param>
    4903       <param name="nextValue" type="wstring" dir="out">
    4904         <desc>Value of the next data key.</desc>
    4905       </param>
     4738    <method name="getExtraDataKeys">
     4739        <desc>
     4740            Returns an array representing the machine-specific extra data keys
     4741            which currently have values defined.
     4742        </desc>
     4743        <param name="value" type="wstring" dir="return" safearray="yes">
     4744            <desc>Array of extra data keys.</desc>
     4745        </param>
    49064746    </method>
    49074747
     
    50034843
    50044844      </desc>
    5005     </method>
    5006 
    5007     <method name="saveSettingsWithBackup">
    5008       <desc>
    5009         Creates a backup copy of the machine settings file (<link
    5010         to="IMachine::settingsFilePath"/>) in case of auto-conversion, and then calls
    5011         <link to="IMachine::saveSettings"/>.
    5012 
    5013         Note that the backup copy is created <b>only</b> if the settings file
    5014         auto-conversion took place (see <link to="#settingsFileVersion"/> for
    5015         details). Otherwise, this call is fully equivalent to
    5016         <link to="IMachine::saveSettings"/> and no backup copying is done.
    5017 
    5018         The backup copy is created in the same directory where the original
    5019         settings file is located. It is given the following file name:
    5020         <pre>
    5021           original.xml.x.y-platform.bak
    5022         </pre>
    5023         where <tt>original.xml</tt> is the original settings file name
    5024         (excluding path), and <tt>x.y-platform</tt> is the version of the old
    5025         format of the settings file (before auto-conversion).
    5026 
    5027         If the given backup file already exists, this method will try to add the
    5028         <tt>.N</tt> suffix to the backup file name (where @c N counts from
    5029         0 to 9) and copy it again until it succeeds. If all suffixes are
    5030         occupied, or if any other copy error occurs, this method will return a
    5031         failure.
    5032 
    5033         If the copy operation succeeds, the @a bakFileName return argument will
    5034         receive a full path to the created backup file (for informational
    5035         purposes). Note that this will happen even if the subsequent
    5036         <link to="#saveSettings"/> call performed by this method after the
    5037         copy operation, fails.
    5038 
    5039         <note>
    5040           The VirtualBox API never calls this method. It is intended purely for
    5041           the purposes of creating backup copies of the settings files by
    5042           front-ends before saving the results of the automatically performed
    5043           settings conversion to disk.
    5044         </note>
    5045 
    5046         <see>settingsFileVersion</see>
    5047 
    5048         <result name="VBOX_E_FILE_ERROR">
    5049           Settings file not accessible.
    5050         </result>
    5051         <result name="VBOX_E_XML_ERROR">
    5052           Could not parse the settings file.
    5053         </result>
    5054         <result name="VBOX_E_INVALID_VM_STATE">
    5055           Virtual machine is not mutable.
    5056         </result>
    5057         <result name="E_ACCESSDENIED">
    5058           Modification request refused.
    5059         </result>
    5060 
    5061       </desc>
    5062       <param name="bakFileName" type="wstring" dir="return">
    5063         <desc>Full path to the created backup copy.</desc>
    5064       </param>
    50654845    </method>
    50664846
     
    1189511675      <desc>Null value, also means "dummy audio driver".</desc>
    1189611676    </const>
    11897     <const name="WinMM"         value="1"/>
    11898     <const name="OSS"           value="2"/>
    11899     <const name="ALSA"          value="3"/>
    11900     <const name="DirectSound"   value="4"/>
    11901     <const name="CoreAudio"     value="5"/>
    11902     <const name="MMPM"          value="6"/>
    11903     <const name="Pulse"         value="7"/>
    11904     <const name="SolAudio"      value="8"/>
     11677    <const name="WinMM"         value="1">
     11678        <desc>Windows multimedia (Windows hosts only).</desc>
     11679    </const>
     11680    <const name="OSS"           value="2">
     11681        <desc>Open Sound System (Linux hosts only).</desc>
     11682    </const>
     11683    <const name="ALSA"          value="3">
     11684        <desc>Advanced Linux Sound Architecture (Linux hosts only).</desc>
     11685    </const>
     11686    <const name="DirectSound"   value="4">
     11687        <desc>DirectSound (Windows hosts only).</desc>
     11688    </const>
     11689    <const name="CoreAudio"     value="5">
     11690        <desc>CoreAudio (Mac hosts only).</desc>
     11691    </const>
     11692    <const name="MMPM"          value="6">
     11693        <desc>Reserved for historical reasons.</desc>
     11694    </const>
     11695    <const name="Pulse"         value="7">
     11696        <desc>PulseAudio (Linux hosts only).</desc>
     11697    </const>
     11698    <const name="SolAudio"      value="8">
     11699        <desc>Solaris audio (Solaris hosts only).</desc>
     11700    </const>
    1190511701  </enum>
    1190611702
  • trunk/src/VBox/Main/include/AudioAdapterImpl.h

    r21878 r22173  
    2828
    2929class Machine;
     30
     31namespace settings
     32{
     33    class AudioAdapter;
     34}
    3035
    3136class ATL_NO_VTABLE AudioAdapter :
     
    8893    // public methods only for internal purposes
    8994
    90     HRESULT loadSettings (const settings::Key &aMachineNode);
    91     HRESULT saveSettings (settings::Key &aMachineNode);
     95    HRESULT loadSettings(const settings::AudioAdapter &data);
     96    HRESULT saveSettings(settings::AudioAdapter &data);
    9297
    9398    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/BIOSSettingsImpl.h

    r21878 r22173  
    2929class Machine;
    3030class GuestOSType;
     31
     32namespace settings
     33{
     34    class BIOSSettings;
     35}
    3136
    3237class ATL_NO_VTABLE BIOSSettings :
     
    119124    // public methods only for internal purposes
    120125
    121     HRESULT loadSettings (const settings::Key &aMachineNode);
    122     HRESULT saveSettings (settings::Key &aMachineNode);
     126    HRESULT loadSettings(const settings::BIOSSettings &data);
     127    HRESULT saveSettings(settings::BIOSSettings &data);
    123128
    124129    const Backupable <Data> &data() const { return mData; }
  • trunk/src/VBox/Main/include/DHCPServerImpl.h

    r21878 r22173  
    2929
    3030#ifdef VBOX_WITH_HOSTNETIF_API
    31 /* class DHCPServer; */
    32 /* #include "netif.h" */
    3331struct NETIFINFO;
    3432#endif
     33
     34namespace settings
     35{
     36    class DHCPServer;
     37}
    3538
    3639class ATL_NO_VTABLE DHCPServer :
     
    6164    void FinalRelease();
    6265
    63     HRESULT init(VirtualBox *aVirtualBox, IN_BSTR aName);
    64     HRESULT init(VirtualBox *aVirtualBox, const settings::Key &aNode);
    65     HRESULT saveSettings (settings::Key &aParentNode);
     66    HRESULT init(VirtualBox *aVirtualBox,
     67                 IN_BSTR aName);
     68    HRESULT init(VirtualBox *aVirtualBox,
     69                 const settings::DHCPServer &data);
     70    HRESULT saveSettings(settings::DHCPServer &data);
    6671
    6772    void uninit();
    6873
    6974    // IDHCPServer properties
    70     STDMETHOD(COMGETTER(NetworkName)) (BSTR *aName);
    71     STDMETHOD(COMGETTER(Enabled)) (BOOL *aEnabled);
    72     STDMETHOD(COMSETTER(Enabled)) (BOOL aEnabled);
    73     STDMETHOD(COMGETTER(IPAddress)) (BSTR *aIPAddress);
    74     STDMETHOD(COMGETTER(NetworkMask)) (BSTR *aNetworkMask);
    75     STDMETHOD(COMGETTER(LowerIP)) (BSTR *aIPAddress);
    76     STDMETHOD(COMGETTER(UpperIP)) (BSTR *aIPAddress);
     75    STDMETHOD(COMGETTER(NetworkName))(BSTR *aName);
     76    STDMETHOD(COMGETTER(Enabled))(BOOL *aEnabled);
     77    STDMETHOD(COMSETTER(Enabled))(BOOL aEnabled);
     78    STDMETHOD(COMGETTER(IPAddress))(BSTR *aIPAddress);
     79    STDMETHOD(COMGETTER(NetworkMask))(BSTR *aNetworkMask);
     80    STDMETHOD(COMGETTER(LowerIP))(BSTR *aIPAddress);
     81    STDMETHOD(COMGETTER(UpperIP))(BSTR *aIPAddress);
    7782
    78     STDMETHOD(SetConfiguration) (IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aFromIPAddress, IN_BSTR aToIPAddress);
     83    STDMETHOD(SetConfiguration)(IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aFromIPAddress, IN_BSTR aToIPAddress);
    7984
    80     STDMETHOD(Start) (IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType);
    81     STDMETHOD(Stop) ();
     85    STDMETHOD(Start)(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType);
     86    STDMETHOD(Stop)();
    8287
    8388    // for VirtualBoxSupportErrorInfoImpl
     
    106111
    107112#endif // ____H_H_DHCPSERVERIMPL
    108 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/DHCPServerRunner.h

    r21860 r22173  
    5353{
    5454public:
    55     DHCPServerRunner(); 
     55    DHCPServerRunner();
    5656    ~DHCPServerRunner() { stop(); /* don't leave abandoned servers */}
    5757
     
    7979    }
    8080
     81    int setOption(DHCPCFG opt, const com::Utf8Str &val, bool enabled)
     82    {
     83        return setOption(opt, val.c_str(), enabled);
     84    }
     85
    8186    int start();
    8287    int stop();
  • trunk/src/VBox/Main/include/DVDDriveImpl.h

    r21878 r22173  
    3030
    3131class Machine;
     32
     33namespace settings
     34{
     35    class DVDDrive;
     36}
    3237
    3338class ATL_NO_VTABLE DVDDrive :
     
    100105    // public methods only for internal purposes
    101106
    102     HRESULT loadSettings (const settings::Key &aMachineNode);
    103     HRESULT saveSettings (settings::Key &aMachineNode);
     107    HRESULT loadSettings(const settings::DVDDrive &data);
     108    HRESULT saveSettings(settings::DVDDrive &data);
    104109
    105110    bool isModified() { AutoWriteLock alock (this); return m.isBackedUp(); }
  • trunk/src/VBox/Main/include/FloppyDriveImpl.h

    r21878 r22173  
    3030
    3131class Machine;
     32
     33namespace settings
     34{
     35    class FloppyDrive;
     36}
    3237
    3338class ATL_NO_VTABLE FloppyDrive :
     
    100105    // public methods only for internal purposes
    101106
    102     HRESULT loadSettings (const settings::Key &aMachineNode);
    103     HRESULT saveSettings (settings::Key &aMachineNode);
     107    HRESULT loadSettings(const settings::FloppyDrive &data);
     108    HRESULT saveSettings(settings::FloppyDrive &data);
    104109
    105110    bool isModified() { AutoWriteLock alock (this); return m.isBackedUp(); }
  • trunk/src/VBox/Main/include/HardDiskImpl.h

    r21878 r22173  
    3838
    3939class Progress;
     40namespace settings
     41{
     42    class Medium;
     43}
    4044
    4145////////////////////////////////////////////////////////////////////////////////
     
    96100    HRESULT init(VirtualBox *aVirtualBox,
    97101                 HardDisk *aParent,
    98                  const settings::Key &aNode);
     102                 const settings::Medium &data);
    99103    void uninit();
    100104
     
    148152    bool isReadOnly();
    149153
    150     HRESULT saveSettings (settings::Key &aParentNode);
    151 
    152     HRESULT compareLocationTo (const char *aLocation, int &aResult);
     154    HRESULT saveSettings(settings::Medium &data);
     155
     156    HRESULT compareLocationTo(const Utf8Str &strLocation, int &aResult);
    153157
    154158    /**
     
    256260private:
    257261
    258     HRESULT setLocation (CBSTR aLocation);
     262    virtual HRESULT setLocation(const Utf8Str &aLocation);
    259263    HRESULT setFormat (CBSTR aFormat);
    260264
  • trunk/src/VBox/Main/include/HostImpl.h

    r21878 r22173  
    4848class Progress;
    4949
     50namespace settings
     51{
     52    class Host;
     53}
     54
    5055#include <list>
    5156
     
    7479
    7580    // public initializer/uninitializer for internal purposes only
    76     HRESULT init (VirtualBox *aParent);
     81    HRESULT init(VirtualBox *aParent);
    7782    void uninit();
    7883
     
    114119
    115120    // public methods only for internal purposes
    116 
    117     HRESULT loadSettings (const settings::Key &aGlobal);
    118     HRESULT saveSettings (settings::Key &aGlobal);
     121    HRESULT loadSettings(const settings::Host &data);
     122    HRESULT saveSettings(settings::Host &data);
    119123
    120124#ifdef VBOX_WITH_USB
  • trunk/src/VBox/Main/include/MachineImpl.h

    r22143 r22173  
    3737#include "ParallelPortImpl.h"
    3838#include "BIOSSettingsImpl.h"
    39 #include "StorageControllerImpl.h"
    4039#ifdef VBOX_WITH_RESOURCE_USAGE_API
    4140#include "PerformanceImpl.h"
     
    7069class SharedFolder;
    7170class HostUSBDevice;
     71class StorageController;
    7272
    7373class SessionMachine;
     74
     75namespace settings
     76{
     77    class MachineConfigFile;
     78    class Snapshot;
     79    class Hardware;
     80    class Storage;
     81    class StorageController;
     82    class MachineRegistryEntry;
     83}
    7484
    7585// Machine class
     
    8797
    8898    enum InstanceType { IsMachine, IsSessionMachine, IsSnapshotMachine };
     99
     100    enum InitMode { Init_New, Init_Import, Init_Registered };
    89101
    90102    /**
     
    151163        const Guid mUuid;
    152164        BOOL mRegistered;
     165        InitMode mInitMode;
    153166
    154167        /** Flag indicating that the config file is read-only. */
    155168        BOOL mConfigFileReadonly;
    156         Bstr mConfigFile;
    157         Bstr mConfigFileFull;
    158 
    159         Utf8Str mSettingsFileVersion;
     169        Utf8Str m_strConfigFile;
     170        Utf8Str m_strConfigFileFull;
     171
     172        // machine settings XML file
     173        settings::MachineConfigFile *m_pMachineConfigFile;
    160174
    161175        BOOL mAccessible;
     
    247261        struct GuestProperty {
    248262            /** Property name */
    249             Bstr mName;
     263            Utf8Str strName;
    250264            /** Property value */
    251             Bstr mValue;
     265            Utf8Str strValue;
    252266            /** Property timestamp */
    253267            ULONG64 mTimestamp;
     
    270284        BOOL           mHWVirtExNestedPagingEnabled;
    271285        BOOL           mHWVirtExVPIDEnabled;
    272         BOOL           mAccelerate3DEnabled;
    273286        BOOL           mAccelerate2DVideoEnabled;
    274287        BOOL           mPAEEnabled;
    275288        ULONG          mCPUCount;
    276 
    277         DeviceType_T   mBootOrder [SchemaDefs::MaxBootPosition];
    278 
    279         typedef std::list <ComObjPtr<SharedFolder> > SharedFolderList;
     289        BOOL           mAccelerate3DEnabled;
     290
     291        DeviceType_T   mBootOrder[SchemaDefs::MaxBootPosition];
     292
     293        typedef std::list< ComObjPtr<SharedFolder> > SharedFolderList;
    280294        SharedFolderList mSharedFolders;
     295
    281296        ClipboardMode_T mClipboardMode;
    282         typedef std::list <GuestProperty> GuestPropertyList;
     297
     298        typedef std::list<GuestProperty> GuestPropertyList;
    283299        GuestPropertyList mGuestProperties;
    284300        BOOL           mPropertyServiceActive;
     
    464480    NS_DECL_ISUPPORTS
    465481
    466     DECLARE_EMPTY_CTOR_DTOR (Machine)
     482    DECLARE_EMPTY_CTOR_DTOR(Machine)
    467483
    468484    HRESULT FinalConstruct();
    469485    void FinalRelease();
    470486
    471     enum InitMode { Init_New, Init_Existing, Init_Registered };
    472 
    473487    // public initializer/uninitializer for internal purposes only
    474     HRESULT init (VirtualBox *aParent, CBSTR aConfigFile,
    475                   InitMode aMode, CBSTR aName = NULL,
    476                   GuestOSType *aOsType = NULL,
    477                   BOOL aNameSync = TRUE, const Guid *aId = NULL);
     488    HRESULT init(VirtualBox *aParent,
     489                 const Utf8Str &strConfigFile,
     490                 InitMode aMode,
     491                 CBSTR aName = NULL,
     492                 GuestOSType *aOsType = NULL,
     493                 BOOL aNameSync = TRUE,
     494                 const Guid *aId = NULL);
    478495    void uninit();
    479496
     497protected:
     498    HRESULT initDataAndChildObjects();
     499    void uninitDataAndChildObjects();
     500
     501public:
    480502    // IMachine properties
    481503    STDMETHOD(COMGETTER(Parent))(IVirtualBox **aParent);
     
    525547    STDMETHOD(COMGETTER(USBController)) (IUSBController * *aUSBController);
    526548    STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aFilePath);
    527     STDMETHOD(COMGETTER(SettingsFileVersion)) (BSTR *aSettingsFileVersion);
    528549    STDMETHOD(COMGETTER(SettingsModified)) (BOOL *aModified);
    529550    STDMETHOD(COMGETTER(SessionState)) (SessionState_T *aSessionState);
     
    555576    STDMETHOD(GetParallelPort) (ULONG slot, IParallelPort **port);
    556577    STDMETHOD(GetNetworkAdapter) (ULONG slot, INetworkAdapter **adapter);
    557     STDMETHOD(GetNextExtraDataKey)(IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue);
     578    STDMETHOD(GetExtraDataKeys) (ComSafeArrayOut(BSTR, aKeys));
    558579    STDMETHOD(GetExtraData)(IN_BSTR aKey, BSTR *aValue);
    559580    STDMETHOD(SetExtraData)(IN_BSTR aKey, IN_BSTR aValue);
    560581    STDMETHOD(SaveSettings)();
    561     STDMETHOD(SaveSettingsWithBackup) (BSTR *aBakFileName);
    562582    STDMETHOD(DiscardSettings)();
    563583    STDMETHOD(DeleteSettings)();
     
    628648     * for reading.
    629649     */
    630     const Bstr &settingsFileFull() const { return mData->mConfigFileFull; }
     650    const Utf8Str &settingsFileFull() const { return mData->m_strConfigFileFull; }
    631651
    632652    /**
     
    650670    virtual HRESULT onSharedFolderChange() { return S_OK; }
    651671
    652     HRESULT saveRegistryEntry (settings::Key &aEntryNode);
    653 
    654     int calculateFullPath (const char *aPath, Utf8Str &aResult);
    655     void calculateRelativePath (const char *aPath, Utf8Str &aResult);
     672    HRESULT saveRegistryEntry(settings::MachineRegistryEntry &data);
     673
     674    int calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult);
     675    void calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult);
    656676
    657677    void getLogFolder (Utf8Str &aLogFolder);
     
    748768    inline Machine *machine();
    749769
    750     HRESULT initDataAndChildObjects();
    751     void uninitDataAndChildObjects();
    752 
    753770    void ensureNoStateDependencies();
    754771
     
    759776                              bool aSetError = false);
    760777
    761     HRESULT loadSettings (bool aRegistered);
    762     HRESULT loadSnapshot (const settings::Key &aNode, const Guid &aCurSnapshotId,
    763                           Snapshot *aParentSnapshot);
    764     HRESULT loadHardware (const settings::Key &aNode);
    765     HRESULT loadStorageControllers (const settings::Key &aNode, bool aRegistered,
    766                            const Guid *aSnapshotId = NULL);
    767     HRESULT loadStorageDevices (ComObjPtr<StorageController> aStorageController,
    768                                 const settings::Key &aNode, bool aRegistered,
    769                                 const Guid *aSnapshotId = NULL);
    770 
    771     HRESULT findSnapshotNode (Snapshot *aSnapshot, settings::Key &aMachineNode,
    772                               settings::Key *aSnapshotsNode,
    773                               settings::Key *aSnapshotNode);
    774 
    775     HRESULT findSnapshot (const Guid &aId, ComObjPtr<Snapshot> &aSnapshot,
    776                           bool aSetError = false);
    777     HRESULT findSnapshot (IN_BSTR aName, ComObjPtr<Snapshot> &aSnapshot,
    778                           bool aSetError = false);
    779 
    780     HRESULT getStorageControllerByName(CBSTR aName,
     778    HRESULT loadSettings(bool aRegistered);
     779    HRESULT loadSnapshot(const settings::Snapshot &data,
     780                         const Guid &aCurSnapshotId,
     781                         Snapshot *aParentSnapshot);
     782    HRESULT loadHardware(const settings::Hardware &data);
     783    HRESULT loadStorageControllers(const settings::Storage &data,
     784                                   bool aRegistered,
     785                                   const Guid *aSnapshotId = NULL);
     786    HRESULT loadStorageDevices(StorageController *aStorageController,
     787                               const settings::StorageController &data,
     788                               bool aRegistered,
     789                               const Guid *aSnapshotId = NULL);
     790
     791    HRESULT findSnapshot(const Guid &aId, ComObjPtr<Snapshot> &aSnapshot,
     792                         bool aSetError = false);
     793    HRESULT findSnapshot(IN_BSTR aName, ComObjPtr<Snapshot> &aSnapshot,
     794                         bool aSetError = false);
     795
     796    HRESULT getStorageControllerByName(const Utf8Str &aName,
    781797                                       ComObjPtr<StorageController> &aStorageController,
    782798                                       bool aSetError = false);
     
    790806        SaveS_ResetCurStateModified = 0x01,
    791807        SaveS_InformCallbacksAnyway = 0x02,
    792         /* ops for #saveSnapshotSettings() */
    793         SaveSS_NoOp = 0x00, SaveSS_AddOp = 0x01,
    794         SaveSS_UpdateAttrsOp = 0x02, SaveSS_UpdateAllOp = 0x03,
    795         SaveSS_OpMask = 0xF,
    796808        /* flags for #saveSnapshotSettings() */
    797809        SaveSS_CurStateModified = 0x40,
     
    803815    };
    804816
    805     HRESULT prepareSaveSettings (bool &aRenamed, bool &aNew);
    806     HRESULT saveSettings (int aFlags = 0);
    807 
    808     HRESULT saveSnapshotSettings (Snapshot *aSnapshot, int aOpFlags);
    809     HRESULT saveSnapshotSettingsWorker (settings::Key &aMachineNode,
    810                                         Snapshot *aSnapshot, int aOpFlags);
    811 
    812     HRESULT saveHardware (settings::Key &aNode);
    813     HRESULT saveStorageControllers (settings::Key &aNode);
    814     HRESULT saveStorageDevices (ComObjPtr<StorageController> aStorageController,
    815                                 settings::Key &aNode);
    816 
    817     HRESULT saveStateSettings (int aFlags);
    818 
    819     HRESULT getExtraData(const Utf8Str &aKey, Utf8Str &aValue);
     817    HRESULT prepareSaveSettings(bool &aRenamed, bool &aNew);
     818    HRESULT saveSettings(int aFlags = 0);
     819
     820    HRESULT saveAllSnapshots();
     821
     822    HRESULT saveHardware(settings::Hardware &data);
     823    HRESULT saveStorageControllers(settings::Storage &data);
     824    HRESULT saveStorageDevices(ComObjPtr<StorageController> aStorageController,
     825                               settings::StorageController &data);
     826
     827    HRESULT saveStateSettings(int aFlags);
    820828
    821829    HRESULT createImplicitDiffs (const Bstr &aFolder,
     
    825833
    826834    void fixupHardDisks(bool aCommit, bool aOnline = false);
    827 
    828     HRESULT lockConfig();
    829     HRESULT unlockConfig();
    830 
    831     /** @note This method is not thread safe */
    832     BOOL isConfigLocked()
    833     {
    834         return !!mData && mData->mHandleCfgFile != NIL_RTFILE;
    835     }
    836835
    837836    bool isInOwnDir (Utf8Str *aSettingsDir = NULL);
     
    10971096
    10981097    // public initializer/uninitializer for internal purposes only
    1099     HRESULT init (SessionMachine *aSessionMachine,
    1100                   IN_GUID aSnapshotId, IN_BSTR aStateFilePath);
    1101     HRESULT init (Machine *aMachine,
    1102                   const settings::Key &aHWNode, const settings::Key &aHDAsNode,
    1103                   IN_GUID aSnapshotId, IN_BSTR aStateFilePath);
     1098    HRESULT init(SessionMachine *aSessionMachine,
     1099                 IN_GUID aSnapshotId,
     1100                 const Utf8Str &aStateFilePath);
     1101    HRESULT init(Machine *aMachine,
     1102                 const settings::Hardware &hardware,
     1103                 const settings::Storage &storage,
     1104                 IN_GUID aSnapshotId,
     1105                 const Utf8Str &aStateFilePath);
    11041106    void uninit();
    11051107
  • trunk/src/VBox/Main/include/MediumImpl.h

    r21878 r22173  
    3232
    3333class VirtualBox;
     34namespace settings
     35{
     36    class Medium;
     37}
    3438
    3539////////////////////////////////////////////////////////////////////////////////
     
    142146    virtual Utf8Str name();
    143147
    144     virtual HRESULT setLocation (CBSTR aLocation);
     148    virtual HRESULT setLocation(const Utf8Str &aLocation);
    145149    virtual HRESULT queryInfo();
    146150
     
    222226
    223227    // protected initializer/uninitializer for internal purposes only
    224     HRESULT protectedInit (VirtualBox *aVirtualBox, CBSTR aLocation,
    225                            const Guid &aId);
    226     HRESULT protectedInit (VirtualBox *aVirtualBox, const settings::Key &aImageNode);
     228    HRESULT protectedInit(VirtualBox *aVirtualBox,
     229                          CBSTR aLocation,
     230                          const Guid &aId);
     231    HRESULT protectedInit(VirtualBox *aVirtualBox,
     232                          const settings::Medium &data);
    227233    void protectedUninit();
    228234
     
    230236
    231237    // public methods for internal purposes only
    232     HRESULT saveSettings (settings::Key &aImagesNode);
     238    HRESULT saveSettings(settings::Medium &data);
    233239};
    234240
     
    266272    // public initializer/uninitializer for internal purposes only
    267273
    268     HRESULT init (VirtualBox *aParent, CBSTR aFilePath,
    269                   const Guid &aId)
    270     {
    271         return protectedInit (aParent, aFilePath, aId);
    272     }
    273 
    274     HRESULT init (VirtualBox *aParent, const settings::Key &aImageNode)
    275     {
    276         return protectedInit (aParent, aImageNode);
     274    HRESULT init(VirtualBox *aParent,
     275                 CBSTR aFilePath,
     276                 const Guid &aId)
     277    {
     278        return protectedInit(aParent, aFilePath, aId);
     279    }
     280
     281    HRESULT init(VirtualBox *aParent,
     282                 const settings::Medium &data)
     283    {
     284        return protectedInit(aParent, data);
    277285    }
    278286
     
    320328    // public initializer/uninitializer for internal purposes only
    321329
    322     HRESULT init (VirtualBox *aParent, CBSTR aFilePath,
    323                   const Guid &aId)
    324     {
    325         return protectedInit (aParent, aFilePath, aId);
    326     }
    327 
    328     HRESULT init (VirtualBox *aParent, const settings::Key &aImageNode)
    329     {
    330         return protectedInit (aParent, aImageNode);
     330    HRESULT init(VirtualBox *aParent,
     331                 CBSTR aFilePath,
     332                 const Guid &aId)
     333    {
     334        return protectedInit(aParent, aFilePath, aId);
     335    }
     336
     337    HRESULT init(VirtualBox *aParent,
     338                 const settings::Medium &data)
     339    {
     340        return protectedInit(aParent, data);
    331341    }
    332342
  • trunk/src/VBox/Main/include/NetworkAdapterImpl.h

    r21878 r22173  
    2929class Machine;
    3030class GuestOSType;
     31
     32namespace settings
     33{
     34    class NetworkAdapter;
     35}
    3136
    3237class ATL_NO_VTABLE NetworkAdapter :
     
    134139    // public methods only for internal purposes
    135140
    136     HRESULT loadSettings (const settings::Key &aAdapterNode);
    137     HRESULT saveSettings (settings::Key &aAdapterNode);
     141    HRESULT loadSettings(const settings::NetworkAdapter &data);
     142    HRESULT saveSettings(settings::NetworkAdapter &data);
    138143
    139144    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/ParallelPortImpl.h

    r21878 r22173  
    2727
    2828class Machine;
     29
     30namespace settings
     31{
     32    class ParallelPort;
     33}
    2934
    3035class ATL_NO_VTABLE ParallelPort :
     
    100105    // public methods only for internal purposes
    101106
    102     HRESULT loadSettings (const settings::Key &aPortNode);
    103     HRESULT saveSettings (settings::Key &aPortNode);
     107    HRESULT loadSettings(const settings::ParallelPort &data);
     108    HRESULT saveSettings(settings::ParallelPort &data);
    104109
    105110    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/Performance.h

    r19270 r22173  
    3333#include <string>
    3434#include <vector>
     35
     36namespace com
     37{
     38    class Utf8Str;
     39}
    3540
    3641namespace pm
     
    414419        ElementList mElements;
    415420
    416         void processMetricList(const std::string &name, const ComPtr<IUnknown> object);
     421        void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object);
    417422    };
    418423}
  • trunk/src/VBox/Main/include/SerialPortImpl.h

    r21878 r22173  
    2929class Machine;
    3030class GuestOSType;
     31
     32namespace settings
     33{
     34    class SerialPort;
     35}
    3136
    3237class ATL_NO_VTABLE SerialPort :
     
    112117    // public methods only for internal purposes
    113118
    114     HRESULT loadSettings (const settings::Key &aPortNode);
    115     HRESULT saveSettings (settings::Key &aPortNode);
     119    HRESULT loadSettings(const settings::SerialPort &data);
     120    HRESULT saveSettings(settings::SerialPort &data);
    116121
    117122    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/SnapshotImpl.h

    r21835 r22173  
    2929class SnapshotMachine;
    3030class VirtualBox;
     31
    3132namespace settings
    3233{
    33     class Key;
     34    class Snapshot;
    3435}
    3536
     
    6566    HRESULT init(VirtualBox *aVirtualBox,
    6667                 const Guid &aId,
    67                  IN_BSTR aName,
    68                  IN_BSTR aDescription,
    69                  RTTIMESPEC aTimeStamp,
     68                 const Utf8Str &aName,
     69                 const Utf8Str &aDescription,
     70                 const RTTIMESPEC &aTimeStamp,
    7071                 SnapshotMachine *aMachine,
    7172                 Snapshot *aParent);
     
    104105
    105106    Guid getId() const;
    106     Bstr getName() const;
     107    const Utf8Str& getName() const;
    107108    RTTIMESPEC getTimeStamp() const;
    108109
    109110    ComObjPtr<Snapshot> findChildOrSelf(IN_GUID aId);
    110     ComObjPtr<Snapshot> findChildOrSelf(IN_BSTR aName);
     111    ComObjPtr<Snapshot> findChildOrSelf(const Utf8Str &aName);
    111112
    112113    void updateSavedStatePaths(const char *aOldPath,
     
    115116                                   const char *aNewPath);
    116117
    117     HRESULT saveSnapshot(settings::Key &aNode, bool aAttrsOnly);
    118     HRESULT saveSnapshotImpl(settings::Key &aNode, bool aAttrsOnly);
     118    HRESULT saveSnapshot(settings::Snapshot &data, bool aAttrsOnly);
     119    HRESULT saveSnapshotImpl(settings::Snapshot &data, bool aAttrsOnly);
    119120
    120121    // for VirtualBoxSupportErrorInfoImpl
  • trunk/src/VBox/Main/include/StorageControllerImpl.h

    r21878 r22173  
    5252        bool operator== (const Data &that) const
    5353        {
    54             return this == &that || ((mStorageControllerType == that.mStorageControllerType) &&
    55                     (mName           == that.mName) &&
    56                     (mPortCount   == that.mPortCount) &&
    57                     (mPortIde0Master == that.mPortIde0Master) &&
    58                     (mPortIde0Slave  == that.mPortIde0Slave)  &&
    59                     (mPortIde1Master == that.mPortIde1Master) &&
    60                     (mPortIde1Slave  == that.mPortIde1Slave));
     54            return    this == &that
     55                   || (    (mStorageControllerType == that.mStorageControllerType)
     56                        && (strName           == that.strName)
     57                        && (mPortCount   == that.mPortCount)
     58                        && (mPortIde0Master == that.mPortIde0Master)
     59                        && (mPortIde0Slave  == that.mPortIde0Slave)
     60                        && (mPortIde1Master == that.mPortIde1Master)
     61                        && (mPortIde1Slave  == that.mPortIde1Slave));
    6162        }
    6263
    63         /** Uniuqe name of the storage controller. */
    64         Bstr mName;
     64        /** Unique name of the storage controller. */
     65        Utf8Str strName;
    6566        /** The connection type of thestorage controller. */
    6667        StorageBus_T mStorageBus;
     
    103104
    104105    // public initializer/uninitializer for internal purposes only
    105     HRESULT init (Machine *aParent, IN_BSTR aName,
    106                   StorageBus_T aBus);
    107     HRESULT init (Machine *aParent, StorageController *aThat, bool aReshare = false);
    108     HRESULT initCopy (Machine *aParent, StorageController *aThat);
     106    HRESULT init(Machine *aParent,
     107                 const Utf8Str &aName,
     108                 StorageBus_T aBus);
     109    HRESULT init(Machine *aParent,
     110                 StorageController *aThat,
     111                 bool aReshare = false);
     112    HRESULT initCopy(Machine *aParent,
     113                     StorageController *aThat);
    109114    void uninit();
    110115
     
    128133    // public methods only for internal purposes
    129134
    130     const Bstr &name() const { return mData->mName; }
     135    const Utf8Str &name() const { return mData->strName; }
    131136    StorageControllerType_T controllerType() const { return mData->mStorageControllerType; }
     137    StorageBus_T storageBus() const { return mData->mStorageBus; }
    132138
    133139    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
     
    159165    const ComObjPtr<StorageController> mPeer;
    160166    /** Data. */
    161     Backupable <Data> mData;
     167    Backupable<Data> mData;
    162168
    163169    /* Instance number of the device in the running VM. */
  • trunk/src/VBox/Main/include/SystemPropertiesImpl.h

    r21878 r22173  
    3333
    3434class VirtualBox;
     35namespace settings
     36{
     37    class SystemProperties;
     38}
    3539
    3640class ATL_NO_VTABLE SystemProperties :
     
    9599    // public methods only for internal purposes
    96100
    97     HRESULT loadSettings (const settings::Key &aGlobal);
    98     HRESULT saveSettings (settings::Key &aGlobal);
     101    HRESULT loadSettings(const settings::SystemProperties &data);
     102    HRESULT saveSettings(settings::SystemProperties &data);
    99103
    100     ComObjPtr<HardDiskFormat> hardDiskFormat (CBSTR aFormat);
     104    ComObjPtr<HardDiskFormat> hardDiskFormat(CBSTR aFormat);
    101105
    102106    // public methods for internal purposes only
    103107    // (ensure there is a caller and a read lock before calling them!)
    104 
    105     /** Default Machine path (as is, not full). Not thread safe (use object lock). */
    106     const Bstr &defaultMachineFolder() const { return mDefaultMachineFolder; }
    107     /** Default Machine path (full). Not thread safe (use object lock). */
    108     const Bstr &defaultMachineFolderFull() const { return mDefaultMachineFolderFull; }
    109     /** Default hard disk path (as is, not full). Not thread safe (use object lock). */
    110     const Bstr &defaultHardDiskFolder() const { return mDefaultHardDiskFolder; }
    111     /** Default hard disk path (full). Not thread safe (use object lock). */
    112     const Bstr &defaultHardDiskFolderFull() const { return mDefaultHardDiskFolderFull; }
    113 
    114     /** Default hard disk format. Not thread safe (use object lock). */
    115     const Bstr &defaultHardDiskFormat() const { return mDefaultHardDiskFormat; }
    116108
    117109    // for VirtualBoxSupportErrorInfoImpl
     
    120112private:
    121113
    122     typedef std::list <ComObjPtr<HardDiskFormat> > HardDiskFormatList;
     114    typedef std::list< ComObjPtr<HardDiskFormat> > HardDiskFormatList;
    123115
    124     HRESULT setDefaultMachineFolder (CBSTR aPath);
    125     HRESULT setDefaultHardDiskFolder (CBSTR aPath);
    126     HRESULT setDefaultHardDiskFormat (CBSTR aFormat);
     116    HRESULT setDefaultMachineFolder(const Utf8Str &aPath);
     117    HRESULT setDefaultHardDiskFolder(const Utf8Str &aPath);
     118    HRESULT setDefaultHardDiskFormat(const Utf8Str &aFormat);
    127119
    128     HRESULT setRemoteDisplayAuthLibrary (CBSTR aPath);
    129     HRESULT setWebServiceAuthLibrary (CBSTR aPath);
     120    HRESULT setRemoteDisplayAuthLibrary(const Utf8Str &aPath);
     121    HRESULT setWebServiceAuthLibrary(const Utf8Str &aPath);
    130122
    131123    const ComObjPtr<VirtualBox, ComWeakRef> mParent;
    132124
    133     Bstr mDefaultMachineFolder;
    134     Bstr mDefaultMachineFolderFull;
    135     Bstr mDefaultHardDiskFolder;
    136     Bstr mDefaultHardDiskFolderFull;
    137     Bstr mDefaultHardDiskFormat;
     125    Utf8Str m_strDefaultMachineFolder;
     126    Utf8Str m_strDefaultMachineFolderFull;
     127    Utf8Str m_strDefaultHardDiskFolder;
     128    Utf8Str m_strDefaultHardDiskFolderFull;
     129    Utf8Str m_strDefaultHardDiskFormat;
    138130
    139131    HardDiskFormatList mHardDiskFormats;
    140132
    141     Bstr mRemoteDisplayAuthLibrary;
    142     Bstr mWebServiceAuthLibrary;
     133    Utf8Str m_strRemoteDisplayAuthLibrary;
     134    Utf8Str m_strWebServiceAuthLibrary;
    143135    ULONG mLogHistoryCount;
    144136    AudioDriverType_T mDefaultAudioDriver;
     137
     138    friend class VirtualBox;
    145139};
    146140
  • trunk/src/VBox/Main/include/USBControllerImpl.h

    r21878 r22173  
    3434class Machine;
    3535class HostUSBDevice;
     36
     37namespace settings
     38{
     39    class USBController;
     40}
    3641
    3742/**
     
    109114    // public methods only for internal purposes
    110115
    111     HRESULT loadSettings (const settings::Key &aMachineNode);
    112     HRESULT saveSettings (settings::Key &aMachineNode);
     116    HRESULT loadSettings(const settings::USBController &data);
     117    HRESULT saveSettings(settings::USBController &data);
    113118
    114119    bool isModified();
  • trunk/src/VBox/Main/include/VRDPServerImpl.h

    r21878 r22173  
    3030
    3131class Machine;
     32
     33namespace settings
     34{
     35    class VRDPSettings;
     36}
    3237
    3338class ATL_NO_VTABLE VRDPServer :
     
    107112    // public methods only for internal purposes
    108113
    109     HRESULT loadSettings (const settings::Key &aMachineNode);
    110     HRESULT saveSettings (settings::Key &aMachineNode);
     114    HRESULT loadSettings(const settings::VRDPSettings &data);
     115    HRESULT saveSettings(settings::VRDPSettings &data);
    111116
    112117    bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
  • trunk/src/VBox/Main/include/VirtualBoxBase.h

    r21878 r22173  
    3636// avoid including VBox/settings.h and VBox/xml.h;
    3737// only declare the classes
    38 namespace settings
    39 {
    40 class XmlTreeBackend;
    41 class TreeBackend;
    42 class Key;
    43 }
    44 
    4538namespace xml
    4639{
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r21878 r22173  
    6262struct VMClientWatcherData;
    6363
     64namespace settings
     65{
     66    class MainConfigFile;
     67}
     68
    6469class ATL_NO_VTABLE VirtualBox :
    6570    public VirtualBoxBaseWithChildrenNEXT,
     
    111116    /* public initializer/uninitializer for internal purposes only */
    112117    HRESULT init();
     118    HRESULT initMachines();
     119    HRESULT initMedia();
    113120    void uninit();
    114121
     
    119126    STDMETHOD(COMGETTER(HomeFolder)) (BSTR *aHomeFolder);
    120127    STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aSettingsFilePath);
    121     STDMETHOD(COMGETTER(SettingsFileVersion)) (BSTR *aSettingsFileVersion);
    122     STDMETHOD(COMGETTER(SettingsFormatVersion)) (BSTR *aSettingsFormatVersion);
    123128    STDMETHOD(COMGETTER(Host)) (IHost **aHost);
    124129    STDMETHOD(COMGETTER(SystemProperties)) (ISystemProperties **aSystemProperties);
     
    168173    STDMETHOD(CreateSharedFolder) (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable);
    169174    STDMETHOD(RemoveSharedFolder) (IN_BSTR aName);
    170     STDMETHOD(GetNextExtraDataKey) (IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue);
     175    STDMETHOD(GetExtraDataKeys) (ComSafeArrayOut(BSTR, aKeys));
    171176    STDMETHOD(GetExtraData) (IN_BSTR aKey, BSTR *aValue);
    172177    STDMETHOD(SetExtraData) (IN_BSTR aKey, IN_BSTR aValue);
     
    183188                                      BSTR *aChanged, BSTR *aValues);
    184189
    185     STDMETHOD(SaveSettings)();
    186     STDMETHOD(SaveSettingsWithBackup) (BSTR *aBakFileName);
    187 
    188190//    STDMETHOD(CreateDHCPServerForInterface) (/*IHostNetworkInterface * aIinterface, */IDHCPServer ** aServer);
    189191    STDMETHOD(CreateDHCPServer) (IN_BSTR aName, IDHCPServer ** aServer);
     
    257259#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    258260
     261    const Utf8Str& getDefaultMachineFolder() const;
     262    const Utf8Str& getDefaultHardDiskFolder() const;
     263    const Utf8Str& getDefaultHardDiskFormat() const;
    259264
    260265    /** Returns the VirtualBox home directory */
    261266    const Utf8Str &homeDir() { return mData.mHomeDir; }
    262267
    263     int calculateFullPath (const char *aPath, Utf8Str &aResult);
    264     void calculateRelativePath (const char *aPath, Utf8Str &aResult);
     268    int calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult);
     269    void calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult);
    265270
    266271    HRESULT registerHardDisk(HardDisk *aHardDisk, bool aSaveRegistry = true);
     
    276281
    277282    HRESULT saveSettings();
    278     HRESULT updateSettings (const char *aOldPath, const char *aNewPath);
    279 
    280     const Bstr &settingsFileName() { return mData.mCfgFile.mName; }
    281 
    282     static HRESULT ensureFilePathExists (const char *aFileName);
    283 
    284     static HRESULT loadSettingsTree (settings::XmlTreeBackend &aTree,
    285                                      xml::File &aFile,
    286                                      bool aValidate,
    287                                      bool aCatchLoadErrors,
    288                                      bool aAddDefaults,
    289                                      Utf8Str *aFormatVersion = NULL);
    290 
    291     /**
    292      * Shortcut to loadSettingsTree (aTree, aFile, true, true, true).
    293      *
    294      * Used when the settings file is to be loaded for the first time for the
    295      * given object in order to recreate it from the stored settings.
    296      *
    297      * @param aFormatVersion Where to store the current format version of the
    298      *                       loaded settings tree.
    299      */
    300     static HRESULT loadSettingsTree_FirstTime (settings::XmlTreeBackend &aTree,
    301                                                xml::File &aFile,
    302                                                Utf8Str &aFormatVersion)
     283    HRESULT updateSettings(const char *aOldPath, const char *aNewPath);
     284
     285    static HRESULT ensureFilePathExists(const Utf8Str &strFileName);
     286
     287    static HRESULT handleUnexpectedExceptions (RT_SRC_POS_DECL);
     288
     289    const Utf8Str& settingsFilePath()
    303290    {
    304         return loadSettingsTree (aTree, aFile, true, true, true,
    305                                  &aFormatVersion);
     291        return m_strSettingsFilePath;
    306292    }
    307 
    308     /**
    309      * Shortcut to loadSettingsTree (aTree, aFile, true, false, true).
    310      *
    311      * Used when the settings file is loaded again (after it has been fully
    312      * checked and validated by #loadSettingsTree_FirstTime()) in order to
    313      * look at settings that don't have any representation within object's
    314      * data fields.
    315      */
    316     static HRESULT loadSettingsTree_Again (settings::XmlTreeBackend &aTree,
    317                                            xml::File &aFile)
    318     {
    319         return loadSettingsTree (aTree, aFile, true, false, true);
    320     }
    321 
    322     /**
    323      * Shortcut to loadSettingsTree (aTree, aFile, true, false, false).
    324      *
    325      * Used when the settings file is loaded again (after it has been fully
    326      * checked and validated by #loadSettingsTree_FirstTime()) in order to
    327      * update some settings and then save them back.
    328      */
    329     static HRESULT loadSettingsTree_ForUpdate (settings::XmlTreeBackend &aTree,
    330                                                xml::File &aFile)
    331     {
    332         return loadSettingsTree (aTree, aFile, true, false, false);
    333     }
    334 
    335     static HRESULT saveSettingsTree (settings::TreeBackend &aTree,
    336                                      xml::File &aFile,
    337                                      Utf8Str &aFormatVersion);
    338 
    339     static HRESULT backupSettingsFile (const Bstr &aFileName,
    340                                        const Utf8Str &aOldFormat,
    341                                        Bstr &aBakFileName);
    342 
    343     static HRESULT handleUnexpectedExceptions (RT_SRC_POS_DECL);
    344293
    345294    /**
     
    364313private:
    365314
    366     typedef std::list <ComObjPtr<Machine> > MachineList;
    367     typedef std::list <ComObjPtr<GuestOSType> > GuestOSTypeList;
    368 
    369     typedef std::map <Guid, ComPtr<IProgress> > ProgressMap;
    370 
    371     typedef std::list <ComObjPtr<HardDisk> > HardDiskList;
    372     typedef std::list <ComObjPtr<DVDImage> > DVDImageList;
    373     typedef std::list <ComObjPtr<FloppyImage> > FloppyImageList;
    374     typedef std::list <ComObjPtr<SharedFolder> > SharedFolderList;
    375     typedef std::list <ComObjPtr<DHCPServer> > DHCPServerList;
    376 
    377     typedef std::map <Guid, ComObjPtr<HardDisk> > HardDiskMap;
     315    typedef std::list< ComObjPtr<Machine> > MachineList;
     316    typedef std::list< ComObjPtr<GuestOSType> > GuestOSTypeList;
     317
     318    typedef std::map<Guid, ComPtr<IProgress> > ProgressMap;
     319
     320    typedef std::list< ComObjPtr<HardDisk> > HardDiskList;
     321    typedef std::list< ComObjPtr<DVDImage> > DVDImageList;
     322    typedef std::list< ComObjPtr<FloppyImage> > FloppyImageList;
     323    typedef std::list< ComObjPtr<SharedFolder> > SharedFolderList;
     324    typedef std::list< ComObjPtr<DHCPServer> > DHCPServerList;
     325
     326    typedef std::map<Guid, ComObjPtr<HardDisk> > HardDiskMap;
    378327
    379328    /**
     
    390339                                     Utf8Str &aConflictType);
    391340
    392     HRESULT loadMachines (const settings::Key &aGlobal);
    393     HRESULT loadMedia (const settings::Key &aGlobal);
    394     HRESULT loadNetservices (const settings::Key &aGlobal);
    395 
    396341    HRESULT registerMachine (Machine *aMachine);
    397342
    398343    HRESULT registerDHCPServer(DHCPServer *aDHCPServer,
    399                                          bool aSaveRegistry = true);
     344                               bool aSaveRegistry = true);
    400345    HRESULT unregisterDHCPServer(DHCPServer *aDHCPServer,
    401                                          bool aSaveRegistry = true);
    402 
    403     HRESULT lockConfig();
    404     HRESULT unlockConfig();
    405 
    406     /** @note This method is not thread safe */
    407     bool isConfigLocked() { return mData.mCfgFile.mHandle != NIL_RTFILE; }
     346                                 bool aSaveRegistry = true);
     347
     348    // VirtualBox main settings file
     349    const Utf8Str m_strSettingsFilePath;
     350    settings::MainConfigFile *m_pMainConfigFile;
    408351
    409352    /**
     
    416359        Data();
    417360
    418         struct CfgFile
    419         {
    420             CfgFile() : mHandle (NIL_RTFILE) {}
    421 
    422             const Bstr mName;
    423             RTFILE mHandle;
    424             /** Flag indicating that the config file is read-only. */
    425             BOOL mReadonly;
    426         };
    427 
    428361        // const data members not requiring locking
    429         const Utf8Str mHomeDir;
     362        const Utf8Str                       mHomeDir;
    430363
    431364        // const objects not requiring locking
    432         const ComObjPtr<Host> mHost;
    433         const ComObjPtr<SystemProperties> mSystemProperties;
     365        const ComObjPtr<Host>               mHost;
     366        const ComObjPtr<SystemProperties>   mSystemProperties;
    434367#ifdef VBOX_WITH_RESOURCE_USAGE_API
    435368        const ComObjPtr<PerformanceCollector> mPerformanceCollector;
    436369#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    437370
    438         CfgFile mCfgFile;
    439 
    440         Utf8Str mSettingsFileVersion;
    441 
    442         MachineList mMachines;
    443         GuestOSTypeList mGuestOSTypes;
    444 
    445         ProgressMap mProgressOperations;
    446 
    447         HardDiskList mHardDisks;
    448         DVDImageList mDVDImages;
    449         FloppyImageList mFloppyImages;
    450         SharedFolderList mSharedFolders;
    451         DHCPServerList mDHCPServers;
     371        MachineList                         mMachines;
     372        GuestOSTypeList                     mGuestOSTypes;
     373
     374        ProgressMap                         mProgressOperations;
     375
     376        HardDiskList                        mHardDisks;
     377        DVDImageList                        mDVDImages;
     378        FloppyImageList                     mFloppyImages;
     379        SharedFolderList                    mSharedFolders;
     380        DHCPServerList                      mDHCPServers;
    452381
    453382        /// @todo NEWMEDIA do we really need this map? Used only in
    454383        /// find() it seems
    455         HardDiskMap mHardDiskMap;
    456 
    457         CallbackList mCallbacks;
     384        HardDiskMap                         mHardDiskMap;
     385
     386        CallbackList                        mCallbacks;
    458387    };
    459388
     
    508437    RWLockHandle mChildrenMapLockHandle;
    509438
     439    /* static variables (defined in VirtualBoxImpl.cpp) */
    510440    static Bstr sVersion;
    511441    static ULONG sRevision;
    512442    static Bstr sPackageType;
    513     static Bstr sSettingsFormatVersion;
    514443
    515444    static DECLCALLBACK(int) ClientWatcher (RTTHREAD thread, void *pvUser);
  • trunk/src/VBox/Main/include/VirtualBoxImplExtra.h

    r21292 r22173  
    2525#define ____H_VIRTUALBOXIMPLEXTRA
    2626
    27 class SettingsTreeHelper : public settings::XmlTreeBackend::InputResolver
    28                          , public settings::XmlTreeBackend::AutoConverter
    29 {
    30 public:
    31 
    32     // InputResolver interface
    33     xml::Input *resolveEntity (const char *aURI, const char *aID);
    34 
    35     // AutoConverter interface
    36     bool needsConversion (const settings::Key &aRoot, char **aOldVersion) const;
    37     const char *templateUri() const;
    38 };
    39 
    4027#endif // ____H_VIRTUALBOXIMPL EXTRA
    41 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h

    r22143 r22173  
    6666
    6767#endif /* ____H_VIRTUALBOXXMLUTIL */
    68 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
     68
  • trunk/src/VBox/Main/xml/Settings.cpp

    r21878 r22173  
    1919 */
    2020
    21 #include <iprt/err.h>
    22 #include <iprt/file.h>
    23 #include <iprt/lock.h>
    24 
    25 #include <libxml/tree.h>
    26 #include <libxml/parser.h>
    27 #include <libxml/globals.h>
    28 #include <libxml/xmlIO.h>
    29 #include <libxml/xmlsave.h>
    30 #include <libxml/uri.h>
    31 
    32 #include <libxml/xmlschemas.h>
    33 
    34 #include <libxslt/xsltInternals.h>
    35 #include <libxslt/transform.h>
    36 #include <libxslt/xsltutils.h>
    37 
    38 #include <list>
    39 
    40 // #include <string.h>
    41 
     21#include "VBox/com/string.h"
    4222#include "VBox/settings.h"
    43 
    44 #include "Logging.h"
    45 
    46 namespace settings
    47 {
    48 
    49 // Helpers
    50 ////////////////////////////////////////////////////////////////////////////////
    51 
    52 inline int sFromHex (char aChar)
    53 {
    54     if (aChar >= '0' && aChar <= '9')
    55         return aChar - '0';
    56     if (aChar >= 'A' && aChar <= 'F')
    57         return aChar - 'A' + 0xA;
    58     if (aChar >= 'a' && aChar <= 'f')
    59         return aChar - 'a' + 0xA;
    60 
    61     throw ENoConversion(com::Utf8StrFmt("'%c' (0x%02X) is not hex", aChar, aChar));
    62 }
    63 
    64 inline char sToHex (int aDigit)
    65 {
    66     return (aDigit < 0xA) ? aDigit + '0' : aDigit - 0xA + 'A';
    67 }
    68 
    69 static char *duplicate_chars (const char *that)
    70 {
    71     char *result = NULL;
    72     if (that != NULL)
    73     {
    74         size_t len = strlen (that) + 1;
    75         result = new char [len];
    76         if (result != NULL)
    77             memcpy (result, that, len);
    78     }
    79     return result;
    80 }
    81 
    82 //////////////////////////////////////////////////////////////////////////////
    83 // string -> type conversions
    84 //////////////////////////////////////////////////////////////////////////////
    85 
    86 uint64_t FromStringInteger (const char *aValue, bool aSigned,
    87                             int aBits, uint64_t aMin, uint64_t aMax)
    88 {
    89     if (aValue == NULL)
    90         throw ENoValue();
    91 
    92     switch (aBits)
    93     {
    94         case 8:
    95         case 16:
    96         case 32:
    97         case 64:
     23#include <iprt/xml_cpp.h>
     24#include <iprt/stream.h>
     25#include <iprt/ctype.h>
     26
     27#include "VirtualBoxXMLUtil.h"
     28
     29using namespace com;
     30using namespace settings;
     31
     32/**
     33 * Opaque data structore for ConfigFileBase (only declared
     34 * in header, defined only here).
     35 */
     36
     37struct ConfigFileBase::Data
     38{
     39    Data()
     40        : pParser(NULL),
     41          pDoc(NULL),
     42          pelmRoot(NULL)
     43    {}
     44
     45    ~Data()
     46    {
     47        cleanup();
     48    }
     49
     50    iprt::MiniString        strFilename;
     51    bool                    fFileExists;
     52
     53    xml::XmlFileParser      *pParser;
     54    xml::Document           *pDoc;
     55    xml::ElementNode        *pelmRoot;
     56    com::Utf8Str            strSettingsVersionFull;     // e.g. "1.7-linux"
     57    SettingsVersion_T       sv;                         // e.g. SETTINGS_VERSION_1_7
     58
     59    void cleanup()
     60    {
     61        if (pDoc)
     62        {
     63            delete pDoc;
     64            pDoc = NULL;
     65            pelmRoot = NULL;
     66        }
     67
     68        if (pParser)
     69        {
     70            delete pParser;
     71            pParser = NULL;
     72        }
     73    }
     74};
     75
     76/**
     77 * Private exception class (not in the header file) that makes
     78 * throwing xml::LogicError instances easier. That class is public
     79 * and should be caught by client code.
     80 */
     81class settings::ConfigFileError : public xml::LogicError
     82{
     83public:
     84    ConfigFileError(const ConfigFileBase *file, const char *pcszFormat, ...)
     85        : xml::LogicError()
     86    {
     87        va_list args;
     88        va_start(args, pcszFormat);
     89        Utf8StrFmtVA what(pcszFormat, args);
     90        va_end(args);
     91
     92        Utf8StrFmt str("Error reading %s. %s", file->m->strFilename.c_str(), what.c_str());
     93
     94        setWhat(str.c_str());
     95    }
     96};
     97
     98/**
     99 * Constructor. Allocates the XML internals.
     100 * @param strFilename
     101 */
     102ConfigFileBase::ConfigFileBase(const com::Utf8Str *pstrFilename)
     103    : m(new Data)
     104{
     105    m->fFileExists = false;
     106
     107    if (pstrFilename)
     108    {
     109        m->strFilename = *pstrFilename;
     110
     111        m->pParser = new xml::XmlFileParser;
     112        m->pDoc = new xml::Document;
     113        m->pParser->read(*pstrFilename,
     114                        *m->pDoc);
     115
     116        m->fFileExists = true;
     117
     118        m->pelmRoot = m->pDoc->getRootElement();
     119        if (!m->pelmRoot || !m->pelmRoot->nameEquals("VirtualBox"))
     120            throw ConfigFileError(this, N_("Root element in VirtualBox settings files must be \"VirtualBox\"."));
     121
     122        if (!(m->pelmRoot->getAttributeValue("version", m->strSettingsVersionFull)))
     123            throw ConfigFileError(this, N_("Required VirtualBox/version attribute is missing"));
     124
     125        m->sv = SettingsVersion_Null;
     126        if (m->strSettingsVersionFull.length() > 3)
     127        {
     128            const char *pcsz = m->strSettingsVersionFull.c_str();
     129            if (    (pcsz[0] == '1')
     130                && (pcsz[1] == '.')
     131                && (pcsz[3] == '-')
     132            )
     133            {
     134                if (pcsz[2] == '7')
     135                    m->sv = SettingsVersion_v1_7;
     136                else if (pcsz[2] == '8')
     137                    m->sv = SettingsVersion_v1_8;
     138            }
     139        }
     140
     141        if (m->sv == SettingsVersion_Null)
     142            throw ConfigFileError(this, N_("Cannot handle settings version '%s'"), m->strSettingsVersionFull.c_str());
     143    }
     144    else
     145    {
     146        m->strSettingsVersionFull = VBOX_XML_VERSION_FULL;
     147        m->sv = SettingsVersion_v1_8;
     148    }
     149}
     150
     151/**
     152 * Clean up.
     153 */
     154ConfigFileBase::~ConfigFileBase()
     155{
     156    if (m)
     157    {
     158        delete m;
     159        m = NULL;
     160    }
     161}
     162
     163/**
     164 * Helper function that parses a UUID in string form into
     165 * a com::Guid item. Since that uses an IPRT function which
     166 * does not accept "{}" characters around the UUID string,
     167 * we handle that here. Throws on errors.
     168 * @param guid
     169 * @param strUUID
     170 */
     171void ConfigFileBase::parseUUID(Guid &guid,
     172                               const Utf8Str &strUUID) const
     173{
     174    // {5f102a55-a51b-48e3-b45a-b28d33469488}
     175    // 01234567890123456789012345678901234567
     176    //           1         2         3
     177    if (    (strUUID[0] == '{')
     178         && (strUUID[37] == '}')
     179       )
     180        guid = strUUID.substr(1, 36).c_str();
     181    else
     182        guid = strUUID.c_str();
     183
     184    if (guid.isEmpty())
     185        throw ConfigFileError(this, N_("UUID \"%s\" has invalid format"), strUUID.c_str());
     186}
     187
     188/**
     189 * Parses the given string in str and attempts to treat it as an ISO
     190 * date/time stamp to put into timestamp. Throws on errors.
     191 * @param timestamp
     192 * @param str
     193 */
     194void ConfigFileBase::parseTimestamp(RTTIMESPEC &timestamp,
     195                                    const com::Utf8Str &str) const
     196{
     197    const char *pcsz = str.c_str();
     198        //  yyyy-mm-ddThh:mm:ss
     199        // "2009-07-10T11:54:03Z"
     200        //  01234567890123456789
     201        //            1
     202    if (str.length() > 19)
     203    {
     204        // timezone must either be unspecified or 'Z' for UTC
     205        if (    (pcsz[19])
     206             && (pcsz[19] != 'Z')
     207           )
     208            throw ConfigFileError(this, N_("Cannot handle ISO timestamp '%s': is not UTC date"), str.c_str());
     209
     210        int32_t yyyy;
     211        uint32_t mm, dd, hh, min, secs;
     212        if (    (pcsz[4] == '-')
     213             && (pcsz[7] == '-')
     214             && (pcsz[10] == 'T')
     215             && (pcsz[13] == ':')
     216             && (pcsz[16] == ':')
     217           )
     218        {
     219            int rc;
     220            if (    (RT_SUCCESS(rc = RTStrToInt32Ex(pcsz, NULL, 0, &yyyy)))
     221                        // could theoretically be negative but let's assume that nobody
     222                        // created virtual machines before the Christian era
     223                 && (RT_SUCCESS(rc = RTStrToUInt32Ex(pcsz + 5, NULL, 0, &mm)))
     224                 && (RT_SUCCESS(rc = RTStrToUInt32Ex(pcsz + 8, NULL, 0, &dd)))
     225                 && (RT_SUCCESS(rc = RTStrToUInt32Ex(pcsz + 11, NULL, 0, &hh)))
     226                 && (RT_SUCCESS(rc = RTStrToUInt32Ex(pcsz + 14, NULL, 0, &min)))
     227                 && (RT_SUCCESS(rc = RTStrToUInt32Ex(pcsz + 17, NULL, 0, &secs)))
     228               )
     229            {
     230                RTTIME time = { yyyy,
     231                                (uint8_t)mm,
     232                                0,
     233                                0,
     234                                (uint8_t)dd,
     235                                (uint8_t)hh,
     236                                (uint8_t)min,
     237                                (uint8_t)secs,
     238                                0,
     239                                RTTIME_FLAGS_TYPE_UTC };
     240                if (RTTimeNormalize(&time))
     241                    if (RTTimeImplode(&timestamp, &time))
     242                        return;
     243            }
     244
     245            throw ConfigFileError(this, N_("Cannot parse ISO timestamp '%s': runtime error, %Rra"), str.c_str(), rc);
     246        }
     247
     248        throw ConfigFileError(this, N_("Cannot parse ISO timestamp '%s': invalid format"), str.c_str());
     249    }
     250}
     251
     252/**
     253 * Helper to create a string for a RTTIMESPEC for writing out ISO timestamps.
     254 * @param stamp
     255 * @return
     256 */
     257com::Utf8Str ConfigFileBase::makeString(const RTTIMESPEC &stamp)
     258{
     259    RTTIME time;
     260    if (!RTTimeExplode(&time, &stamp))
     261        throw ConfigFileError(this, N_("Timespec %lld ms is invalid"), RTTimeSpecGetMilli(&stamp));
     262
     263    return Utf8StrFmt("%04ld-%02hd-%02hdT%02hd:%02hd:%02hdZ",
     264                      time.i32Year,
     265                      (uint16_t)time.u8Month,
     266                      (uint16_t)time.u8MonthDay,
     267                      (uint16_t)time.u8Hour,
     268                      (uint16_t)time.u8Minute,
     269                      (uint16_t)time.u8Second);
     270}
     271
     272com::Utf8Str ConfigFileBase::makeString(const Guid &guid)
     273{
     274    Utf8Str str("{");
     275    str.append(guid.toString());
     276    str.append("}");
     277    return str;
     278}
     279
     280/**
     281 * Helper method to read in an ExtraData subtree and stores its contents
     282 * in the given map of extradata items. Used for both main and machine
     283 * extradata (MainConfigFile and MachineConfigFile).
     284 * @param elmExtraData
     285 * @param map
     286 */
     287void ConfigFileBase::readExtraData(const xml::ElementNode &elmExtraData,
     288                                   ExtraDataItemsMap &map)
     289{
     290    xml::NodesLoop nlLevel4(elmExtraData);
     291    const xml::ElementNode *pelmExtraDataItem;
     292    while ((pelmExtraDataItem = nlLevel4.forAllNodes()))
     293    {
     294        if (pelmExtraDataItem->nameEquals("ExtraDataItem"))
     295        {
     296            // <ExtraDataItem name="GUI/LastWindowPostion" value="97,88,981,858"/>
     297            Utf8Str strName, strValue;
     298            if (    ((pelmExtraDataItem->getAttributeValue("name", strName)))
     299                 && ((pelmExtraDataItem->getAttributeValue("value", strValue)))
     300               )
     301                map[strName] = strValue;
     302            else
     303                throw ConfigFileError(this, N_("ExtraDataItem element must have name and value attributes"));
     304        }
     305        else
     306            throw ConfigFileError(this, N_("Invalid element %s in ExtraData section"), pelmExtraDataItem->getName());
     307    }
     308}
     309
     310/**
     311 * Reads <USBDeviceFilter> entries from under the given elmDeviceFilters node and
     312 * stores them in the given linklist. This is in ConfigFileBase because it's used
     313 * from both MainConfigFile (for host filters) and MachineConfigFile (for machine
     314 * filters).
     315 * @param elmDeviceFilters
     316 * @param ll
     317 */
     318void ConfigFileBase::readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters,
     319                                          USBDeviceFiltersList &ll)
     320{
     321    xml::NodesLoop nl1(elmDeviceFilters, "DeviceFilter");
     322    const xml::ElementNode *pelmLevel4Child;
     323    while ((pelmLevel4Child = nl1.forAllNodes()))
     324    {
     325        USBDeviceFilter flt;
     326        flt.action = USBDeviceFilterAction_Ignore;
     327        Utf8Str strAction;
     328        if (    (pelmLevel4Child->getAttributeValue("name", flt.strName))
     329             && (pelmLevel4Child->getAttributeValue("active", flt.fActive))
     330           )
     331        {
     332            pelmLevel4Child->getAttributeValue("vendorId", flt.strVendorId);
     333            pelmLevel4Child->getAttributeValue("productId", flt.strProductId);
     334            pelmLevel4Child->getAttributeValue("revision", flt.strRevision);
     335            pelmLevel4Child->getAttributeValue("manufacturer", flt.strManufacturer);
     336            pelmLevel4Child->getAttributeValue("product", flt.strProduct);
     337            pelmLevel4Child->getAttributeValue("serialNumber", flt.strSerialNumber);
     338            pelmLevel4Child->getAttributeValue("port", flt.strPort);
     339
     340            // the next 2 are irrelevant for host USB objects
     341            pelmLevel4Child->getAttributeValue("remote", flt.strRemote);
     342            pelmLevel4Child->getAttributeValue("maskedInterfaces", flt.ulMaskedInterfaces);
     343
     344            // action is only used with host USB objects
     345            if (pelmLevel4Child->getAttributeValue("action", strAction))
     346            {
     347                if (strAction == "Ignore")
     348                    flt.action = USBDeviceFilterAction_Ignore;
     349                else if (strAction == "Hold")
     350                    flt.action = USBDeviceFilterAction_Hold;
     351                else
     352                    throw ConfigFileError(this, N_("Invalid value %s in DeviceFilter/action attribute"), strAction.c_str());
     353            }
     354
     355            ll.push_back(flt);
     356        }
     357    }
     358}
     359
     360/**
     361 * Creates a new stub xml::Document in the m->pDoc member with the
     362 * root "VirtualBox" element set up. This is used by both
     363 * MainConfigFile and MachineConfigFile when writing out their XML.
     364 */
     365void ConfigFileBase::createStubDocument()
     366{
     367    Assert(m->pDoc == NULL);
     368    m->pDoc = new xml::Document;
     369
     370    m->pelmRoot = m->pDoc->createRootElement("VirtualBox");
     371    m->pelmRoot->setAttribute("xmlns", VBOX_XML_NAMESPACE);
     372
     373    const char *pcszVersion;
     374    switch (m->sv)
     375    {
     376        case SettingsVersion_v1_7:
     377            pcszVersion = "1.7";
     378        break;
     379        case SettingsVersion_v1_8:
     380            pcszVersion = "1.8";
     381        break;
     382    }
     383    m->pelmRoot->setAttribute("version", Utf8StrFmt("%s-%s",
     384                                                    pcszVersion,
     385                                                    VBOX_XML_PLATFORM));       // e.g. "linux"
     386}
     387
     388/**
     389 *
     390 * @param elmParent
     391 * @param me
     392 */
     393void ConfigFileBase::writeExtraData(xml::ElementNode &elmParent,
     394                                    const ExtraDataItemsMap &me)
     395{
     396    if (me.size())
     397    {
     398        xml::ElementNode *pelmExtraData = elmParent.createChild("ExtraData");
     399        for (ExtraDataItemsMap::const_iterator it = me.begin();
     400             it != me.end();
     401             ++it)
     402        {
     403            const Utf8Str &strName = it->first;
     404            const Utf8Str &strValue = it->second;
     405            xml::ElementNode *pelmThis = pelmExtraData->createChild("ExtraDataItem");
     406            pelmThis->setAttribute("name", strName);
     407            pelmThis->setAttribute("value", strValue);
     408        }
     409    }
     410}
     411
     412/**
     413 * Creates <DeviceFilter> nodes under the given parent element according to
     414 * the contents of the given USBDeviceFiltersList. If fHostMode is true,
     415 * this means that we're supposed to write filters for the IHost interface
     416 * (respect "action", omit "strRemote" and "ulMaskedInterfaces" in
     417 * struct USBDeviceFilter).
     418 * @param elmParent
     419 * @param ll
     420 * @param fHostMode
     421 */
     422void ConfigFileBase::writeUSBDeviceFilters(xml::ElementNode &elmParent,
     423                                           const USBDeviceFiltersList &ll,
     424                                           bool fHostMode)
     425{
     426    for (USBDeviceFiltersList::const_iterator it = ll.begin();
     427         it != ll.end();
     428         ++it)
     429    {
     430        const USBDeviceFilter &flt = *it;
     431        xml::ElementNode *pelmFilter = elmParent.createChild("DeviceFilter");
     432        pelmFilter->setAttribute("name", flt.strName);
     433        pelmFilter->setAttribute("active", flt.fActive);
     434        if (flt.strVendorId.length())
     435            pelmFilter->setAttribute("vendorId", flt.strVendorId);
     436        if (flt.strProductId.length())
     437            pelmFilter->setAttribute("productId", flt.strProductId);
     438        if (flt.strRevision.length())
     439            pelmFilter->setAttribute("revision", flt.strRevision);
     440        if (flt.strManufacturer.length())
     441            pelmFilter->setAttribute("manufacturer", flt.strManufacturer);
     442        if (flt.strProduct.length())
     443            pelmFilter->setAttribute("product", flt.strProduct);
     444        if (flt.strSerialNumber.length())
     445            pelmFilter->setAttribute("serialNumber", flt.strSerialNumber);
     446        if (flt.strPort.length())
     447            pelmFilter->setAttribute("port", flt.strPort);
     448
     449        if (fHostMode)
     450        {
     451            const char *pcsz =
     452                (flt.action == USBDeviceFilterAction_Ignore) ? "Ignore"
     453                : /*(flt.action == USBDeviceFilterAction_Hold) ?*/ "Hold";
     454            pelmFilter->setAttribute("action", pcsz);
     455        }
     456        else
     457        {
     458            if (flt.strRemote.length())
     459                pelmFilter->setAttribute("remote", flt.strRemote);
     460            if (flt.ulMaskedInterfaces)
     461                pelmFilter->setAttribute("maskedInterfaces", flt.ulMaskedInterfaces);
     462        }
     463    }
     464}
     465
     466/**
     467 * Cleans up memory allocated by the internal XML parser. To be called by
     468 * descendant classes when they're done analyzing the DOM tree to discard it.
     469 */
     470void ConfigFileBase::clearDocument()
     471{
     472    m->cleanup();
     473}
     474
     475/**
     476 * Returns true only if the underlying config file exists on disk;
     477 * either because the file has been loaded from disk, or it's been written
     478 * to disk, or both.
     479 * @return
     480 */
     481bool ConfigFileBase::fileExists()
     482{
     483    return m->fFileExists;
     484}
     485
     486/**
     487 * Reads one <MachineEntry> from the main VirtualBox.xml file.
     488 * @param elmMachineRegistry
     489 */
     490void MainConfigFile::readMachineRegistry(const xml::ElementNode &elmMachineRegistry)
     491{
     492    // <MachineEntry uuid="{ xxx }" src="   xxx "/>
     493    xml::NodesLoop nl1(elmMachineRegistry);
     494    const xml::ElementNode *pelmChild1;
     495    while ((pelmChild1 = nl1.forAllNodes()))
     496    {
     497        if (pelmChild1->nameEquals("MachineEntry"))
     498        {
     499            MachineRegistryEntry mre;
     500            Utf8Str strUUID;
     501            if (    ((pelmChild1->getAttributeValue("uuid", strUUID)))
     502                 && ((pelmChild1->getAttributeValue("src", mre.strSettingsFile)))
     503               )
     504            {
     505                parseUUID(mre.uuid, strUUID);
     506                llMachines.push_back(mre);
     507            }
     508            else
     509                throw ConfigFileError(this, N_("MachineEntry element must have uuid and src attributes"));
     510        }
     511        else
     512            throw ConfigFileError(this, N_("Invalid element %s in MachineRegistry section"), pelmChild1->getName());
     513    }
     514}
     515
     516/**
     517 * Reads a media registry entry from the main VirtualBox.xml file.
     518 * @param t
     519 * @param elmMedium
     520 * @param llMedia
     521 */
     522void MainConfigFile::readMedium(MediaType t,
     523                                const xml::ElementNode &elmMedium,  // MediaRegistry/HardDisks or a single HardDisk node if recursing
     524                                MediaList &llMedia)
     525{
     526    // <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
     527    settings::Medium med;
     528    Utf8Str strUUID;
     529    if (    (elmMedium.getAttributeValue("uuid", strUUID))
     530         && (elmMedium.getAttributeValue("location", med.strLocation))
     531       )
     532    {
     533        parseUUID(med.uuid, strUUID);
     534        elmMedium.getAttributeValue("Description", med.strDescription);       // optional
     535
     536        if (t == HardDisk)
     537        {
     538            if (!(elmMedium.getAttributeValue("format", med.strFormat)))
     539                throw ConfigFileError(this, N_("HardDisk element must have format attribute"));
     540
     541            if (!(elmMedium.getAttributeValue("autoReset", med.fAutoReset)))
     542                med.fAutoReset = false;
     543
     544            Utf8Str strType;
     545            if ((elmMedium.getAttributeValue("type", strType)))
     546            {
     547                if (strType == "Normal")
     548                    med.hdType = HardDiskType_Normal;
     549                else if (strType == "Immutable")
     550                    med.hdType = HardDiskType_Immutable;
     551                else if (strType == "Writethrough")
     552                    med.hdType = HardDiskType_Writethrough;
     553                else
     554                    throw ConfigFileError(this, N_("HardDisk/type attribute must be one of Normal, Immutable or Writethrough"));
     555            }
     556        }
     557
     558        // recurse to handle children
     559        xml::NodesLoop nl2(elmMedium);
     560        const xml::ElementNode *pelmHDChild;
     561        while ((pelmHDChild = nl2.forAllNodes()))
     562        {
     563            if (    t == HardDisk
     564                 && (pelmHDChild->nameEquals("HardDisk"))
     565               )
     566                // recurse with this element and push the child onto our current children list
     567                readMedium(t,
     568                           *pelmHDChild,
     569                           med.llChildren);
     570            else if (pelmHDChild->nameEquals("Property"))
     571            {
     572                Utf8Str strPropName, strPropValue;
     573                if (    (pelmHDChild->getAttributeValue("name", strPropName))
     574                     && (pelmHDChild->getAttributeValue("value", strPropValue))
     575                   )
     576                    med.properties[strPropName] = strPropValue;
     577                else
     578                    throw ConfigFileError(this, N_("HardDisk/Property element must have name and value attributes"));
     579            }
     580        }
     581
     582        llMedia.push_back(med);
     583    }
     584    else
     585        throw ConfigFileError(this, N_("%s element must have uuid and location attributes"), elmMedium.getName());
     586}
     587
     588/**
     589 * Reads in the entire <MediaRegistry> chunk.
     590 * @param elmMediaRegistry
     591 */
     592void MainConfigFile::readMediaRegistry(const xml::ElementNode &elmMediaRegistry)
     593{
     594    // <MachineEntry uuid="{ xxx }" src="   xxx "/>
     595    xml::NodesLoop nl1(elmMediaRegistry);
     596    const xml::ElementNode *pelmChild1;
     597    while ((pelmChild1 = nl1.forAllNodes()))
     598    {
     599        MediaType t = Error;
     600        if (pelmChild1->nameEquals("HardDisks"))
     601            t = HardDisk;
     602        else if (pelmChild1->nameEquals("DVDImages"))
     603            t = DVDImage;
     604        else if (pelmChild1->nameEquals("FloppyImages"))
     605            t = FloppyImage;
     606        else
     607            throw ConfigFileError(this, N_("Invalid element %s in MediaRegistry section"), pelmChild1->getName());
     608
     609        xml::NodesLoop nl1(*pelmChild1);
     610        const xml::ElementNode *pelmMedium;
     611        while ((pelmMedium = nl1.forAllNodes()))
     612        {
     613            if (    t == HardDisk
     614                 && (pelmMedium->nameEquals("HardDisk"))
     615               )
     616                readMedium(t,
     617                           *pelmMedium,
     618                           llHardDisks);      // list to append hard disk data to: the root list
     619            else if (    t == DVDImage
     620                      && (pelmMedium->nameEquals("Image"))
     621                    )
     622                readMedium(t,
     623                           *pelmMedium,
     624                           llDvdImages);      // list to append dvd images to: the root list
     625            else if (    t == FloppyImage
     626                      && (pelmMedium->nameEquals("Image"))
     627                    )
     628                readMedium(t,
     629                           *pelmMedium,
     630                           llFloppyImages);      // list to append floppy images to: the root list
     631        }
     632    }
     633}
     634
     635/**
     636 * Reads in the <DHCPServers> chunk.
     637 * @param elmDHCPServers
     638 */
     639void MainConfigFile::readDHCPServers(const xml::ElementNode &elmDHCPServers)
     640{
     641    xml::NodesLoop nl1(elmDHCPServers);
     642    const xml::ElementNode *pelmServer;
     643    while ((pelmServer = nl1.forAllNodes()))
     644    {
     645        if (pelmServer->nameEquals("DHCPServer"))
     646        {
     647            DHCPServer srv;
     648            if (    (pelmServer->getAttributeValue("networkName", srv.strNetworkName))
     649                 && (pelmServer->getAttributeValue("IPAddress", srv.strIPAddress))
     650                 && (pelmServer->getAttributeValue("networkMask", srv.strIPNetworkMask))
     651                 && (pelmServer->getAttributeValue("lowerIP", srv.strIPLower))
     652                 && (pelmServer->getAttributeValue("upperIP", srv.strIPUpper))
     653                 && (pelmServer->getAttributeValue("enabled", srv.fEnabled))
     654               )
     655                llDhcpServers.push_back(srv);
     656            else
     657                throw ConfigFileError(this, N_("DHCPServer element must have networkName, IPAddress, networkMask, lowerIP, upperIP and enabled attributes"));
     658        }
     659        else
     660            throw ConfigFileError(this, N_("Invalid element %s in DHCPServers section"), pelmServer->getName());
     661    }
     662}
     663
     664/**
     665 * Constructor.
     666 *
     667 * If pstrFilename is != NULL, this reads the given settings file into the member
     668 * variables and various substructures and lists. Otherwise, the member variables
     669 * are initialized with default values.
     670 *
     671 * Throws variants of xml::Error for I/O, XML and logical content errors, which
     672 * the caller should catch; if this constructor does not throw, then the file has
     673 * been successfully read.
     674 *
     675 * @param strFilename
     676 */
     677MainConfigFile::MainConfigFile(const Utf8Str *pstrFilename)
     678    : ConfigFileBase(pstrFilename)
     679{
     680    if (pstrFilename)
     681    {
     682        // the ConfigFileBase constructor has loaded the XML file, so now
     683        // we need only analyze what is in there
     684        xml::NodesLoop nlRootChildren(*m->pelmRoot);
     685        const xml::ElementNode *pelmRootChild;
     686        while ((pelmRootChild = nlRootChildren.forAllNodes()))
     687        {
     688            if (pelmRootChild->nameEquals("Global"))
     689            {
     690                xml::NodesLoop nlGlobalChildren(*pelmRootChild);
     691                const xml::ElementNode *pelmGlobalChild;
     692                while ((pelmGlobalChild = nlGlobalChildren.forAllNodes()))
     693                {
     694                    if (pelmGlobalChild->nameEquals("SystemProperties"))
     695                    {
     696                        pelmGlobalChild->getAttributeValue("defaultMachineFolder", systemProperties.strDefaultMachineFolder);
     697                        pelmGlobalChild->getAttributeValue("defaultHardDiskFolder", systemProperties.strDefaultHardDiskFolder);
     698                        pelmGlobalChild->getAttributeValue("defaultHardDiskFormat", systemProperties.strDefaultHardDiskFormat);
     699                        pelmGlobalChild->getAttributeValue("remoteDisplayAuthLibrary", systemProperties.strRemoteDisplayAuthLibrary);
     700                        pelmGlobalChild->getAttributeValue("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
     701                        pelmGlobalChild->getAttributeValue("LogHistoryCount", systemProperties.ulLogHistoryCount);
     702                    }
     703                    else if (pelmGlobalChild->nameEquals("ExtraData"))
     704                        readExtraData(*pelmGlobalChild, mapExtraDataItems);
     705                    else if (pelmGlobalChild->nameEquals("MachineRegistry"))
     706                        readMachineRegistry(*pelmGlobalChild);
     707                    else if (pelmGlobalChild->nameEquals("MediaRegistry"))
     708                        readMediaRegistry(*pelmGlobalChild);
     709                    else if (pelmGlobalChild->nameEquals("NetserviceRegistry"))
     710                    {
     711                        xml::NodesLoop nlLevel4(*pelmGlobalChild);
     712                        const xml::ElementNode *pelmLevel4Child;
     713                        while ((pelmLevel4Child = nlLevel4.forAllNodes()))
     714                        {
     715                            if (pelmLevel4Child->nameEquals("DHCPServers"))
     716                                readDHCPServers(*pelmLevel4Child);
     717                            else
     718                                throw ConfigFileError(this, N_("Invalid element %s in NetserviceRegistry section"), pelmLevel4Child->getName());
     719                        }
     720                    }
     721                    else if (pelmGlobalChild->nameEquals("USBDeviceFilters"))
     722                        readUSBDeviceFilters(*pelmGlobalChild, host.llUSBDeviceFilters);
     723                    else
     724                        throw ConfigFileError(this, N_("Invalid element %s in Global section"), pelmGlobalChild->getName());
     725                }
     726            } // end if (pelmRootChild->nameEquals("Global"))
     727        }
     728
     729        clearDocument();
     730    }
     731}
     732
     733/**
     734 * Writes out a single <HardDisk> element for the given Medium structure
     735 * and recurses to write the child hard disks underneath. Called from
     736 * MainConfigFile::write().
     737 * @param elmMedium
     738 * @param m
     739 * @param level
     740 */
     741void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,
     742                                   const Medium &m,
     743                                   uint32_t level)          // 0 for "root" call, incremented with each recursion
     744{
     745    xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");
     746    pelmHardDisk->setAttribute("uuid", makeString(m.uuid));
     747    pelmHardDisk->setAttribute("location", m.strLocation);
     748    pelmHardDisk->setAttribute("format", m.strFormat);
     749    if (m.fAutoReset)
     750        pelmHardDisk->setAttribute("autoReset", m.fAutoReset);
     751    if (m.strDescription.length())
     752        pelmHardDisk->setAttribute("Description", m.strDescription);
     753
     754    for (PropertiesMap::const_iterator it = m.properties.begin();
     755         it != m.properties.end();
     756         ++it)
     757    {
     758        xml::ElementNode *pelmProp = pelmHardDisk->createChild("Property");
     759        pelmProp->setAttribute("name", it->first);
     760        pelmProp->setAttribute("value", it->second);
     761    }
     762
     763    // only for base hard disks, save the type
     764    if (level == 0)
     765    {
     766        const char *pcszType =
     767            m.hdType == HardDiskType_Normal ? "Normal" :
     768            m.hdType == HardDiskType_Immutable ? "Immutable" :
     769            /*m.hdType == HardDiskType_Writethrough ?*/ "Writethrough";
     770        pelmHardDisk->setAttribute("type", pcszType);
     771    }
     772
     773    for (MediaList::const_iterator it = m.llChildren.begin();
     774         it != m.llChildren.end();
     775         ++it)
     776    {
     777        // recurse for children
     778        writeHardDisk(*pelmHardDisk, // parent
     779                      *it,           // settings::Medium
     780                      ++level);      // recursion level
     781    }
     782}
     783
     784/**
     785 * Called from the IMachine interface to write out a machine config file. This
     786 * builds an XML DOM tree and writes it out to disk.
     787 */
     788void MainConfigFile::write()
     789{
     790    createStubDocument();
     791
     792    xml::ElementNode *pelmGlobal = m->pelmRoot->createChild("Global");
     793
     794    writeExtraData(*pelmGlobal, mapExtraDataItems);
     795
     796    xml::ElementNode *pelmMachineRegistry = pelmGlobal->createChild("MachineRegistry");
     797    for (MachinesRegistry::const_iterator it = llMachines.begin();
     798         it != llMachines.end();
     799         ++it)
     800    {
     801        // <MachineEntry uuid="{5f102a55-a51b-48e3-b45a-b28d33469488}" src="/mnt/innotek-unix/vbox-machines/Windows 5.1 XP 1 (Office 2003)/Windows 5.1 XP 1 (Office 2003).xml"/>
     802        const MachineRegistryEntry &mre = *it;
     803        xml::ElementNode *pelmMachineEntry = pelmMachineRegistry->createChild("MachineEntry");
     804        pelmMachineEntry->setAttribute("uuid", makeString(mre.uuid));
     805        pelmMachineEntry->setAttribute("src", mre.strSettingsFile);
     806    }
     807
     808    xml::ElementNode *pelmMediaRegistry = pelmGlobal->createChild("MediaRegistry");
     809
     810    xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks");
     811    for (MediaList::const_iterator it = llHardDisks.begin();
     812         it != llHardDisks.end();
     813         ++it)
     814    {
     815        writeHardDisk(*pelmHardDisks, *it, 0);
     816    }
     817
     818    xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages");
     819    for (MediaList::const_iterator it = llDvdImages.begin();
     820         it != llDvdImages.end();
     821         ++it)
     822    {
     823        const Medium &m = *it;
     824        xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image");
     825        pelmMedium->setAttribute("uuid", makeString(m.uuid));
     826        pelmMedium->setAttribute("location", m.strLocation);
     827        if (m.strDescription.length())
     828            pelmMedium->setAttribute("Description", m.strDescription);
     829    }
     830
     831    xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages");
     832    for (MediaList::const_iterator it = llFloppyImages.begin();
     833         it != llFloppyImages.end();
     834         ++it)
     835    {
     836        const Medium &m = *it;
     837        xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image");
     838        pelmMedium->setAttribute("uuid", makeString(m.uuid));
     839        pelmMedium->setAttribute("location", m.strLocation);
     840        if (m.strDescription.length())
     841            pelmMedium->setAttribute("Description", m.strDescription);
     842    }
     843
     844    xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry");
     845    xml::ElementNode *pelmDHCPServers = pelmNetserviceRegistry->createChild("DHCPServers");
     846    for (DHCPServersList::const_iterator it = llDhcpServers.begin();
     847         it != llDhcpServers.end();
     848         ++it)
     849    {
     850        const DHCPServer &d = *it;
     851        xml::ElementNode *pelmThis = pelmDHCPServers->createChild("DHCPServer");
     852        pelmThis->setAttribute("networkName", d.strNetworkName);
     853        pelmThis->setAttribute("IPAddress", d.strIPAddress);
     854        pelmThis->setAttribute("networkMask", d.strIPNetworkMask);
     855        pelmThis->setAttribute("lowerIP", d.strIPLower);
     856        pelmThis->setAttribute("upperIP", d.strIPUpper);
     857        pelmThis->setAttribute("enabled", (d.fEnabled) ? 1 : 0);        // too bad we chose 1 vs. 0 here
     858    }
     859
     860    xml::ElementNode *pelmSysProps = pelmGlobal->createChild("SystemProperties");
     861    if (systemProperties.strDefaultMachineFolder.length())
     862        pelmSysProps->setAttribute("defaultMachineFolder", systemProperties.strDefaultMachineFolder);
     863    if (systemProperties.strDefaultHardDiskFolder.length())
     864        pelmSysProps->setAttribute("defaultHardDiskFolder", systemProperties.strDefaultHardDiskFolder);
     865    if (systemProperties.strDefaultHardDiskFormat.length())
     866        pelmSysProps->setAttribute("defaultHardDiskFormat", systemProperties.strDefaultHardDiskFormat);
     867    if (systemProperties.strRemoteDisplayAuthLibrary.length())
     868        pelmSysProps->setAttribute("remoteDisplayAuthLibrary", systemProperties.strRemoteDisplayAuthLibrary);
     869    if (systemProperties.strWebServiceAuthLibrary.length())
     870        pelmSysProps->setAttribute("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
     871    pelmSysProps->setAttribute("LogHistoryCount", systemProperties.ulLogHistoryCount);
     872
     873    writeUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
     874                          host.llUSBDeviceFilters,
     875                          true);               // fHostMode
     876
     877    // now go write the XML
     878    xml::XmlFileWriter writer(*m->pDoc);
     879    writer.write(m->strFilename.c_str());
     880
     881    m->fFileExists = true;
     882
     883    clearDocument();
     884}
     885
     886/**
     887 * @param elmNetwork
     888 * @param ll
     889 */
     890void MachineConfigFile::readNetworkAdapters(const xml::ElementNode &elmNetwork,
     891                                            NetworkAdaptersList &ll)
     892{
     893    xml::NodesLoop nl1(elmNetwork, "Adapter");
     894    const xml::ElementNode *pelmAdapter;
     895    while ((pelmAdapter = nl1.forAllNodes()))
     896    {
     897        NetworkAdapter nic;
     898
     899        if (!pelmAdapter->getAttributeValue("slot", nic.ulSlot))
     900            throw ConfigFileError(this, N_("Required Adapter/slot attribute is missing"));
     901
     902        Utf8Str strTemp;
     903        if (pelmAdapter->getAttributeValue("type", strTemp))
     904        {
     905            if (strTemp == "Am79C970A")
     906                nic.type = NetworkAdapterType_Am79C970A;
     907            else if (strTemp == "Am79C973")
     908                nic.type = NetworkAdapterType_Am79C973;
     909            else if (strTemp == "82540EM")
     910                nic.type = NetworkAdapterType_I82540EM;
     911            else if (strTemp == "82543GC")
     912                nic.type = NetworkAdapterType_I82543GC;
     913            else if (strTemp == "82545EM")
     914                nic.type = NetworkAdapterType_I82545EM;
     915            else
     916                throw ConfigFileError(this, N_("Invalid value %s in Adapter/type attribute"), strTemp.c_str());
     917        }
     918
     919        pelmAdapter->getAttributeValue("enabled", nic.fEnabled);
     920        pelmAdapter->getAttributeValue("MACAddress", nic.strMACAddress);
     921        pelmAdapter->getAttributeValue("cable", nic.fCableConnected);
     922        pelmAdapter->getAttributeValue("speed", nic.ulLineSpeed);
     923        pelmAdapter->getAttributeValue("trace", nic.fTraceEnabled);
     924        pelmAdapter->getAttributeValue("tracefile", nic.strTraceFile);
     925
     926        const xml::ElementNode *pelmAdapterChild;
     927        if ((pelmAdapterChild = pelmAdapter->findChildElement("NAT")))
     928        {
     929            nic.mode = NetworkAttachmentType_NAT;
     930            pelmAdapterChild->getAttributeValue("name", nic.strName);    // optional network name
     931        }
     932        else if (    ((pelmAdapterChild = pelmAdapter->findChildElement("HostInterface")))
     933                  || ((pelmAdapterChild = pelmAdapter->findChildElement("BridgedInterface")))
     934                )
     935        {
     936            nic.mode = NetworkAttachmentType_Bridged;
     937            pelmAdapterChild->getAttributeValue("name", nic.strName);    // optional host interface name
     938        }
     939        else if ((pelmAdapterChild = pelmAdapter->findChildElement("InternalNetwork")))
     940        {
     941            nic.mode = NetworkAttachmentType_Internal;
     942            if (!pelmAdapterChild->getAttributeValue("name", nic.strName))    // required network name
     943                throw ConfigFileError(this, N_("Required 'name' element is missing under 'InternalNetwork' element"));
     944        }
     945        else if ((pelmAdapterChild = pelmAdapter->findChildElement("HostOnlyInterface")))
     946        {
     947            nic.mode = NetworkAttachmentType_HostOnly;
     948            if (!pelmAdapterChild->getAttributeValue("name", nic.strName))    // required network name
     949                throw ConfigFileError(this, N_("Required 'name' element is missing under 'HostOnlyInterface' element"));
     950        }
     951        // else: default is NetworkAttachmentType_Null
     952
     953        ll.push_back(nic);
     954    }
     955}
     956
     957/**
     958 * Called from MachineConfigFile::readHardware() to read serial port information.
     959 * @param elmUART
     960 * @param ll
     961 */
     962void MachineConfigFile::readSerialPorts(const xml::ElementNode &elmUART,
     963                                        SerialPortsList &ll)
     964{
     965    xml::NodesLoop nl1(elmUART, "Port");
     966    const xml::ElementNode *pelmPort;
     967    while ((pelmPort = nl1.forAllNodes()))
     968    {
     969        SerialPort port;
     970        if (!pelmPort->getAttributeValue("slot", port.ulSlot))
     971            throw ConfigFileError(this, N_("Required UART/Port/slot attribute is missing"));
     972
     973        // slot must be unique
     974        for (SerialPortsList::const_iterator it = ll.begin();
     975             it != ll.end();
     976             ++it)
     977            if ((*it).ulSlot == port.ulSlot)
     978                throw ConfigFileError(this, N_("UART/Port/slot attribute value %d is used twice, must be unique"), port.ulSlot);
     979
     980        if (!pelmPort->getAttributeValue("enabled", port.fEnabled))
     981            throw ConfigFileError(this, N_("Required UART/Port/enabled attribute is missing"));
     982        if (!pelmPort->getAttributeValue("IOBase", port.ulIOBase))
     983            throw ConfigFileError(this, N_("Required UART/Port/IOBase attribute is missing"));
     984        if (!pelmPort->getAttributeValue("IRQ", port.ulIRQ))
     985            throw ConfigFileError(this, N_("Required UART/Port/IRQ attribute is missing"));
     986
     987        Utf8Str strPortMode;
     988        if (!pelmPort->getAttributeValue("hostMode", strPortMode))
     989            throw ConfigFileError(this, N_("Required UART/Port/hostMode attribute is missing"));
     990        if (strPortMode == "RawFile")
     991            port.portMode = PortMode_RawFile;
     992        else if (strPortMode == "HostPipe")
     993            port.portMode = PortMode_HostPipe;
     994        else if (strPortMode == "HostDevice")
     995            port.portMode = PortMode_HostDevice;
     996        else if (strPortMode == "Disconnected")
     997            port.portMode = PortMode_Disconnected;
     998        else
     999            throw ConfigFileError(this, N_("Invalid value %s in UART/Port/hostMode attribute"), strPortMode.c_str());
     1000
     1001        pelmPort->getAttributeValue("path", port.strPath);
     1002        pelmPort->getAttributeValue("server", port.fServer);
     1003
     1004        ll.push_back(port);
     1005    }
     1006}
     1007
     1008/**
     1009 * Called from MachineConfigFile::readHardware() to read parallel port information.
     1010 * @param elmLPT
     1011 * @param ll
     1012 */
     1013void MachineConfigFile::readParallelPorts(const xml::ElementNode &elmLPT,
     1014                                          ParallelPortsList &ll)
     1015{
     1016    xml::NodesLoop nl1(elmLPT, "Port");
     1017    const xml::ElementNode *pelmPort;
     1018    while ((pelmPort = nl1.forAllNodes()))
     1019    {
     1020        ParallelPort port;
     1021        if (!pelmPort->getAttributeValue("slot", port.ulSlot))
     1022            throw ConfigFileError(this, N_("Required LPT/Port/slot attribute is missing"));
     1023
     1024        // slot must be unique
     1025        for (ParallelPortsList::const_iterator it = ll.begin();
     1026             it != ll.end();
     1027             ++it)
     1028            if ((*it).ulSlot == port.ulSlot)
     1029                throw ConfigFileError(this, N_("LPT/Port/slot attribute value %d is used twice, must be unique"), port.ulSlot);
     1030
     1031        if (!pelmPort->getAttributeValue("enabled", port.fEnabled))
     1032            throw ConfigFileError(this, N_("Required LPT/Port/enabled attribute is missing"));
     1033        if (!pelmPort->getAttributeValue("IOBase", port.ulIOBase))
     1034            throw ConfigFileError(this, N_("Required LPT/Port/IOBase attribute is missing"));
     1035        if (!pelmPort->getAttributeValue("IRQ", port.ulIRQ))
     1036            throw ConfigFileError(this, N_("Required LPT/Port/IRQ attribute is missing"));
     1037
     1038        pelmPort->getAttributeValue("path", port.strPath);
     1039
     1040        ll.push_back(port);
     1041    }
     1042}
     1043
     1044/**
     1045 * Called from MachineConfigFile::readHardware() to read guest property information.
     1046 * @param elmGuestProperties
     1047 * @param hw
     1048 */
     1049void MachineConfigFile::readGuestProperties(const xml::ElementNode &elmGuestProperties,
     1050                                            Hardware &hw)
     1051{
     1052    xml::NodesLoop nl1(elmGuestProperties, "GuestProperty");
     1053    const xml::ElementNode *pelmProp;
     1054    while ((pelmProp = nl1.forAllNodes()))
     1055    {
     1056        GuestProperty prop;
     1057        pelmProp->getAttributeValue("name", prop.strName);
     1058        pelmProp->getAttributeValue("value", prop.strValue);
     1059
     1060        pelmProp->getAttributeValue("timestamp", prop.timestamp);
     1061        pelmProp->getAttributeValue("flags", prop.strFlags);
     1062        hw.llGuestProperties.push_back(prop);
     1063    }
     1064
     1065    elmGuestProperties.getAttributeValue("notificationPatterns", hw.strNotificationPatterns);
     1066}
     1067
     1068/**
     1069 * Reads in a <Hardware> block and stores it in the given structure. Used
     1070 * both directly from readMachine and from readSnapshot, since snapshots
     1071 * have their own hardware sections.
     1072 * @param elmHardware
     1073 * @param hw
     1074 */
     1075void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
     1076                                     Hardware &hw)
     1077{
     1078    elmHardware.getAttributeValue("version", hw.strVersion);
     1079            // defaults to 2 and is only written if != 2
     1080
     1081    xml::NodesLoop nl1(elmHardware);
     1082    const xml::ElementNode *pelmHwChild;
     1083    while ((pelmHwChild = nl1.forAllNodes()))
     1084    {
     1085        if (pelmHwChild->nameEquals("CPU"))
     1086        {
     1087            pelmHwChild->getAttributeValue("count", hw.cCPUs);
     1088
     1089            const xml::ElementNode *pelmCPUChild;
     1090            if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtEx")))
     1091                pelmCPUChild->getAttributeValue("enabled", hw.fHardwareVirt);
     1092            if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExNestedPaging")))
     1093                pelmCPUChild->getAttributeValue("enabled", hw.fNestedPaging);
     1094            if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExVPID")))
     1095                pelmCPUChild->getAttributeValue("enabled", hw.fVPID);
     1096            if ((pelmCPUChild = pelmHwChild->findChildElement("PAE")))
     1097                pelmCPUChild->getAttributeValue("enabled", hw.fPAE);
     1098        }
     1099        else if (pelmHwChild->nameEquals("Memory"))
     1100            pelmHwChild->getAttributeValue("RAMSize", hw.ulMemorySizeMB);
     1101        else if (pelmHwChild->nameEquals("Boot"))
     1102        {
     1103            xml::NodesLoop nl2(*pelmHwChild, "Order");
     1104            const xml::ElementNode *pelmOrder;
     1105            while ((pelmOrder = nl2.forAllNodes()))
     1106            {
     1107                uint32_t ulPos;
     1108                Utf8Str strDevice;
     1109                if (!pelmOrder->getAttributeValue("position", ulPos))
     1110                    throw ConfigFileError(this, N_("'Order' element lacks 'position' attribute"));
     1111                if (!pelmOrder->getAttributeValue("device", strDevice))
     1112                    throw ConfigFileError(this, N_("'Order' element lacks 'device' attribute"));
     1113                if (hw.mapBootOrder.find(ulPos) != hw.mapBootOrder.end())
     1114                    throw ConfigFileError(this, N_("Value %d of 'position' attribute in 'Order' element is not unique"), ulPos);
     1115
     1116                DeviceType_T type;
     1117                if (strDevice == "None")
     1118                    type = DeviceType_Null;
     1119                else if (strDevice == "Floppy")
     1120                    type = DeviceType_Floppy;
     1121                else if (strDevice == "DVD")
     1122                    type = DeviceType_DVD;
     1123                else if (strDevice == "HardDisk")
     1124                    type = DeviceType_HardDisk;
     1125                else if (strDevice == "Network")
     1126                    type = DeviceType_Network;
     1127                else
     1128                    throw ConfigFileError(this, N_("Invalid value %s in Boot/Order/device attribute"), strDevice.c_str());
     1129                hw.mapBootOrder[ulPos] = type;
     1130            }
     1131        }
     1132        else if (pelmHwChild->nameEquals("Display"))
     1133        {
     1134            pelmHwChild->getAttributeValue("VRAMSize", hw.ulVRAMSizeMB);
     1135            pelmHwChild->getAttributeValue("monitorCount", hw.cMonitors);
     1136            pelmHwChild->getAttributeValue("accelerate3D", hw.fAccelerate3D);
     1137            pelmHwChild->getAttributeValue("accelerate2DVideo", hw.fAccelerate2DVideo);
     1138        }
     1139        else if (pelmHwChild->nameEquals("RemoteDisplay"))
     1140        {
     1141            pelmHwChild->getAttributeValue("enabled", hw.vrdpSettings.fEnabled);
     1142            pelmHwChild->getAttributeValue("port", hw.vrdpSettings.ulPort);
     1143            pelmHwChild->getAttributeValue("netAddress", hw.vrdpSettings.strNetAddress);
     1144
     1145            Utf8Str strAuthType;
     1146            if (pelmHwChild->getAttributeValue("authType", strAuthType))
     1147            {
     1148                if (strAuthType == "Null")
     1149                    hw.vrdpSettings.authType = VRDPAuthType_Null;
     1150                else if (strAuthType == "Guest")
     1151                    hw.vrdpSettings.authType = VRDPAuthType_Guest;
     1152                else if (strAuthType == "External")
     1153                    hw.vrdpSettings.authType = VRDPAuthType_External;
     1154                else
     1155                    throw ConfigFileError(this, N_("Invalid value %s in RemoteDisplay/authType attribute"), strAuthType.c_str());
     1156            }
     1157
     1158            pelmHwChild->getAttributeValue("authTimeout", hw.vrdpSettings.ulAuthTimeout);
     1159            pelmHwChild->getAttributeValue("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
     1160            pelmHwChild->getAttributeValue("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
     1161        }
     1162        else if (pelmHwChild->nameEquals("BIOS"))
     1163        {
     1164            const xml::ElementNode *pelmBIOSChild;
     1165            if ((pelmBIOSChild = pelmHwChild->findChildElement("ACPI")))
     1166                pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fACPIEnabled);
     1167            if ((pelmBIOSChild = pelmHwChild->findChildElement("IOAPIC")))
     1168                pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fIOAPICEnabled);
     1169            if ((pelmBIOSChild = pelmHwChild->findChildElement("Logo")))
     1170            {
     1171                pelmBIOSChild->getAttributeValue("fadeIn", hw.biosSettings.fLogoFadeIn);
     1172                pelmBIOSChild->getAttributeValue("fadeOut", hw.biosSettings.fLogoFadeOut);
     1173                pelmBIOSChild->getAttributeValue("displayTime", hw.biosSettings.ulLogoDisplayTime);
     1174                pelmBIOSChild->getAttributeValue("imagePath", hw.biosSettings.strLogoImagePath);
     1175            }
     1176            if ((pelmBIOSChild = pelmHwChild->findChildElement("BootMenu")))
     1177            {
     1178                Utf8Str strBootMenuMode;
     1179                if (pelmBIOSChild->getAttributeValue("mode", strBootMenuMode))
     1180                {
     1181                    if (strBootMenuMode == "Disabled")
     1182                        hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_Disabled;
     1183                    else if (strBootMenuMode == "MenuOnly")
     1184                        hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_MenuOnly;
     1185                    else if (strBootMenuMode == "MessageAndMenu")
     1186                        hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
     1187                    else
     1188                        throw ConfigFileError(this, N_("Invalid value %s in BootMenu/mode attribute"), strBootMenuMode.c_str());
     1189                }
     1190            }
     1191            if ((pelmBIOSChild = pelmHwChild->findChildElement("PXEDebug")))
     1192                pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fPXEDebugEnabled);
     1193            if ((pelmBIOSChild = pelmHwChild->findChildElement("TimeOffset")))
     1194                pelmBIOSChild->getAttributeValue("value", hw.biosSettings.llTimeOffset);
     1195        }
     1196        else if (pelmHwChild->nameEquals("DVDDrive"))
     1197        {
     1198            const xml::ElementNode *pDriveChild;
     1199            pelmHwChild->getAttributeValue("passthrough", hw.dvdDrive.fPassThrough);
     1200            Utf8Str strTmp;
     1201            if (    ((pDriveChild = pelmHwChild->findChildElement("Image")))
     1202                 && (pDriveChild->getAttributeValue("uuid", strTmp))
     1203               )
     1204                parseUUID(hw.dvdDrive.uuid, strTmp);
     1205            else if ((pDriveChild = pelmHwChild->findChildElement("HostDrive")))
     1206                pDriveChild->getAttributeValue("src", hw.dvdDrive.strHostDriveSrc);
     1207        }
     1208        else if (pelmHwChild->nameEquals("FloppyDrive"))
     1209        {
     1210            const xml::ElementNode *pDriveChild;
     1211            pelmHwChild->getAttributeValue("enabled", hw.floppyDrive.fEnabled);
     1212            Utf8Str strTmp;
     1213            if (    ((pDriveChild = pelmHwChild->findChildElement("Image")))
     1214                 && (pDriveChild->getAttributeValue("uuid", strTmp))
     1215               )
     1216                parseUUID(hw.floppyDrive.uuid, strTmp);
     1217            else if ((pDriveChild = pelmHwChild->findChildElement("HostDrive")))
     1218                pDriveChild->getAttributeValue("src", hw.floppyDrive.strHostDriveSrc);
     1219        }
     1220        else if (pelmHwChild->nameEquals("USBController"))
     1221        {
     1222            pelmHwChild->getAttributeValue("enabled", hw.usbController.fEnabled);
     1223            pelmHwChild->getAttributeValue("enabledEhci", hw.usbController.fEnabledEHCI);
     1224
     1225            readUSBDeviceFilters(*pelmHwChild,
     1226                                 hw.usbController.llDeviceFilters);
     1227        }
     1228        else if (pelmHwChild->nameEquals("Network"))
     1229            readNetworkAdapters(*pelmHwChild, hw.llNetworkAdapters);
     1230        else if (pelmHwChild->nameEquals("UART"))
     1231            readSerialPorts(*pelmHwChild, hw.llSerialPorts);
     1232        else if (pelmHwChild->nameEquals("LPT"))
     1233            readParallelPorts(*pelmHwChild, hw.llParallelPorts);
     1234        else if (pelmHwChild->nameEquals("AudioAdapter"))
     1235        {
     1236            pelmHwChild->getAttributeValue("enabled", hw.audioAdapter.fEnabled);
     1237
     1238            Utf8Str strTemp;
     1239            if (pelmHwChild->getAttributeValue("controller", strTemp))
     1240            {
     1241                if (strTemp == "SB16")
     1242                    hw.audioAdapter.controllerType = AudioControllerType_SB16;
     1243                else if (strTemp == "AC97")
     1244                    hw.audioAdapter.controllerType = AudioControllerType_AC97;
     1245                else
     1246                    throw ConfigFileError(this, N_("Invalid value %s in AudioAdapter/controller attribute"), strTemp.c_str());
     1247            }
     1248            if (pelmHwChild->getAttributeValue("driver", strTemp))
     1249            {
     1250                if (strTemp == "Null")
     1251                    hw.audioAdapter.driverType = AudioDriverType_Null;
     1252                else if (strTemp == "WinMM")
     1253                    hw.audioAdapter.driverType = AudioDriverType_WinMM;
     1254                else if (strTemp == "DirectSound")
     1255                    hw.audioAdapter.driverType = AudioDriverType_DirectSound;
     1256                else if (strTemp == "SolAudio")
     1257                    hw.audioAdapter.driverType = AudioDriverType_SolAudio;
     1258                else if (strTemp == "ALSA")
     1259                    hw.audioAdapter.driverType = AudioDriverType_ALSA;
     1260                else if (strTemp == "Pulse")
     1261                    hw.audioAdapter.driverType = AudioDriverType_Pulse;
     1262                else if (strTemp == "OSS")
     1263                    hw.audioAdapter.driverType = AudioDriverType_OSS;
     1264                else if (strTemp == "CoreAudio")
     1265                    hw.audioAdapter.driverType = AudioDriverType_CoreAudio;
     1266                else if (strTemp == "MMPM")
     1267                    hw.audioAdapter.driverType = AudioDriverType_MMPM;
     1268                else
     1269                    throw ConfigFileError(this, N_("Invalid value %s in AudioAdapter/driver attribute"), strTemp.c_str());
     1270            }
     1271        }
     1272        else if (pelmHwChild->nameEquals("SharedFolders"))
     1273        {
     1274            xml::NodesLoop nl2(*pelmHwChild, "SharedFolder");
     1275            const xml::ElementNode *pelmFolder;
     1276            while ((pelmFolder = nl2.forAllNodes()))
     1277            {
     1278                SharedFolder sf;
     1279                pelmFolder->getAttributeValue("name", sf.strName);
     1280                pelmFolder->getAttributeValue("hostPath", sf.strHostPath);
     1281                pelmFolder->getAttributeValue("writable", sf.fWritable);
     1282                hw.llSharedFolders.push_back(sf);
     1283            }
     1284        }
     1285        else if (pelmHwChild->nameEquals("Clipboard"))
     1286        {
     1287            Utf8Str strTemp;
     1288            if (pelmHwChild->getAttributeValue("mode", strTemp))
     1289            {
     1290                if (strTemp == "Disabled")
     1291                    hw.clipboardMode = ClipboardMode_Disabled;
     1292                else if (strTemp == "HostToGuest")
     1293                    hw.clipboardMode = ClipboardMode_HostToGuest;
     1294                else if (strTemp == "GuestToHost")
     1295                    hw.clipboardMode = ClipboardMode_GuestToHost;
     1296                else if (strTemp == "Bidirectional")
     1297                    hw.clipboardMode = ClipboardMode_Bidirectional;
     1298                else
     1299                    throw ConfigFileError(this, N_("Invalid value %s in Clipbord/mode attribute"), strTemp.c_str());
     1300            }
     1301        }
     1302        else if (pelmHwChild->nameEquals("Guest"))
     1303        {
     1304            pelmHwChild->getAttributeValue("memoryBalloonSize", hw.ulMemoryBalloonSize);
     1305            pelmHwChild->getAttributeValue("statisticsUpdateInterval", hw.ulStatisticsUpdateInterval);
     1306        }
     1307        else if (pelmHwChild->nameEquals("GuestProperties"))
     1308            readGuestProperties(*pelmHwChild, hw);
     1309        else
     1310            throw ConfigFileError(this, N_("Invalid element %s in Hardware section"), pelmHwChild->getName());
     1311    }
     1312
     1313    if (hw.ulMemorySizeMB == (uint32_t)-1)
     1314        throw ConfigFileError(this, N_("Required Memory/RAMSize element/attribute is missing"));
     1315}
     1316
     1317/**
     1318 * Reads in a <StorageControllers> block and stores it in the given Storage structure.
     1319 * Used both directly from readMachine and from readSnapshot, since snapshots
     1320 * have their own storage controllers sections.
     1321 *
     1322 * @param elmStorageControllers
     1323 */
     1324void MachineConfigFile::readStorageControllers(const xml::ElementNode &elmStorageControllers,
     1325                                               Storage &strg)
     1326{
     1327    xml::NodesLoop nlStorageControllers(elmStorageControllers, "StorageController");
     1328    const xml::ElementNode *pelmController;
     1329    while ((pelmController = nlStorageControllers.forAllNodes()))
     1330    {
     1331        StorageController sctl;
     1332
     1333        if (!pelmController->getAttributeValue("name", sctl.strName))
     1334            throw ConfigFileError(this, N_("Required StorageController/name attribute is missing"));
     1335        Utf8Str strType;
     1336        if (!pelmController->getAttributeValue("type", strType))
     1337            throw ConfigFileError(this, N_("Required StorageController/type attribute is missing"));
     1338
     1339        if (strType == "AHCI")
     1340        {
     1341            sctl.storageBus = StorageBus_SATA;
     1342            sctl.controllerType = StorageControllerType_IntelAhci;
     1343        }
     1344        else if (strType == "LsiLogic")
     1345        {
     1346            sctl.storageBus = StorageBus_SCSI;
     1347            sctl.controllerType = StorageControllerType_LsiLogic;
     1348        }
     1349        else if (strType == "BusLogic")
     1350        {
     1351            sctl.storageBus = StorageBus_SCSI;
     1352            sctl.controllerType = StorageControllerType_BusLogic;
     1353        }
     1354        else if (strType == "PIIX3")
     1355        {
     1356            sctl.storageBus = StorageBus_IDE;
     1357            sctl.controllerType = StorageControllerType_PIIX3;
     1358        }
     1359        else if (strType == "PIIX4")
     1360        {
     1361            sctl.storageBus = StorageBus_IDE;
     1362            sctl.controllerType = StorageControllerType_PIIX4;
     1363        }
     1364        else if (strType == "ICH6")
     1365        {
     1366            sctl.storageBus = StorageBus_IDE;
     1367            sctl.controllerType = StorageControllerType_ICH6;
     1368        }
     1369        else
     1370            throw ConfigFileError(this, N_("Invalid value %s for StorageController/type attribute"), strType.c_str());
     1371
     1372        pelmController->getAttributeValue("PortCount", sctl.ulPortCount);
     1373
     1374        pelmController->getAttributeValue("IDE0MasterEmulationPort", sctl.lIDE0MasterEmulationPort);
     1375        pelmController->getAttributeValue("IDE0SlaveEmulationPort", sctl.lIDE0SlaveEmulationPort);
     1376        pelmController->getAttributeValue("IDE1MasterEmulationPort", sctl.lIDE1MasterEmulationPort);
     1377        pelmController->getAttributeValue("IDE1SlaveEmulationPort", sctl.lIDE1SlaveEmulationPort);
     1378
     1379        xml::NodesLoop nlAttached(*pelmController, "AttachedDevice");
     1380        const xml::ElementNode *pelmAttached;
     1381        while ((pelmAttached = nlAttached.forAllNodes()))
     1382        {
     1383            AttachedDevice att;
     1384
     1385            Utf8Str strTemp;
     1386            pelmAttached->getAttributeValue("type", strTemp);
     1387            if (strTemp != "HardDisk")
     1388                throw ConfigFileError(this, N_("AttachedDevice element must have 'HardDisk' type"));
     1389
     1390            const xml::ElementNode *pelmImage;
     1391            if (!(pelmImage = pelmAttached->findChildElement("Image")))
     1392                throw ConfigFileError(this, N_("Required AttachedDevice/Image element is missing"));
     1393
     1394            if (!pelmImage->getAttributeValue("uuid", strTemp))
     1395                throw ConfigFileError(this, N_("Required AttachedDevice/Image/uuid attributeis missing"));
     1396            parseUUID(att.uuid, strTemp);
     1397
     1398            if (!pelmAttached->getAttributeValue("port", att.lPort))
     1399                throw ConfigFileError(this, N_("Required AttachedDevice/port attribute is missing"));
     1400            if (!pelmAttached->getAttributeValue("device", att.lDevice))
     1401                throw ConfigFileError(this, N_("Required AttachedDevice/device attribute is missing"));
     1402
     1403            sctl.llAttachedDevices.push_back(att);
     1404        }
     1405
     1406        strg.llStorageControllers.push_back(sctl);
     1407    }
     1408}
     1409
     1410/**
     1411 * Called initially for the <Snapshot> element under <Machine>, if present,
     1412 * to store the snapshot's data into the given Snapshot structure (which is
     1413 * then the one in the Machine struct). This might then recurse if
     1414 * a <Snapshots> (plural) element is found in the snapshot, which should
     1415 * contain a list of child snapshots; such lists are maintained in the
     1416 * Snapshot structure.
     1417 *
     1418 * @param elmSnapshot
     1419 * @param snap
     1420 */
     1421void MachineConfigFile::readSnapshot(const xml::ElementNode &elmSnapshot,
     1422                                     Snapshot &snap)
     1423{
     1424    Utf8Str strTemp;
     1425
     1426    if (!elmSnapshot.getAttributeValue("uuid", strTemp))
     1427        throw ConfigFileError(this, N_("Required Snapshot/uuid attribute is missing"));
     1428    parseUUID(snap.uuid, strTemp);
     1429
     1430    if (!elmSnapshot.getAttributeValue("name", snap.strName))
     1431        throw ConfigFileError(this, N_("Required Snapshot/name attribute is missing"));
     1432
     1433    elmSnapshot.getAttributeValue("Description", snap.strDescription);
     1434
     1435    if (!elmSnapshot.getAttributeValue("timeStamp", strTemp))
     1436        throw ConfigFileError(this, N_("Required Snapshot/timeStamp attribute is missing"));
     1437    parseTimestamp(snap.timestamp, strTemp);
     1438
     1439    elmSnapshot.getAttributeValue("stateFile", snap.strStateFile);      // online snapshots only
     1440
     1441    xml::NodesLoop nlSnapshotChildren(elmSnapshot);
     1442    const xml::ElementNode *pelmSnapshotChild;
     1443    while ((pelmSnapshotChild = nlSnapshotChildren.forAllNodes()))
     1444    {
     1445        if (pelmSnapshotChild->nameEquals("Description"))
     1446            snap.strDescription = pelmSnapshotChild->getValue();
     1447        else if (pelmSnapshotChild->nameEquals("Hardware"))
     1448            readHardware(*pelmSnapshotChild, snap.hardware);
     1449        else if (pelmSnapshotChild->nameEquals("StorageControllers"))
     1450            readStorageControllers(*pelmSnapshotChild, snap.storage);
     1451        else if (pelmSnapshotChild->nameEquals("Snapshots"))
     1452        {
     1453            xml::NodesLoop nlChildSnapshots(*pelmSnapshotChild);
     1454            const xml::ElementNode *pelmChildSnapshot;
     1455            while ((pelmChildSnapshot = nlChildSnapshots.forAllNodes()))
     1456            {
     1457                if (pelmChildSnapshot->nameEquals("Snapshot"))
     1458                {
     1459                    Snapshot child;
     1460                    readSnapshot(*pelmChildSnapshot, child);
     1461                    snap.llChildSnapshots.push_back(child);
     1462                }
     1463                else
     1464                    throw ConfigFileError(this, N_("Invalid element %s under Snapshots element"), pelmChildSnapshot->getName());
     1465            }
     1466        }
     1467        else
     1468            throw ConfigFileError(this, N_("Invalid element %s under Snapshot element"), pelmSnapshotChild->getName());
     1469    }
     1470}
     1471
     1472/**
     1473 * Called from the constructor to actually read in the Machine element
     1474 * of a machine config file.
     1475 * @param elmMachine
     1476 */
     1477void MachineConfigFile::readMachine(const xml::ElementNode &elmMachine)
     1478{
     1479    Utf8Str strUUID;
     1480    if (    (elmMachine.getAttributeValue("uuid", strUUID))
     1481         && (elmMachine.getAttributeValue("name", strName))
     1482       )
     1483    {
     1484        parseUUID(uuid, strUUID);
     1485
     1486        if (!elmMachine.getAttributeValue("nameSync", fNameSync))
     1487            fNameSync = true;
     1488
     1489        Utf8Str str;
     1490        elmMachine.getAttributeValue("Description", strDescription);
     1491        elmMachine.getAttributeValue("OSType", strOsType);
     1492        elmMachine.getAttributeValue("stateFile", strStateFile);
     1493        if (elmMachine.getAttributeValue("currentSnapshot", str))
     1494            parseUUID(uuidCurrentSnapshot, str);
     1495        elmMachine.getAttributeValue("snapshotFolder", strSnapshotFolder);
     1496        if (!elmMachine.getAttributeValue("currentStateModified", fCurrentStateModified))
     1497            fCurrentStateModified = true;
     1498        if (elmMachine.getAttributeValue("lastStateChange", str))
     1499            parseTimestamp(timeLastStateChange, str);
     1500            // constructor has called RTTimeNow(&timeLastStateChange) before
     1501
     1502        xml::NodesLoop nlRootChildren(elmMachine);
     1503        const xml::ElementNode *pelmMachineChild;
     1504        while ((pelmMachineChild = nlRootChildren.forAllNodes()))
     1505        {
     1506            if (pelmMachineChild->nameEquals("ExtraData"))
     1507                readExtraData(*pelmMachineChild,
     1508                              mapExtraDataItems);
     1509            else if (pelmMachineChild->nameEquals("Hardware"))
     1510                readHardware(*pelmMachineChild, hardwareMachine);
     1511            else if (pelmMachineChild->nameEquals("StorageControllers"))
     1512                readStorageControllers(*pelmMachineChild, storageMachine);
     1513            else if (pelmMachineChild->nameEquals("Snapshot"))
     1514            {
     1515                Snapshot snap;
     1516                // this will recurse into child snapshots, if necessary
     1517                readSnapshot(*pelmMachineChild, snap);
     1518                llFirstSnapshot.push_back(snap);
     1519            }
     1520            else if (pelmMachineChild->nameEquals("Description"))
     1521                strDescription = pelmMachineChild->getValue();
     1522            else
     1523                throw ConfigFileError(this, N_("Invalid element %s under Machine element"), pelmMachineChild->getName());
     1524        }
     1525    }
     1526    else
     1527        throw ConfigFileError(this, N_("Machine element must have uuid and name attributes"));
     1528}
     1529
     1530/**
     1531 * Constructor.
     1532 *
     1533 * If pstrFilename is != NULL, this reads the given settings file into the member
     1534 * variables and various substructures and lists. Otherwise, the member variables
     1535 * are initialized with default values.
     1536 *
     1537 * Throws variants of xml::Error for I/O, XML and logical content errors, which
     1538 * the caller should catch; if this constructor does not throw, then the file has
     1539 * been successfully read and parsed.
     1540 *
     1541 * @param strFilename
     1542 */
     1543MachineConfigFile::MachineConfigFile(const Utf8Str *pstrFilename)
     1544    : ConfigFileBase(pstrFilename),
     1545      fNameSync(true),
     1546      fCurrentStateModified(true),
     1547      fAborted(false)
     1548{
     1549    RTTimeNow(&timeLastStateChange);
     1550
     1551    if (pstrFilename)
     1552    {
     1553        // the ConfigFileBase constructor has loaded the XML file, so now
     1554        // we need only analyze what is in there
     1555
     1556        xml::NodesLoop nlRootChildren(*m->pelmRoot);
     1557        const xml::ElementNode *pelmRootChild;
     1558        while ((pelmRootChild = nlRootChildren.forAllNodes()))
     1559        {
     1560            if (pelmRootChild->nameEquals("Machine"))
     1561                readMachine(*pelmRootChild);
     1562            else
     1563                throw ConfigFileError(this, N_("Invalid element %s under root element"), pelmRootChild->getName());
     1564        }
     1565
     1566        clearDocument();
     1567    }
     1568}
     1569
     1570/**
     1571 * Creates a <Hardware> node under elmParent and then writes out the XML
     1572 * keys under that. Called for both the <Machine> node and for snapshots.
     1573 * @param elmParent
     1574 * @param st
     1575 */
     1576void MachineConfigFile::writeHardware(xml::ElementNode &elmParent,
     1577                                      const Hardware &hw)
     1578{
     1579    xml::ElementNode *pelmHardware = elmParent.createChild("Hardware");
     1580
     1581    if (hw.strVersion != "2")
     1582        pelmHardware->setAttribute("version", hw.strVersion);
     1583
     1584    xml::ElementNode *pelmCPU = pelmHardware->createChild("CPU");
     1585    pelmCPU->createChild("HardwareVirtEx")->setAttribute("enabled", hw.fHardwareVirt);
     1586    if (hw.fNestedPaging)
     1587        pelmCPU->createChild("HardwareVirtExNestedPaging")->setAttribute("enabled", hw.fNestedPaging);
     1588    if (hw.fVPID)
     1589        pelmCPU->createChild("HardwareVirtExVPID")->setAttribute("enabled", hw.fVPID);
     1590    if (hw.fPAE)
     1591        pelmCPU->createChild("PAE")->setAttribute("enabled", hw.fPAE);
     1592    pelmCPU->setAttribute("count", hw.cCPUs);
     1593
     1594    xml::ElementNode *pelmMemory = pelmHardware->createChild("Memory");
     1595    pelmMemory->setAttribute("RAMSize", hw.ulMemorySizeMB);
     1596
     1597    xml::ElementNode *pelmBoot = pelmHardware->createChild("Boot");
     1598    for (BootOrderMap::const_iterator it = hw.mapBootOrder.begin();
     1599         it != hw.mapBootOrder.end();
     1600         ++it)
     1601    {
     1602        uint32_t i = it->first;
     1603        DeviceType_T type = it->second;
     1604        const char *pcszDevice;
     1605
     1606        switch (type)
     1607        {
     1608            case DeviceType_Floppy:     pcszDevice = "Floppy"; break;
     1609            case DeviceType_DVD:        pcszDevice = "DVD"; break;
     1610            case DeviceType_HardDisk:   pcszDevice = "HardDisk"; break;
     1611            case DeviceType_Network:    pcszDevice = "Network"; break;
     1612            default: /*case DeviceType_Null:*/      pcszDevice = "None"; break;
     1613        }
     1614
     1615        xml::ElementNode *pelmOrder = pelmBoot->createChild("Order");
     1616        pelmOrder->setAttribute("position", i);
     1617        pelmOrder->setAttribute("device", pcszDevice);
     1618    }
     1619
     1620    xml::ElementNode *pelmDisplay = pelmHardware->createChild("Display");
     1621    pelmDisplay->setAttribute("VRAMSize", hw.ulVRAMSizeMB);
     1622    pelmDisplay->setAttribute("monitorCount", hw.cMonitors);
     1623    pelmDisplay->setAttribute("accelerate3D", hw.fAccelerate3D);
     1624
     1625    if (m->sv >= SettingsVersion_v1_8)
     1626        pelmDisplay->setAttribute("accelerate2DVideo", hw.fAccelerate2DVideo);
     1627
     1628    xml::ElementNode *pelmVRDP = pelmHardware->createChild("RemoteDisplay");
     1629    pelmVRDP->setAttribute("enabled", hw.vrdpSettings.fEnabled);
     1630    pelmVRDP->setAttribute("port", hw.vrdpSettings.ulPort);
     1631    if (hw.vrdpSettings.strNetAddress.length())
     1632        pelmVRDP->setAttribute("netAddress", hw.vrdpSettings.strNetAddress);
     1633    const char *pcszAuthType;
     1634    switch (hw.vrdpSettings.authType)
     1635    {
     1636        case VRDPAuthType_Guest:    pcszAuthType = "Guest";    break;
     1637        case VRDPAuthType_External: pcszAuthType = "External"; break;
     1638        default: /*case VRDPAuthType_Null:*/ pcszAuthType = "Null"; break;
     1639    }
     1640    pelmVRDP->setAttribute("authType", pcszAuthType);
     1641
     1642    if (hw.vrdpSettings.ulAuthTimeout != 0)
     1643        pelmVRDP->setAttribute("authTimeout", hw.vrdpSettings.ulAuthTimeout);
     1644    if (hw.vrdpSettings.fAllowMultiConnection)
     1645        pelmVRDP->setAttribute("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
     1646    if (hw.vrdpSettings.fReuseSingleConnection)
     1647        pelmVRDP->setAttribute("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
     1648
     1649    xml::ElementNode *pelmBIOS = pelmHardware->createChild("BIOS");
     1650    pelmBIOS->createChild("ACPI")->setAttribute("enabled", hw.biosSettings.fACPIEnabled);
     1651    pelmBIOS->createChild("IOAPIC")->setAttribute("enabled", hw.biosSettings.fIOAPICEnabled);
     1652
     1653    xml::ElementNode *pelmLogo = pelmBIOS->createChild("Logo");
     1654    pelmLogo->setAttribute("fadeIn", hw.biosSettings.fLogoFadeIn);
     1655    pelmLogo->setAttribute("fadeOut", hw.biosSettings.fLogoFadeOut);
     1656    pelmLogo->setAttribute("displayTime", hw.biosSettings.ulLogoDisplayTime);
     1657    if (hw.biosSettings.strLogoImagePath.length())
     1658        pelmLogo->setAttribute("imagePath", hw.biosSettings.strLogoImagePath);
     1659
     1660    const char *pcszBootMenu;
     1661    switch (hw.biosSettings.biosBootMenuMode)
     1662    {
     1663        case BIOSBootMenuMode_Disabled: pcszBootMenu = "Disabled"; break;
     1664        case BIOSBootMenuMode_MenuOnly: pcszBootMenu = "MenuOnly"; break;
     1665        default: /*BIOSBootMenuMode_MessageAndMenu*/ pcszBootMenu = "MessageAndMenu"; break;
     1666    }
     1667    pelmBIOS->createChild("BootMenu")->setAttribute("mode", pcszBootMenu);
     1668    pelmBIOS->createChild("TimeOffset")->setAttribute("value", hw.biosSettings.llTimeOffset);
     1669    pelmBIOS->createChild("PXEDebug")->setAttribute("enabled", hw.biosSettings.fPXEDebugEnabled);
     1670
     1671    xml::ElementNode *pelmDVD = pelmHardware->createChild("DVDDrive");
     1672    pelmDVD->setAttribute("passthrough", hw.dvdDrive.fPassThrough);
     1673    if (!hw.dvdDrive.uuid.isEmpty())
     1674        pelmDVD->createChild("Image")->setAttribute("uuid", makeString(hw.dvdDrive.uuid));
     1675    else if (hw.dvdDrive.strHostDriveSrc.length())
     1676        pelmDVD->createChild("HostDrive")->setAttribute("src", hw.dvdDrive.strHostDriveSrc);
     1677
     1678    xml::ElementNode *pelmFloppy = pelmHardware->createChild("FloppyDrive");
     1679    pelmFloppy->setAttribute("enabled", hw.floppyDrive.fEnabled);
     1680    if (!hw.floppyDrive.uuid.isEmpty())
     1681        pelmFloppy->createChild("Image")->setAttribute("uuid", makeString(hw.floppyDrive.uuid));
     1682    else if (hw.floppyDrive.strHostDriveSrc.length())
     1683        pelmFloppy->createChild("HostDrive")->setAttribute("src", hw.floppyDrive.strHostDriveSrc);
     1684
     1685    xml::ElementNode *pelmUSB = pelmHardware->createChild("USBController");
     1686    pelmUSB->setAttribute("enabled", hw.usbController.fEnabled);
     1687    pelmUSB->setAttribute("enabledEhci", hw.usbController.fEnabledEHCI);
     1688
     1689    writeUSBDeviceFilters(*pelmUSB,
     1690                          hw.usbController.llDeviceFilters,
     1691                          false);               // fHostMode
     1692
     1693    xml::ElementNode *pelmNetwork = pelmHardware->createChild("Network");
     1694    for (NetworkAdaptersList::const_iterator it = hw.llNetworkAdapters.begin();
     1695         it != hw.llNetworkAdapters.end();
     1696         ++it)
     1697    {
     1698        const NetworkAdapter &nic = *it;
     1699
     1700        xml::ElementNode *pelmAdapter = pelmNetwork->createChild("Adapter");
     1701        pelmAdapter->setAttribute("slot", nic.ulSlot);
     1702        pelmAdapter->setAttribute("enabled", nic.fEnabled);
     1703        pelmAdapter->setAttribute("MACAddress", nic.strMACAddress);
     1704        pelmAdapter->setAttribute("cable", nic.fCableConnected);
     1705        pelmAdapter->setAttribute("speed", nic.ulLineSpeed);
     1706        if (nic.fTraceEnabled)
     1707        {
     1708            pelmAdapter->setAttribute("trace", nic.fTraceEnabled);
     1709            pelmAdapter->setAttribute("tracefile", nic.strTraceFile);
     1710        }
     1711
     1712        const char *pcszType;
     1713        switch (nic.type)
     1714        {
     1715            case NetworkAdapterType_Am79C973:   pcszType = "Am79C973"; break;
     1716            case NetworkAdapterType_I82540EM:   pcszType = "82540EM"; break;
     1717            case NetworkAdapterType_I82543GC:   pcszType = "82543GC"; break;
     1718            case NetworkAdapterType_I82545EM:   pcszType = "82545EM"; break;
     1719            default: /*case NetworkAdapterType_Am79C970A:*/  pcszType = "Am79C970A"; break;
     1720        }
     1721        pelmAdapter->setAttribute("type", pcszType);
     1722
     1723        xml::ElementNode *pelmNAT;
     1724        switch (nic.mode)
     1725        {
     1726            case NetworkAttachmentType_NAT:
     1727                pelmNAT = pelmAdapter->createChild("NAT");
     1728                if (nic.strName.length())
     1729                    pelmNAT->setAttribute("network", nic.strName);
    981730            break;
    99         default:
    100             throw xml::ENotImplemented (RT_SRC_POS);
    101     }
    102 
    103     if (aSigned)
    104     {
    105         int64_t result;
    106         int vrc = RTStrToInt64Full (aValue, 0, &result);
    107         if (RT_SUCCESS(vrc))
    108         {
    109             if (result >= (int64_t) aMin && result <= (int64_t) aMax)
    110                 return (uint64_t) result;
    111         }
    112     }
    113     else
    114     {
    115         uint64_t result;
    116         int vrc = RTStrToUInt64Full (aValue, 0, &result);
    117         if (RT_SUCCESS(vrc))
    118         {
    119             if (result >= aMin && result <= aMax)
    120                 return result;
    121         }
    122     }
    123 
    124     throw ENoConversion(com::Utf8StrFmt("'%s' is not integer", aValue));
    125 }
    126 
    127 template<> bool FromString <bool> (const char *aValue)
    128 {
    129     if (aValue == NULL)
    130         throw ENoValue();
    131 
    132     if (strcmp (aValue, "true") == 0 ||
    133         strcmp (aValue, "1") == 0)
    134         /* This contradicts the XML Schema's interpretation of boolean: */
    135         //strcmp (aValue, "yes") == 0 ||
    136         //strcmp (aValue, "on") == 0)
    137         return true;
    138     else if (strcmp (aValue, "false") == 0 ||
    139              strcmp (aValue, "0") == 0)
    140             /* This contradicts the XML Schema's interpretation of boolean: */
    141             //strcmp (aValue, "no") == 0 ||
    142             //strcmp (aValue, "off") == 0)
    143         return false;
    144 
    145     throw ENoConversion(com::Utf8StrFmt("'%s' is not bool", aValue));
    146 }
    147 
    148 template<> RTTIMESPEC FromString <RTTIMESPEC> (const char *aValue)
    149 {
    150     if (aValue == NULL)
    151         throw ENoValue();
    152 
    153     /* Parse ISO date (xsd:dateTime). The format is:
    154      * '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
    155      * where zzzzzz is: (('+' | '-') hh ':' mm) | 'Z' */
    156     uint32_t yyyy = 0;
    157     uint16_t mm = 0, dd = 0, hh = 0, mi = 0, ss = 0;
    158     char buf [256];
    159     if (strlen (aValue) > RT_ELEMENTS (buf) - 1 ||
    160         sscanf (aValue, "%d-%hu-%huT%hu:%hu:%hu%s",
    161                 &yyyy, &mm, &dd, &hh, &mi, &ss, buf) == 7)
    162     {
    163         /* currently, we accept only the UTC timezone ('Z'),
    164          * ignoring fractional seconds, if present */
    165         if (buf [0] == 'Z' ||
    166             (buf [0] == '.' && buf [strlen (buf) - 1] == 'Z'))
    167         {
    168             RTTIME time = { yyyy, (uint8_t) mm, 0, 0, (uint8_t) dd,
    169                             (uint8_t) hh, (uint8_t) mi, (uint8_t) ss, 0,
    170                             RTTIME_FLAGS_TYPE_UTC };
    171             if (RTTimeNormalize (&time))
    172             {
    173                 RTTIMESPEC timeSpec;
    174                 if (RTTimeImplode (&timeSpec, &time))
    175                     return timeSpec;
    176             }
    177         }
    178         else
    179             throw ENoConversion(com::Utf8StrFmt("'%s' is not UTC date", aValue));
    180     }
    181 
    182     throw ENoConversion(com::Utf8StrFmt("'%s' is not ISO date", aValue));
    183 }
    184 
    185 stdx::char_auto_ptr FromString (const char *aValue, size_t *aLen)
    186 {
    187     if (aValue == NULL)
    188         throw ENoValue();
    189 
    190     /* each two chars produce one byte */
    191     size_t len = strlen (aValue) / 2;
    192 
    193     /* therefore, the original length must be even */
    194     if (len % 2 != 0)
    195         throw ENoConversion(com::Utf8StrFmt("'%.*s' is not binary data",
    196                                             aLen, aValue));
    197 
    198     stdx::char_auto_ptr result (new char [len]);
    199 
    200     const char *src = aValue;
    201     char *dst = result.get();
    202 
    203     for (size_t i = 0; i < len; ++ i, ++ dst)
    204     {
    205         *dst = sFromHex (*src ++) << 4;
    206         *dst |= sFromHex (*src ++);
    207     }
    208 
    209     if (aLen != NULL)
    210         *aLen = len;
    211 
    212     return result;
    213 }
    214 
    215 //////////////////////////////////////////////////////////////////////////////
    216 // type -> string conversions
    217 //////////////////////////////////////////////////////////////////////////////
    218 
    219 stdx::char_auto_ptr ToStringInteger (uint64_t aValue, unsigned int aBase,
    220                                      bool aSigned, int aBits)
    221 {
    222     unsigned int flags = RTSTR_F_SPECIAL;
    223     if (aSigned)
    224         flags |= RTSTR_F_VALSIGNED;
    225 
    226     /* maximum is binary representation + terminator */
    227     size_t len = aBits + 1;
    228 
    229     switch (aBits)
    230     {
    231         case 8:
    232             flags |= RTSTR_F_8BIT;
     1731
     1732            case NetworkAttachmentType_Bridged:
     1733                pelmAdapter->createChild("BridgedInterface")->setAttribute("name", nic.strName);
    2331734            break;
    234         case 16:
    235             flags |= RTSTR_F_16BIT;
     1735
     1736            case NetworkAttachmentType_Internal:
     1737                pelmAdapter->createChild("InternalNetwork")->setAttribute("name", nic.strName);
    2361738            break;
    237         case 32:
    238             flags |= RTSTR_F_32BIT;
     1739
     1740            case NetworkAttachmentType_HostOnly:
     1741                pelmAdapter->createChild("HostOnlyInterface")->setAttribute("name", nic.strName);
    2391742            break;
    240         case 64:
    241             flags |= RTSTR_F_64BIT;
     1743
     1744            default: /*case NetworkAttachmentType_Null:*/
    2421745            break;
    243         default:
    244             throw xml::ENotImplemented (RT_SRC_POS);
    245     }
    246 
    247     stdx::char_auto_ptr result (new char [len]);
    248     if (aBase == 0)
    249         aBase = 10;
    250     int vrc = RTStrFormatNumber (result.get(), aValue, aBase, 0, 0, flags);
    251     if (RT_SUCCESS(vrc))
    252         return result;
    253 
    254     throw xml::EIPRTFailure (vrc);
    255 }
    256 
    257 template<> stdx::char_auto_ptr ToString <bool> (const bool &aValue,
    258                                                 unsigned int aExtra /* = 0 */)
    259 {
    260     /* Convert to the canonical form according to XML Schema */
    261     stdx::char_auto_ptr result (duplicate_chars (aValue ? "true" : "false"));
    262     return result;
    263 }
    264 
    265 template<> stdx::char_auto_ptr ToString <RTTIMESPEC> (const RTTIMESPEC &aValue,
    266                                                       unsigned int aExtra /* = 0 */)
    267 {
    268     RTTIME time;
    269     if (!RTTimeExplode (&time, &aValue))
    270         throw ENoConversion(com::Utf8StrFmt("timespec %lld ms is invalid",
    271                                             RTTimeSpecGetMilli (&aValue)));
    272 
    273     /* Store ISO date (xsd:dateTime). The format is:
    274      * '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
    275      * where zzzzzz is: (('+' | '-') hh ':' mm) | 'Z' */
    276     char buf [256];
    277     RTStrPrintf (buf, sizeof (buf),
    278                 "%04ld-%02hd-%02hdT%02hd:%02hd:%02hdZ",
    279                 time.i32Year, (uint16_t) time.u8Month, (uint16_t) time.u8MonthDay,
    280                 (uint16_t) time.u8Hour, (uint16_t) time.u8Minute, (uint16_t) time.u8Second);
    281 
    282     stdx::char_auto_ptr result (duplicate_chars (buf));
    283     return result;
    284 }
    285 
    286 stdx::char_auto_ptr ToString (const char *aData, size_t aLen)
    287 {
    288     /* each byte will produce two hex digits and there will be a null
    289      * terminator */
    290     stdx::char_auto_ptr result (new char [aLen * 2 + 1]);
    291 
    292     const char *src = aData;
    293     char *dst =  result.get();
    294 
    295     for (size_t i = 0; i < aLen; ++ i, ++ src)
    296     {
    297         *dst++ = sToHex ((*src) >> 4);
    298         *dst++ = sToHex ((*src) & 0xF);
    299     }
    300 
    301     *dst = '\0';
    302 
    303     return result;
    304 }
    305 
    306 //////////////////////////////////////////////////////////////////////////////
    307 // XmlKeyBackend Class
    308 //////////////////////////////////////////////////////////////////////////////
    309 
    310 class XmlKeyBackend : public Key::Backend
    311 {
    312 public:
    313 
    314     XmlKeyBackend (xmlNodePtr aNode);
    315     ~XmlKeyBackend();
    316 
    317     const char *name() const;
    318     void setName (const char *aName);
    319     const char *value (const char *aName) const;
    320     void setValue (const char *aName, const char *aValue);
    321 
    322     Key::List keys (const char *aName = NULL) const;
    323     Key findKey (const char *aName) const;
    324 
    325     Key appendKey (const char *aName);
    326     void zap();
    327 
    328     void *position() const { return mNode; }
    329 
    330 private:
    331 
    332     xmlNodePtr mNode;
    333 
    334     xmlChar *mNodeText;
    335 
    336     DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (XmlKeyBackend);
    337 
    338     friend class XmlTreeBackend;
    339 };
    340 
    341 XmlKeyBackend::XmlKeyBackend (xmlNodePtr aNode)
    342     : mNode (aNode), mNodeText (NULL)
    343 {
    344     AssertReturnVoid (mNode);
    345     AssertReturnVoid (mNode->type == XML_ELEMENT_NODE);
    346 }
    347 
    348 XmlKeyBackend::~XmlKeyBackend()
    349 {
    350     xmlFree (mNodeText);
    351 }
    352 
    353 const char *XmlKeyBackend::name() const
    354 {
    355     return mNode ? (char *) mNode->name : NULL;
    356 }
    357 
    358 void XmlKeyBackend::setName (const char *aName)
    359 {
    360     throw xml::ENotImplemented (RT_SRC_POS);
    361 }
    362 
    363 const char *XmlKeyBackend::value (const char *aName) const
    364 {
    365     if (!mNode)
    366         return NULL;
    367 
    368     if (aName == NULL)
    369     {
    370         /* @todo xmlNodeListGetString (,,1) returns NULL for things like
    371          * <Foo></Foo> and may want to return "" in this case to distinguish
    372          * from <Foo/> (where NULL is pretty much expected). */
    373         if (!mNodeText)
    374             unconst(mNodeText) =
    375                 xmlNodeListGetString (mNode->doc, mNode->children, 0);
    376         return (char *) mNodeText;
    377     }
    378 
    379     xmlAttrPtr attr = xmlHasProp (mNode, (const xmlChar *) aName);
    380     if (!attr)
    381         return NULL;
    382 
    383     if (attr->type == XML_ATTRIBUTE_NODE)
    384     {
    385         /* @todo for now, we only understand the most common case: only 1 text
    386          * node comprises the attribute's contents. Otherwise we'd need to
    387          * return a newly allocated string buffer to the caller that
    388          * concatenates all text nodes and obey him to free it or provide our
    389          * own internal map of attribute=value pairs and return const pointers
    390          * to values from this map. */
    391         if (attr->children != NULL &&
    392             attr->children->next == NULL &&
    393             (attr->children->type == XML_TEXT_NODE ||
    394              attr->children->type == XML_CDATA_SECTION_NODE))
    395             return (char *) attr->children->content;
    396     }
    397     else if (attr->type == XML_ATTRIBUTE_DECL)
    398     {
    399         return (char *) ((xmlAttributePtr) attr)->defaultValue;
    400     }
    401 
    402     return NULL;
    403 }
    404 
    405 void XmlKeyBackend::setValue (const char *aName, const char *aValue)
    406 {
    407     if (!mNode)
    408         return;
    409 
    410     if (aName == NULL)
    411     {
    412         xmlChar *value = (xmlChar *) aValue;
    413         if (value != NULL)
    414         {
    415             value = xmlEncodeSpecialChars (mNode->doc, value);
    416             if (value == NULL)
    417                 throw std::bad_alloc();
    418         }
    419 
    420         xmlNodeSetContent (mNode, value);
    421 
    422         if (value != (xmlChar *) aValue)
    423             xmlFree (value);
    424 
    425         /* outdate the node text holder */
    426         if (mNodeText != NULL)
    427         {
    428             xmlFree (mNodeText);
    429             mNodeText = NULL;
    430         }
    431 
    432         return;
    433     }
    434 
    435     if (aValue == NULL)
    436     {
    437         /* remove the attribute if it exists */
    438         xmlAttrPtr attr = xmlHasProp (mNode, (const xmlChar *) aName);
    439         if (attr != NULL)
    440         {
    441             int rc = xmlRemoveProp (attr);
    442             if (rc != 0)
    443                 throw xml::EInvalidArg (RT_SRC_POS);
    444         }
    445         return;
    446     }
    447 
    448     xmlAttrPtr attr = xmlSetProp (mNode, (const xmlChar *) aName,
    449                                   (const xmlChar *) aValue);
    450     if (attr == NULL)
    451         throw std::bad_alloc();
    452 }
    453 
    454 Key::List XmlKeyBackend::keys (const char *aName /* = NULL */) const
    455 {
    456     Key::List list;
    457 
    458     if (!mNode)
    459         return list;
    460 
    461     for (xmlNodePtr node = mNode->children; node; node = node->next)
    462     {
    463         if (node->type == XML_ELEMENT_NODE)
    464         {
    465             if (aName == NULL ||
    466                 strcmp (aName, (char *) node->name) == 0)
    467                 list.push_back (Key (new XmlKeyBackend (node)));
    468         }
    469     }
    470 
    471     return list;
    472 }
    473 
    474 Key XmlKeyBackend::findKey (const char *aName) const
    475 {
    476     Key key;
    477 
    478     if (!mNode)
    479         return key;
    480 
    481     for (xmlNodePtr node = mNode->children; node; node = node->next)
    482     {
    483         if (node->type == XML_ELEMENT_NODE)
    484         {
    485             if (aName == NULL ||
    486                 strcmp (aName, (char *) node->name) == 0)
    487             {
    488                 key = Key (new XmlKeyBackend (node));
    489                 break;
    490             }
    491         }
    492     }
    493 
    494     return key;
    495 }
    496 
    497 Key XmlKeyBackend::appendKey (const char *aName)
    498 {
    499     if (!mNode)
    500         return Key();
    501 
    502     xmlNodePtr node = xmlNewChild (mNode, NULL, (const xmlChar *) aName, NULL);
    503     if (node == NULL)
    504         throw std::bad_alloc();
    505 
    506     return Key (new XmlKeyBackend (node));
    507 }
    508 
    509 void XmlKeyBackend::zap()
    510 {
    511     if (!mNode)
    512         return;
    513 
    514     xmlUnlinkNode (mNode);
    515     xmlFreeNode (mNode);
    516     mNode = NULL;
    517 }
    518 
    519 //////////////////////////////////////////////////////////////////////////////
    520 // XmlTreeBackend Class
    521 //////////////////////////////////////////////////////////////////////////////
    522 
    523 struct XmlTreeBackend::Data
    524 {
    525     Data() : ctxt (NULL), doc (NULL)
    526            , inputResolver (NULL)
    527            , autoConverter (NULL), oldVersion (NULL) {}
    528 
    529     xmlParserCtxtPtr ctxt;
    530     xmlDocPtr doc;
    531 
    532     Key root;
    533 
    534     InputResolver *inputResolver;
    535 
    536     AutoConverter *autoConverter;
    537     char *oldVersion;
    538 
    539     std::auto_ptr <stdx::exception_trap_base> trappedErr;
    540 
    541     /**
    542      * This is to avoid throwing exceptions while in libxml2 code and
    543      * redirect them to our level instead. Also used to perform clean up
    544      * by deleting the I/O stream instance and self when requested.
    545      */
    546     struct IOCtxt
    547     {
    548         IOCtxt (xml::Stream *aStream, std::auto_ptr <stdx::exception_trap_base> &aErr)
    549             : stream (aStream), deleteStreamOnClose (false)
    550             , err (aErr) {}
    551 
    552         template <typename T>
    553         void setErr (const T& aErr) { err.reset (new stdx::exception_trap <T> (aErr)); }
    554 
    555         void resetErr() { err.reset(); }
    556 
    557         xml::Stream *stream;
    558         bool deleteStreamOnClose;
    559 
    560         std::auto_ptr <stdx::exception_trap_base> &err;
    561     };
    562 
    563     struct InputCtxt : public IOCtxt
    564     {
    565         InputCtxt (xml::Input *aInput, std::auto_ptr <stdx::exception_trap_base> &aErr)
    566             : IOCtxt (aInput, aErr), input (aInput) {}
    567 
    568         xml::Input *input;
    569     };
    570 
    571     struct OutputCtxt : public IOCtxt
    572     {
    573         OutputCtxt (xml::Output *aOutput, std::auto_ptr <stdx::exception_trap_base> &aErr)
    574             : IOCtxt (aOutput, aErr), output (aOutput) {}
    575 
    576         xml::Output *output;
    577     };
    578 };
    579 
    580 XmlTreeBackend::XmlTreeBackend()
    581     : m (new Data())
    582 {
    583     /* create a parser context */
    584     m->ctxt = xmlNewParserCtxt();
    585     if (m->ctxt == NULL)
    586         throw std::bad_alloc();
    587 }
    588 
    589 XmlTreeBackend::~XmlTreeBackend()
    590 {
    591     reset();
    592 
    593     xmlFreeParserCtxt (m->ctxt);
    594     m->ctxt = NULL;
    595 }
    596 
    597 void XmlTreeBackend::setInputResolver (InputResolver &aResolver)
    598 {
    599     m->inputResolver = &aResolver;
    600 }
    601 
    602 void XmlTreeBackend::resetInputResolver()
    603 {
    604     m->inputResolver = NULL;
    605 }
    606 
    607 void XmlTreeBackend::setAutoConverter (AutoConverter &aConverter)
    608 {
    609     m->autoConverter = &aConverter;
    610 }
    611 
    612 void XmlTreeBackend::resetAutoConverter()
    613 {
    614     m->autoConverter = NULL;
    615 }
    616 
    617 const char *XmlTreeBackend::oldVersion() const
    618 {
    619     return m->oldVersion;
    620 }
    621 
    622 extern "C" xmlGenericErrorFunc xsltGenericError;
    623 extern "C" void *xsltGenericErrorContext;
    624 
    625 void XmlTreeBackend::rawRead (xml::Input &aInput, const char *aSchema /* = NULL */,
    626                               int aFlags /* = 0 */)
    627 {
    628     /* Reset error variables used to memorize exceptions while inside the
    629      * libxml2 code. */
    630     m->trappedErr.reset();
    631 
    632     /* We use the global lock for the whole duration of this method to serialize
    633      * access to thread-unsafe xmlGetExternalEntityLoader() and some other
    634      * calls. It means that only one thread is able to parse an XML stream at a
    635      * time but another choice would be to patch libxml2/libxslt which is
    636      * unwanted now for several reasons. Search for "thread-safe" to find all
    637      * unsafe cases. */
    638     xml::GlobalLock global;
    639     global.setExternalEntityLoader(ExternalEntityLoader);
    640 
    641     sThat = this;
    642     xmlDocPtr doc = NULL;
    643 
    644     try
    645     {
    646         /* Note: when parsing we use XML_PARSE_NOBLANKS to instruct libxml2 to
    647          * remove text nodes that contain only blanks. This is important because
    648          * otherwise xmlSaveDoc() won't be able to do proper indentation on
    649          * output. */
    650         /* parse the stream */
    651         /* NOTE: new InputCtxt instance will be deleted when the stream is closed by
    652          * the libxml2 API (e.g. when calling xmlFreeParserCtxt()) */
    653         doc = xmlCtxtReadIO (m->ctxt,
    654                              ReadCallback, CloseCallback,
    655                              new Data::InputCtxt (&aInput, m->trappedErr),
    656                              aInput.uri(), NULL,
    657                              XML_PARSE_NOBLANKS);
    658         if (doc == NULL)
    659         {
    660             /* look if there was a forwared exception from the lower level */
    661             if (m->trappedErr.get() != NULL)
    662                 m->trappedErr->rethrow();
    663 
    664             throw xml::XmlError(xmlCtxtGetLastError (m->ctxt));
    665         }
    666 
    667         char *oldVersion = NULL;
    668 
    669         /* perform automatic document transformation if necessary */
    670         if (m->autoConverter != NULL &&
    671             m->autoConverter->
    672                 needsConversion (Key (new XmlKeyBackend (xmlDocGetRootElement (doc))),
    673                                  &oldVersion))
    674         {
    675             xmlDocPtr xsltDoc = NULL;
    676             xsltStylesheetPtr xslt = NULL;
    677             char *errorStr = NULL;
    678 
    679             xmlGenericErrorFunc oldXsltGenericError = xsltGenericError;
    680             void *oldXsltGenericErrorContext = xsltGenericErrorContext;
    681 
    682             try
    683             {
    684                 /* parse the XSLT template */
    685                 {
    686                     xml::Input *xsltInput =
    687                         m->inputResolver->resolveEntity
    688                             (m->autoConverter->templateUri(), NULL);
    689                     /* NOTE: new InputCtxt instance will be deleted when the
    690                      * stream is closed by the libxml2 API */
    691                     xsltDoc = xmlCtxtReadIO (m->ctxt,
    692                                              ReadCallback, CloseCallback,
    693                                              new Data::InputCtxt (xsltInput, m->trappedErr),
    694                                              m->autoConverter->templateUri(),
    695                                              NULL, 0);
    696                     delete xsltInput;
    697                 }
    698 
    699                 if (xsltDoc == NULL)
    700                 {
    701                     /* look if there was a forwared exception from the lower level */
    702                     if (m->trappedErr.get() != NULL)
    703                         m->trappedErr->rethrow();
    704 
    705                     throw xml::XmlError(xmlCtxtGetLastError (m->ctxt));
    706                 }
    707 
    708                 /* setup stylesheet compilation and transformation error
    709                  * reporting. Note that we could create a new transform context
    710                  * for doing xsltApplyStylesheetUser and use
    711                  * xsltSetTransformErrorFunc() on it to set a dedicated error
    712                  * handler but as long as we already do several non-thread-safe
    713                  * hacks, this is not really important. */
    714 
    715                 xsltGenericError = ValidityErrorCallback;
    716                 xsltGenericErrorContext = &errorStr;
    717 
    718                 xslt = xsltParseStylesheetDoc (xsltDoc);
    719                 if (xslt == NULL)
    720                 {
    721                     if (errorStr != NULL)
    722                         throw xml::LogicError (errorStr);
    723                     /* errorStr is freed in catch(...) below */
    724 
    725                     throw xml::LogicError (RT_SRC_POS);
    726                 }
    727 
    728                 /* repeat transformations until autoConverter is satisfied */
    729                 do
    730                 {
    731                     xmlDocPtr newDoc = xsltApplyStylesheet (xslt, doc, NULL);
    732                     if (newDoc == NULL && errorStr == NULL)
    733                         throw xml::LogicError (RT_SRC_POS);
    734 
    735                     if (errorStr != NULL)
    736                     {
    737                         xmlFreeDoc (newDoc);
    738                         throw xml::RuntimeError(errorStr);
    739                         /* errorStr is freed in catch(...) below */
    740                     }
    741 
    742                     /* replace the old document on success */
    743                     xmlFreeDoc (doc);
    744                     doc = newDoc;
    745                 }
    746                 while (m->autoConverter->
    747                        needsConversion (Key (new XmlKeyBackend (xmlDocGetRootElement (doc))),
    748                                         NULL));
    749 
    750                 RTStrFree (errorStr);
    751 
    752                 /* NOTE: xsltFreeStylesheet() also fress the document
    753                  * passed to xsltParseStylesheetDoc(). */
    754                 xsltFreeStylesheet (xslt);
    755 
    756                 /* restore the previous generic error func */
    757                 xsltGenericError = oldXsltGenericError;
    758                 xsltGenericErrorContext = oldXsltGenericErrorContext;
    759             }
    760             catch (...)
    761             {
    762                 RTStrFree (errorStr);
    763 
    764                 /* NOTE: xsltFreeStylesheet() also fress the document
    765                  * passed to xsltParseStylesheetDoc(). */
    766                 if (xslt != NULL)
    767                     xsltFreeStylesheet (xslt);
    768                 else if (xsltDoc != NULL)
    769                     xmlFreeDoc (xsltDoc);
    770 
    771                 /* restore the previous generic error func */
    772                 xsltGenericError = oldXsltGenericError;
    773                 xsltGenericErrorContext = oldXsltGenericErrorContext;
    774 
    775                 RTStrFree (oldVersion);
    776 
    777                 throw;
    778             }
    779         }
    780 
    781         /* validate the document */
    782         if (aSchema != NULL)
    783         {
    784             xmlSchemaParserCtxtPtr schemaCtxt = NULL;
    785             xmlSchemaPtr schema = NULL;
    786             xmlSchemaValidCtxtPtr validCtxt = NULL;
    787             char *errorStr = NULL;
    788 
    789             try
    790             {
    791                 bool valid = false;
    792 
    793                 schemaCtxt = xmlSchemaNewParserCtxt (aSchema);
    794                 if (schemaCtxt == NULL)
    795                     throw xml::LogicError (RT_SRC_POS);
    796 
    797                 /* set our error handlers */
    798                 xmlSchemaSetParserErrors (schemaCtxt, ValidityErrorCallback,
    799                                           ValidityWarningCallback, &errorStr);
    800                 xmlSchemaSetParserStructuredErrors (schemaCtxt,
    801                                                     StructuredErrorCallback,
    802                                                     &errorStr);
    803                 /* load schema */
    804                 schema = xmlSchemaParse (schemaCtxt);
    805                 if (schema != NULL)
    806                 {
    807                     validCtxt = xmlSchemaNewValidCtxt (schema);
    808                     if (validCtxt == NULL)
    809                         throw xml::LogicError (RT_SRC_POS);
    810 
    811                     /* instruct to create default attribute's values in the document */
    812                     if (aFlags & Read_AddDefaults)
    813                         xmlSchemaSetValidOptions (validCtxt, XML_SCHEMA_VAL_VC_I_CREATE);
    814 
    815                     /* set our error handlers */
    816                     xmlSchemaSetValidErrors (validCtxt, ValidityErrorCallback,
    817                                              ValidityWarningCallback, &errorStr);
    818 
    819                     /* finally, validate */
    820                     valid = xmlSchemaValidateDoc (validCtxt, doc) == 0;
    821                 }
    822 
    823                 if (!valid)
    824                 {
    825                     /* look if there was a forwared exception from the lower level */
    826                     if (m->trappedErr.get() != NULL)
    827                         m->trappedErr->rethrow();
    828 
    829                     if (errorStr == NULL)
    830                         throw xml::LogicError (RT_SRC_POS);
    831 
    832                     throw xml::RuntimeError(errorStr);
    833                     /* errorStr is freed in catch(...) below */
    834                 }
    835 
    836                 RTStrFree (errorStr);
    837 
    838                 xmlSchemaFreeValidCtxt (validCtxt);
    839                 xmlSchemaFree (schema);
    840                 xmlSchemaFreeParserCtxt (schemaCtxt);
    841             }
    842             catch (...)
    843             {
    844                 RTStrFree (errorStr);
    845 
    846                 if (validCtxt)
    847                     xmlSchemaFreeValidCtxt (validCtxt);
    848                 if (schema)
    849                     xmlSchemaFree (schema);
    850                 if (schemaCtxt)
    851                     xmlSchemaFreeParserCtxt (schemaCtxt);
    852 
    853                 RTStrFree (oldVersion);
    854 
    855                 throw;
    856             }
    857         }
    858 
    859         /* reset the previous tree on success */
    860         reset();
    861 
    862         m->doc = doc;
    863         /* assign the root key */
    864         m->root = Key (new XmlKeyBackend (xmlDocGetRootElement (m->doc)));
    865 
    866         /* memorize the old version string also used as a flag that
    867          * the conversion has been performed (transfers ownership) */
    868         m->oldVersion = oldVersion;
    869 
    870         sThat = NULL;
    871     }
    872     catch (...)
    873     {
    874         if (doc != NULL)
    875             xmlFreeDoc (doc);
    876 
    877         sThat = NULL;
    878 
    879         throw;
    880     }
    881 }
    882 
    883 void XmlTreeBackend::rawWrite (xml::Output &aOutput)
    884 {
    885     /* reset error variables used to memorize exceptions while inside the
    886      * libxml2 code */
    887     m->trappedErr.reset();
    888 
    889     /* set up an input stream for parsing the document. This will be deleted
    890      * when the stream is closed by the libxml2 API (e.g. when calling
    891      * xmlFreeParserCtxt()). */
    892     Data::OutputCtxt *outputCtxt =
    893         new Data::OutputCtxt (&aOutput, m->trappedErr);
    894 
    895     /* serialize to the stream */
    896 
    897     xmlIndentTreeOutput = 1;
    898     xmlTreeIndentString = "  ";
    899     xmlSaveNoEmptyTags = 0;
    900 
    901     xmlSaveCtxtPtr saveCtxt = xmlSaveToIO (WriteCallback, CloseCallback,
    902                                            outputCtxt, NULL,
    903                                            XML_SAVE_FORMAT);
    904     if (saveCtxt == NULL)
    905         throw xml::LogicError (RT_SRC_POS);
    906 
    907     long rc = xmlSaveDoc (saveCtxt, m->doc);
    908     if (rc == -1)
    909     {
    910         /* look if there was a forwared exception from the lower level */
    911         if (m->trappedErr.get() != NULL)
    912             m->trappedErr->rethrow();
    913 
    914         /* there must be an exception from the Output implementation,
    915          * otherwise the save operation must always succeed. */
    916         throw xml::LogicError (RT_SRC_POS);
    917     }
    918 
    919     xmlSaveClose (saveCtxt);
    920 }
    921 
    922 void XmlTreeBackend::reset()
    923 {
    924     RTStrFree (m->oldVersion);
    925     m->oldVersion = NULL;
    926 
    927     if (m->doc)
    928     {
    929         /* reset the root key's node */
    930         GetKeyBackend (m->root)->mNode = NULL;
    931         /* free the document*/
    932         xmlFreeDoc (m->doc);
    933         m->doc = NULL;
    934     }
    935 }
    936 
    937 Key &XmlTreeBackend::rootKey() const
    938 {
    939     return m->root;
    940 }
    941 
    942 /* static */
    943 int XmlTreeBackend::ReadCallback (void *aCtxt, char *aBuf, int aLen)
    944 {
    945     AssertReturn(aCtxt != NULL, 0);
    946 
    947     Data::InputCtxt *ctxt = static_cast <Data::InputCtxt *> (aCtxt);
    948 
    949     /* To prevent throwing exceptions while inside libxml2 code, we catch
    950      * them and forward to our level using a couple of variables. */
    951     try
    952     {
    953         return ctxt->input->read (aBuf, aLen);
    954     }
    955     catch (const xml::EIPRTFailure &err) { ctxt->setErr (err); }
    956     catch (const xml::Error &err) { ctxt->setErr (err); }
    957     catch (const std::exception &err) { ctxt->setErr (err); }
    958     catch (...) { ctxt->setErr (xml::LogicError (RT_SRC_POS)); }
    959 
    960     return -1 /* failure */;
    961 }
    962 
    963 /* static */
    964 int XmlTreeBackend::WriteCallback (void *aCtxt, const char *aBuf, int aLen)
    965 {
    966     AssertReturn(aCtxt != NULL, 0);
    967 
    968     Data::OutputCtxt *ctxt = static_cast <Data::OutputCtxt *> (aCtxt);
    969 
    970     /* To prevent throwing exceptions while inside libxml2 code, we catch
    971      * them and forward to our level using a couple of variables. */
    972     try
    973     {
    974         return ctxt->output->write (aBuf, aLen);
    975     }
    976     catch (const xml::EIPRTFailure &err) { ctxt->setErr (err); }
    977     catch (const xml::Error &err) { ctxt->setErr (err); }
    978     catch (const std::exception &err) { ctxt->setErr (err); }
    979     catch (...) { ctxt->setErr (xml::LogicError (RT_SRC_POS)); }
    980 
    981     return -1 /* failure */;
    982 }
    983 
    984 /* static */
    985 int XmlTreeBackend::CloseCallback (void *aCtxt)
    986 {
    987     AssertReturn(aCtxt != NULL, 0);
    988 
    989     Data::IOCtxt *ctxt = static_cast <Data::IOCtxt *> (aCtxt);
    990 
    991     /* To prevent throwing exceptions while inside libxml2 code, we catch
    992      * them and forward to our level using a couple of variables. */
    993     try
    994     {
    995         /// @todo there is no explicit close semantics in Stream yet
    996 #if 0
    997         ctxt->stream->close();
    998 #endif
    999 
    1000         /* perform cleanup when necessary */
    1001         if (ctxt->deleteStreamOnClose)
    1002             delete ctxt->stream;
    1003 
    1004         delete ctxt;
    1005 
    1006         return 0 /* success */;
    1007     }
    1008     catch (const xml::EIPRTFailure &err) { ctxt->setErr (err); }
    1009     catch (const xml::Error &err) { ctxt->setErr (err); }
    1010     catch (const std::exception &err) { ctxt->setErr (err); }
    1011     catch (...) { ctxt->setErr (xml::LogicError (RT_SRC_POS)); }
    1012 
    1013     return -1 /* failure */;
    1014 }
    1015 
    1016 /* static */
    1017 void XmlTreeBackend::ValidityErrorCallback (void *aCtxt, const char *aMsg, ...)
    1018 {
    1019     AssertReturnVoid (aCtxt != NULL);
    1020     AssertReturnVoid (aMsg != NULL);
    1021 
    1022     char * &str = *(char * *) aCtxt;
    1023 
    1024     char *newMsg = NULL;
    1025     {
    1026         va_list args;
    1027         va_start (args, aMsg);
    1028         RTStrAPrintfV (&newMsg, aMsg, args);
    1029         va_end (args);
    1030     }
    1031 
    1032     AssertReturnVoid (newMsg != NULL);
    1033 
    1034     /* strip spaces, trailing EOLs and dot-like char */
    1035     size_t newMsgLen = strlen (newMsg);
    1036     while (newMsgLen && strchr (" \n.?!", newMsg [newMsgLen - 1]))
    1037         -- newMsgLen;
    1038 
    1039     /* anything left? */
    1040     if (newMsgLen > 0)
    1041     {
    1042         if (str == NULL)
    1043         {
    1044             str = newMsg;
    1045             newMsg [newMsgLen] = '\0';
    1046         }
    1047         else
    1048         {
    1049             /* append to the existing string */
    1050             size_t strLen = strlen (str);
    1051             char *newStr = (char *) RTMemRealloc (str, strLen + 2 + newMsgLen + 1);
    1052             AssertReturnVoid (newStr != NULL);
    1053 
    1054             memcpy (newStr + strLen, ".\n", 2);
    1055             memcpy (newStr + strLen + 2, newMsg, newMsgLen);
    1056             newStr [strLen + 2 + newMsgLen] = '\0';
    1057             str = newStr;
    1058             RTStrFree (newMsg);
    1059         }
    1060     }
    1061 }
    1062 
    1063 /* static */
    1064 void XmlTreeBackend::ValidityWarningCallback (void *aCtxt, const char *aMsg, ...)
    1065 {
    1066     NOREF (aCtxt);
    1067     NOREF (aMsg);
    1068 }
    1069 
    1070 /* static */
    1071 void XmlTreeBackend::StructuredErrorCallback (void *aCtxt, xmlErrorPtr aErr)
    1072 {
    1073     AssertReturnVoid (aCtxt != NULL);
    1074     AssertReturnVoid (aErr != NULL);
    1075 
    1076     char * &str = *(char * *) aCtxt;
    1077 
    1078     char *newMsg = xml::XmlError::Format (aErr);
    1079     AssertReturnVoid (newMsg != NULL);
    1080 
    1081     if (str == NULL)
    1082         str = newMsg;
    1083     else
    1084     {
    1085         /* append to the existing string */
    1086         size_t newMsgLen = strlen (newMsg);
    1087         size_t strLen = strlen (str);
    1088         char *newStr = (char *) RTMemRealloc (str, strLen + newMsgLen + 2);
    1089         AssertReturnVoid (newStr != NULL);
    1090 
    1091         memcpy (newStr + strLen, ".\n", 2);
    1092         memcpy (newStr + strLen + 2, newMsg, newMsgLen);
    1093         str = newStr;
    1094         RTStrFree (newMsg);
    1095     }
    1096 }
    1097 
    1098 /* static */
    1099 XmlTreeBackend *XmlTreeBackend::sThat = NULL;
    1100 
    1101 /* static */
    1102 xmlParserInputPtr XmlTreeBackend::ExternalEntityLoader (const char *aURI,
    1103                                                         const char *aID,
    1104                                                         xmlParserCtxtPtr aCtxt)
    1105 {
    1106     AssertReturn(sThat != NULL, NULL);
    1107 
    1108     if (sThat->m->inputResolver == NULL)
    1109         return xml::GlobalLock::callDefaultLoader(aURI, aID, aCtxt);
    1110 
    1111     /* To prevent throwing exceptions while inside libxml2 code, we catch
    1112      * them and forward to our level using a couple of variables. */
    1113     try
    1114     {
    1115         xml::Input *input = sThat->m->inputResolver->resolveEntity (aURI, aID);
    1116         if (input == NULL)
    1117             return NULL;
    1118 
    1119         Data::InputCtxt *ctxt = new Data::InputCtxt (input, sThat->m->trappedErr);
    1120         ctxt->deleteStreamOnClose = true;
    1121 
    1122         /* create an input buffer with custom hooks */
    1123         xmlParserInputBufferPtr bufPtr =
    1124             xmlParserInputBufferCreateIO (ReadCallback, CloseCallback,
    1125                                           ctxt, XML_CHAR_ENCODING_NONE);
    1126         if (bufPtr)
    1127         {
    1128             /* create an input stream */
    1129             xmlParserInputPtr inputPtr =
    1130                 xmlNewIOInputStream (aCtxt, bufPtr, XML_CHAR_ENCODING_NONE);
    1131 
    1132             if (inputPtr != NULL)
    1133             {
    1134                 /* pass over the URI to the stream struct (it's NULL by
    1135                  * default) */
    1136                 inputPtr->filename =
    1137                     (char *) xmlCanonicPath ((const xmlChar *) input->uri());
    1138                 return inputPtr;
    1139             }
    1140         }
    1141 
    1142         /* either of libxml calls failed */
    1143 
    1144         if (bufPtr)
    1145             xmlFreeParserInputBuffer (bufPtr);
    1146 
    1147         delete input;
    1148         delete ctxt;
    1149 
    1150         throw std::bad_alloc();
    1151     }
    1152     catch (const xml::EIPRTFailure &err) { sThat->m->trappedErr.reset (stdx::new_exception_trap (err)); }
    1153     catch (const xml::Error &err) { sThat->m->trappedErr.reset (stdx::new_exception_trap (err)); }
    1154     catch (const std::exception &err) { sThat->m->trappedErr.reset (stdx::new_exception_trap (err)); }
    1155     catch (...) { sThat->m->trappedErr.reset (stdx::new_exception_trap (xml::LogicError (RT_SRC_POS))); }
    1156 
    1157     return NULL;
    1158 }
    1159 
    1160 
    1161 } /* namespace settings */
    1162 
     1746        }
     1747    }
     1748
     1749    xml::ElementNode *pelmPorts = pelmHardware->createChild("UART");
     1750    for (SerialPortsList::const_iterator it = hw.llSerialPorts.begin();
     1751         it != hw.llSerialPorts.end();
     1752         ++it)
     1753    {
     1754        const SerialPort &port = *it;
     1755        xml::ElementNode *pelmPort = pelmPorts->createChild("Port");
     1756        pelmPort->setAttribute("slot", port.ulSlot);
     1757        pelmPort->setAttribute("enabled", port.fEnabled);
     1758        pelmPort->setAttributeHex("IOBase", port.ulIOBase);
     1759        pelmPort->setAttribute("IRQ", port.ulIRQ);
     1760
     1761        const char *pcszHostMode;
     1762        switch (port.portMode)
     1763        {
     1764            case PortMode_HostPipe: pcszHostMode = "HostPipe"; break;
     1765            case PortMode_HostDevice: pcszHostMode = "HostDevice"; break;
     1766            case PortMode_RawFile: pcszHostMode = "RawFile"; break;
     1767            default: /*case PortMode_Disconnected:*/ pcszHostMode = "Disconnected"; break;
     1768        }
     1769        pelmPort->setAttribute("hostMode", pcszHostMode);
     1770    }
     1771
     1772    pelmPorts = pelmHardware->createChild("LPT");
     1773    for (ParallelPortsList::const_iterator it = hw.llParallelPorts.begin();
     1774         it != hw.llParallelPorts.end();
     1775         ++it)
     1776    {
     1777        const ParallelPort &port = *it;
     1778        xml::ElementNode *pelmPort = pelmPorts->createChild("Port");
     1779        pelmPort->setAttribute("slot", port.ulSlot);
     1780        pelmPort->setAttribute("enabled", port.fEnabled);
     1781        pelmPort->setAttributeHex("IOBase", port.ulIOBase);
     1782        pelmPort->setAttribute("IRQ", port.ulIRQ);
     1783        if (port.strPath.length())
     1784            pelmPort->setAttribute("path", port.strPath);
     1785    }
     1786
     1787    xml::ElementNode *pelmAudio = pelmHardware->createChild("AudioAdapter");
     1788    pelmAudio->setAttribute("controller", (hw.audioAdapter.controllerType == AudioControllerType_SB16) ? "SB16" : "AC97");
     1789
     1790    const char *pcszDriver;
     1791    switch (hw.audioAdapter.driverType)
     1792    {
     1793        case AudioDriverType_WinMM: pcszDriver = "WinMM"; break;
     1794        case AudioDriverType_DirectSound: pcszDriver = "DirectSound"; break;
     1795        case AudioDriverType_SolAudio: pcszDriver = "SolAudio"; break;
     1796        case AudioDriverType_ALSA: pcszDriver = "ALSA"; break;
     1797        case AudioDriverType_Pulse: pcszDriver = "Pulse"; break;
     1798        case AudioDriverType_OSS: pcszDriver = "OSS"; break;
     1799        case AudioDriverType_CoreAudio: pcszDriver = "CoreAudio"; break;
     1800        case AudioDriverType_MMPM: pcszDriver = "MMPM"; break;
     1801        default: /*case AudioDriverType_Null:*/ pcszDriver = "Null"; break;
     1802    }
     1803    pelmAudio->setAttribute("driver", pcszDriver);
     1804
     1805    pelmAudio->setAttribute("enabled", hw.audioAdapter.fEnabled);
     1806
     1807    xml::ElementNode *pelmSharedFolders = pelmHardware->createChild("SharedFolders");
     1808    for (SharedFoldersList::const_iterator it = hw.llSharedFolders.begin();
     1809         it != hw.llSharedFolders.end();
     1810         ++it)
     1811    {
     1812        const SharedFolder &sf = *it;
     1813        xml::ElementNode *pelmThis = pelmSharedFolders->createChild("SharedFolder");
     1814        pelmThis->setAttribute("name", sf.strName);
     1815        pelmThis->setAttribute("hostPath", sf.strHostPath);
     1816        pelmThis->setAttribute("writable", sf.fWritable);
     1817    }
     1818
     1819    xml::ElementNode *pelmClip = pelmHardware->createChild("Clipboard");
     1820    const char *pcszClip;
     1821    switch (hw.clipboardMode)
     1822    {
     1823        case ClipboardMode_Disabled: pcszClip = "Disabled"; break;
     1824        case ClipboardMode_HostToGuest: pcszClip = "HostToGuest"; break;
     1825        case ClipboardMode_GuestToHost: pcszClip = "GuestToHost"; break;
     1826        default: /*case ClipboardMode_Bidirectional:*/ pcszClip = "Bidirectional"; break;
     1827    }
     1828    pelmClip->setAttribute("mode", pcszClip);
     1829
     1830    xml::ElementNode *pelmGuest = pelmHardware->createChild("Guest");
     1831    pelmGuest->setAttribute("memoryBalloonSize", hw.ulMemoryBalloonSize);
     1832    pelmGuest->setAttribute("statisticsUpdateInterval", hw.ulStatisticsUpdateInterval);
     1833
     1834    xml::ElementNode *pelmGuestProps = pelmHardware->createChild("GuestProperties");
     1835    for (GuestPropertiesList::const_iterator it = hw.llGuestProperties.begin();
     1836         it != hw.llGuestProperties.end();
     1837         ++it)
     1838    {
     1839        const GuestProperty &prop = *it;
     1840        xml::ElementNode *pelmProp = pelmGuestProps->createChild("GuestProperty");
     1841        pelmProp->setAttribute("name", prop.strName);
     1842        pelmProp->setAttribute("value", prop.strValue);
     1843        pelmProp->setAttribute("timestamp", prop.timestamp);
     1844        pelmProp->setAttribute("flags", prop.strFlags);
     1845    }
     1846
     1847    if (hw.strNotificationPatterns.length())
     1848        pelmGuestProps->setAttribute("notificationPatterns", hw.strNotificationPatterns);
     1849}
     1850
     1851/**
     1852 * Creates a <StorageControllers> node under elmParent and then writes out the XML
     1853 * keys under that. Called for both the <Machine> node and for snapshots.
     1854 * @param elmParent
     1855 * @param st
     1856 */
     1857void MachineConfigFile::writeStorageControllers(xml::ElementNode &elmParent,
     1858                                                const Storage &st)
     1859{
     1860    xml::ElementNode *pelmStorageControllers = elmParent.createChild("StorageControllers");
     1861
     1862    for (StorageControllersList::const_iterator it = st.llStorageControllers.begin();
     1863         it != st.llStorageControllers.end();
     1864         ++it)
     1865    {
     1866        const StorageController &sc = *it;
     1867
     1868        xml::ElementNode *pelmController = pelmStorageControllers->createChild("StorageController");
     1869        pelmController->setAttribute("name", sc.strName);
     1870
     1871        const char *pcszType;
     1872        switch (sc.controllerType)
     1873        {
     1874            case StorageControllerType_IntelAhci: pcszType = "AHCI"; break;
     1875            case StorageControllerType_LsiLogic: pcszType = "LsiLogic"; break;
     1876            case StorageControllerType_BusLogic: pcszType = "BusLogic"; break;
     1877            case StorageControllerType_PIIX4: pcszType = "PIIX4"; break;
     1878            case StorageControllerType_ICH6: pcszType = "ICH6"; break;
     1879            default: /*case StorageControllerType_PIIX3:*/ pcszType = "PIIX3"; break;
     1880        }
     1881        pelmController->setAttribute("type", pcszType);
     1882
     1883        pelmController->setAttribute("PortCount", sc.ulPortCount);
     1884
     1885        if (sc.controllerType == StorageControllerType_IntelAhci)
     1886        {
     1887            pelmController->setAttribute("IDE0MasterEmulationPort", sc.lIDE0MasterEmulationPort);
     1888            pelmController->setAttribute("IDE0SlaveEmulationPort", sc.lIDE0SlaveEmulationPort);
     1889            pelmController->setAttribute("IDE1MasterEmulationPort", sc.lIDE1MasterEmulationPort);
     1890            pelmController->setAttribute("IDE1SlaveEmulationPort", sc.lIDE1SlaveEmulationPort);
     1891        }
     1892
     1893        for (AttachedDevicesList::const_iterator it2 = sc.llAttachedDevices.begin();
     1894             it2 != sc.llAttachedDevices.end();
     1895             ++it2)
     1896        {
     1897            const AttachedDevice &dev = *it2;
     1898
     1899            xml::ElementNode *pelmDevice = pelmController->createChild("AttachedDevice");
     1900            pelmDevice->setAttribute("type", "HardDisk");
     1901
     1902            pelmDevice->setAttribute("port", dev.lPort);
     1903            pelmDevice->setAttribute("device", dev.lDevice);
     1904            pelmDevice->createChild("Image")->setAttribute("uuid", makeString(dev.uuid));
     1905        }
     1906    }
     1907}
     1908
     1909/**
     1910 * Writes a single snapshot into the DOM tree. Initially this gets called from MachineConfigFile::write()
     1911 * for the root snapshot of a machine, if present; elmParent then points to the <Snapshots> node under the
     1912 * <Machine> node to which <Snapshot> must be added. This may then recurse for child snapshots.
     1913 * @param elmParent
     1914 * @param snap
     1915 */
     1916void MachineConfigFile::writeSnapshot(xml::ElementNode &elmParent,
     1917                                      const Snapshot &snap)
     1918{
     1919    xml::ElementNode *pelmSnapshot = elmParent.createChild("Snapshot");
     1920
     1921    pelmSnapshot->setAttribute("uuid", makeString(snap.uuid));
     1922    pelmSnapshot->setAttribute("name", snap.strName);
     1923    pelmSnapshot->setAttribute("Description", snap.strDescription);
     1924
     1925    pelmSnapshot->setAttribute("timeStamp", makeString(snap.timestamp));
     1926
     1927    if (snap.strStateFile.length())
     1928        pelmSnapshot->setAttribute("stateFile", snap.strStateFile);
     1929
     1930    writeHardware(*pelmSnapshot, snap.hardware);
     1931    writeStorageControllers(*pelmSnapshot, snap.storage);
     1932
     1933    if (snap.llChildSnapshots.size())
     1934    {
     1935        xml::ElementNode *pelmChildren = pelmSnapshot->createChild("Snapshots");
     1936        for (SnapshotsList::const_iterator it = snap.llChildSnapshots.begin();
     1937             it != snap.llChildSnapshots.end();
     1938             ++it)
     1939        {
     1940            const Snapshot &child = *it;
     1941            writeSnapshot(*pelmChildren, child);
     1942        }
     1943    }
     1944}
     1945
     1946/**
     1947 * Called from Main code to write a machine config file to disk. This builds a DOM tree from
     1948 * the member variables and then writes the XML file; it throws xml::Error instances on errors,
     1949 * in particular if the file cannot be written.
     1950 */
     1951void MachineConfigFile::write(const com::Utf8Str &strFilename)
     1952{
     1953    m->strFilename = strFilename;
     1954
     1955    createStubDocument();
     1956
     1957    xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine");
     1958
     1959    pelmMachine->setAttribute("uuid", makeString(uuid));
     1960    pelmMachine->setAttribute("name", strName);
     1961    if (!fNameSync)
     1962        pelmMachine->setAttribute("nameSync", fNameSync);
     1963    if (strDescription.length())
     1964        pelmMachine->createChild("Description")->addContent(strDescription);
     1965    pelmMachine->setAttribute("OSType", strOsType);
     1966    if (strStateFile.length())
     1967        pelmMachine->setAttribute("stateFile", strStateFile);
     1968    if (!uuidCurrentSnapshot.isEmpty())
     1969        pelmMachine->setAttribute("currentSnapshot", makeString(uuidCurrentSnapshot));
     1970    if (strSnapshotFolder.length())
     1971        pelmMachine->setAttribute("snapshotFolder", strSnapshotFolder);
     1972    if (!fCurrentStateModified)
     1973        pelmMachine->setAttribute("currentStateModified", fCurrentStateModified);
     1974    pelmMachine->setAttribute("lastStateChange", makeString(timeLastStateChange));
     1975    if (fAborted)
     1976        pelmMachine->setAttribute("aborted", fAborted);
     1977
     1978    writeExtraData(*pelmMachine, mapExtraDataItems);
     1979
     1980    if (llFirstSnapshot.size())
     1981        writeSnapshot(*pelmMachine, llFirstSnapshot.front());
     1982
     1983    writeHardware(*pelmMachine, hardwareMachine);
     1984
     1985    writeStorageControllers(*pelmMachine, storageMachine);
     1986
     1987    // now go write the XML
     1988    xml::XmlFileWriter writer(*m->pDoc);
     1989    writer.write(m->strFilename.c_str());
     1990
     1991    m->fFileExists = true;
     1992
     1993    clearDocument();
     1994}
     1995
  • trunk/src/VBox/Main/xml/ovfreader.cpp

    r21701 r22173  
    3838    xml::XmlFileParser parser;
    3939    xml::Document doc;
    40     parser.read(m_strPath.raw(),
     40    parser.read(m_strPath,
    4141                doc);
    4242
    4343    const xml::ElementNode *pRootElem = doc.getRootElement();
    44     if (strcmp(pRootElem->getName(), "Envelope"))
     44    if (pRootElem && strcmp(pRootElem->getName(), "Envelope"))
    4545        throw OVFLogicError(N_("Root element in OVF file must be \"Envelope\"."));
    4646
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r21428 r22173  
    497497}
    498498
     499bool Node::nameEquals(const char *pcsz) const
     500{
     501    if (m->pcszName == pcsz)
     502        return true;
     503    if (m->pcszName == NULL)
     504        return false;
     505    if (pcsz == NULL)
     506        return false;
     507    return !strcmp(m->pcszName, pcsz);
     508}
     509
     510
    499511/**
    500512 * Returns the value of a node. If this node is an attribute, returns
     
    732744/**
    733745 * Convenience method which attempts to find the attribute with the given
     746 * name and returns its value as a string.
     747 *
     748 * @param pcszMatch name of attribute to find.
     749 * @param str out: attribute value
     750 * @return TRUE if attribute was found and str was thus updated.
     751 */
     752bool ElementNode::getAttributeValue(const char *pcszMatch, iprt::MiniString &str) const
     753{
     754    const Node* pAttr;
     755    if ((pAttr = findAttribute(pcszMatch)))
     756    {
     757        str = pAttr->getValue();
     758        return true;
     759    }
     760
     761    return false;
     762}
     763
     764/**
     765 * Convenience method which attempts to find the attribute with the given
     766 * name and returns its value as a signed integer. This calls
     767 * RTStrToInt32Ex internally and will only output the integer if that
     768 * function returns no error.
     769 *
     770 * @param pcszMatch name of attribute to find.
     771 * @param i out: attribute value
     772 * @return TRUE if attribute was found and str was thus updated.
     773 */
     774bool ElementNode::getAttributeValue(const char *pcszMatch, int32_t &i) const
     775{
     776    const char *pcsz;
     777    if (    (getAttributeValue(pcszMatch, pcsz))
     778         && (VINF_SUCCESS == RTStrToInt32Ex(pcsz, NULL, 0, &i))
     779       )
     780        return true;
     781
     782    return false;
     783}
     784
     785/**
     786 * Convenience method which attempts to find the attribute with the given
     787 * name and returns its value as an unsigned integer.This calls
     788 * RTStrToUInt32Ex internally and will only output the integer if that
     789 * function returns no error.
     790 *
     791 * @param pcszMatch name of attribute to find.
     792 * @param i out: attribute value
     793 * @return TRUE if attribute was found and str was thus updated.
     794 */
     795bool ElementNode::getAttributeValue(const char *pcszMatch, uint32_t &i) const
     796{
     797    const char *pcsz;
     798    if (    (getAttributeValue(pcszMatch, pcsz))
     799         && (VINF_SUCCESS == RTStrToUInt32Ex(pcsz, NULL, 0, &i))
     800       )
     801        return true;
     802
     803    return false;
     804}
     805
     806/**
     807 * Convenience method which attempts to find the attribute with the given
    734808 * name and returns its value as a signed long integer. This calls
    735809 * RTStrToInt64Ex internally and will only output the integer if that
     
    744818    const char *pcsz;
    745819    if (    (getAttributeValue(pcszMatch, pcsz))
    746          && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 10, &i))
     820         && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 0, &i))
    747821       )
    748822        return true;
     
    765839    const char *pcsz;
    766840    if (    (getAttributeValue(pcszMatch, pcsz))
    767          && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 10, &i))
     841         && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 0, &i))
    768842       )
    769843        return true;
     844
     845    return false;
     846}
     847
     848/**
     849 * Convenience method which attempts to find the attribute with the given
     850 * name and returns its value as a boolean. This accepts "true", "false",
     851 * "yes", "no", "1" or "0" as valid values.
     852 *
     853 * @param pcszMatch name of attribute to find.
     854 * @param i out: attribute value
     855 * @return TRUE if attribute was found and str was thus updated.
     856 */
     857bool ElementNode::getAttributeValue(const char *pcszMatch, bool &f) const
     858{
     859    const char *pcsz;
     860    if (getAttributeValue(pcszMatch, pcsz))
     861    {
     862        if (    (!strcmp(pcsz, "true"))
     863             || (!strcmp(pcsz, "yes"))
     864             || (!strcmp(pcsz, "1"))
     865           )
     866        {
     867            f = true;
     868            return true;
     869        }
     870        if (    (!strcmp(pcsz, "false"))
     871             || (!strcmp(pcsz, "no"))
     872             || (!strcmp(pcsz, "0"))
     873           )
     874        {
     875            f = false;
     876            return true;
     877        }
     878    }
    770879
    771880    return false;
     
    870979}
    871980
     981AttributeNode* ElementNode::setAttribute(const char *pcszName, int32_t i)
     982{
     983    char *psz = NULL;
     984    RTStrAPrintf(&psz, "%RI32", i);
     985    AttributeNode *p = setAttribute(pcszName, psz);
     986    RTStrFree(psz);
     987    return p;
     988}
     989
     990AttributeNode* ElementNode::setAttribute(const char *pcszName, uint32_t i)
     991{
     992    char *psz = NULL;
     993    RTStrAPrintf(&psz, "%RU32", i);
     994    AttributeNode *p = setAttribute(pcszName, psz);
     995    RTStrFree(psz);
     996    return p;
     997}
     998
     999AttributeNode* ElementNode::setAttribute(const char *pcszName, int64_t i)
     1000{
     1001    char *psz = NULL;
     1002    RTStrAPrintf(&psz, "%RI64", i);
     1003    AttributeNode *p = setAttribute(pcszName, psz);
     1004    RTStrFree(psz);
     1005    return p;
     1006}
     1007
     1008AttributeNode* ElementNode::setAttribute(const char *pcszName, uint64_t i)
     1009{
     1010    char *psz = NULL;
     1011    RTStrAPrintf(&psz, "%RU64", i);
     1012    AttributeNode *p = setAttribute(pcszName, psz);
     1013    RTStrFree(psz);
     1014    return p;
     1015}
     1016
     1017AttributeNode* ElementNode::setAttributeHex(const char *pcszName, uint32_t i)
     1018{
     1019    char *psz = NULL;
     1020    RTStrAPrintf(&psz, "0x%RX32", i);
     1021    AttributeNode *p = setAttribute(pcszName, psz);
     1022    RTStrFree(psz);
     1023    return p;
     1024}
     1025
     1026AttributeNode* ElementNode::setAttribute(const char *pcszName, bool f)
     1027{
     1028    return setAttribute(pcszName, (f) ? "true" : "false");
     1029}
    8721030
    8731031AttributeNode::AttributeNode()
     
    9101068 * NULL, like this:
    9111069 * <code>
    912  *      xml::Node node;         // should point to an element
     1070 *      xml::ElementNode node;               // should point to an element
    9131071 *      xml::NodesLoop loop(node, "child");  // find all "child" elements under node
    914  *      const xml::Node *pChild = NULL;
     1072 *      const xml::ElementNode *pChild = NULL;
    9151073 *      while (pChild = loop.forAllNodes())
    9161074 *          ...;
     
    10181176/**
    10191177 * Returns the root element of the document, or NULL if the document is empty.
     1178 * Const variant.
    10201179 * @return
    10211180 */
    10221181const ElementNode* Document::getRootElement() const
     1182{
     1183    return m->pRootElement;
     1184}
     1185
     1186/**
     1187 * Returns the root element of the document, or NULL if the document is empty.
     1188 * Non-const variant.
     1189 * @return
     1190 */
     1191ElementNode* Document::getRootElement()
    10231192{
    10241193    return m->pRootElement;
     
    11511320 * @param doc out: document to be reset and filled with data according to file contents.
    11521321 */
    1153 void XmlFileParser::read(const char *pcszFilename,
     1322void XmlFileParser::read(const iprt::MiniString &strFilename,
    11541323                         Document &doc)
    11551324{
     
    11571326//     global.setExternalEntityLoader(ExternalEntityLoader);
    11581327
    1159     m->strXmlFilename = pcszFilename;
     1328    m->strXmlFilename = strFilename;
     1329    const char *pcszFilename = strFilename.c_str();
    11601330
    11611331    ReadContext context(pcszFilename);
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