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.

2627 lines
90 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft OLE
  3. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  4. // All rights reserved.
  5. //
  6. // File: virtdf.cxx
  7. //
  8. // Contents: Implementation for in-memory Virtual Docfile class.
  9. //
  10. // Classes: VirtualDF
  11. //
  12. // Functions: VirtualDF (public)
  13. // ~VirtualDF (public)
  14. // GenerateVirtualDF (public)
  15. // DeleteVirtualDocFileTree (public)
  16. // GenerateVirtualDFRoot (protected)
  17. // GrowVirtualDFTree (protected)
  18. // DeleteVirtualDocFileSubTree (protected)
  19. // DeleteVirtualCtrNodeStreamTree (protected)
  20. // AppendVirtualStmNodesToVirtualCtrNode (protected)
  21. // AppendVirtualCtrNode (protected)
  22. // AppendVirtualStmNode (protected)
  23. // AdjustTreeOnStgMoveElement (public)
  24. // AdjustTreeOnStmMoveElement (public)
  25. // AdjustTreeOnStgCopyElement(public)
  26. // AdjustTreeOnStmCopyElement(public)
  27. // AdjustTreeOnCopyTo (public)
  28. // CopyVirtualDocFileTree (public)
  29. // CopyVirtualDFRooti (protected)
  30. // CopyGrowVirtualDFTree (protected)
  31. // CopyAppendVirtualStmNodesToVirtualCtrNode (protected)
  32. // CopyAppendVirtualCtrNode (protected)
  33. // CopyAppendVirtualStmNode (protected)
  34. // Associate (public)
  35. // DeleteVirtualCtrNodeStreamNode (public)
  36. // CommitCloseThenOpenDocfile (public)
  37. //
  38. // History: DeanE 21-Mar-96 Created
  39. // Narindk 22-Apr-96 Added more functions.
  40. // SCousens 2-Feb-97 Added for Cnvrs/NSS
  41. // SCousens 8-Apr-98 Handle stg collisions on createdf
  42. // georgis 2-Apr-98 Added support for large streams
  43. //--------------------------------------------------------------------------
  44. #include <dfheader.hxx>
  45. #pragma hdrstop
  46. // Debug object declaration
  47. DH_DECLARE;
  48. //+--------------------------------------------------------------------------
  49. // Member: VirtualDF::VirtualDF, public [multiple]
  50. //
  51. // Synopsis: Constructor. This method cannot fail.
  52. //
  53. // Arguments: None.
  54. //
  55. // Returns: Nothing.
  56. //
  57. // History: DeanE 21-Mar-96 Created
  58. // SCousens 2-Feb-97 Added for Cnvrs/NSS
  59. //---------------------------------------------------------------------------
  60. VirtualDF::VirtualDF() : _ptszName(NULL),
  61. _pvcnRoot(NULL),
  62. _pdgi(NULL),
  63. _pgdu(NULL),
  64. _ulSeed(0),
  65. _dwRootMode(0),
  66. _dwStgMode(0),
  67. _dwStmMode(0),
  68. _dwStgType(STGTYPE_DOCFILE),
  69. _pDBCSStrGen(NULL)
  70. {
  71. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::VirtualDF"));
  72. }
  73. //+--------------------------------------------------------------------------
  74. // Member: VirtualDF::VirtualDF, public [multiple]
  75. //
  76. // Synopsis: Constructor. This method cannot fail.
  77. //
  78. // Arguments: _fUseStgEx - whether to use the Ex apis
  79. //
  80. // Returns: Nothing.
  81. //
  82. // History: SCousens 4-Apr-97 Added for Cnvrs/NSS
  83. //---------------------------------------------------------------------------
  84. VirtualDF::VirtualDF(STGTYPE dwStgFmt) : _ptszName(NULL),
  85. _pvcnRoot(NULL),
  86. _pdgi(NULL),
  87. _pgdu(NULL),
  88. _ulSeed(0),
  89. _dwRootMode(0),
  90. _dwStgMode(0),
  91. _dwStmMode(0),
  92. _dwStgType(dwStgFmt),
  93. _pDBCSStrGen(NULL)
  94. {
  95. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::VirtualDF"));
  96. }
  97. //+--------------------------------------------------------------------------
  98. // Member: VirtualDF::~VirtualDF, public
  99. //
  100. // Synopsis: Destructor. Frees resources associated with this docfile.
  101. //
  102. // Arguments: None.
  103. //
  104. // Returns: Nothing.
  105. //
  106. // History: DeanE 21-Mar-96 Created
  107. //---------------------------------------------------------------------------
  108. VirtualDF::~VirtualDF()
  109. {
  110. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::~VirtualDF"));
  111. if(NULL != _pdgi)
  112. {
  113. delete _pdgi;
  114. _pdgi = NULL;
  115. }
  116. if(NULL != _pgdu)
  117. {
  118. delete _pgdu;
  119. _pgdu = NULL;
  120. }
  121. if(NULL != _ptszName)
  122. {
  123. delete _ptszName;
  124. _ptszName = NULL;
  125. }
  126. if(NULL != _pDBCSStrGen)
  127. {
  128. delete _pDBCSStrGen;
  129. _pDBCSStrGen = NULL;
  130. }
  131. }
  132. //----------------------------------------------------------------------------
  133. // Member: VirtualDF::GenerateVirtualDF, public
  134. //
  135. // Synopsis: Creates a VirtualDocFile tree consisting of VirtualCtrNode
  136. // node(s) and VirtualStmNodes(s) based on the ChanceDocFile
  137. // created prior to this.
  138. //
  139. // Arguments: [pChanceDF] - Pointer to ChanceDocFile tree
  140. // [ppvcnRoot] - Returned root of VirtualDocFile tree
  141. //
  142. // Returns: HRESULT
  143. //
  144. // History: Narindk 22-Apr-96 Created
  145. // SCousens 2-Feb-97 Added for Cnvrs/NSS
  146. //
  147. // Notes: This function calls GenerateVirtualDFRoot to generate Virtual
  148. // DF tree's root and GrowVirtualDFTree to generate rest of the
  149. // tree. If the function succeeds, it returns pointer to the root
  150. // of VirtualDocFile generated in ppvcnRoot parameter.
  151. // - Get seed from ChanceDocFile tree and construct DG_INTEGER &
  152. // DG_STRING objects.
  153. // - Get the modes for creating various storages/streams from thw
  154. // ChanceDocFile tree.
  155. // - Get name of rootdocfile, if given, from chancedocfile tree.
  156. // - Call GenerateVirtualDFRoot.
  157. // - Call GrowVirtualDFTree
  158. // - If successful, assign root of new VirtualDF in *ppvcnRoot.
  159. //---------------------------------------------------------------------------
  160. HRESULT VirtualDF::GenerateVirtualDF(
  161. ChanceDF *pChanceDF,
  162. VirtualCtrNode **ppvcnRoot)
  163. {
  164. HRESULT hr = S_OK;
  165. LPTSTR ptszName = NULL;
  166. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GenerateVirtualDF"));
  167. DH_VDATEPTRIN(pChanceDF, ChanceDF) ;
  168. DH_VDATEPTROUT(ppvcnRoot, PVCTRNODE) ;
  169. DH_ASSERT(NULL != pChanceDF);
  170. DH_ASSERT(NULL != ppvcnRoot);
  171. if(S_OK == hr)
  172. {
  173. *ppvcnRoot = NULL;
  174. // Create a DataGen obj of type DG_INTEGER that will allow us to fill
  175. // count parameters of VirtualDocFile tree components, excepting those
  176. // which we got from already created ChanceDocFile tree. Use the
  177. // same seed value as was used in creation of ChanceDocFile tree.
  178. // Get the value of seed used to create ChanceDocFile tree and store it.
  179. _ulSeed = pChanceDF->GetSeed();
  180. _pdgi = new(NullOnFail) DG_INTEGER(_ulSeed);
  181. if (NULL == _pdgi)
  182. {
  183. hr = E_OUTOFMEMORY;
  184. }
  185. }
  186. if(S_OK == hr)
  187. {
  188. // Create a new DataGen object to create random strings.
  189. _pgdu = new(NullOnFail) DG_STRING(_ulSeed);
  190. if (NULL == _pgdu)
  191. {
  192. hr = E_OUTOFMEMORY;
  193. }
  194. }
  195. if(S_OK == hr)
  196. {
  197. // Get the value of different creation modes.
  198. _dwRootMode = pChanceDF->GetRootMode();
  199. _dwStgMode = pChanceDF->GetStgMode();
  200. _dwStmMode = pChanceDF->GetStmMode();
  201. // Get user provided name for DocFile, if any
  202. ptszName = pChanceDF->GetDocFileName();
  203. if(NULL != ptszName)
  204. {
  205. _ptszName = new TCHAR[_tcslen(ptszName)+1];
  206. if (_ptszName == NULL)
  207. {
  208. hr = E_OUTOFMEMORY;
  209. }
  210. else
  211. {
  212. _tcscpy(_ptszName, ptszName);
  213. }
  214. }
  215. }
  216. if (S_OK == hr)
  217. {
  218. // Generates the root VirtualCtrNode for the VirtualDocFile tree.
  219. hr = GenerateVirtualDFRoot(pChanceDF->_pcnRoot);
  220. DH_HRCHECK(hr, TEXT("GenerateVirtualDFRoot")) ;
  221. }
  222. if (S_OK == hr)
  223. {
  224. // Generate remaining VirtualDF tree based on the ChanceDF tree.
  225. hr = GrowVirtualDFTree(pChanceDF->_pcnRoot, _pvcnRoot);
  226. DH_HRCHECK(hr, TEXT("GrowVirtualDFTree")) ;
  227. }
  228. // Fill the out parameter
  229. if(S_OK == hr)
  230. {
  231. *ppvcnRoot = _pvcnRoot;
  232. }
  233. return hr;
  234. }
  235. //----------------------------------------------------------------------------
  236. // Member: VirtualDF::GenerateVirtualDFRoot, protected
  237. //
  238. // Synopsis: Creates the root VirtualCtrNode for the VirtualDocFile tree.
  239. //
  240. // Arguments: [pcnRoot] - Pointer to root of ChanceDocFile tree
  241. //
  242. // Returns: HRESULT
  243. //
  244. // History: Narindk 22-Apr-96 Created
  245. // SCousens 2-Feb-97 Added for Cnvrs/NSS
  246. //
  247. // Notes: - Generate a random name for RootDocFile if it is not provided
  248. // in the test.
  249. // - Creates VirtualCtrNode object and initializes it with info
  250. // based on corresponding ChanceDocFile root.
  251. // - Create real IStorage corresponding to this VirtualCtrNode.
  252. // - Creates IStreams corresponding to this VirtualCtrNode, if
  253. // required.
  254. // - Calculates in memory CRC for this IStorage and assigns it
  255. // to _dwCRC variable.
  256. //---------------------------------------------------------------------------
  257. HRESULT VirtualDF::GenerateVirtualDFRoot(ChanceNode *pcnRoot)
  258. {
  259. HRESULT hr = S_OK;
  260. DH_VDATEPTRIN(pcnRoot, ChanceNode) ;
  261. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GenerateVirtualDFRoot"));
  262. DH_ASSERT(NULL != pcnRoot);
  263. if(S_OK == hr)
  264. {
  265. if(NULL == _ptszName)
  266. {
  267. // Create a random file name for this root.
  268. // Hack for FE DBCS systems
  269. _pDBCSStrGen = new(NullOnFail) CDBCSStringGen;
  270. if (NULL == _pDBCSStrGen)
  271. {
  272. hr = E_OUTOFMEMORY;
  273. }
  274. if(S_OK == hr)
  275. {
  276. hr = _pDBCSStrGen->Init(_ulSeed);
  277. }
  278. if((S_OK == hr) && (_pDBCSStrGen->SystemIsDBCS()))
  279. {
  280. hr = _pDBCSStrGen->GenerateRandomFileName(&_ptszName);
  281. if(S_OK != hr)
  282. {
  283. DH_TRACE((DH_LVL_TRACE1,
  284. TEXT("Unable to generate DBCS name. Fall back to GenerateRandomName")));
  285. hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &_ptszName);
  286. }
  287. }
  288. else
  289. {
  290. hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &_ptszName);
  291. }
  292. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  293. }
  294. }
  295. // Generate VirtualCtrNode for the root node.
  296. if(S_OK == hr)
  297. {
  298. _pvcnRoot = new VirtualCtrNode();
  299. if (NULL == _pvcnRoot)
  300. {
  301. hr = E_OUTOFMEMORY;
  302. }
  303. }
  304. if(S_OK == hr)
  305. {
  306. hr = _pvcnRoot->Init(
  307. _ptszName,
  308. pcnRoot->_cStorages,
  309. pcnRoot->_cStreams);
  310. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  311. }
  312. // Call VirtualCtrNode::CreateRoot to create a corresponding Root Storage
  313. // on disk.
  314. if(S_OK == hr)
  315. {
  316. if (STGTYPE_DOCFILE == _dwStgType)
  317. {
  318. hr = _pvcnRoot->CreateRoot(
  319. _dwRootMode | STGM_CREATE,
  320. 0);
  321. DH_HRCHECK(hr, TEXT("VirtualCtrNode::CreateRoot")) ;
  322. }
  323. else
  324. {
  325. hr = _pvcnRoot->CreateRootEx(
  326. _dwRootMode | STGM_CREATE,
  327. STGFMT_GENERIC,
  328. 0,
  329. NULL,
  330. NULL);
  331. DH_HRCHECK(hr, TEXT("VirtualCtrNode::CreateRootEx")) ;
  332. }
  333. // Generate VirtualStmNode(s) depending upon if root has streams in it.
  334. DH_ASSERT((pcnRoot->_cStreams) == (_pvcnRoot->_cStreams));
  335. }
  336. if ((S_OK == hr) && (0 != _pvcnRoot->_cStreams))
  337. {
  338. hr = AppendVirtualStmNodesToVirtualCtrNode(
  339. _pvcnRoot->_cStreams,
  340. _pvcnRoot,
  341. pcnRoot->_cbMinStream,
  342. pcnRoot->_cbMaxStream);
  343. DH_HRCHECK(hr, TEXT("AppendVirtualStmNodesToVirtualCtrNode")) ;
  344. }
  345. // Calculate the CRC for storage name
  346. if(S_OK == hr)
  347. {
  348. hr = CalculateInMemoryCRCForStg(_pvcnRoot, &(_pvcnRoot->_dwCRC));
  349. DH_HRCHECK(hr, TEXT("CalculateInMemoryCRCForStg")) ;
  350. }
  351. return hr;
  352. }
  353. //----------------------------------------------------------------------------
  354. // Member: VirtualDF::GrowVirtualDFTree, protected
  355. //
  356. // Synopsis: Creates the ramaining VirtualDocFile tree.
  357. //
  358. // Arguments: [pcnCurrent] - Pointer to current node of ChanceDocFile tree
  359. // [pvcnCurrent] - Pointer to current VirtualCtrNode
  360. //
  361. // Returns: HRESULT
  362. //
  363. // History: Narindk 13-Jun-96 Made into a new function
  364. //
  365. // Notes: The VirtualDocFile tree is created based on the corresponding
  366. // ChanceDocFile tree. This function is called either from the
  367. // GenerateVirtualDF function or may call itself recursively. The
  368. // ChanceDocFile tree is traversed from the top down, and based
  369. // on its contents, a VirtualDF tree is generated topdown.
  370. //
  371. // First assign the passed in ChanceNode to pcnCurrentChild and
  372. // passed in VirtualCtrNode to pvcnFisrtBorn variables.
  373. // Loop till pcnCurrentChild's _pcnChild is non NULL & hr is S_OK
  374. // - Call AppendVirtualCtrNode to create a new node pvcnNextBorn
  375. // based on info from corresponding ChanceDocFile node and
  376. // append it to pvcnFirstBorn in the tree being generated.
  377. // - Assign pcnCurrentChild's _pcnChild to pcnCurrentSister.
  378. // - Loop till pcnCurrentSister's _pcnSister is non NULL & hr=S_OK
  379. // - Call AppendVirtualCtrNode to create a new node pvcn
  380. // NextBornSister and append it to pvcnFirstBorn. Pl.
  381. // note that append function would take care to append
  382. // it to its older sister.
  383. // - Assign pcnCurrentSister's _pcnSister to variable
  384. // pcnCurrentSister.
  385. // - If pcnCurrentSister's _pcnChild is non NULL, then
  386. // make a recursive call to itself GrowVirtualDFTree.
  387. // - Reinitialize pvcnNextBornSister to NULL & go back to
  388. // top of this inner loop and repeat.
  389. // - Assign pvcnNextBorn to pvcnFirstBorn and reinitailize pvcn
  390. // NextBorn to NULL.
  391. // - Assign pcnCurrentChild's _pcnChild to pcnCurrentChild.
  392. // - Go to top of outer loop and repeat.
  393. //---------------------------------------------------------------------------
  394. HRESULT VirtualDF::GrowVirtualDFTree(
  395. ChanceNode *pcnCurrent,
  396. VirtualCtrNode *pvcnCurrent)
  397. {
  398. HRESULT hr = S_OK;
  399. VirtualCtrNode *pvcnFirstBorn = NULL;
  400. VirtualCtrNode *pvcnNextBorn = NULL;
  401. VirtualCtrNode *pvcnNextBornSister = NULL;
  402. ChanceNode *pcnCurrentSister = NULL;
  403. ChanceNode *pcnCurrentChild = NULL;
  404. DH_VDATEPTRIN(pcnCurrent, ChanceNode) ;
  405. DH_VDATEPTRIN(pvcnCurrent, VirtualCtrNode) ;
  406. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GrowVirtualDFTree"));
  407. DH_ASSERT(NULL != pcnCurrent);
  408. DH_ASSERT(NULL != pvcnCurrent);
  409. if(S_OK == hr)
  410. {
  411. pvcnFirstBorn = pvcnCurrent;
  412. pcnCurrentChild = pcnCurrent;
  413. }
  414. while((NULL != pcnCurrentChild->_pcnChild) && (S_OK == hr))
  415. {
  416. int x=10;
  417. do
  418. {
  419. hr = AppendVirtualCtrNode(
  420. pvcnFirstBorn,
  421. pcnCurrentChild->_pcnChild,
  422. &pvcnNextBorn);
  423. DH_HRCHECK(hr, TEXT("AppendVirtualCtrNode")) ;
  424. if (STG_E_FILEALREADYEXISTS == hr)
  425. {
  426. // delete the ctr node so we can try again.
  427. DeleteVirtualDocFileTree (pvcnNextBorn);
  428. // DeleteVirtualDocFileTree decrements the _cChildren,
  429. // but since no child was added in the first place,
  430. // restore it to its original value so we can try again.
  431. pvcnFirstBorn->_cChildren++;
  432. DH_TRACE ((DH_LVL_ALWAYS,
  433. TEXT("Above ERROR and ASSERT are OK.")));
  434. }
  435. } while (STG_E_FILEALREADYEXISTS == hr && --x);
  436. if(S_OK == hr)
  437. {
  438. pcnCurrentSister = pcnCurrentChild->_pcnChild;
  439. while((NULL != pcnCurrentSister->_pcnSister) && (S_OK == hr))
  440. {
  441. int x=10;
  442. do
  443. {
  444. hr = AppendVirtualCtrNode(
  445. pvcnFirstBorn,
  446. pcnCurrentSister->_pcnSister,
  447. &pvcnNextBornSister);
  448. DH_HRCHECK(hr, TEXT("AppendVirtualCtrNode")) ;
  449. if (STG_E_FILEALREADYEXISTS == hr)
  450. {
  451. // delete the ctr node so we can try again.
  452. DeleteVirtualDocFileTree (pvcnNextBornSister);
  453. // DeleteVirtualDocFileTree decrements the _cChildren,
  454. // but since no child was added in the first place,
  455. // restore it to its original value so we can try again.
  456. pvcnFirstBorn->_cChildren++;
  457. DH_TRACE ((DH_LVL_ALWAYS,
  458. TEXT("Above ERROR and ASSERT are OK.")));
  459. }
  460. } while (STG_E_FILEALREADYEXISTS == hr && --x);
  461. pcnCurrentSister = pcnCurrentSister->_pcnSister;
  462. // Check if there are any children of this sister node, if
  463. // yes, then make a recursive call to self.
  464. if(NULL != pcnCurrentSister->_pcnChild)
  465. {
  466. hr = GrowVirtualDFTree(
  467. pcnCurrentSister,
  468. pvcnNextBornSister);
  469. DH_HRCHECK(hr, TEXT("GrowVirtualDFTree"));
  470. }
  471. // Reinitialize the variables
  472. pvcnNextBornSister = NULL;
  473. }
  474. }
  475. pvcnFirstBorn = pvcnNextBorn;
  476. pvcnNextBorn = NULL;
  477. pcnCurrentChild = pcnCurrentChild->_pcnChild;
  478. }
  479. return hr;
  480. }
  481. //----------------------------------------------------------------------------
  482. // Member: VirtualDF::AppendVirtualCtrNode, protected
  483. //
  484. // Synopsis: Creates and appends VirtualCtrNode to VirtualDocFile tree
  485. // being created.
  486. //
  487. // Arguments: [pvcnParent] - Parent VirtualCtrNode for the new VirtualCtrNode
  488. // [pcnCurrent] - Corresponding ChanceNode in ChanceDocFile tree.
  489. // [ppvcnNew] - Pointer to pointer to new VirtualCtrNode to be
  490. // created.
  491. // Returns: HRESULT
  492. //
  493. // History: Narindk 23-Apr-96 Created
  494. //
  495. // Notes: - Generate a random name for VirtualCtrNode
  496. // - Creates VirtualCtrNode object and initializes it with info
  497. // based on corresponding ChanceDocFile node.
  498. // - Appends this node to the VirtualDF tree being generated.
  499. // - Create real IStorage corresponding to this VirtualCtrNode.
  500. // - Creates IStreams corresponding to this VirtualCtrNode, if
  501. // required.
  502. // - Calculates in memory CRC for this IStorage and assigns it
  503. // to _dwCRC variable.
  504. //---------------------------------------------------------------------------
  505. HRESULT VirtualDF::AppendVirtualCtrNode(
  506. VirtualCtrNode *pvcnParent,
  507. ChanceNode *pcnCurrent,
  508. VirtualCtrNode **ppvcnNew)
  509. {
  510. HRESULT hr = S_OK;
  511. LPTSTR ptcsName = NULL ;
  512. VirtualCtrNode *pvcnOldSister = NULL;
  513. DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ;
  514. DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ;
  515. DH_VDATEPTRIN(pcnCurrent, ChanceNode) ;
  516. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendVirtualCtrNode"));
  517. DH_ASSERT(NULL != pvcnParent);
  518. DH_ASSERT(NULL != ppvcnNew);
  519. DH_ASSERT(NULL != pcnCurrent);
  520. if(S_OK == hr)
  521. {
  522. *ppvcnNew = NULL;
  523. hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &ptcsName);
  524. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  525. }
  526. if(S_OK == hr)
  527. {
  528. // Allocate and Initialize new VirtualCtrNode
  529. *ppvcnNew = new VirtualCtrNode();
  530. if (NULL == *ppvcnNew)
  531. {
  532. hr = E_OUTOFMEMORY;
  533. }
  534. }
  535. if(S_OK == hr)
  536. {
  537. hr = (*ppvcnNew)->Init(
  538. ptcsName,
  539. pcnCurrent->_cStorages,
  540. pcnCurrent->_cStreams);
  541. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  542. }
  543. // Append new VirtualCtr Node
  544. if(S_OK == hr)
  545. {
  546. if(NULL == pvcnParent->_pvcnChild)
  547. {
  548. hr = pvcnParent->AppendChildCtr(*ppvcnNew);
  549. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ;
  550. }
  551. else
  552. {
  553. pvcnOldSister = pvcnParent->_pvcnChild;
  554. while(NULL != pvcnOldSister->_pvcnSister)
  555. {
  556. pvcnOldSister = pvcnOldSister->_pvcnSister;
  557. }
  558. hr = pvcnOldSister->AppendSisterCtr(*ppvcnNew);
  559. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ;
  560. }
  561. }
  562. // Call VirtualCtrNode::Create to create a corresponding Storage on disk.
  563. if(S_OK == hr)
  564. {
  565. hr = (*ppvcnNew)->Create(
  566. _dwStgMode | STGM_CREATE,
  567. 0,
  568. 0);
  569. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Create")) ;
  570. // Generate VirtualStmNode(s) depending upon if it has streams in it.
  571. DH_ASSERT((pcnCurrent->_cStreams) == ((*ppvcnNew)->_cStreams));
  572. }
  573. if ((S_OK == hr) && (0 != (*ppvcnNew)->_cStreams))
  574. {
  575. hr = AppendVirtualStmNodesToVirtualCtrNode(
  576. (*ppvcnNew)->_cStreams,
  577. *ppvcnNew,
  578. pcnCurrent->_cbMinStream,
  579. pcnCurrent->_cbMaxStream);
  580. DH_HRCHECK(hr, TEXT("AppendVirtualStmNodesToVirtualCtrNode")) ;
  581. }
  582. // Calculate the CRC for storage name
  583. if(S_OK == hr)
  584. {
  585. hr = CalculateInMemoryCRCForStg(*ppvcnNew, &((*ppvcnNew)->_dwCRC));
  586. DH_HRCHECK(hr, TEXT("CalculateInMemoryCRCForStg")) ;
  587. }
  588. // Cleanup
  589. if(NULL != ptcsName)
  590. {
  591. delete ptcsName;
  592. ptcsName = NULL;
  593. }
  594. return hr;
  595. }
  596. //----------------------------------------------------------------------------
  597. // Member: VirtualDF::AppendVirtualStmNodesToVirtualCtrNode, protected
  598. //
  599. // Synopsis: Creates and appends VirtualStmNode(s) to VirtualCtrNode
  600. //
  601. // Arguments: [cStreams] - Number of streams to be created
  602. // [pvcn] - Pointer to VirtualCtrNode for which the streams
  603. // need to be created and appended.
  604. // [cbMinStream] - Minimum size of created stream.
  605. // [cbMaxStream] - Maximum size of created stream.
  606. //
  607. // Returns: HRESULT
  608. //
  609. // History: Narindk 23-Apr-96 Created
  610. //
  611. // Notes: if number of streams to be created and appended to parent
  612. // VirtualCtrNode pvcn is not zero, then loop till cStreams is
  613. // not equal to zero.
  614. // - Call AppendVirtualStmNode to create a new VirtualStmNode
  615. // and append it to parent VirtualCtrNode. Pl. note that
  616. // this function would take care if the newly created node
  617. // need to be appended to older VirtualStmNode sister.
  618. // - Decrement cStreams and o back to top of loop & repeat.
  619. //---------------------------------------------------------------------------
  620. HRESULT VirtualDF::AppendVirtualStmNodesToVirtualCtrNode(
  621. ULONG cStreams,
  622. VirtualCtrNode *pvcn,
  623. ULONG cbMinStream,
  624. ULONG cbMaxStream)
  625. {
  626. HRESULT hr = S_OK;
  627. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  628. DH_FUNCENTRY(
  629. &hr,
  630. DH_LVL_DFLIB,
  631. _TEXT("::AppendVirtualStmNodesToVirtualCtrNode"));
  632. DH_ASSERT(0 != cStreams);
  633. DH_ASSERT(NULL != pvcn);
  634. while((S_OK == hr) && (0 != cStreams))
  635. {
  636. hr = AppendVirtualStmNode(
  637. pvcn,
  638. cbMinStream,
  639. cbMaxStream);
  640. DH_HRCHECK(hr, TEXT("AppendVirtualStmNode")) ;
  641. cStreams--;
  642. }
  643. return hr;
  644. }
  645. //----------------------------------------------------------------------------
  646. // Member: VirtualDF::AppendVirtualStmNode, protected
  647. //
  648. // Synopsis: Creates and appends first VirtualStmNode to VirtualCtrNode
  649. //
  650. // Arguments: [pvcnParent] - Pointer to VirtualCtrNode for which the streams
  651. // need to be created and appended.
  652. // [cbMinStream] - Minimum size of created stream.
  653. // [cbMaxStream] - Maximum size of created stream.
  654. //
  655. // Returns: HRESULT
  656. //
  657. // History: Narindk 23-Apr-96 Created
  658. // georgis 02-Apr-98 Added support for large streams
  659. //
  660. // Notes: - Generate a random name for VirtualStmNode
  661. // - Generates a random size for stream based on inforamtion
  662. // from corresponding ChanceDocFile tree node.
  663. // - Creates VirtualStmNode object and initializes it with above
  664. // info
  665. // - Appends this node to the parent VirtualCtrNode.
  666. // - Create real IStream corresponding to this VirtualStmNode.
  667. // - Set the size of stream based on size calculated above.
  668. // - Write into the stream random data of above size
  669. // - Calculates in memory CRC for this IStream and assigns it
  670. // to _dwCRC variable.
  671. //---------------------------------------------------------------------------
  672. HRESULT VirtualDF::AppendVirtualStmNode(
  673. VirtualCtrNode *pvcnParent,
  674. ULONG cbMinStream,
  675. ULONG cbMaxStream)
  676. {
  677. HRESULT hr = S_OK;
  678. VirtualStmNode *pvsnNew = NULL;
  679. VirtualStmNode *pvsnOldSister = NULL;
  680. ULONG cb = 0;
  681. USHORT usErr = 0;
  682. LPTSTR ptcsName = NULL ;
  683. BYTE *pBuffer = NULL ;
  684. ULONG culWritten = 0;
  685. ULARGE_INTEGER uli;
  686. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::AppendVirtualStmNode"));
  687. DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ;
  688. DH_ASSERT(NULL != pvcnParent);
  689. if (S_OK == hr)
  690. {
  691. hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &ptcsName);
  692. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  693. }
  694. if (S_OK == hr)
  695. {
  696. // Generate random size for stream.
  697. usErr = _pdgi->Generate(&cb, cbMinStream, cbMaxStream);
  698. if (DG_RC_SUCCESS != usErr)
  699. {
  700. hr = E_FAIL;
  701. }
  702. }
  703. // Allocate a new VirtualStmNode
  704. if (S_OK == hr)
  705. {
  706. pvsnNew = new VirtualStmNode();
  707. if (NULL == pvsnNew)
  708. {
  709. hr = E_OUTOFMEMORY;
  710. }
  711. }
  712. if(S_OK == hr)
  713. {
  714. hr = pvsnNew->Init(ptcsName, cb);
  715. DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ;
  716. }
  717. if(S_OK == hr)
  718. {
  719. if(NULL == pvcnParent->_pvsnStream)
  720. {
  721. // Append it to parent storage
  722. hr = pvcnParent->AppendFirstChildStm(pvsnNew);
  723. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ;
  724. }
  725. else
  726. {
  727. pvsnOldSister = pvcnParent->_pvsnStream;
  728. while(NULL != pvsnOldSister->_pvsnSister)
  729. {
  730. pvsnOldSister = pvsnOldSister->_pvsnSister;
  731. }
  732. // Append it to preceding sister stream
  733. hr = pvsnOldSister->AppendSisterStm(pvsnNew);
  734. DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ;
  735. }
  736. }
  737. // Call VirtualStmNode::Create to create a corresponding Stream on disk.
  738. if(S_OK == hr)
  739. {
  740. // Since in OLE code: simpstg.cxx, it makes the following comparison:
  741. // if (grfMode != (STGM_READWRITE | STGM_SHARE_EXCLUSIVE))
  742. // return STG_E_INVALIDFLAG;
  743. // We can't pass _dwStmMode | STGM_CREATE like in normal mode,
  744. // otherwise we will get STG_E_INVALIDFLAG error.
  745. if (_dwRootMode & STGM_SIMPLE)
  746. {
  747. hr = pvsnNew->Create(
  748. _dwStmMode | STGM_FAILIFTHERE,
  749. 0,
  750. 0);
  751. DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ;
  752. }
  753. else
  754. {
  755. hr = pvsnNew->Create(
  756. _dwStmMode | STGM_CREATE | STGM_FAILIFTHERE,
  757. 0,
  758. 0);
  759. DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ;
  760. }
  761. }
  762. // Call VirtualStmNode::SetSize to set size of stream.
  763. if(S_OK == hr)
  764. {
  765. ULISet32(uli, cb);
  766. hr = pvsnNew->SetSize(uli);
  767. DH_HRCHECK(hr, TEXT("VirtualStmNode::SetSize")) ;
  768. }
  769. if(S_OK == hr)
  770. {
  771. ULONG ulTotalWritten = 0;
  772. ULONG ulChunkSize =0;
  773. DWORD dwOffset=0;
  774. register DWORD dwCRC=CRC_PRECONDITION;
  775. #if 0
  776. // Use for small chunks
  777. hr = GenerateRandomName(_pgdu, STM_CHUNK_SIZE, STM_CHUNK_SIZE, (LPTSTR *) &pBuffer);
  778. DH_HRCHECK(hr, TEXT("GenerateRandomName"));
  779. #else
  780. // If the chunk is very large, avoid generating many random numbers
  781. hr = GenerateRandomStreamData(_pgdu,(LPTSTR *) &pBuffer,STM_CHUNK_SIZE);
  782. DH_HRCHECK(hr, TEXT("GenerateRandomStreamData"));
  783. #endif
  784. while ((S_OK == hr) && (ulTotalWritten < cb))
  785. {
  786. // Write the data from random offset to the end of the buffer
  787. _pdgi->Generate(&dwOffset,0,STM_CHUNK_SIZE-2);
  788. ulChunkSize=min(cb-ulTotalWritten,STM_CHUNK_SIZE-dwOffset);
  789. hr = pvsnNew->Write(pBuffer+dwOffset, ulChunkSize, &culWritten);
  790. DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ;
  791. if (S_OK == hr) // Skip if we are failing
  792. {
  793. ulTotalWritten+=culWritten;
  794. // Calculate the CRC now, to spare aditional Read
  795. for (register int i=0; i<culWritten; i++)
  796. {
  797. CRC_CALC(dwCRC,(BYTE) pBuffer[dwOffset+i])
  798. };
  799. }
  800. }
  801. // Update the vsnode created
  802. pvsnNew->_dwCRC.dwCRCData=dwCRC;
  803. hr=CalculateCRCForName(pvsnNew->_ptszName,&pvsnNew->_dwCRC.dwCRCName);
  804. DH_HRCHECK(hr, TEXT("CalculateCRCForName"));
  805. pvsnNew->_dwCRC.dwCRCSum=CRC_PRECONDITION;
  806. MUNGECRC(pvsnNew->_dwCRC.dwCRCSum,pvsnNew->_dwCRC.dwCRCData);
  807. MUNGECRC(pvsnNew->_dwCRC.dwCRCSum,pvsnNew->_dwCRC.dwCRCName);
  808. }
  809. // Since for simple mode docfile, access to streams follows a linear
  810. // pattern, it needs to close the current stream before creating and
  811. // open another stream. So for simple mode docfile, after the docfile
  812. // is created, all the elements are closed except the root storage.
  813. // For the normal mode docfile, after it is created, all the elements
  814. // are kept open.
  815. if ((S_OK == hr) && (_dwRootMode & STGM_SIMPLE))
  816. {
  817. hr = pvsnNew->Close();
  818. DH_HRCHECK(hr, TEXT("VirtualStmNode::Close")) ;
  819. }
  820. // Cleanup
  821. if(NULL != ptcsName)
  822. {
  823. delete ptcsName;
  824. ptcsName = NULL;
  825. }
  826. if(NULL != pBuffer)
  827. {
  828. delete pBuffer;
  829. pBuffer = NULL;
  830. }
  831. return hr;
  832. }
  833. //----------------------------------------------------------------------------
  834. // Member: VirtualDF::DeleteVirtualDocFileTree, public
  835. //
  836. // Synopsis: Deletes the VirtualDocFileTree from the passed in Virtual
  837. // CtrNode node down.
  838. //
  839. // Arguments: [pvcnTrav] - Pointer to VirtualCtrNode from which node
  840. // downwards, including itself, the tree would
  841. // be deleted.
  842. //
  843. // Returns: HRESULT
  844. //
  845. // History: Narindk 24-Apr-96 Created
  846. //
  847. // Notes: First step is to check if the whole tree needs to be deleted or
  848. // just a part of it. In case only a part of tree is to be
  849. // deleted, isolate the node from the remaining tree by readjusting
  850. // the pointers in the remaining tree. Then call the function
  851. // DeleteVirtualDocFileSubTree to delete the subtree. In case,
  852. // the complete tree needs to be deleted, we call the function
  853. // DeleteVirtualDocFileSubTree directly to delete the complete
  854. // tree.
  855. //---------------------------------------------------------------------------
  856. HRESULT VirtualDF::DeleteVirtualDocFileTree(VirtualCtrNode *pvcnTrav)
  857. {
  858. HRESULT hr = S_OK;
  859. VirtualCtrNode *pTempNode = NULL;
  860. DH_VDATEPTRIN(pvcnTrav, VirtualCtrNode) ;
  861. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualDocFileTree"));
  862. DH_ASSERT(NULL != pvcnTrav);
  863. if(S_OK == hr)
  864. {
  865. // This basically readjusts the pointers in the tree if the passed in
  866. // VirtualCtrNode is not the root of the VirtualDF tree.
  867. if(NULL != pvcnTrav->_pvcnParent)
  868. {
  869. // Decrease the _cChildren variable of the parent VirtualCtrNode.
  870. pvcnTrav->_pvcnParent->_cChildren--;
  871. // Find its previous node whose pointers need readjustment.
  872. pTempNode = pvcnTrav->_pvcnParent->_pvcnChild;
  873. while ((pvcnTrav != pvcnTrav->_pvcnParent->_pvcnChild) &&
  874. (pvcnTrav != pTempNode->_pvcnSister))
  875. {
  876. pTempNode = pTempNode->_pvcnSister;
  877. DH_ASSERT(NULL != pTempNode);
  878. }
  879. // Readjust the child pointer or sister pointer as the case may be.
  880. pvcnTrav->_pvcnParent->_pvcnChild = (pvcnTrav == pTempNode) ?
  881. pvcnTrav->_pvcnSister : pvcnTrav->_pvcnParent->_pvcnChild;
  882. pTempNode->_pvcnSister = pvcnTrav->_pvcnSister;
  883. }
  884. }
  885. if(S_OK == hr)
  886. {
  887. hr = DeleteVirtualDocFileSubTree(&pvcnTrav);
  888. DH_HRCHECK(hr, TEXT("DeleteVirtualDocFileSubTree")) ;
  889. }
  890. return hr;
  891. }
  892. //----------------------------------------------------------------------------
  893. // Member: VirtualDF::DeleteVirtualDocFileSubTree, protected
  894. //
  895. // Synopsis: Deletes iteratively all VirtualCtrNode nodes under and including// the passed in VirtualCtrNode and calls a function to delete
  896. // all VirtualStmNodes under the VirtualCtrNodes being deleted.
  897. //
  898. // Arguments: [**ppvcnTrav]- Pointer to pointer to VirtualCtrNode from
  899. // which node under, including itself, the tree
  900. // would be deleted.
  901. //
  902. // Returns: HRESULT
  903. //
  904. // History: Narindk 24-Apr-96 Created
  905. //
  906. // Notes: This function is called only through DeleteVirtualDocFileTree.
  907. //
  908. // Assign the passed in VirtualCtrNode to a variable pTempRoot.
  909. // NULL the pTempRoot's parent.
  910. // Loop till the pTempRoot is not NULL to delete tree iteratively.
  911. // - Assign pTempRoot to a temp variable pTempNode.
  912. // - Traverse the tree to make pTempNode point to last child
  913. // (_pvcnChild).
  914. // - Assign pTempNode's _pvcnParent to pTempRoot
  915. // - Assign the pTempRoot's _pvcnChild pointer to point to the
  916. // sister of pTempNode's _pvcnSister rather than to itself,
  917. // therby isolating itself.
  918. // - Decrement the _cChildren of pTempRoot (used to verify).
  919. // - Assign pTempNode's _pvcnSister to NULL.
  920. // - if pTempNode's _pvsnStream is not NULL, call function
  921. // DeleteVirtualCtrNodeStreamTree to delete all its Virtual
  922. // StmNodes.
  923. // - Assert to ensure the pTempNode's _cChildren and _cStreams
  924. // are zero before deleting it.
  925. // - Delete pTempNode.
  926. // - Go back to top of loop and repeat till all nodes are
  927. // deleted.
  928. //---------------------------------------------------------------------------
  929. HRESULT VirtualDF::DeleteVirtualDocFileSubTree(VirtualCtrNode **ppvcnTrav)
  930. {
  931. HRESULT hr = S_OK;
  932. VirtualCtrNode *pTempRoot = NULL;
  933. VirtualCtrNode *pTempNode = NULL;
  934. DH_VDATEPTRIN(ppvcnTrav, PVCTRNODE) ;
  935. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualDocFileSubTree"));
  936. DH_ASSERT(NULL != *ppvcnTrav);
  937. if(S_OK == hr)
  938. {
  939. pTempRoot = *ppvcnTrav;
  940. pTempRoot->_pvcnParent = NULL;
  941. // This iteratives deletes the VirtualCtrNode and everything under it.
  942. while(NULL != pTempRoot)
  943. {
  944. pTempNode = pTempRoot;
  945. while(NULL != pTempNode->_pvcnChild)
  946. {
  947. pTempNode = pTempNode->_pvcnChild;
  948. }
  949. pTempRoot = pTempNode->_pvcnParent;
  950. if(pTempRoot != NULL)
  951. {
  952. pTempRoot->_pvcnChild = pTempNode->_pvcnSister;
  953. // Decrease the children count, this would be used to verify
  954. // before deleting the VirtualCtrNode.
  955. pTempRoot->_cChildren--;
  956. }
  957. pTempNode->_pvcnSister = NULL;
  958. if(pTempNode->_pvsnStream != NULL)
  959. {
  960. hr = DeleteVirtualCtrNodeStreamTree(pTempNode);
  961. DH_HRCHECK(hr, TEXT("DeleteVirtualCtrNodeStreamTree")) ;
  962. }
  963. // Confirm before deleting that all its sub child storages and
  964. // streams have been deleted, assert if not.
  965. DH_ASSERT(0 == pTempNode->_cChildren);
  966. DH_ASSERT(0 == pTempNode->_cStreams);
  967. delete pTempNode;
  968. pTempNode = NULL;
  969. }
  970. }
  971. return hr;
  972. }
  973. //----------------------------------------------------------------------------
  974. // Member: VirtualDF::DeleteVirtualCtrNodeStreamTree, protected
  975. //
  976. // Synopsis: Deletes iteratively all VirtualStmNodes under the given
  977. // VirtualCtrNode.
  978. //
  979. // Arguments: [*pvcnTrav]- Pointer to VirtualCtrNode for which all streams
  980. // need to be deleted.
  981. //
  982. // Returns: HRESULT
  983. //
  984. // History: Narindk 24-Apr-96 Created
  985. //
  986. // Notes: Loop till pvcnTrav's _pvsnStream is not NULL
  987. // - Assign a temp variable pvsnTemp to point to _pvsnStream of
  988. // passed in VirtualCtrNode pvcnTrav.
  989. // - Assign pvcnTrav's _pvsnStream to point to pvsnTemp's _pvsn
  990. // Sister, thereby isolating the first VirtualStmNode.
  991. // - Decrease the _cStreams pf pvcnTrav (used to verify).
  992. // - Assign pvsnTemp's _pvsnSister to NULL.
  993. // - Delete pvsnTemp
  994. // - Go back to top of loop.
  995. //---------------------------------------------------------------------------
  996. HRESULT VirtualDF::DeleteVirtualCtrNodeStreamTree(VirtualCtrNode *pvcnTrav)
  997. {
  998. HRESULT hr = S_OK;
  999. VirtualStmNode *pvsnTemp = NULL;
  1000. DH_VDATEPTRIN(pvcnTrav, VirtualCtrNode) ;
  1001. DH_FUNCENTRY(&hr, DH_LVL_DFLIB,TEXT("::::DeleteVirtualCtrNodeStreamTree"));
  1002. DH_ASSERT(NULL != pvcnTrav);
  1003. if(S_OK == hr)
  1004. {
  1005. // This iteratively deletes all VirtualStmNodes.
  1006. while(NULL != pvcnTrav->_pvsnStream)
  1007. {
  1008. pvsnTemp = pvcnTrav->_pvsnStream;
  1009. pvcnTrav->_pvsnStream = pvsnTemp->_pvsnSister;
  1010. // Decrease the stream count. This would be used to verify before
  1011. // deleting the parent VirtualCtrNode.
  1012. pvcnTrav->_cStreams--;
  1013. // Delete the node.
  1014. pvsnTemp->_pvsnSister = NULL;
  1015. delete pvsnTemp;
  1016. pvsnTemp = NULL;
  1017. }
  1018. }
  1019. return hr;
  1020. }
  1021. //----------------------------------------------------------------------------
  1022. // Member: VirtualDF::AdjustTreeOnStgMoveElement, public
  1023. //
  1024. // Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
  1025. // as move is operated on a IStorage element
  1026. //
  1027. // Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved
  1028. // [pvcnTo] - Pointer to VirtualCtrNode moved to
  1029. //
  1030. // Returns: HRESULT
  1031. //
  1032. // History: Narindk 13-May-1996 Created
  1033. //
  1034. // Notes; Doesn't initialize the _pstg of moved tree elements
  1035. // as that would require opening of those moved storages/streams.
  1036. // This readjusts the tree by removing the moved element from
  1037. // its original position in tree & reinserting it in tree at its
  1038. // new destination. This function is not used when the root it
  1039. // self is moved, assert if root is being moved.
  1040. //
  1041. // 1. Decrease the pvcnFrom's _pvcnParent's _cChildren count
  1042. // indicating that pvcnFrom is being moved.
  1043. // 2. In the tree, find its previous node whose pointers would
  1044. // need readjustment. Find its older sister if it has one,
  1045. // adjust its _pvcnSister pointer. Or if the node being moved
  1046. // is _pvcnChild of its parent _pvcnParent, then adjust the
  1047. // _pvcnParent's _pvcnChild to _pvcnSister of node being moved.
  1048. // 3. NULL out pvcnFrom's _pvcnParent, _pvcnSister pointers thereby
  1049. // isolating this VirtualCtrNode. NULL out _pstg too since
  1050. // that would have been already move to by IStorage::MoveElement// To call prior to calling this function.
  1051. // 4. In destination node pvcnTo, check if it's _pvcnChild is NULL.
  1052. // if yes, then assign pvcnFrom to _pvcnTo's _pvcnChild. If it
  1053. // is not NULL, then traverse through its children to reach
  1054. // last _pvcnSister and assign pvcnFrom to that.
  1055. // 5. Assign pvcnFrom's _pvcnParent to be pvcnTo. Also increment
  1056. // pvcnTo's _cChildren count indicating the new VirtualCtrNode
  1057. // being moved here.
  1058. //---------------------------------------------------------------------------
  1059. HRESULT VirtualDF::AdjustTreeOnStgMoveElement(
  1060. VirtualCtrNode *pvcnFrom,
  1061. VirtualCtrNode *pvcnTo )
  1062. {
  1063. HRESULT hr = S_OK;
  1064. VirtualCtrNode *pTempNode = NULL;
  1065. VirtualCtrNode *pvcnTrav = NULL;
  1066. DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ;
  1067. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1068. DH_FUNCENTRY(
  1069. &hr,
  1070. DH_LVL_DFLIB,
  1071. _TEXT("::AdjustTreeOnStgMoveElement"));
  1072. DH_ASSERT(NULL != pvcnTo);
  1073. DH_ASSERT(NULL != pvcnFrom);
  1074. // Assert if this is the root that is being moved.
  1075. DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
  1076. if(S_OK == hr)
  1077. {
  1078. // Decrease the _cChildren variable of the parent VirtualCtrNode.
  1079. pvcnFrom->_pvcnParent->_cChildren--;
  1080. // Find its previous node whose pointers need readjustment.
  1081. pTempNode = pvcnFrom->_pvcnParent->_pvcnChild;
  1082. while ((pvcnFrom != pvcnFrom->_pvcnParent->_pvcnChild) &&
  1083. (pvcnFrom != pTempNode->_pvcnSister))
  1084. {
  1085. pTempNode = pTempNode->_pvcnSister;
  1086. DH_ASSERT(NULL != pTempNode);
  1087. }
  1088. // Readjust the child pointer or sister pointer as the case may be.
  1089. pvcnFrom->_pvcnParent->_pvcnChild = (pvcnFrom == pTempNode) ?
  1090. pvcnFrom->_pvcnSister : pvcnFrom->_pvcnParent->_pvcnChild;
  1091. pTempNode->_pvcnSister = pvcnFrom->_pvcnSister;
  1092. // NULL out its pointers
  1093. pvcnFrom->_pvcnParent = NULL;
  1094. pvcnFrom->_pvcnSister = NULL;
  1095. pvcnFrom->_pstg = NULL;
  1096. }
  1097. if(S_OK == hr)
  1098. {
  1099. if(NULL != pvcnTo->_pvcnChild)
  1100. {
  1101. pvcnTrav = pvcnTo->_pvcnChild;
  1102. while(NULL != pvcnTrav->_pvcnSister)
  1103. {
  1104. pvcnTrav = pvcnTrav->_pvcnSister;
  1105. }
  1106. pvcnTrav->_pvcnSister = pvcnFrom;
  1107. }
  1108. else
  1109. {
  1110. pvcnTo->_pvcnChild = pvcnFrom;
  1111. }
  1112. pvcnFrom->_pvcnParent = pvcnTo;
  1113. pvcnTo->_cChildren++;
  1114. }
  1115. // The storage was closed prior to its move. So do we need to reopen it
  1116. // from here now from moved destination.
  1117. return hr;
  1118. }
  1119. //----------------------------------------------------------------------------
  1120. // Member: VirtualDF::AdjustTreeOnStmMoveElement, public
  1121. //
  1122. // Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
  1123. // as move is operated on a IStream element
  1124. //
  1125. // Arguments: [pvsnFrom] - Pointer to VirtualStmNode to be moved
  1126. // [pvcnTo] - Pointer to VirtualCtrNode moved to
  1127. //
  1128. // Returns: HRESULT
  1129. //
  1130. // History: Narindk 9-July-1996 Created
  1131. //
  1132. // Notes; Doesn't initialize the _pstm of moved tree elements
  1133. // as that would require opening of the moved stream.
  1134. // This readjusts the tree by removing the moved element from
  1135. // its original position in tree & reinserting it in tree at its
  1136. // new destination.
  1137. //
  1138. // 1. Decrease the pvcnFrom's _pvcnParent's _cStreams count
  1139. // indicating that pvsnFrom is being moved.
  1140. // 2. In the tree, find its previous node whose pointers would
  1141. // need readjustment. Find its older sister if it has one,
  1142. // adjust its _pvsnSister pointer. Or if the node being moved
  1143. // is _pvsnStream of its parent _pvcnParent, then adjust the
  1144. // _pvcnParent's _pvsnStream to _pvsnSister of node being moved.
  1145. // 3. NULL out pvsnFrom's _pvcnParent, _pvsnSister pointers thereby
  1146. // isolating this VirtualStmNode. NULL out _pstm too since
  1147. // that would have been already move to by IStorage::MoveElement// To call prior to calling this function.
  1148. // 4. In destination node pvcnTo,check if it's _pvsnStream is NULL.
  1149. // if yes, then assign pvsnFrom to _pvcnTo's _pvcnStream. If it
  1150. // is not NULL, then traverse through its stream nodes to reach
  1151. // last _pvsnSister and assign pvsnFrom to that.
  1152. // 5. Assign pvsnFrom's _pvcnParent to be pvcnTo. Also increment
  1153. // pvcnTo's _cStreams count indicating the new VirtualStmNode
  1154. // being moved here.
  1155. //---------------------------------------------------------------------------
  1156. HRESULT VirtualDF::AdjustTreeOnStmMoveElement(
  1157. VirtualStmNode *pvsnFrom,
  1158. VirtualCtrNode *pvcnTo )
  1159. {
  1160. HRESULT hr = S_OK;
  1161. VirtualStmNode *pTempNode = NULL;
  1162. VirtualStmNode *pvsnTrav = NULL;
  1163. DH_VDATEPTRIN(pvsnFrom, VirtualStmNode) ;
  1164. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1165. DH_FUNCENTRY(
  1166. &hr,
  1167. DH_LVL_DFLIB,
  1168. _TEXT("::AdjustTreeOnStmMoveElement"));
  1169. DH_ASSERT(NULL != pvcnTo);
  1170. DH_ASSERT(NULL != pvsnFrom);
  1171. DH_ASSERT(NULL != pvsnFrom->_pvcnParent);
  1172. if(S_OK == hr)
  1173. {
  1174. // Decrease the _cStreams variable of the parent VirtualCtrNode.
  1175. pvsnFrom->_pvcnParent->_cStreams--;
  1176. // Find its previous node whose pointers need readjustment.
  1177. pTempNode = pvsnFrom->_pvcnParent->_pvsnStream;
  1178. while ((pvsnFrom != pvsnFrom->_pvcnParent->_pvsnStream) &&
  1179. (pvsnFrom != pTempNode->_pvsnSister))
  1180. {
  1181. pTempNode = pTempNode->_pvsnSister;
  1182. DH_ASSERT(NULL != pTempNode);
  1183. }
  1184. // Readjust the pointer(s) as the case may be.
  1185. pvsnFrom->_pvcnParent->_pvsnStream = (pvsnFrom == pTempNode) ?
  1186. pvsnFrom->_pvsnSister : pvsnFrom->_pvcnParent->_pvsnStream;
  1187. pTempNode->_pvsnSister = pvsnFrom->_pvsnSister;
  1188. // NULL out its pointers
  1189. pvsnFrom->_pvcnParent = NULL;
  1190. pvsnFrom->_pvsnSister = NULL;
  1191. pvsnFrom->_pstm = NULL;
  1192. }
  1193. if(S_OK == hr)
  1194. {
  1195. if(NULL != pvcnTo->_pvsnStream)
  1196. {
  1197. pvsnTrav = pvcnTo->_pvsnStream;
  1198. while(NULL != pvsnTrav->_pvsnSister)
  1199. {
  1200. pvsnTrav = pvsnTrav->_pvsnSister;
  1201. }
  1202. pvsnTrav->_pvsnSister = pvsnFrom;
  1203. }
  1204. else
  1205. {
  1206. pvcnTo->_pvsnStream = pvsnFrom;
  1207. }
  1208. pvsnFrom->_pvcnParent = pvcnTo;
  1209. pvcnTo->_cStreams++;
  1210. }
  1211. // The stream was closed prior to its move. So do we need to reopen it
  1212. // from here now from moved destination.
  1213. return hr;
  1214. }
  1215. //----------------------------------------------------------------------------
  1216. // Member: VirtualDF::AdjustTreeOnStgCopyElement, public
  1217. //
  1218. // Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
  1219. // as copy is operated on a IStorage element
  1220. //
  1221. // Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved as copy
  1222. // [pvcnTo] - Pointer to VirtualCtrNode moved to
  1223. //
  1224. // Returns: HRESULT
  1225. //
  1226. // History: Narindk 20-May-1996 Created
  1227. //
  1228. // Notes; Doesn't initialize the _pstg's/_pstm's of copied tree elements
  1229. // as that would require opening of those copied storages/streams.
  1230. // This readjusts the tree by inserting the copied element in tree
  1231. // at its new destination. This function is not used when the
  1232. // root itself is copied, assert if root is being moved.
  1233. //
  1234. // 1. Call CopyVirtualDocFileTree function to copy pvcnFrom to
  1235. // pvcnNew.
  1236. // 2. In destination node pvcnTo, check if it's _pvcnChild is NULL.
  1237. // if yes, then assign pvcnFrom to _pvcnTo's _pvcnChild. If it
  1238. // is not NULL, then traverse through its children to reach
  1239. // last _pvcnSister and assign pvcnFrom to that.
  1240. // 3. Assign pvcnFrom's _pvcnParent to be pvcnTo. Also increment
  1241. // pvcnTo's _cChildren count indicating the new VirtualCtrNode
  1242. // being copied here. Also assign pvcnNew's _pvcnSister to
  1243. // NULL.
  1244. //---------------------------------------------------------------------------
  1245. HRESULT VirtualDF::AdjustTreeOnStgCopyElement(
  1246. VirtualCtrNode *pvcnFrom,
  1247. VirtualCtrNode *pvcnTo )
  1248. {
  1249. HRESULT hr = S_OK;
  1250. VirtualCtrNode *pvcnTrav = NULL;
  1251. VirtualCtrNode *pvcnNew = NULL;
  1252. DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ;
  1253. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1254. DH_FUNCENTRY(
  1255. &hr,
  1256. DH_LVL_DFLIB,
  1257. _TEXT("::AdjustVirtualDocFileTreeOnStgCopyElement"));
  1258. DH_ASSERT(NULL != pvcnTo);
  1259. DH_ASSERT(NULL != pvcnFrom);
  1260. // Assert if this is the root that is being copied.
  1261. DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
  1262. if(S_OK == hr)
  1263. {
  1264. hr = CopyVirtualDocFileTree(pvcnFrom, NEW_STGSTM, &pvcnNew);
  1265. }
  1266. if(S_OK == hr)
  1267. {
  1268. if(NULL != pvcnTo->_pvcnChild)
  1269. {
  1270. pvcnTrav = pvcnTo->_pvcnChild;
  1271. while(NULL != pvcnTrav->_pvcnSister)
  1272. {
  1273. pvcnTrav = pvcnTrav->_pvcnSister;
  1274. }
  1275. pvcnTrav->_pvcnSister = pvcnNew;
  1276. }
  1277. else
  1278. {
  1279. pvcnTo->_pvcnChild = pvcnNew;
  1280. }
  1281. pvcnNew->_pvcnParent = pvcnTo;
  1282. pvcnTo->_cChildren++;
  1283. pvcnNew->_pvcnSister = NULL;
  1284. }
  1285. // The storage was closed prior to its copy. So do we need to open it
  1286. // now from copied destination. How about other _pstg / _pstm for
  1287. // copied tree?
  1288. return hr;
  1289. }
  1290. //----------------------------------------------------------------------------
  1291. // Member: VirtualDF::AdjustTreeOnStmCopyElement, public
  1292. //
  1293. // Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
  1294. // as copy is operated on a IStream element
  1295. //
  1296. // Arguments: [pvsnFrom] - Pointer to VirtualstmNode to be moved as copy
  1297. // [pvcnTo] - Pointer to VirtualCtrNode moved to
  1298. //
  1299. // Returns: HRESULT
  1300. //
  1301. // History: Narindk 9-July-1996 Created
  1302. //
  1303. // Notes; Doesn't initialize the _pstm of copied tree stream element
  1304. // as that would require opening of the copied stream.
  1305. // This readjusts the tree by inserting the copied element in tree
  1306. // at its new destination.
  1307. //
  1308. // 1. Copy the VirtualStmNode to be copied to a new VirtualStmNode.
  1309. // 2. In destination node pvcnTo,check if it's _pvsnStream is NULL.
  1310. // if yes, then assign pvsnFrom to _pvcnTo's _pvsnStream. If it
  1311. // is not NULL, then traverse through its streams to reach
  1312. // last _pvsnSister and assign pvsnFrom to that.
  1313. // 3. Assign pvsnFrom's _pvcnParent to be pvcnTo. Also increment
  1314. // pvcnTo's _cStreams count indicating the new VirtualStmNode
  1315. // being copied here.
  1316. //---------------------------------------------------------------------------
  1317. HRESULT VirtualDF::AdjustTreeOnStmCopyElement(
  1318. VirtualStmNode *pvsnFrom,
  1319. VirtualCtrNode *pvcnTo )
  1320. {
  1321. HRESULT hr = S_OK;
  1322. VirtualStmNode *pvsnTrav = NULL;
  1323. VirtualStmNode *pvsnNew = NULL;
  1324. DH_VDATEPTRIN(pvsnFrom, VirtualStmNode) ;
  1325. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1326. DH_FUNCENTRY(
  1327. &hr,
  1328. DH_LVL_DFLIB,
  1329. _TEXT("::AdjustVirtualDocFileTreeOnStmCopyElement"));
  1330. DH_ASSERT(NULL != pvcnTo);
  1331. DH_ASSERT(NULL != pvsnFrom);
  1332. // Copy the VirtualStmNode to be moved as copy
  1333. if (S_OK == hr)
  1334. {
  1335. pvsnNew = new VirtualStmNode();
  1336. if (NULL == pvsnNew)
  1337. {
  1338. hr = E_OUTOFMEMORY;
  1339. }
  1340. }
  1341. if(S_OK == hr)
  1342. {
  1343. pvsnNew->_dwCRC.dwCRCName = pvsnFrom->_dwCRC.dwCRCName;
  1344. pvsnNew->_dwCRC.dwCRCData = pvsnFrom->_dwCRC.dwCRCData;
  1345. pvsnNew->_dwCRC.dwCRCSum = pvsnFrom->_dwCRC.dwCRCSum;
  1346. hr = pvsnNew->Init(pvsnFrom->_ptszName, pvsnFrom->_cb);
  1347. DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ;
  1348. }
  1349. if(S_OK == hr)
  1350. {
  1351. if(NULL != pvcnTo->_pvsnStream)
  1352. {
  1353. pvsnTrav = pvcnTo->_pvsnStream;
  1354. while(NULL != pvsnTrav->_pvsnSister)
  1355. {
  1356. pvsnTrav = pvsnTrav->_pvsnSister;
  1357. }
  1358. pvsnTrav->_pvsnSister = pvsnNew;
  1359. }
  1360. else
  1361. {
  1362. pvcnTo->_pvsnStream = pvsnNew;
  1363. }
  1364. pvsnNew->_pvcnParent = pvcnTo;
  1365. pvcnTo->_cStreams++;
  1366. }
  1367. // The stream was closed prior to its copy. So do we need to open it
  1368. // now from copied destination.
  1369. return hr;
  1370. }
  1371. //----------------------------------------------------------------------------
  1372. // Member: VirtualDF::AdjustTreeOnCopyTo, public
  1373. //
  1374. // Synopsis: Adjusts the VirtualDocFileTree when IStorage::CopyTo
  1375. // is operated on a IStorage element
  1376. //
  1377. // Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved
  1378. // [pvcnTo] - Pointer to VirtualCtrNode moved to
  1379. //
  1380. // Returns: HRESULT
  1381. //
  1382. // History: Narindk 21-May-1996 Created
  1383. //
  1384. // Notes: This function differs from VirtualDF::AdjustTreeOnStgCopyEle
  1385. // ment bcause readjusts the tree in the lght that tree has to
  1386. // readjusted since an IStorage elemnt is moved as copy to desti-
  1387. // nation container by IStorage::MoveElementTo as copy. But here,
  1388. // we need to readjust the tree in the light thst the entire
  1389. // contents of an open IStorage object are copied into a dest
  1390. // by IStorage::CopyTo
  1391. //
  1392. // -Call CopyVirtualDocFileTree to copy everything under the node
  1393. // pvcnFrom, where IStorage::CopyTo source is to pvcnNew.
  1394. // -if pvcnNew has VirtualStmNode in it (_pvsnStream), then
  1395. // -Check if pvcnTo (dest) has _pvsnStream as NULL or not.
  1396. // -If not NULL, then loop to get to end of VirtualStm
  1397. // Nodes's _pvsnSister in the chain.
  1398. // -As appropriate, assign pvcnNew->_pvsnStream to the
  1399. // pvcnTo destination.
  1400. // -Adjust the _pvcnParent of pvcnNew->_pvsnStream to
  1401. // point to pvcnTo and increase _cStream member of
  1402. // pvcnTo node.
  1403. // -Assign a temp variable pvsnTemp to point to the pvcnNew
  1404. // ->_pvsnStream and then loop through to end of all
  1405. // sister VirtualStmNodes and make their _pvcnParent as
  1406. // pvcnTo and keep on incrementing _cStreams member of
  1407. // pvcnTo with each new VirtualStmNode traversed.
  1408. // -Now all VirtualStmNodes fro pvcnNew have been copied
  1409. // to pvcnTo, their destination.
  1410. // -Repeat same for any VirtualCtrNodes that pvcnNew may have.
  1411. // if pvcnNew has VirtualCtrNode in it (_pvcnChild), then
  1412. // -Check if pvcnTo (dest) has _pvcnChild as NULL or not.
  1413. // -If not NULL, then loop to get to end of VirtualCtr
  1414. // Nodes's _pvcnSister in the chain.
  1415. // -As appropriate, assign pvcnNew->_pvcnChild to the
  1416. // pvcnTo destination.
  1417. // -Adjust the _pvcnParent of pvcnNew->_pvcnChild to
  1418. // point to pvcnTo and increase _cChildren member of
  1419. // pvcnTo node.
  1420. // -Assign a temp variable pvcnTemp to point to the pvcnNew
  1421. // ->_pvcnChild and then loop through to end of all
  1422. // sister VirtualCtrNodes and make their _pvcnParent as
  1423. // pvcnTo and keep on incrementing _cChildren member of
  1424. // pvcnTo with each new VirtualCtrNode traversed.
  1425. // -Now all VirtualCtrNodes fro pvcnNew have been copied
  1426. // to pvcnTo, their destination.
  1427. // -Now everhing under pvcnNew has been copied to pvcnTo, so
  1428. // delete pvcnNew.
  1429. //---------------------------------------------------------------------------
  1430. HRESULT VirtualDF::AdjustTreeOnCopyTo(
  1431. VirtualCtrNode *pvcnFrom,
  1432. VirtualCtrNode *pvcnTo )
  1433. {
  1434. HRESULT hr = S_OK;
  1435. VirtualCtrNode *pvcnNew = NULL;
  1436. VirtualCtrNode *pvcnTrav = NULL;
  1437. VirtualCtrNode *pvcnTemp = NULL;
  1438. VirtualStmNode *pvsnTrav = NULL;
  1439. VirtualStmNode *pvsnTemp = NULL;
  1440. DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ;
  1441. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1442. DH_FUNCENTRY(
  1443. &hr,
  1444. DH_LVL_DFLIB,
  1445. _TEXT("::AdjustTreeOnCopyTo"));
  1446. DH_ASSERT(NULL != pvcnTo);
  1447. DH_ASSERT(NULL != pvcnFrom);
  1448. // Assert if this is the root that is being copied.
  1449. DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
  1450. if(S_OK == hr)
  1451. {
  1452. hr = CopyVirtualDocFileTree(pvcnFrom, NEW_STGSTM, &pvcnNew);
  1453. }
  1454. if(S_OK == hr)
  1455. {
  1456. if(NULL != pvcnNew->_pvsnStream)
  1457. {
  1458. // Append these VirtualStmNode to pvcnTo VirtualCtrNode.
  1459. // BUGBUG: what if these VirtualStmNodes have same name stream in
  1460. // in destination too.
  1461. if(NULL != pvcnTo->_pvsnStream)
  1462. {
  1463. pvsnTrav = pvcnTo->_pvsnStream;
  1464. while(NULL != pvsnTrav->_pvsnSister)
  1465. {
  1466. pvsnTrav = pvsnTrav->_pvsnSister;
  1467. }
  1468. pvsnTrav->_pvsnSister = pvcnNew->_pvsnStream;
  1469. }
  1470. else
  1471. {
  1472. pvcnTo->_pvsnStream = pvcnNew->_pvsnStream;
  1473. }
  1474. pvcnNew->_pvsnStream->_pvcnParent = pvcnTo;
  1475. pvcnTo->_cStreams++;
  1476. if(NULL != pvsnTrav)
  1477. {
  1478. pvsnTemp = pvsnTrav->_pvsnSister;
  1479. }
  1480. else
  1481. {
  1482. pvsnTemp = pvcnTo->_pvsnStream;
  1483. }
  1484. while(NULL != pvsnTemp->_pvsnSister)
  1485. {
  1486. pvsnTemp->_pvsnSister->_pvcnParent = pvcnTo;
  1487. pvcnTo->_cStreams++;
  1488. pvsnTemp = pvsnTemp->_pvsnSister;
  1489. }
  1490. }
  1491. }
  1492. if(S_OK == hr)
  1493. {
  1494. if(NULL != pvcnNew->_pvcnChild)
  1495. {
  1496. // Append these storages to pvcnTo VirtualCtrNode.
  1497. // BUGBUG: what if these VirtualCtrNodes have same name stroage in
  1498. // in destination too.
  1499. if(NULL != pvcnTo->_pvcnChild)
  1500. {
  1501. pvcnTrav = pvcnTo->_pvcnChild;
  1502. while(NULL != pvcnTrav->_pvcnSister)
  1503. {
  1504. pvcnTrav = pvcnTrav->_pvcnSister;
  1505. }
  1506. pvcnTrav->_pvcnSister = pvcnNew->_pvcnChild;
  1507. }
  1508. else
  1509. {
  1510. pvcnTo->_pvcnChild = pvcnNew->_pvcnChild;
  1511. }
  1512. pvcnNew->_pvcnChild->_pvcnParent = pvcnTo;
  1513. pvcnTo->_cChildren++;
  1514. if(NULL != pvcnTrav)
  1515. {
  1516. pvcnTemp = pvcnTrav->_pvcnSister;
  1517. }
  1518. else
  1519. {
  1520. pvcnTemp = pvcnTo->_pvcnChild;
  1521. }
  1522. while(NULL != pvcnTemp->_pvcnSister)
  1523. {
  1524. pvcnTemp->_pvcnSister->_pvcnParent = pvcnTo;
  1525. pvcnTo->_cChildren++;
  1526. pvcnTemp = pvcnTemp->_pvcnSister;
  1527. }
  1528. }
  1529. }
  1530. // All the VirtualCtrNodes and VirtualStmNodes under pvcnNew are now
  1531. // adjusted under the pvcnTo node. So delete the pvcnNew.
  1532. if(NULL != pvcnNew)
  1533. {
  1534. pvcnNew->_pvcnChild = NULL;
  1535. pvcnNew->_pvsnStream = NULL;
  1536. delete pvcnNew;
  1537. pvcnNew = NULL;
  1538. }
  1539. // BUGBUG: How about filling up of _pstg / _pstm fieds for copied tree
  1540. // nodes? May be not required if somebody needs, these could be opened.
  1541. return hr;
  1542. }
  1543. //----------------------------------------------------------------------------
  1544. // Member: VirtualDF::CopyVirtualDocFileTree, public
  1545. //
  1546. // Synopsis: Copies VirtualDocFileTree from old root to a new root with all
  1547. // its structure.
  1548. //
  1549. // Arguments: [pvcnOldTreeRoot] - Pointer to VirtualCtrNode to be moved
  1550. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1551. // [ppvcnNewTreeRoot] - Pointer to VirtualCtrNode of new tree
  1552. //
  1553. // Returns: HRESULT
  1554. //
  1555. // History: Narindk 19-May-1996 Created
  1556. //
  1557. // Notes: In case of transaction mode, where it is just needed to keep
  1558. // a copy of virtualdocfile tree and no new IStroages/Istreams
  1559. // are in question, then the second parameter should be OLD_STGSTM
  1560. // However if say MoveTo/CopyTo where there would be new IStorages
  1561. // /IStreams, it should be given NEW_STGSTM.
  1562. //
  1563. // This function call CopyVirtualDFRoot to copy root VirtualCtr
  1564. // Node and calls CopyVirtualDFTree to copy rest of tree.
  1565. // - Call CopyVirtualDFRoot.
  1566. // - Call CopyGrowVirtualDFTree
  1567. // - If successful, assign root of new VirtualDF in *ppvcnRoot.
  1568. //---------------------------------------------------------------------------
  1569. HRESULT VirtualDF::CopyVirtualDocFileTree(
  1570. VirtualCtrNode *pvcnOldTreeRoot,
  1571. TREEOP treeOpType,
  1572. VirtualCtrNode **ppvcnNewTreeRoot)
  1573. {
  1574. HRESULT hr = S_OK;
  1575. VirtualCtrNode *pvcnTempNewTreeRoot = NULL;
  1576. DH_VDATEPTRIN(pvcnOldTreeRoot, VirtualCtrNode) ;
  1577. DH_VDATEPTROUT(ppvcnNewTreeRoot, PVCTRNODE) ;
  1578. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyVirtualDocFileTree"));
  1579. DH_ASSERT(NULL != pvcnOldTreeRoot);
  1580. DH_ASSERT(NULL != ppvcnNewTreeRoot);
  1581. if (S_OK == hr)
  1582. {
  1583. // Initialize out parameter
  1584. *ppvcnNewTreeRoot = NULL;
  1585. // Generates the root VirtualCtrNode for the VirtualDocFile tree.
  1586. hr = CopyVirtualDFRoot(
  1587. pvcnOldTreeRoot,
  1588. treeOpType,
  1589. &pvcnTempNewTreeRoot);
  1590. DH_HRCHECK(hr, TEXT("CopyVirtualDFRoot")) ;
  1591. }
  1592. if (S_OK == hr)
  1593. {
  1594. // Generate remaining new VirtualDF tree based on old VirtualDF tree.
  1595. hr = CopyGrowVirtualDFTree(
  1596. pvcnOldTreeRoot,
  1597. pvcnTempNewTreeRoot,
  1598. treeOpType);
  1599. DH_HRCHECK(hr, TEXT("CopyGrowVirtualDFTree")) ;
  1600. }
  1601. // Fill the out parameter
  1602. if(S_OK == hr)
  1603. {
  1604. *ppvcnNewTreeRoot = pvcnTempNewTreeRoot;
  1605. }
  1606. return hr;
  1607. }
  1608. //----------------------------------------------------------------------------
  1609. // Member: VirtualDF::CopyVirtualDFRoot, protected
  1610. //
  1611. // Synopsis: Creates the root VirtualCtrNode for the VirtualDocFile tree.
  1612. //
  1613. // Arguments: [pvcnRootOld] - Pointer to root of old VirtualDocFile tree
  1614. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1615. // [ppvcnRootNew] - Pointer to pointer to new VirtualDF tree
  1616. //
  1617. // Returns: HRESULT
  1618. //
  1619. // History: Narindk 19-May-96 Created
  1620. //
  1621. // Notes: - Creates VirtualCtrNode object and initializes it with info
  1622. // based on corresponding old source VirtualDocFile root.
  1623. // - Calls CopyAppendVirtualStmNodesToVirtualCtrNode to append
  1624. // VirtualStmNodes to this VirtualCtrNode, if present in old
  1625. // source tree, so required to be copied.
  1626. // - Copies in memory CRC for this VirtualCtrNode _dwCRC from old
  1627. // source VirtualCtrNode.
  1628. // - if treeOpType is OLD_STGSTM, as would be in transaction tree
  1629. // copy procedure, when no new disk IStorages/IStreams are made,
  1630. // this assign's new VirtualCtrNode's _pstg to be old source
  1631. // VirtualCtrNode's _pstg.
  1632. //---------------------------------------------------------------------------
  1633. HRESULT VirtualDF::CopyVirtualDFRoot(
  1634. VirtualCtrNode *pvcnRootOld,
  1635. TREEOP treeOpType,
  1636. VirtualCtrNode **ppvcnRootNew)
  1637. {
  1638. HRESULT hr = S_OK;
  1639. DH_VDATEPTRIN(pvcnRootOld, VirtualCtrNode) ;
  1640. DH_VDATEPTROUT(ppvcnRootNew, PVCTRNODE) ;
  1641. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyVirtualDFRoot"));
  1642. DH_ASSERT(NULL != pvcnRootOld);
  1643. DH_ASSERT(NULL != ppvcnRootNew);
  1644. // Generate VirtualCtrNode for the root node.
  1645. if(S_OK == hr)
  1646. {
  1647. // Initialize out parameter
  1648. *ppvcnRootNew = NULL;
  1649. *ppvcnRootNew = new VirtualCtrNode();
  1650. if (NULL == *ppvcnRootNew)
  1651. {
  1652. hr = E_OUTOFMEMORY;
  1653. }
  1654. }
  1655. if(S_OK == hr)
  1656. {
  1657. hr = (*ppvcnRootNew)->Init(
  1658. pvcnRootOld->_ptszName,
  1659. pvcnRootOld->_cChildren,
  1660. pvcnRootOld->_cStreams);
  1661. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  1662. }
  1663. if ((S_OK == hr) && (0 != (*ppvcnRootNew)->_cStreams))
  1664. {
  1665. hr = CopyAppendVirtualStmNodesToVirtualCtrNode(
  1666. (*ppvcnRootNew)->_cStreams,
  1667. *ppvcnRootNew,
  1668. pvcnRootOld,
  1669. treeOpType);
  1670. DH_HRCHECK(hr, TEXT("CopyAppendVirtualStmNodesToVirtualCtrNode")) ;
  1671. }
  1672. if(S_OK == hr)
  1673. {
  1674. (*ppvcnRootNew)->_dwCRC = pvcnRootOld->_dwCRC;
  1675. if(OLD_STGSTM == treeOpType)
  1676. {
  1677. (*ppvcnRootNew)->_pstg = pvcnRootOld->_pstg;
  1678. }
  1679. }
  1680. return hr;
  1681. }
  1682. //----------------------------------------------------------------------------
  1683. // Member: VirtualDF::CopyGrowVirtualDFTree, protected
  1684. //
  1685. // Synopsis: Creates the ramaining VirtualDocFile tree.
  1686. //
  1687. // Arguments: [pvcnFrom] - Pointer to current node of original VirtualDocFile/// tree
  1688. // [pvcnTo] - Pointer to current VirtualCtrNode of copied Virtual
  1689. // DocFile tree
  1690. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1691. //
  1692. // Returns: HRESULT
  1693. //
  1694. // History: Narindk 13-June-96 Created
  1695. //
  1696. // Notes: The copied VirtualDocFile tree is created based on corresponding
  1697. // original VirtualDocFile tree. This function is called either
  1698. // from the CopyGenerateVirtualDF function or may call itself
  1699. // recursively. The original VirtualDocFile tree is traversed from
  1700. // the top down, and based on its contents, a new VirtualDF tree
  1701. // is generated topdown.
  1702. //
  1703. // First assign the passed in pvcnFrom to pvcnCurrentChild and
  1704. // passed in pvcnTo to pvcnFisrtBorn variables.
  1705. // Loop till pvcnCurrentChild's _pvcnChild is non NULL & hr is S_OK
  1706. // - Call CopyAppendVirtualCtrNode to create a new node called
  1707. // pvcnNextBorn based on info from corresponding old pvcnCurrent-
  1708. // Child's _pvcnChild and append it to pvcnFirstBorn in the tree
  1709. // being generated by copy.
  1710. // - Assign pvcnCurrentChild's _pvcnChild to pvcnCurrentSister.
  1711. // - Loop till pvcnCurrentSister's _pvcnSister is non NULL
  1712. // - Call CopyAppendVirtualCtrNode to create a new node
  1713. // pvcnNextBornSister and append it to pvcnFirstBorn. Pl.
  1714. // note that append function would take care to append
  1715. // it to its older sister.
  1716. // - Assign pvcnCurrentSister's _pvcnSister to variable
  1717. // pvcnCurrentSister.
  1718. // - If pvcnCurrentSister's _pvcnChild is non NULL, then
  1719. // make a recursive call to self CopyGrowVirtualDFTree.
  1720. // - Reinitialize pvcnNextBornSister to NULL & go back to
  1721. // top of this inner loop and repeat.
  1722. // - Assign pvcnNextBorn to pvcnFirstBorn and reinitailize pvcn
  1723. // NextBorn to NULL.
  1724. // - Assign pvcnCurrentChild's _pvcnChild to pvcnCurrentChild.
  1725. // - Go to top of outer loop and repeat.
  1726. //---------------------------------------------------------------------------
  1727. //---------------------------------------------------------------------------
  1728. HRESULT VirtualDF::CopyGrowVirtualDFTree(
  1729. VirtualCtrNode *pvcnFrom,
  1730. VirtualCtrNode *pvcnTo,
  1731. TREEOP treeOpType)
  1732. {
  1733. HRESULT hr = S_OK;
  1734. VirtualCtrNode *pvcnFirstBorn = NULL;
  1735. VirtualCtrNode *pvcnNextBorn = NULL;
  1736. VirtualCtrNode *pvcnNextBornSister = NULL;
  1737. VirtualCtrNode *pvcnCurrentSister = NULL;
  1738. VirtualCtrNode *pvcnCurrentChild = NULL;
  1739. DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ;
  1740. DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
  1741. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyGrowVirtualDFTree"));
  1742. DH_ASSERT(NULL != pvcnFrom);
  1743. DH_ASSERT(NULL != pvcnTo);
  1744. if(S_OK == hr)
  1745. {
  1746. pvcnFirstBorn = pvcnTo;
  1747. pvcnCurrentChild = pvcnFrom;
  1748. }
  1749. while((NULL != pvcnCurrentChild->_pvcnChild) && (S_OK == hr))
  1750. {
  1751. hr = CopyAppendVirtualCtrNode(
  1752. pvcnFirstBorn,
  1753. pvcnCurrentChild->_pvcnChild,
  1754. treeOpType,
  1755. &pvcnNextBorn);
  1756. DH_HRCHECK(hr, TEXT("CopyAppendVirtualCtrNode")) ;
  1757. if(S_OK == hr)
  1758. {
  1759. pvcnCurrentSister = pvcnCurrentChild->_pvcnChild;
  1760. while((NULL != pvcnCurrentSister->_pvcnSister) && (S_OK == hr))
  1761. {
  1762. hr = CopyAppendVirtualCtrNode(
  1763. pvcnFirstBorn,
  1764. pvcnCurrentSister->_pvcnSister,
  1765. treeOpType,
  1766. &pvcnNextBornSister);
  1767. DH_HRCHECK(hr, TEXT("CopyAppendVirtualCtrNode")) ;
  1768. pvcnCurrentSister = pvcnCurrentSister->_pvcnSister;
  1769. // Check if there are any children of this sister node, if
  1770. // yes, then make a recursive call to self.
  1771. if(NULL != pvcnCurrentSister->_pvcnChild)
  1772. {
  1773. hr = CopyGrowVirtualDFTree(
  1774. pvcnCurrentSister,
  1775. pvcnNextBornSister,
  1776. treeOpType);
  1777. DH_HRCHECK(hr, TEXT("CopyGrowVirtualDFTree"));
  1778. }
  1779. // Reinitialize the variables
  1780. pvcnNextBornSister = NULL;
  1781. }
  1782. }
  1783. pvcnFirstBorn = pvcnNextBorn;
  1784. pvcnNextBorn = NULL;
  1785. pvcnCurrentChild = pvcnCurrentChild->_pvcnChild;
  1786. }
  1787. return hr;
  1788. }
  1789. //----------------------------------------------------------------------------
  1790. // Member: VirtualDF::CopyAppendVirtualCtrNode, protected
  1791. //
  1792. // Synopsis: Creates and appends VirtualCtrNode to VirtualDocFile tree
  1793. // being created.
  1794. //
  1795. // Arguments: [pvcnParent] - Parent VirtualCtrNode for the new VirtualCtrNode
  1796. // [pcnSource] - Corresponding VirtualCtrNode in old VirtualDF
  1797. // tree.
  1798. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1799. // [ppvcnNew] - Pointer to pointer to new VirtualCtrNode to be
  1800. // created.
  1801. //
  1802. // Returns: HRESULT
  1803. //
  1804. // History: Narindk 20-May-96 Created
  1805. //
  1806. // Notes: - Creates VirtualCtrNode object ppvcnNew & initializes it with
  1807. // info based on corresponding old source pvcnSource node.
  1808. // - Appends this node to copy VirtualDF tree being generated.
  1809. // - Calls CopyAppendVirtualStmNodesToVirtualCtrNode to append
  1810. // VirtualStmNodes to this VirtualCtrNode, if present in old
  1811. // source tree, so required to be copied.
  1812. // - Copies in memory CRC for this VirtualCtrNode _dwCRC from old
  1813. // source VirtualCtrNode.
  1814. // - if treeOpType is OLD_STGSTM, as would be in transaction tree
  1815. // copy procedure, when no new disk IStorages/IStreams are made,
  1816. // this assign's new VirtualCtrNode's _pstg to be old source
  1817. // VirtualCtrNode's _pstg.
  1818. //---------------------------------------------------------------------------
  1819. HRESULT VirtualDF::CopyAppendVirtualCtrNode(
  1820. VirtualCtrNode *pvcnParent,
  1821. VirtualCtrNode *pvcnSource,
  1822. TREEOP treeOpType,
  1823. VirtualCtrNode **ppvcnNew)
  1824. {
  1825. HRESULT hr = S_OK;
  1826. VirtualCtrNode *pvcnOldSister = NULL;
  1827. DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ;
  1828. DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ;
  1829. DH_VDATEPTRIN(pvcnSource, VirtualCtrNode) ;
  1830. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyAppendChildVirtualCtrNode"));
  1831. DH_ASSERT(NULL != pvcnParent);
  1832. DH_ASSERT(NULL != ppvcnNew);
  1833. DH_ASSERT(NULL != pvcnSource);
  1834. if(S_OK == hr)
  1835. {
  1836. *ppvcnNew = NULL;
  1837. // Allocate and Initialize new VirtualCtrNode
  1838. *ppvcnNew = new VirtualCtrNode();
  1839. if (NULL == *ppvcnNew)
  1840. {
  1841. hr = E_OUTOFMEMORY;
  1842. }
  1843. }
  1844. if(S_OK == hr)
  1845. {
  1846. hr = (*ppvcnNew)->Init(
  1847. pvcnSource->_ptszName,
  1848. pvcnSource->_cChildren,
  1849. pvcnSource->_cStreams);
  1850. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  1851. }
  1852. // Append new VirtualCtr Node
  1853. if(S_OK == hr)
  1854. {
  1855. if(NULL == pvcnParent->_pvcnChild)
  1856. {
  1857. hr = pvcnParent->AppendChildCtr(*ppvcnNew);
  1858. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ;
  1859. }
  1860. else
  1861. {
  1862. pvcnOldSister = pvcnParent->_pvcnChild;
  1863. while(NULL != pvcnOldSister->_pvcnSister)
  1864. {
  1865. pvcnOldSister = pvcnOldSister->_pvcnSister;
  1866. }
  1867. hr = pvcnOldSister->AppendSisterCtr(*ppvcnNew);
  1868. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ;
  1869. }
  1870. }
  1871. if ((S_OK == hr) && (0 != (*ppvcnNew)->_cStreams))
  1872. {
  1873. hr = CopyAppendVirtualStmNodesToVirtualCtrNode(
  1874. (*ppvcnNew)->_cStreams,
  1875. *ppvcnNew,
  1876. pvcnSource,
  1877. treeOpType);
  1878. DH_HRCHECK(hr, TEXT("CopyAppendVirtualStmNodesToVirtualCtrNode")) ;
  1879. }
  1880. if(S_OK == hr)
  1881. {
  1882. (*ppvcnNew)->_dwCRC = pvcnSource->_dwCRC;
  1883. if(OLD_STGSTM == treeOpType)
  1884. {
  1885. (*ppvcnNew)->_pstg = pvcnSource->_pstg;
  1886. }
  1887. }
  1888. return hr;
  1889. }
  1890. //----------------------------------------------------------------------------
  1891. // Member: VirtualDF::CopyAppendVirtualStmNodesToVirtualCtrNode, protected
  1892. //
  1893. // Synopsis: Creates and appends VirtualStmNode(s) to VirtualCtrNode
  1894. //
  1895. // Arguments: [cStreams] - Number of streams to be created
  1896. // [pvcn] - Pointer to VirtualCtrNode for which the streams
  1897. // need to be created and appended.
  1898. // [pvcnSource] - Pointer to correspoding VirtualCtrNode in
  1899. // old VirtualDF tree.
  1900. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1901. //
  1902. // Returns: HRESULT
  1903. //
  1904. // History: Narindk 20-May-96 Created
  1905. //
  1906. // Notes: if number of streams to be created and appended to parent
  1907. // VirtualCtrNode pvcn is not zero, then loop till cStreams is
  1908. // not equal to zero.
  1909. // - First time in loop, assign pvsnSource from pvcnSource's
  1910. // _pvcsnStream, otherwise assign pvsnSource's _pvsnSister
  1911. // to pvsnSource with each traversal of loop.
  1912. // - Call CopyAppendVirtualStmNode to create a new VirtualStm
  1913. // Node and append it to parent VirtualCtrNode. Pl. note that
  1914. // this function would take care if the newly created node
  1915. // need to be appended to older VirtualStmNode sister.
  1916. // - Decrement cStreams and go back to top of loop & repeat.
  1917. //---------------------------------------------------------------------------
  1918. HRESULT VirtualDF::CopyAppendVirtualStmNodesToVirtualCtrNode(
  1919. ULONG cStreams,
  1920. VirtualCtrNode *pvcn,
  1921. VirtualCtrNode *pvcnSource,
  1922. TREEOP treeOpType)
  1923. {
  1924. HRESULT hr = S_OK;
  1925. VirtualStmNode *pvsnSource = NULL;
  1926. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1927. DH_VDATEPTRIN(pvcnSource, VirtualCtrNode) ;
  1928. DH_FUNCENTRY(
  1929. &hr,
  1930. DH_LVL_DFLIB,
  1931. _TEXT("::CopyAppendVirtualStmNodesToVirtualCtrNode"));
  1932. DH_ASSERT(0 != cStreams);
  1933. DH_ASSERT(NULL != pvcn);
  1934. DH_ASSERT(NULL != pvcnSource);
  1935. while((S_OK == hr) && (0 != cStreams))
  1936. {
  1937. if(NULL == pvsnSource)
  1938. {
  1939. pvsnSource = pvcnSource->_pvsnStream;
  1940. }
  1941. else
  1942. {
  1943. pvsnSource = pvsnSource->_pvsnSister;
  1944. }
  1945. DH_ASSERT(NULL != pvsnSource);
  1946. hr = CopyAppendVirtualStmNode(
  1947. pvcn,
  1948. pvsnSource,
  1949. treeOpType);
  1950. DH_HRCHECK(hr, TEXT("CopyAppendFirstVirtualStmNode")) ;
  1951. cStreams--;
  1952. }
  1953. return hr;
  1954. }
  1955. //----------------------------------------------------------------------------
  1956. // Member: VirtualDF::CopyAppendVirtualStmNode, protected
  1957. //
  1958. // Synopsis: Creates and appends first VirtualStmNode to VirtualCtrNode
  1959. //
  1960. // Arguments: [pvcnParent] - Pointer to VirtualCtrNode for which the streams
  1961. // need to be created and appended.
  1962. // [pvsnSource] - Pointer to corresponding VirtualStmNode in old
  1963. // VirtualDF tree.
  1964. // [treeOpType] - OLD_STGSTM or NEW_STGSTM
  1965. //
  1966. // Returns: HRESULT
  1967. //
  1968. // History: Narindk 20-May-96 Created
  1969. //
  1970. // Notes: - Creates VirtualStmNode pvsnNew and initializes it with above
  1971. // info from pvsnSource
  1972. // - Appends this node to the parent VirtualCtrNode pvcnParent.
  1973. // - Copies in memory CRC for this VirtualStmNode's _dwCRC from old
  1974. // source pvsnSource.
  1975. // - if treeOpType is OLD_STGSTM, as would be in transaction tree
  1976. // copy procedure, when no new disk IStorages/IStreams are made,
  1977. // this assign's new VirtualStmNode's _pstm to be pvsnSource's
  1978. // _pstm
  1979. //---------------------------------------------------------------------------
  1980. HRESULT VirtualDF::CopyAppendVirtualStmNode(
  1981. VirtualCtrNode *pvcnParent,
  1982. VirtualStmNode *pvsnSource,
  1983. TREEOP treeOpType)
  1984. {
  1985. HRESULT hr = S_OK;
  1986. VirtualStmNode *pvsnNew = NULL;
  1987. VirtualStmNode *pvsnOldSister = NULL;
  1988. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyAppendFirstVirtualStmNode"));
  1989. DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ;
  1990. DH_VDATEPTRIN(pvsnSource, VirtualStmNode) ;
  1991. DH_ASSERT(NULL != pvcnParent);
  1992. DH_ASSERT(NULL != pvsnSource);
  1993. if (S_OK == hr)
  1994. {
  1995. pvsnNew = new VirtualStmNode();
  1996. if (NULL == pvsnNew)
  1997. {
  1998. hr = E_OUTOFMEMORY;
  1999. }
  2000. }
  2001. if(S_OK == hr)
  2002. {
  2003. hr = pvsnNew->Init(pvsnSource->_ptszName, pvsnSource->_cb);
  2004. DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ;
  2005. }
  2006. if(S_OK == hr)
  2007. {
  2008. if(NULL == pvcnParent->_pvsnStream)
  2009. {
  2010. // Append it to parent storage
  2011. hr = pvcnParent->AppendFirstChildStm(pvsnNew);
  2012. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ;
  2013. }
  2014. else
  2015. {
  2016. pvsnOldSister = pvcnParent->_pvsnStream;
  2017. while(NULL != pvsnOldSister->_pvsnSister)
  2018. {
  2019. pvsnOldSister = pvsnOldSister->_pvsnSister;
  2020. }
  2021. // Append it to preceding sister stream
  2022. hr = pvsnOldSister->AppendSisterStm(pvsnNew);
  2023. DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ;
  2024. }
  2025. }
  2026. if(S_OK == hr)
  2027. {
  2028. pvsnNew->_dwCRC.dwCRCName = pvsnSource->_dwCRC.dwCRCName;
  2029. pvsnNew->_dwCRC.dwCRCData = pvsnSource->_dwCRC.dwCRCData;
  2030. pvsnNew->_dwCRC.dwCRCSum = pvsnSource->_dwCRC.dwCRCSum;
  2031. if(OLD_STGSTM == treeOpType)
  2032. {
  2033. pvsnNew->_pstm = pvsnSource->_pstm;
  2034. }
  2035. }
  2036. return hr;
  2037. }
  2038. //----------------------------------------------------------------------------
  2039. // Member: VirtualDF::Associate, public
  2040. //
  2041. // Synopsis: Assocaies a VirtualDF tree with a VirtualCtrNode and its name.
  2042. //
  2043. // Arguments: [pvcn] - Pointer to VirtualCtrNode to be associated with
  2044. // [pIStorage] - pointer to Disk IStorage to associate with
  2045. //
  2046. // Returns: HRESULT
  2047. //
  2048. // History: Narindk 6-June-96 Created
  2049. //
  2050. // Notes: This function is currently being used by GenerateVirtualDFFrom
  2051. // DiskDF in util.cxx.
  2052. //---------------------------------------------------------------------------
  2053. HRESULT VirtualDF::Associate(
  2054. VirtualCtrNode *pvcn,
  2055. LPSTORAGE pIStorage,
  2056. ULONG ulSeed)
  2057. {
  2058. HRESULT hr = S_OK;
  2059. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::Associate"));
  2060. DH_VDATEPTRIN(pvcn, VirtualCtrNode);
  2061. DH_VDATEPTRIN(pIStorage, IStorage);
  2062. DH_ASSERT(NULL != pvcn);
  2063. DH_ASSERT(NULL != pIStorage);
  2064. // Associate name
  2065. if(S_OK == hr)
  2066. {
  2067. _ptszName = new TCHAR[_tcslen(pvcn->_ptszName)+1];
  2068. if (_ptszName == NULL)
  2069. {
  2070. hr = E_OUTOFMEMORY;
  2071. }
  2072. else
  2073. {
  2074. _tcscpy(_ptszName, pvcn->_ptszName);
  2075. }
  2076. }
  2077. // Associate given root IStorage with root VirtualCtrNode's _pstg and
  2078. // also Associate root of VirtualDF _pvcnRoot with the passed in root
  2079. // VirtualCtrNode.
  2080. if(S_OK == hr)
  2081. {
  2082. pvcn->_pstg = pIStorage;
  2083. _pvcnRoot = pvcn;
  2084. }
  2085. // Create the DataGens if we need to and if we can
  2086. // If ulSeed is UL_INVALIDSEED, caller is not interested.
  2087. if (UL_INVALIDSEED != ulSeed)
  2088. {
  2089. // We need a totally new set of datagens to prevent
  2090. // duplicate names. So Generate a new seed.
  2091. DG_INTEGER *pdgiNew = new DG_INTEGER (ulSeed);
  2092. if (NULL != pdgiNew)
  2093. {
  2094. ULONG ulTmp = 0;
  2095. if (DG_RC_SUCCESS == pdgiNew->Generate(&ulTmp, 0, 0xFFFFFFFF))
  2096. {
  2097. ulSeed = ulTmp;
  2098. }
  2099. delete pdgiNew;
  2100. }
  2101. if (NULL == _pdgi)
  2102. {
  2103. _pdgi = new(NullOnFail) DG_INTEGER(ulSeed);
  2104. }
  2105. if (NULL == _pgdu)
  2106. {
  2107. _pgdu = new(NullOnFail) DG_STRING(ulSeed);
  2108. }
  2109. if (NULL == _pdgi || NULL == _pgdu)
  2110. {
  2111. hr = E_OUTOFMEMORY;
  2112. }
  2113. }
  2114. return hr;
  2115. }
  2116. //----------------------------------------------------------------------------
  2117. // Member: VirtualDF::DeleteVirtualCtrNodeStreamNode, public
  2118. //
  2119. // Synopsis: Deletes the VirtualStmNode passed in under the given
  2120. // VirtualCtrNode.
  2121. //
  2122. // Arguments: [*pvcn]- Pointer to VirtualCtrNode for which VirtualStmNode
  2123. // need to be deleted.
  2124. // [*pvsn] - Pointer to VirtualStmNode to be deleted
  2125. //
  2126. // Returns: HRESULT
  2127. //
  2128. // History: Narindk 9-July-96 Created
  2129. //
  2130. // Notes: - Assign a temp variable pvsnTemp to point to _pvsnStream of
  2131. // passed in VirtualStmNode pvsn's _pvcnParent.
  2132. // - Delete the corresponding VirtualStmNode from VirtualCtrNode
  2133. // chain of VirtualStmNode and readjusts parent VirtualCtrNode
  2134. // /child VirtualStmNodes pointers and _cStreams count of the
  2135. // VirtualCtrNode.
  2136. // - In a loop, befor entering into which pvsnOldSister is
  2137. // set to NULL, find the passed in VirtualStmNode and
  2138. // break when found.
  2139. // - if VirtualStmNode to be deleted is first one in the
  2140. // VirtualStmNode chain of parent, then parent VirtualCtr
  2141. // Node's _pvsnStream ptr needs to be adjusted to point to
  2142. // "to be delted" VirtualStmNode's _pvsnSister.
  2143. // - If VirtualStmNode to be deleted is not first one in the
  2144. // VirtualStmNode chain, then its older sister is located
  2145. // and its _pvsnSister pointer is adjusted to "to be delted"
  2146. // VirtualStmNode's _pvsnSister.
  2147. // - Decrease the _cStreams count of the VirtualCtrNode parent
  2148. // - Delete the VirtualStmNode after setting its pointers to
  2149. // NULL.
  2150. //---------------------------------------------------------------------------
  2151. HRESULT VirtualDF::DeleteVirtualCtrNodeStreamNode(VirtualStmNode *pvsn)
  2152. {
  2153. HRESULT hr = S_OK;
  2154. VirtualStmNode *pvsnTemp = NULL;
  2155. VirtualStmNode *pvsnOldSister = NULL;
  2156. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualCtrNodeStreamNode"));
  2157. DH_VDATEPTRIN(pvsn, VirtualStmNode);
  2158. DH_ASSERT(NULL != pvsn);
  2159. DH_ASSERT(NULL != pvsn->_pvcnParent);
  2160. if(S_OK == hr)
  2161. {
  2162. pvsnTemp = pvsn->_pvcnParent->_pvsnStream;
  2163. pvsnOldSister = NULL;
  2164. // This locates the VirtualStmNode to be deleted and the
  2165. // nodes whose pointers may need to be readjusted.
  2166. while((pvsnTemp != pvsn) && (NULL != pvsnTemp->_pvsnSister))
  2167. {
  2168. pvsnOldSister = pvsnTemp;
  2169. pvsnTemp = pvsnTemp->_pvsnSister;
  2170. }
  2171. DH_ASSERT(pvsnTemp == pvsn);
  2172. // Adjust the pointers
  2173. if(NULL == pvsnOldSister)
  2174. {
  2175. pvsn->_pvcnParent->_pvsnStream = pvsnTemp->_pvsnSister;
  2176. }
  2177. else
  2178. {
  2179. pvsnOldSister->_pvsnSister = pvsnTemp->_pvsnSister;
  2180. }
  2181. // Decrease the stream count of the parent VirtualCtrNode parent.
  2182. pvsn->_pvcnParent->_cStreams--;
  2183. // Delete the node after NULLing its pointers.
  2184. pvsnTemp->_pvcnParent = NULL;
  2185. pvsnTemp->_pvsnSister= NULL;
  2186. delete pvsnTemp;
  2187. pvsnTemp = NULL;
  2188. }
  2189. return hr;
  2190. }