Source code of Windows XP (NT5)
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.

1031 lines
32 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000 - 2000
  5. //
  6. // File: snapinpersistence.cpp
  7. //
  8. // Contents:
  9. //
  10. // Classes: CComponentPersistor, CDPersistor
  11. //
  12. //____________________________________________________________________________
  13. #include "stdafx.h"
  14. #include "mtnode.h"
  15. #include "regutil.h"
  16. /*+-------------------------------------------------------------------------*
  17. *
  18. * struct less_component
  19. *
  20. * PURPOSE: implements viewID and CLSID based comparison for CComponent* pointers
  21. * This allows to sort components before pesisting
  22. *+-------------------------------------------------------------------------*/
  23. struct less_component // define the struct to perform the comparison
  24. {
  25. typedef std::pair<int, CComponent*> comp_type;
  26. bool operator ()(const comp_type& arg1, const comp_type& arg2) const
  27. {
  28. return arg1.first != arg2.first ? arg1.first < arg2.first :
  29. arg1.second->GetCLSID() < arg2.second->GetCLSID();
  30. }
  31. };
  32. /*+-------------------------------------------------------------------------*
  33. *
  34. * struct less_compdata
  35. *
  36. * PURPOSE: implements CLSID based comparison for CComponentData* pointers
  37. * This allows to sort component data before pesisting
  38. *+-------------------------------------------------------------------------*/
  39. struct less_compdata // define the struct to perform the comparison
  40. {
  41. bool operator ()(const CComponentData* pCD1, const CComponentData* pCD2) const
  42. {
  43. return pCD1->GetCLSID() < pCD2->GetCLSID();
  44. }
  45. };
  46. /***************************************************************************\
  47. *
  48. * METHOD: CMTSnapinNodeStreamsAndStorages::ScGetXmlStorage
  49. *
  50. * PURPOSE: gets CXML_IStorage for snapin. creates & inits one there is none
  51. *
  52. * PARAMETERS:
  53. * int idView [in] view number
  54. * const CLSID& clsid [in] CLSID identifying the snapin
  55. * CXML_IStorage *& pXMLStorage [out] xml storage for the snapin
  56. *
  57. * RETURNS:
  58. * SC - result code
  59. *
  60. \***************************************************************************/
  61. SC CMTSnapinNodeStreamsAndStorages::ScGetXmlStorage(int idView, const CLSID& clsid, CXML_IStorage *& pXMLStorage)
  62. {
  63. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScGetXmlStorage"));
  64. // init out parameter
  65. pXMLStorage = NULL;
  66. // try to find it first
  67. bool bFound = false;
  68. sc = ScFindXmlStorage( idView, clsid, bFound, pXMLStorage );
  69. if (sc)
  70. return sc;
  71. if (bFound)
  72. {
  73. // recheck
  74. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  75. if (sc)
  76. return sc;
  77. // return the ponter we found
  78. return sc;
  79. }
  80. // insert the new one
  81. typedef std::map<key_t, CXML_IStorage> col_t;
  82. col_t::iterator it = m_XMLStorage.insert(col_t::value_type( key_t( idView, clsid ), CXML_IStorage())).first;
  83. pXMLStorage = &it->second;
  84. // recheck
  85. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  86. if (sc)
  87. return sc;
  88. return sc;
  89. }
  90. /***************************************************************************\
  91. *
  92. * METHOD: CMTSnapinNodeStreamsAndStorages::ScFindXmlStorage
  93. *
  94. * PURPOSE: Finds the storage.
  95. *
  96. * PARAMETERS:
  97. * int idView [in] view number
  98. * const CLSID& clsid [in] CLSID identifying the snapin
  99. * bool& bFound [out] whether data was found
  100. * CXML_IStorage *& pXMLStorage [out] pointer to found data
  101. *
  102. * RETURNS:
  103. * SC - result code
  104. *
  105. \***************************************************************************/
  106. SC CMTSnapinNodeStreamsAndStorages::
  107. ScFindXmlStorage(int idView, const CLSID& clsid, bool& bFound, CXML_IStorage *& pXMLStorage)
  108. {
  109. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScFindXmlStorage"));
  110. // init out parameters
  111. bFound = false;
  112. pXMLStorage = NULL;
  113. typedef std::map<key_t, CXML_IStorage> col_t;
  114. col_t::iterator it = m_XMLStorage.find( key_t( idView, clsid ) );
  115. // give a try to find it by the hash value
  116. if ( it == m_XMLStorage.end() )
  117. {
  118. bool bFoundInHash = false;
  119. sc = ScCheckForStreamsAndStoragesByHashValue( idView, clsid, bFoundInHash );
  120. if (sc)
  121. return sc;
  122. if ( !bFoundInHash ) // if not found - return
  123. return sc;
  124. // try again - it may be in the map by now
  125. it = m_XMLStorage.find( key_t( idView, clsid ) );
  126. if ( it == m_XMLStorage.end() ) // if still not found - return
  127. return sc;
  128. }
  129. // found!
  130. bFound = true;
  131. pXMLStorage = &it->second;
  132. #ifdef DBG // set the snapin name to identify the problems in debug
  133. tstring strSnapin;
  134. GetSnapinNameFromCLSID( clsid, strSnapin );
  135. pXMLStorage->m_dbg_Data.SetTraceInfo(TraceSnapinPersistenceError, true, strSnapin);
  136. #endif // #ifdef DBG
  137. return sc;
  138. }
  139. /***************************************************************************\
  140. *
  141. * METHOD: CMTSnapinNodeStreamsAndStorages::ScFindXmlStream
  142. *
  143. * PURPOSE: Finds the stream.
  144. *
  145. * PARAMETERS:
  146. * int idView [in] view number
  147. * const CLSID& clsid [in] CLSID identifying the snapin
  148. * bool& bFound [out] whether data was found
  149. * CXML_IStream *& pXMLStream [out] pointer to found data
  150. *
  151. * RETURNS:
  152. * SC - result code
  153. *
  154. \***************************************************************************/
  155. SC CMTSnapinNodeStreamsAndStorages::
  156. ScFindXmlStream(int idView, const CLSID& clsid, bool& bFound, CXML_IStream *& pXMLStream)
  157. {
  158. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScFindXmlStream"));
  159. // init out parameters
  160. bFound = false;
  161. pXMLStream = NULL;
  162. typedef std::map<key_t, CXML_IStream> col_t;
  163. col_t::iterator it = m_XMLStream.find( key_t( idView, clsid ) );
  164. // give a try to find it by the hash value
  165. if ( it == m_XMLStream.end() )
  166. {
  167. bool bFoundInHash = false;
  168. sc = ScCheckForStreamsAndStoragesByHashValue( idView, clsid, bFoundInHash );
  169. if (sc)
  170. return sc;
  171. if ( !bFoundInHash ) // if not found - return
  172. return sc;
  173. // try again - it may be in the map by now
  174. it = m_XMLStream.find( key_t( idView, clsid ) );
  175. if ( it == m_XMLStream.end() ) // if still not found - return
  176. return sc;
  177. }
  178. // found!
  179. bFound = true;
  180. pXMLStream = &it->second;
  181. #ifdef DBG // set the snapin name to identify the problems in debug
  182. tstring strSnapin;
  183. GetSnapinNameFromCLSID( clsid, strSnapin );
  184. pXMLStream->m_dbg_Data.SetTraceInfo(TraceSnapinPersistenceError, true, strSnapin);
  185. #endif // #ifdef DBG
  186. return sc;
  187. }
  188. /***************************************************************************\
  189. *
  190. * METHOD: CMTSnapinNodeStreamsAndStorages::ScGetXmlStream
  191. *
  192. * PURPOSE:
  193. *
  194. * PARAMETERS:
  195. * int idView [in] view number
  196. * const CLSID& clsid [in] CLSID identifying the snapin
  197. * CXML_IStream *& pXMLStream [out] xml stream for the snapin
  198. *
  199. * RETURNS:
  200. * SC - result code
  201. *
  202. \***************************************************************************/
  203. SC CMTSnapinNodeStreamsAndStorages::ScGetXmlStream(int idView, const CLSID& clsid, CXML_IStream *& pXMLStream)
  204. {
  205. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScGetXmlStream"));
  206. // init out parameter
  207. pXMLStream = NULL;
  208. // try to find it first
  209. bool bFound = false;
  210. sc = ScFindXmlStream( idView, clsid, bFound, pXMLStream );
  211. if (sc)
  212. return sc;
  213. if (bFound)
  214. {
  215. // recheck
  216. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  217. if (sc)
  218. return sc;
  219. // return the ponter we found
  220. return sc;
  221. }
  222. // insert the new one
  223. typedef std::map<key_t, CXML_IStream> col_t;
  224. col_t::iterator it = m_XMLStream.insert(col_t::value_type( key_t( idView, clsid ), CXML_IStream())).first;
  225. pXMLStream = &it->second;
  226. // recheck
  227. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  228. if (sc)
  229. return sc;
  230. return sc;
  231. }
  232. /***************************************************************************\
  233. *
  234. * METHOD: CMTSnapinNodeStreamsAndStorages::ScInitIStorage
  235. *
  236. * PURPOSE: Initializes IStorage from the given source data
  237. *
  238. * PARAMETERS:
  239. * int idView [in] view number
  240. * LPCWSTR szHash [in] hash key (name of storage element) identifying the snapin
  241. * IStorage *pSource [in] source data for initialization
  242. *
  243. * RETURNS:
  244. * SC - result code
  245. *
  246. \***************************************************************************/
  247. SC CMTSnapinNodeStreamsAndStorages::ScInitIStorage( int idView, LPCWSTR szHash, IStorage *pSource )
  248. {
  249. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScInitIStorage"));
  250. // parameter check;
  251. sc = ScCheckPointers( pSource );
  252. if (sc)
  253. return sc;
  254. // insert the new one
  255. typedef std::map<hash_t, CXML_IStorage> col_t;
  256. col_t::iterator it = m_StorageByHash.insert( col_t::value_type(hash_t(idView, szHash), CXML_IStorage())).first;
  257. CXML_IStorage *pXMLStorage = &it->second;
  258. // recheck the pointer
  259. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  260. if (sc)
  261. return sc;
  262. sc = pXMLStorage->ScInitializeFrom( pSource );
  263. if (sc)
  264. return sc;
  265. return sc;
  266. }
  267. /***************************************************************************\
  268. *
  269. * METHOD: CMTSnapinNodeStreamsAndStorages::ScInitIStream
  270. *
  271. * PURPOSE: Initializes IStream from the given source data
  272. *
  273. * PARAMETERS:
  274. * int idView [in] view number
  275. * LPCWSTR szHash [in] hash key (name of storage element) identifying the snapin
  276. * IStream *pSource [in] source data for initialization
  277. *
  278. * RETURNS:
  279. * SC - result code
  280. *
  281. \***************************************************************************/
  282. SC CMTSnapinNodeStreamsAndStorages::ScInitIStream ( int idView, LPCWSTR szHash, IStream *pSource )
  283. {
  284. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScInitIStream"));
  285. // parameter check;
  286. sc = ScCheckPointers( pSource );
  287. if (sc)
  288. return sc;
  289. // insert the new one
  290. typedef std::map<hash_t, CXML_IStream> col_t;
  291. col_t::iterator it = m_StreamByHash.insert( col_t::value_type(hash_t(idView, szHash), CXML_IStream())).first;
  292. CXML_IStream *pXMLStream = &it->second;
  293. // recheck the pointer
  294. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  295. if (sc)
  296. return sc;
  297. sc = pXMLStream->ScInitializeFrom( pSource );
  298. if (sc)
  299. return sc;
  300. return sc;
  301. }
  302. /***************************************************************************\
  303. *
  304. * METHOD: CMTSnapinNodeStreamsAndStorages::ScGetIStorage
  305. *
  306. * PURPOSE: returns existing or creates a new IStorage for the component
  307. *
  308. * PARAMETERS:
  309. * int idView [in] view number
  310. * const CLSID& clsid [in] CLSID identifying the snapin
  311. * IStorage **ppStorage [out] - storage for the component
  312. *
  313. * RETURNS:
  314. * SC - result code
  315. *
  316. \***************************************************************************/
  317. SC CMTSnapinNodeStreamsAndStorages::ScGetIStorage( int idView, const CLSID& clsid, IStorage **ppStorage )
  318. {
  319. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScGetIStorage"));
  320. // paramter check
  321. sc = ScCheckPointers( ppStorage );
  322. if (sc)
  323. return sc;
  324. // init an out parameter
  325. *ppStorage = NULL;
  326. CXML_IStorage *pXMLStorage = NULL;
  327. sc = ScGetXmlStorage( idView, clsid, pXMLStorage );
  328. if (sc)
  329. return sc;
  330. // recheck the pointer
  331. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  332. if (sc)
  333. return sc;
  334. // get the interface
  335. sc = pXMLStorage->ScGetIStorage(ppStorage);
  336. if (sc)
  337. return sc;
  338. return sc;
  339. }
  340. /***************************************************************************\
  341. *
  342. * METHOD: CMTSnapinNodeStreamsAndStorages::ScGetIStream
  343. *
  344. * PURPOSE: returns existing or creates a new IStream for the component
  345. *
  346. * PARAMETERS:
  347. * int idView [in] view number
  348. * const CLSID& clsid [in] CLSID identifying the snapin
  349. * IStream **ppStream [out] - stream fro the component
  350. *
  351. * RETURNS:
  352. * SC - result code
  353. *
  354. \***************************************************************************/
  355. SC CMTSnapinNodeStreamsAndStorages::ScGetIStream ( int idView, const CLSID& clsid, IStream **ppStream )
  356. {
  357. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScGetIStream"));
  358. // paramter check
  359. sc = ScCheckPointers( ppStream );
  360. if (sc)
  361. return sc;
  362. // init an out parameter
  363. *ppStream = NULL;
  364. CXML_IStream *pXMLStream = NULL;
  365. sc = ScGetXmlStream( idView, clsid, pXMLStream );
  366. if (sc)
  367. return sc;
  368. // recheck the pointer
  369. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  370. if (sc)
  371. return sc;
  372. // get the interface
  373. sc = pXMLStream->ScGetIStream(ppStream);
  374. if (sc)
  375. return sc;
  376. return sc;
  377. }
  378. /***************************************************************************\
  379. *
  380. * METHOD: CMTSnapinNodeStreamsAndStorages::HasStream
  381. *
  382. * PURPOSE: Checks if snapins stream is available
  383. *
  384. * PARAMETERS:
  385. * int idView [in] view number
  386. * const CLSID& clsid [in] CLSID identifying the snapin
  387. *
  388. * RETURNS:
  389. * bool - true == found
  390. *
  391. \***************************************************************************/
  392. bool CMTSnapinNodeStreamsAndStorages::HasStream(int idView, const CLSID& clsid)
  393. {
  394. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::HasStream"));
  395. bool bFound = false;
  396. CXML_IStream * pUnused = NULL;
  397. sc = ScFindXmlStream( idView, clsid, bFound, pUnused );
  398. if (sc)
  399. return false; // not found if error
  400. return bFound;
  401. }
  402. /***************************************************************************\
  403. *
  404. * METHOD: CMTSnapinNodeStreamsAndStorages::HasStorage
  405. *
  406. * PURPOSE: Checks if snapins storage is available
  407. *
  408. * PARAMETERS:
  409. * int idView [in] view number
  410. * const CLSID& clsid [in] CLSID identifying the snapin
  411. *
  412. * RETURNS:
  413. * bool - true == found
  414. *
  415. \***************************************************************************/
  416. bool CMTSnapinNodeStreamsAndStorages::HasStorage(int idView, const CLSID& clsid)
  417. {
  418. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::HasStorage"));
  419. bool bFound = false;
  420. CXML_IStorage * pUnused = NULL;
  421. sc = ScFindXmlStorage( idView, clsid, bFound, pUnused );
  422. if (sc)
  423. return false; // not found if error
  424. return bFound;
  425. }
  426. /***************************************************************************\
  427. *
  428. * METHOD: CMTSnapinNodeStreamsAndStorages::ScCheckForStreamsAndStoragesByHashValue
  429. *
  430. * PURPOSE: Looks up streams and storages by a generated hash value.
  431. * if the streams/storages are found, they are moved to the
  432. * the list of 'recognized' storages - those identified by the CLSID.
  433. * This is a required step to recognize the streams and storages retrieved
  434. * from a structured storage based console, where they are identified by the
  435. * hash value. It is not possible to map from the hash value to the key
  436. * in unique way, so the collections of data are kept untill the request
  437. * comes and the hash can be mapped by matching with the one generated from
  438. * the key supplied by request.
  439. *
  440. * PARAMETERS:
  441. * int idView [in] view number
  442. * const CLSID& clsid [in] CLSID identifying the snapin
  443. * bool& bFound [out] - true if at least one matching hash value was found
  444. *
  445. * RETURNS:
  446. * SC - result code
  447. *
  448. \***************************************************************************/
  449. SC CMTSnapinNodeStreamsAndStorages::ScCheckForStreamsAndStoragesByHashValue( int idView, const CLSID& clsid, bool& bFound )
  450. {
  451. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::ScCheckForStreamsAndStoragesByHashValue"));
  452. bFound = false;
  453. wchar_t buff[MAX_PATH];
  454. std::wstring strHashValue = CMTNode::GetComponentStreamName( buff, clsid );
  455. // process streams
  456. {
  457. typedef std::map<hash_t, CXML_IStream> col_t;
  458. col_t::iterator it = m_StreamByHash.begin();
  459. while ( it != m_StreamByHash.end() )
  460. {
  461. if ( it->first.second == strHashValue )
  462. {
  463. bFound = true;
  464. // put to a 'recognized' list
  465. int idView = it->first.first;
  466. m_XMLStream[key_t(idView, clsid)] = it->second;
  467. // for sanity: make sure it is not in the storage map!
  468. ASSERT( m_StorageByHash.find(it->first) == m_StorageByHash.end() );
  469. m_StorageByHash.erase( it->first );
  470. // remove from hash table
  471. it = m_StreamByHash.erase( it );
  472. }
  473. else
  474. ++ it;
  475. }
  476. if ( bFound )
  477. return sc;
  478. }
  479. // process storages
  480. {
  481. typedef std::map<hash_t, CXML_IStorage> col_t;
  482. col_t::iterator it = m_StorageByHash.begin();
  483. while ( it != m_StorageByHash.end() )
  484. {
  485. if ( it->first.second == strHashValue )
  486. {
  487. bFound = true;
  488. // put to a 'recognized' list
  489. int idView = it->first.first;
  490. m_XMLStorage[key_t(idView, clsid)] = it->second;
  491. // for sanity: make sure it is not in the stream map!
  492. ASSERT( m_StreamByHash.find( it->first ) == m_StreamByHash.end() );
  493. m_StreamByHash.erase( it->first );
  494. // remove from hash table
  495. it = m_StorageByHash.erase( it );
  496. }
  497. else
  498. ++it;
  499. }
  500. }
  501. return sc;
  502. }
  503. /*+-------------------------------------------------------------------------*
  504. *
  505. * CMTSnapinNodeStreamsAndStorages::RemoveView
  506. *
  507. * PURPOSE: removes information about one view
  508. *
  509. * PARAMETERS:
  510. * int idView [in] view number
  511. *
  512. * RETURNS:
  513. * void
  514. *
  515. *+-------------------------------------------------------------------------*/
  516. void CMTSnapinNodeStreamsAndStorages::RemoveView(int nViewId)
  517. {
  518. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::RemoveView"));
  519. { // remove streams
  520. std::map<key_t, CXML_IStream>::iterator it_stream;
  521. for (it_stream = m_XMLStream.begin();it_stream != m_XMLStream.end();)
  522. {
  523. if (it_stream->first.first == nViewId)
  524. it_stream = m_XMLStream.erase(it_stream);
  525. else
  526. ++it_stream;
  527. }
  528. }
  529. { // remove storages
  530. std::map<key_t, CXML_IStorage>::iterator it_storage;
  531. for (it_storage = m_XMLStorage.begin();it_storage != m_XMLStorage.end();)
  532. {
  533. if (it_storage->first.first == nViewId)
  534. it_storage = m_XMLStorage.erase(it_storage);
  535. else
  536. ++it_storage;
  537. }
  538. }
  539. { // remove streams by hash
  540. std::map<hash_t, CXML_IStream>::iterator it_stream;
  541. for (it_stream = m_StreamByHash.begin();it_stream != m_StreamByHash.end();)
  542. {
  543. if (it_stream->first.first == nViewId)
  544. it_stream = m_StreamByHash.erase(it_stream);
  545. else
  546. ++it_stream;
  547. }
  548. }
  549. { // remove storages by hash
  550. std::map<hash_t, CXML_IStorage>::iterator it_storage;
  551. for (it_storage = m_StorageByHash.begin();it_storage != m_StorageByHash.end();)
  552. {
  553. if (it_storage->first.first == nViewId)
  554. it_storage = m_StorageByHash.erase(it_storage);
  555. else
  556. ++it_storage;
  557. }
  558. }
  559. }
  560. /***************************************************************************\
  561. *
  562. * METHOD: CMTSnapinNodeStreamsAndStorages::Persist
  563. *
  564. * PURPOSE: persists stream and storage collections
  565. *
  566. * PARAMETERS:
  567. * CPersistor& persistor [in] peristor for the operation
  568. * bool bPersistViewId [in] whether to store view identifier
  569. * (ComponentDatas are saved with thi parameter set to false,
  570. * since the view id has no meaning for them)
  571. *
  572. * RETURNS:
  573. * SC - result code
  574. *
  575. \***************************************************************************/
  576. void CMTSnapinNodeStreamsAndStorages::Persist(CPersistor& persistor, bool bPersistViewId)
  577. {
  578. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::Persist"));
  579. if (persistor.IsStoring())
  580. {
  581. // define iterators for saving
  582. std::map<key_t, CXML_IStorage>::iterator itStorages;
  583. std::map<key_t, CXML_IStream>::iterator itStreams;
  584. std::map<hash_t, CXML_IStorage>::iterator itStoragesByHash;
  585. std::map<hash_t, CXML_IStream>::iterator itStreamsByHash;
  586. // init iterators to point to the start of the collections
  587. itStorages = m_XMLStorage.begin();
  588. itStreams = m_XMLStream.begin();
  589. itStoragesByHash = m_StorageByHash.begin();
  590. itStreamsByHash = m_StreamByHash.begin();
  591. // we have 4 collections to save here.
  592. // while saving them one by one would not change the functionality,
  593. // console file is more readable when they are sorted by the snapin's clsid.
  594. // following code does not do any explicit sorting, but persist in the
  595. // certain order assurring the result is a sorted array of persisted data
  596. // These 4 iterators represents 4 lines (queues) of sorted items, so
  597. // in order to get the proper result we just need to merge them correctly.
  598. // This is done by the following loop which splits the persistence in two steps:
  599. // 1. Pick the right line (iterator) to persist it's first item.
  600. // 2. Persist the selected item.
  601. // There are 4 boolean variables indicating which item to save (only one can be 'true')
  602. // thus the second part is strigth-forward - test variables and do the persisting.
  603. // The iterator is picked by the following rules.
  604. // 1.1 Only lines with items compete.
  605. // 1.2 If there are items in lines key'ed by guids (in contrast to hash values)
  606. // they are processed first, leaving hash values at the end.
  607. // 1.3 If still there are 2 lines competing - their key's are compared and one
  608. // with a smaller key is choosen
  609. while ( 1 )
  610. {
  611. // see what collection has data to save
  612. bool bSaveStorage = ( itStorages != m_XMLStorage.end() );
  613. bool bSaveStream = ( itStreams != m_XMLStream.end() );
  614. bool bSaveStorageByHash = ( itStoragesByHash != m_StorageByHash.end() );
  615. bool bSaveStreamByHash = ( itStreamsByHash != m_StreamByHash.end() );
  616. // exit if nothind to tsave - assume we are done
  617. if ( !( bSaveStorage || bSaveStream || bSaveStorageByHash || bSaveStreamByHash ))
  618. break;
  619. // if both main collections are willing to save - let the smaller key win
  620. if ( bSaveStorage && bSaveStream )
  621. {
  622. bSaveStorage = ( itStorages->first < itStreams->first );
  623. bSaveStream = !bSaveStorage;
  624. }
  625. // if not done with a main collections - dont save by hash
  626. if ( bSaveStorage || bSaveStream )
  627. bSaveStorageByHash = bSaveStreamByHash = false;
  628. // if both hash collections are willing to save - let the smaller key win
  629. if ( bSaveStorageByHash && bSaveStreamByHash )
  630. {
  631. bSaveStorageByHash = ( itStoragesByHash->first < itStreamsByHash->first );
  632. bSaveStreamByHash = !bSaveStorageByHash;
  633. }
  634. // only variable one can be set !
  635. ASSERT ( 1 == ( (int)bSaveStorage + (int)bSaveStream + (int)bSaveStorageByHash + (int)bSaveStreamByHash) );
  636. // add the tag for snapin entry
  637. CPersistor persistorChild(persistor, GetItemXMLType());
  638. // save one winning entry
  639. if ( bSaveStorage )
  640. {
  641. // persist a key
  642. CLSID clsid = itStorages->first.second;
  643. int idView = itStorages->first.first;
  644. persistorChild.Persist( clsid, XML_NAME_CLSID_SNAPIN );
  645. if (bPersistViewId)
  646. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  647. // persist data
  648. persistorChild.Persist( itStorages->second );
  649. // advance to the next entry
  650. ++itStorages;
  651. }
  652. else if (bSaveStream)
  653. {
  654. // persist a key
  655. CLSID clsid = itStreams->first.second;
  656. int idView = itStreams->first.first;
  657. persistorChild.Persist( clsid, XML_NAME_CLSID_SNAPIN );
  658. if (bPersistViewId)
  659. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  660. // persist data
  661. persistorChild.Persist( itStreams->second );
  662. // advance to the next entry
  663. ++itStreams;
  664. }
  665. else if ( bSaveStorageByHash )
  666. {
  667. // persist a key
  668. std::wstring hash = itStoragesByHash->first.second;
  669. int idView = itStoragesByHash->first.first;
  670. if (bPersistViewId)
  671. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  672. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  673. persistorHash.PersistContents( hash );
  674. // persist data
  675. persistorChild.Persist( itStoragesByHash->second );
  676. // advance to the next entry
  677. ++itStoragesByHash;
  678. }
  679. else if (bSaveStreamByHash)
  680. {
  681. // persist a key
  682. std::wstring hash = itStreamsByHash->first.second;
  683. int idView = itStreamsByHash->first.first;
  684. if (bPersistViewId)
  685. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  686. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  687. persistorHash.PersistContents( hash );
  688. // persist data
  689. persistorChild.Persist( itStreamsByHash->second );
  690. // advance to the next entry
  691. ++itStreamsByHash;
  692. }
  693. else
  694. {
  695. ASSERT( false ); // should not come here!
  696. break;
  697. }
  698. }
  699. }
  700. else
  701. {
  702. XMLListCollectionBase::Persist(persistor);
  703. }
  704. }
  705. /*+-------------------------------------------------------------------------*
  706. *
  707. * CMTSnapinNodeStreamsAndStorages::OnNewElement
  708. *
  709. * PURPOSE: called for each component data found loading XML doc
  710. *
  711. * PARAMETERS:
  712. * CPersistor& persistor :
  713. *
  714. * RETURNS:
  715. * void
  716. *
  717. *+-------------------------------------------------------------------------*/
  718. void CMTSnapinNodeStreamsAndStorages::OnNewElement(CPersistor& persistor)
  719. {
  720. DECLARE_SC(sc, TEXT("CDPersistor::OnNewElement"));
  721. // persistor is 'locked' on particular child element, so that
  722. // a simple CPersistor constructor can be used to create child's peristor.
  723. // Creating the child persistor is also necessary to release that 'lock'
  724. CPersistor persistorChild(persistor, GetItemXMLType());
  725. CLSID clsid;
  726. std::wstring hash;
  727. bool bByHash = false;
  728. ZeroMemory(&clsid,sizeof(clsid));
  729. // look how entry is key'ed - by regular key of by a hash value
  730. if ( persistorChild.HasElement( XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN ) )
  731. {
  732. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  733. persistorHash.PersistContents( hash );
  734. bByHash = true;
  735. }
  736. else
  737. persistorChild.Persist(clsid, XML_NAME_CLSID_SNAPIN);
  738. // persist the view id - default to value used to store component data
  739. int idView = VIEW_ID_DOCUMENT;
  740. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView, attr_optional);
  741. // now we should look what data do we have
  742. // and persist if recognized
  743. if (persistorChild.HasElement(CXML_IStream::_GetXMLType(),NULL))
  744. {
  745. CXML_IStream *pXMLStream = NULL;
  746. if (bByHash)
  747. {
  748. pXMLStream = &m_StreamByHash[ hash_t(idView, hash) ];
  749. }
  750. else
  751. {
  752. sc = ScGetXmlStream( idView, clsid, pXMLStream );
  753. if (sc)
  754. sc.Throw();
  755. }
  756. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  757. if (sc)
  758. sc.Throw();
  759. persistorChild.Persist( *pXMLStream );
  760. }
  761. else if (persistorChild.HasElement(CXML_IStorage::_GetXMLType(),NULL))
  762. {
  763. CXML_IStorage *pXMLStorage = NULL;
  764. if (bByHash)
  765. {
  766. pXMLStorage = &m_StorageByHash[ hash_t(idView, hash) ];
  767. }
  768. else
  769. {
  770. sc = ScGetXmlStorage( idView, clsid, pXMLStorage );
  771. if (sc)
  772. sc.Throw();
  773. }
  774. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  775. if (sc)
  776. sc.Throw();
  777. persistorChild.Persist( *pXMLStorage );
  778. }
  779. }
  780. /*+-------------------------------------------------------------------------*
  781. *+-------------------------------------------------------------------------*
  782. *+-------------------------------------------------------------------------*
  783. *+-------------------------------------------------------------------------*/
  784. /*+-------------------------------------------------------------------------*
  785. *
  786. * CComponentPersistor::Persist
  787. *
  788. * PURPOSE: persists IComponent collection related to snapin ( and its extensions)
  789. *
  790. * PARAMETERS:
  791. * CPersistor &persistor :
  792. *
  793. * RETURNS:
  794. * void
  795. *
  796. *+-------------------------------------------------------------------------*/
  797. void CComponentPersistor::Persist(CPersistor &persistor)
  798. {
  799. DECLARE_SC(sc, TEXT("CComponentPersistor::Persist"));
  800. // let the base class do the job
  801. BC::Persist( persistor, true /*bPersistViewId*/ );
  802. }
  803. /***************************************************************************\
  804. *
  805. * METHOD: CComponentPersistor::ScReset
  806. *
  807. * PURPOSE: Restores component xml streams/storages into "Just loaded" state
  808. *
  809. * PARAMETERS:
  810. *
  811. * RETURNS:
  812. * SC - result code
  813. *
  814. \***************************************************************************/
  815. SC CComponentPersistor::ScReset()
  816. {
  817. DECLARE_SC(sc, TEXT("CComponentPersistor::ScReset"));
  818. // save contents to string
  819. std::wstring strContents;
  820. sc = ScSaveToString(&strContents);
  821. if (sc)
  822. return sc;
  823. // cleanup (anything not saved should go away)
  824. m_XMLStorage.clear();
  825. m_XMLStream.clear();
  826. // load from string
  827. sc = ScLoadFromString(strContents.c_str());
  828. if (sc)
  829. return sc;
  830. return sc;
  831. }
  832. //############################################################################
  833. //############################################################################
  834. /*+-------------------------------------------------------------------------*
  835. *
  836. * CDPersistor::Persist
  837. *
  838. * PURPOSE: persists collection of component datas
  839. *
  840. * PARAMETERS:
  841. * CPersistor& persistor :
  842. *
  843. * RETURNS:
  844. * void
  845. *
  846. *+-------------------------------------------------------------------------*/
  847. void CDPersistor::Persist(CPersistor& persistor)
  848. {
  849. DECLARE_SC(sc, TEXT("CDPersistor::Persist"));
  850. // let the base class do the job
  851. BC::Persist( persistor, false /*bPersistViewId*/ );
  852. }
  853. /***************************************************************************\
  854. *
  855. * METHOD: CDPersistor::ScReset
  856. *
  857. * PURPOSE: Restores component data xml streams/storages into "Just loaded" state
  858. *
  859. * PARAMETERS:
  860. *
  861. * RETURNS:
  862. * SC - result code
  863. *
  864. \***************************************************************************/
  865. SC CDPersistor::ScReset()
  866. {
  867. DECLARE_SC(sc, TEXT("CDPersistor::ScReset"));
  868. // save contents to string
  869. std::wstring strContents;
  870. sc = ScSaveToString(&strContents);
  871. if (sc)
  872. return sc;
  873. // cleanup (anything not saved should go away)
  874. m_XMLStorage.clear();
  875. m_XMLStream.clear();
  876. // load from string
  877. sc = ScLoadFromString(strContents.c_str());
  878. if (sc)
  879. return sc;
  880. return sc;
  881. }