Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

690 lines
22 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Configuration.cpp
  5. Abstract:
  6. This file contains the implementation of the ...
  7. Revision History:
  8. Davide Massarenti (Dmassare) 01/09/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. const MPC::Config::DefinitionOfTag* MPC::Config::DefinitionOfTag::FindSubTag( /*[in]*/ LPCWSTR szTag ) const
  14. {
  15. const DefinitionOfTag** ptr = m_tblSubTags;
  16. if(ptr)
  17. {
  18. while(*ptr)
  19. {
  20. if(!MPC::StrICmp( (*ptr)->m_szTag, szTag ))
  21. {
  22. return (*ptr);
  23. }
  24. ptr++;
  25. }
  26. }
  27. return NULL;
  28. }
  29. const MPC::Config::DefinitionOfAttribute* MPC::Config::DefinitionOfTag::FindAttribute( /*[in]*/ XMLTypes xt, /*[in]*/ LPCWSTR szName ) const
  30. {
  31. const DefinitionOfAttribute* ptr = m_tblAttributes;
  32. if(ptr)
  33. {
  34. while(ptr->m_xt != XT_invalid)
  35. {
  36. if(ptr->m_xt == xt)
  37. {
  38. if(ptr->m_xt == XT_value || !MPC::StrICmp( ptr->m_szName, szName )) return ptr;
  39. }
  40. ptr++;
  41. }
  42. }
  43. return NULL;
  44. }
  45. ////////////////////////////////////////////////////////////////////////////////
  46. void MPC::Config::ClearValue( /*[in]*/ TypeConstructor* defType ,
  47. /*[in]*/ const DefinitionOfAttribute* defAttrib )
  48. {
  49. {
  50. void* data = defType->GetOffset( defAttrib->m_offset );
  51. VARTYPE dest;
  52. switch(defAttrib->m_mtType)
  53. {
  54. case MT_bool : *(bool *)data = false ; break;
  55. case MT_BOOL : *(BOOL *)data = FALSE ; break;
  56. case MT_VARIANT_BOOL: *(VARIANT_BOOL*)data = VARIANT_FALSE; break;
  57. case MT_int : *(int *)data = 0 ; break;
  58. case MT_long : *(long *)data = 0 ; break;
  59. case MT_DWORD : *(DWORD *)data = 0 ; break;
  60. case MT_float : *(float *)data = 0 ; break;
  61. case MT_double : *(double *)data = 0 ; break;
  62. case MT_DATE : *(DATE *)data = 0 ; break;
  63. case MT_DATE_US : *(DATE *)data = 0 ; break;
  64. case MT_DATE_CIM : *(DATE *)data = 0 ; break;
  65. case MT_CHAR : *(CHAR *)data = 0 ; break;
  66. case MT_WCHAR : *(WCHAR *)data = 0 ; break;
  67. case MT_BSTR : *(CComBSTR *)data = (LPCWSTR)NULL; break;
  68. case MT_string : *(MPC::string *)data = "" ; break;
  69. case MT_wstring : *(MPC::wstring*)data = L"" ; break;
  70. case MT_bitfield : *(DWORD *)data = 0 ; break;
  71. }
  72. }
  73. if(defAttrib->m_fPresenceFlag)
  74. {
  75. bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence );
  76. *data = false;
  77. }
  78. }
  79. HRESULT MPC::Config::LoadValue( /*[in]*/ TypeConstructor* defType ,
  80. /*[in]*/ const DefinitionOfAttribute* defAttrib ,
  81. /*[in/out]*/ CComVariant& value ,
  82. /*[in]*/ bool fFound )
  83. {
  84. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadValue" );
  85. USES_CONVERSION;
  86. HRESULT hr;
  87. if(fFound)
  88. {
  89. void* data = defType->GetOffset( defAttrib->m_offset );
  90. VARTYPE dest;
  91. switch(defAttrib->m_mtType)
  92. {
  93. case MT_bool : dest = VT_BOOL ; break;
  94. case MT_BOOL : dest = VT_BOOL ; break;
  95. case MT_VARIANT_BOOL: dest = VT_BOOL ; break;
  96. case MT_int : dest = VT_I4 ; break;
  97. case MT_long : dest = VT_I4 ; break;
  98. case MT_DWORD : dest = VT_I4 ; break;
  99. case MT_float : dest = VT_R4 ; break;
  100. case MT_double : dest = VT_R8 ; break;
  101. case MT_DATE : dest = VT_ILLEGAL; break;
  102. case MT_DATE_US : dest = VT_ILLEGAL; break;
  103. case MT_DATE_CIM : dest = VT_ILLEGAL; break;
  104. case MT_CHAR : dest = VT_BSTR ; break;
  105. case MT_WCHAR : dest = VT_BSTR ; break;
  106. case MT_BSTR : dest = VT_BSTR ; break;
  107. case MT_string : dest = VT_BSTR ; break;
  108. case MT_wstring : dest = VT_BSTR ; break;
  109. case MT_bitfield : dest = VT_BSTR ; break;
  110. default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  111. }
  112. if(dest == VT_ILLEGAL)
  113. {
  114. LPCWSTR szDate;
  115. bool fCIM = false;
  116. LCID lcid = 0;
  117. __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( VT_BSTR ));
  118. szDate = value.bstrVal; SANITIZEWSTR(szDate);
  119. switch(defAttrib->m_mtType)
  120. {
  121. case MT_DATE : fCIM = false; lcid = 0; break;
  122. case MT_DATE_US : fCIM = false; lcid = -1; break;
  123. case MT_DATE_CIM: fCIM = true ; lcid = 0; break;
  124. }
  125. //
  126. // We try as much as we can to parse the date. First the expected format, then the US one, finally the user default.
  127. //
  128. if(FAILED(MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, fCIM, lcid )))
  129. {
  130. if(FAILED(MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, /*fCIM*/false, -1 )))
  131. {
  132. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, /*fCIM*/false, 0 ));
  133. }
  134. }
  135. }
  136. else
  137. {
  138. __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( dest ));
  139. switch(defAttrib->m_mtType)
  140. {
  141. case MT_bool : *(bool *)data = (value.boolVal == VARIANT_TRUE) ? true : false; break;
  142. case MT_BOOL : *(BOOL *)data = (value.boolVal == VARIANT_TRUE) ? TRUE : FALSE; break;
  143. case MT_VARIANT_BOOL: *(VARIANT_BOOL*)data = value.boolVal ; break;
  144. case MT_int : *(int *)data = value.lVal ; break;
  145. case MT_long : *(long *)data = value.lVal ; break;
  146. case MT_DWORD : *(DWORD *)data = value.lVal ; break;
  147. case MT_float : *(float *)data = value.fltVal ; break;
  148. case MT_double : *(double *)data = value.dblVal ; break;
  149. case MT_CHAR : *(CHAR *)data = value.bstrVal ? ( CHAR)value.bstrVal[0] : 0 ; break;
  150. case MT_WCHAR : *(WCHAR *)data = value.bstrVal ? (WCHAR)value.bstrVal[0] : 0 ; break;
  151. case MT_BSTR : *(CComBSTR *)data = value.bstrVal ; break;
  152. case MT_string : *(MPC::string *)data = OLE2A(SAFEBSTR(value.bstrVal)) ; break;
  153. case MT_wstring : *(MPC::wstring*)data = SAFEBSTR(value.bstrVal) ; break;
  154. case MT_bitfield:
  155. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToBitField( value.bstrVal, *(DWORD*)data, defAttrib->m_Lookup, /*fUseTilde*/false ));
  156. break;
  157. }
  158. }
  159. }
  160. if(defAttrib->m_fPresenceFlag)
  161. {
  162. bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence );
  163. *data = fFound;
  164. }
  165. hr = S_OK;
  166. __MPC_FUNC_CLEANUP;
  167. __MPC_FUNC_EXIT(hr);
  168. }
  169. HRESULT MPC::Config::SaveValue( /*[in]*/ const TypeConstructor* defType ,
  170. /*[in]*/ const DefinitionOfAttribute* defAttrib ,
  171. /*[out]*/ CComVariant& value ,
  172. /*[out]*/ bool& fFound )
  173. {
  174. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveValue" );
  175. HRESULT hr;
  176. if(defAttrib->m_fPresenceFlag)
  177. {
  178. bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence );
  179. fFound = *data;
  180. }
  181. else
  182. {
  183. fFound = true;
  184. }
  185. value.Clear();
  186. if(fFound)
  187. {
  188. const void* data = defType->GetOffset( defAttrib->m_offset );
  189. VARTYPE src;
  190. WCHAR rgBuf[2];
  191. switch(defAttrib->m_mtType)
  192. {
  193. case MT_bool : value.boolVal = *(bool *)data ? VARIANT_TRUE : VARIANT_FALSE; src = VT_BOOL ; break;
  194. case MT_BOOL : value.boolVal = *(BOOL *)data ? VARIANT_TRUE : VARIANT_FALSE; src = VT_BOOL ; break;
  195. case MT_VARIANT_BOOL: value.boolVal = *(VARIANT_BOOL*)data ; src = VT_BOOL ; break;
  196. case MT_int : value.lVal = *(int *)data ; src = VT_I4 ; break;
  197. case MT_long : value.lVal = *(long *)data ; src = VT_I4 ; break;
  198. case MT_DWORD : value.lVal = *(DWORD *)data ; src = VT_I4 ; break;
  199. case MT_float : value.fltVal = *(float *)data ; src = VT_R4 ; break;
  200. case MT_double : value.dblVal = *(double *)data ; src = VT_R8 ; break;
  201. case MT_DATE : ; src = VT_ILLEGAL; break;
  202. case MT_DATE_US : ; src = VT_ILLEGAL; break;
  203. case MT_DATE_CIM : ; src = VT_ILLEGAL; break;
  204. case MT_CHAR : rgBuf[0] = *(CHAR *)data; rgBuf[1] = 0; value = rgBuf ; src = VT_BSTR ; break;
  205. case MT_WCHAR : rgBuf[0] = *(WCHAR *)data; rgBuf[1] = 0; value = rgBuf ; src = VT_BSTR ; break;
  206. case MT_BSTR : value = *(CComBSTR *)data ; src = VT_BSTR ; break;
  207. case MT_string : value = ((MPC::string *)data)->c_str() ; src = VT_BSTR ; break;
  208. case MT_wstring : value = ((MPC::wstring*)data)->c_str() ; src = VT_BSTR ; break;
  209. case MT_bitfield:
  210. {
  211. MPC::wstring strText;
  212. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertBitFieldToString( *(DWORD*)data, strText, defAttrib->m_Lookup ));
  213. value = strText.c_str(); src = VT_BSTR;
  214. }
  215. break;
  216. default: __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  217. }
  218. if(src == VT_ILLEGAL)
  219. {
  220. MPC::wstring strDate;
  221. bool fCIM = false;
  222. LCID lcid = 0;
  223. switch(defAttrib->m_mtType)
  224. {
  225. case MT_DATE : fCIM = false; lcid = 0; break;
  226. case MT_DATE_US : fCIM = false; lcid = -1; break;
  227. case MT_DATE_CIM: fCIM = true ; lcid = 0; break;
  228. }
  229. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( *(DATE*)data, strDate, /*fGMT*/false, fCIM, lcid ));
  230. value = strDate.c_str();
  231. }
  232. else if(src != VT_BSTR)
  233. {
  234. value.vt = src;
  235. __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( VT_BSTR ));
  236. }
  237. }
  238. hr = S_OK;
  239. __MPC_FUNC_CLEANUP;
  240. __MPC_FUNC_EXIT(hr);
  241. }
  242. ////////////////////////////////////////////////////////////////////////////////
  243. HRESULT MPC::Config::LoadNode( /*[in]*/ TypeConstructor* defType ,
  244. /*[in]*/ const DefinitionOfTag* defTag ,
  245. /*[in]*/ IXMLDOMNode* xdn )
  246. {
  247. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadNode" );
  248. HRESULT hr;
  249. const DefinitionOfTag* defSubTag;
  250. const DefinitionOfAttribute* defAttrib;
  251. //
  252. // First of all, clean all the variables.
  253. //
  254. defAttrib = defTag->m_tblAttributes;
  255. if(defAttrib)
  256. {
  257. while(defAttrib->m_xt != XT_invalid)
  258. {
  259. ClearValue( defType, defAttrib );
  260. defAttrib++;
  261. }
  262. }
  263. //
  264. // Load all the attributes.
  265. //
  266. {
  267. CComPtr<IXMLDOMNamedNodeMap> xdnnmAttribs;
  268. __MPC_EXIT_IF_METHOD_FAILS(hr, xdn->get_attributes( &xdnnmAttribs ));
  269. if(xdnnmAttribs)
  270. {
  271. while(1)
  272. {
  273. CComPtr<IXMLDOMNode> xdnNode;
  274. CComQIPtr<IXMLDOMAttribute> xdaAttrib;
  275. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnnmAttribs->nextNode( &xdnNode ));
  276. if(xdnNode == NULL) break;
  277. if((xdaAttrib = xdnNode))
  278. {
  279. CComBSTR bstrName;
  280. __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->get_name( &bstrName ));
  281. defAttrib = defTag->FindAttribute( XT_attribute, SAFEBSTR( bstrName ) );
  282. if(defAttrib)
  283. {
  284. CComVariant value;
  285. __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->get_value( &value ));
  286. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, true ));
  287. }
  288. }
  289. }
  290. }
  291. }
  292. //
  293. // Load the node as value.
  294. //
  295. defAttrib = defTag->FindAttribute( XT_value, NULL );
  296. if(defAttrib)
  297. {
  298. MPC::XmlUtil xml( xdn );
  299. CComVariant value;
  300. bool fFound;
  301. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, value, fFound ));
  302. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, fFound ));
  303. }
  304. //
  305. // Load all subnodes.
  306. //
  307. if(defTag->m_tblSubTags)
  308. {
  309. CComPtr<IXMLDOMNode> xdnChild;
  310. __MPC_EXIT_IF_METHOD_FAILS(hr, xdn->get_firstChild( &xdnChild ));
  311. while(xdnChild)
  312. {
  313. CComPtr<IXMLDOMNode> xdnSibling;
  314. CComBSTR bstrName;
  315. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnChild->get_nodeName( &bstrName ));
  316. defAttrib = defTag->FindAttribute( XT_element, SAFEBSTR( bstrName ) );
  317. if(defAttrib)
  318. {
  319. MPC::XmlUtil xml( xdnChild );
  320. CComVariant value;
  321. bool fFound;
  322. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, value, fFound ));
  323. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, fFound ));
  324. }
  325. defSubTag = defTag->FindSubTag( SAFEBSTR( bstrName ) );
  326. if(defSubTag)
  327. {
  328. TypeConstructor* defSubType;
  329. __MPC_EXIT_IF_METHOD_FAILS(hr, defType->CreateInstance( defSubTag, defSubType ));
  330. __MPC_EXIT_IF_METHOD_FAILS(hr, defSubType->LoadNode( xdnChild ));
  331. }
  332. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnChild->get_nextSibling( &xdnSibling ));
  333. xdnChild = xdnSibling;
  334. }
  335. }
  336. hr = S_OK;
  337. __MPC_FUNC_CLEANUP;
  338. __MPC_FUNC_EXIT(hr);
  339. }
  340. HRESULT MPC::Config::LoadXmlUtil( /*[in]*/ TypeConstructor* defType ,
  341. /*[in]*/ MPC::XmlUtil& xml )
  342. {
  343. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadXmlUtil" );
  344. HRESULT hr;
  345. CComPtr<IXMLDOMNode> xdnRoot;
  346. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot( &xdnRoot ));
  347. __MPC_EXIT_IF_METHOD_FAILS(hr, defType->LoadNode( xdnRoot ));
  348. hr = S_OK;
  349. __MPC_FUNC_CLEANUP;
  350. __MPC_FUNC_EXIT(hr);
  351. }
  352. HRESULT MPC::Config::LoadStream( /*[in]*/ TypeConstructor* defType ,
  353. /*[in]*/ IStream* pStream )
  354. {
  355. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadStream" );
  356. HRESULT hr;
  357. MPC::XmlUtil xml;
  358. bool fFound;
  359. bool fLoaded;
  360. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.LoadAsStream( pStream, defType->GetTag(), fLoaded, &fFound ));
  361. if(fFound)
  362. {
  363. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadXmlUtil( defType, xml ));
  364. }
  365. hr = S_OK;
  366. __MPC_FUNC_CLEANUP;
  367. __MPC_FUNC_EXIT(hr);
  368. }
  369. HRESULT MPC::Config::LoadFile( /*[in]*/ TypeConstructor* defType ,
  370. /*[in]*/ LPCWSTR szFile )
  371. {
  372. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadFile" );
  373. HRESULT hr;
  374. MPC::XmlUtil xml;
  375. MPC::wstring strFileOrig( szFile ); strFileOrig += L".orig";
  376. bool fFound;
  377. bool fLoaded;
  378. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( szFile, defType->GetTag(), fLoaded, &fFound ));
  379. if(fFound == false)
  380. {
  381. //
  382. // If fails, try to load "<file>.orig"
  383. //
  384. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( strFileOrig.c_str(), defType->GetTag(), fLoaded, &fFound ));
  385. }
  386. if(fFound && fLoaded)
  387. {
  388. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadXmlUtil( defType, xml ));
  389. }
  390. hr = S_OK;
  391. __MPC_FUNC_CLEANUP;
  392. __MPC_FUNC_EXIT(hr);
  393. }
  394. ////////////////////////////////////////////////////////////////////////////////
  395. HRESULT MPC::Config::SaveNode( /*[in]*/ const TypeConstructor* defType ,
  396. /*[in]*/ const DefinitionOfTag* defTag ,
  397. /*[in]*/ IXMLDOMNode* xdn )
  398. {
  399. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveNode" );
  400. HRESULT hr;
  401. const DefinitionOfAttribute* defAttrib;
  402. defAttrib = defTag->m_tblAttributes;
  403. if(defAttrib)
  404. {
  405. MPC::XmlUtil xml( xdn );
  406. while(defAttrib->m_xt != XT_invalid)
  407. {
  408. CComVariant value;
  409. bool fFound;
  410. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveValue( defType, defAttrib, value, fFound ));
  411. if(fFound)
  412. {
  413. if(defAttrib->m_xt == XT_attribute)
  414. {
  415. CComPtr<IXMLDOMAttribute> xdaAttrib;
  416. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, defAttrib->m_szName, &xdaAttrib, fFound ));
  417. if(fFound)
  418. {
  419. __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->put_value( value ));
  420. }
  421. }
  422. else if(defAttrib->m_xt == XT_value)
  423. {
  424. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( NULL, value, fFound ));
  425. }
  426. else if(defAttrib->m_xt == XT_element)
  427. {
  428. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( defAttrib->m_szName, value, fFound ));
  429. }
  430. }
  431. defAttrib++;
  432. }
  433. }
  434. hr = S_OK;
  435. __MPC_FUNC_CLEANUP;
  436. __MPC_FUNC_EXIT(hr);
  437. }
  438. HRESULT MPC::Config::SaveSubNode( /*[in]*/ const TypeConstructor* defType ,
  439. /*[in]*/ IXMLDOMNode* xdn )
  440. {
  441. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveSubNode" );
  442. HRESULT hr;
  443. CComPtr<IXMLDOMNode> xdnChild;
  444. MPC::XmlUtil xml( xdn );
  445. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( defType->GetTag(), &xdnChild ));
  446. __MPC_EXIT_IF_METHOD_FAILS(hr, defType->SaveNode( xdnChild ));
  447. hr = S_OK;
  448. __MPC_FUNC_CLEANUP;
  449. __MPC_FUNC_EXIT(hr);
  450. }
  451. HRESULT MPC::Config::SaveXmlUtil( /*[in ]*/ const TypeConstructor* defType ,
  452. /*[out]*/ MPC::XmlUtil& xml )
  453. {
  454. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveXmlUtil" );
  455. HRESULT hr;
  456. CComPtr<IXMLDOMNode> xdnRoot;
  457. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( defType->GetTag() ));
  458. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot( &xdnRoot ));
  459. __MPC_EXIT_IF_METHOD_FAILS(hr, defType->SaveNode( xdnRoot ));
  460. hr = S_OK;
  461. __MPC_FUNC_CLEANUP;
  462. __MPC_FUNC_EXIT(hr);
  463. }
  464. HRESULT MPC::Config::SaveStream( /*[in]*/ const TypeConstructor* defType ,
  465. /*[in]*/ IStream* *ppStream )
  466. {
  467. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveStream" );
  468. HRESULT hr;
  469. MPC::XmlUtil xml;
  470. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveXmlUtil( defType, xml ));
  471. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.SaveAsStream( (IUnknown**)ppStream ));
  472. hr = S_OK;
  473. __MPC_FUNC_CLEANUP;
  474. __MPC_FUNC_EXIT(hr);
  475. }
  476. HRESULT MPC::Config::SaveFile( /*[in]*/ const TypeConstructor* defType ,
  477. /*[in]*/ LPCWSTR szFile )
  478. {
  479. __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveFile" );
  480. HRESULT hr;
  481. MPC::XmlUtil xml;
  482. MPC::wstring strFileNew ( szFile ); strFileNew += L".new";
  483. MPC::wstring strFileOrig( szFile ); strFileOrig += L".orig";
  484. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveXmlUtil( defType, xml ));
  485. //
  486. // First of all, delete "<file>.new" and recreate it.
  487. //
  488. ::SetFileAttributesW( strFileNew.c_str(), FILE_ATTRIBUTE_NORMAL );
  489. ::DeleteFileW ( strFileNew.c_str() );
  490. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Save( strFileNew.c_str() ));
  491. //
  492. // Then move "<file>" to "<file>.orig"
  493. //
  494. ::SetFileAttributesW( szFile , FILE_ATTRIBUTE_NORMAL );
  495. ::SetFileAttributesW( strFileOrig.c_str(), FILE_ATTRIBUTE_NORMAL );
  496. ::DeleteFileW ( strFileOrig.c_str() );
  497. if(::MoveFileW( szFile, strFileOrig.c_str() ) == FALSE)
  498. {
  499. DWORD dwRes = ::GetLastError();
  500. if(dwRes != ERROR_FILE_NOT_FOUND)
  501. {
  502. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  503. }
  504. }
  505. //
  506. // Then rename "<file>.new" to "<file>"
  507. //
  508. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileW( strFileNew.c_str(), szFile ));
  509. //
  510. // Finally delete "<file>.orig"
  511. //
  512. (void)::DeleteFileW( strFileOrig.c_str() );
  513. hr = S_OK;
  514. __MPC_FUNC_CLEANUP;
  515. __MPC_FUNC_EXIT(hr);
  516. }