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.

1035 lines
33 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. sc = CMTNode::ScGetComponentStreamName( buff, countof(buff), clsid );
  455. if(sc)
  456. return sc;
  457. std::wstring strHashValue = buff;
  458. // process streams
  459. {
  460. typedef std::map<hash_t, CXML_IStream> col_t;
  461. col_t::iterator it = m_StreamByHash.begin();
  462. while ( it != m_StreamByHash.end() )
  463. {
  464. if ( it->first.second == strHashValue )
  465. {
  466. bFound = true;
  467. // put to a 'recognized' list
  468. int idView = it->first.first;
  469. m_XMLStream[key_t(idView, clsid)] = it->second;
  470. // for sanity: make sure it is not in the storage map!
  471. ASSERT( m_StorageByHash.find(it->first) == m_StorageByHash.end() );
  472. m_StorageByHash.erase( it->first );
  473. // remove from hash table
  474. it = m_StreamByHash.erase( it );
  475. }
  476. else
  477. ++ it;
  478. }
  479. if ( bFound )
  480. return sc;
  481. }
  482. // process storages
  483. {
  484. typedef std::map<hash_t, CXML_IStorage> col_t;
  485. col_t::iterator it = m_StorageByHash.begin();
  486. while ( it != m_StorageByHash.end() )
  487. {
  488. if ( it->first.second == strHashValue )
  489. {
  490. bFound = true;
  491. // put to a 'recognized' list
  492. int idView = it->first.first;
  493. m_XMLStorage[key_t(idView, clsid)] = it->second;
  494. // for sanity: make sure it is not in the stream map!
  495. ASSERT( m_StreamByHash.find( it->first ) == m_StreamByHash.end() );
  496. m_StreamByHash.erase( it->first );
  497. // remove from hash table
  498. it = m_StorageByHash.erase( it );
  499. }
  500. else
  501. ++it;
  502. }
  503. }
  504. return sc;
  505. }
  506. /*+-------------------------------------------------------------------------*
  507. *
  508. * CMTSnapinNodeStreamsAndStorages::RemoveView
  509. *
  510. * PURPOSE: removes information about one view
  511. *
  512. * PARAMETERS:
  513. * int idView [in] view number
  514. *
  515. * RETURNS:
  516. * void
  517. *
  518. *+-------------------------------------------------------------------------*/
  519. void CMTSnapinNodeStreamsAndStorages::RemoveView(int nViewId)
  520. {
  521. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::RemoveView"));
  522. { // remove streams
  523. std::map<key_t, CXML_IStream>::iterator it_stream;
  524. for (it_stream = m_XMLStream.begin();it_stream != m_XMLStream.end();)
  525. {
  526. if (it_stream->first.first == nViewId)
  527. it_stream = m_XMLStream.erase(it_stream);
  528. else
  529. ++it_stream;
  530. }
  531. }
  532. { // remove storages
  533. std::map<key_t, CXML_IStorage>::iterator it_storage;
  534. for (it_storage = m_XMLStorage.begin();it_storage != m_XMLStorage.end();)
  535. {
  536. if (it_storage->first.first == nViewId)
  537. it_storage = m_XMLStorage.erase(it_storage);
  538. else
  539. ++it_storage;
  540. }
  541. }
  542. { // remove streams by hash
  543. std::map<hash_t, CXML_IStream>::iterator it_stream;
  544. for (it_stream = m_StreamByHash.begin();it_stream != m_StreamByHash.end();)
  545. {
  546. if (it_stream->first.first == nViewId)
  547. it_stream = m_StreamByHash.erase(it_stream);
  548. else
  549. ++it_stream;
  550. }
  551. }
  552. { // remove storages by hash
  553. std::map<hash_t, CXML_IStorage>::iterator it_storage;
  554. for (it_storage = m_StorageByHash.begin();it_storage != m_StorageByHash.end();)
  555. {
  556. if (it_storage->first.first == nViewId)
  557. it_storage = m_StorageByHash.erase(it_storage);
  558. else
  559. ++it_storage;
  560. }
  561. }
  562. }
  563. /***************************************************************************\
  564. *
  565. * METHOD: CMTSnapinNodeStreamsAndStorages::Persist
  566. *
  567. * PURPOSE: persists stream and storage collections
  568. *
  569. * PARAMETERS:
  570. * CPersistor& persistor [in] peristor for the operation
  571. * bool bPersistViewId [in] whether to store view identifier
  572. * (ComponentDatas are saved with thi parameter set to false,
  573. * since the view id has no meaning for them)
  574. *
  575. * RETURNS:
  576. * SC - result code
  577. *
  578. \***************************************************************************/
  579. void CMTSnapinNodeStreamsAndStorages::Persist(CPersistor& persistor, bool bPersistViewId)
  580. {
  581. DECLARE_SC(sc, TEXT("CMTSnapinNodeStreamsAndStorages::Persist"));
  582. if (persistor.IsStoring())
  583. {
  584. // define iterators for saving
  585. std::map<key_t, CXML_IStorage>::iterator itStorages;
  586. std::map<key_t, CXML_IStream>::iterator itStreams;
  587. std::map<hash_t, CXML_IStorage>::iterator itStoragesByHash;
  588. std::map<hash_t, CXML_IStream>::iterator itStreamsByHash;
  589. // init iterators to point to the start of the collections
  590. itStorages = m_XMLStorage.begin();
  591. itStreams = m_XMLStream.begin();
  592. itStoragesByHash = m_StorageByHash.begin();
  593. itStreamsByHash = m_StreamByHash.begin();
  594. // we have 4 collections to save here.
  595. // while saving them one by one would not change the functionality,
  596. // console file is more readable when they are sorted by the snapin's clsid.
  597. // following code does not do any explicit sorting, but persist in the
  598. // certain order assurring the result is a sorted array of persisted data
  599. // These 4 iterators represents 4 lines (queues) of sorted items, so
  600. // in order to get the proper result we just need to merge them correctly.
  601. // This is done by the following loop which splits the persistence in two steps:
  602. // 1. Pick the right line (iterator) to persist it's first item.
  603. // 2. Persist the selected item.
  604. // There are 4 boolean variables indicating which item to save (only one can be 'true')
  605. // thus the second part is strigth-forward - test variables and do the persisting.
  606. // The iterator is picked by the following rules.
  607. // 1.1 Only lines with items compete.
  608. // 1.2 If there are items in lines key'ed by guids (in contrast to hash values)
  609. // they are processed first, leaving hash values at the end.
  610. // 1.3 If still there are 2 lines competing - their key's are compared and one
  611. // with a smaller key is choosen
  612. while ( 1 )
  613. {
  614. // see what collection has data to save
  615. bool bSaveStorage = ( itStorages != m_XMLStorage.end() );
  616. bool bSaveStream = ( itStreams != m_XMLStream.end() );
  617. bool bSaveStorageByHash = ( itStoragesByHash != m_StorageByHash.end() );
  618. bool bSaveStreamByHash = ( itStreamsByHash != m_StreamByHash.end() );
  619. // exit if nothind to tsave - assume we are done
  620. if ( !( bSaveStorage || bSaveStream || bSaveStorageByHash || bSaveStreamByHash ))
  621. break;
  622. // if both main collections are willing to save - let the smaller key win
  623. if ( bSaveStorage && bSaveStream )
  624. {
  625. bSaveStorage = ( itStorages->first < itStreams->first );
  626. bSaveStream = !bSaveStorage;
  627. }
  628. // if not done with a main collections - dont save by hash
  629. if ( bSaveStorage || bSaveStream )
  630. bSaveStorageByHash = bSaveStreamByHash = false;
  631. // if both hash collections are willing to save - let the smaller key win
  632. if ( bSaveStorageByHash && bSaveStreamByHash )
  633. {
  634. bSaveStorageByHash = ( itStoragesByHash->first < itStreamsByHash->first );
  635. bSaveStreamByHash = !bSaveStorageByHash;
  636. }
  637. // only variable one can be set !
  638. ASSERT ( 1 == ( (int)bSaveStorage + (int)bSaveStream + (int)bSaveStorageByHash + (int)bSaveStreamByHash) );
  639. // add the tag for snapin entry
  640. CPersistor persistorChild(persistor, GetItemXMLType());
  641. // save one winning entry
  642. if ( bSaveStorage )
  643. {
  644. // persist a key
  645. CLSID clsid = itStorages->first.second;
  646. int idView = itStorages->first.first;
  647. persistorChild.Persist( clsid, XML_NAME_CLSID_SNAPIN );
  648. if (bPersistViewId)
  649. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  650. // persist data
  651. persistorChild.Persist( itStorages->second );
  652. // advance to the next entry
  653. ++itStorages;
  654. }
  655. else if (bSaveStream)
  656. {
  657. // persist a key
  658. CLSID clsid = itStreams->first.second;
  659. int idView = itStreams->first.first;
  660. persistorChild.Persist( clsid, XML_NAME_CLSID_SNAPIN );
  661. if (bPersistViewId)
  662. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  663. // persist data
  664. persistorChild.Persist( itStreams->second );
  665. // advance to the next entry
  666. ++itStreams;
  667. }
  668. else if ( bSaveStorageByHash )
  669. {
  670. // persist a key
  671. std::wstring hash = itStoragesByHash->first.second;
  672. int idView = itStoragesByHash->first.first;
  673. if (bPersistViewId)
  674. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  675. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  676. persistorHash.PersistContents( hash );
  677. // persist data
  678. persistorChild.Persist( itStoragesByHash->second );
  679. // advance to the next entry
  680. ++itStoragesByHash;
  681. }
  682. else if (bSaveStreamByHash)
  683. {
  684. // persist a key
  685. std::wstring hash = itStreamsByHash->first.second;
  686. int idView = itStreamsByHash->first.first;
  687. if (bPersistViewId)
  688. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView);
  689. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  690. persistorHash.PersistContents( hash );
  691. // persist data
  692. persistorChild.Persist( itStreamsByHash->second );
  693. // advance to the next entry
  694. ++itStreamsByHash;
  695. }
  696. else
  697. {
  698. ASSERT( false ); // should not come here!
  699. break;
  700. }
  701. }
  702. }
  703. else
  704. {
  705. XMLListCollectionBase::Persist(persistor);
  706. }
  707. }
  708. /*+-------------------------------------------------------------------------*
  709. *
  710. * CMTSnapinNodeStreamsAndStorages::OnNewElement
  711. *
  712. * PURPOSE: called for each component data found loading XML doc
  713. *
  714. * PARAMETERS:
  715. * CPersistor& persistor :
  716. *
  717. * RETURNS:
  718. * void
  719. *
  720. *+-------------------------------------------------------------------------*/
  721. void CMTSnapinNodeStreamsAndStorages::OnNewElement(CPersistor& persistor)
  722. {
  723. DECLARE_SC(sc, TEXT("CDPersistor::OnNewElement"));
  724. // persistor is 'locked' on particular child element, so that
  725. // a simple CPersistor constructor can be used to create child's peristor.
  726. // Creating the child persistor is also necessary to release that 'lock'
  727. CPersistor persistorChild(persistor, GetItemXMLType());
  728. CLSID clsid;
  729. std::wstring hash;
  730. bool bByHash = false;
  731. ZeroMemory(&clsid,sizeof(clsid));
  732. // look how entry is key'ed - by regular key of by a hash value
  733. if ( persistorChild.HasElement( XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN ) )
  734. {
  735. CPersistor persistorHash( persistorChild, XML_TAG_HASH_VALUE, XML_NAME_CLSID_SNAPIN);
  736. persistorHash.PersistContents( hash );
  737. bByHash = true;
  738. }
  739. else
  740. persistorChild.Persist(clsid, XML_NAME_CLSID_SNAPIN);
  741. // persist the view id - default to value used to store component data
  742. int idView = VIEW_ID_DOCUMENT;
  743. persistorChild.PersistAttribute(XML_ATTR_ICOMPONENT_VIEW_ID, idView, attr_optional);
  744. // now we should look what data do we have
  745. // and persist if recognized
  746. if (persistorChild.HasElement(CXML_IStream::_GetXMLType(),NULL))
  747. {
  748. CXML_IStream *pXMLStream = NULL;
  749. if (bByHash)
  750. {
  751. pXMLStream = &m_StreamByHash[ hash_t(idView, hash) ];
  752. }
  753. else
  754. {
  755. sc = ScGetXmlStream( idView, clsid, pXMLStream );
  756. if (sc)
  757. sc.Throw();
  758. }
  759. sc = ScCheckPointers( pXMLStream, E_UNEXPECTED );
  760. if (sc)
  761. sc.Throw();
  762. persistorChild.Persist( *pXMLStream );
  763. }
  764. else if (persistorChild.HasElement(CXML_IStorage::_GetXMLType(),NULL))
  765. {
  766. CXML_IStorage *pXMLStorage = NULL;
  767. if (bByHash)
  768. {
  769. pXMLStorage = &m_StorageByHash[ hash_t(idView, hash) ];
  770. }
  771. else
  772. {
  773. sc = ScGetXmlStorage( idView, clsid, pXMLStorage );
  774. if (sc)
  775. sc.Throw();
  776. }
  777. sc = ScCheckPointers( pXMLStorage, E_UNEXPECTED );
  778. if (sc)
  779. sc.Throw();
  780. persistorChild.Persist( *pXMLStorage );
  781. }
  782. }
  783. /*+-------------------------------------------------------------------------*
  784. *+-------------------------------------------------------------------------*
  785. *+-------------------------------------------------------------------------*
  786. *+-------------------------------------------------------------------------*/
  787. /*+-------------------------------------------------------------------------*
  788. *
  789. * CComponentPersistor::Persist
  790. *
  791. * PURPOSE: persists IComponent collection related to snapin ( and its extensions)
  792. *
  793. * PARAMETERS:
  794. * CPersistor &persistor :
  795. *
  796. * RETURNS:
  797. * void
  798. *
  799. *+-------------------------------------------------------------------------*/
  800. void CComponentPersistor::Persist(CPersistor &persistor)
  801. {
  802. DECLARE_SC(sc, TEXT("CComponentPersistor::Persist"));
  803. // let the base class do the job
  804. BC::Persist( persistor, true /*bPersistViewId*/ );
  805. }
  806. /***************************************************************************\
  807. *
  808. * METHOD: CComponentPersistor::ScReset
  809. *
  810. * PURPOSE: Restores component xml streams/storages into "Just loaded" state
  811. *
  812. * PARAMETERS:
  813. *
  814. * RETURNS:
  815. * SC - result code
  816. *
  817. \***************************************************************************/
  818. SC CComponentPersistor::ScReset()
  819. {
  820. DECLARE_SC(sc, TEXT("CComponentPersistor::ScReset"));
  821. // save contents to string
  822. std::wstring strContents;
  823. sc = ScSaveToString(&strContents);
  824. if (sc)
  825. return sc;
  826. // cleanup (anything not saved should go away)
  827. m_XMLStorage.clear();
  828. m_XMLStream.clear();
  829. // load from string
  830. sc = ScLoadFromString(strContents.c_str());
  831. if (sc)
  832. return sc;
  833. return sc;
  834. }
  835. //############################################################################
  836. //############################################################################
  837. /*+-------------------------------------------------------------------------*
  838. *
  839. * CDPersistor::Persist
  840. *
  841. * PURPOSE: persists collection of component datas
  842. *
  843. * PARAMETERS:
  844. * CPersistor& persistor :
  845. *
  846. * RETURNS:
  847. * void
  848. *
  849. *+-------------------------------------------------------------------------*/
  850. void CDPersistor::Persist(CPersistor& persistor)
  851. {
  852. DECLARE_SC(sc, TEXT("CDPersistor::Persist"));
  853. // let the base class do the job
  854. BC::Persist( persistor, false /*bPersistViewId*/ );
  855. }
  856. /***************************************************************************\
  857. *
  858. * METHOD: CDPersistor::ScReset
  859. *
  860. * PURPOSE: Restores component data xml streams/storages into "Just loaded" state
  861. *
  862. * PARAMETERS:
  863. *
  864. * RETURNS:
  865. * SC - result code
  866. *
  867. \***************************************************************************/
  868. SC CDPersistor::ScReset()
  869. {
  870. DECLARE_SC(sc, TEXT("CDPersistor::ScReset"));
  871. // save contents to string
  872. std::wstring strContents;
  873. sc = ScSaveToString(&strContents);
  874. if (sc)
  875. return sc;
  876. // cleanup (anything not saved should go away)
  877. m_XMLStorage.clear();
  878. m_XMLStream.clear();
  879. // load from string
  880. sc = ScLoadFromString(strContents.c_str());
  881. if (sc)
  882. return sc;
  883. return sc;
  884. }