- Timestamp:
- Aug 11, 2009 3:38:59 PM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 61 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r21806 r22173 474 474 HRESULT hrc = NewUniqueKey(machine, "VBoxInternal/DBGF/loadsyms", KeyStr); 475 475 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); 477 477 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); 479 479 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); 481 481 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); 483 483 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); 485 485 486 486 return FAILED(hrc); -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r21769 r22173 1267 1267 if (!strcmp(a->argv[1], "enumerate")) 1268 1268 { 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 } 1282 1282 } 1283 1283 else … … 1306 1306 if (!strcmp(a->argv[1], "enumerate")) 1307 1307 { 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 } 1323 1321 } 1324 1322 else … … 1697 1695 #endif /* !VBOX_ONLY_DOCS */ 1698 1696 1699 enum ConvertSettings1700 {1701 ConvertSettings_No = 0,1702 ConvertSettings_Yes = 1,1703 ConvertSettings_Backup = 2,1704 ConvertSettings_Ignore = 3,1705 };1706 1707 #ifndef VBOX_ONLY_DOCS1708 /**1709 * Checks if any of the settings files were auto-converted and informs the1710 * 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 do1725 {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 else1828 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 else1845 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 1858 1697 // main 1859 1698 /////////////////////////////////////////////////////////////////////////////// … … 1871 1710 int iCmdArg; 1872 1711 1873 ConvertSettings fConvertSettings = ConvertSettings_No;1874 1875 1712 /* global options */ 1876 1713 for (int i = 1; i < argc || argc <= iCmd; i++) … … 1912 1749 iCmd++; 1913 1750 } 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 }1932 1751 else 1933 1752 { … … 2013 1832 NS_GetMainEventQ(getter_AddRefs(eventQ)); 2014 1833 #endif 2015 2016 if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))2017 break;2018 1834 2019 1835 #ifdef USE_XPCOM_QUEUE -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
r21806 r22173 616 616 { 617 617 char szFilenameAbs[RTPATH_MAX] = ""; 618 int vrc = RTPathAbs(Utf8Str(src) , szFilenameAbs, sizeof(szFilenameAbs));618 int vrc = RTPathAbs(Utf8Str(src).c_str(), szFilenameAbs, sizeof(szFilenameAbs)); 619 619 if (RT_FAILURE(vrc)) 620 620 { … … 650 650 { 651 651 char szFilenameAbs[RTPATH_MAX] = ""; 652 int vrc = RTPathAbs(Utf8Str(dst) , szFilenameAbs, sizeof(szFilenameAbs));652 int vrc = RTPathAbs(Utf8Str(dst).c_str(), szFilenameAbs, sizeof(szFilenameAbs)); 653 653 if (RT_FAILURE(vrc)) 654 654 { -
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r21520 r22173 771 771 } 772 772 #endif /* VBOXSDL_WITH_X11 */ 773 774 enum ConvertSettings775 {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 the784 * 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 the789 * 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 do802 {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 else905 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 else922 CHECK_ERROR (virtualBox, SaveSettings());923 }924 925 if (FAILED(rc))926 break;927 }928 }929 while (0);930 931 return SUCCEEDED (rc);932 }933 773 934 774 /** entry point */ … … 1184 1024 sysInfo->COMGETTER (NetworkAdapterCount) (&NetworkAdapterCount); 1185 1025 1186 ConvertSettings fConvertSettings = ConvertSettings_No;1187 1188 1026 // command line argument parsing stuff 1189 1027 for (int curArg = 1; curArg < argc; curArg++) … … 1602 1440 gHostKeyMod = atoi(argv[curArg]); 1603 1441 } 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;1613 1442 /* just show the help screen */ 1614 1443 else … … 1623 1452 } 1624 1453 if (FAILED (rc)) 1625 break;1626 1627 if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))1628 1454 break; 1629 1455 -
trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h
r22157 r22173 610 610 #endif 611 611 612 bool checkForSettingsAutoConversion (bool aAfterRefresh = false);613 614 bool checkForSettingsAutoConversionAfterRefresh() { return checkForSettingsAutoConversion (true); }615 616 612 CSession openSession (const QString &aId, bool aExisting = false); 617 613 -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp
r22157 r22173 2111 2111 2112 2112 /** 2113 * Checks if any of the settings files were auto-converted and informs the user2114 * 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 aExit2117 * 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> </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> </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 the2167 * 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 /**2219 2113 * Opens a direct session for a machine with the given ID. 2220 2114 * This method does user-friendly error handling (display error messages, etc.). … … 4484 4378 4485 4379 retranslateUi(); 4486 4487 /* Note: the settings conversion check must be done before anything else4488 * that may unconditionally overwrite settings files in the new format (like4489 * SetExtraData()). But after loading the proper the language. */4490 if (!checkForSettingsAutoConversion())4491 return;4492 4380 4493 4381 #ifdef VBOX_GUI_WITH_SYSTRAY -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxSelectorWnd.cpp
r21833 r22173 1115 1115 true /* aDescription */); 1116 1116 1117 if (!oldAccessible && item->accessible() && 1118 !vboxGlobal().checkForSettingsAutoConversionAfterRefresh()) 1117 if (!oldAccessible && item->accessible()) 1119 1118 fileExit(); 1120 1119 } -
trunk/src/VBox/Main/ApplianceImpl.cpp
r21878 r22173 994 994 995 995 /* 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())); 997 997 998 998 /* Next we have to download the OVF */ … … 1554 1554 VirtualSystemDescriptionEntry *vsdeHD = *itHD; 1555 1555 1556 const char *pcszDstFilePath = vsdeHD->strVbox.c_str();1557 1556 /* Check if the destination file exists already or the 1558 1557 * destination path is empty. */ 1559 if ( !(*pcszDstFilePath)1560 || RTPathExists( pcszDstFilePath)1558 if ( vsdeHD->strVbox.isEmpty() 1559 || RTPathExists(vsdeHD->strVbox.c_str()) 1561 1560 ) 1562 1561 /* This isn't allowed */ 1563 1562 throw setError(VBOX_E_FILE_ERROR, 1564 1563 tr("Destination file '%s' exists", 1565 pcszDstFilePath));1564 vsdeHD->strVbox.c_str())); 1566 1565 1567 1566 /* Find the disk from the OVF's disk list */ … … 1581 1580 1582 1581 /* Make sure all target directories exists */ 1583 rc = VirtualBox::ensureFilePathExists( pcszDstFilePath);1582 rc = VirtualBox::ensureFilePathExists(vsdeHD->strVbox.c_str()); 1584 1583 if (FAILED(rc)) 1585 1584 throw rc; … … 1598 1597 srcFormat = L"VMDK"; 1599 1598 /* Create an empty hard disk */ 1600 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr( pcszDstFilePath), dstHdVBox.asOutParam());1599 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam()); 1601 1600 if (FAILED(rc)) throw rc; 1602 1601 … … 1607 1606 /* Advance to the next operation */ 1608 1607 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()), 1610 1609 vsdeHD->ulSizeMB); // operation's weight, as set up with the IProgress originally 1611 1610 } … … 1638 1637 if (FAILED(rc)) throw rc; 1639 1638 /* 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()); 1641 1640 if (FAILED(rc)) throw rc; 1642 1641 /* Clone the source disk image */ … … 1725 1724 } 1726 1725 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)); 1728 1727 1729 1728 rc = sMachine->AttachHardDisk(hdId, … … 1882 1881 { 1883 1882 /* 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())); 1885 1884 filesList.push_back(pair<Utf8Str, ULONG>(strTmpDisk, (*itH)->ulSizeMB)); 1886 1885 } … … 1925 1924 /* Provide a OVF file (haven't to exist) so the import routine can 1926 1925 * 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())); 1928 1927 /* Now check if there is an manifest file. This is optional. */ 1929 1928 Utf8Str strManifestFile = manifestFileName(strTmpOvf); … … 2976 2975 2977 2976 /* 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())); 2979 2978 2980 2979 /* Prepare the temporary writing of the OVF */ -
trunk/src/VBox/Main/AudioAdapterImpl.cpp
r21878 r22173 361 361 * @note Locks this object for writing. 362 362 */ 363 HRESULT AudioAdapter::loadSettings (const settings::Key &aMachineNode) 364 { 365 using namespace settings; 366 367 AssertReturn(!aMachineNode.isNull(), E_FAIL); 368 363 HRESULT AudioAdapter::loadSettings(const settings::AudioAdapter &data) 364 { 369 365 AutoCaller autoCaller(this); 370 366 AssertComRCReturnRC(autoCaller.rc()); … … 383 379 * default to B. */ 384 380 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; 447 384 448 385 return S_OK; … … 456 393 * @note Locks this object for reading. 457 394 */ 458 HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode) 459 { 460 using namespace settings; 461 462 AssertReturn(!aMachineNode.isNull(), E_FAIL); 463 395 HRESULT AudioAdapter::saveSettings(settings::AudioAdapter &data) 396 { 464 397 AutoCaller autoCaller(this); 465 398 AssertComRCReturnRC(autoCaller.rc()); … … 467 400 AutoReadLock alock(this); 468 401 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; 562 405 return S_OK; 563 406 } -
trunk/src/VBox/Main/BIOSSettingsImpl.cpp
r21878 r22173 459 459 * @note Locks this object for writing. 460 460 */ 461 HRESULT BIOSSettings::loadSettings (const settings::Key &aMachineNode) 462 { 463 using namespace settings; 464 465 AssertReturn(!aMachineNode.isNull(), E_FAIL); 466 461 HRESULT BIOSSettings::loadSettings(const settings::BIOSSettings &data) 462 { 467 463 AutoCaller autoCaller(this); 468 464 AssertComRCReturnRC(autoCaller.rc()); … … 470 466 AutoWriteLock alock(this); 471 467 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; 545 480 546 481 return S_OK; … … 554 489 * @note Locks this object for reading. 555 490 */ 556 HRESULT BIOSSettings::saveSettings (settings::Key &aMachineNode) 557 { 558 using namespace settings; 559 560 AssertReturn(!aMachineNode.isNull(), E_FAIL); 561 491 HRESULT BIOSSettings::saveSettings(settings::BIOSSettings &data) 492 { 562 493 AutoCaller autoCaller(this); 563 494 AssertComRCReturnRC(autoCaller.rc()); … … 565 496 AutoReadLock alock(this); 566 497 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; 624 509 625 510 return S_OK; -
trunk/src/VBox/Main/ConsoleImpl.cpp
r21984 r22173 956 956 957 957 PSSMHANDLE ssm; 958 int vrc = SSMR3Open (Utf8Str(savedStateFile), 0, &ssm);958 int vrc = SSMR3Open(Utf8Str(savedStateFile).c_str(), 0, &ssm); 959 959 if (VBOX_SUCCESS (vrc)) 960 960 { … … 1020 1020 vrc = SSMR3PutU32 (pSSM, (uint32_t)name.length() + 1 /* term. 0 */); 1021 1021 AssertRC (vrc); 1022 vrc = SSMR3PutStrZ (pSSM, name);1022 vrc = SSMR3PutStrZ(pSSM, name.c_str()); 1023 1023 AssertRC (vrc); 1024 1024 … … 1026 1026 vrc = SSMR3PutU32 (pSSM, (uint32_t)hostPath.length() + 1 /* term. 0 */); 1027 1027 AssertRC (vrc); 1028 vrc = SSMR3PutStrZ (pSSM, hostPath );1028 vrc = SSMR3PutStrZ (pSSM, hostPath.c_str()); 1029 1029 AssertRC (vrc); 1030 1030 … … 1846 1846 Utf8Str dir = stateFilePath; 1847 1847 dir.stripFilename(); 1848 if (!RTDirExists(dir ))1848 if (!RTDirExists(dir.c_str())) 1849 1849 { 1850 int vrc = RTDirCreateFullPath (dir, 0777);1850 int vrc = RTDirCreateFullPath(dir.c_str(), 0777); 1851 1851 if (VBOX_FAILURE (vrc)) 1852 1852 { … … 3322 3322 (unsigned) ulInstance, 0, &pBase); 3323 3323 ComAssertRC (vrc); 3324 if (VBOX_SUCCESS 3324 if (VBOX_SUCCESS(vrc)) 3325 3325 { 3326 3326 Assert(pBase); … … 3334 3334 fCableConnected ? PDMNETWORKLINKSTATE_UP 3335 3335 : PDMNETWORKLINKSTATE_DOWN); 3336 ComAssertRC 3336 ComAssertRC(vrc); 3337 3337 } 3338 3338 } … … 4507 4507 /* make sure the Logs folder exists */ 4508 4508 Assert(logDir.length()); 4509 if (!RTDirExists (logDir))4510 RTDirCreateFullPath (logDir, 0777);4511 4512 Utf8Str logFile = Utf8StrFmt 4513 4514 Utf8Str pngFile = Utf8StrFmt 4515 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); 4516 4516 4517 4517 /* … … 4548 4548 * exists) to provide correct rotation even if the sequence is 4549 4549 * broken */ 4550 if ( RTFileRename (oldName, newName, RTFILEMOVE_FLAGS_REPLACE)4550 if ( RTFileRename(oldName.c_str(), newName.c_str(), RTFILEMOVE_FLAGS_REPLACE) 4551 4551 == VERR_FILE_NOT_FOUND) 4552 RTFileDelete (newName);4552 RTFileDelete(newName.c_str()); 4553 4553 } 4554 4554 } … … 4726 4726 CheckComRCReturnRC(rc); 4727 4727 ComAssertRet (!!savedStateFile, E_FAIL); 4728 int vrc = SSMR3ValidateFile (Utf8Str (savedStateFile), false /* fChecksumIt */);4729 if (VBOX_FAILURE 4730 return setError 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); 4734 4734 } 4735 4735 … … 6685 6685 LogRel (("Failed to launch VRDP server (%Rrc), error message: '%s'\n", 6686 6686 vrc, errMsg.raw())); 6687 throw setError (E_FAIL, errMsg);6687 throw setError(E_FAIL, errMsg.c_str()); 6688 6688 } 6689 6689 … … 6785 6785 task->mSavedStateFile.raw())); 6786 6786 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())); 6790 6791 6791 6792 if (VBOX_SUCCESS (vrc)) … … 6878 6879 /* Set the error message as the COM error. 6879 6880 * Progress::notifyComplete() will pick it up later. */ 6880 throw setError (E_FAIL, task->mErrorMsg);6881 throw setError(E_FAIL, task->mErrorMsg.c_str()); 6881 6882 } 6882 6883 } … … 7094 7095 hrc = hardDisk->COMGETTER(Location)(bstr.asOutParam()); H(); 7095 7096 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(); 7097 7098 hrc = hardDisk->COMGETTER(Format)(bstr.asOutParam()); H(); 7098 7099 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(); 7100 7101 7101 7102 /* Pass all custom parameters. */ … … 7115 7116 if (values [i]) 7116 7117 { 7117 Utf8Str name = names 7118 Utf8Str value = values 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()); 7120 7121 if ( !(name.compare("HostIPStack")) 7121 7122 && !(value.compare("0"))) … … 7136 7137 rc = CFGMR3InsertNode(pParent, "Parent", &pCur); RC_CHECK(); 7137 7138 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(); 7139 7140 7140 7141 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(); 7142 7143 7143 7144 /* Pass all custom parameters. */ … … 7158 7159 Utf8Str name = names [i]; 7159 7160 Utf8Str value = values [i]; 7160 rc = CFGMR3InsertString (pVDC, name , value);7161 rc = CFGMR3InsertString (pVDC, name.c_str(), value.c_str()); 7161 7162 if ( !(name.compare("HostIPStack")) 7162 7163 && !(value.compare("0"))) … … 7241 7242 LogFlowFunc (("Saving the state to '%s'...\n", task->mSavedStateFile.raw())); 7242 7243 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())); 7246 7248 if (VBOX_FAILURE (vrc)) 7247 7249 { … … 7370 7372 COM_IIDOF(IConsole), 7371 7373 Console::getComponentName(), 7372 errMsg );7374 errMsg.c_str()); 7373 7375 else 7374 7376 task->mProgress->notifyComplete (rc); -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r22171 r22173 227 227 rc = CFGMR3InsertInteger(pRoot, "RamHoleSize", cbRamHole); RC_CHECK(); 228 228 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(); 230 230 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK(); 231 231 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK(); … … 779 779 Bstr logoImagePath; 780 780 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(); 782 782 783 783 /* … … 1102 1102 Utf8Str name = names[ii]; 1103 1103 Utf8Str value = values[ii]; 1104 rc = CFGMR3InsertString(pVDC, name , value);1104 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); 1105 1105 if ( name.compare("HostIPStack") == 0 1106 1106 && value.compare("0") == 0) … … 1145 1145 Utf8Str name = names[ii]; 1146 1146 Utf8Str value = values[ii]; 1147 rc = CFGMR3InsertString(pVDC, name , value);1147 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); 1148 1148 if ( name.compare("HostIPStack") == 0 1149 1149 && value.compare("0") == 0) … … 1907 1907 */ 1908 1908 /** @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 1913 1935 /* 1914 * Get the next key1936 * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:") 1915 1937 */ 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 1917 1944 Bstr strExtraDataValue; 1918 if ( fGlobalExtraData)1919 hrc = virtualBox->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),1920 1945 if (i < cGlobalValues) 1946 // this is still one of the global values: 1947 hrc = virtualBox->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam()); 1921 1948 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)); 1947 1952 1948 1953 /* … … 1952 1957 */ 1953 1958 PCFGMNODE pNode; 1954 c har *pszCFGMValueName = strrchr(pszExtraDataKey, '/');1959 const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/'); 1955 1960 if (pszCFGMValueName) 1956 1961 { 1957 1962 /* terminate the node and advance to the value (Utf8Str might not 1958 1963 offically like this but wtf) */ 1959 * pszCFGMValueName = '\0';1964 *(char*)pszCFGMValueName = '\0'; 1960 1965 pszCFGMValueName++; 1961 1966 -
trunk/src/VBox/Main/DHCPServerImpl.cpp
r21878 r22173 86 86 } 87 87 88 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, const settings::Key &aNode) 89 { 90 using namespace settings; 91 88 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, 89 const settings::DHCPServer &data) 90 { 92 91 /* Enclose the state transition NotReady->InInit->Ready */ 93 92 AutoInitSpan autoInitSpan(this); … … 99 98 aVirtualBox->addDependentChild (this); 100 99 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; 107 106 108 107 autoInitSpan.setSucceeded(); … … 111 110 } 112 111 113 HRESULT DHCPServer::saveSettings (settings::Key &aParentNode) 114 { 115 using namespace settings; 116 117 AssertReturn(!aParentNode.isNull(), E_FAIL); 118 112 HRESULT DHCPServer::saveSettings(settings::DHCPServer &data) 113 { 119 114 AutoCaller autoCaller(this); 120 115 CheckComRCReturnRC(autoCaller.rc()); … … 122 117 AutoReadLock alock(this); 123 118 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; 133 125 134 126 return S_OK; … … 243 235 } 244 236 245 STDMETHODIMP DHCPServer::Start 237 STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType) 246 238 { 247 239 /* Silently ignore attepmts to run disabled servers. */ -
trunk/src/VBox/Main/DVDDriveImpl.cpp
r21945 r22173 411 411 * @note Locks this object for writing. 412 412 */ 413 HRESULT DVDDrive::loadSettings (const settings::Key &aMachineNode) 414 { 415 using namespace settings; 416 417 AssertReturn(!aMachineNode.isNull(), E_FAIL); 418 413 HRESULT DVDDrive::loadSettings(const settings::DVDDrive &data) 414 { 419 415 AutoCaller autoCaller(this); 420 416 AssertComRCReturnRC(autoCaller.rc()); … … 435 431 HRESULT rc = S_OK; 436 432 437 /* DVD drive (required, contains either Image or HostDrive or nothing) */438 Key dvdDriveNode = aMachineNode.key ("DVDDrive");439 440 433 /* 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; 455 444 456 445 /* find the corresponding object */ … … 458 447 459 448 com::SafeIfaceArray<IHostDVDDrive> coll; 460 rc = host->COMGETTER(DVDDrives) 449 rc = host->COMGETTER(DVDDrives)(ComSafeArrayAsOutParam(coll)); 461 450 AssertComRC (rc); 462 451 463 452 ComPtr<IHostDVDDrive> drive; 464 rc = host->FindHostDVDDrive 453 rc = host->FindHostDVDDrive(src, drive.asOutParam()); 465 454 466 455 if (SUCCEEDED(rc)) 467 456 { 468 rc = CaptureHostDrive 457 rc = CaptureHostDrive(drive); 469 458 CheckComRCReturnRC(rc); 470 459 } … … 477 466 hostDrive.createObject(); 478 467 rc = hostDrive->init (src); 479 AssertComRC 468 AssertComRC(rc); 480 469 rc = CaptureHostDrive (hostDrive); 481 470 CheckComRCReturnRC(rc); … … 489 478 } 490 479 else 491 AssertComRC 480 AssertComRC(rc); 492 481 } 493 482 … … 502 491 * @note Locks this object for reading. 503 492 */ 504 HRESULT DVDDrive::saveSettings (settings::Key &aMachineNode) 505 { 506 using namespace settings; 507 508 AssertReturn(!aMachineNode.isNull(), E_FAIL); 509 493 HRESULT DVDDrive::saveSettings(settings::DVDDrive &data) 494 { 510 495 AutoCaller autoCaller(this); 511 496 AssertComRCReturnRC(autoCaller.rc()); … … 513 498 AutoReadLock alock(this); 514 499 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; 518 503 519 504 switch (m->state) … … 524 509 525 510 Bstr id; 526 HRESULTrc = m->image->COMGETTER(Id) (id.asOutParam());511 rc = m->image->COMGETTER(Id) (id.asOutParam()); 527 512 AssertComRC (rc); 528 513 Assert (!id.isEmpty()); 529 514 530 Key imageNode = node.createKey ("Image");531 imageNode.setValue <Guid> ("uuid", Guid(id));515 data.uuid = Guid(id); 516 data.strHostDriveSrc.setNull(); 532 517 break; 533 518 } … … 537 522 538 523 Bstr name; 539 HRESULT rc = m->hostDrive->COMGETTER(Name)(name.asOutParam());524 rc = m->hostDrive->COMGETTER(Name)(name.asOutParam()); 540 525 AssertComRC (rc); 541 526 Assert (!name.isEmpty()); 542 527 543 Key hostDriveNode = node.createKey ("HostDrive");544 hostDriveNode.setValue <Bstr> ("src", name);528 data.uuid.clear(); 529 data.strHostDriveSrc = name; 545 530 break; 546 531 } 547 532 case DriveState_NotMounted: 548 533 /* do nothing, i.e.leave the drive node empty */ 549 break; 534 data.uuid.clear(); 535 data.strHostDriveSrc.setNull(); 536 break; 550 537 default: 551 538 ComAssertMsgFailedRet (("Invalid drive state: %d", m->state), -
trunk/src/VBox/Main/FloppyDriveImpl.cpp
r21878 r22173 418 418 * @note Locks this object for writing. 419 419 */ 420 HRESULT FloppyDrive::loadSettings (const settings::Key &aMachineNode) 421 { 422 using namespace settings; 423 424 AssertReturn(!aMachineNode.isNull(), E_FAIL); 425 420 HRESULT FloppyDrive::loadSettings(const settings::FloppyDrive &data) 421 { 426 422 AutoCaller autoCaller(this); 427 423 AssertComRCReturnRC(autoCaller.rc()); … … 442 438 HRESULT rc = S_OK; 443 439 444 /* Floppy drive (required, contains either Image or HostDrive or nothing) */445 Key floppyDriveNode = aMachineNode.key ("FloppyDrive");446 447 440 /* 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()); 456 446 CheckComRCReturnRC(rc); 457 447 } 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; 462 451 463 452 /* find the corresponding object */ … … 502 491 * @note Locks this object for reading. 503 492 */ 504 HRESULT FloppyDrive::saveSettings (settings::Key &aMachineNode) 505 { 506 using namespace settings; 507 508 AssertReturn(!aMachineNode.isNull(), E_FAIL); 509 493 HRESULT FloppyDrive::saveSettings(settings::FloppyDrive &data) 494 { 510 495 AutoCaller autoCaller(this); 511 496 AssertComRCReturnRC(autoCaller.rc()); … … 513 498 AutoReadLock alock(this); 514 499 515 Key node = aMachineNode.createKey ("FloppyDrive"); 516 517 node.setValue <bool> ("enabled", !!m->enabled); 500 data.fEnabled = !!m->enabled; 518 501 519 502 switch (m->state) … … 528 511 Assert (!id.isEmpty()); 529 512 530 Key imageNode = node.createKey ("Image");531 imageNode.setValue <Guid> ("uuid", Guid(id));513 data.uuid = Guid(id); 514 data.strHostDriveSrc.setNull(); 532 515 break; 533 516 } … … 541 524 Assert (!name.isEmpty()); 542 525 543 Key hostDriveNode = node.createKey ("HostDrive");544 hostDriveNode.setValue <Bstr> ("src", name);526 data.uuid.clear(); 527 data.strHostDriveSrc = name; 545 528 break; 546 529 } 547 530 case DriveState_NotMounted: 548 531 /* do nothing, i.e.leave the drive node empty */ 549 break; 532 data.uuid.clear(); 533 data.strHostDriveSrc.setNull(); 534 break; 550 535 default: 551 536 ComAssertMsgFailedRet (("Invalid drive state: %d", m->state), -
trunk/src/VBox/Main/HardDiskImpl.cpp
r21878 r22173 22 22 */ 23 23 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 37 24 #include <iprt/param.h> 38 25 #include <iprt/path.h> … … 40 27 #include <iprt/tcp.h> 41 28 29 #include <VBox/com/array.h> 30 #include <VBox/com/SupportErrorInfo.h> 31 32 #include <VBox/err.h> 33 #include <VBox/settings.h> 34 42 35 #include <list> 43 36 #include <memory> 37 38 #include "HardDiskImpl.h" 39 #include "SystemPropertiesImpl.h" 40 #include "ProgressImpl.h" 41 42 #include "Logging.h" 44 43 45 44 //////////////////////////////////////////////////////////////////////////////// … … 878 877 { 879 878 Assert (!m.lastAccessError.isEmpty()); 880 rc = setError (E_FAIL, Utf8Str (m.lastAccessError));879 rc = setError(E_FAIL, Utf8Str(m.lastAccessError).c_str()); 881 880 } 882 881 else … … 906 905 * @note Locks VirtualBox lock for writing, treeLock() for writing. 907 906 */ 908 HRESULT HardDisk::init (VirtualBox *aVirtualBox, 909 HardDisk *aParent, 910 const settings::Key &aNode) 911 { 912 using namespace settings; 913 907 HRESULT HardDisk::init(VirtualBox *aVirtualBox, 908 HardDisk *aParent, 909 const settings::Medium &data) 910 { 914 911 AssertReturn(aVirtualBox, E_INVALIDARG); 915 912 … … 930 927 { 931 928 /* we set mParent */ 932 AutoWriteLock treeLock 929 AutoWriteLock treeLock(this->treeLock()); 933 930 934 931 mParent = aParent; … … 939 936 * as inaccessible for now */ 940 937 m.state = MediaState_Inaccessible; 941 m.lastAccessError = tr 938 m.lastAccessError = tr("Accessibility check was not yet performed"); 942 939 943 940 /* required */ 944 unconst(m.id) = aNode.value <Guid> ("uuid");941 unconst(m.id) = data.uuid; 945 942 946 943 /* optional */ 947 { 948 settings::Key descNode = aNode.findKey ("Description"); 949 if (!descNode.isNull()) 950 m.description = descNode.keyStringValue(); 951 } 944 m.description = data.strDescription; 952 945 953 946 /* 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)); 957 949 CheckComRCReturnRC(rc); 958 950 959 951 /* optional, only for diffs, default is false */ 960 952 if (aParent != NULL) 961 mm.autoReset = aNode.value <bool> ("autoReset");953 mm.autoReset = data.fAutoReset; 962 954 else 963 955 mm.autoReset = false; … … 968 960 * compatibility; we can also clean them up from the XML upon next 969 961 * 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); 976 969 } 977 970 978 971 /* required */ 979 Bstr location = aNode.stringValue ("location"); 980 rc = setLocation (location); 972 rc = setLocation(data.strLocation); 981 973 CheckComRCReturnRC(rc); 982 974 983 975 /* type is only for base hard disks */ 984 976 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; 996 978 997 979 LogFlowThisFunc(("m.locationFull='%ls', mm.format=%ls, m.id={%RTuuid}\n", … … 1006 988 1007 989 /* 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 1015 1001 CheckComRCBreakRC (rc); 1016 1002 1017 rc = mVirtualBox->registerHardDisk( hardDisk, false /* aSaveRegistry */);1003 rc = mVirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */); 1018 1004 CheckComRCBreakRC (rc); 1019 1005 } … … 1965 1951 * @note Locks this object, treeLock() and children for reading. 1966 1952 */ 1967 HRESULT HardDisk::saveSettings (settings::Key &aParentNode) 1968 { 1969 using namespace settings; 1970 1971 AssertReturn(!aParentNode.isNull(), E_FAIL); 1972 1953 HRESULT HardDisk::saveSettings(settings::Medium &data) 1954 { 1973 1955 AutoCaller autoCaller(this); 1974 1956 CheckComRCReturnRC(autoCaller.rc()); … … 1979 1961 AutoReadLock treeLock (this->treeLock()); 1980 1962 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 1988 1967 /* optional, only for diffs, default is false */ 1989 1968 if (!mParent.isNull()) 1990 diskNode.setValueOr <bool> ("autoReset", !!mm.autoReset, false); 1969 data.fAutoReset = !!mm.autoReset; 1970 else 1971 data.fAutoReset = false; 1972 1991 1973 /* 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; 1997 1975 1998 1976 /* optional properties */ 1977 data.properties.clear(); 1999 1978 for (Data::PropertyMap::const_iterator it = mm.properties.begin(); 2000 it != mm.properties.end(); ++ it) 1979 it != mm.properties.end(); 1980 ++it) 2001 1981 { 2002 1982 /* only save properties that have non-default values */ 2003 1983 if (!it->second.isNull()) 2004 1984 { 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; 2008 1988 } 2009 1989 } … … 2011 1991 /* only for base hard disks */ 2012 1992 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; 2021 1994 2022 1995 /* save all children */ 2023 1996 for (List::const_iterator it = children().begin(); 2024 1997 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); 2029 2004 } 2030 2005 … … 2044 2019 * the specified location, and -1 otherwise. 2045 2020 */ 2046 HRESULT HardDisk::compareLocationTo (const char *aLocation, int &aResult)2021 HRESULT HardDisk::compareLocationTo(const Utf8Str &strLocation, int &aResult) 2047 2022 { 2048 2023 AutoCaller autoCaller(this); … … 2057 2032 if (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File) 2058 2033 { 2059 Utf8Str location (aLocation);2034 Utf8Str location(strLocation); 2060 2035 2061 2036 /* For locations represented by files, append the default path if 2062 2037 * 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); 2072 2045 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()); 2078 2052 } 2079 2053 else 2080 aResult = locationFull.compare (aLocation);2054 aResult = locationFull.compare(strLocation); 2081 2055 2082 2056 return S_OK; … … 2097 2071 Utf8Str location (m.locationFull); 2098 2072 2099 Utf8Str name = RTPathFilename (location);2073 Utf8Str name = RTPathFilename(location.c_str()); 2100 2074 return name; 2101 2075 } … … 2362 2336 Bstr HardDisk::preferredDiffFormat() 2363 2337 { 2364 Bstr format;2365 2366 2338 AutoCaller autoCaller(this); 2367 Assert ComRCReturn (autoCaller.rc(), format);2339 AssertReturn(autoCaller.rc(), ""); 2368 2340 2369 2341 /* mm.format is const, no need to lock */ 2370 format = mm.format;2342 Bstr bstrFormat = mm.format; 2371 2343 2372 2344 /* check that our own format supports diffs */ 2373 2345 if (!(mm.formatObj->capabilities() & HardDiskFormatCapabilities_Differencing)) 2374 {2375 2346 /* 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; 2381 2350 } 2382 2351 … … 2951 2920 * @note Must be called from under this object's write lock. 2952 2921 */ 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); 2922 HRESULT HardDisk::setLocation(const Utf8Str &aLocation) 2923 { 2924 AssertReturn(!aLocation.isEmpty(), E_FAIL); 2959 2925 2960 2926 AutoCaller autoCaller(this); … … 2978 2944 Guid id; 2979 2945 2980 Utf8Str location 2946 Utf8Str location(aLocation); 2981 2947 2982 2948 if (m.state == MediaState_NotCreated) … … 2985 2951 Assert (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File); 2986 2952 2987 if (RTPathFilename (location) == NULL)2953 if (RTPathFilename(location.c_str()) == NULL) 2988 2954 { 2989 2955 /* no file name is given (either an empty string or ends with a … … 2991 2957 * this */ 2992 2958 2993 ComAssertMsgRet 2994 2995 2959 ComAssertMsgRet(!mm.formatObj->fileExtensions().empty(), 2960 ("Must be at least one extension if it is HardDiskFormatCapabilities_File\n"), 2961 E_FAIL); 2996 2962 2997 2963 Bstr ext = mm.formatObj->fileExtensions().front(); 2998 ComAssertMsgRet 2999 3000 2964 ComAssertMsgRet(!ext.isEmpty(), 2965 ("Default extension must not be empty\n"), 2966 E_FAIL); 3001 2967 3002 2968 id.create(); 3003 2969 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()); 3006 2974 } 3007 2975 } 3008 2976 3009 2977 /* 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()); 3018 2983 3019 2984 /* get the full file name */ … … 3033 2998 { 3034 2999 RTFILE file; 3035 vrc = RTFileOpen (&file, locationFull, RTFILE_O_READ);3000 vrc = RTFileOpen(&file, locationFull.c_str(), RTFILE_O_READ); 3036 3001 if (RT_SUCCESS(vrc)) 3037 3002 RTFileClose (file); … … 3039 3004 if (RT_SUCCESS(vrc)) 3040 3005 { 3041 vrc = VDGetFormat (locationFull, &backendName);3006 vrc = VDGetFormat(locationFull.c_str(), &backendName); 3042 3007 } 3043 3008 else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND) … … 3045 3010 /* assume it's not a file, restore the original location */ 3046 3011 location = locationFull = aLocation; 3047 vrc = VDGetFormat (locationFull, &backendName);3012 vrc = VDGetFormat(locationFull.c_str(), &backendName); 3048 3013 } 3049 3014 … … 3113 3078 /* get the format object first */ 3114 3079 { 3115 AutoReadLock propsLock 3080 AutoReadLock propsLock(mVirtualBox->systemProperties()); 3116 3081 3117 3082 unconst(mm.formatObj) … … 3253 3218 * images can be opened as base images. Should be fixed ASAP. */ 3254 3219 vrc = VDOpen(hdd, 3255 Utf8Str(mm.format) ,3256 location ,3220 Utf8Str(mm.format).c_str(), 3221 location.c_str(), 3257 3222 flags, 3258 3223 mm.vdDiskIfaces); … … 3304 3269 { 3305 3270 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')"), 3307 3272 &uuid, m.locationFull.raw(), m.id.raw(), 3308 mVirtualBox->settingsFile Name().raw());3273 mVirtualBox->settingsFilePath().raw()); 3309 3274 throw S_OK; 3310 3275 } … … 3354 3319 { 3355 3320 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')"), 3357 3322 &parentId, m.locationFull.raw(), 3358 mVirtualBox->settingsFile Name().raw());3323 mVirtualBox->settingsFilePath().raw()); 3359 3324 throw S_OK; 3360 3325 } … … 3383 3348 { 3384 3349 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')"), 3386 3351 m.locationFull.raw(), 3387 mVirtualBox->settingsFile Name().raw());3352 mVirtualBox->settingsFilePath().raw()); 3388 3353 throw S_OK; 3389 3354 } … … 3394 3359 { 3395 3360 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')"), 3397 3362 &parentId, m.locationFull.raw(), 3398 3363 mParent->id().raw(), 3399 mVirtualBox->settingsFile Name().raw());3364 mVirtualBox->settingsFilePath().raw()); 3400 3365 throw S_OK; 3401 3366 } … … 3678 3643 3679 3644 /* static */ 3680 DECLCALLBACK(int) HardDisk::vdConfigQuery 3681 3645 DECLCALLBACK(int) HardDisk::vdConfigQuery(void *pvUser, const char *pszName, 3646 char *pszValue, size_t cchValue) 3682 3647 { 3683 3648 AssertReturn(VALID_PTR (pszValue), VERR_INVALID_POINTER); … … 3699 3664 return VERR_CFGM_VALUE_NOT_FOUND; 3700 3665 3701 memcpy (pszValue, value, value.length() + 1);3666 memcpy(pszValue, value.c_str(), value.length() + 1); 3702 3667 3703 3668 return VINF_SUCCESS; … … 3773 3738 { 3774 3739 /* ensure the directory exists */ 3775 rc = VirtualBox::ensureFilePathExists (location);3740 rc = VirtualBox::ensureFilePathExists(location.c_str()); 3776 3741 CheckComRCThrowRC (rc); 3777 3742 … … 3781 3746 that->mm.vdProgress = task->progress; 3782 3747 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); 3789 3760 3790 3761 if (RT_FAILURE(vrc)) … … 3883 3854 try 3884 3855 { 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); 3888 3861 if (RT_FAILURE(vrc)) 3889 3862 { 3890 throw setError 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()); 3893 3866 } 3894 3867 … … 3902 3875 /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to 3903 3876 * 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); 3911 3887 3912 3888 that->mm.vdProgress = NULL; … … 4057 4033 /* open the first image with VDOPEN_FLAGS_INFO because 4058 4034 * 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() ? 4062 4039 VD_OPEN_FLAGS_INFO : 0, 4063 4040 (*it)->mm.vdDiskIfaces); 4064 4041 if (RT_FAILURE(vrc)) 4065 4042 throw vrc; … … 4109 4086 { 4110 4087 /* 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); 4115 4093 if (RT_FAILURE(vrc)) 4116 4094 throw vrc; … … 4349 4327 4350 4328 /** 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); 4355 4334 if (RT_FAILURE(vrc)) 4356 4335 { … … 4395 4374 4396 4375 /* 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); 4401 4381 if (RT_FAILURE(vrc)) 4402 4382 { … … 4408 4388 } 4409 4389 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); 4417 4399 4418 4400 that->mm.vdProgress = NULL; … … 4533 4515 try 4534 4516 { 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); 4538 4522 if (RT_SUCCESS(vrc)) 4539 4523 vrc = VDClose (hdd, true /* fDelete */); … … 4601 4585 { 4602 4586 /* 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); 4606 4592 if (RT_SUCCESS(vrc)) 4607 4593 vrc = VDClose (hdd, true /* fDelete */); … … 4615 4601 4616 4602 /* 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); 4620 4608 if (RT_FAILURE(vrc)) 4621 4609 { … … 4628 4616 that->mm.vdProgress = task->progress; 4629 4617 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); 4638 4629 4639 4630 that->mm.vdProgress = NULL; … … 4705 4696 4706 4697 /** 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); 4711 4703 if (RT_FAILURE(vrc)) 4712 4704 { -
trunk/src/VBox/Main/HostImpl.cpp
r21885 r22173 1345 1345 //////////////////////////////////////////////////////////////////////////////// 1346 1346 1347 HRESULT Host::loadSettings (const settings::Key &aGlobal) 1348 { 1349 using namespace settings; 1350 1347 HRESULT Host::loadSettings(const settings::Host &data) 1348 { 1351 1349 AutoCaller autoCaller(this); 1352 1350 CheckComRCReturnRC(autoCaller.rc()); … … 1354 1352 AutoWriteLock alock(this); 1355 1353 1356 AssertReturn(!aGlobal.isNull(), E_FAIL);1357 1358 1354 HRESULT rc = S_OK; 1359 1355 1360 1356 #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); 1394 1365 CheckComRCBreakRC (rc); 1395 1366 1396 mUSBDeviceFilters.push_back (filterObj);1397 filterObj->mInList = true;1367 mUSBDeviceFilters.push_back(pFilter); 1368 pFilter->mInList = true; 1398 1369 1399 1370 /* 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); 1404 1375 } 1405 1376 } … … 1409 1380 } 1410 1381 1411 HRESULT Host::saveSettings (settings::Key &aGlobal) 1412 { 1413 using namespace settings; 1414 1382 HRESULT Host::saveSettings(settings::Host &data) 1383 { 1415 1384 AutoCaller autoCaller(this); 1416 1385 CheckComRCReturnRC(autoCaller.rc()); … … 1418 1387 AutoWriteLock alock(this); 1419 1388 1420 ComAssertRet (!aGlobal.isNull(), E_FAIL);1421 1422 1389 #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); 1482 1400 } 1483 1401 #endif /* VBOX_WITH_USB */ -
trunk/src/VBox/Main/MachineImpl.cpp
r22143 r22173 43 43 #include "USBControllerImpl.h" 44 44 #include "HostImpl.h" 45 #include "SystemPropertiesImpl.h"46 45 #include "SharedFolderImpl.h" 47 46 #include "GuestOSTypeImpl.h" … … 96 95 // globals 97 96 ///////////////////////////////////////////////////////////////////////////// 98 99 /**100 * @note The template is NOT completely valid according to VBOX_XML_SCHEMA101 * (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_LINEFEED106 "<!-- Sun VirtualBox Machine Configuration -->" RTFILE_LINEFEED107 "<VirtualBox xmlns=\"" VBOX_XML_NAMESPACE "\" "108 "version=\"" VBOX_XML_VERSION_FULL "\">" RTFILE_LINEFEED109 "</VirtualBox>" RTFILE_LINEFEED110 };111 97 112 98 /** … … 258 244 while (thatIt != thatFolders.end()) 259 245 { 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) 263 250 { 264 251 thatFolders.erase (thatIt); … … 383 370 * @return Success indicator. if not S_OK, the machine object is invalid 384 371 */ 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 */) 372 HRESULT 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 */) 390 379 { 391 380 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); 396 385 AssertReturn(aMode != Init_New || (aName != NULL && *aName != '\0'), 397 386 E_INVALIDARG); … … 415 404 mData.allocate(); 416 405 406 mData->m_pMachineConfigFile = NULL; 407 417 408 /* memorize the config file name (as provided) */ 418 mData->m ConfigFile = aConfigFile;409 mData->m_strConfigFile = strConfigFile; 419 410 420 411 /* 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); 423 413 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); 429 418 430 419 if (aMode == Init_Registered) … … 435 424 * in loadSettings() */ 436 425 unconst(mData->mUuid) = *aId; 426 427 // now load the settings from XML: 437 428 rc = registeredInit(); 438 429 } 439 430 else 440 431 { 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 445 435 } 446 436 else if (aMode == Init_New) … … 448 438 /* check for the file existence */ 449 439 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 ) 452 444 { 453 rc = setError 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()); 456 448 if (RT_SUCCESS(vrc)) 457 RTFileClose 449 RTFileClose(f); 458 450 } 459 451 else 460 452 { 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); 465 460 } 461 462 // create an empty machine config 463 mData->m_pMachineConfigFile = new settings::MachineConfigFile(NULL); 466 464 } 467 465 else … … 479 477 if (aMode != Init_New) 480 478 { 481 rc = loadSettings 479 rc = loadSettings(false /* aRegistered */); 482 480 } 483 481 else … … 495 493 /* initialize the default snapshots folder 496 494 * (note: depends on the name value set above!) */ 497 rc = COMSETTER(SnapshotFolder) 498 AssertComRC 495 rc = COMSETTER(SnapshotFolder)(NULL); 496 AssertComRC(rc); 499 497 500 498 if (aOsType) … … 571 569 AssertReturn(!mData->mAccessible, E_FAIL); 572 570 573 HRESULT rc = lockConfig(); 574 575 if (SUCCEEDED(rc)) 576 rc = initDataAndChildObjects(); 571 HRESULT rc = initDataAndChildObjects(); 577 572 578 573 if (SUCCEEDED(rc)) … … 584 579 mData->mRegistered = FALSE; 585 580 586 rc = loadSettings 581 rc = loadSettings(true /* aRegistered */); 587 582 588 583 /* Restore the registered flag (even on failure) */ 589 584 mData->mRegistered = TRUE; 590 591 if (FAILED (rc))592 unlockConfig();593 585 } 594 586 … … 610 602 /* fetch the current error info */ 611 603 mData->mAccessError = com::ErrorInfo(); 612 LogWarning 613 614 604 LogWarning(("Machine {%RTuuid} is inaccessible! [%ls]\n", 605 mData->mUuid.raw(), 606 mData->mAccessError.getText().raw())); 615 607 616 608 /* rollback all changes */ … … 701 693 alock.leave(); 702 694 703 /* make sure the configuration is unlocked */704 unlockConfig();705 706 695 if (isModified()) 707 696 { … … 721 710 } 722 711 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 */ 721 HRESULT 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 */ 799 void 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 723 914 // IMachine properties 724 915 ///////////////////////////////////////////////////////////////////////////// … … 754 945 AutoReinitSpan autoReinitSpan(this); 755 946 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 } 756 955 757 956 rc = registeredInit(); … … 825 1024 826 1025 if (!*aName) 827 return setError 828 tr("Machine name cannot be empty"));1026 return setError(E_INVALIDARG, 1027 tr("Machine name cannot be empty")); 829 1028 830 1029 AutoCaller autoCaller(this); … … 951 1150 if ( hwVersion.compare ("1") != 0 952 1151 && hwVersion.compare ("2") != 0) 953 return setError 954 tr("Invalid hardware version: %ls\n"), aHWVersion);1152 return setError(E_INVALIDARG, 1153 tr("Invalid hardware version: %ls\n"), aHWVersion); 955 1154 956 1155 AutoCaller autoCaller(this); … … 986 1185 { 987 1186 /* 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); 993 1193 994 1194 AutoCaller autoCaller(this); … … 1024 1224 { 1025 1225 /* 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); 1031 1232 1032 1233 AutoCaller autoCaller(this); … … 1064 1265 if (memorySize < SchemaDefs::MinGuestVRAM || 1065 1266 memorySize > SchemaDefs::MaxGuestVRAM) 1066 return setError 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); 1069 1270 1070 1271 AutoCaller autoCaller(this); … … 1103 1304 /* check limits */ 1104 1305 if (memoryBalloonSize >= VMMDEV_MAX_MEMORY_BALLOON (mHWData->mMemorySize)) 1105 return setError 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)); 1108 1309 1109 1310 AutoCaller autoCaller(this); … … 1241 1442 /* make sure monitor count is a sensible number */ 1242 1443 if (monitorCount < 1 || monitorCount > SchemaDefs::MaxGuestMonitors) 1243 return setError 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); 1246 1447 1247 1448 AutoCaller autoCaller(this); … … 1438 1639 1439 1640 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)")); 1443 1643 1444 1644 Utf8Str snapshotFolder = aSnapshotFolder; … … 1459 1659 } 1460 1660 1461 int vrc = calculateFullPath 1661 int vrc = calculateFullPath(snapshotFolder, snapshotFolder); 1462 1662 if (RT_FAILURE(vrc)) 1463 return setError 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); 1466 1666 1467 1667 mUserData.backup(); … … 1586 1786 AutoReadLock alock(this); 1587 1787 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); 1603 1789 return S_OK; 1604 1790 } … … 1616 1802 CheckComRCReturnRC(rc); 1617 1803 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 */ 1624 1808 *aModified = TRUE; 1625 }1626 1809 else 1627 {1628 1810 *aModified = isModified(); 1629 }1630 1811 1631 1812 return S_OK; … … 1789 1970 } 1790 1971 1791 STDMETHODIMP 1792 Machine::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders)) 1972 STDMETHODIMP Machine::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders)) 1793 1973 { 1794 1974 CheckComArgOutSafeArrayPointerValid(aSharedFolders); … … 1805 1985 } 1806 1986 1807 STDMETHODIMP 1808 Machine::COMGETTER(ClipboardMode) (ClipboardMode_T *aClipboardMode) 1987 STDMETHODIMP Machine::COMGETTER(ClipboardMode) (ClipboardMode_T *aClipboardMode) 1809 1988 { 1810 1989 CheckComArgOutPointerValid(aClipboardMode); … … 1893 2072 { 1894 2073 if (aPosition < 1 || aPosition > SchemaDefs::MaxBootPosition) 1895 return setError 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); 1898 2077 1899 2078 if (aDevice == DeviceType_USB) 1900 return setError 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")); 1902 2081 1903 2082 AutoCaller autoCaller(this); … … 1918 2097 { 1919 2098 if (aPosition < 1 || aPosition > SchemaDefs::MaxBootPosition) 1920 return setError 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); 1923 2102 1924 2103 AutoCaller autoCaller(this); … … 1936 2115 LONG aDevice) 1937 2116 { 1938 LogFlowThisFunc (("aControllerName=\"%ls\" aControllerPort=%ld aDevice=%ld\n",2117 LogFlowThisFunc (("aControllerName=\"%ls\" aControllerPort=%ld aDevice=%ld\n", 1939 2118 aControllerName, aControllerPort, aDevice)); 1940 2119 … … 1993 2172 ComObjPtr<HardDisk> hd = (*it)->hardDisk(); 1994 2173 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); 1999 2177 } 2000 2178 … … 2016 2194 mHDData->mAttachments.end()) 2017 2195 { 2018 return setError 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()); 2021 2199 } 2022 2200 … … 2316 2494 2317 2495 if (it == mHDData->mAttachments.end()) 2318 return setError 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); 2321 2499 2322 2500 ComObjPtr<HardDiskAttachment> hda = *it; … … 2399 2577 AutoReadLock alock(this); 2400 2578 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 2584 STDMETHODIMP 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 */ 2611 STDMETHODIMP Machine::GetExtraData(IN_BSTR aKey, 2612 BSTR *aValue) 2613 { 2614 CheckComArgNotNull(aKey); 2517 2615 CheckComArgOutPointerValid(aValue); 2518 2616 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()); 2524 2619 2525 2620 /* start with nothing found */ 2526 2621 Bstr("").cloneTo(aValue); 2527 2622 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 */ 2639 STDMETHODIMP Machine::SetExtraData(IN_BSTR aKey, IN_BSTR aValue) 2640 { 2641 CheckComArgNotNull(aKey); 2642 2643 AutoCaller autoCaller (this); 2644 CheckComRCReturnRC (autoCaller.rc()); 2605 2645 2606 2646 Bstr val; … … 2610 2650 val = aValue; 2611 2651 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); 2701 2699 } 2702 2700 2703 2701 /* fire a notification */ 2704 if ( SUCCEEDED(rc) && changed)2705 mParent->onExtraDataChange 2706 2707 return rc;2702 if (fChanged) 2703 mParent->onExtraDataChange(mData->mUuid, aKey, aValue); 2704 2705 return S_OK; 2708 2706 } 2709 2707 … … 2714 2712 2715 2713 /* saveSettings() needs mParent lock */ 2716 AutoMultiWriteLock2 alock 2714 AutoMultiWriteLock2 alock(mParent, this); 2717 2715 2718 2716 /* when there was auto-conversion, we want to save the file even if 2719 2717 * 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); 2724 2719 CheckComRCReturnRC(rc); 2725 2720 2726 2721 /* 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); 2766 2723 2767 2724 /* save all VM data excluding snapshots */ … … 2799 2756 2800 2757 if (mData->mRegistered) 2801 return setError 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")); 2803 2760 2804 2761 /* 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()); 2809 2765 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); 2813 2770 2814 2771 /* delete the Logs folder, nothing important should be left … … 2816 2773 * some private files there that we don't want to delete) */ 2817 2774 Utf8Str logFolder; 2818 getLogFolder 2775 getLogFolder(logFolder); 2819 2776 Assert(logFolder.length()); 2820 if (RTDirExists(logFolder ))2777 if (RTDirExists(logFolder.c_str())) 2821 2778 { 2822 2779 /* Delete all VBox.log[.N] files from the Logs folder … … 2824 2781 * Console::powerUpThread()). Also, delete the VBox.png[.N] 2825 2782 * files that may have been created by the GUI. */ 2826 Utf8Str log = Utf8StrFmt 2827 RTFileDelete (log);2828 log = Utf8StrFmt 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()); 2830 2787 for (int i = 3; i >= 0; i--) 2831 2788 { 2832 log = Utf8StrFmt 2833 RTFileDelete (log);2834 log = Utf8StrFmt 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()); 2836 2793 } 2837 2794 2838 RTDirRemove (logFolder);2795 RTDirRemove(logFolder.c_str()); 2839 2796 } 2840 2797 … … 2844 2801 Utf8Str snapshotFolder(mUserData->mSnapshotFolderFull); 2845 2802 Assert(snapshotFolder.length()); 2846 if (RTDirExists(snapshotFolder ))2847 RTDirRemove(snapshotFolder );2803 if (RTDirExists(snapshotFolder.c_str())) 2804 RTDirRemove(snapshotFolder.c_str()); 2848 2805 2849 2806 /* delete the directory that contains the settings file, but only … … 2852 2809 { 2853 2810 Utf8Str settingsDir; 2854 if (isInOwnDir 2855 RTDirRemove (settingsDir);2811 if (isInOwnDir(&settingsDir)) 2812 RTDirRemove(settingsDir.c_str()); 2856 2813 } 2857 2814 } … … 2904 2861 } 2905 2862 2906 STDMETHODIMP 2907 Machine::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable) 2908 { 2909 CheckComArgNotNull (aName); 2910 CheckComArgNotNull (aHostPath); 2863 STDMETHODIMP Machine::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable) 2864 { 2865 CheckComArgNotNull(aName); 2866 CheckComArgNotNull(aHostPath); 2911 2867 2912 2868 AutoCaller autoCaller(this); … … 2921 2877 rc = findSharedFolder (aName, sharedFolder, false /* aSetError */); 2922 2878 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); 2925 2882 2926 2883 sharedFolder.createObject(); … … 2979 2936 2980 2937 if (mData->mSession.mState != SessionState_Open) 2981 return setError 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); 2984 2941 2985 2942 directControl = mData->mSession.mDirectControl; … … 3006 2963 3007 2964 if (mData->mSession.mState != SessionState_Open) 3008 return setError 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); 3011 2968 3012 2969 directControl = mData->mSession.mDirectControl; … … 3021 2978 } 3022 2979 3023 STDMETHODIMP Machine::GetGuestProperty (IN_BSTR aName, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags) 2980 STDMETHODIMP Machine::GetGuestProperty(IN_BSTR aName, 2981 BSTR *aValue, 2982 ULONG64 *aTimestamp, 2983 BSTR *aFlags) 3024 2984 { 3025 2985 #if !defined (VBOX_WITH_GUEST_PROPS) 3026 2986 ReturnComNotImplemented(); 3027 2987 #else 3028 CheckComArgNotNull 2988 CheckComArgNotNull(aName); 3029 2989 CheckComArgOutPointerValid(aValue); 3030 2990 CheckComArgOutPointerValid(aTimestamp); … … 3039 2999 HRESULT rc = E_FAIL; 3040 3000 3001 Utf8Str strName(aName); 3002 3041 3003 if (!mHWData->mPropertyServiceActive) 3042 3004 { 3043 3005 bool found = false; 3044 3006 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) 3048 3011 { 3049 3012 char szFlags[MAX_FLAGS_LEN + 1]; 3050 it-> mValue.cloneTo(aValue);3013 it->strValue.cloneTo(aValue); 3051 3014 *aTimestamp = it->mTimestamp; 3052 writeFlags 3053 Bstr 3015 writeFlags(it->mFlags, szFlags); 3016 Bstr(szFlags).cloneTo(aFlags); 3054 3017 found = true; 3055 3018 } … … 3102 3065 using namespace guestProp; 3103 3066 3104 CheckComArgNotNull 3105 CheckComArgNotNull 3067 CheckComArgNotNull(aName); 3068 CheckComArgNotNull(aValue); 3106 3069 if ((aFlags != NULL) && !VALID_PTR (aFlags)) 3107 3070 return E_INVALIDARG; … … 3148 3111 if (SUCCEEDED(rc)) 3149 3112 { 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) 3154 3117 { 3155 3118 property = *it; 3156 3119 if (it->mFlags & (RDONLYHOST)) 3157 rc = setError 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); 3160 3123 else 3161 3124 { … … 3164 3127 * get a new one. */ 3165 3128 for (it = mHWData->mGuestProperties.begin(); 3166 it->mName != aName; ++ it) 3129 it->strName != utf8Name; 3130 ++it) 3167 3131 ; 3168 3132 mHWData->mGuestProperties.erase (it); … … 3177 3141 { 3178 3142 RTTIMESPEC time; 3179 property. mValue = aValue;3180 property.mTimestamp = RTTimeSpecGetNano(RTTimeNow 3143 property.strValue = aValue; 3144 property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time)); 3181 3145 if (aFlags != NULL) 3182 3146 property.mFlags = fFlags; … … 3188 3152 RTTIMESPEC time; 3189 3153 mHWData.backup(); 3190 property. mName = aName;3191 property. mValue = aValue;3192 property.mTimestamp = RTTimeSpecGetNano(RTTimeNow 3154 property.strName = aName; 3155 property.strValue = aValue; 3156 property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time)); 3193 3157 property.mFlags = fFlags; 3194 3158 mHWData->mGuestProperties.push_back (property); … … 3234 3198 } 3235 3199 3236 STDMETHODIMP Machine:: 3237 EnumerateGuestProperties (IN_BSTR aPatterns,ComSafeArrayOut(BSTR, aNames),3238 ComSafeArrayOut(BSTR, aValues),3239 ComSafeArrayOut(ULONG64, aTimestamps),3240 ComSafeArrayOut(BSTR, aFlags))3200 STDMETHODIMP Machine::EnumerateGuestProperties(IN_BSTR aPatterns, 3201 ComSafeArrayOut(BSTR, aNames), 3202 ComSafeArrayOut(BSTR, aValues), 3203 ComSafeArrayOut(ULONG64, aTimestamps), 3204 ComSafeArrayOut(BSTR, aFlags)) 3241 3205 { 3242 3206 #if !defined (VBOX_WITH_GUEST_PROPS) … … 3259 3223 HRESULT rc = E_FAIL; 3260 3224 3225 Utf8Str strPatterns(aPatterns); 3226 3261 3227 bool matchAll = false; 3262 3228 if ((NULL == aPatterns) || (0 == aPatterns[0])) … … 3265 3231 { 3266 3232 3267 /*3268 * Look for matching patterns and build up a list.3269 */3233 /* 3234 * Look for matching patterns and build up a list. 3235 */ 3270 3236 HWData::GuestPropertyList propList; 3271 3237 for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin(); 3272 it != mHWData->mGuestProperties.end(); ++it) 3238 it != mHWData->mGuestProperties.end(); 3239 ++it) 3273 3240 if ( matchAll 3274 || RTStrSimplePatternMultiMatch (Utf8Str (aPatterns).raw(),3275 3276 Utf8Str (it->mName).raw(),3277 3241 || RTStrSimplePatternMultiMatch(strPatterns.raw(), 3242 RTSTR_MAX, 3243 it->strName.raw(), 3244 RTSTR_MAX, NULL) 3278 3245 ) 3279 propList.push_back 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 */ 3284 3251 size_t cEntries = propList.size(); 3285 3252 SafeArray<BSTR> names (cEntries); … … 3289 3256 size_t iProp = 0; 3290 3257 for (HWData::GuestPropertyList::iterator it = propList.begin(); 3291 it != propList.end(); ++it) 3258 it != propList.end(); 3259 ++it) 3292 3260 { 3293 3261 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]); 3296 3264 timestamps[iProp] = it->mTimestamp; 3297 writeFlags 3298 Bstr 3265 writeFlags(it->mFlags, szFlags); 3266 Bstr(szFlags).cloneTo(&flags[iProp]); 3299 3267 ++iProp; 3300 3268 } … … 3307 3275 else 3308 3276 { 3309 ComPtr<IInternalSessionControl> directControl = 3310 mData->mSession.mDirectControl; 3277 ComPtr<IInternalSessionControl> directControl = mData->mSession.mDirectControl; 3311 3278 3312 3279 /* just be on the safe side when calling another process */ … … 3316 3283 rc = E_FAIL; 3317 3284 else 3318 rc = directControl->EnumerateGuestProperties 3319 3320 3321 3322 3285 rc = directControl->EnumerateGuestProperties(aPatterns, 3286 ComSafeArrayOutArg(aNames), 3287 ComSafeArrayOutArg(aValues), 3288 ComSafeArrayOutArg(aTimestamps), 3289 ComSafeArrayOutArg(aFlags)); 3323 3290 } 3324 3291 return rc; … … 3326 3293 } 3327 3294 3328 STDMETHODIMP Machine:: 3329 GetHardDiskAttachmentsOfController(IN_BSTR aName, ComSafeArrayOut(IHardDiskAttachment*, aAttachments))3295 STDMETHODIMP Machine:: GetHardDiskAttachmentsOfController(IN_BSTR aName, 3296 ComSafeArrayOut(IHardDiskAttachment*, aAttachments)) 3330 3297 { 3331 3298 HDData::AttachmentList atts; … … 3340 3307 } 3341 3308 3342 STDMETHODIMP Machine:: 3343 AddStorageController(IN_BSTR aName, 3344 StorageBus_T aConnectionType, 3345 IStorageController **controller) 3309 STDMETHODIMP Machine::AddStorageController(IN_BSTR aName, 3310 StorageBus_T aConnectionType, 3311 IStorageController **controller) 3346 3312 { 3347 3313 CheckComArgStrNotEmptyOrNull(aName); … … 3385 3351 } 3386 3352 3387 STDMETHODIMP Machine:: 3388 GetStorageControllerByName(IN_BSTR aName,IStorageController **aStorageController)3353 STDMETHODIMP Machine::GetStorageControllerByName(IN_BSTR aName, 3354 IStorageController **aStorageController) 3389 3355 { 3390 3356 CheckComArgStrNotEmptyOrNull(aName); … … 3431 3397 { 3432 3398 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); 3435 3402 } 3436 3403 } … … 3460 3427 * @note locks this object for reading. 3461 3428 */ 3462 HRESULT Machine::saveRegistryEntry (settings::Key &aEntryNode) 3463 { 3464 AssertReturn(!aEntryNode.isNull(), E_FAIL); 3465 3429 HRESULT Machine::saveRegistryEntry(settings::MachineRegistryEntry &data) 3430 { 3466 3431 AutoLimitedCaller autoCaller(this); 3467 3432 AssertComRCReturnRC(autoCaller.rc()); … … 3469 3434 AutoReadLock alock(this); 3470 3435 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; 3475 3438 3476 3439 return S_OK; … … 3488 3451 * @note Locks this object for reading. 3489 3452 */ 3490 int Machine::calculateFullPath (const char *aPath, Utf8Str &aResult)3453 int Machine::calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult) 3491 3454 { 3492 3455 AutoCaller autoCaller(this); … … 3495 3458 AutoReadLock alock(this); 3496 3459 3497 AssertReturn (!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE);3498 3499 Utf8Str strSettingsDir = mData->m ConfigFileFull;3460 AssertReturn (!mData->m_strConfigFileFull.isEmpty(), VERR_GENERAL_FAILURE); 3461 3462 Utf8Str strSettingsDir = mData->m_strConfigFileFull; 3500 3463 3501 3464 strSettingsDir.stripFilename(); 3502 3465 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)); 3504 3467 if (RT_SUCCESS(vrc)) 3505 3468 aResult = folder; … … 3519 3482 * @note Locks this object for reading. 3520 3483 */ 3521 void Machine::calculateRelativePath (const char *aPath, Utf8Str &aResult)3484 void Machine::calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult) 3522 3485 { 3523 3486 AutoCaller autoCaller(this); … … 3526 3489 AutoReadLock alock(this); 3527 3490 3528 AssertReturnVoid (!mData->m ConfigFileFull.isNull());3529 3530 Utf8Str settingsDir = mData->m ConfigFileFull;3491 AssertReturnVoid (!mData->m_strConfigFileFull.isEmpty()); 3492 3493 Utf8Str settingsDir = mData->m_strConfigFileFull; 3531 3494 3532 3495 settingsDir.stripFilename(); 3533 if (RTPathStartsWith( aPath, settingsDir))3496 if (RTPathStartsWith(strPath.c_str(), settingsDir.c_str())) 3534 3497 { 3535 3498 /* when assigning, we create a separate Utf8Str instance because both … … 3538 3501 * first, and since its the same as aPath, an attempt to copy garbage 3539 3502 * will be made. */ 3540 aResult = Utf8Str( aPath+ settingsDir.length() + 1);3503 aResult = Utf8Str(strPath.c_str() + settingsDir.length() + 1); 3541 3504 } 3542 3505 } … … 3572 3535 * lock). 3573 3536 */ 3574 HRESULT Machine::openSession 3537 HRESULT Machine::openSession(IInternalSessionControl *aControl) 3575 3538 { 3576 3539 LogFlowThisFuncEnter(); … … 3584 3547 3585 3548 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()); 3588 3552 3589 3553 LogFlowThisFunc(("mSession.mState=%d\n", mData->mSession.mState)); … … 3591 3555 if (mData->mSession.mState == SessionState_Open || 3592 3556 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()); 3597 3560 3598 3561 /* may not be busy */ … … 3616 3579 3617 3580 if (mData->mSession.mPid != pid) 3618 return setError 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); 3623 3586 } 3624 3587 … … 3698 3661 3699 3662 /* The failure may occur w/o any error info (from RPC), so provide one */ 3700 if (FAILED 3701 setError 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); 3703 3666 } 3704 3667 3705 if (FAILED 3668 if (FAILED(rc)) 3706 3669 aControl->Uninitialize(); 3707 3670 } … … 3722 3685 * SessionMachine::uninit() to reap the child process later. */ 3723 3686 3724 if (FAILED 3687 if (FAILED(rc)) 3725 3688 { 3726 3689 /* Close the remote session, remove the remote control from the list … … 3773 3736 3774 3737 /* uninitialize the created session machine on failure */ 3775 if (FAILED 3738 if (FAILED(rc)) 3776 3739 sessionMachine->uninit(); 3777 3740 … … 3785 3748 * (inside the lock). 3786 3749 */ 3787 HRESULT Machine::openRemoteSession (IInternalSessionControl *aControl, 3788 IN_BSTR aType, IN_BSTR aEnvironment, 3789 Progress *aProgress) 3750 HRESULT Machine::openRemoteSession(IInternalSessionControl *aControl, 3751 IN_BSTR aType, 3752 IN_BSTR aEnvironment, 3753 Progress *aProgress) 3790 3754 { 3791 3755 LogFlowThisFuncEnter(); … … 3800 3764 3801 3765 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()); 3804 3769 3805 3770 LogFlowThisFunc(("mSession.mState=%d\n", mData->mSession.mState)); … … 3808 3773 mData->mSession.mState == SessionState_Spawning || 3809 3774 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()); 3814 3778 3815 3779 /* may not be busy */ … … 3817 3781 3818 3782 /* 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; 3825 3789 sz = RTPATH_MAX - sz; 3826 3790 … … 3837 3801 { 3838 3802 /* clone the current environment */ 3839 int vrc2 = RTEnvClone 3840 AssertRCBreakStmt 3841 3842 newEnvStr = RTStrDup (Utf8Str (aEnvironment));3843 AssertPtrBreakStmt 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); 3844 3808 3845 3809 /* put new variables to the environment … … 3876 3840 3877 3841 if (newEnvStr != NULL) 3878 RTStrFree 3842 RTStrFree(newEnvStr); 3879 3843 } 3880 3844 … … 3895 3859 Utf8Str idStr = mData->mUuid.toString(); 3896 3860 # 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 }; 3898 3862 # else 3899 3863 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 }; 3901 3865 # endif 3902 vrc = RTProcCreate (path, args, env, 0, &pid);3866 vrc = RTProcCreate(szPath, args, env, 0, &pid); 3903 3867 } 3904 3868 #else /* !VBOX_WITH_QTGUI */ … … 3918 3882 Utf8Str idStr = mData->mUuid.toString(); 3919 3883 # ifdef RT_OS_WINDOWS 3920 const char * args[] = { path, "--startvm", idStr, 0 };3884 const char * args[] = {szPath, "--startvm", idStr.c_str(), 0 }; 3921 3885 # else 3922 3886 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 }; 3924 3888 # endif 3925 vrc = RTProcCreate (path, args, env, 0, &pid);3889 vrc = RTProcCreate(szPath, args, env, 0, &pid); 3926 3890 } 3927 3891 #else /* !VBOX_WITH_VBOXSDL */ … … 3947 3911 /* Leave space for 2 args, as "headless" needs --vrdp off on non-OSE. */ 3948 3912 # 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 }; 3950 3914 # else 3951 3915 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 }; 3953 3917 # endif 3954 3918 #ifdef VBOX_WITH_VRDP … … 3965 3929 args[pos] = "--capture"; 3966 3930 } 3967 vrc = RTProcCreate (path, args, env, 0, &pid);3931 vrc = RTProcCreate(szPath, args, env, 0, &pid); 3968 3932 } 3969 3933 #else /* !VBOX_WITH_HEADLESS */ … … 4001 3965 LogFlowThisFunc(("AssignMachine (NULL) returned %08X\n", rc)); 4002 3966 4003 if (FAILED 3967 if (FAILED(rc)) 4004 3968 { 4005 3969 /* restore the session state */ 4006 3970 mData->mSession.mState = SessionState_Closed; 4007 3971 /* The failure may occur w/o any error info (from RPC), so provide one */ 4008 return setError 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); 4010 3974 } 4011 3975 … … 4083 4047 4084 4048 /* 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); 4088 4053 4089 4054 alock.enter(); … … 4094 4059 aControl->Uninitialize(); 4095 4060 4096 return setError 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()); 4099 4064 } 4100 4065 … … 4246 4211 /* the process was already unexpectedly terminated, we just need to set an 4247 4212 * 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()); 4252 4216 #else 4253 4217 … … 4257 4221 4258 4222 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()); 4263 4226 #endif 4264 4227 4265 if (FAILED 4228 if (FAILED(rc)) 4266 4229 { 4267 4230 /* Close the remote session, remove the remote control from the list … … 4351 4314 { 4352 4315 if (mData->mRegistered) 4353 return setError 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()); 4357 4320 } 4358 4321 else 4359 4322 { 4360 4323 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()); 4365 4327 4366 4328 size_t snapshotCount = 0; … … 4368 4330 snapshotCount = mData->mFirstSnapshot->getAllChildrenCount() + 1; 4369 4331 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); 4374 4335 4375 4336 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()); 4380 4340 4381 4341 if (mHDData->mAttachments.size() != 0) 4382 return setError 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()); 4386 4346 4387 4347 /* Note that we do not prevent unregistration of a DVD or Floppy image … … 4396 4356 * isConfigLocked() is FALSE then it means that no config file exists yet, 4397 4357 * so create it by calling saveSettings() too. */ 4398 if (isModified() || (aRegistered && !isConfigLocked())) 4358 if ( isModified() 4359 || (aRegistered && !mData->m_pMachineConfigFile->fileExists()) 4360 ) 4399 4361 { 4400 4362 rc = saveSettings(); … … 4465 4427 AssertFailed(); 4466 4428 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.")); 4470 4431 } 4471 4432 … … 4554 4515 mData->mMachineState > MachineState_Paused || 4555 4516 mData->mMachineState == MachineState_Saved)) 4556 return setError 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); 4559 4520 break; 4560 4521 } … … 4564 4525 (mType != IsSessionMachine || 4565 4526 mData->mMachineState > MachineState_Paused)) 4566 return setError 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); 4569 4530 break; 4570 4531 } … … 4572 4533 4573 4534 return S_OK; 4574 }4575 4576 /**4577 * Helper to initialize all associated child objects and allocate data4578 * structures.4579 *4580 * This method must be called as a part of the object's initialization procedure4581 * (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_VRDP4609 /* create an associated VRDPServer object (default is disabled) */4610 unconst(mVRDPServer).createObject();4611 mVRDPServer->init (this);4612 #endif4613 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 data4656 * structures.4657 *4658 * This method must be called as a part of the object's uninitialization4659 * 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_VRDP4728 if (mVRDPServer)4729 {4730 mVRDPServer->uninit();4731 unconst(mVRDPServer).setNull();4732 }4733 #endif4734 4735 if (mBIOSSettings)4736 {4737 mBIOSSettings->uninit();4738 unconst(mBIOSSettings).setNull();4739 }4740 4741 /* Deassociate hard disks (only when a real Machine or a SnapshotMachine4742 * instance is uninitialized; SessionMachine instances refer to real4743 * Machine hard disks). This is necessary for a clean re-initialization of4744 * the VM after successfully re-checking the accessibility state. Note4745 * that in case of normal Machine or SnapshotMachine uninitialization (as4746 * a result of unregistering or discarding the snapshot), outdated hard4747 * disk attachments will already be uninitialized and deleted, so this4748 * 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 here4770 * since it may be still in use) */4771 mHDData.free();4772 mStorageControllers.free();4773 mHWData.free();4774 mUserData.free();4775 mSSData.free();4776 4535 } 4777 4536 … … 4887 4646 4888 4647 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); 4890 4649 4891 4650 return rc; … … 4903 4662 * @note Doesn't lock any objects. 4904 4663 */ 4905 HRESULT Machine::loadSettings 4664 HRESULT Machine::loadSettings(bool aRegistered) 4906 4665 { 4907 4666 LogFlowThisFuncEnter(); … … 4915 4674 try 4916 4675 { 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); 4932 4680 4933 4681 /* If the stored UUID is not empty, it means the registered machine … … 4936 4684 if (!mData->mUuid.isEmpty()) 4937 4685 { 4938 if (mData->mUuid != id)4686 if (mData->mUuid != mData->m_pMachineConfigFile->uuid) 4939 4687 { 4940 throw setError 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()); 4946 4694 } 4947 4695 } 4948 4696 else 4949 unconst (mData->mUuid) =id;4697 unconst (mData->mUuid) = mData->m_pMachineConfigFile->uuid; 4950 4698 4951 4699 /* name (required) */ 4952 mUserData->mName = m achineNode.stringValue ("name");4700 mUserData->mName = mData->m_pMachineConfigFile->strName; 4953 4701 4954 4702 /* 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 } 5005 4729 5006 4730 /* 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); 5012 4733 5013 4734 /* 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; 5026 4738 5027 4739 /* … … 5033 4745 5034 4746 /* 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 } 5046 4759 5047 4760 /* Hardware node (required) */ 5048 rc = loadHardware (hardwareNode);5049 CheckComRCThrowRC 4761 rc = loadHardware(mData->m_pMachineConfigFile->hardwareMachine); 4762 CheckComRCThrowRC(rc); 5050 4763 5051 4764 /* Load storage controllers */ 5052 rc = loadStorageControllers (machineNode.key ("StorageControllers"), aRegistered);5053 CheckComRCThrowRC 4765 rc = loadStorageControllers(mData->m_pMachineConfigFile->storageMachine, aRegistered); 4766 CheckComRCThrowRC(rc); 5054 4767 5055 4768 /* … … 5061 4774 5062 4775 /* set the machine state to Aborted or Saved when appropriate */ 5063 if ( aborted)5064 { 5065 Assert 4776 if (mData->m_pMachineConfigFile->fAborted) 4777 { 4778 Assert(!mSSData->mStateFilePath); 5066 4779 mSSData->mStateFilePath.setNull(); 5067 4780 … … 5096 4809 * @param aParentSnapshot Parent snapshot. 5097 4810 */ 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); 4811 HRESULT 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 } 5106 4831 5107 4832 /* 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); 5142 4841 5143 4842 /* 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); 5172 4854 5173 4855 /* memorize the first snapshot if necessary */ 5174 4856 if (!mData->mFirstSnapshot) 5175 mData->mFirstSnapshot = snapshot;4857 mData->mFirstSnapshot = pSnapshot; 5176 4858 5177 4859 /* memorize the current snapshot when appropriate */ 5178 4860 if ( !mData->mCurrentSnapshot 5179 && snapshot->getId() == aCurSnapshotId4861 && pSnapshot->getId() == aCurSnapshotId 5180 4862 ) 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); 5196 4876 } 5197 4877 … … 5202 4882 * @param aNode <Hardware> node. 5203 4883 */ 5204 HRESULT Machine::loadHardware (const settings::Key &aNode) 5205 { 5206 using namespace settings; 5207 5208 AssertReturn(!aNode.isNull(), E_INVALIDARG); 4884 HRESULT Machine::loadHardware(const settings::Hardware &data) 4885 { 5209 4886 AssertReturn(mType == IsMachine || mType == IsSnapshotMachine, E_FAIL); 5210 4887 5211 4888 HRESULT rc = S_OK; 5212 4889 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; 5299 4912 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; 5313 4920 5314 4921 #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); 5318 4925 #endif 5319 4926 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 5350 4950 /* 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; 5453 4999 5454 5000 #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 5492 5013 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 */ 5496 5016 } 5497 5017 catch(std::bad_alloc &e) … … 5499 5019 return E_OUTOFMEMORY; 5500 5020 } 5501 #endif /* VBOX_WITH_GUEST_PROPS defined */ 5502 5503 AssertComRC (rc); 5021 5022 AssertComRC(rc); 5504 5023 return rc; 5505 5024 } 5506 5025 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 */ 5029 HRESULT Machine::loadStorageControllers(const settings::Storage &data, 5030 bool aRegistered, 5031 const Guid *aSnapshotId /* = NULL */) 5032 { 5033 AssertReturn (mType == IsMachine || mType == IsSnapshotMachine, E_FAIL); 5517 5034 5518 5035 HRESULT rc = S_OK; 5519 5520 Key::List children = aNode.keys ("StorageController");5521 5036 5522 5037 /* Make sure the attached hard disks don't get unregistered until we 5523 5038 * associate them with tis machine (important for VMs loaded (opened) after 5524 5039 * 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; 5570 5049 /* Try to find one with the name first. */ 5571 rc = getStorageControllerByName (controllerName, ctl, false /* aSetError */);5050 rc = getStorageControllerByName(ctlData.strName, pCtl, false /* aSetError */); 5572 5051 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); 5587 5069 5588 5070 /* 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; 5606 5079 } 5607 5080 5608 5081 /* 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); 5612 5086 } 5613 5087 … … 5624 5098 * @note Lock mParent for reading and hard disks for writing before calling. 5625 5099 */ 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) || 5100 HRESULT Machine::loadStorageDevices(StorageController *aStorageController, 5101 const settings::StorageController &data, 5102 bool aRegistered, 5103 const Guid *aSnapshotId /*= NULL*/) 5104 { 5105 AssertReturn ((mType == IsMachine && aSnapshotId == NULL) || 5634 5106 (mType == IsSnapshotMachine && aSnapshotId != NULL), E_FAIL); 5635 5107 5636 5108 HRESULT rc = S_OK; 5637 5109 5638 Key::List children = aNode.keys ("AttachedDevice"); 5639 5640 if (!aRegistered && children.size() > 0) 5641 { 5110 if (!aRegistered && data.llAttachedDevices.size() > 0) 5642 5111 /* when the machine is being loaded (opened) from a file, it cannot 5643 5112 * have hard disks attached (this should not happen normally, 5644 5113 * because we don't allow to attach hard disks to an unregistered 5645 5114 * 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; 5672 5125 5673 5126 /* 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) 5681 5134 { 5682 5135 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()); 5717 5176 } 5718 5177 5719 5178 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); 5724 5186 5725 5187 /* associate the hard disk with this machine and snapshot */ 5726 5188 if (mType == IsSnapshotMachine) 5727 rc = hd->attachTo(mData->mUuid, *aSnapshotId);5189 rc = pDisk->attachTo(mData->mUuid, *aSnapshotId); 5728 5190 else 5729 rc = hd->attachTo(mData->mUuid);5191 rc = pDisk->attachTo(mData->mUuid); 5730 5192 5731 5193 AssertComRCBreakRC (rc); … … 5735 5197 5736 5198 mHDData.backup(); 5737 mHDData->mAttachments.push_back (attachment);5199 mHDData->mAttachments.push_back(pAttachment); 5738 5200 } 5739 5201 … … 5742 5204 5743 5205 /** 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. 5832 5207 * 5833 5208 * @param aId snapshot UUID to find (empty UUID refers the first snapshot) … … 5844 5219 { 5845 5220 if (aSetError) 5846 return setError 5847 tr("This machine does not have any snapshots"));5221 return setError(E_FAIL, 5222 tr("This machine does not have any snapshots")); 5848 5223 return E_FAIL; 5849 5224 } … … 5852 5227 aSnapshot = mData->mFirstSnapshot; 5853 5228 else 5854 aSnapshot = mData->mFirstSnapshot->findChildOrSelf 5229 aSnapshot = mData->mFirstSnapshot->findChildOrSelf(aId); 5855 5230 5856 5231 if (!aSnapshot) 5857 5232 { 5858 5233 if (aSetError) 5859 return setError 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()); 5862 5237 return E_FAIL; 5863 5238 } … … 5884 5259 { 5885 5260 if (aSetError) 5886 return setError 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")); 5888 5263 return VBOX_E_OBJECT_NOT_FOUND; 5889 5264 } … … 5894 5269 { 5895 5270 if (aSetError) 5896 return setError 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); 5898 5273 return VBOX_E_OBJECT_NOT_FOUND; 5899 5274 } … … 5909 5284 * @param aSetError true to set extended error info on failure 5910 5285 */ 5911 HRESULT Machine::getStorageControllerByName( CBSTRaName,5286 HRESULT Machine::getStorageControllerByName(const Utf8Str &aName, 5912 5287 ComObjPtr<StorageController> &aStorageController, 5913 5288 bool aSetError /* = false */) 5914 5289 { 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) 5921 5295 { 5922 5296 if ((*it)->name() == aName) … … 5928 5302 5929 5303 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()); 5932 5307 return VBOX_E_OBJECT_NOT_FOUND; 5933 5308 } … … 5963 5338 * @param aNew receives |true| if a virgin settings file was created. 5964 5339 */ 5965 HRESULT Machine::prepareSaveSettings (bool &aRenamed, bool &aNew) 5340 HRESULT Machine::prepareSaveSettings(bool &aRenamed, 5341 bool &aNew) 5966 5342 { 5967 5343 /* Note: tecnhically, mParent needs to be locked only when the machine is … … 5978 5354 /* if we're ready and isConfigLocked() is FALSE then it means 5979 5355 * that no config file exists yet (we will create a virgin one) */ 5980 aNew = ! isConfigLocked();5356 aNew = !mData->m_pMachineConfigFile->fileExists(); 5981 5357 5982 5358 /* 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 ) 5986 5363 { 5987 5364 aRenamed = true; 5988 5989 if (!aNew)5990 {5991 /* unlock the old config file */5992 rc = unlockConfig();5993 CheckComRCReturnRC(rc);5994 }5995 5365 5996 5366 bool dirRenamed = false; … … 6007 5377 Utf8Str newName = mUserData->mName; 6008 5378 6009 configFile = mData->m ConfigFileFull;5379 configFile = mData->m_strConfigFileFull; 6010 5380 6011 5381 /* first, rename the directory if it matches the machine name */ … … 6013 5383 configDir.stripFilename(); 6014 5384 newConfigDir = configDir; 6015 if ( RTPathFilename(configDir) == name)5385 if (!strcmp(RTPathFilename(configDir.c_str()), name.c_str())) 6016 5386 { 6017 5387 newConfigDir.stripFilename(); … … 6027 5397 if (RT_FAILURE(vrc)) 6028 5398 { 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); 6033 5404 break; 6034 5405 } … … 6044 5415 { 6045 5416 /* 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())); 6049 5421 if (!aNew) 6050 5422 { … … 6053 5425 if (RT_FAILURE(vrc)) 6054 5426 { 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); 6059 5432 break; 6060 5433 } … … 6064 5437 6065 5438 /* update mConfigFileFull amd mConfigFile */ 6066 Bstr oldConfigFileFull = mData->mConfigFileFull;6067 Bstr oldConfigFile = mData->mConfigFile;6068 mData->m ConfigFileFull = newConfigFile;5439 Utf8Str oldConfigFileFull = mData->m_strConfigFileFull; 5440 Utf8Str oldConfigFile = mData->m_strConfigFile; 5441 mData->m_strConfigFileFull = newConfigFile; 6069 5442 /* try to get the relative path for mConfigFile */ 6070 5443 Utf8Str path = newConfigFile; 6071 5444 mParent->calculateRelativePath (path, path); 6072 mData->m ConfigFile = path;5445 mData->m_strConfigFile = path; 6073 5446 6074 5447 /* last, try to update the global settings with the new path */ 6075 5448 if (mData->mRegistered) 6076 5449 { 6077 rc = mParent->updateSettings (configDir, newConfigDir);6078 if (FAILED 5450 rc = mParent->updateSettings(configDir.c_str(), newConfigDir.c_str()); 5451 if (FAILED(rc)) 6079 5452 { 6080 5453 /* revert to old values */ 6081 mData->m ConfigFileFull = oldConfigFileFull;6082 mData->m ConfigFile = oldConfigFile;5454 mData->m_strConfigFileFull = oldConfigFileFull; 5455 mData->m_strConfigFile = oldConfigFile; 6083 5456 break; 6084 5457 } … … 6087 5460 /* update the snapshot folder */ 6088 5461 path = mUserData->mSnapshotFolderFull; 6089 if (RTPathStartsWith (path, configDir))5462 if (RTPathStartsWith(path.c_str(), configDir.c_str())) 6090 5463 { 6091 path = Utf8StrFmt 6092 5464 path = Utf8StrFmt("%s%s", newConfigDir.raw(), 5465 path.raw() + configDir.length()); 6093 5466 mUserData->mSnapshotFolderFull = path; 6094 5467 calculateRelativePath (path, path); … … 6098 5471 /* update the saved state file path */ 6099 5472 path = mSSData->mStateFilePath; 6100 if (RTPathStartsWith (path, configDir))5473 if (RTPathStartsWith(path.c_str(), configDir.c_str())) 6101 5474 { 6102 path = Utf8StrFmt 6103 5475 path = Utf8StrFmt("%s%s", newConfigDir.raw(), 5476 path.raw() + configDir.length()); 6104 5477 mSSData->mStateFilePath = path; 6105 5478 } … … 6109 5482 * and will save all snapshots in this case. */ 6110 5483 if (mData->mFirstSnapshot) 6111 mData->mFirstSnapshot->updateSavedStatePaths (configDir,6112 newConfigDir);5484 mData->mFirstSnapshot->updateSavedStatePaths(configDir.c_str(), 5485 newConfigDir.c_str()); 6113 5486 } 6114 5487 while (0); 6115 5488 6116 if (FAILED 5489 if (FAILED(rc)) 6117 5490 { 6118 5491 /* silently try to rename everything back */ 6119 5492 if (fileRenamed) 6120 RTFileRename 5493 RTFileRename(newConfigFile.raw(), configFile.raw(), 0); 6121 5494 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); 6131 5496 } 6132 5497 … … 6140 5505 6141 5506 /* ensure the settings directory exists */ 6142 Utf8Str path(mData->m ConfigFileFull);5507 Utf8Str path(mData->m_strConfigFileFull); 6143 5508 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); 6147 5512 if (RT_FAILURE(vrc)) 6148 5513 { 6149 return setError 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); 6153 5518 } 6154 5519 } 6155 5520 6156 5521 /* 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); 6167 5526 if (RT_FAILURE(vrc)) 6168 5527 { 6169 5528 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); 6175 5535 } 6176 5536 … … 6197 5557 * left unlocked: if this machine is an unregistered one. 6198 5558 */ 6199 HRESULT Machine::saveSettings 5559 HRESULT Machine::saveSettings(int aFlags /*= 0*/) 6200 5560 { 6201 5561 LogFlowThisFuncEnter(); … … 6240 5600 bool isRenamed = false; 6241 5601 bool isNew = false; 6242 rc = prepareSaveSettings 5602 rc = prepareSaveSettings(isRenamed, isNew); 6243 5603 CheckComRCReturnRC(rc); 6244 5604 6245 5605 try 6246 5606 { 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()); 6305 5618 /* try to make the file name relative to the settings file dir */ 6306 5619 Utf8Str stateFilePath = mSSData->mStateFilePath; 6307 calculateRelativePath (stateFilePath, stateFilePath); 6308 machineNode.setStringValue ("stateFile", stateFilePath); 5620 calculateRelativePath(stateFilePath, stateFilePath); 5621 5622 mData->m_pMachineConfigFile->strStateFile = stateFilePath; 6309 5623 } 6310 5624 else 6311 5625 { 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(); 6323 5632 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); 6389 5652 } 6390 5653 catch (HRESULT err) … … 6422 5685 } 6423 5686 5687 HRESULT 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 6424 5727 /** 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. 6435 5732 */ 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); 5733 HRESULT 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 */ 5893 HRESULT 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 */ 5942 HRESULT 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 */ 5978 HRESULT Machine::saveStateSettings(int aFlags) 5979 { 5980 if (aFlags == 0) 5981 return S_OK; 5982 5983 AutoCaller autoCaller (this); 5984 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 6442 5985 6443 5986 /* This object's write lock is also necessary to serialize file access … … 6445 5988 AutoWriteLock alock(this); 6446 5989 6447 AssertReturn(isConfigLocked(), E_FAIL);6448 6449 5990 HRESULT rc = S_OK; 6450 5991 5992 Assert(mData->m_pMachineConfigFile); 5993 6451 5994 try 6452 5995 { 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 snapshot6483 * in the settings file represented by \a aMachineNode.6484 *6485 * If \a aOpFlags = SaveSS_UpdateAllOp, \a aSnapshot can be NULL to indicate6486 * 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 be6488 * removed (it is so when both mCurrentSnapshot and mFirstSnapshot are NULL).6489 *6490 * \a aOp may be just SaveSS_UpdateCurrentId if only the currentSnapshot6491 * 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_AddOp6496 * or SaveSS_UpdateAttrsOp possibly combined with6497 * 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 do6524 {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 aSnapshot6537 * with the first snapshot to recreate the whole tree, otherwise6538 * break */6539 if (mData->mFirstSnapshot)6540 {6541 aSnapshot = mData->mFirstSnapshot;6542 recreateWholeTree = true;6543 }6544 else6545 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 do6564 {6565 Key snapshotsNode;6566 6567 if (!parentNode.isNull())6568 snapshotsNode = parentNode.createKey ("Snapshots");6569 else6570 snapshotsNode = aMachineNode;6571 do6572 {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 created6578 * for every normal/immutable hard disk of the VM, so we need to6579 * 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 definitely6592 * created diffs for them and associated new diffs with6593 * 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 else6625 {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 else6645 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 the6660 * 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") == 06677 && 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 else6682 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 else6693 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> nodes6738 * 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_VRDP6768 /* VRDP settings (optional) */6769 rc = mVRDPServer->saveSettings (aNode);6770 CheckComRCReturnRC(rc);6771 #endif6772 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_PROPS6895 /* Guest properties */6896 try6897 {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_iterator6948 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_iterator7029 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 aFlags7053 * (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 access7068 * (prevent concurrent reads and writes) */7069 AutoWriteLock alock(this);7070 7071 AssertReturn(isConfigLocked(), E_FAIL);7072 7073 HRESULT rc = S_OK;7074 7075 try7076 {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 7089 5996 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; 7095 5998 7096 5999 if (aFlags & SaveSTS_StateFilePath) 7097 {7098 6000 if (mSSData->mStateFilePath) 7099 6001 { 7100 6002 /* try to make the file name relative to the settings file dir */ 7101 6003 Utf8Str stateFilePath = mSSData->mStateFilePath; 7102 calculateRelativePath 7103 m achineNode.setStringValue ("stateFile", stateFilePath);6004 calculateRelativePath(stateFilePath, stateFilePath); 6005 mData->m_pMachineConfigFile->strStateFile = stateFilePath; 7104 6006 } 7105 6007 else 7106 machineNode.zapValue ("stateFile"); 7107 } 6008 mData->m_pMachineConfigFile->strStateFile.setNull(); 7108 6009 7109 6010 if (aFlags & SaveSTS_StateTimeStamp) 7110 6011 { 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); 7127 6021 } 7128 6022 catch (...) … … 7200 6094 7201 6095 rc = hd->LockRead (NULL); 7202 CheckComRCThrowRC 6096 CheckComRCThrowRC(rc); 7203 6097 7204 6098 lockedMedia.push_back (hd); … … 7232 6126 hd->root()->name().raw()), 7233 6127 1); // weight 7234 CheckComRCThrowRC 6128 CheckComRCThrowRC(rc); 7235 6129 7236 6130 mHDData->mAttachments.push_back (hda); … … 7243 6137 hd->root()->name().raw()), 7244 6138 1); // weight 7245 CheckComRCThrowRC 6139 CheckComRCThrowRC(rc); 7246 6140 7247 6141 ComObjPtr<HardDisk> diff; 7248 6142 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); 7253 6148 7254 6149 /* leave the lock before the potentially lengthy operation */ … … 7260 6155 alock.enter(); 7261 6156 7262 CheckComRCThrowRC 6157 CheckComRCThrowRC(rc); 7263 6158 7264 6159 rc = diff->attachTo (mData->mUuid); … … 7270 6165 rc = attachment->init (diff, hda->controller(), hda->port(), 7271 6166 hda->device(), true /* aImplicit */); 7272 CheckComRCThrowRC 6167 CheckComRCThrowRC(rc); 7273 6168 7274 6169 mHDData->mAttachments.push_back (attachment); … … 7286 6181 { 7287 6182 HRESULT rc2 = (*it)->UnlockRead (NULL); 7288 AssertComRC 7289 } 7290 } 7291 7292 if (FAILED 6183 AssertComRC(rc2); 6184 } 6185 } 6186 6187 if (FAILED(rc)) 7293 6188 { 7294 6189 MultiResultRef mrc (rc); … … 7336 6231 /* deassociate and mark for deletion */ 7337 6232 rc = hd->detachFrom (mData->mUuid); 7338 AssertComRC 6233 AssertComRC(rc); 7339 6234 implicitAtts.push_back (*it); 7340 6235 continue; … … 7349 6244 /* no: de-associate */ 7350 6245 rc = hd->detachFrom (mData->mUuid); 7351 AssertComRC 6246 AssertComRC(rc); 7352 6247 continue; 7353 6248 } … … 7447 6342 { 7448 6343 rc = hd->LockWrite (NULL); 7449 AssertComRC 6344 AssertComRC(rc); 7450 6345 7451 6346 mData->mSession.mLockedMedia.push_back ( … … 7460 6355 AutoWriteLock parentLock (parent); 7461 6356 rc = parent->UnlockWrite (NULL); 7462 AssertComRC 6357 AssertComRC(rc); 7463 6358 rc = parent->LockRead (NULL); 7464 AssertComRC 6359 AssertComRC(rc); 7465 6360 7466 6361 /* XXX actually we should replace the old entry in that … … 7496 6391 /* now de-associate from the current machine state */ 7497 6392 rc = hd->detachFrom (mData->mUuid); 7498 AssertComRC 6393 AssertComRC(rc); 7499 6394 7500 6395 if (aOnline) … … 7526 6421 7527 6422 /** 7528 * Helper to lock the machine configuration for write access.7529 *7530 * @return S_OK or E_FAIL and sets error info on failure7531 *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 seriously7555 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 else7561 {7562 mData->mConfigFileReadonly = TRUE;7563 }7564 }7565 else7566 {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 access7584 *7585 * @return S_OK7586 *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 /**7609 6423 * Returns true if the settings file is located in the directory named exactly 7610 6424 * as the machine. This will be true if the machine settings structure was … … 7619 6433 bool Machine::isInOwnDir(Utf8Str *aSettingsDir /* = NULL */) 7620 6434 { 7621 Utf8Str settingsDir = mData->m ConfigFileFull;6435 Utf8Str settingsDir = mData->m_strConfigFileFull; 7622 6436 settingsDir.stripFilename(); 7623 char *dirName = RTPathFilename(settingsDir );6437 char *dirName = RTPathFilename(settingsDir.c_str()); 7624 6438 7625 6439 AssertReturn(dirName, false); … … 8317 7131 if (mIPCSem < 0 && errnoSave == ENOSYS) 8318 7132 { 8319 setError 8320 tr("Cannot create IPC semaphore. Most likely your host kernel lacks "8321 8322 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")); 8323 7137 return E_FAIL; 8324 7138 } … … 8523 7337 * for the aAbnormal argument. */ 8524 7338 HRESULT rc = mUSBController->notifyProxy (false /* aInsertFilters */); 8525 AssertComRC 7339 AssertComRC(rc); 8526 7340 NOREF (rc); 8527 7341 … … 8803 7617 #ifdef VBOX_WITH_USB 8804 7618 HRESULT rc = mUSBController->notifyProxy (true /* aInsertFilters */); 8805 AssertComRC 7619 AssertComRC(rc); 8806 7620 NOREF (rc); 8807 7621 … … 8833 7647 #ifdef VBOX_WITH_USB 8834 7648 HRESULT rc = mUSBController->notifyProxy (false /* aInsertFilters */); 8835 AssertComRC 7649 AssertComRC(rc); 8836 7650 NOREF (rc); 8837 7651 … … 9021 7835 9022 7836 Utf8Str stateFilePathFull = aSavedStateFile; 9023 int vrc = calculateFullPath 7837 int vrc = calculateFullPath(stateFilePathFull, stateFilePathFull); 9024 7838 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); 9028 7843 9029 7844 mSSData->mStateFilePath = stateFilePathFull; … … 9110 7925 if (stateFilePath) 9111 7926 { 9112 HRESULT rc = VirtualBox::ensureFilePathExists (Utf8Str(stateFilePath));7927 HRESULT rc = VirtualBox::ensureFilePathExists(Utf8Str(stateFilePath)); 9113 7928 CheckComRCReturnRC(rc); 9114 7929 } … … 9277 8092 AutoWriteLock vboxLock(mParent); 9278 8093 rc = saveSettings(); 9279 CheckComRCReturnRC (rc);8094 CheckComRCReturnRC (rc); 9280 8095 vboxLock.unlock(); 9281 8096 … … 9339 8154 9340 8155 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()); 9345 8159 9346 8160 /* create a progress object. The number of operations is: 1 (preparing) + # … … 9403 8217 9404 8218 if (mData->mCurrentSnapshot.isNull()) 9405 return setError 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()); 9409 8223 9410 8224 /* create a progress object. The number of operations is: … … 9471 8285 } 9472 8286 9473 STDMETHODIMP SessionMachine:: 9474 PullGuestProperties (ComSafeArrayOut(BSTR, aNames), 9475 ComSafeArrayOut(BSTR, aValues), 9476 ComSafeArrayOut(ULONG64, aTimestamps), 9477 ComSafeArrayOut(BSTR, aFlags)) 8287 STDMETHODIMP SessionMachine::PullGuestProperties(ComSafeArrayOut(BSTR, aNames), 8288 ComSafeArrayOut(BSTR, aValues), 8289 ComSafeArrayOut(ULONG64, aTimestamps), 8290 ComSafeArrayOut(BSTR, aFlags)) 9478 8291 { 9479 8292 LogFlowThisFunc(("\n")); … … 9499 8312 unsigned i = 0; 9500 8313 for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin(); 9501 it != mHWData->mGuestProperties.end(); ++it) 8314 it != mHWData->mGuestProperties.end(); 8315 ++it) 9502 8316 { 9503 8317 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]); 9506 8320 timestamps[i] = it->mTimestamp; 9507 writeFlags 9508 Bstr 8321 writeFlags(it->mFlags, szFlags); 8322 Bstr(szFlags).cloneTo(&flags[i]); 9509 8323 ++i; 9510 8324 } … … 9520 8334 } 9521 8335 9522 STDMETHODIMP SessionMachine::PushGuestProperties 9523 9524 9525 8336 STDMETHODIMP SessionMachine::PushGuestProperties(ComSafeArrayIn (IN_BSTR, aNames), 8337 ComSafeArrayIn (IN_BSTR, aValues), 8338 ComSafeArrayIn (ULONG64, aTimestamps), 8339 ComSafeArrayIn (IN_BSTR, aFlags)) 9526 8340 { 9527 8341 LogFlowThisFunc(("\n")); … … 9578 8392 } 9579 8393 9580 STDMETHODIMP SessionMachine::PushGuestProperty (IN_BSTR aName, IN_BSTR aValue, 9581 ULONG64 aTimestamp, IN_BSTR aFlags) 8394 STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName, 8395 IN_BSTR aValue, 8396 ULONG64 aTimestamp, 8397 IN_BSTR aFlags) 9582 8398 { 9583 8399 LogFlowThisFunc(("\n")); … … 9614 8430 mHWData.backup(); 9615 8431 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) 9618 8435 { 9619 mHWData->mGuestProperties.erase 8436 mHWData->mGuestProperties.erase(iter); 9620 8437 break; 9621 8438 } … … 9628 8445 /* send a callback notification if appropriate */ 9629 8446 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) 9633 8452 ) 9634 mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags); 8453 mParent->onGuestPropertyChange(mData->mUuid, 8454 aName, 8455 aValue, 8456 aFlags); 9635 8457 } 9636 8458 catch(std::bad_alloc &e) … … 10072 8894 { 10073 8895 /* delete the saved state file (it might have been already created) */ 10074 RTFileDelete (Utf8Str (mSnapshotData.mStateFilePath));8896 RTFileDelete(Utf8Str(mSnapshotData.mStateFilePath).c_str()); 10075 8897 } 10076 8898 … … 10122 8944 mData->mFirstSnapshot = mData->mCurrentSnapshot; 10123 8945 10124 int opFlags = SaveSS_AddOp | SaveSS_CurrentId;10125 8946 if (!Global::IsOnline (mSnapshotData.mLastState)) 10126 {10127 8947 /* the machine was powered off or saved when taking a snapshot, so 10128 8948 * reset the mCurrentStateModified flag */ 10129 8949 mData->mCurrentStateModified = FALSE; 10130 opFlags |= SaveSS_CurStateModified; 10131 } 10132 10133 rc = saveSnapshotSettings (mSnapshotData.mSnapshot, opFlags); 8950 8951 rc = saveSettings(); 10134 8952 } 10135 8953 … … 10158 8976 /* delete the saved state file (it might have been already created) */ 10159 8977 if (mSnapshotData.mSnapshot->stateFilePath()) 10160 RTFileDelete (Utf8Str (mSnapshotData.mSnapshot->stateFilePath()));8978 RTFileDelete(Utf8Str(mSnapshotData.mSnapshot->stateFilePath()).c_str()); 10161 8979 10162 8980 mSnapshotData.mSnapshot->uninit(); … … 10237 9055 10238 9056 /* 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)); 10241 9062 10242 9063 alock.enter(); 10243 9064 10244 9065 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); 10248 9071 } 10249 9072 … … 10385 9208 * prerequisites */ 10386 9209 rc = hd->prepareDiscard (chain); 10387 CheckComRCThrowRC 9210 CheckComRCThrowRC(rc); 10388 9211 10389 9212 if (hd->parent().isNull() && chain != NULL) … … 10415 9238 /* adjust back references */ 10416 9239 rc2 = replaceHd->detachFrom (mData->mUuid, snapshotId); 10417 AssertComRC 9240 AssertComRC(rc2); 10418 9241 10419 9242 rc2 = hd->attachTo (mData->mUuid, snapshotId); 10420 AssertComRC 9243 AssertComRC(rc2); 10421 9244 10422 9245 /* replace the hard disk in the attachment object */ … … 10475 9298 aTask.snapshot->uninit(); 10476 9299 10477 rc = saveSnapshotSettings(parentSnapshot, 10478 SaveSS_UpdateAllOp | SaveSS_CurrentId | SaveSS_CurStateModified); 10479 CheckComRCThrowRC (rc); 9300 rc = saveAllSnapshots(); 9301 CheckComRCThrowRC(rc); 10480 9302 10481 9303 /// @todo (dmik) … … 10487 9309 1); // weight 10488 9310 10489 RTFileDelete(Utf8Str(stateFilePath) );9311 RTFileDelete(Utf8Str(stateFilePath).c_str()); 10490 9312 } 10491 9313 … … 10519 9341 { 10520 9342 rc = it->hd->discard (aTask.progress, it->chain); 10521 CheckComRCBreakRC 9343 CheckComRCBreakRC(rc); 10522 9344 10523 9345 /* prevent from calling cancelDiscard() */ … … 10527 9349 alock.enter(); 10528 9350 10529 CheckComRCThrowRC 9351 CheckComRCThrowRC(rc); 10530 9352 } 10531 9353 catch (HRESULT aRC) { rc = aRC; } 10532 9354 10533 if FAILED 9355 if FAILED(rc) 10534 9356 { 10535 9357 HRESULT rc2 = S_OK; … … 10546 9368 10547 9369 rc2 = it->replaceHd->attachTo (mData->mUuid, it->snapshotId); 10548 AssertComRC 9370 AssertComRC(rc2); 10549 9371 10550 9372 rc2 = it->hd->detachFrom (mData->mUuid, it->snapshotId); 10551 AssertComRC 9373 AssertComRC(rc2); 10552 9374 10553 9375 AutoWriteLock attLock (it->replaceHda); … … 10557 9379 } 10558 9380 10559 if (!aTask.subTask || FAILED 9381 if (!aTask.subTask || FAILED(rc)) 10560 9382 { 10561 9383 if (!aTask.subTask) … … 10647 9469 { 10648 9470 Assert (!mSSData->mStateFilePath.isEmpty()); 10649 RTFileDelete (Utf8Str (mSSData->mStateFilePath));9471 RTFileDelete(Utf8Str(mSSData->mStateFilePath).c_str()); 10650 9472 mSSData->mStateFilePath.setNull(); 10651 9473 aTask.modifyLastState (MachineState_PoweredOff); 10652 9474 rc = saveStateSettings (SaveSTS_StateFilePath); 10653 CheckComRCThrowRC 9475 CheckComRCThrowRC(rc); 10654 9476 } 10655 9477 … … 10671 9493 * a failure */ 10672 9494 rc = aTask.progress->resultCode(); 10673 Assert (FAILED 9495 Assert (FAILED(rc)); 10674 9496 errorInSubtask = true; 10675 9497 throw rc; … … 10710 9532 snapshotLock.lock(); 10711 9533 10712 CheckComRCThrowRC 9534 CheckComRCThrowRC(rc); 10713 9535 10714 9536 /* Note: on success, current (old) hard disks will be … … 10739 9561 10740 9562 /* 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); 10743 9568 10744 9569 alock.enter(); … … 10751 9576 else 10752 9577 { 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); 10756 9583 } 10757 9584 } … … 10815 9642 * was a failure */ 10816 9643 rc = aTask.progress->resultCode(); 10817 Assert (FAILED 9644 Assert (FAILED(rc)); 10818 9645 errorInSubtask = true; 10819 9646 } … … 10852 9679 * already committed machine data and deleted old diffs before 10853 9680 * discarding the current snapshot so there is no way to rollback */ 10854 HRESULT rc2 = saveSettings 9681 HRESULT rc2 = saveSettings(SaveS_ResetCurStateModified | saveFlags); 10855 9682 10856 9683 /// @todo NEWMEDIA return multiple errors … … 10964 9791 { 10965 9792 rc = hd->LockWrite (&mediaState); 10966 CheckComRCThrowRC 9793 CheckComRCThrowRC(rc); 10967 9794 10968 9795 mData->mSession.mLockedMedia.push_back ( … … 10975 9802 { 10976 9803 rc = hd->LockRead (&mediaState); 10977 CheckComRCThrowRC 9804 CheckComRCThrowRC(rc); 10978 9805 10979 9806 mData->mSession.mLockedMedia.push_back ( … … 11042 9869 MediaState_T mediaState; 11043 9870 rc = (*it)->COMGETTER(State) (&mediaState); 11044 CheckComRCThrowRC 9871 CheckComRCThrowRC(rc); 11045 9872 11046 9873 Assert (mediaState == MediaState_LockedRead || … … 11052 9879 Bstr error; 11053 9880 rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam()); 11054 CheckComRCThrowRC 9881 CheckComRCThrowRC(rc); 11055 9882 11056 9883 if (!error.isEmpty()) … … 11058 9885 Bstr loc; 11059 9886 rc = (*it)->COMGETTER(Location) (loc.asOutParam()); 11060 CheckComRCThrowRC 9887 CheckComRCThrowRC(rc); 11061 9888 11062 9889 /* collect multiple errors */ … … 11065 9892 /* be in sync with MediumBase::setStateError() */ 11066 9893 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()); 11070 9898 11071 9899 eik.fetch(); … … 11074 9902 11075 9903 eik.restore(); 11076 CheckComRCThrowRC 9904 CheckComRCThrowRC((HRESULT) mrc); 11077 9905 } 11078 9906 catch (HRESULT aRC) … … 11237 10065 { 11238 10066 Assert (!mSSData->mStateFilePath.isEmpty()); 11239 RTFileDelete (Utf8Str (mSSData->mStateFilePath));10067 RTFileDelete(Utf8Str(mSSData->mStateFilePath).c_str()); 11240 10068 } 11241 10069 mSSData->mStateFilePath.setNull(); … … 11363 10191 HRESULT SnapshotMachine::init (SessionMachine *aSessionMachine, 11364 10192 IN_GUID aSnapshotId, 11365 IN_BSTRaStateFilePath)10193 const Utf8Str &aStateFilePath) 11366 10194 { 11367 10195 LogFlowThisFuncEnter(); … … 11421 10249 { 11422 10250 rc = (*it)->hardDisk()->attachTo (mData->mUuid, mSnapshotId); 11423 AssertComRC 10251 AssertComRC(rc); 11424 10252 } 11425 10253 … … 11497 10325 * @note Doesn't lock anything. 11498 10326 */ 11499 HRESULT SnapshotMachine::init (Machine *aMachine, 11500 const settings::Key &aHWNode, 11501 const settings::Key &aHDAsNode, 11502 IN_GUID aSnapshotId, IN_BSTR aStateFilePath) 10327 HRESULT SnapshotMachine::init(Machine *aMachine, 10328 const settings::Hardware &hardware, 10329 const settings::Storage &storage, 10330 IN_GUID aSnapshotId, 10331 const Utf8Str &aStateFilePath) 11503 10332 { 11504 10333 LogFlowThisFuncEnter(); 11505 10334 LogFlowThisFunc(("mName={%ls}\n", aMachine->mUserData->mName.raw())); 11506 10335 11507 AssertReturn(aMachine && !aHWNode.isNull() && !aHDAsNode.isNull() && 11508 !Guid (aSnapshotId).isEmpty(), 11509 E_INVALIDARG); 10336 AssertReturn(aMachine && !Guid(aSnapshotId).isEmpty(), E_INVALIDARG); 11510 10337 11511 10338 /* Enclose the state transition NotReady->InInit->Ready */ … … 11580 10407 /* load hardware and harddisk settings */ 11581 10408 11582 HRESULT rc = loadHardware (aHWNode);10409 HRESULT rc = loadHardware(hardware); 11583 10410 if (SUCCEEDED(rc)) 11584 rc = loadStorageControllers (aHDAsNode, true /* aRegistered */, &mSnapshotId);10411 rc = loadStorageControllers(storage, true /* aRegistered */, &mSnapshotId); 11585 10412 11586 10413 if (SUCCEEDED(rc)) 11587 {11588 10414 /* commit all changes made during the initialization */ 11589 10415 commit(); 11590 }11591 10416 11592 10417 /* Confirm a successful initialization when it's the case */ … … 11647 10472 AutoWriteLock alock(this); 11648 10473 11649 mPeer->saveSnapshotSettings (aSnapshot, SaveSS_UpdateAttrsOp);10474 // mPeer->saveAllSnapshots(); @todo 11650 10475 11651 10476 /* inform callbacks */ -
trunk/src/VBox/Main/MediumImpl.cpp
r21878 r22173 552 552 Utf8Str path = m.locationFull; 553 553 554 if (RTPathStartsWith (path, aOldPath))554 if (RTPathStartsWith(path.c_str(), aOldPath)) 555 555 { 556 556 Utf8Str newPath = Utf8StrFmt ("%s%s", aNewPath, … … 688 688 Utf8Str location (m.locationFull); 689 689 690 Utf8Str name = RTPathFilename (location);690 Utf8Str name = RTPathFilename(location.c_str()); 691 691 return name; 692 692 } … … 700 700 * @note Must be called from under this object's write lock. 701 701 */ 702 HRESULT MediumBase::setLocation (CBSTRaLocation)702 HRESULT MediumBase::setLocation(const Utf8Str &aLocation) 703 703 { 704 704 /* get the full file name */ 705 705 Utf8Str locationFull; 706 int vrc = mVirtualBox->calculateFullPath (Utf8Str (aLocation), locationFull);706 int vrc = mVirtualBox->calculateFullPath(aLocation, locationFull); 707 707 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); 711 712 712 713 m.location = aLocation; … … 790 791 { 791 792 RTFILE file; 792 vrc = RTFileOpen (&file, Utf8Str (m.locationFull), RTFILE_O_READ);793 vrc = RTFileOpen(&file, Utf8Str(m.locationFull).c_str(), RTFILE_O_READ); 793 794 if (RT_SUCCESS(vrc)) 794 795 { … … 976 977 * newly opened media so convert this into an error */ 977 978 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()); 979 980 } 980 981 … … 995 996 * @param aImageNode Either <DVDImage> or <FloppyImage> settings node. 996 997 */ 997 HRESULT ImageMediumBase::protectedInit 998 const settings::Key &aImageNode)998 HRESULT ImageMediumBase::protectedInit(VirtualBox *aVirtualBox, 999 const settings::Medium &data) 999 1000 { 1000 1001 AssertReturn(aVirtualBox, E_INVALIDARG); … … 1018 1019 1019 1020 /* required */ 1020 unconst(m.id) = aImageNode.value <Guid> ("uuid");1021 unconst(m.id) = data.uuid; 1021 1022 /* 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; 1031 1027 1032 1028 LogFlowThisFunc(("m.locationFull='%ls', m.id={%RTuuid}\n", … … 1077 1073 * @note Locks this object for reading. 1078 1074 */ 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 } 1075 HRESULT 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(); 1101 1087 1102 1088 return S_OK; -
trunk/src/VBox/Main/NetworkAdapterImpl.cpp
r21961 r22173 897 897 * @note Locks this object for writing. 898 898 */ 899 HRESULT NetworkAdapter::loadSettings (const settings::Key &aAdapterNode) 900 { 901 using namespace settings; 902 903 AssertReturn(!aAdapterNode.isNull(), E_FAIL); 904 899 HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data) 900 { 905 901 AutoCaller autoCaller(this); 906 902 AssertComRCReturnRC(autoCaller.rc()); … … 921 917 HRESULT rc = S_OK; 922 918 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; 942 921 /* MAC address (can be null) */ 943 rc = COMSETTER(MACAddress) (Bstr (aAdapterNode.stringValue ("MACAddress")));922 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress)); 944 923 CheckComRCReturnRC(rc); 945 924 /* cable (required) */ 946 mData->mCableConnected = aAdapterNode.value <bool> ("cable");925 mData->mCableConnected = data.fCableConnected; 947 926 /* line speed (defaults to 100 Mbps) */ 948 mData->mLineSpeed = aAdapterNode.value <ULONG> ("speed");927 mData->mLineSpeed = data.ulLineSpeed; 949 928 /* 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: 997 956 #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); 1004 959 #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; 1015 968 } 1016 969 … … 1027 980 * @note Locks this object for reading. 1028 981 */ 1029 HRESULT NetworkAdapter::saveSettings (settings::Key &aAdapterNode) 1030 { 1031 using namespace settings; 1032 1033 AssertReturn(!aAdapterNode.isNull(), E_FAIL); 1034 982 HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data) 983 { 1035 984 AutoCaller autoCaller(this); 1036 985 AssertComRCReturnRC(autoCaller.rc()); … … 1038 987 AutoReadLock alock(this); 1039 988 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) 1077 1002 { 1078 1003 case NetworkAttachmentType_Null: 1079 { 1080 /* do nothing -- empty content */ 1081 break; 1082 } 1004 data.strName.setNull(); 1005 break; 1006 1083 1007 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 1091 1011 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 1098 1015 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 1105 1019 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; 1118 1022 } 1119 1023 -
trunk/src/VBox/Main/ParallelPortImpl.cpp
r21878 r22173 174 174 * @note Locks this object for writing. 175 175 */ 176 HRESULT ParallelPort::loadSettings (const settings::Key &aPortNode) 177 { 178 using namespace settings; 179 180 AssertReturn(!aPortNode.isNull(), E_FAIL); 181 176 HRESULT ParallelPort::loadSettings(const settings::ParallelPort &data) 177 { 182 178 AutoCaller autoCaller(this); 183 179 AssertComRCReturnRC(autoCaller.rc()); … … 197 193 198 194 /* enabled (required) */ 199 mData->mEnabled = aPortNode.value <bool> ("enabled");195 mData->mEnabled = data.fEnabled; 200 196 /* I/O base (required) */ 201 mData->mIOBase = aPortNode.value <ULONG> ("IOBase");197 mData->mIOBase = data.ulIOBase; 202 198 /* IRQ (required) */ 203 mData->mIRQ = aPortNode.value <ULONG> ("IRQ");199 mData->mIRQ = data.ulIRQ; 204 200 /* device path (optional, defaults to null) */ 205 Bstr path = aPortNode.stringValue ("path"); 206 201 Bstr path(data.strPath); 207 202 HRESULT rc = checkSetPath (path); 208 203 CheckComRCReturnRC(rc); … … 221 216 * @note Locks this object for reading. 222 217 */ 223 HRESULT ParallelPort::saveSettings (settings::Key &aPortNode) 224 { 225 using namespace settings; 226 227 AssertReturn(!aPortNode.isNull(), E_FAIL); 228 218 HRESULT ParallelPort::saveSettings(settings::ParallelPort &data) 219 { 229 220 AutoCaller autoCaller(this); 230 221 AssertComRCReturnRC(autoCaller.rc()); … … 232 223 AutoReadLock alock(this); 233 224 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; 241 229 242 230 return S_OK; -
trunk/src/VBox/Main/Performance.cpp
r21878 r22173 477 477 { 478 478 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>()); 480 480 } 481 481 else 482 processMetricList( std::string("*"), ComPtr<IUnknown>());482 processMetricList("*", ComPtr<IUnknown>()); 483 483 } 484 484 else … … 488 488 { 489 489 case 0: 490 processMetricList( std::string("*"), objectArray[i]);490 processMetricList("*", objectArray[i]); 491 491 break; 492 492 case 1: 493 processMetricList( std::string(com::Utf8Str(nameArray[0])), objectArray[i]);493 processMetricList(com::Utf8Str(nameArray[0]), objectArray[i]); 494 494 break; 495 495 default: 496 processMetricList( std::string(com::Utf8Str(nameArray[i])), objectArray[i]);496 processMetricList(com::Utf8Str(nameArray[i]), objectArray[i]); 497 497 break; 498 498 } … … 500 500 } 501 501 502 void Filter::processMetricList(const std::string&name, const ComPtr<IUnknown> object)503 { 504 s td::string::size_typestartPos = 0;505 506 for (s td::string::size_typepos = name.find(",");502 void Filter::processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object) 503 { 504 size_t startPos = 0; 505 506 for (size_t pos = name.find(","); 507 507 pos != std::string::npos; 508 508 pos = name.find(",", startPos)) 509 509 { 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()))); 511 511 startPos = pos + 1; 512 512 } 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()))); 514 514 } 515 515 -
trunk/src/VBox/Main/SerialPortImpl.cpp
r21878 r22173 175 175 * @note Locks this object for writing. 176 176 */ 177 HRESULT SerialPort::loadSettings (const settings::Key &aPortNode) 178 { 179 using namespace settings; 180 181 AssertReturn(!aPortNode.isNull(), E_FAIL); 182 177 HRESULT SerialPort::loadSettings(const settings::SerialPort &data) 178 { 183 179 AutoCaller autoCaller(this); 184 180 AssertComRCReturnRC(autoCaller.rc()); … … 198 194 199 195 /* enabled (required) */ 200 mData->mEnabled = aPortNode.value <bool> ("enabled");196 mData->mEnabled = data.fEnabled; 201 197 /* I/O base (required) */ 202 mData->mIOBase = aPortNode.value <ULONG> ("IOBase");198 mData->mIOBase = data.ulIOBase; 203 199 /* IRQ (required) */ 204 mData->mIRQ = aPortNode.value <ULONG> ("IRQ");200 mData->mIRQ = data.ulIRQ; 205 201 /* 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; 217 203 218 204 /* pipe/device path (optional, defaults to null) */ 219 Bstr path = aPortNode.stringValue ("path");220 HRESULT rc = checkSetPath 205 Bstr path(data.strPath); 206 HRESULT rc = checkSetPath(path); 221 207 CheckComRCReturnRC(rc); 222 208 mData->mPath = path; 223 209 224 210 /* server mode (optional, defaults to false) */ 225 mData->mServer = aPortNode.value <bool> ("server");211 mData->mServer = data.fServer; 226 212 227 213 return S_OK; … … 237 223 * @note Locks this object for reading. 238 224 */ 239 HRESULT SerialPort::saveSettings (settings::Key &aPortNode) 240 { 241 using namespace settings; 242 243 AssertReturn(!aPortNode.isNull(), E_FAIL); 244 225 HRESULT SerialPort::saveSettings(settings::SerialPort &data) 226 { 245 227 AutoCaller autoCaller(this); 246 228 AssertComRCReturnRC(autoCaller.rc()); … … 248 230 AutoReadLock alock(this); 249 231 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; 275 236 276 237 /* Always save non-null mPath and mServer to preserve the user values for 277 238 * later use. Note that 'server' is false by default in XML so we don't 278 239 * 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; 283 242 284 243 return S_OK; -
trunk/src/VBox/Main/SharedFolderImpl.cpp
r21878 r22173 207 207 /* Check whether the path is full (absolute) */ 208 208 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)); 211 213 if (RT_FAILURE(vrc)) 212 214 return setError (E_INVALIDARG, 213 215 tr ("Invalid shared folder path: '%s' (%Rrc)"), hostPath.raw(), vrc); 214 216 215 if (RTPathCompare (hostPath, hostPathFull) != 0)217 if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0) 216 218 return setError (E_INVALIDARG, 217 219 tr ("Shared folder path '%s' is not absolute"), hostPath.raw()); … … 291 293 292 294 /* 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)) 297 300 : VERR_PATH_NOT_FOUND; 298 301 if (RT_SUCCESS(vrc)) -
trunk/src/VBox/Main/SnapshotImpl.cpp
r21878 r22173 48 48 {} 49 49 50 Guid id;51 Bstr name;52 Bstr description;50 Guid uuid; 51 Utf8Str strName; 52 Utf8Str strDescription; 53 53 RTTIMESPEC timeStamp; 54 54 ComObjPtr<SnapshotMachine> pMachine; … … 84 84 HRESULT Snapshot::init(VirtualBox *aVirtualBox, 85 85 const Guid &aId, 86 IN_BSTRaName,87 IN_BSTRaDescription,88 RTTIMESPECaTimeStamp,86 const Utf8Str &aName, 87 const Utf8Str &aDescription, 88 const RTTIMESPEC &aTimeStamp, 89 89 SnapshotMachine *aMachine, 90 90 Snapshot *aParent) 91 91 { 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); 95 95 96 96 /* Enclose the state transition NotReady->InInit->Ready */ … … 105 105 mParent = aParent; 106 106 107 m-> id = aId;108 m-> name = aName;109 m-> description = aDescription;107 m->uuid = aId; 108 m->strName = aName; 109 m->strDescription = aDescription; 110 110 m->timeStamp = aTimeStamp; 111 111 m->pMachine = aMachine; … … 253 253 AutoReadLock alock(this); 254 254 255 m-> id.toUtf16().cloneTo(aId);255 m->uuid.toUtf16().cloneTo(aId); 256 256 return S_OK; 257 257 } … … 266 266 AutoReadLock alock(this); 267 267 268 m-> name.cloneTo(aName);268 m->strName.cloneTo(aName); 269 269 return S_OK; 270 270 } … … 274 274 * (see its lock requirements). 275 275 */ 276 STDMETHODIMP Snapshot::COMSETTER(Name) 276 STDMETHODIMP Snapshot::COMSETTER(Name)(IN_BSTR aName) 277 277 { 278 278 CheckComArgNotNull(aName); … … 281 281 CheckComRCReturnRC(autoCaller.rc()); 282 282 283 Utf8Str strName(aName); 284 283 285 AutoWriteLock alock(this); 284 286 285 if (m-> name != aName)286 { 287 m-> name = aName;287 if (m->strName != strName) 288 { 289 m->strName = strName; 288 290 289 291 alock.leave(); /* Important! (child->parent locks are forbidden) */ … … 304 306 AutoReadLock alock(this); 305 307 306 m-> description.cloneTo(aDescription);308 m->strDescription.cloneTo(aDescription); 307 309 return S_OK; 308 310 } … … 315 317 CheckComRCReturnRC(autoCaller.rc()); 316 318 319 Utf8Str strDescription(aDescription); 320 317 321 AutoWriteLock alock(this); 318 322 319 if (m-> description != aDescription)320 { 321 m-> description = aDescription;323 if (m->strDescription != strDescription) 324 { 325 m->strDescription = strDescription; 322 326 323 327 alock.leave(); /* Important! (child->parent locks are forbidden) */ … … 475 479 Guid Snapshot::getId() const 476 480 { 477 return m-> id;481 return m->uuid; 478 482 } 479 483 … … 483 487 * @return 484 488 */ 485 BstrSnapshot::getName() const486 { 487 return m-> name;489 const Utf8Str& Snapshot::getName() const 490 { 491 return m->strName; 488 492 } 489 493 … … 512 516 AutoReadLock alock(this); 513 517 514 if (m-> id == aId)518 if (m->uuid == aId) 515 519 child = this; 516 520 else … … 535 539 * Caller must hold the snapshots tree lock! 536 540 */ 537 ComObjPtr<Snapshot> Snapshot::findChildOrSelf( IN_BSTRaName)541 ComObjPtr<Snapshot> Snapshot::findChildOrSelf(const Utf8Str &aName) 538 542 { 539 543 ComObjPtr<Snapshot> child; 540 AssertReturn( aName, child);544 AssertReturn(!aName.isEmpty(), child); 541 545 542 546 AutoCaller autoCaller(this); 543 547 AssertComRC(autoCaller.rc()); 544 548 545 AutoReadLock alock (this);546 547 if (m-> name == aName)549 AutoReadLock alock (this); 550 551 if (m->strName == aName) 548 552 child = this; 549 553 else … … 572 576 573 577 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())); 575 579 576 580 /* state file may be NULL (for offline snapshots) */ 577 581 if ( path.length() 578 && RTPathStartsWith(path , aOldPath)582 && RTPathStartsWith(path.c_str(), aOldPath) 579 583 ) 580 584 { … … 625 629 * @return 626 630 */ 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 } 631 HRESULT 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; 655 639 656 640 if (aAttrsOnly) … … 663 647 Utf8Str strStateFilePath = stateFilePath(); 664 648 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); 685 659 686 660 alock.unlock(); 687 661 662 data.llChildSnapshots.clear(); 663 688 664 if (m->llChildren.size()) 689 665 { 690 Key snapshotsNode = aNode.createKey ("Snapshots");691 692 HRESULT rc = S_OK;693 694 666 for (SnapshotsList::const_iterator it = m->llChildren.begin(); 695 667 it != m->llChildren.end(); 696 668 ++it) 697 669 { 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); 701 675 } 702 676 } … … 713 687 * @param aAttrsOnly If true, only updatge user-changeable attrs. 714 688 */ 715 HRESULT Snapshot::saveSnapshot(settings::Key &aNode, bool aAttrsOnly) 716 { 717 AssertReturn(!aNode.isNull(), E_INVALIDARG); 718 689 HRESULT Snapshot::saveSnapshot(settings::Snapshot &data, bool aAttrsOnly) 690 { 719 691 AutoWriteLock listLock(m->pMachine->snapshotsTreeLockHandle()); 720 692 721 return saveSnapshotImpl( aNode, aAttrsOnly);722 } 723 693 return saveSnapshotImpl(data, aAttrsOnly); 694 } 695 -
trunk/src/VBox/Main/StorageControllerImpl.cpp
r21878 r22173 63 63 * @param aName Name of the storage controller. 64 64 */ 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); 65 HRESULT 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); 71 72 if ( (aStorageBus <= StorageBus_Null) 72 73 || (aStorageBus > StorageBus_SCSI)) … … 87 88 mData.allocate(); 88 89 89 mData-> mName = aName;90 mData->strName = aName; 90 91 mData->mStorageBus = aStorageBus; 91 92 … … 237 238 238 239 /* mName is constant during life time, no need to lock */ 239 mData.data()-> mName.cloneTo(aName);240 mData.data()->strName.cloneTo(aName); 240 241 241 242 return S_OK; … … 461 462 { 462 463 /* 463 * The port count is fixed to 2. 464 * The port count is fixed to 2. 464 465 */ 465 466 if (aPortCount != 2) -
trunk/src/VBox/Main/SystemPropertiesImpl.cpp
r21878 r22173 77 77 unconst(mParent) = aParent; 78 78 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); 84 84 85 85 mLogHistoryCount = 3; … … 362 362 AutoReadLock alock(this); 363 363 364 m DefaultMachineFolderFull.cloneTo(aDefaultMachineFolder);364 m_strDefaultMachineFolderFull.cloneTo(aDefaultMachineFolder); 365 365 366 366 return S_OK; … … 391 391 AutoReadLock alock(this); 392 392 393 m DefaultHardDiskFolderFull.cloneTo(aDefaultHardDiskFolder);393 m_strDefaultHardDiskFolderFull.cloneTo(aDefaultHardDiskFolder); 394 394 395 395 return S_OK; … … 437 437 AutoReadLock alock(this); 438 438 439 m DefaultHardDiskFormat.cloneTo(aDefaultHardDiskFormat);439 m_strDefaultHardDiskFormat.cloneTo(aDefaultHardDiskFormat); 440 440 441 441 return S_OK; … … 466 466 AutoReadLock alock(this); 467 467 468 m RemoteDisplayAuthLibrary.cloneTo(aRemoteDisplayAuthLibrary);468 m_strRemoteDisplayAuthLibrary.cloneTo(aRemoteDisplayAuthLibrary); 469 469 470 470 return S_OK; … … 495 495 AutoReadLock alock(this); 496 496 497 m WebServiceAuthLibrary.cloneTo(aWebServiceAuthLibrary);497 m_strWebServiceAuthLibrary.cloneTo(aWebServiceAuthLibrary); 498 498 499 499 return S_OK; … … 563 563 ///////////////////////////////////////////////////////////////////////////// 564 564 565 HRESULT SystemProperties::loadSettings (const settings::Key &aGlobal) 566 { 567 using namespace settings; 568 565 HRESULT SystemProperties::loadSettings(const settings::SystemProperties &data) 566 { 569 567 AutoCaller autoCaller(this); 570 568 CheckComRCReturnRC(autoCaller.rc()); … … 572 570 AutoWriteLock alock(this); 573 571 574 AssertReturn(!aGlobal.isNull(), E_FAIL);575 576 572 HRESULT rc = S_OK; 577 573 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); 584 575 CheckComRCReturnRC(rc); 585 576 586 bstr = properties.stringValue ("defaultHardDiskFolder"); 587 rc = setDefaultHardDiskFolder (bstr); 577 rc = setDefaultHardDiskFolder(data.strDefaultHardDiskFolder); 588 578 CheckComRCReturnRC(rc); 589 579 590 bstr = properties.stringValue ("defaultHardDiskFormat"); 591 rc = setDefaultHardDiskFormat (bstr); 580 rc = setDefaultHardDiskFormat(data.strDefaultHardDiskFormat); 592 581 CheckComRCReturnRC(rc); 593 582 594 bstr = properties.stringValue ("remoteDisplayAuthLibrary"); 595 rc = setRemoteDisplayAuthLibrary (bstr); 583 rc = setRemoteDisplayAuthLibrary(data.strRemoteDisplayAuthLibrary); 596 584 CheckComRCReturnRC(rc); 597 585 598 bstr = properties.stringValue ("webServiceAuthLibrary"); 599 rc = setWebServiceAuthLibrary (bstr); 586 rc = setWebServiceAuthLibrary(data.strWebServiceAuthLibrary); 600 587 CheckComRCReturnRC(rc); 601 588 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 594 HRESULT 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; 641 607 642 608 return S_OK; … … 678 644 ///////////////////////////////////////////////////////////////////////////// 679 645 680 HRESULT SystemProperties::setDefaultMachineFolder (CBSTR aPath) 681 { 682 Utf8Str path; 683 if (aPath && *aPath) 684 path = aPath; 685 else 646 HRESULT SystemProperties::setDefaultMachineFolder(const Utf8Str &aPath) 647 { 648 Utf8Str path(aPath); 649 if (path.isEmpty()) 686 650 path = "Machines"; 687 651 688 652 /* get the full file name */ 689 653 Utf8Str folder; 690 int vrc = mParent->calculateFullPath 654 int vrc = mParent->calculateFullPath(path, folder); 691 655 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 667 HRESULT SystemProperties::setDefaultHardDiskFolder(const Utf8Str &aPath) 668 { 669 Utf8Str path(aPath); 670 if (path.isEmpty()) 708 671 path = "HardDisks"; 709 672 710 673 /* get the full file name */ 711 674 Utf8Str folder; 712 int vrc = mParent->calculateFullPath 675 int vrc = mParent->calculateFullPath(path, folder); 713 676 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 688 HRESULT SystemProperties::setDefaultHardDiskFormat(const Utf8Str &aFormat) 689 { 690 if (!aFormat.isEmpty()) 691 m_strDefaultHardDiskFormat = aFormat; 728 692 else 729 m DefaultHardDiskFormat = "VDI";730 731 return S_OK; 732 } 733 734 HRESULT SystemProperties::setRemoteDisplayAuthLibrary (CBSTRaPath)735 { 736 if ( aPath && *aPath)737 m RemoteDisplayAuthLibrary = aPath;693 m_strDefaultHardDiskFormat = "VDI"; 694 695 return S_OK; 696 } 697 698 HRESULT SystemProperties::setRemoteDisplayAuthLibrary(const Utf8Str &aPath) 699 { 700 if (!aPath.isEmpty()) 701 m_strRemoteDisplayAuthLibrary = aPath; 738 702 else 739 m RemoteDisplayAuthLibrary = "VRDPAuth";740 741 return S_OK; 742 } 743 744 HRESULT SystemProperties::setWebServiceAuthLibrary (CBSTRaPath)745 { 746 if ( aPath && *aPath)747 m WebServiceAuthLibrary = aPath;703 m_strRemoteDisplayAuthLibrary = "VRDPAuth"; 704 705 return S_OK; 706 } 707 708 HRESULT SystemProperties::setWebServiceAuthLibrary(const Utf8Str &aPath) 709 { 710 if (!aPath.isEmpty()) 711 m_strWebServiceAuthLibrary = aPath; 748 712 else 749 m WebServiceAuthLibrary = "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 559 559 * @note Locks this object for writing. 560 560 */ 561 HRESULT USBController::loadSettings (const settings::Key &aMachineNode) 562 { 563 using namespace settings; 564 565 AssertReturn(!aMachineNode.isNull(), E_FAIL); 566 561 HRESULT USBController::loadSettings(const settings::USBController &data) 562 { 567 563 AutoCaller autoCaller(this); 568 564 AssertComRCReturnRC(autoCaller.rc()); … … 581 577 * default to B. */ 582 578 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); 621 592 CheckComRCReturnRC(rc); 622 593 623 mDeviceFilters->push_back (filterObj);624 filterObj->mInList = true;594 mDeviceFilters->push_back(pFilter); 595 pFilter->mInList = true; 625 596 } 626 597 #endif /* VBOX_WITH_USB */ … … 636 607 * @note Locks this object for reading. 637 608 */ 638 HRESULT USBController::saveSettings (settings::Key &aMachineNode) 639 { 640 using namespace settings; 641 642 AssertReturn(!aMachineNode.isNull(), E_FAIL); 643 609 HRESULT USBController::saveSettings(settings::USBController &data) 610 { 644 611 AutoCaller autoCaller(this); 645 612 CheckComRCReturnRC(autoCaller.rc()); … … 647 614 AutoReadLock alock(this); 648 615 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) 671 625 { 672 626 AutoWriteLock filterLock (*it); 673 627 const USBDeviceFilter::Data &data = (*it)->data(); 674 628 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 */681 629 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; 690 638 (*it)->COMGETTER (Revision) (str.asOutParam()); 691 if (!str.isNull()) 692 filter.setValue <Bstr> ("revision", str); 693 639 f.strRevision = str; 694 640 (*it)->COMGETTER (Manufacturer) (str.asOutParam()); 695 if (!str.isNull()) 696 filter.setValue <Bstr> ("manufacturer", str); 697 641 f.strManufacturer = str; 698 642 (*it)->COMGETTER (Product) (str.asOutParam()); 699 if (!str.isNull()) 700 filter.setValue <Bstr> ("product", str); 701 643 f.strProduct = str; 702 644 (*it)->COMGETTER (SerialNumber) (str.asOutParam()); 703 if (!str.isNull()) 704 filter.setValue <Bstr> ("serialNumber", str); 705 645 f.strSerialNumber = str; 706 646 (*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; 717 650 } 718 651 #endif /* VBOX_WITH_USB */ … … 1215 1148 ComAssertComRCRet (rc, false); 1216 1149 if (!manufacturer.isNull()) 1217 USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer) , true);1150 USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true); 1218 1151 1219 1152 Bstr product; … … 1221 1154 ComAssertComRCRet (rc, false); 1222 1155 if (!product.isNull()) 1223 USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product) , true);1156 USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true); 1224 1157 1225 1158 Bstr serialNumber; … … 1227 1160 ComAssertComRCRet (rc, false); 1228 1161 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); 1230 1163 1231 1164 Bstr address; -
trunk/src/VBox/Main/VFSExplorerImpl.cpp
r21811 r22173 421 421 { 422 422 PCRTS3KEYENTRY pKeys = NULL; 423 vrc = RTS3GetBucketKeys(hS3, m->strBucket , &pKeys);423 vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys); 424 424 if (RT_FAILURE(vrc)) 425 425 throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc); … … 623 623 for (size_t a=0; a < sfaNames.size(); ++a) 624 624 { 625 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]) ))625 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str())) 626 626 { 627 627 BSTR name; -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r21878 r22173 26 26 #include <iprt/string.h> 27 27 #include <iprt/uuid.h> 28 #include <iprt/stream.h> 28 29 #include <iprt/thread.h> 29 30 #include <iprt/process.h> … … 84 85 ///////////////////////////////////////////////////////////////////////////// 85 86 86 static const char gDefaultGlobalConfig [] =87 {88 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" RTFILE_LINEFEED89 "<!-- Sun VirtualBox Global Configuration -->" RTFILE_LINEFEED90 "<VirtualBox xmlns=\"" VBOX_XML_NAMESPACE "\" "91 "version=\"" VBOX_XML_VERSION_FULL "\">" RTFILE_LINEFEED92 " <Global>"RTFILE_LINEFEED93 " <MachineRegistry/>"RTFILE_LINEFEED94 " <MediaRegistry/>"RTFILE_LINEFEED95 " <NetserviceRegistry>"RTFILE_LINEFEED96 " <DHCPServers>"RTFILE_LINEFEED97 " <DHCPServer "98 #ifdef RT_OS_WINDOWS99 "networkName=\"HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter\" "100 #else101 "networkName=\"HostInterfaceNetworking-vboxnet0\" "102 #endif103 "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_LINEFEED106 " </DHCPServers>"RTFILE_LINEFEED107 " </NetserviceRegistry>"RTFILE_LINEFEED108 " <USBDeviceFilters/>"RTFILE_LINEFEED109 " <SystemProperties/>"RTFILE_LINEFEED110 " </Global>"RTFILE_LINEFEED111 "</VirtualBox>"RTFILE_LINEFEED112 };113 114 87 // static 115 88 Bstr VirtualBox::sVersion; … … 120 93 // static 121 94 Bstr VirtualBox::sPackageType; 122 123 // static124 Bstr VirtualBox::sSettingsFormatVersion;125 95 126 96 // constructor / destructor … … 176 146 LogFlowThisFunc(("Version: %ls, Package: %ls\n", sVersion.raw(), sPackageType.raw())); 177 147 178 if (sSettingsFormatVersion.isNull())179 sSettingsFormatVersion = VBOX_XML_VERSION_FULL;180 LogFlowThisFunc(("Settings Format Version: %ls\n",181 sSettingsFormatVersion.raw()));182 183 148 /* Get the VirtualBox home directory. */ 184 149 { 185 char homeDir 186 int vrc = com::GetVBoxUserHomeDirectory (homeDir, sizeof(homeDir));150 char homeDir[RTPATH_MAX]; 151 int vrc = com::GetVBoxUserHomeDirectory(homeDir, sizeof(homeDir)); 187 152 if (RT_FAILURE(vrc)) 188 153 return setError (E_FAIL, … … 194 159 } 195 160 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)) 222 204 { 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); 226 218 } 227 else228 {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 try238 {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_API253 /* create the performance collector object BEFORE host */254 unconst(mData.mPerformanceCollector).createObject();255 rc = mData.mPerformanceCollector->init();256 219 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); 334 254 } 335 255 … … 380 300 } 381 301 302 HRESULT 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 332 HRESULT 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 382 386 void VirtualBox::uninit() 383 387 { … … 442 446 } 443 447 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 444 445 /* unlock the config file */446 unlockConfig();447 448 448 449 LogFlowThisFunc(("Releasing callbacks...\n")); … … 575 576 576 577 /* 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); 604 579 return S_OK; 605 580 } … … 782 757 783 758 /** @note Locks mSystemProperties object for reading. */ 784 STDMETHODIMP VirtualBox::CreateMachine 785 786 787 788 759 STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aName, 760 IN_BSTR aOsTypeId, 761 IN_BSTR aBaseFolder, 762 IN_BSTR aId, 763 IMachine **aMachine) 789 764 { 790 765 LogFlowThisFuncEnter(); … … 805 780 * machine folder will be used as a base folder. 806 781 */ 807 Bstr settingsFile = aBaseFolder; 808 if (settingsFile.isEmpty()) 809 { 810 AutoReadLock propsLock (systemProperties()); 782 Utf8Str strSettingsFile = aBaseFolder; 783 if (strSettingsFile.isEmpty()) 811 784 /* 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); 817 793 818 794 HRESULT rc = E_FAIL; … … 836 812 { 837 813 for (GuestOSTypeList::const_iterator it = mData.mGuestOSTypes.begin(); 838 it != mData.mGuestOSTypes.end(); ++ it) 814 it != mData.mGuestOSTypes.end(); 815 ++ it) 839 816 { 840 817 if ((*it)->id() == aOsTypeId) … … 846 823 847 824 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); 850 828 } 851 829 852 830 /* 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); 855 838 if (SUCCEEDED(rc)) 856 839 { … … 865 848 } 866 849 867 STDMETHODIMP VirtualBox::CreateLegacyMachine 868 869 870 871 850 STDMETHODIMP VirtualBox::CreateLegacyMachine(IN_BSTR aName, 851 IN_BSTR aOsTypeId, 852 IN_BSTR aSettingsFile, 853 IN_BSTR aId, 854 IMachine **aMachine) 872 855 { 873 856 CheckComArgStrNotEmptyOrNull (aName); … … 883 866 Utf8Str settingsFile = aSettingsFile; 884 867 /* append the default extension if none */ 885 if (!RTPathHaveExt (settingsFile))886 settingsFile = Utf8StrFmt 868 if (!RTPathHaveExt(settingsFile.c_str())) 869 settingsFile = Utf8StrFmt("%s.xml", settingsFile.raw()); 887 870 888 871 /* create a new object */ … … 919 902 920 903 /* 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); 923 911 if (SUCCEEDED(rc)) 924 912 { … … 931 919 } 932 920 933 STDMETHODIMP VirtualBox::OpenMachine 934 921 STDMETHODIMP VirtualBox::OpenMachine(IN_BSTR aSettingsFile, 922 IMachine **aMachine) 935 923 { 936 924 CheckComArgStrNotEmptyOrNull(aSettingsFile); … … 948 936 { 949 937 /* initialize the machine object */ 950 rc = machine->init (this, aSettingsFile, Machine::Init_Existing); 938 rc = machine->init(this, 939 aSettingsFile, 940 Machine::Init_Import); 951 941 if (SUCCEEDED(rc)) 952 942 { … … 1119 1109 Bstr format = aFormat; 1120 1110 if (format.isEmpty()) 1121 { 1122 AutoReadLock propsLock (systemProperties()); 1123 format = systemProperties()->defaultHardDiskFormat(); 1124 } 1111 format = getDefaultHardDiskFormat(); 1125 1112 1126 1113 HRESULT rc = E_FAIL; … … 1447 1434 * @note Locks this object for reading. 1448 1435 */ 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; 1436 STDMETHODIMP 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; 1545 1460 } 1546 1461 … … 1548 1463 * @note Locks this object for reading. 1549 1464 */ 1550 STDMETHODIMP VirtualBox::GetExtraData (IN_BSTR aKey, BSTR *aValue) 1465 STDMETHODIMP VirtualBox::GetExtraData(IN_BSTR aKey, 1466 BSTR *aValue) 1551 1467 { 1552 1468 CheckComArgNotNull(aKey); … … 1559 1475 Bstr("").cloneTo(aValue); 1560 1476 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; 1606 1486 } 1607 1487 … … 1609 1489 * @note Locks this object for writing. 1610 1490 */ 1611 STDMETHODIMP VirtualBox::SetExtraData (IN_BSTR aKey, IN_BSTR aValue) 1491 STDMETHODIMP VirtualBox::SetExtraData(IN_BSTR aKey, 1492 IN_BSTR aValue) 1612 1493 { 1613 1494 CheckComArgNotNull(aKey); … … 1623 1504 val = aValue; 1624 1505 1625 bool changed = false;1626 HRESULT rc = S_OK;1506 Utf8Str strKey(aKey); 1507 Bstr oldVal(""); 1627 1508 1628 1509 /* serialize file access (prevent concurrent reads and writes) */ 1629 1510 AutoWriteLock alock(this); 1630 1511 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); 1708 1544 } 1709 1545 1710 1546 /* fire a notification */ 1711 if ( SUCCEEDED(rc) && changed)1712 onExtraDataChange 1713 1714 return rc;1547 if (fChanged) 1548 onExtraDataChange(Guid::Empty, aKey, aValue); 1549 1550 return S_OK; 1715 1551 } 1716 1552 … … 1918 1754 { 1919 1755 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();1954 1756 } 1955 1757 … … 2718 2520 * @note Locks this object and hard disk objects for reading. 2719 2521 */ 2720 HRESULT VirtualBox:: 2721 findHardDisk(const Guid *aId, CBSTR aLocation, 2722 bool aSetError, ComObjPtr<HardDisk> *aHardDisk /*= NULL*/) 2522 HRESULT VirtualBox::findHardDisk(const Guid *aId, 2523 CBSTR aLocation, 2524 bool aSetError, 2525 ComObjPtr<HardDisk> *aHardDisk /*= NULL*/) 2723 2526 { 2724 2527 AssertReturn(aId || aLocation, E_INVALIDARG); … … 2750 2553 const ComObjPtr<HardDisk> &hd = (*it).second; 2751 2554 2752 HRESULT rc = hd->compareLocationTo 2555 HRESULT rc = hd->compareLocationTo(location, result); 2753 2556 CheckComRCReturnRC(rc); 2754 2557 … … 2767 2570 { 2768 2571 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()); 2772 2576 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()); 2776 2581 } 2777 2582 … … 2794 2599 * @note Locks this object and image objects for reading. 2795 2600 */ 2796 HRESULT VirtualBox::findDVDImage(const Guid *aId, CBSTR aLocation, 2601 HRESULT VirtualBox::findDVDImage(const Guid *aId, 2602 CBSTR aLocation, 2797 2603 bool aSetError, 2798 2604 ComObjPtr<DVDImage> *aImage /* = NULL */) … … 2804 2610 if (aLocation != NULL) 2805 2611 { 2806 int vrc = calculateFullPath (Utf8Str(aLocation), location);2612 int vrc = calculateFullPath(Utf8Str(aLocation), location); 2807 2613 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); 2811 2618 } 2812 2619 … … 2824 2631 found = (aId && (*it)->id() == *aId) || 2825 2632 (aLocation != NULL && 2826 RTPathCompare (location, Utf8Str ((*it)->locationFull())) == 0); 2633 RTPathCompare(location.c_str(), 2634 Utf8Str((*it)->locationFull()).c_str() 2635 ) == 0); 2827 2636 if (found) 2828 2637 { … … 2838 2647 { 2839 2648 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()); 2843 2653 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()); 2847 2658 } 2848 2659 … … 2876 2687 if (aLocation != NULL) 2877 2688 { 2878 int vrc = calculateFullPath (Utf8Str(aLocation), location);2689 int vrc = calculateFullPath(Utf8Str(aLocation), location); 2879 2690 if (RT_FAILURE(vrc)) 2880 2691 return setError (VBOX_E_FILE_ERROR, … … 2896 2707 found = (aId && (*it)->id() == *aId) || 2897 2708 (aLocation != NULL && 2898 RTPathCompare (location, Utf8Str ((*it)->locationFull())) == 0); 2709 RTPathCompare(location.c_str(), 2710 Utf8Str((*it)->locationFull()).c_str() 2711 ) == 0); 2899 2712 if (found) 2900 2713 { … … 2910 2723 { 2911 2724 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()); 2915 2729 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()); 2919 2734 } 2920 2735 2921 2736 return rc; 2737 } 2738 2739 /** 2740 * Returns the default machine folder from the system properties 2741 * with proper locking. 2742 * @return 2743 */ 2744 const 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 */ 2755 const 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 */ 2766 const Utf8Str& VirtualBox::getDefaultHardDiskFormat() const 2767 { 2768 AutoReadLock propsLock(mData.mSystemProperties); 2769 return mData.mSystemProperties->m_strDefaultHardDiskFormat; 2922 2770 } 2923 2771 … … 2933 2781 * @note Doesn't lock any object. 2934 2782 */ 2935 int VirtualBox::calculateFullPath (const char *aPath, Utf8Str &aResult)2783 int VirtualBox::calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult) 2936 2784 { 2937 2785 AutoCaller autoCaller(this); … … 2940 2788 /* no need to lock since mHomeDir is const */ 2941 2789 2942 char folder 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)); 2944 2792 if (RT_SUCCESS(vrc)) 2945 2793 aResult = folder; … … 2959 2807 * @note Doesn't lock any object. 2960 2808 */ 2961 void VirtualBox::calculateRelativePath (const char *aPath, Utf8Str &aResult)2809 void VirtualBox::calculateRelativePath(const Utf8Str &strPath, Utf8Str &aResult) 2962 2810 { 2963 2811 AutoCaller autoCaller(this); … … 2968 2816 Utf8Str settingsDir = mData.mHomeDir; 2969 2817 2970 if (RTPathStartsWith (aPath, settingsDir))2818 if (RTPathStartsWith(strPath.c_str(), settingsDir.c_str())) 2971 2819 { 2972 2820 /* when assigning, we create a separate Utf8Str instance because both … … 2975 2823 * first, and since its the same as aPath, an attempt to copy garbage 2976 2824 * will be made. */ 2977 aResult = Utf8Str (aPath+ settingsDir.length() + 1);2825 aResult = Utf8Str(strPath.c_str() + settingsDir.length() + 1); 2978 2826 } 2979 2827 } … … 3054 2902 3055 2903 /** 3056 * Reads in the machine definitions from the configuration loader3057 * 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 file3100 * and creates the relevant objects.3101 *3102 * @param aGlobal <Global> node3103 *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 file3192 * and creates the relevant objects.3193 *3194 * @param aGlobal <Global> node3195 *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 /**3243 2904 * Helper function to write out the configuration tree. 3244 2905 * … … 3247 2908 HRESULT VirtualBox::saveSettings() 3248 2909 { 3249 AutoCaller autoCaller (this);3250 AssertComRCReturn 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); 3253 2914 3254 2915 HRESULT rc = S_OK; … … 3259 2920 try 3260 2921 { 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); 3367 2979 } 3368 2980 3369 2981 /* 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(); 3380 2990 } 3381 2991 catch (HRESULT err) … … 3444 3054 3445 3055 /* add to the collection of registered machines */ 3446 mData.mMachines.push_back 3056 mData.mMachines.push_back(aMachine); 3447 3057 3448 3058 if (autoCaller.state() != InInit) … … 3491 3101 { 3492 3102 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')"), 3494 3104 aHardDisk->locationFull().raw(), 3495 3105 aHardDisk->id().raw(), 3496 3106 strConflict.raw(), 3497 m Data.mCfgFile.mName.raw());3107 m_strSettingsFilePath.raw()); 3498 3108 } 3499 3109 … … 3609 3219 { 3610 3220 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')"), 3612 3222 aImage->locationFull().raw(), 3613 3223 aImage->id().raw(), 3614 3224 strConflict.raw(), 3615 m Data.mCfgFile.mName.raw());3225 m_strSettingsFilePath.raw()); 3616 3226 } 3617 3227 … … 3712 3322 { 3713 3323 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')"), 3715 3325 aImage->locationFull().raw(), 3716 3326 aImage->id().raw(), 3717 3327 strConflict.raw(), 3718 m Data.mCfgFile.mName.raw());3328 m_strSettingsFilePath.raw()); 3719 3329 } 3720 3330 … … 3726 3336 rc = saveSettings(); 3727 3337 if (FAILED (rc)) 3728 unregisterFloppyImage 3338 unregisterFloppyImage(aImage, false /* aSaveRegistry */); 3729 3339 } 3730 3340 … … 3874 3484 */ 3875 3485 /* static */ 3876 HRESULT VirtualBox::ensureFilePathExists (const char *aFileName)3877 { 3878 Utf8Str strDir( aFileName);3486 HRESULT VirtualBox::ensureFilePathExists(const Utf8Str &strFileName) 3487 { 3488 Utf8Str strDir(strFileName); 3879 3489 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); 3883 3493 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 } 4051 3499 4052 3500 return S_OK; … … 4076 3524 */ 4077 3525 /* static */ 4078 HRESULT VirtualBox::handleUnexpectedExceptions 3526 HRESULT VirtualBox::handleUnexpectedExceptions(RT_SRC_POS_DECL) 4079 3527 { 4080 3528 try … … 4085 3533 catch (const std::exception &err) 4086 3534 { 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); 4091 3538 } 4092 3539 catch (...) 4093 3540 { 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); 4097 3543 } 4098 3544 … … 4100 3546 AssertFailed(); 4101 3547 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 returns4111 * S_OK, but subsequent #isConfigLocked() will return FALSE. This is used4112 * in some places to determine the (valid) situation when no config file4113 * 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 seriously4141 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 else4147 {4148 mData.mCfgFile.mReadonly = TRUE;4149 }4150 }4151 else4152 {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;4193 3548 } 4194 3549 … … 4793 4148 { 4794 4149 rc = (*it)->COMGETTER(NetworkName) (bstr.asOutParam()); 4795 CheckComRCThrowRC 4150 CheckComRCThrowRC(rc); 4796 4151 4797 4152 if(bstr == aName) -
trunk/src/VBox/Main/VirtualBoxImplExtra.cpp
r21878 r22173 24 24 */ 25 25 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 indicate71 * 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 XSLT111 * template identified by #templateUri(), or @false if no conversion is112 * required.113 *114 * The implementation normally checks for the "version" value of the115 * root key to determine if the conversion is necessary. When the116 * @a aOldVersion argument is not NULL, the implementation must return a117 * non-NULL non-empty string representing the old version (before118 * conversion) in it this string is used by XmlTreeBackend::oldVersion()119 * and must be non-NULL to indicate that the conversion has been120 * performed on the tree. The returned string must be allocated using121 * RTStrDup() or such.122 *123 * This method is called again after the successful transformation to124 * let the implementation retry the version check and request another125 * transformation if necessary. This may be used to perform multi-step126 * 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 conversion128 * templates to make each of them convert directly to the recent129 * version.130 *131 * @note Multi-step transformations are performed in a loop that exits132 * only when this method returns @false. It's up to the133 * implementation to detect cycling (repeated requests to convert134 * from the same version) wrong version order, etc. and throw an135 * EConversionCycle exception to break the loop without returning136 * @false (which means the transformation succeeded).137 *138 * @param aRoot Root settings key.139 * @param aOldVersionString Where to store old version string140 * pointer. May be NULL. Allocated memory is141 * freed by the caller using RTStrFree().142 */143 bool SettingsTreeHelper::144 needsConversion (const settings::Key &aRoot, char **aOldVersion) const145 {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 same164 * 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() const174 {175 return VBOX_XML_SETTINGS_CONVERTER;176 }177 178 #if defined VBOX_MAIN_SETTINGS_ADDONS179 180 // Settings API additions181 ////////////////////////////////////////////////////////////////////////////////182 183 namespace settings184 {185 186 template<> stdx::char_auto_ptr187 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 needed195 * w/o allocating the result buffer itself is to provide that both cch196 * 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 throw240 * 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_ptr250 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_ADDONS267 268 } /* namespace settings */269 270 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/generic/NetIf-generic.cpp
r21886 r22173 80 80 pIf->COMGETTER(Name)(interfaceName.asOutParam()); 81 81 Utf8Str strName(interfaceName); 82 return NetIfAdpCtl(strName , pszAddr, pszOption, pszMask);82 return NetIfAdpCtl(strName.c_str(), pszAddr, pszOption, pszMask); 83 83 } 84 84 … … 242 242 progress.queryInterfaceTo(aProgress); 243 243 iface.queryInterfaceTo(aHostNetworkInterface); 244 rc = NetIfAdpCtl(Utf8Str(ifname) , "remove", NULL, NULL);244 rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL); 245 245 if (RT_FAILURE(rc)) 246 246 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 98 98 */ 99 99 /* static */ 100 HRESULT SupportErrorInfoBase::setErrorInternal ( 101 HRESULT aResultCode, const GUID *aIID, 102 const char *aComponent, const char *aText, 103 bool aWarning, IVirtualBoxErrorInfo *aInfo /*= NULL*/) 100 HRESULT SupportErrorInfoBase::setErrorInternal(HRESULT aResultCode, 101 const GUID *aIID, 102 const char *aComponent, 103 const Utf8Str &strText, 104 bool aWarning, 105 IVirtualBoxErrorInfo *aInfo /*= NULL*/) 104 106 { 105 107 /* whether multi-error mode is turned on */ 106 108 bool preserve = ((uintptr_t) RTTlsGet (MultiResult::sCounter)) > 0; 107 109 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)); 112 118 113 119 if (aInfo == NULL) … … 117 123 (aWarning && aResultCode != S_OK), 118 124 E_FAIL); 119 AssertReturn(aText != NULL, E_FAIL); 120 AssertReturn(*aText != '\0', E_FAIL); 125 AssertReturn(!strText.isEmpty(), E_FAIL); 121 126 122 127 /* reset the error severity bit if it's a warning */ … … 263 268 CheckComRCBreakRC (rc); 264 269 265 rc = infoObj->init (aResultCode, aIID, aComponent, aText, curInfo);270 rc = infoObj->init(aResultCode, aIID, aComponent, strText, curInfo); 266 271 CheckComRCBreakRC (rc); 267 272 … … 335 340 } 336 341 342 HRESULT SupportErrorInfoBase::setError (HRESULT aResultCode, const Utf8Str &strText) 343 { 344 HRESULT rc = setError(aResultCode, 345 mainInterfaceID(), 346 componentName(), 347 strText); 348 return rc; 349 } 350 337 351 HRESULT SupportErrorInfoBase::setWarning (HRESULT aResultCode, const char *aText, ...) 338 352 { -
trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp
r21878 r22173 41 41 * Initializes the error info object with the given error details. 42 42 */ 43 HRESULT VirtualBoxErrorInfo::init (HRESULT aResultCode, const GUID *aIID, 44 const char *aComponent, const char *aText, 45 IVirtualBoxErrorInfo *aNext) 43 HRESULT VirtualBoxErrorInfo::init(HRESULT aResultCode, 44 const GUID *aIID, 45 const char *aComponent, 46 const Utf8Str &strText, 47 IVirtualBoxErrorInfo *aNext) 46 48 { 47 49 mResultCode = aResultCode; … … 51 53 52 54 mComponent = aComponent; 53 mText = aText;55 mText = strText; 54 56 mNext = aNext; 55 57 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r22165 r22173 347 347 348 348 <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 349 394 name="AccessMode" 350 395 uuid="1da0007c-ddf7-4be8-bcac-d84a1558785f" … … 1401 1446 </attribute> 1402 1447 1403 <attribute name="settingsFileVersion" type="wstring" readonly="yes">1404 <desc>1405 Current version of the format of the global VirtualBox settings file1406 (<tt>VirtualBox.xml</tt>).1407 1408 The version string has the following format:1409 <pre>1410 x.y-platform1411 </pre>1412 where @c x and @c y are the major and the minor format1413 versions, and @c platform is the platform identifier.1414 1415 The current version usually matches the value of the1416 <link to="#settingsFormatVersion"/> attribute unless the1417 settings file was created by an older version of VirtualBox and there1418 was a change of the settings file format since then.1419 1420 Note that VirtualBox automatically converts settings files from older1421 versions to the most recent version when reading them (usually at1422 VirtualBox startup) but it doesn't save the changes back until1423 you call a method that implicitly saves settings (such as1424 <link to="#setExtraData"/>) or call <link to="#saveSettings"/>1425 explicitly. Therefore, if the value of this attribute differs from the1426 value of <link to="#settingsFormatVersion"/>, then it1427 means that the settings file was converted but the result of the1428 conversion is not yet saved to disk.1429 1430 The above feature may be used by interactive front-ends to inform users1431 about the settings file format change and offer them to explicitly save1432 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-platform1447 </pre>1448 where @c x and @c y are the major and the minor format1449 versions, and @c platform is the platform identifier.1450 1451 VirtualBox uses this version of the format when saving settings files1452 (either as a result of method calls that require to save settings or as1453 a result of an explicit call to <link to="#saveSettings"/>).1454 1455 <see>settingsFileVersion</see>1456 </desc>1457 </attribute>1458 1459 1448 <attribute name="host" type="IHost" readonly="yes"> 1460 1449 <desc>Associated host object.</desc> … … 2297 2286 </method> 2298 2287 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> 2322 2295 </param> 2323 2296 </method> … … 2750 2723 <param name="values" type="wstring" dir="out"> 2751 2724 <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 file2758 (<link to="#settingsFilePath"/>).2759 2760 This method is only useful for explicitly saving the global settings2761 file after it has been auto-converted from the old format to the most2762 recent format (see <link to="#settingsFileVersion"/> for details).2763 Normally, the global settings file is implicitly saved when a global2764 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 file2779 (<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 file2783 auto-conversion took place (see <link to="#settingsFileVersion"/> for2784 details). Otherwise, this call is fully equivalent to2785 <link to="IVirtualBox::saveSettings"/> and no backup copying is done.2786 2787 The backup copy is created in the same directory where the original2788 settings file is located. It is given the following file name:2789 <pre>2790 original.xml.x.y-platform.bak2791 </pre>2792 where <tt>original.xml</tt> is the original settings file name2793 (excluding path), and <tt>x.y-platform</tt> is the version of the old2794 format of the settings file (before auto-conversion).2795 2796 If the given backup file already exists, this method will try to add the2797 <tt>.N</tt> suffix to the backup file name (where @c N counts from2798 0 to 9) and copy it again until it succeeds. If all suffixes are2799 occupied, or if any other copy error occurs, this method will return a2800 failure.2801 2802 If the copy operation succeeds, the @a bakFileName return argument will2803 receive a full path to the created backup file (for informational2804 purposes). Note that this will happen even if the subsequent2805 <link to="#saveSettings"/> call performed by this method after the2806 copy operation, fails.2807 2808 <note>2809 The VirtualBox API never calls this method. It is intended purely for2810 the purposes of creating backup copies of the settings files by2811 front-ends before saving the results of the automatically performed2812 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>2830 2725 </param> 2831 2726 </method> … … 4224 4119 to OpenGL only. </desc> 4225 4120 </attribute> 4226 4121 4227 4122 <attribute name="accelerate2DVideoEnabled" type="boolean" default="false"> 4228 4123 <desc> … … 4350 4245 <desc> 4351 4246 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 machine4358 (<link to="IMachine::settingsFilePath"/>).4359 4360 The version string has the following format:4361 <pre>4362 x.y-platform4363 </pre>4364 where @c x and @c y are the major and the minor format4365 versions, and @c platform is the platform identifier.4366 4367 The current version usually matches the value of the4368 <link to="IVirtualBox::settingsFormatVersion"/> attribute unless the4369 settings file was created by an older version of VirtualBox and there4370 was a change of the settings file format since then.4371 4372 Note that VirtualBox automatically converts settings files from older4373 versions to the most recent version when reading them (usually at4374 VirtualBox startup) but it doesn't save the changes back until4375 you call a method that implicitly saves settings (such as4376 <link to="#setExtraData"/>) or call <link to="#saveSettings"/>4377 explicitly. Therefore, if the value of this attribute differs from the4378 value of <link to="IVirtualBox::settingsFormatVersion"/>, then it4379 means that the settings file was converted but the result of the4380 conversion is not yet saved to disk.4381 4382 The above feature may be used by interactive front-ends to inform users4383 about the settings file format change and offer them to explicitly save4384 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>4389 4247 </desc> 4390 4248 </attribute> … … 4878 4736 </method> 4879 4737 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> 4906 4746 </method> 4907 4747 … … 5003 4843 5004 4844 </desc> 5005 </method>5006 5007 <method name="saveSettingsWithBackup">5008 <desc>5009 Creates a backup copy of the machine settings file (<link5010 to="IMachine::settingsFilePath"/>) in case of auto-conversion, and then calls5011 <link to="IMachine::saveSettings"/>.5012 5013 Note that the backup copy is created <b>only</b> if the settings file5014 auto-conversion took place (see <link to="#settingsFileVersion"/> for5015 details). Otherwise, this call is fully equivalent to5016 <link to="IMachine::saveSettings"/> and no backup copying is done.5017 5018 The backup copy is created in the same directory where the original5019 settings file is located. It is given the following file name:5020 <pre>5021 original.xml.x.y-platform.bak5022 </pre>5023 where <tt>original.xml</tt> is the original settings file name5024 (excluding path), and <tt>x.y-platform</tt> is the version of the old5025 format of the settings file (before auto-conversion).5026 5027 If the given backup file already exists, this method will try to add the5028 <tt>.N</tt> suffix to the backup file name (where @c N counts from5029 0 to 9) and copy it again until it succeeds. If all suffixes are5030 occupied, or if any other copy error occurs, this method will return a5031 failure.5032 5033 If the copy operation succeeds, the @a bakFileName return argument will5034 receive a full path to the created backup file (for informational5035 purposes). Note that this will happen even if the subsequent5036 <link to="#saveSettings"/> call performed by this method after the5037 copy operation, fails.5038 5039 <note>5040 The VirtualBox API never calls this method. It is intended purely for5041 the purposes of creating backup copies of the settings files by5042 front-ends before saving the results of the automatically performed5043 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>5065 4845 </method> 5066 4846 … … 11895 11675 <desc>Null value, also means "dummy audio driver".</desc> 11896 11676 </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> 11905 11701 </enum> 11906 11702 -
trunk/src/VBox/Main/include/AudioAdapterImpl.h
r21878 r22173 28 28 29 29 class Machine; 30 31 namespace settings 32 { 33 class AudioAdapter; 34 } 30 35 31 36 class ATL_NO_VTABLE AudioAdapter : … … 88 93 // public methods only for internal purposes 89 94 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); 92 97 93 98 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } -
trunk/src/VBox/Main/include/BIOSSettingsImpl.h
r21878 r22173 29 29 class Machine; 30 30 class GuestOSType; 31 32 namespace settings 33 { 34 class BIOSSettings; 35 } 31 36 32 37 class ATL_NO_VTABLE BIOSSettings : … … 119 124 // public methods only for internal purposes 120 125 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); 123 128 124 129 const Backupable <Data> &data() const { return mData; } -
trunk/src/VBox/Main/include/DHCPServerImpl.h
r21878 r22173 29 29 30 30 #ifdef VBOX_WITH_HOSTNETIF_API 31 /* class DHCPServer; */32 /* #include "netif.h" */33 31 struct NETIFINFO; 34 32 #endif 33 34 namespace settings 35 { 36 class DHCPServer; 37 } 35 38 36 39 class ATL_NO_VTABLE DHCPServer : … … 61 64 void FinalRelease(); 62 65 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); 66 71 67 72 void uninit(); 68 73 69 74 // IDHCPServer properties 70 STDMETHOD(COMGETTER(NetworkName)) 71 STDMETHOD(COMGETTER(Enabled)) 72 STDMETHOD(COMSETTER(Enabled)) 73 STDMETHOD(COMGETTER(IPAddress)) 74 STDMETHOD(COMGETTER(NetworkMask)) 75 STDMETHOD(COMGETTER(LowerIP)) 76 STDMETHOD(COMGETTER(UpperIP)) 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); 77 82 78 STDMETHOD(SetConfiguration) 83 STDMETHOD(SetConfiguration)(IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aFromIPAddress, IN_BSTR aToIPAddress); 79 84 80 STDMETHOD(Start) 81 STDMETHOD(Stop) 85 STDMETHOD(Start)(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType); 86 STDMETHOD(Stop)(); 82 87 83 88 // for VirtualBoxSupportErrorInfoImpl … … 106 111 107 112 #endif // ____H_H_DHCPSERVERIMPL 108 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/DHCPServerRunner.h
r21860 r22173 53 53 { 54 54 public: 55 DHCPServerRunner(); 55 DHCPServerRunner(); 56 56 ~DHCPServerRunner() { stop(); /* don't leave abandoned servers */} 57 57 … … 79 79 } 80 80 81 int setOption(DHCPCFG opt, const com::Utf8Str &val, bool enabled) 82 { 83 return setOption(opt, val.c_str(), enabled); 84 } 85 81 86 int start(); 82 87 int stop(); -
trunk/src/VBox/Main/include/DVDDriveImpl.h
r21878 r22173 30 30 31 31 class Machine; 32 33 namespace settings 34 { 35 class DVDDrive; 36 } 32 37 33 38 class ATL_NO_VTABLE DVDDrive : … … 100 105 // public methods only for internal purposes 101 106 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); 104 109 105 110 bool isModified() { AutoWriteLock alock (this); return m.isBackedUp(); } -
trunk/src/VBox/Main/include/FloppyDriveImpl.h
r21878 r22173 30 30 31 31 class Machine; 32 33 namespace settings 34 { 35 class FloppyDrive; 36 } 32 37 33 38 class ATL_NO_VTABLE FloppyDrive : … … 100 105 // public methods only for internal purposes 101 106 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); 104 109 105 110 bool isModified() { AutoWriteLock alock (this); return m.isBackedUp(); } -
trunk/src/VBox/Main/include/HardDiskImpl.h
r21878 r22173 38 38 39 39 class Progress; 40 namespace settings 41 { 42 class Medium; 43 } 40 44 41 45 //////////////////////////////////////////////////////////////////////////////// … … 96 100 HRESULT init(VirtualBox *aVirtualBox, 97 101 HardDisk *aParent, 98 const settings:: Key &aNode);102 const settings::Medium &data); 99 103 void uninit(); 100 104 … … 148 152 bool isReadOnly(); 149 153 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); 153 157 154 158 /** … … 256 260 private: 257 261 258 HRESULT setLocation (CBSTRaLocation);262 virtual HRESULT setLocation(const Utf8Str &aLocation); 259 263 HRESULT setFormat (CBSTR aFormat); 260 264 -
trunk/src/VBox/Main/include/HostImpl.h
r21878 r22173 48 48 class Progress; 49 49 50 namespace settings 51 { 52 class Host; 53 } 54 50 55 #include <list> 51 56 … … 74 79 75 80 // public initializer/uninitializer for internal purposes only 76 HRESULT init 81 HRESULT init(VirtualBox *aParent); 77 82 void uninit(); 78 83 … … 114 119 115 120 // 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); 119 123 120 124 #ifdef VBOX_WITH_USB -
trunk/src/VBox/Main/include/MachineImpl.h
r22143 r22173 37 37 #include "ParallelPortImpl.h" 38 38 #include "BIOSSettingsImpl.h" 39 #include "StorageControllerImpl.h"40 39 #ifdef VBOX_WITH_RESOURCE_USAGE_API 41 40 #include "PerformanceImpl.h" … … 70 69 class SharedFolder; 71 70 class HostUSBDevice; 71 class StorageController; 72 72 73 73 class SessionMachine; 74 75 namespace settings 76 { 77 class MachineConfigFile; 78 class Snapshot; 79 class Hardware; 80 class Storage; 81 class StorageController; 82 class MachineRegistryEntry; 83 } 74 84 75 85 // Machine class … … 87 97 88 98 enum InstanceType { IsMachine, IsSessionMachine, IsSnapshotMachine }; 99 100 enum InitMode { Init_New, Init_Import, Init_Registered }; 89 101 90 102 /** … … 151 163 const Guid mUuid; 152 164 BOOL mRegistered; 165 InitMode mInitMode; 153 166 154 167 /** Flag indicating that the config file is read-only. */ 155 168 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; 160 174 161 175 BOOL mAccessible; … … 247 261 struct GuestProperty { 248 262 /** Property name */ 249 Bstr mName;263 Utf8Str strName; 250 264 /** Property value */ 251 Bstr mValue;265 Utf8Str strValue; 252 266 /** Property timestamp */ 253 267 ULONG64 mTimestamp; … … 270 284 BOOL mHWVirtExNestedPagingEnabled; 271 285 BOOL mHWVirtExVPIDEnabled; 272 BOOL mAccelerate3DEnabled;273 286 BOOL mAccelerate2DVideoEnabled; 274 287 BOOL mPAEEnabled; 275 288 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; 280 294 SharedFolderList mSharedFolders; 295 281 296 ClipboardMode_T mClipboardMode; 282 typedef std::list <GuestProperty> GuestPropertyList; 297 298 typedef std::list<GuestProperty> GuestPropertyList; 283 299 GuestPropertyList mGuestProperties; 284 300 BOOL mPropertyServiceActive; … … 464 480 NS_DECL_ISUPPORTS 465 481 466 DECLARE_EMPTY_CTOR_DTOR 482 DECLARE_EMPTY_CTOR_DTOR(Machine) 467 483 468 484 HRESULT FinalConstruct(); 469 485 void FinalRelease(); 470 486 471 enum InitMode { Init_New, Init_Existing, Init_Registered };472 473 487 // 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); 478 495 void uninit(); 479 496 497 protected: 498 HRESULT initDataAndChildObjects(); 499 void uninitDataAndChildObjects(); 500 501 public: 480 502 // IMachine properties 481 503 STDMETHOD(COMGETTER(Parent))(IVirtualBox **aParent); … … 525 547 STDMETHOD(COMGETTER(USBController)) (IUSBController * *aUSBController); 526 548 STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aFilePath); 527 STDMETHOD(COMGETTER(SettingsFileVersion)) (BSTR *aSettingsFileVersion);528 549 STDMETHOD(COMGETTER(SettingsModified)) (BOOL *aModified); 529 550 STDMETHOD(COMGETTER(SessionState)) (SessionState_T *aSessionState); … … 555 576 STDMETHOD(GetParallelPort) (ULONG slot, IParallelPort **port); 556 577 STDMETHOD(GetNetworkAdapter) (ULONG slot, INetworkAdapter **adapter); 557 STDMETHOD(Get NextExtraDataKey)(IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue);578 STDMETHOD(GetExtraDataKeys) (ComSafeArrayOut(BSTR, aKeys)); 558 579 STDMETHOD(GetExtraData)(IN_BSTR aKey, BSTR *aValue); 559 580 STDMETHOD(SetExtraData)(IN_BSTR aKey, IN_BSTR aValue); 560 581 STDMETHOD(SaveSettings)(); 561 STDMETHOD(SaveSettingsWithBackup) (BSTR *aBakFileName);562 582 STDMETHOD(DiscardSettings)(); 563 583 STDMETHOD(DeleteSettings)(); … … 628 648 * for reading. 629 649 */ 630 const Bstr &settingsFileFull() const { return mData->mConfigFileFull; }650 const Utf8Str &settingsFileFull() const { return mData->m_strConfigFileFull; } 631 651 632 652 /** … … 650 670 virtual HRESULT onSharedFolderChange() { return S_OK; } 651 671 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); 656 676 657 677 void getLogFolder (Utf8Str &aLogFolder); … … 748 768 inline Machine *machine(); 749 769 750 HRESULT initDataAndChildObjects();751 void uninitDataAndChildObjects();752 753 770 void ensureNoStateDependencies(); 754 771 … … 759 776 bool aSetError = false); 760 777 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, 781 797 ComObjPtr<StorageController> &aStorageController, 782 798 bool aSetError = false); … … 790 806 SaveS_ResetCurStateModified = 0x01, 791 807 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,796 808 /* flags for #saveSnapshotSettings() */ 797 809 SaveSS_CurStateModified = 0x40, … … 803 815 }; 804 816 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); 820 828 821 829 HRESULT createImplicitDiffs (const Bstr &aFolder, … … 825 833 826 834 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 }836 835 837 836 bool isInOwnDir (Utf8Str *aSettingsDir = NULL); … … 1097 1096 1098 1097 // 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); 1104 1106 void uninit(); 1105 1107 -
trunk/src/VBox/Main/include/MediumImpl.h
r21878 r22173 32 32 33 33 class VirtualBox; 34 namespace settings 35 { 36 class Medium; 37 } 34 38 35 39 //////////////////////////////////////////////////////////////////////////////// … … 142 146 virtual Utf8Str name(); 143 147 144 virtual HRESULT setLocation (CBSTRaLocation);148 virtual HRESULT setLocation(const Utf8Str &aLocation); 145 149 virtual HRESULT queryInfo(); 146 150 … … 222 226 223 227 // 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); 227 233 void protectedUninit(); 228 234 … … 230 236 231 237 // public methods for internal purposes only 232 HRESULT saveSettings (settings::Key &aImagesNode);238 HRESULT saveSettings(settings::Medium &data); 233 239 }; 234 240 … … 266 272 // public initializer/uninitializer for internal purposes only 267 273 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); 277 285 } 278 286 … … 320 328 // public initializer/uninitializer for internal purposes only 321 329 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); 331 341 } 332 342 -
trunk/src/VBox/Main/include/NetworkAdapterImpl.h
r21878 r22173 29 29 class Machine; 30 30 class GuestOSType; 31 32 namespace settings 33 { 34 class NetworkAdapter; 35 } 31 36 32 37 class ATL_NO_VTABLE NetworkAdapter : … … 134 139 // public methods only for internal purposes 135 140 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); 138 143 139 144 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } -
trunk/src/VBox/Main/include/ParallelPortImpl.h
r21878 r22173 27 27 28 28 class Machine; 29 30 namespace settings 31 { 32 class ParallelPort; 33 } 29 34 30 35 class ATL_NO_VTABLE ParallelPort : … … 100 105 // public methods only for internal purposes 101 106 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); 104 109 105 110 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } -
trunk/src/VBox/Main/include/Performance.h
r19270 r22173 33 33 #include <string> 34 34 #include <vector> 35 36 namespace com 37 { 38 class Utf8Str; 39 } 35 40 36 41 namespace pm … … 414 419 ElementList mElements; 415 420 416 void processMetricList(const std::string&name, const ComPtr<IUnknown> object);421 void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object); 417 422 }; 418 423 } -
trunk/src/VBox/Main/include/SerialPortImpl.h
r21878 r22173 29 29 class Machine; 30 30 class GuestOSType; 31 32 namespace settings 33 { 34 class SerialPort; 35 } 31 36 32 37 class ATL_NO_VTABLE SerialPort : … … 112 117 // public methods only for internal purposes 113 118 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); 116 121 117 122 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } -
trunk/src/VBox/Main/include/SnapshotImpl.h
r21835 r22173 29 29 class SnapshotMachine; 30 30 class VirtualBox; 31 31 32 namespace settings 32 33 { 33 class Key;34 class Snapshot; 34 35 } 35 36 … … 65 66 HRESULT init(VirtualBox *aVirtualBox, 66 67 const Guid &aId, 67 IN_BSTRaName,68 IN_BSTRaDescription,69 RTTIMESPECaTimeStamp,68 const Utf8Str &aName, 69 const Utf8Str &aDescription, 70 const RTTIMESPEC &aTimeStamp, 70 71 SnapshotMachine *aMachine, 71 72 Snapshot *aParent); … … 104 105 105 106 Guid getId() const; 106 BstrgetName() const;107 const Utf8Str& getName() const; 107 108 RTTIMESPEC getTimeStamp() const; 108 109 109 110 ComObjPtr<Snapshot> findChildOrSelf(IN_GUID aId); 110 ComObjPtr<Snapshot> findChildOrSelf( IN_BSTRaName);111 ComObjPtr<Snapshot> findChildOrSelf(const Utf8Str &aName); 111 112 112 113 void updateSavedStatePaths(const char *aOldPath, … … 115 116 const char *aNewPath); 116 117 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); 119 120 120 121 // for VirtualBoxSupportErrorInfoImpl -
trunk/src/VBox/Main/include/StorageControllerImpl.h
r21878 r22173 52 52 bool operator== (const Data &that) const 53 53 { 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)); 61 62 } 62 63 63 /** Uni uqe name of the storage controller. */64 Bstr mName;64 /** Unique name of the storage controller. */ 65 Utf8Str strName; 65 66 /** The connection type of thestorage controller. */ 66 67 StorageBus_T mStorageBus; … … 103 104 104 105 // 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); 109 114 void uninit(); 110 115 … … 128 133 // public methods only for internal purposes 129 134 130 const Bstr &name() const { return mData->mName; }135 const Utf8Str &name() const { return mData->strName; } 131 136 StorageControllerType_T controllerType() const { return mData->mStorageControllerType; } 137 StorageBus_T storageBus() const { return mData->mStorageBus; } 132 138 133 139 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } … … 159 165 const ComObjPtr<StorageController> mPeer; 160 166 /** Data. */ 161 Backupable 167 Backupable<Data> mData; 162 168 163 169 /* Instance number of the device in the running VM. */ -
trunk/src/VBox/Main/include/SystemPropertiesImpl.h
r21878 r22173 33 33 34 34 class VirtualBox; 35 namespace settings 36 { 37 class SystemProperties; 38 } 35 39 36 40 class ATL_NO_VTABLE SystemProperties : … … 95 99 // public methods only for internal purposes 96 100 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); 99 103 100 ComObjPtr<HardDiskFormat> hardDiskFormat 104 ComObjPtr<HardDiskFormat> hardDiskFormat(CBSTR aFormat); 101 105 102 106 // public methods for internal purposes only 103 107 // (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; }116 108 117 109 // for VirtualBoxSupportErrorInfoImpl … … 120 112 private: 121 113 122 typedef std::list <ComObjPtr<HardDiskFormat> > HardDiskFormatList;114 typedef std::list< ComObjPtr<HardDiskFormat> > HardDiskFormatList; 123 115 124 HRESULT setDefaultMachineFolder (CBSTRaPath);125 HRESULT setDefaultHardDiskFolder (CBSTRaPath);126 HRESULT setDefaultHardDiskFormat (CBSTRaFormat);116 HRESULT setDefaultMachineFolder(const Utf8Str &aPath); 117 HRESULT setDefaultHardDiskFolder(const Utf8Str &aPath); 118 HRESULT setDefaultHardDiskFormat(const Utf8Str &aFormat); 127 119 128 HRESULT setRemoteDisplayAuthLibrary (CBSTRaPath);129 HRESULT setWebServiceAuthLibrary (CBSTRaPath);120 HRESULT setRemoteDisplayAuthLibrary(const Utf8Str &aPath); 121 HRESULT setWebServiceAuthLibrary(const Utf8Str &aPath); 130 122 131 123 const ComObjPtr<VirtualBox, ComWeakRef> mParent; 132 124 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; 138 130 139 131 HardDiskFormatList mHardDiskFormats; 140 132 141 Bstr mRemoteDisplayAuthLibrary;142 Bstr mWebServiceAuthLibrary;133 Utf8Str m_strRemoteDisplayAuthLibrary; 134 Utf8Str m_strWebServiceAuthLibrary; 143 135 ULONG mLogHistoryCount; 144 136 AudioDriverType_T mDefaultAudioDriver; 137 138 friend class VirtualBox; 145 139 }; 146 140 -
trunk/src/VBox/Main/include/USBControllerImpl.h
r21878 r22173 34 34 class Machine; 35 35 class HostUSBDevice; 36 37 namespace settings 38 { 39 class USBController; 40 } 36 41 37 42 /** … … 109 114 // public methods only for internal purposes 110 115 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); 113 118 114 119 bool isModified(); -
trunk/src/VBox/Main/include/VRDPServerImpl.h
r21878 r22173 30 30 31 31 class Machine; 32 33 namespace settings 34 { 35 class VRDPSettings; 36 } 32 37 33 38 class ATL_NO_VTABLE VRDPServer : … … 107 112 // public methods only for internal purposes 108 113 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); 111 116 112 117 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); } -
trunk/src/VBox/Main/include/VirtualBoxBase.h
r21878 r22173 36 36 // avoid including VBox/settings.h and VBox/xml.h; 37 37 // only declare the classes 38 namespace settings39 {40 class XmlTreeBackend;41 class TreeBackend;42 class Key;43 }44 45 38 namespace xml 46 39 { -
trunk/src/VBox/Main/include/VirtualBoxImpl.h
r21878 r22173 62 62 struct VMClientWatcherData; 63 63 64 namespace settings 65 { 66 class MainConfigFile; 67 } 68 64 69 class ATL_NO_VTABLE VirtualBox : 65 70 public VirtualBoxBaseWithChildrenNEXT, … … 111 116 /* public initializer/uninitializer for internal purposes only */ 112 117 HRESULT init(); 118 HRESULT initMachines(); 119 HRESULT initMedia(); 113 120 void uninit(); 114 121 … … 119 126 STDMETHOD(COMGETTER(HomeFolder)) (BSTR *aHomeFolder); 120 127 STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aSettingsFilePath); 121 STDMETHOD(COMGETTER(SettingsFileVersion)) (BSTR *aSettingsFileVersion);122 STDMETHOD(COMGETTER(SettingsFormatVersion)) (BSTR *aSettingsFormatVersion);123 128 STDMETHOD(COMGETTER(Host)) (IHost **aHost); 124 129 STDMETHOD(COMGETTER(SystemProperties)) (ISystemProperties **aSystemProperties); … … 168 173 STDMETHOD(CreateSharedFolder) (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable); 169 174 STDMETHOD(RemoveSharedFolder) (IN_BSTR aName); 170 STDMETHOD(Get NextExtraDataKey) (IN_BSTR aKey, BSTR *aNextKey, BSTR *aNextValue);175 STDMETHOD(GetExtraDataKeys) (ComSafeArrayOut(BSTR, aKeys)); 171 176 STDMETHOD(GetExtraData) (IN_BSTR aKey, BSTR *aValue); 172 177 STDMETHOD(SetExtraData) (IN_BSTR aKey, IN_BSTR aValue); … … 183 188 BSTR *aChanged, BSTR *aValues); 184 189 185 STDMETHOD(SaveSettings)();186 STDMETHOD(SaveSettingsWithBackup) (BSTR *aBakFileName);187 188 190 // STDMETHOD(CreateDHCPServerForInterface) (/*IHostNetworkInterface * aIinterface, */IDHCPServer ** aServer); 189 191 STDMETHOD(CreateDHCPServer) (IN_BSTR aName, IDHCPServer ** aServer); … … 257 259 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 258 260 261 const Utf8Str& getDefaultMachineFolder() const; 262 const Utf8Str& getDefaultHardDiskFolder() const; 263 const Utf8Str& getDefaultHardDiskFormat() const; 259 264 260 265 /** Returns the VirtualBox home directory */ 261 266 const Utf8Str &homeDir() { return mData.mHomeDir; } 262 267 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); 265 270 266 271 HRESULT registerHardDisk(HardDisk *aHardDisk, bool aSaveRegistry = true); … … 276 281 277 282 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() 303 290 { 304 return loadSettingsTree (aTree, aFile, true, true, true, 305 &aFormatVersion); 291 return m_strSettingsFilePath; 306 292 } 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 fully312 * checked and validated by #loadSettingsTree_FirstTime()) in order to313 * look at settings that don't have any representation within object's314 * 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 fully326 * checked and validated by #loadSettingsTree_FirstTime()) in order to327 * 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);344 293 345 294 /** … … 364 313 private: 365 314 366 typedef std::list <ComObjPtr<Machine> > MachineList;367 typedef std::list <ComObjPtr<GuestOSType> > GuestOSTypeList;368 369 typedef std::map 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 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; 378 327 379 328 /** … … 390 339 Utf8Str &aConflictType); 391 340 392 HRESULT loadMachines (const settings::Key &aGlobal);393 HRESULT loadMedia (const settings::Key &aGlobal);394 HRESULT loadNetservices (const settings::Key &aGlobal);395 396 341 HRESULT registerMachine (Machine *aMachine); 397 342 398 343 HRESULT registerDHCPServer(DHCPServer *aDHCPServer, 399 344 bool aSaveRegistry = true); 400 345 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; 408 351 409 352 /** … … 416 359 Data(); 417 360 418 struct CfgFile419 {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 428 361 // const data members not requiring locking 429 const Utf8Str mHomeDir;362 const Utf8Str mHomeDir; 430 363 431 364 // 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; 434 367 #ifdef VBOX_WITH_RESOURCE_USAGE_API 435 368 const ComObjPtr<PerformanceCollector> mPerformanceCollector; 436 369 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 437 370 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; 452 381 453 382 /// @todo NEWMEDIA do we really need this map? Used only in 454 383 /// find() it seems 455 HardDiskMap mHardDiskMap;456 457 CallbackList mCallbacks;384 HardDiskMap mHardDiskMap; 385 386 CallbackList mCallbacks; 458 387 }; 459 388 … … 508 437 RWLockHandle mChildrenMapLockHandle; 509 438 439 /* static variables (defined in VirtualBoxImpl.cpp) */ 510 440 static Bstr sVersion; 511 441 static ULONG sRevision; 512 442 static Bstr sPackageType; 513 static Bstr sSettingsFormatVersion;514 443 515 444 static DECLCALLBACK(int) ClientWatcher (RTTHREAD thread, void *pvUser); -
trunk/src/VBox/Main/include/VirtualBoxImplExtra.h
r21292 r22173 25 25 #define ____H_VIRTUALBOXIMPLEXTRA 26 26 27 class SettingsTreeHelper : public settings::XmlTreeBackend::InputResolver28 , public settings::XmlTreeBackend::AutoConverter29 {30 public:31 32 // InputResolver interface33 xml::Input *resolveEntity (const char *aURI, const char *aID);34 35 // AutoConverter interface36 bool needsConversion (const settings::Key &aRoot, char **aOldVersion) const;37 const char *templateUri() const;38 };39 40 27 #endif // ____H_VIRTUALBOXIMPL EXTRA 41 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h
r22143 r22173 66 66 67 67 #endif /* ____H_VIRTUALBOXXMLUTIL */ 68 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ 68 -
trunk/src/VBox/Main/xml/Settings.cpp
r21878 r22173 19 19 */ 20 20 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" 42 22 #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 29 using namespace com; 30 using namespace settings; 31 32 /** 33 * Opaque data structore for ConfigFileBase (only declared 34 * in header, defined only here). 35 */ 36 37 struct 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 */ 81 class settings::ConfigFileError : public xml::LogicError 82 { 83 public: 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 */ 102 ConfigFileBase::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 */ 154 ConfigFileBase::~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 */ 171 void 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 */ 194 void ConfigFileBase::parseTimestamp(RTTIMESPEC ×tamp, 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(×tamp, &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 */ 257 com::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 272 com::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 */ 287 void 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 */ 318 void 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 */ 365 void 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 */ 393 void 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 */ 422 void 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 */ 470 void 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 */ 481 bool ConfigFileBase::fileExists() 482 { 483 return m->fFileExists; 484 } 485 486 /** 487 * Reads one <MachineEntry> from the main VirtualBox.xml file. 488 * @param elmMachineRegistry 489 */ 490 void 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 */ 522 void 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 */ 592 void 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 */ 639 void 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 */ 677 MainConfigFile::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 */ 741 void 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 */ 788 void 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 */ 890 void 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 */ 962 void 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 */ 1013 void 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 */ 1049 void 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 */ 1075 void 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 */ 1324 void 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 */ 1421 void 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 */ 1477 void 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 */ 1543 MachineConfigFile::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 */ 1576 void 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); 98 1730 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); 233 1734 break; 234 case 16: 235 flags |= RTSTR_F_16BIT; 1735 1736 case NetworkAttachmentType_Internal: 1737 pelmAdapter->createChild("InternalNetwork")->setAttribute("name", nic.strName); 236 1738 break; 237 case 32: 238 flags |= RTSTR_F_32BIT; 1739 1740 case NetworkAttachmentType_HostOnly: 1741 pelmAdapter->createChild("HostOnlyInterface")->setAttribute("name", nic.strName); 239 1742 break; 240 case 64: 241 flags |= RTSTR_F_64BIT;1743 1744 default: /*case NetworkAttachmentType_Null:*/ 242 1745 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 */ 1857 void 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 */ 1916 void 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 */ 1951 void 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 38 38 xml::XmlFileParser parser; 39 39 xml::Document doc; 40 parser.read(m_strPath .raw(),40 parser.read(m_strPath, 41 41 doc); 42 42 43 43 const xml::ElementNode *pRootElem = doc.getRootElement(); 44 if ( strcmp(pRootElem->getName(), "Envelope"))44 if (pRootElem && strcmp(pRootElem->getName(), "Envelope")) 45 45 throw OVFLogicError(N_("Root element in OVF file must be \"Envelope\".")); 46 46 -
trunk/src/VBox/Runtime/r3/xml.cpp
r21428 r22173 497 497 } 498 498 499 bool 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 499 511 /** 500 512 * Returns the value of a node. If this node is an attribute, returns … … 732 744 /** 733 745 * 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 */ 752 bool 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 */ 774 bool 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 */ 795 bool 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 734 808 * name and returns its value as a signed long integer. This calls 735 809 * RTStrToInt64Ex internally and will only output the integer if that … … 744 818 const char *pcsz; 745 819 if ( (getAttributeValue(pcszMatch, pcsz)) 746 && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 10, &i))820 && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 0, &i)) 747 821 ) 748 822 return true; … … 765 839 const char *pcsz; 766 840 if ( (getAttributeValue(pcszMatch, pcsz)) 767 && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 10, &i))841 && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 0, &i)) 768 842 ) 769 843 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 */ 857 bool 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 } 770 879 771 880 return false; … … 870 979 } 871 980 981 AttributeNode* 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 990 AttributeNode* 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 999 AttributeNode* 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 1008 AttributeNode* 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 1017 AttributeNode* 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 1026 AttributeNode* ElementNode::setAttribute(const char *pcszName, bool f) 1027 { 1028 return setAttribute(pcszName, (f) ? "true" : "false"); 1029 } 872 1030 873 1031 AttributeNode::AttributeNode() … … 910 1068 * NULL, like this: 911 1069 * <code> 912 * xml:: Node node;// should point to an element1070 * xml::ElementNode node; // should point to an element 913 1071 * xml::NodesLoop loop(node, "child"); // find all "child" elements under node 914 * const xml:: Node *pChild = NULL;1072 * const xml::ElementNode *pChild = NULL; 915 1073 * while (pChild = loop.forAllNodes()) 916 1074 * ...; … … 1018 1176 /** 1019 1177 * Returns the root element of the document, or NULL if the document is empty. 1178 * Const variant. 1020 1179 * @return 1021 1180 */ 1022 1181 const 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 */ 1191 ElementNode* Document::getRootElement() 1023 1192 { 1024 1193 return m->pRootElement; … … 1151 1320 * @param doc out: document to be reset and filled with data according to file contents. 1152 1321 */ 1153 void XmlFileParser::read(const char *pcszFilename,1322 void XmlFileParser::read(const iprt::MiniString &strFilename, 1154 1323 Document &doc) 1155 1324 { … … 1157 1326 // global.setExternalEntityLoader(ExternalEntityLoader); 1158 1327 1159 m->strXmlFilename = pcszFilename; 1328 m->strXmlFilename = strFilename; 1329 const char *pcszFilename = strFilename.c_str(); 1160 1330 1161 1331 ReadContext context(pcszFilename);
Note:
See TracChangeset
for help on using the changeset viewer.