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.

4355 lines
137 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: util.cxx
  7. //
  8. // Contents: Implementation of utilities for common class library and for
  9. // tests.
  10. //
  11. // Functions: - GenerateRandomName
  12. // - GetVirtualCtrNodeForTest
  13. // - GetVirtualStmNodeForTest
  14. // - DestroyStorage
  15. // - DestroyStream
  16. // - AddStorage
  17. // - AddStream
  18. // - CalculateCRCForName
  19. // - CalculateCRCForDataBuffer
  20. // - CalculateInMemoryCRCForStg
  21. // - CalculateInMemoryCRCForStm
  22. // - ReadAndCalculateDiskCRCForStm
  23. // - CalculateDiskCRCForStg
  24. // - EnumerateInMemoryDocFile
  25. // - OpenRandomVirtualCtrNodeStg
  26. // - CloseRandomVirtualCtrNodeStg
  27. // - ParseVirtualDFAndCloseOpenStgsStms
  28. // - ParseVirtualDFAndCommitAllOpenStgs
  29. // - CalculateCRCForDocFile
  30. // - CalculateCRCForDocFileStmData
  31. // - TStringToOleString
  32. // - EnumerateDiskDocFile
  33. // - GenerateVirtualDFFromDiskDF
  34. // - GenerateRemVirtualDFTree [local to this file]
  35. // - GenVirtualCtrNode [local to this file]
  36. // - GenVirtualStmNode [local to this file]
  37. // - PrivAtol
  38. // - GenerateRandomString
  39. // - GenerateRandomStreamData
  40. // - ParseVirtualDFAndOpenAllSubStgsStms
  41. // - CommitRandomVirtualCtrNodeStg
  42. //
  43. // History: 17-Apr-96 Narindk Created.
  44. // 2-Feb-97 SCousens Added for Cnvrs/NSS
  45. // 31-Mar-98 SCousens Added GenerateRandomStreamData
  46. //
  47. //--------------------------------------------------------------------------
  48. #include <dfheader.hxx>
  49. #pragma hdrstop
  50. // Debug Object declaration
  51. DH_DECLARE;
  52. // CRC 32 Bitwise lookup table, logic taken from CRC-32 description in
  53. // 'C Programmer's Guide to Netbios' book.
  54. ULONG aulCrc[256] =
  55. {
  56. 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
  57. 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  58. 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
  59. 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  60. 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
  61. 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  62. 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
  63. 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  64. 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
  65. 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  66. 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
  67. 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  68. 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
  69. 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  70. 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
  71. 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  72. 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
  73. 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  74. 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
  75. 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  76. 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
  77. 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  78. 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
  79. 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  80. 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
  81. 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  82. 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
  83. 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  84. 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
  85. 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  86. 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
  87. 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  88. 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
  89. 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  90. 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
  91. 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  92. 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
  93. 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  94. 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
  95. 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  96. 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
  97. 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  98. 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  99. };
  100. // Functions local to this file
  101. HRESULT GenerateRemVirtualDFTree(
  102. VirtualCtrNode *pvcnParent,
  103. LPSTORAGE pIStgParent);
  104. HRESULT GenVirtualCtrNode(
  105. LPTSTR ptcsName,
  106. VirtualCtrNode **ppvcnNew);
  107. HRESULT GenVirtualStmNode(
  108. LPTSTR ptcsName,
  109. DWORD cbSize,
  110. VirtualStmNode **ppvsnNew);
  111. //+-------------------------------------------------------------------------
  112. // Function: GenerateRandomName
  113. //
  114. // Synopsis: Generates a random name using datagen object.
  115. //
  116. // Arguments: [pgds] - Pointer to DG_STRING object.
  117. // [pptszName] - Pointer to pointer to returned string.
  118. // [ulMinLen] - Minimum length of string
  119. // [ulMaxLen] - Maximum length of string
  120. //
  121. // Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
  122. //
  123. // History: 11-Nov-96 BogdanT Changed the DG_UNICODE ptr. to DG_STRING
  124. // 17-Apr-96 NarindK Created.
  125. //
  126. // Notes: BUGBUG: This function need to be enhance to handle different
  127. // character sets.
  128. // Please note that the name generated may have an extension b/w
  129. // 0 and FILEEXT_MAXLEN besides the length of name b/w ulMinLen and
  130. // ulMax Len.
  131. //--------------------------------------------------------------------------
  132. HRESULT GenerateRandomName(
  133. DG_STRING *pgds,
  134. ULONG ulMinLen,
  135. ULONG ulMaxLen,
  136. LPTSTR *pptszName)
  137. {
  138. HRESULT hr = S_OK;
  139. ULONG cTemp = 0;
  140. USHORT usErr = 0;
  141. ULONG ulActMaxLen = 0;
  142. ULONG ulActMinLen = 0;
  143. ULONG ulNameLen = 0;
  144. ULONG ulExtLen = 0;
  145. LPTSTR ptszName = NULL;
  146. LPTSTR ptszExt = NULL;
  147. LPWSTR pwszName = NULL;
  148. LPWSTR pwszExt = NULL;
  149. TCHAR ptszFATCharSet[FAT_CHARSET_SIZE];
  150. // TCHAR ptszOFSCharSet[OFS_CHARSET_SIZE];
  151. LPWSTR pwszFATCharSet = NULL;
  152. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRandomName"));
  153. DH_VDATEPTRIN(pgds, DG_STRING) ;
  154. DH_VDATEPTROUT(pptszName, LPTSTR) ;
  155. DH_ASSERT(NULL != pgds);
  156. DH_ASSERT(NULL != pptszName);
  157. if (S_OK == hr)
  158. {
  159. // Initialize out parameter.
  160. *pptszName = NULL;
  161. // Sanity check. Min length for name must be <= maximum length, if it
  162. // isn't then make maximum length equal to minimum length.
  163. if (ulMaxLen < ulMinLen)
  164. {
  165. ulMaxLen = ulMinLen;
  166. }
  167. // If Maximum length provided is 0, then default maximum length would
  168. // be used. If Minimum length provided is zero, then 1 would be used
  169. // for it.
  170. // BUGBUG: We are using default maximum length for FAT system.
  171. ulActMaxLen = (ulMaxLen == 0 ? DEF_FATNAME_MAXLEN : ulMaxLen);
  172. ulActMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
  173. // '\0', '\', '/', and ':' are invalid for IStorage/IStream names
  174. // (For doc file)
  175. // '*', '"' '<' '>' '?' are invalid for IStorage/IStream names on OFS
  176. // Initialize valid character set for FAT file names
  177. _tcscpy(ptszFATCharSet, _TEXT("abcdefghijklmnopqrstuvwxyz"));
  178. _tcscat(ptszFATCharSet, _TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
  179. _tcscat(ptszFATCharSet, _TEXT("0123456789"));
  180. //BUGBUG: Check if these characters are not valid for IStorage/IStream
  181. // names.
  182. // _tcscat(ptszFATCharSet, L"_^$~!#%&-{}()@'`");
  183. // Initialize valid character set for other file names. BUGBUG: Not
  184. // using OFS character set at present.
  185. // for (TCHAR wch = 0x01; wch <= 0x7f; wch++)
  186. // {
  187. // if (wch != L'\\' && wch != L'/' && wch != L'*' && wch != L'?')
  188. // {
  189. // ptszOFSCharSet[cTemp++] = wch;
  190. // }
  191. // }
  192. // ptszOFSCharSet[cTemp] = NULL;
  193. // Call DataGen to generate a random file name
  194. // BUGBUG: We are using FAT character set to generate random names.
  195. #ifdef _MAC
  196. usErr = pgds->Generate(
  197. (UCHAR **)&ptszName, // force compiler to chose the right
  198. (UCHAR *)ptszFATCharSet, // version of Generate
  199. ulActMinLen,
  200. ulActMaxLen);
  201. #else
  202. if(S_OK == hr)
  203. {
  204. // Convert TCHAR to WCHAR
  205. hr = TStrToWStr(ptszFATCharSet, &pwszFATCharSet);
  206. DH_HRCHECK(hr, TEXT("TStrToWStr")) ;
  207. }
  208. usErr = pgds->Generate(
  209. &pwszName,
  210. pwszFATCharSet,
  211. ulActMinLen,
  212. ulActMaxLen);
  213. #endif //_MAC
  214. if (usErr != DG_RC_SUCCESS) // DataGen error
  215. {
  216. hr = E_FAIL;
  217. }
  218. }
  219. if (S_OK == hr)
  220. {
  221. // Generate a random extension
  222. #ifdef _MAC
  223. usErr = pgds->Generate(
  224. (UCHAR **)&ptszExt, // force compiler to chose the right
  225. (UCHAR *)ptszFATCharSet, // version of Generate
  226. 0,
  227. FILEEXT_MAXLEN);
  228. #else
  229. usErr = pgds->Generate(
  230. &pwszExt,
  231. pwszFATCharSet,
  232. 0,
  233. FILEEXT_MAXLEN);
  234. #endif //_MAC
  235. if (usErr != DG_RC_SUCCESS) // Failed to generate extension
  236. {
  237. hr = E_FAIL;
  238. delete pwszName;
  239. pwszName = NULL;
  240. }
  241. }
  242. #ifndef _MAC
  243. // In MAC version we don't use the WSZs so skip the conversions
  244. if(S_OK == hr)
  245. {
  246. //Convert WCHAR to TCHAR
  247. hr = WStrToTStr(pwszName, &ptszName);
  248. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  249. }
  250. if((S_OK == hr) && (NULL != *pwszExt))
  251. {
  252. //Convert WCHAR to TCHAR
  253. hr = WStrToTStr(pwszExt, &ptszExt);
  254. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  255. }
  256. #endif //_MAC
  257. if (S_OK == hr)
  258. {
  259. ulNameLen = _tcslen(ptszName);
  260. if(NULL != ptszExt)
  261. {
  262. ulExtLen = _tcslen(ptszExt);
  263. // If the length of the extension > 0, a '.' will be added.
  264. if (ulExtLen > 0)
  265. {
  266. ulNameLen += ulExtLen + 1;
  267. }
  268. }
  269. // Construct the full name
  270. *pptszName = new TCHAR[ulNameLen + 1];
  271. if(NULL == *pptszName)
  272. {
  273. hr = E_OUTOFMEMORY;
  274. }
  275. }
  276. if (S_OK == hr)
  277. {
  278. _tcscpy(*pptszName, ptszName);
  279. if (ulExtLen > 0)
  280. {
  281. _tcscat(*pptszName, _TEXT("."));
  282. _tcscat(*pptszName, ptszExt);
  283. }
  284. }
  285. // Clean up
  286. if (NULL != ptszExt)
  287. {
  288. delete ptszExt;
  289. ptszExt = NULL;
  290. }
  291. if (NULL != ptszName)
  292. {
  293. delete ptszName;
  294. ptszName = NULL;
  295. }
  296. if (NULL != pwszExt)
  297. {
  298. delete pwszExt;
  299. pwszExt = NULL;
  300. }
  301. if (NULL != pwszName)
  302. {
  303. delete pwszName;
  304. pwszName = NULL;
  305. }
  306. if (NULL != pwszFATCharSet)
  307. {
  308. delete pwszFATCharSet;
  309. pwszFATCharSet = NULL;
  310. }
  311. return hr;
  312. }
  313. //+-------------------------------------------------------------------------
  314. // Function: GetVirtualCtrNodeForTest
  315. //
  316. // Synopsis: Gets a random VirtualCtrNode for doing tests on it.
  317. //
  318. // Arguments: [pVirtualCtrNode] - Pointer to root node of subtree.
  319. // [pgdi] - pointer to data generator object
  320. // [cMin] - Minimum no of VirtualCtrNodes in subtree.
  321. // Should be greater than zero and less than cMax.
  322. // [cMax] - Maximum number of VirtualCtrNodes in subtree.
  323. // Should be greater or equal to cMin
  324. // [ppVirtualCtrNodeForTest] - Returned VirtualCtrNode
  325. //
  326. // Returns: HRESULT
  327. //
  328. // History: 27-Apr-96 NarindK Created.
  329. // 12-Mar-97 MikeW Converted to use CtrNodes not VirtDF's
  330. //
  331. // Notes: If the number of actual maximum number of storages is known,
  332. // provide that to cMax parameter or else pass 0 to have
  333. // EnumerateInMemoryDocfile called for you to know actual number
  334. // of storages (thereby VirtualCtrNodes) in the tree in test. Pl.
  335. // note that if a test provides improper values for cMin/cMax,
  336. // asserts would be thrown by the function. However it is okay to
  337. // provide valid cMin and cMax values which are lesser than actual
  338. // number of VirtualCtrNodes in the tree.
  339. //
  340. // Call OpenRandomVirtualCtrNodeStg after calling this function to
  341. // open up the storage of this random VirtualCtrNode. This might
  342. // not be required if the original VirtualDF tree is being used,
  343. // since during first creation of VirtualDF tree, when all stgs/
  344. // stms are created, they are open. However if a InMemory Docfile
  345. // is generated from Disk DocFile, then only the root storage is
  346. // open, all other storages/streams are closed.
  347. //
  348. // -Pick up a random number cRandom between cMin and cmax by
  349. // DataGen obj pgdi.
  350. // -Assign root VirtualCtrNode of tree to pvcnTrav and increment
  351. // temp variable counter.
  352. // -if counter is equal to cRandom i.e. 1, then return root Virtual
  353. // CtrNode for test.
  354. // -Else start a forever loop till node is found
  355. // -While pvcnTrav's _pvcnChild is not NULL and counter is less
  356. // than cRandom, loop.
  357. // -if counter equals cRandom, then node found, break out of
  358. // forever loop.
  359. // -Else while pvcnTrav's _pvcnSister is eual to NULL, loop
  360. // assinging _pvcnParent to pvcnTrav
  361. // -Assign pvcnTrav's _pvcnSister to pvcnTrav and increment
  362. // counter and go back to start of forever loop
  363. // -With node found, return that to calling function.
  364. //--------------------------------------------------------------------------
  365. HRESULT GetVirtualCtrNodeForTest(
  366. VirtualCtrNode *pVirtualCtrNode,
  367. DG_INTEGER *pdgi,
  368. ULONG cMin,
  369. ULONG cMax,
  370. VirtualCtrNode **ppVirtualCtrNodeForTest)
  371. {
  372. HRESULT hr = S_OK;
  373. VirtualCtrNode *pvcnTrav = NULL;
  374. USHORT usErr = 0;
  375. ULONG counter = 0;
  376. ULONG cRandom = 0;
  377. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetVirtualCtrNodeForTest"));
  378. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  379. DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode ) ;
  380. DH_VDATEPTROUT(ppVirtualCtrNodeForTest, PVCTRNODE) ;
  381. DH_ASSERT(NULL != pdgi);
  382. DH_ASSERT(NULL != pVirtualCtrNode);
  383. DH_ASSERT(NULL != ppVirtualCtrNodeForTest);
  384. // Sanity check: The tree must have atleast one virtualCtrNode in it,
  385. // and cMin must be <= cMax
  386. DH_ASSERT(cMin > 0);
  387. DH_ASSERT(cMin <= cMax || 0 == cMax);
  388. // Initialize out parameter
  389. *ppVirtualCtrNodeForTest = NULL;
  390. // If cMax is 0, find the number of CtrNodes under the given root.
  391. if (S_OK == hr && 0 == cMax)
  392. {
  393. hr = EnumerateInMemoryDocFile(pVirtualCtrNode, &cMax, NULL);
  394. if (S_OK == hr && cMax < cMin)
  395. {
  396. hr = E_UNEXPECTED;
  397. }
  398. }
  399. // Pick up a random number
  400. if(S_OK == hr)
  401. {
  402. usErr = pdgi->Generate(&cRandom, cMin, cMax);
  403. if (DG_RC_SUCCESS != usErr)
  404. {
  405. hr = E_FAIL;
  406. }
  407. }
  408. if(S_OK == hr)
  409. {
  410. pvcnTrav = pVirtualCtrNode;
  411. // pvcnTrav = pVirtualDF->GetVirtualDFRoot();
  412. // DH_ASSERT(NULL != pvcnTrav);
  413. counter++;
  414. if(counter != cRandom)
  415. {
  416. for(;;)
  417. {
  418. DH_ASSERT((NULL != pvcnTrav) && (cRandom >= counter));
  419. while((pvcnTrav->GetFirstChildVirtualCtrNode() != NULL) &&
  420. (counter < cRandom))
  421. {
  422. pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
  423. counter++;
  424. }
  425. if(cRandom == counter)
  426. {
  427. break;
  428. }
  429. while(NULL == pvcnTrav->GetFirstSisterVirtualCtrNode())
  430. {
  431. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  432. DH_ASSERT(NULL != pvcnTrav);
  433. }
  434. DH_ASSERT(NULL != pvcnTrav->GetFirstSisterVirtualCtrNode());
  435. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  436. counter++;
  437. }
  438. }
  439. }
  440. if(S_OK == hr)
  441. {
  442. // Return the out parameter
  443. *ppVirtualCtrNodeForTest = pvcnTrav;
  444. }
  445. return hr;
  446. }
  447. //+-------------------------------------------------------------------------
  448. // Function: GetVirtualCtrNodeForTest
  449. //
  450. // Synopsis: Gets a random VirtualCtrNode for doing tests on it.
  451. //
  452. // Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
  453. // [pgdi] - pointer to data generator object
  454. // [cMin] - Minimum no of VirtualCtrNodes in subtree.
  455. // Should be greater than zero and less than cMax.
  456. // [cMax] - Maximum number of VirtualCtrNodes in subtree.
  457. // Should be greater or equal to cMin
  458. // [ppVirtualCtrNodeForTest] - Returned VirtualCtrNode
  459. //
  460. // Returns: HRESULT
  461. //
  462. // History: 12-Mar-97 MikeW Created
  463. //
  464. // Notes: Just thunk to the version of the routine that takes a
  465. // VirtualCtrNode instead of a VirtualDF.
  466. //--------------------------------------------------------------------------
  467. HRESULT GetVirtualCtrNodeForTest(
  468. VirtualDF *pVirtualDF,
  469. DG_INTEGER *pdgi,
  470. ULONG cMin,
  471. ULONG cMax,
  472. VirtualCtrNode **ppVirtualCtrNodeForTest)
  473. {
  474. DH_VDATEPTRIN(pVirtualDF, *pVirtualDF);
  475. //
  476. // Most of the parameter checking is left to the main version of this
  477. // routine
  478. //
  479. return GetVirtualCtrNodeForTest(
  480. pVirtualDF->GetVirtualDFRoot(),
  481. pdgi,
  482. cMin,
  483. cMax,
  484. ppVirtualCtrNodeForTest);
  485. }
  486. //+-------------------------------------------------------------------------
  487. // Function: GetVirtualStmNodeForTest
  488. //
  489. // Synopsis: Gets a VirtualStmNode for doing tests on it.
  490. //
  491. // Arguments: [pVirtualCtrNode] - Pointer to root node of subtree.
  492. // [pgdi] - pointer to data generator object
  493. // [cMin] - Minimum no of VirtualStmNodes in VirtualDF tree.
  494. // Should be greater than zero and less than cMax.
  495. // [cMax] - Maximum number of VirtualStmNodes in VirtualDF tree.
  496. // Should be greater or equal to cMin
  497. // [ppVirtualCtrNodeParent] - returned parent VirtualCtrNode
  498. // [ppVirtualStmNodeForTest] - returned VirtualStmNode
  499. //
  500. // Returns: HRESULT
  501. //
  502. // History: 27-Apr-96 NarindK Created.
  503. // 12-Mar-97 MikeW Converted to use CtrNodes not VirtDF's
  504. //
  505. // Notes: If the number of actual maximum number of storages is known,
  506. // provide that to cMax parameter or else pass 0 to have
  507. // EnumerateInMemoryDocfile called for you to know actual number
  508. // of storages (thereby VirtualCtrNodes) in the tree in test. Pl.
  509. // note that if a test provides improper values for cMin/cMax,
  510. // asserts would be thrown by the function. However it is okay to
  511. // provide valid cMin and cMax values which are lesser than actual
  512. // number of VirtualStmNodes in the tree.
  513. //
  514. // Also note that this function returns a randomly picked Virtual
  515. // StmNode and its parent VirtualCtrNode (which is also randomly
  516. // picked based on VirtualStmNode). The difference of this func
  517. // from GetVirtualCtrNode is that the random VirtualCtrNode picked
  518. // up is one having streams in it. If none of VirtualCtrNodes
  519. // traversed have any streams in it, this returns an error.
  520. //
  521. // -Pick up a random number cRandomStm between cMin and cMax by
  522. // DataGen obj pgdi.
  523. // -Assign root VirtualCtrNode of tree to pvcnTrav and increment
  524. // temp variable counter.
  525. // -Check in pvcnTrav's _cStreams > 0, if yes, then increment the
  526. // counter by that number.
  527. // -if counter is greater or equal cRandom , check return tha
  528. // desired VirtualStmNode of the root.
  529. // -Else start a forever loop till a valid node is found
  530. // -While pvcnTrav's _pvcnChild is not NULL and counter is less
  531. // than cRandomStg, loop. In the loop, check if pvcnTrav's
  532. // > 0, if yes, update the counter.
  533. // -if counter is greater or equal to cRandomStg, then break
  534. // out of the forever loop
  535. // -Else while pvcnTrav's _pvcnSister is eual to NULL, loop
  536. // assinging _pvcnParent to pvcnTrav
  537. // -Assign pvcnTrav's _pvcnSister to pvcnTrav . If pvcnTrav's
  538. // _cStreams is > 0, then update the counter and go back to
  539. // start of forever loop
  540. // -With parent VirtualCtrNode found, find the number of which
  541. // child VirtualStmNode of it to return by doing cRandomStm
  542. // minus (counter minus pvcnTrav's _cStreams count). Assign this
  543. // calculated value to cChildStm.
  544. // -Assign pvsnTrav the value of pvcnTrav's _pvsnStream and decre
  545. // ment the cChildStm variable.
  546. // -While cChildStm != zer0 and NULL is not equal to pvsnTrav,loop
  547. // -Assign pvsnTrav's _pvsnSister to pvsnTrav.
  548. // -Decrement cChildStm and go back to top of loop.
  549. // -Return the parent VirtualCtrNode and random VirtualStmNode
  550. // to the caller.
  551. //--------------------------------------------------------------------------
  552. HRESULT GetVirtualStmNodeForTest(
  553. VirtualCtrNode *pVirtualCtrNode,
  554. DG_INTEGER *pdgi,
  555. ULONG cMin,
  556. ULONG cMax,
  557. VirtualCtrNode **ppVirtualCtrNodeParent,
  558. VirtualStmNode **ppVirtualStmNodeForTest)
  559. {
  560. HRESULT hr = S_OK;
  561. VirtualCtrNode *pvcnTrav = NULL;
  562. VirtualStmNode *pvsnTrav = NULL;
  563. USHORT usErr = 0;
  564. ULONG counter = 0;
  565. ULONG cRandomStm = 0;
  566. ULONG cChildStm = 0;
  567. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetVirtualStmNodeForTest"));
  568. DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode ) ;
  569. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  570. DH_VDATEPTROUT(ppVirtualStmNodeForTest, PVSTMNODE) ;
  571. DH_VDATEPTROUT(ppVirtualCtrNodeParent, PVCTRNODE) ;
  572. // The pointer to parent pVirtualCtrNodeParent shouldn't be NULL.
  573. // cChildStmToFetch can be zero, in which case first stream is
  574. // is returned.
  575. DH_ASSERT(NULL != pdgi);
  576. DH_ASSERT(NULL != pVirtualCtrNode);
  577. DH_ASSERT(NULL != ppVirtualStmNodeForTest);
  578. DH_ASSERT(NULL != ppVirtualCtrNodeParent);
  579. // Sanity check: cMin must be <= cMax or cMax must be 0
  580. DH_ASSERT(cMin <= cMax || 0 == cMax);
  581. // if cMax is 0, find the number of stm nodes under the root
  582. if(S_OK == hr && cMax == 0)
  583. {
  584. hr = EnumerateInMemoryDocFile(pVirtualCtrNode, NULL, &cMax);
  585. if (S_OK == hr && cMax < cMin)
  586. {
  587. hr = E_UNEXPECTED;
  588. }
  589. }
  590. // Pick up a random number
  591. if(S_OK == hr)
  592. {
  593. // Initialize out parameter
  594. *ppVirtualCtrNodeParent = NULL;
  595. *ppVirtualStmNodeForTest = NULL;
  596. usErr = pdgi->Generate(&cRandomStm, cMin, cMax);
  597. if (DG_RC_SUCCESS != usErr)
  598. {
  599. hr = E_FAIL;
  600. }
  601. }
  602. if(S_OK == hr)
  603. {
  604. pvcnTrav = pVirtualCtrNode;
  605. // pvcnTrav = pVirtualDF->GetVirtualDFRoot();
  606. // DH_ASSERT(NULL != pvcnTrav);
  607. if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
  608. {
  609. counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
  610. }
  611. }
  612. if(counter < cRandomStm)
  613. {
  614. for(;;)
  615. {
  616. DH_ASSERT(NULL != pvcnTrav);
  617. while((pvcnTrav->GetFirstChildVirtualCtrNode() != NULL) &&
  618. (counter < cRandomStm))
  619. {
  620. pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
  621. if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
  622. {
  623. counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
  624. }
  625. }
  626. if(counter >= cRandomStm)
  627. {
  628. break;
  629. }
  630. while(NULL == pvcnTrav->GetFirstSisterVirtualCtrNode())
  631. {
  632. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  633. DH_ASSERT(NULL != pvcnTrav);
  634. }
  635. DH_ASSERT(NULL != pvcnTrav->GetFirstSisterVirtualCtrNode());
  636. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  637. if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
  638. {
  639. counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
  640. }
  641. }
  642. }
  643. if(S_OK == hr)
  644. {
  645. // Calculate which child stream needs to be picked up
  646. cChildStm = cRandomStm -
  647. (counter - pvcnTrav->GetVirtualCtrNodeStreamCount());
  648. pvsnTrav = pvcnTrav->GetFirstChildVirtualStmNode();
  649. cChildStm--;
  650. DH_ASSERT(NULL != pvsnTrav);
  651. while((0 != cChildStm) && (NULL != pvsnTrav))
  652. {
  653. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
  654. cChildStm--;
  655. }
  656. // Return the out parameter
  657. *ppVirtualCtrNodeParent = pvcnTrav;
  658. *ppVirtualStmNodeForTest = pvsnTrav;
  659. }
  660. return hr;
  661. }
  662. //+-------------------------------------------------------------------------
  663. // Function: GetVirtualStmNodeForTest
  664. //
  665. // Synopsis: Gets a VirtualStmNode for doing tests on it.
  666. //
  667. // Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
  668. // [pgdi] - pointer to data generator object
  669. // [cMin] - Minimum no of VirtualStmNodes in VirtualDF tree.
  670. // Should be greater than zero and less than cMax.
  671. // [cMax] - Maximum number of VirtualStmNodes in VirtualDF tree.
  672. // Should be greater or equal to cMin
  673. // [ppVirtualCtrNodeParent] - returned parent VirtualCtrNode
  674. // [ppVirtualStmNodeForTest] - returned VirtualStmNode
  675. //
  676. // Returns: HRESULT
  677. //
  678. // History: 12-Mar-97 MikeW Created
  679. //
  680. // Notes: Just thunk to the version of the routine that takes a
  681. // VirtualCtrNode instead of a VirtualDF.
  682. //--------------------------------------------------------------------------
  683. HRESULT GetVirtualStmNodeForTest(
  684. VirtualDF *pVirtualDF,
  685. DG_INTEGER *pdgi,
  686. ULONG cMin,
  687. ULONG cMax,
  688. VirtualCtrNode **ppVirtualCtrNodeParent,
  689. VirtualStmNode **ppVirtualStmNodeForTest)
  690. {
  691. DH_VDATEPTRIN(pVirtualDF, *pVirtualDF);
  692. //
  693. // Most of the parameter checking is left to the main version of this
  694. // routine
  695. //
  696. return GetVirtualStmNodeForTest(
  697. pVirtualDF->GetVirtualDFRoot(),
  698. pdgi,
  699. cMin,
  700. cMax,
  701. ppVirtualCtrNodeParent,
  702. ppVirtualStmNodeForTest);
  703. }
  704. //+-------------------------------------------------------------------------
  705. // Function: DestroyStorage
  706. //
  707. // Synopsis: Destorys a VirtualCtrNode and associated IStorage.
  708. //
  709. // Arguments: [pVirtualDF] - pointer to VirtualDocFile tree.
  710. // [pVirtualCtrNode] - Pointer to VirtualCtrNode
  711. //
  712. // Returns: HRESULT
  713. //
  714. // History: 29-Apr-96 NarindK Created.
  715. //
  716. // Notes: Call VirtualCtrNode::Destroy to destroy the node.
  717. // Call VirtualDF::DeleteVirtualDocFileTree to delete the corres-
  718. // ponding VirtualCtrNode from the VirtualDF tree.
  719. //--------------------------------------------------------------------------
  720. HRESULT DestroyStorage(
  721. VirtualDF *pVirtualDF,
  722. VirtualCtrNode *pVirtualCtrNode)
  723. {
  724. HRESULT hr = S_OK;
  725. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DestroyStorage"));
  726. DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
  727. DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
  728. DH_ASSERT(NULL != pVirtualCtrNode);
  729. DH_ASSERT(NULL != pVirtualDF);
  730. if(S_OK == hr)
  731. {
  732. hr = pVirtualCtrNode->Destroy();
  733. DH_HRCHECK(hr, TEXT("pVirtualCtrNode->Destroy()")) ;
  734. }
  735. if(S_OK == hr)
  736. {
  737. // Now adjust the VirtualDocFile tree. This will decrease the
  738. // _cChildren variable value of the parent VrtualCtrNode too.
  739. hr = pVirtualDF->DeleteVirtualDocFileTree(pVirtualCtrNode);
  740. DH_HRCHECK(hr, TEXT("pTestVirtualDF->DeleteVirtualFileDocTree")) ;
  741. }
  742. return hr;
  743. }
  744. //+-------------------------------------------------------------------------
  745. // Function: DestroyStream
  746. //
  747. // Synopsis: Destorys a VirtualStmNode and associated IStream.
  748. //
  749. // Arguments: [pVirtualDF] - pointer to VirtualDF tree
  750. // [pVirtualStmNode] - Pointer to VirtualStmNode to be destoryed
  751. //
  752. // Returns: HRESULT
  753. //
  754. // History: 9-July-96 NarindK Created.
  755. //
  756. // Notes: Call VirtualStmNode::Destroy to destroy the IStream.
  757. // Call VirtualDF::DeleteVirtualCtrNodeStreamNode to delete corres-
  758. // ponding VirtualCtrNode from the VirtualDF tree.
  759. //--------------------------------------------------------------------------
  760. HRESULT DestroyStream(
  761. VirtualDF *pVirtualDF,
  762. VirtualStmNode *pVirtualStmNode)
  763. {
  764. HRESULT hr = S_OK;
  765. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DestroyStream"));
  766. DH_VDATEPTRIN(pVirtualStmNode, VirtualStmNode) ;
  767. DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
  768. DH_ASSERT(NULL != pVirtualDF);
  769. DH_ASSERT(NULL != pVirtualStmNode);
  770. if(S_OK == hr)
  771. {
  772. hr = pVirtualStmNode->Destroy();
  773. DH_HRCHECK(hr, TEXT("pVirtualStmNode->Destroy()")) ;
  774. }
  775. if(S_OK == hr)
  776. {
  777. // Now adjust the VirtualDocFile tree. This will decrease the
  778. // _cStreams variable value of the parent VirtualCtrNode too.
  779. hr = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pVirtualStmNode);
  780. DH_HRCHECK(hr, TEXT("pTestVirtualDF->DeleteVirtualCtrNodeStreamNode")) ;
  781. }
  782. return hr;
  783. }
  784. //+-------------------------------------------------------------------------
  785. // Function: AddStorage
  786. //
  787. // Synopsis: Adds a VirtualCtrNode and associated IStorage.
  788. //
  789. // Arguments: [pVirtualCtrNode] - Pointer to existing VirtualCtrNode
  790. // [ppNewVirtualCtrNode] _ Returned new VirtualCtrNode
  791. // [pName] - Name of new storage
  792. // [grfMode] - Mode in which new storage is to be opened
  793. //
  794. // Returns: HRESULT
  795. //
  796. // History: 29-Apr-96 NarindK Created.
  797. //
  798. // Notes: - Creates a simple new VirtualCtrNode and initializes it with
  799. // name passed in. Its _cChildren and _cStreams are initialized
  800. // to zero.
  801. // - Append the newly created node pvcnNew to its parent node
  802. // pVirtualCtrNode. This would be appended as _pvcnChild or
  803. // as _pvcnSister of existing old sister as the case might be.
  804. // - Increase the parent's pVirtualCtrNode's _cChildren variable
  805. // indicating the new VirtualCtrNode added.
  806. // - Create a disk IStorage corresponding to this VirtualCtrNode
  807. // based on passed in grfmode.
  808. // - If CreateStorage call returns STG_S_CONVERTED, it indicates
  809. // that an existing stream with specified name was replaced witho
  810. // a new storage object containing a single stream called
  811. // CONTENTS. If so, adjust the VirtualDF tree.
  812. // - If successful, copy pvcnNew into out parameter *ppNewVirtual
  813. // CtrNode, else delete the VirtualCtrNode allocated earlier.
  814. // Note: Please note that the CRC for node(s) created is not set.
  815. //--------------------------------------------------------------------------
  816. HRESULT AddStorage(
  817. VirtualDF *pVirtualDF,
  818. VirtualCtrNode *pVirtualCtrNode,
  819. LPTSTR pName,
  820. DWORD grfMode,
  821. VirtualCtrNode **ppNewVirtualCtrNode)
  822. {
  823. HRESULT hr = S_OK;
  824. HRESULT hrTemp = S_OK;
  825. VirtualCtrNode *pvcnNew = NULL;
  826. VirtualStmNode *pvsnOld = NULL;
  827. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::AddStorage"));
  828. DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
  829. DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
  830. DH_VDATEPTROUT(ppNewVirtualCtrNode, PVCTRNODE) ;
  831. DH_VDATESTRINGPTR(pName);
  832. DH_ASSERT(NULL != pVirtualDF);
  833. DH_ASSERT(NULL != pVirtualCtrNode);
  834. DH_ASSERT(NULL != ppNewVirtualCtrNode);
  835. if(S_OK == hr)
  836. {
  837. // Initialize out parameter
  838. *ppNewVirtualCtrNode = NULL;
  839. // Allocate and Initialize new VirtualCtrNode
  840. hr = GenVirtualCtrNode(pName, &pvcnNew);
  841. DH_HRCHECK(hr, TEXT("GenVirtualCtrNode")) ;
  842. }
  843. // Append new VirtualCtr Node
  844. if(S_OK == hr)
  845. {
  846. if(0 == pVirtualCtrNode->GetVirtualCtrNodeChildrenCount())
  847. {
  848. hr = pVirtualCtrNode->AppendChildCtr(pvcnNew);
  849. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ;
  850. }
  851. else
  852. {
  853. hr=pVirtualCtrNode->GetFirstChildVirtualCtrNode()->AppendSisterCtr(
  854. pvcnNew);
  855. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ;
  856. }
  857. }
  858. if(S_OK == hr)
  859. {
  860. // Increment the _cChildren variable of parent VirtualCtrNode
  861. pVirtualCtrNode->IncreaseChildrenStgCount();
  862. }
  863. // Call VirtualCtrNode::Create to create a corresponding Storage on disk.
  864. if(S_OK == hr)
  865. {
  866. hr = pvcnNew->Create(
  867. grfMode,
  868. 0,
  869. 0);
  870. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Create")) ;
  871. }
  872. // Fill in the output parameter
  873. if((S_OK == hr) || (STG_S_CONVERTED == hr))
  874. {
  875. if(STG_S_CONVERTED == hr)
  876. {
  877. VirtualStmNode *pvsnNew = NULL;
  878. ULONG cb = 0;
  879. // Remember hr
  880. hrTemp = hr;
  881. // Delete the VirtualStmNode with stream that is converted to this
  882. // storage. First find the corresponding VirtualStmNode with same
  883. // name.
  884. pvsnOld =
  885. pvcnNew->GetParentVirtualCtrNode()->GetFirstChildVirtualStmNode();
  886. DH_ASSERT(NULL != pvsnOld);
  887. while((NULL != pvsnOld) &&
  888. (0 != _tcscmp(pName, pvsnOld->GetVirtualStmNodeName())))
  889. {
  890. pvsnOld = pvsnOld->GetFirstSisterVirtualStmNode();
  891. }
  892. // Delete the old VirtualStmNode
  893. if((NULL != pvsnOld) &&
  894. (0 == _tcscmp(pName, pvsnOld->GetVirtualStmNodeName())))
  895. {
  896. // Remember size of VirtualStmNode
  897. cb = pvsnOld->GetVirtualStmNodeSize();
  898. hr = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pvsnOld);
  899. }
  900. else
  901. {
  902. hr = E_FAIL;
  903. }
  904. // Generate a new VirtualStmNode for CONTENTS stream generated
  905. if(S_OK == hr)
  906. {
  907. hr = GenVirtualStmNode(TEXT("CONTENTS"), cb, &pvsnNew);
  908. if(S_OK == hr)
  909. {
  910. hr = pvcnNew->AppendFirstChildStm(pvsnNew);
  911. }
  912. if(S_OK == hr)
  913. {
  914. pvcnNew->IncreaseChildrenStmCount();
  915. }
  916. }
  917. }
  918. if(S_OK == hr)
  919. {
  920. *ppNewVirtualCtrNode = pvcnNew;
  921. if(STG_S_CONVERTED == hrTemp)
  922. {
  923. hr = hrTemp;
  924. }
  925. }
  926. }
  927. else
  928. {
  929. // Storage wasn't created successfully, delete the VirtualCtrNode
  930. // being created. Adjust the VirtualDocFile tree. This will decrease
  931. // _cChildren variable value of the parent VirtualCtrNode too.
  932. hrTemp = pVirtualDF->DeleteVirtualDocFileTree(pvcnNew);
  933. DH_HRCHECK(hrTemp, TEXT("pVirtualDF->DeleteVirtualFileDocTree")) ;
  934. }
  935. return hr;
  936. }
  937. //+-------------------------------------------------------------------------
  938. // Function: AddStream
  939. //
  940. // Synopsis: Adds a VirtualStmNode & associated IStream to a VirtualCtrNode.
  941. // Set the size of stream if cbSize is nonzero, but doesn't write
  942. // into it.
  943. //
  944. // Arguments: [pVirtualCtrNode] - Pointer to existing VirtualCtrNode
  945. // [ppNewVirtualStmNode] - Returned new VirtualStmNode
  946. // [pName] - Name of new stream
  947. // [grfMode] - Mode of new stream
  948. // [cbSize] - Size of new stream
  949. //
  950. // Returns: HRESULT
  951. //
  952. // History: 29-Apr-96 NarindK Created.
  953. //
  954. // Notes: - Creates a simple new VirtualStmNode and initializes it with
  955. // name & cbSize passed in.
  956. // - Append the newly created node pvsnNew to its parent node
  957. // pVirtualCtrNode. This would be appended as _pvsnStream or
  958. // as _pvsnSister of existing old sister as the case might be.
  959. // - Increase the parent's pVirtualCtrNode's _cStreams variable
  960. // indicating the new VirtualStmNode added.
  961. // - Create a disk IStream corresponding to this VirtualStmNode.
  962. // based on passed in grfmode.
  963. // - If cbSize is non zero, do SetSize on stream.
  964. // - If successful, copy pvsnNew into out parameter *ppNewVirtual
  965. // StmNode, else delete the VirtualStmNode allocated earlier.
  966. // Note: Please note that the CRC for node created is not set.
  967. //--------------------------------------------------------------------------
  968. HRESULT AddStream(
  969. VirtualDF *pVirtualDF,
  970. VirtualCtrNode *pVirtualCtrNode,
  971. LPTSTR pName,
  972. ULONG cbSize,
  973. DWORD grfMode,
  974. VirtualStmNode **ppNewVirtualStmNode)
  975. {
  976. HRESULT hr = S_OK;
  977. HRESULT hrTemp = S_OK;
  978. VirtualStmNode *pvsnNew = NULL;
  979. ULARGE_INTEGER uli;
  980. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::AddStream"));
  981. DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
  982. DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
  983. DH_VDATEPTROUT(ppNewVirtualStmNode, PVSTMNODE) ;
  984. DH_VDATESTRINGPTR(pName);
  985. DH_ASSERT(NULL != pVirtualCtrNode);
  986. DH_ASSERT(NULL != ppNewVirtualStmNode);
  987. if(S_OK == hr)
  988. {
  989. // Initialize out parameter
  990. *ppNewVirtualStmNode = NULL;
  991. // Allocate and Initialize new VirtualStmNode
  992. hr = GenVirtualStmNode(pName, cbSize, &pvsnNew);
  993. DH_HRCHECK(hr, TEXT("GenVirtualStmNode")) ;
  994. }
  995. // Append new VirtualStm Node
  996. if(S_OK == hr)
  997. {
  998. if(0 == pVirtualCtrNode->GetVirtualCtrNodeStreamCount())
  999. {
  1000. hr = pVirtualCtrNode->AppendFirstChildStm(pvsnNew);
  1001. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ;
  1002. }
  1003. else
  1004. {
  1005. hr=pVirtualCtrNode->GetFirstChildVirtualStmNode()->AppendSisterStm(
  1006. pvsnNew);
  1007. DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ;
  1008. }
  1009. }
  1010. if(S_OK == hr)
  1011. {
  1012. // Increment the _cStreams variable of parent VirtualCtrNode
  1013. pVirtualCtrNode->IncreaseChildrenStmCount();
  1014. }
  1015. // Call VirtualStmNode::Create to create a corresponding Stream on disk.
  1016. if(S_OK == hr)
  1017. {
  1018. hr = pvsnNew->Create(
  1019. grfMode,
  1020. 0,
  1021. 0);
  1022. DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ;
  1023. }
  1024. // Call VirtualStmNode::SetSize to set size of stream.
  1025. if((S_OK == hr) && (0 != cbSize))
  1026. {
  1027. ULISet32(uli, cbSize);
  1028. hr = pvsnNew->SetSize(uli);
  1029. DH_HRCHECK(hr, TEXT("VirtualStmNode::SetSize")) ;
  1030. }
  1031. // Fill in the output parameter
  1032. if(S_OK == hr)
  1033. {
  1034. *ppNewVirtualStmNode = pvsnNew;
  1035. }
  1036. else
  1037. {
  1038. // Stream wasn't created successfully, so delete the VirtualStmNode.
  1039. // Adjust the VirtualDocFile tree. This will decrease the
  1040. // _cStreams variable value of the parent VirtualCtrNode too.
  1041. hrTemp = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pvsnNew);
  1042. DH_HRCHECK(
  1043. hrTemp,
  1044. TEXT("pVirtualDF->DeleteVirtualCtrNodeStreamNode")) ;
  1045. }
  1046. return hr;
  1047. }
  1048. //+-------------------------------------------------------------------------
  1049. // Function: CalculateCRCForName
  1050. //
  1051. // Synopsis: Calulates CRC for a IStorage/IStream's name.
  1052. //
  1053. // Arguments: [ptcsName] - pointer to name of stream
  1054. // [pdwCRCForName] - pointer to CRC
  1055. //
  1056. // Returns: HRESULT
  1057. //
  1058. // History: 8-May-96 NarindK Created.
  1059. //
  1060. // Notes: This is a common function used by other CRC utilities function
  1061. // and also called directly is virtdf.cxx to calculate in memory
  1062. // CRC for VirtualCtrNode. Since for VirtualCtrNodes/IStorages,
  1063. // we CRC only name, we could use this function to calculate CRC.
  1064. // - Assign passed in name to a temp. variable ptszTemp.
  1065. // - Loop while *ptszTemp is not NULL, and call CRC_CALC macro
  1066. // to generate CRC for the name.
  1067. //--------------------------------------------------------------------------
  1068. HRESULT CalculateCRCForName(
  1069. const LPTSTR ptcsName,
  1070. DWORD *pdwCRCForName)
  1071. {
  1072. HRESULT hr = S_OK;
  1073. LPTSTR ptszTemp = NULL;
  1074. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForName"));
  1075. DH_VDATESTRINGPTR(ptcsName) ;
  1076. DH_VDATEPTROUT(pdwCRCForName, DWORD) ;
  1077. DH_ASSERT(NULL != ptcsName);
  1078. DH_ASSERT(NULL != pdwCRCForName);
  1079. if(S_OK == hr)
  1080. {
  1081. // Initialize out parameter
  1082. *pdwCRCForName = CRC_PRECONDITION;
  1083. ptszTemp = ptcsName;
  1084. while(NULL != *ptszTemp)
  1085. {
  1086. CRC_CALC(*pdwCRCForName, (BYTE)*ptszTemp++);
  1087. }
  1088. }
  1089. return hr;
  1090. }
  1091. //+-------------------------------------------------------------------------
  1092. // Function: CalculateCRCForDataBuffer
  1093. //
  1094. // Synopsis: Calulates CRC for a given data Buffer.
  1095. //
  1096. // Arguments: [ptszBuffer] - pointer to data buffer.
  1097. // [culBufferSize] - size of data buffer
  1098. // [pdwCRCForName] - pointer to CRC
  1099. //
  1100. // Returns: HRESULT
  1101. //
  1102. // History: 8-May-96 NarindK Created.
  1103. //
  1104. // Notes: This is a common function used by other CRC utilities function
  1105. // - Assign pointer to passed in buffer to pByteBuffer.
  1106. // - Loop for culBufferSize, and call CRC_CALC macro
  1107. // to generate CRC for the data buffer.
  1108. //--------------------------------------------------------------------------
  1109. HRESULT CalculateCRCForDataBuffer(
  1110. const LPTSTR ptszBuffer,
  1111. ULONG culBufferSize,
  1112. DWORD *pdwCRCForDataBuffer)
  1113. {
  1114. HRESULT hr = S_OK;
  1115. LPBYTE pByteBuffer = NULL;
  1116. ULONG i = 0;
  1117. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForDataBuffer"));
  1118. DH_VDATEPTRIN(ptszBuffer, TCHAR);
  1119. DH_VDATEPTROUT(pdwCRCForDataBuffer, DWORD) ;
  1120. DH_ASSERT(NULL != ptszBuffer);
  1121. DH_ASSERT(NULL != pdwCRCForDataBuffer);
  1122. // calculate the CRC for data of stream.
  1123. if(S_OK == hr)
  1124. {
  1125. // Initialize out parameter
  1126. *pdwCRCForDataBuffer = CRC_PRECONDITION;
  1127. pByteBuffer = (BYTE *)ptszBuffer;
  1128. if ( S_OK == hr )
  1129. {
  1130. for (i=0; i < culBufferSize; i++)
  1131. {
  1132. CRC_CALC(*pdwCRCForDataBuffer, pByteBuffer[i]);
  1133. }
  1134. }
  1135. }
  1136. return hr;
  1137. }
  1138. //+-------------------------------------------------------------------------
  1139. // Function: CalculateInMemoryCRCForStg
  1140. //
  1141. // Synopsis: Calulate in memory CRC for a Stroage name
  1142. //
  1143. // Arguments: [pvsn] - Pointer to VirtualCtrNode.
  1144. // [pdwCRC] - pointer to computed CRC
  1145. //
  1146. // Returns: HRESULT
  1147. //
  1148. // History: 8-May-96 NarindK Created.
  1149. //
  1150. // Notes: For IStorages, only name is CRC'd.
  1151. // - Call CalculateCRCForName to calculate CRC
  1152. //
  1153. //--------------------------------------------------------------------------
  1154. HRESULT CalculateInMemoryCRCForStg(
  1155. VirtualCtrNode *pvcn,
  1156. DWORD *pdwCRC)
  1157. {
  1158. HRESULT hr = S_OK;
  1159. DH_FUNCENTRY(NULL, DH_LVL_DFLIB,_TEXT("CalculateInMemoryCRCForStg"));
  1160. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1161. DH_VDATEPTROUT(pdwCRC, DWORD) ;
  1162. DH_ASSERT(NULL != pvcn);
  1163. DH_ASSERT(NULL != pdwCRC);
  1164. // Now calulate the CRC for name of storage.
  1165. if ( S_OK == hr )
  1166. {
  1167. // Initialize out parameter
  1168. *pdwCRC = CRC_PRECONDITION;
  1169. hr = CalculateCRCForName(pvcn->GetVirtualCtrNodeName(), pdwCRC);
  1170. DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
  1171. }
  1172. return hr;
  1173. }
  1174. //+-------------------------------------------------------------------------
  1175. // Function: CalculateInMemoryCRCForStm
  1176. //
  1177. // Synopsis: Calulates CRC for a IStream's data and name.
  1178. //
  1179. // Arguments: [pvsn] - Pointer to VirtualStmNode.
  1180. // [ptszBuffer] - Pointer to buffer used to write into stream
  1181. // [culBufferSize] - Pointer to buffer size used to calculate CRC
  1182. // [pdwCRC] - pointer to computed CRC
  1183. //
  1184. // Returns: HRESULT
  1185. //
  1186. // History: 8-May-96 NarindK Created.
  1187. //
  1188. // Notes: For IStreams, both name and data of stream are CRC'd. Ensure
  1189. // that stream is opened before this function is called.
  1190. //
  1191. // This function is presently called directly in virtdf.cxx to
  1192. // calculate in memory CRC for VirtualStmNode. Since for the
  1193. // VirtualStmNodes/IStreams, we CRC name and data, we could use
  1194. // this function to calculate CRC if we pass it the stream name,
  1195. // buffer, size of buffer as input parameters.
  1196. // - Call CalculateCRCForDataBuffer to calculate dwCRCForData.
  1197. // - Call CalculateCRCForName to calculate dwCRCForName.
  1198. // - Compute the total CRC based on above two CRC's.
  1199. //
  1200. //--------------------------------------------------------------------------
  1201. HRESULT CalculateInMemoryCRCForStm(
  1202. VirtualStmNode *pvsn,
  1203. const LPTSTR ptszBuffer,
  1204. ULONG culBufferSize,
  1205. DWCRCSTM *pdwCRC)
  1206. {
  1207. HRESULT hr = S_OK;
  1208. DWORD dwCRCForData= CRC_PRECONDITION;
  1209. DWORD dwCRCForName= CRC_PRECONDITION;
  1210. ULONG i = 0;
  1211. DH_FUNCENTRY(NULL, DH_LVL_DFLIB,_TEXT("CalculateInMemoryCRCForStm"));
  1212. DH_VDATEPTRIN(pvsn, VirtualStmNode) ;
  1213. DH_VDATEPTROUT(pdwCRC, DWORD) ;
  1214. DH_VDATEPTRIN(ptszBuffer, TCHAR);
  1215. DH_ASSERT(NULL != pvsn);
  1216. DH_ASSERT(NULL != ptszBuffer);
  1217. DH_ASSERT(NULL != pdwCRC);
  1218. if(S_OK == hr)
  1219. {
  1220. // Initialize CRC values to CRC_PRECONDITION
  1221. pdwCRC->dwCRCName = pdwCRC->dwCRCData = pdwCRC->dwCRCSum = CRC_PRECONDITION;
  1222. }
  1223. // First calculate the CRC for data of stream.
  1224. if(S_OK == hr)
  1225. {
  1226. hr = CalculateCRCForDataBuffer(ptszBuffer, culBufferSize,&dwCRCForData);
  1227. DH_HRCHECK(hr, TEXT("CalculateCRCForDataBuffer")) ;
  1228. }
  1229. // Now calulate the CRC for name of stream.
  1230. if ( S_OK == hr )
  1231. {
  1232. hr = CalculateCRCForName(pvsn->GetVirtualStmNodeName(), &dwCRCForName);
  1233. DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
  1234. }
  1235. // Compute the total CRC value based on above two CRC's and record
  1236. // individual CRC's for name and data
  1237. if ( S_OK == hr )
  1238. {
  1239. pdwCRC->dwCRCData = dwCRCForData;
  1240. pdwCRC->dwCRCName = dwCRCForName;
  1241. MUNGECRC(pdwCRC->dwCRCSum,dwCRCForData);
  1242. MUNGECRC(pdwCRC->dwCRCSum,dwCRCForName);
  1243. }
  1244. return hr;
  1245. }
  1246. //+-------------------------------------------------------------------------
  1247. // Function: CalculateStreamDataCRC
  1248. //
  1249. // Synopsis: Calculates the CRC of the stream data,
  1250. // using the IStream given (independent of virtualdf stuff)
  1251. //
  1252. // Arguments: [pStm] - the Stream
  1253. // [dwSize] - the size if known, or zero => call Stat
  1254. // [pdwCRC] - pointer to data CRC
  1255. // [dwChunkSize] - if >0 the stream will be read at chunks
  1256. // of this size.
  1257. //
  1258. // Returns: HRESULT
  1259. //
  1260. // History: 02-Apr-98 georgis Created.
  1261. //
  1262. //--------------------------------------------------------------------------
  1263. HRESULT CalculateStreamDataCRC(IStream *pStm,
  1264. DWORD dwSize,
  1265. DWORD *pdwCRC,
  1266. DWORD dwChunkSize)
  1267. {
  1268. HRESULT hr=S_OK;
  1269. STATSTG statstg;
  1270. DWORD dwBufferSize=0;
  1271. BYTE *pBuffer=NULL;
  1272. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateStreamDataCRC"));
  1273. DH_VDATEPTRIN(pStm, IStream);
  1274. DH_VDATEPTROUT(pdwCRC, DWORD);
  1275. *pdwCRC=0; // invalid CRC
  1276. // Ask for size if unknown (zero passed)
  1277. if (0==dwSize)
  1278. {
  1279. hr = pStm->Stat(&statstg, STATFLAG_NONAME);
  1280. DH_HRCHECK(hr, TEXT("IStorage::Stat"));
  1281. dwSize=statstg.cbSize.LowPart; //BIGBUG: assume LowPart only
  1282. }
  1283. // Allocate the buffer
  1284. if (S_OK == hr)
  1285. {
  1286. if (dwChunkSize>0)
  1287. {
  1288. dwBufferSize=dwChunkSize;
  1289. }
  1290. else
  1291. {
  1292. dwBufferSize=dwSize;
  1293. }
  1294. pBuffer = new BYTE[dwBufferSize];
  1295. if (NULL==pBuffer)
  1296. {
  1297. hr=E_OUTOFMEMORY;
  1298. DH_HRCHECK(hr,TEXT("new"));
  1299. }
  1300. }
  1301. // Reset the stream
  1302. if (S_OK== hr)
  1303. {
  1304. LARGE_INTEGER li;
  1305. LISet32(li,0L);
  1306. hr=pStm->Seek(li,STREAM_SEEK_SET,NULL);
  1307. DH_HRCHECK(hr,TEXT("Seek"));
  1308. };
  1309. // Do the actual read, calculate the CRC
  1310. if (S_OK == hr)
  1311. {
  1312. DWORD dwTotalRead=0;
  1313. DWORD dwRead=0;
  1314. register DWORD dwCRC=CRC_PRECONDITION;
  1315. while ((S_OK==hr)&&(dwTotalRead < dwSize))
  1316. {
  1317. hr=pStm->Read(pBuffer, dwBufferSize, &dwRead);
  1318. DH_HRCHECK(hr,TEXT("Read"));
  1319. dwTotalRead+=dwRead;
  1320. if (S_OK==hr)
  1321. {
  1322. for (register int i=0; i<dwRead; i++)
  1323. {
  1324. CRC_CALC(dwCRC,pBuffer[i]);
  1325. }
  1326. };
  1327. }
  1328. *pdwCRC=dwCRC;
  1329. }
  1330. if (NULL!=pBuffer)
  1331. {
  1332. delete pBuffer;
  1333. };
  1334. return hr;
  1335. }
  1336. //+-------------------------------------------------------------------------
  1337. // Function: ReadAndCalculateDiskCRCForStm
  1338. //
  1339. // Synopsis: Calulates CRC for a IStream's name and data.
  1340. //
  1341. // Arguments: [pvsn] - pointer to VirtualStmNode
  1342. // [pdwCRC] - pointer to CRC
  1343. //
  1344. // Returns: HRESULT
  1345. //
  1346. // History: 8-May-96 NarindK Created.
  1347. // 2-Apr-98 georgis use VirtualStmNode::UpdateCRC
  1348. //
  1349. // Notes: VirtualStmNode::UpdateCRC() actually obsoletes this function,
  1350. // It remains for compatibility with the old tests
  1351. //
  1352. // BUGBUG: all the DWCRCSTM structures are called dw* and
  1353. // all pointers to them pdw* . We should fix this
  1354. //
  1355. //--------------------------------------------------------------------------
  1356. HRESULT ReadAndCalculateDiskCRCForStm(
  1357. VirtualStmNode *pvsn,
  1358. DWCRCSTM *pdwCRC,
  1359. DWORD dwChunkSize)
  1360. {
  1361. HRESULT hr = S_OK;
  1362. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ReadAndCalculateDiskCRCForStm"));
  1363. DH_VDATEPTRIN(pvsn, VirtualStmNode) ;
  1364. DH_VDATEPTROUT(pdwCRC, DWCRCSTM) ;
  1365. hr=pvsn->UpdateCRC(dwChunkSize);
  1366. DH_HRCHECK(hr, TEXT("pvsn->UpdateCRC")) ;
  1367. pdwCRC->dwCRCSum =pvsn->GetVirtualStmNodeCRC();
  1368. pdwCRC->dwCRCName=pvsn->GetVirtualStmNodeCRCName();
  1369. pdwCRC->dwCRCData=pvsn->GetVirtualStmNodeCRCData();
  1370. return hr;
  1371. }
  1372. //+-------------------------------------------------------------------------
  1373. // Function: CalculateDiskCRCForStg
  1374. //
  1375. // Synopsis: Calulates CRC for a IStrorage's name.
  1376. //
  1377. // Arguments: [pvcn] - pointer to VirtualCtrNode
  1378. // [pdwCRCForName] - pointer to CRC
  1379. //
  1380. // Returns: HRESULT
  1381. //
  1382. // History: 8-May-96 NarindK Created.
  1383. //
  1384. // Notes: For IStorages, only name is CRC'd.
  1385. // -Call VirtualCtrNode::Stat to get information about storage.
  1386. // -Call CalculateCRCForName to calculate CRC for name of the
  1387. // storage obtained from STATSTG structure.
  1388. //--------------------------------------------------------------------------
  1389. HRESULT CalculateDiskCRCForStg(
  1390. VirtualCtrNode *pvcn,
  1391. DWORD *pdwCRCForName)
  1392. {
  1393. HRESULT hr = S_OK;
  1394. LPMALLOC pMalloc = NULL;
  1395. LPTSTR ptszName = NULL;
  1396. STATSTG statStg;
  1397. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateDiskCRCForStg"));
  1398. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1399. DH_VDATEPTROUT(pdwCRCForName, DWORD) ;
  1400. // For IStorages, only name are CRC'd.
  1401. DH_ASSERT(NULL != pvcn);
  1402. DH_ASSERT(NULL != pdwCRCForName);
  1403. // Initialization
  1404. statStg.pwcsName = NULL;
  1405. // Get the statistics about ths opened stream
  1406. if(S_OK == hr)
  1407. {
  1408. // Initialize out parameter
  1409. *pdwCRCForName = CRC_PRECONDITION;
  1410. hr = pvcn->Stat(&statStg, STATFLAG_DEFAULT);
  1411. DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
  1412. }
  1413. // First get pMalloc that would be used to free up the name string from
  1414. // STATSTG.
  1415. if ( S_OK == hr )
  1416. {
  1417. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  1418. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  1419. }
  1420. if(S_OK == hr)
  1421. {
  1422. //Convert WCHAR to TCHAR
  1423. hr = OleStringToTString(statStg.pwcsName, &ptszName);
  1424. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  1425. }
  1426. if((S_OK == hr) && (NULL != ptszName))
  1427. {
  1428. hr = CalculateCRCForName(ptszName, pdwCRCForName);
  1429. DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
  1430. }
  1431. // Clean up
  1432. if ( NULL != statStg.pwcsName)
  1433. {
  1434. pMalloc->Free(statStg.pwcsName);
  1435. statStg.pwcsName = NULL;
  1436. }
  1437. if(NULL != pMalloc)
  1438. {
  1439. pMalloc->Release();
  1440. pMalloc = NULL;
  1441. }
  1442. if(NULL != ptszName)
  1443. {
  1444. delete ptszName;
  1445. ptszName = NULL;
  1446. }
  1447. return hr;
  1448. }
  1449. //+-------------------------------------------------------------------------
  1450. // Function: EnumerateInMemoryDocFile
  1451. //
  1452. // Synopsis: Enumerates a in memory docfile.
  1453. //
  1454. // Arguments: [pvcn] - pointer to VirtualCtrNode
  1455. // [pdwNumStg] - pointer to number of Storages in doc hierarchy.
  1456. // [pdwNumStm] - pointer to number of streams in doc hierarchy
  1457. //
  1458. // Returns: HRESULT
  1459. //
  1460. // History: 3-June-96 NarindK Created.
  1461. //
  1462. // Notes: pdwNumStg, pdwNumStm may be NULL if user is not interested in
  1463. // these values to be returned back. Includes the passed in pvcn
  1464. // in pdwnumStg count.
  1465. // -Count the passed in storage pvcn as 1 in pNumStg count.
  1466. // -Check if pvcn's _pvsnStream is NULL or not by calling the
  1467. // GetFirstChildVirtualStmNode() function, assign to pvsnTrav var
  1468. // -If it is not NULL,loop till pvsnTrav is not NULL.
  1469. // -Increment pNumStm for stream found for this pvcn.
  1470. // -Assign pvcnTrav->_pvsnSister (GetFirstSisterVirtualStmNode)
  1471. // to pvsnTrav.
  1472. // -Go back to top of loop and repeat.
  1473. // -Check if pvcn's _pvcnChild is NULL or not by calling the func
  1474. // pvcn->GetFirstChildVirtualCtrNode() and assign it to pvcnTrav.
  1475. // -Loop while pvcnTrav is not NULL and hr is S_OK.
  1476. // -Make a recursive call to self (EnumerateInMemoryDocFile)
  1477. // -Assign pvcnTrav->_pvcnSister to pvcnTrav. (Got thru'
  1478. // GetFirstSisterVirtualCtrNode function).
  1479. // -Update pNumStg and pNumStm based on above call, where out
  1480. // parameters are cChildStg and cChildStm.
  1481. // -Reinitialize these variables and go back to top of loop.
  1482. //--------------------------------------------------------------------------
  1483. HRESULT EnumerateInMemoryDocFile(
  1484. VirtualCtrNode *pvcn,
  1485. ULONG *pNumStg,
  1486. ULONG *pNumStm )
  1487. {
  1488. HRESULT hr = S_OK;
  1489. ULONG cChildStg = 0;
  1490. ULONG cChildStm = 0;
  1491. VirtualCtrNode *pvcnTrav = NULL;
  1492. VirtualStmNode *pvsnTrav = NULL;
  1493. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("EnumerateInMemoryDocFile"));
  1494. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1495. if(NULL != pNumStg)
  1496. {
  1497. DH_VDATEPTROUT(pNumStg, ULONG) ;
  1498. }
  1499. if(NULL != pNumStm)
  1500. {
  1501. DH_VDATEPTROUT(pNumStm, ULONG) ;
  1502. }
  1503. DH_ASSERT(NULL != pvcn);
  1504. if(S_OK == hr)
  1505. {
  1506. if(NULL != pNumStg)
  1507. {
  1508. // Count the storage passed in.
  1509. *pNumStg = 1;
  1510. }
  1511. if(NULL != pNumStm)
  1512. {
  1513. *pNumStm = 0;
  1514. }
  1515. pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
  1516. // Count number of VirtualStmNodes that this VirtualCtrNode has.
  1517. while(NULL != pvsnTrav)
  1518. {
  1519. if(NULL != pNumStm)
  1520. {
  1521. (*pNumStm)++;
  1522. }
  1523. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
  1524. }
  1525. // Next recurse into the child VirtualCtrNodes of this VirtualCtrNode
  1526. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  1527. while((NULL != pvcnTrav) && (S_OK == hr))
  1528. {
  1529. hr = EnumerateInMemoryDocFile(
  1530. pvcnTrav,
  1531. &cChildStg,
  1532. &cChildStm);
  1533. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  1534. // Update number of nodes on basis of child nodes as found
  1535. if((NULL != pNumStg) && (0 != cChildStg))
  1536. {
  1537. *pNumStg = *pNumStg + cChildStg;
  1538. }
  1539. if((NULL != pNumStm) && (0 != cChildStm))
  1540. {
  1541. *pNumStm = *pNumStm + cChildStm;
  1542. }
  1543. // Reinitialize variables
  1544. cChildStg = 0;
  1545. cChildStm = 0;
  1546. }
  1547. }
  1548. // flatfile only: if we're at the root, increment stream counter to include
  1549. // the default flatfile stream (CONTENTS)
  1550. if(StorageIsFlat() && NULL == pvcn->GetParentVirtualCtrNode())
  1551. {
  1552. (*pNumStm)++;
  1553. }
  1554. return hr;
  1555. }
  1556. //-------------------------------------------------------------------------
  1557. // Function: OpenRandomVirtualCtrNodeStg
  1558. //
  1559. // Synopsis: Opens a VirtualCtrNode's IStorage. This traverses through all
  1560. // the parents of the VirtualCtrNode and opens them and then
  1561. // opens up the required storage. Please ensure that root IStorage
  1562. // is open before this call.
  1563. //
  1564. // Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage has to
  1565. // opened.
  1566. // [grfMode] - Mode to open the IStorage. (Note: all the parent
  1567. // IStorages would be opened in that mode too.)
  1568. //
  1569. // Returns: HRESULT
  1570. //
  1571. // History: 6-June-96 NarindK Created.
  1572. //
  1573. // Notes: This function doesn't reopen the root, which is already
  1574. // open since we need to have a valid function. If VirtualCtrNode // node whose storage has to be opened is same as Root, then
  1575. // functions returns w/o any error. Call CloseRandomVirtualCtr
  1576. // NodeStg function to close the storages opened by this call.
  1577. //
  1578. // -Initilize the counter to 1.
  1579. // -Assign pvcn to pvcnTrav and loop till pvcnTrav->_pvcnParent
  1580. // (obtained thru GetParentVirtualCtrNode() is non NULL)
  1581. // -Increment counter.
  1582. // -Assign pvcnTrav->_pvcnParent to pvcnTrav
  1583. // -Go back to top of loop and repeat.
  1584. // -Check if counter is 1 or not. If 1, then the node to be opened// is the root itsef that was opened prior to this call. So just
  1585. // return without any error.
  1586. // -If counter>1, then allocate an array of VirtualCtrNode pointers
  1587. // of size counter and continue.
  1588. // -Assign passed in node ovcn to temp var pvcnTrav. And fill up
  1589. // the above allocated arrays starting from the passed in node
  1590. // way upto root.
  1591. // -Increment the conter since root is already open, then in a
  1592. // do-while loop, open up all the nodes till we reach the passed
  1593. // in node. Pl. note that the nodes are opened as per grfMode that
  1594. // was passed in to us.
  1595. // -Delete the array of pointers.
  1596. //--------------------------------------------------------------------------
  1597. HRESULT OpenRandomVirtualCtrNodeStg(
  1598. VirtualCtrNode *pvcn,
  1599. DWORD grfMode)
  1600. {
  1601. HRESULT hr = S_OK;
  1602. ULONG counter = 1;
  1603. VirtualCtrNode *pvcnTrav = NULL;
  1604. PVCTRNODE *pvcnArrayPtr = NULL;
  1605. BOOL fIsRoot = FALSE;
  1606. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("OpenRandomVirtualCtrNodeStg"));
  1607. DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
  1608. DH_ASSERT(NULL != pvcn);
  1609. if(S_OK == hr)
  1610. {
  1611. // Count number of parents till the root.
  1612. pvcnTrav = pvcn;
  1613. while(NULL != pvcnTrav->GetParentVirtualCtrNode())
  1614. {
  1615. counter++;
  1616. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  1617. }
  1618. if( 1 == counter)
  1619. {
  1620. fIsRoot = TRUE;
  1621. }
  1622. else
  1623. {
  1624. // Allocate an array of desired size
  1625. pvcnArrayPtr = new PVCTRNODE [counter];
  1626. if(NULL == pvcnArrayPtr)
  1627. {
  1628. hr = E_OUTOFMEMORY;
  1629. }
  1630. }
  1631. }
  1632. if((S_OK == hr) && (FALSE == fIsRoot))
  1633. {
  1634. // Fill up the array starting from node itself, with parent chain
  1635. // upto including root.
  1636. pvcnTrav = pvcn;
  1637. pvcnArrayPtr[--counter] = pvcn;
  1638. while(NULL != pvcnTrav->GetParentVirtualCtrNode())
  1639. {
  1640. pvcnArrayPtr[--counter] = pvcnTrav->GetParentVirtualCtrNode();
  1641. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  1642. }
  1643. // Root is already open, so open the other parent nodes down to random
  1644. // test node.
  1645. counter++;
  1646. do
  1647. {
  1648. if(NULL != pvcnArrayPtr[counter]->GetIStoragePointer())
  1649. {
  1650. // If the storage is already open, then do an addref on it
  1651. // rather than trying to open it since all internal storages
  1652. // are always opened with STGM_SHARE_EXCLUSIVE mode (OLE).
  1653. hr = pvcnArrayPtr[counter]->AddRefCount();
  1654. DH_HRCHECK(hr, TEXT("VirtualCtrNode::AddRefCount")) ;
  1655. }
  1656. else
  1657. {
  1658. hr = pvcnArrayPtr[counter]->Open(
  1659. NULL,
  1660. grfMode,
  1661. NULL,
  1662. 0);
  1663. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open")) ;
  1664. }
  1665. } while(pvcnArrayPtr[counter++] != pvcn);
  1666. }
  1667. // Cleanup
  1668. if(NULL != pvcnArrayPtr)
  1669. {
  1670. delete []pvcnArrayPtr;
  1671. pvcnArrayPtr = NULL;
  1672. }
  1673. return hr;
  1674. }
  1675. //-------------------------------------------------------------------------
  1676. // Function: CloseRandomVirtualCtrNodeStg
  1677. //
  1678. // Synopsis: Close a VirtualCtrNode's IStorage and all other IStorages that
  1679. // were open in prior call to OpenRandomVirtualCtrNodeStg.
  1680. // This traverses through all the parents of the VirtualCtrNode
  1681. // and closes them excluding the root IStorage, which was not
  1682. // reopened during OpenRandomVirtualCtrNodeStg call.
  1683. //
  1684. // Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage has to
  1685. // closed.
  1686. //
  1687. // Returns: HRESULT
  1688. //
  1689. // History: 18-June-96 NarindK Created.
  1690. //
  1691. // Notes:
  1692. //--------------------------------------------------------------------------
  1693. HRESULT CloseRandomVirtualCtrNodeStg(VirtualCtrNode *pvcn)
  1694. {
  1695. HRESULT hr = S_OK;
  1696. VirtualCtrNode *pvcnTrav = NULL;
  1697. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CloseRandomVirtualCtrNodeStg"));
  1698. DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
  1699. DH_ASSERT(NULL != pvcn);
  1700. pvcnTrav = pvcn;
  1701. if(S_OK == hr)
  1702. {
  1703. while((NULL != pvcnTrav->GetParentVirtualCtrNode()) && (S_OK == hr))
  1704. {
  1705. hr = pvcnTrav->Close();
  1706. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Close")) ;
  1707. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  1708. }
  1709. }
  1710. return hr;
  1711. }
  1712. //-------------------------------------------------------------------------
  1713. // Function: ParseVirtualDFAndCloseOpenStgsStms
  1714. //
  1715. // Synopsis: This function parses the VirtualDF tree and calls Close
  1716. // release on all open IStorages/IStreams pointers under and/
  1717. // or including the passed in VirtualCtrNode
  1718. //
  1719. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  1720. // [eNodeOp]- May be NODE_INC_TOPSTG / NODE_EXC_TOPSTG
  1721. //
  1722. // Returns: HRESULT
  1723. //
  1724. // History: 16-July-96 NarindK Created.
  1725. //
  1726. // Notes: If NODE_INC_TOPSTG is given, it calls a close/release on the
  1727. // passed in VirtualCtrNode, if it is NODE_EXC_TOPSTG, it doesn't
  1728. // call a close/release on the IStorage pointer of passed in
  1729. // VirtualCtrNode.
  1730. //
  1731. // Also note that if a Parent's IStorage ptr is Released and is
  1732. // NULL, its child IStorage/IStream pointers will not be valid,
  1733. // for use, but we still need to Release them if they exist.
  1734. //
  1735. // - If eNodeOp is NODE_INC_TOPSTG, then see if pvcn's _pstg is not
  1736. // NULL and call VirtualCtrNode::Close on it to release it. if
  1737. // eNodeOp is NODE_EXC_TOPSTG, skip this step
  1738. // - Assign pvcn's _pvcnChild to pvcnTrav and pvcn's _pvsnStream
  1739. // to pvsnTrav
  1740. // - If pvsnTrav is not NULL (i.e pvcn has child VirtualStmNodes),
  1741. // in a loop -
  1742. // -Check if pvsnTrav's _pstm is not NULL, if not Call
  1743. // VirtualStmNode::Close in it to release, else skip it.
  1744. // -Advance pvsnTrav to bext VirtualStmNode _pvsnSister &
  1745. // go back to top of loop.
  1746. // - If pvcnTrav is not NULL (ie pvcn has child VirtualCtrNodes),
  1747. // in a loop -
  1748. // - Call ParseVirtualDFAndCloseOpenStgsStms recursively
  1749. // Pl. note it is called with NODE_INC_TOPSTG always.
  1750. // - Advance pvcnTrav to next sister VirtualCtrNode i.e.
  1751. // _pvcnSister and go back to top of loop.
  1752. //--------------------------------------------------------------------------
  1753. HRESULT ParseVirtualDFAndCloseOpenStgsStms(
  1754. VirtualCtrNode *pvcn,
  1755. NODE_OP eNodeOp)
  1756. {
  1757. HRESULT hr = S_OK;
  1758. VirtualStmNode *pvsnTrav = NULL;
  1759. VirtualCtrNode *pvcnTrav = NULL;
  1760. DH_FUNCENTRY(
  1761. &hr,
  1762. DH_LVL_DFLIB,
  1763. _TEXT("ParseVirtualDFAndCloseOpenStgsStms"));
  1764. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1765. DH_ASSERT(NULL != pvcn);
  1766. DH_ASSERT((NODE_INC_TOPSTG == eNodeOp) ||
  1767. (NODE_EXC_TOPSTG == eNodeOp));
  1768. if((S_OK == hr) && (NODE_INC_TOPSTG == eNodeOp))
  1769. {
  1770. if(NULL != pvcn->GetIStoragePointer())
  1771. {
  1772. hr = pvcn->Close();
  1773. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Close"));
  1774. }
  1775. }
  1776. if(S_OK == hr)
  1777. {
  1778. pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
  1779. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  1780. // Release IStream pointers if any.
  1781. while((NULL != pvsnTrav) && (S_OK == hr))
  1782. {
  1783. if(NULL != pvsnTrav->GetIStreamPointer())
  1784. {
  1785. hr = pvsnTrav->Close();
  1786. DH_HRCHECK(hr, TEXT("VirtualStmNode::Close"));
  1787. }
  1788. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
  1789. }
  1790. // Next recurse into the child VirtualCtrNodes of this VirtualCtrNode
  1791. while((NULL != pvcnTrav) && (S_OK == hr))
  1792. {
  1793. hr = ParseVirtualDFAndCloseOpenStgsStms(
  1794. pvcnTrav,
  1795. NODE_INC_TOPSTG);
  1796. DH_HRCHECK(hr, TEXT("ParseVirtualDFAndCloseOpenStgsStms"));
  1797. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  1798. }
  1799. }
  1800. return hr;
  1801. }
  1802. //-------------------------------------------------------------------------
  1803. // Function: ParseVirtualDFAndCommitAllOpenStgs
  1804. //
  1805. // Synopsis: This function parses the VirtualDF tree and calls commit
  1806. // on all open IStorages pointers under passed in VirtualCtrNode
  1807. //
  1808. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  1809. // [grfCommitFlags] - Commit flags.
  1810. // [eNodeOp] - NODE_INC_TOPSTG / NODE_EXC_TOPSTG
  1811. //
  1812. // Returns: HRESULT
  1813. //
  1814. // History: 23-July-96 NarindK Created.
  1815. //
  1816. // Notes: - Assign pvcn's _pvcnChild, if not NULL, to local var pvcnTrav.
  1817. // - If pvcnTrav is not NULL (ie pvcn has child VirtualCtrNodes),
  1818. // traverse the tree in loop to reach last child.
  1819. // - while pvcnTrav is not equal to pvcn and hr is S_OK, loop
  1820. // - If pvcnTrav has IStoragePointer, call Commit.
  1821. // - If pvcnTrav has sister nodes, call the function
  1822. // recursively with NODE_INC_TOPSTG always.
  1823. // - Assgin pvcnTrav's parent to pvcnTrav and go back
  1824. // to top of loop.
  1825. // - if eNodeOp is equal to NODE_INC_TOPSTG and hr is S_OK, then
  1826. // commit the top storage pvcn, else skip commiting it.
  1827. //--------------------------------------------------------------------------
  1828. HRESULT ParseVirtualDFAndCommitAllOpenStgs(
  1829. VirtualCtrNode *pvcn,
  1830. DWORD grfCommitMode,
  1831. NODE_OP eNodeOp)
  1832. {
  1833. HRESULT hr = S_OK;
  1834. VirtualCtrNode *pvcnTrav = NULL;
  1835. DH_FUNCENTRY(
  1836. &hr,
  1837. DH_LVL_DFLIB,
  1838. _TEXT("ParseVirtualDFAndCommitAllOpenStgs"));
  1839. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1840. DH_ASSERT(NULL != pvcn);
  1841. DH_ASSERT((NODE_INC_TOPSTG == eNodeOp) ||
  1842. (NODE_EXC_TOPSTG == eNodeOp));
  1843. if(S_OK == hr)
  1844. {
  1845. pvcnTrav = pvcn;
  1846. while(NULL != pvcnTrav->GetFirstChildVirtualCtrNode())
  1847. {
  1848. pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
  1849. }
  1850. DH_ASSERT(NULL != pvcnTrav);
  1851. }
  1852. // Commit this storage, next commit any sister VirtualCtrNodes it might
  1853. // have and commit those by recursing into them, then go to parent and
  1854. // repeat. if parent is equal to pvcnParent, quit the loop
  1855. while((pvcn != pvcnTrav) && (S_OK == hr))
  1856. {
  1857. if(NULL != pvcnTrav->GetIStoragePointer())
  1858. {
  1859. hr = pvcnTrav->Commit(grfCommitMode);
  1860. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit"));
  1861. }
  1862. while((NULL != pvcnTrav->GetFirstSisterVirtualCtrNode()) &&
  1863. (S_OK == hr))
  1864. {
  1865. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  1866. hr = ParseVirtualDFAndCommitAllOpenStgs(
  1867. pvcnTrav,
  1868. grfCommitMode,
  1869. NODE_INC_TOPSTG);
  1870. DH_HRCHECK(hr, TEXT("ParseVirtualDFAndCommitAllOpenStgs"));
  1871. }
  1872. // Go to Parent VirtualCtrNode and commit them
  1873. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  1874. }
  1875. if((S_OK == hr) &&
  1876. (NODE_INC_TOPSTG == eNodeOp) &&
  1877. (NULL != pvcn->GetIStoragePointer()))
  1878. {
  1879. hr = pvcn->Commit(grfCommitMode);
  1880. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit"));
  1881. }
  1882. return hr;
  1883. }
  1884. //-------------------------------------------------------------------------
  1885. //
  1886. // The following utilitiy functions are to calculate the CRC for a docfile
  1887. // These are independent of VirtualDF tree or any other base code implement-
  1888. // ation.
  1889. //
  1890. //-------------------------------------------------------------------------
  1891. //+-------------------------------------------------------------------------
  1892. // Function: CalculateCRCForDocFile
  1893. //
  1894. // Synopsis: Calulates CRC for the disk docfile.
  1895. //
  1896. // Arguments: [pIStorage] - pointer to IStorage
  1897. // [crcflags] - what stuff to include in the crc
  1898. // [pdwCRC] - pointer to CRC
  1899. //
  1900. // Returns: HRESULT
  1901. //
  1902. // History: 30-May-96 NarindK Created.
  1903. // 24-Jul-97 MikeW Include state bits
  1904. // 02-Apr-98 georgis read in chunks
  1905. //
  1906. // Notes: For IStorages, only name is CRC'd. For IStorages/IStreams,
  1907. // both name and data are CRC'd.
  1908. //
  1909. // Please not that this function will not indicate a failure if
  1910. // and whenver the IEnumSTATSTG->Next returns fail, that just
  1911. // indicates the completion of enumeration sequence.
  1912. //
  1913. // If VERIFY_OP is equal to VERIFY_INC_TOPSTG_NAME, then the func
  1914. // goes ahead and calculates CRC for toplevel storage name also
  1915. // else if it is equal to VERIFY_EXC_TOPSTG_NAME, it doesn't
  1916. // include the CRC for top level storage name. Pl. note that
  1917. // the recursive call to itself in function includes VERIFY_INC_
  1918. // TOPSTG_NAME, so this parameter is used only for TOP level
  1919. // storage that is passed in (pointed by pIStorage).
  1920. //
  1921. // - if VERIFY_OP is VERIFY_INC_TOPSTG_NAME then,
  1922. // -Call pIStorage->Stat to get STATSTG structure for passed
  1923. // IStorage.
  1924. // -Call CalculateCRCForName to get the CRC for name of this
  1925. // storage obtained from STATSTG structure.
  1926. // -Fold the CRC into grand CRC pdwCRC.
  1927. // -Call pIStorage->Enumerate to get LPENUMSTATSTG for storage.
  1928. // -Call lpEnumStatStg->Next to get next element in enumeration
  1929. // sequence. If it returns S_FALSE, means no elements to enum
  1930. // earte, so just return w/o any error.
  1931. // -Else loop till hr is S_OK.
  1932. // -If node is of type STGSTY_STORAGE, then
  1933. // -Open the child IStorage.
  1934. // -Make a recursive call to calculate CRC for this
  1935. // child Istorage to self CalculateCRCForDocFile.
  1936. // -Fold the CRC from above call into grand CRC pdwCRC.
  1937. // -Release the child IStorage
  1938. // -If node is of type STGSTY_STREAM, then
  1939. // -Call CalculateCRCForDocFileStmData to calculate CRC
  1940. // for stream data.
  1941. // -Call CalculateCRCForName to calculate CRC for its
  1942. // name.
  1943. // -Fold the above two into grand CRC pdwCRC.
  1944. // -Get the next element in enumeration sequence. If it returns
  1945. // S_FALSE, then simply return w/o any error.
  1946. // -Else go back to top of loop and repeat.
  1947. //--------------------------------------------------------------------------
  1948. HRESULT CalculateCRCForDocFile(
  1949. IStorage *pIStorage,
  1950. DWORD crcflags,
  1951. DWORD *pdwCRC,
  1952. DWORD dwChunkSize)
  1953. {
  1954. HRESULT hr = S_OK;
  1955. LPENUMSTATSTG lpEnumStatStg = NULL;
  1956. ULONG *pceltFetched = NULL;
  1957. LPSTORAGE pIStorageChild = NULL;
  1958. DWORD dwCurrStgCRC = 0;
  1959. DWORD dwCurrStgNameCRC= 0;
  1960. DWORD dwCurrStmNameCRC= 0;
  1961. DWORD dwCurrStmDataCRC= 0;
  1962. BOOL fIEnumNextFail = FALSE;
  1963. ULONG i = 0;
  1964. LPTSTR ptszName = NULL;
  1965. LPTSTR ptszNameStm = NULL;
  1966. LPTSTR ptszNameStg = NULL;
  1967. LPOLESTR poszNameStg = NULL;
  1968. STATSTG statStg;
  1969. STATSTG statStgEnum;
  1970. DWORD statflag = STATFLAG_DEFAULT;
  1971. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForDocFile"));
  1972. DH_VDATEPTRIN(pIStorage, IStorage) ;
  1973. DH_VDATEPTROUT(pdwCRC, DWORD) ;
  1974. DH_ASSERT(NULL != pIStorage);
  1975. DH_ASSERT(NULL != pdwCRC);
  1976. // Initialization
  1977. statStg.pwcsName = NULL;
  1978. statStgEnum.pwcsName = NULL;
  1979. // Initialize out parameter
  1980. *pdwCRC = CRC_PRECONDITION;
  1981. // Call Stat on the passed IStorage to get its name and state bits
  1982. if (! (CRC_INC_TOPSTG_NAME & crcflags))
  1983. {
  1984. statflag = STATFLAG_NONAME;
  1985. }
  1986. if(S_OK == hr)
  1987. {
  1988. hr = pIStorage->Stat(&statStg, statflag);
  1989. DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
  1990. }
  1991. if (CRC_INC_STATEBITS & crcflags)
  1992. {
  1993. // Fold the CRC into grand CRC
  1994. MUNGECRC(*pdwCRC, statStg.grfStateBits);
  1995. DH_TRACE((
  1996. DH_LVL_CRCDUMP,
  1997. TEXT("statebits=0x%08x, crc=0x%08x"),
  1998. statStg.grfStateBits,
  1999. *pdwCRC));
  2000. }
  2001. // If crcflags includes CRC_INC_TOPSTG_NAME, then calculate and
  2002. // include the top level storage name in calculating grand CRC.
  2003. if(CRC_INC_TOPSTG_NAME & crcflags)
  2004. {
  2005. DH_ASSERT(NULL != statStg.pwcsName);
  2006. // Find the CRC for the storage name
  2007. if(S_OK == hr)
  2008. {
  2009. //Convert WCHAR to TCHAR
  2010. hr = OleStringToTString(statStg.pwcsName, &ptszName);
  2011. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2012. }
  2013. if(S_OK == hr)
  2014. {
  2015. hr = CalculateCRCForName(ptszName, &dwCurrStgNameCRC);
  2016. DH_HRCHECK(hr, TEXT("CalculateCRCForDocFileNames")) ;
  2017. }
  2018. // Fold the CRC into grand CRC
  2019. MUNGECRC(*pdwCRC, dwCurrStgNameCRC);
  2020. DH_TRACE((
  2021. DH_LVL_CRCDUMP,
  2022. TEXT("storage=%s, crc=0x%08x"),
  2023. ptszName,
  2024. *pdwCRC));
  2025. // Clean up
  2026. if(NULL != statStg.pwcsName)
  2027. {
  2028. CoTaskMemFree(statStg.pwcsName);
  2029. statStg.pwcsName = NULL;
  2030. }
  2031. if(NULL != ptszName)
  2032. {
  2033. delete ptszName;
  2034. ptszName = NULL;
  2035. }
  2036. }
  2037. // Get the enumerator so that we could enumerate this storage
  2038. if(S_OK == hr)
  2039. {
  2040. hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
  2041. DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
  2042. }
  2043. // if successful to get enumerator, get the first element of the enumeration
  2044. // sequence.
  2045. if ( S_OK == hr )
  2046. {
  2047. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2048. if(S_FALSE == hr)
  2049. {
  2050. fIEnumNextFail = TRUE;
  2051. }
  2052. }
  2053. // Loop through till lpEnumStatStg->Next returns FALSE which is desired
  2054. // sequene or some other error happens
  2055. while(S_OK == hr)
  2056. {
  2057. // If the element is an IStorage, open this and make a recursive call
  2058. // to CalculateCRCForDocFile function.
  2059. if (STGTY_STORAGE == statStgEnum.type)
  2060. {
  2061. //Convert WCHAR to TCHAR
  2062. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
  2063. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2064. if(S_OK == hr)
  2065. {
  2066. // Convert TCHAR to OLECHAR
  2067. hr = TStringToOleString(ptszNameStg, &poszNameStg);
  2068. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2069. }
  2070. if(S_OK == hr)
  2071. {
  2072. hr = pIStorage->OpenStorage(
  2073. poszNameStg,
  2074. NULL,
  2075. STGM_READ | STGM_SHARE_EXCLUSIVE,
  2076. NULL,
  2077. 0,
  2078. &pIStorageChild);
  2079. DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
  2080. }
  2081. if (S_OK == hr)
  2082. {
  2083. // Make recursive call including CRC_INC_TOPSTG_NAME
  2084. hr = CalculateCRCForDocFile(
  2085. pIStorageChild,
  2086. crcflags | CRC_INC_TOPSTG_NAME,
  2087. &dwCurrStgCRC);
  2088. DH_HRCHECK(hr, TEXT("CalculateCRCForDocFile")) ;
  2089. }
  2090. // Fold the CRC for contained IStorage into grand CRC
  2091. MUNGECRC(*pdwCRC, dwCurrStgCRC);
  2092. // Release the storage pointer
  2093. if(NULL != pIStorageChild)
  2094. {
  2095. pIStorageChild->Release();
  2096. pIStorageChild = NULL;
  2097. }
  2098. }
  2099. else
  2100. // If the element is an IStream, calculate CRC for its name and Data.
  2101. if (STGTY_STREAM == statStgEnum.type)
  2102. {
  2103. // Calulate CRC for IStream Data.
  2104. if(S_OK == hr)
  2105. {
  2106. //Convert WCHAR to TCHAR
  2107. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
  2108. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2109. }
  2110. if(S_OK == hr)
  2111. {
  2112. hr = CalculateCRCForDocFileStmData(
  2113. pIStorage,
  2114. ptszNameStm,
  2115. statStgEnum.cbSize.LowPart,
  2116. &dwCurrStmDataCRC,
  2117. dwChunkSize);
  2118. DH_HRCHECK(hr, TEXT("CalculateCRCForDocFileStmData"));
  2119. }
  2120. // Calulate CRC for IStream Name.
  2121. if(S_OK == hr)
  2122. {
  2123. hr = CalculateCRCForName(
  2124. ptszNameStm,
  2125. &dwCurrStmNameCRC);
  2126. DH_HRCHECK(hr, TEXT("CalculateCRCForName"));
  2127. DH_TRACE((
  2128. DH_LVL_CRCDUMP,
  2129. TEXT("stream %s, name crc=0x%08x, data crc=0x%08x"),
  2130. ptszNameStm,
  2131. dwCurrStmNameCRC,
  2132. dwCurrStmDataCRC));
  2133. }
  2134. // Fold the CRC's for contained IStream into grand CRC
  2135. MUNGECRC(*pdwCRC, dwCurrStmDataCRC);
  2136. MUNGECRC(*pdwCRC, dwCurrStmNameCRC);
  2137. }
  2138. else
  2139. // The element is neither IStorage nor IStream, report error.
  2140. {
  2141. hr = E_UNEXPECTED;
  2142. }
  2143. // Clean up
  2144. if(NULL != statStgEnum.pwcsName)
  2145. {
  2146. CoTaskMemFree(statStgEnum.pwcsName);
  2147. statStgEnum.pwcsName = NULL;
  2148. }
  2149. if(NULL != ptszNameStm)
  2150. {
  2151. delete ptszNameStm;
  2152. ptszNameStm = NULL;
  2153. }
  2154. if(NULL != ptszNameStg)
  2155. {
  2156. delete ptszNameStg;
  2157. ptszNameStg = NULL;
  2158. }
  2159. if(NULL != poszNameStg)
  2160. {
  2161. delete poszNameStg;
  2162. poszNameStg = NULL;
  2163. }
  2164. // Get the next element in the enumeration sequence
  2165. if(S_OK == hr)
  2166. {
  2167. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2168. if(S_FALSE == hr)
  2169. {
  2170. fIEnumNextFail = TRUE;
  2171. }
  2172. }
  2173. }
  2174. // IEnumSTATSTG->Next would return S_FALSE if it can't enumerate the
  2175. // next element because there might not be any elements to enumerate
  2176. // hence it doesn't indicate an error for this function, but is just
  2177. // a condition for looping through the total docfile structure, hence
  2178. // don't reprot failure because of it.
  2179. if(TRUE == fIEnumNextFail)
  2180. {
  2181. hr = S_OK;
  2182. }
  2183. // Clean up
  2184. if (NULL != lpEnumStatStg)
  2185. {
  2186. lpEnumStatStg->Release();
  2187. lpEnumStatStg = NULL;
  2188. }
  2189. return hr;
  2190. }
  2191. //+-------------------------------------------------------------------------
  2192. // Function: CalculateCRCForDocFileStmData
  2193. //
  2194. // Synopsis: Calulates CRC for the disk docfile's stream data.
  2195. //
  2196. // Arguments: [pIStorage] - pointer to parent storage
  2197. // [ptcsName] - pointer to name string
  2198. // [cbSize] - size of the data to be read.
  2199. // [pdwCurrStmDataCRC]- pointer to returned CRC
  2200. //
  2201. // Returns: HRESULT
  2202. //
  2203. // History: 30-May-96 NarindK Created.
  2204. // 02-Apr-98 georgis Use CalculateStreamDataCRC
  2205. //
  2206. //--------------------------------------------------------------------------
  2207. HRESULT CalculateCRCForDocFileStmData(
  2208. LPSTORAGE pIStorage,
  2209. LPTSTR ptcsName,
  2210. DWORD cbSize,
  2211. DWORD *pdwCurrStmDataCRC,
  2212. DWORD dwChunkSize)
  2213. {
  2214. HRESULT hr = S_OK;
  2215. LPSTREAM pIStreamChild = NULL;
  2216. LPOLESTR pOleStrTemp = NULL;
  2217. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, TEXT("CalculateCRCForDocFileStmData"));
  2218. DH_VDATEPTRIN(pIStorage, IStorage) ;
  2219. DH_VDATESTRINGPTR(ptcsName) ;
  2220. DH_VDATEPTROUT(pdwCurrStmDataCRC, DWORD) ;
  2221. DH_ASSERT(NULL != pIStorage);
  2222. DH_ASSERT(NULL != ptcsName);
  2223. DH_ASSERT(NULL != pdwCurrStmDataCRC);
  2224. // Open the stream
  2225. hr = TStringToOleString(ptcsName, &pOleStrTemp);
  2226. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2227. if ( S_OK == hr )
  2228. {
  2229. hr = pIStorage->OpenStream(
  2230. pOleStrTemp,
  2231. NULL,
  2232. STGM_READ | STGM_SHARE_EXCLUSIVE,
  2233. 0,
  2234. &pIStreamChild);
  2235. DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
  2236. }
  2237. if ( S_OK == hr )
  2238. {
  2239. // Calculate the CRC for the stream data
  2240. hr=CalculateStreamDataCRC(
  2241. pIStreamChild,
  2242. cbSize,
  2243. pdwCurrStmDataCRC,
  2244. dwChunkSize);
  2245. DH_HRCHECK(hr, TEXT("CalculateStreamDataCRC"));
  2246. }
  2247. if (NULL!= pIStreamChild)
  2248. {
  2249. pIStreamChild->Release();
  2250. }
  2251. if (NULL != pOleStrTemp)
  2252. {
  2253. delete pOleStrTemp;
  2254. }
  2255. return hr;
  2256. }
  2257. //+-------------------------------------------------------------------------
  2258. // Function: CalculateCRCForDocFileStmData
  2259. //
  2260. // Synopsis: Calulates CRC for the disk docfile's stream data.
  2261. //
  2262. // Arguments: [ptcsName] - ? not used
  2263. // [pIChildStream] - pointer to the opened stream
  2264. // [cbSize] - size of the data to be read.
  2265. // [pdwCurrStmDataCRC]- pointer to returned CRC
  2266. //
  2267. // Returns: HRESULT
  2268. //
  2269. // History: 15-Nov-96 JiminLi Created.
  2270. // 02-Apr-98 georgis Use CalculateStreamDataCRC
  2271. //
  2272. // Notes: CalculateStreamDataCRC actually obsoletes this function
  2273. // It remains for compatibility with the old tests
  2274. //
  2275. //--------------------------------------------------------------------------
  2276. HRESULT CalculateCRCForDocFileStmData(
  2277. LPTSTR ptcsName,
  2278. LPSTREAM pIChildStream,
  2279. DWORD cbSize,
  2280. DWORD *pdwCurrStmDataCRC,
  2281. DWORD dwChunkSize)
  2282. {
  2283. HRESULT hr = S_OK;
  2284. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, TEXT("CalculateCRCForDocFileStmData"));
  2285. DH_VDATEPTRIN(pIChildStream, IStream) ;
  2286. DH_VDATEPTROUT(pdwCurrStmDataCRC, DWORD) ;
  2287. DH_ASSERT(NULL != pdwCurrStmDataCRC);
  2288. DH_ASSERT(0 != cbSize);
  2289. // The stream is kept open before calling this function
  2290. DH_ASSERT(NULL != pIChildStream);
  2291. // Calculate the CRC for the stream data
  2292. hr=CalculateStreamDataCRC(
  2293. pIChildStream,
  2294. cbSize,
  2295. pdwCurrStmDataCRC,
  2296. dwChunkSize);
  2297. DH_HRCHECK(hr, TEXT("CalculateStreamDataCRC"));
  2298. return hr;
  2299. }
  2300. //+-------------------------------------------------------------------------
  2301. //
  2302. // Function: EnumerateDiskDocFile
  2303. //
  2304. // Synopsis: Enumerates a disk docfile.
  2305. //
  2306. // Arguments: [pIStorage] - pointer to IStorage
  2307. // [eVerifyOp] - VERIFY_SHORT or VERIFY_DETAIL
  2308. // [pdwNumStg] - pointer to number of Storages in doc hierarchy.
  2309. // [pdwNumStm] - pointer to number of streams in doc hierarchy
  2310. //
  2311. // Returns: HRESULT
  2312. //
  2313. // History: 3-June-96 NarindK Created.
  2314. //
  2315. // Notes: pdwNumStg, pdwNumStm may be NULL if user is not interested in
  2316. // these values to be returned back. eVerifyOp should normally
  2317. // be specified as VERIFY_SHORT unless test requires it otherwise
  2318. //
  2319. // -Count the passed in pIStorage as 1 in pNumStg count.
  2320. // -Call pIStorage->EnumElements to get LPENUMSTATSTG lpEnumStatStg
  2321. // -Call lpEnumStatStg->Next to get next node. If it returns
  2322. // S_FALSE, that indicates no elements to enumerate, so return
  2323. // without any error.
  2324. // -Else loop till hr is S_OK
  2325. // -if node is of type STGTY_STORAGE, then
  2326. // -open that child storage and make a recursive call to
  2327. // EnumerateDiskDocFile passing it pointer to opened
  2328. // child storage, and cChildStg and cChildStm local
  2329. // variables for count.
  2330. // -close the child storage opened.
  2331. // -Update the pNumStg, pNumStm based on above recursive
  2332. // call's out parameters cChildStg and CChildStm.
  2333. // -if node is of type STGTY_STREAM, then update pNumStm count
  2334. // - if flag VERIFY_DETAIL is passed in, then open that
  2335. // stream and read its contents. This verification
  2336. // is useful in cases like corruption tests where this
  2337. // verification ensures proper stability of OLE under
  2338. // such situations.
  2339. // -Get the next element in enumeration sequence.
  2340. // -Reinitilize the local variables cChildStg, cChildStm.
  2341. // -Go back to top of loop and repeat.
  2342. //--------------------------------------------------------------------------
  2343. HRESULT EnumerateDiskDocFile(
  2344. LPSTORAGE pIStorage,
  2345. VERIFY_OP eVerifyOp,
  2346. ULONG *pNumStg,
  2347. ULONG *pNumStm )
  2348. {
  2349. HRESULT hr = S_OK;
  2350. LPMALLOC pMalloc = NULL;
  2351. LPENUMSTATSTG lpEnumStatStg = NULL;
  2352. ULONG *pceltFetched = NULL;
  2353. LPSTORAGE pIStorageChild = NULL;
  2354. BOOL fIEnumNextFail = FALSE;
  2355. ULONG cChildStg = 0;
  2356. ULONG cChildStm = 0;
  2357. LPSTREAM pIStreamChild = NULL;
  2358. LPOLESTR pocsBuffer = NULL;
  2359. LPTSTR ptszNameStg = NULL;
  2360. LPOLESTR poszNameStg = NULL;
  2361. LPTSTR ptszNameStm = NULL;
  2362. LPOLESTR poszNameStm = NULL;
  2363. ULONG culRead = 0;
  2364. ULONG culCurBufferLen = 0;
  2365. STATSTG statStgEnum;
  2366. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateDiskDocFile"));
  2367. DH_VDATEPTRIN(pIStorage, IStorage) ;
  2368. if(NULL != pNumStg)
  2369. {
  2370. DH_VDATEPTROUT(pNumStg, ULONG) ;
  2371. }
  2372. if(NULL != pNumStm)
  2373. {
  2374. DH_VDATEPTROUT(pNumStm, ULONG) ;
  2375. }
  2376. DH_ASSERT(NULL != pIStorage);
  2377. // Initialization
  2378. statStgEnum.pwcsName = NULL;
  2379. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  2380. if ( S_OK == hr )
  2381. {
  2382. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  2383. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  2384. }
  2385. // Call EnumElements on passed IStorage to enumerate it.
  2386. if(S_OK == hr)
  2387. {
  2388. // Initialize out parameter
  2389. if(NULL != pNumStg)
  2390. {
  2391. // Count the storage passed in.
  2392. *pNumStg = 1;
  2393. }
  2394. if(NULL != pNumStm)
  2395. {
  2396. *pNumStm = 0;
  2397. }
  2398. hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
  2399. DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
  2400. }
  2401. // if successful to get enumerator, get the first element of the enumeration
  2402. // sequence.
  2403. if ( S_OK == hr )
  2404. {
  2405. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2406. if(S_FALSE == hr)
  2407. {
  2408. fIEnumNextFail = TRUE;
  2409. }
  2410. }
  2411. // Loop through till lpEnumStatStg->Next returns FALSE which is desired
  2412. // sequence or some other error happens
  2413. while(S_OK == hr)
  2414. {
  2415. // If the element is an IStorage, open this and make a recursive call
  2416. // to EnumerateDocFile function.
  2417. if (STGTY_STORAGE == statStgEnum.type)
  2418. {
  2419. //Convert WCHAR to TCHAR
  2420. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
  2421. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2422. if(S_OK == hr)
  2423. {
  2424. // Convert TCHAR to OLECHAR
  2425. hr = TStringToOleString(ptszNameStg, &poszNameStg);
  2426. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2427. }
  2428. if(S_OK == hr)
  2429. {
  2430. hr = pIStorage->OpenStorage(
  2431. poszNameStg,
  2432. NULL,
  2433. STGM_READ | STGM_SHARE_EXCLUSIVE,
  2434. NULL,
  2435. 0,
  2436. &pIStorageChild);
  2437. DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
  2438. }
  2439. if (S_OK == hr)
  2440. {
  2441. // Recursive call to EnumerateDiskDocFile
  2442. hr = EnumerateDiskDocFile(
  2443. pIStorageChild,
  2444. eVerifyOp,
  2445. &cChildStg,
  2446. &cChildStm);
  2447. DH_HRCHECK(hr, TEXT("EnumerateDiskDocFile")) ;
  2448. }
  2449. // Release the storage pointer
  2450. if(NULL != pIStorageChild)
  2451. {
  2452. pIStorageChild->Release();
  2453. pIStorageChild = NULL;
  2454. }
  2455. // Release string pointers.
  2456. if(NULL != ptszNameStg)
  2457. {
  2458. delete ptszNameStg;
  2459. ptszNameStg = NULL;
  2460. }
  2461. if(NULL != poszNameStg)
  2462. {
  2463. delete poszNameStg;
  2464. poszNameStg = NULL;
  2465. }
  2466. // Update number of storage and stream objects, if required.
  2467. if((NULL != pNumStg) && (0 != cChildStg))
  2468. {
  2469. *pNumStg = cChildStg + *pNumStg;
  2470. }
  2471. if((NULL != pNumStm) && (0 != cChildStm))
  2472. {
  2473. *pNumStm = cChildStm + *pNumStm;
  2474. }
  2475. }
  2476. else
  2477. if (STGTY_STREAM == statStgEnum.type)
  2478. {
  2479. if(NULL != pNumStm)
  2480. {
  2481. (*pNumStm)++;
  2482. }
  2483. if(VERIFY_DETAIL == eVerifyOp)
  2484. {
  2485. //Attempt to open and read the stream. Useful for corruption
  2486. // tests to see that OLE doesn't GPF under those conditions.
  2487. //Convert WCHAR to TCHAR
  2488. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
  2489. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2490. if(S_OK == hr)
  2491. {
  2492. // Convert TCHAR to OLECHAR
  2493. hr = TStringToOleString(ptszNameStm, &poszNameStm);
  2494. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2495. }
  2496. // Open the stream.
  2497. if(S_OK == hr)
  2498. {
  2499. hr = pIStorage->OpenStream(
  2500. poszNameStm,
  2501. NULL,
  2502. STGM_READ | STGM_SHARE_EXCLUSIVE,
  2503. 0,
  2504. &pIStreamChild);
  2505. DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
  2506. }
  2507. // Read the stream in loop
  2508. while(( culCurBufferLen < statStgEnum.cbSize.LowPart) &&
  2509. (S_OK == hr))
  2510. {
  2511. if ( S_OK == hr )
  2512. {
  2513. pocsBuffer = new OLECHAR [STM_BUFLEN];
  2514. if (pocsBuffer == NULL)
  2515. {
  2516. hr = E_OUTOFMEMORY;
  2517. }
  2518. }
  2519. if ( S_OK == hr )
  2520. {
  2521. // Initialize the buffer
  2522. memset(pocsBuffer, '\0', STM_BUFLEN);
  2523. // Read the stream.
  2524. hr = pIStreamChild->Read(
  2525. pocsBuffer,
  2526. STM_BUFLEN,
  2527. &culRead);
  2528. DH_HRCHECK(hr, TEXT("IStream::Read")) ;
  2529. }
  2530. // Release the buffer
  2531. if(NULL != pocsBuffer)
  2532. {
  2533. delete [] pocsBuffer;
  2534. pocsBuffer = NULL;
  2535. }
  2536. // Increment culCurBufferLen
  2537. culCurBufferLen = culCurBufferLen + culRead;
  2538. }
  2539. // Release the stream
  2540. if(NULL != pIStreamChild)
  2541. {
  2542. pIStreamChild->Release();
  2543. pIStreamChild = NULL;
  2544. }
  2545. // Release string pointers.
  2546. if(NULL != ptszNameStm)
  2547. {
  2548. delete ptszNameStm;
  2549. ptszNameStm = NULL;
  2550. }
  2551. if(NULL != poszNameStm)
  2552. {
  2553. delete poszNameStm;
  2554. poszNameStm = NULL;
  2555. }
  2556. }
  2557. }
  2558. else
  2559. // The element is neither IStorage nor IStream, report error.
  2560. {
  2561. hr = E_UNEXPECTED;
  2562. }
  2563. // Clean up
  2564. if(NULL != statStgEnum.pwcsName)
  2565. {
  2566. pMalloc->Free(statStgEnum.pwcsName);
  2567. statStgEnum.pwcsName = NULL;
  2568. }
  2569. // Get the next element in the enumeration sequence
  2570. if(S_OK == hr)
  2571. {
  2572. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2573. if(S_FALSE == hr)
  2574. {
  2575. fIEnumNextFail = TRUE;
  2576. }
  2577. }
  2578. // Reinitialize the variables
  2579. cChildStg = 0;
  2580. cChildStm = 0;
  2581. }
  2582. // IEnumSTATSTG->Next returning S_FALSE indicates end of traversal in
  2583. // docfile hierarchy, not an error.
  2584. if(TRUE == fIEnumNextFail)
  2585. {
  2586. hr = S_OK;
  2587. }
  2588. // Clean up
  2589. if (NULL != lpEnumStatStg)
  2590. {
  2591. lpEnumStatStg->Release();
  2592. lpEnumStatStg = NULL;
  2593. }
  2594. if(NULL != pMalloc)
  2595. {
  2596. pMalloc->Release();
  2597. pMalloc = NULL;
  2598. }
  2599. return hr;
  2600. }
  2601. //+-------------------------------------------------------------------------
  2602. // Function: GenerateVirtualDFFromDiskDF
  2603. //
  2604. // Synopsis: Enumerates a disk docfile and creates an in memory virtual
  2605. // DocFile tree for the docfile.
  2606. //
  2607. // Arguments: [pNewVirtualDF] - Pointer to new VirtualDF tree being made.
  2608. // [ptszRootDFName] - Pointer to name of root Disk file.
  2609. // [grfMode] - Mode to open the root storage
  2610. // [ppvcnRoot] - pointer to pointer to root of VirtualDF.
  2611. // [pIRootStg] - Default value is NULL, when fDFOpened is TRUE,
  2612. // then pIRootStg must not be NULL, it is RootStg
  2613. // pointer
  2614. // [fDFOpened] - Default value is FALSE, i.e. the docfile is not
  2615. // opened, StgOpenStorage is called to open it.
  2616. // When it's TRUE, the pIRootStg is the stg pointer.
  2617. //
  2618. // Returns: HRESULT
  2619. //
  2620. // History: 5-June-96 NarindK Created.
  2621. // 3-Feb-97 JiminLi Adapted
  2622. //
  2623. // Notes: -Call TStringToOleString to convert given DocFile name to
  2624. // OLECHAR.
  2625. // - Call StgOpenStorage to open Root storage.
  2626. // -Call GenVirtualCtrNode to generate the root *ppvcnRoot of new
  2627. // VirtualDocFile tree being made passing it name from above Stat
  2628. // call. If successful, assocaite disk root IStorage with the
  2629. // root VirtualCtrNode's _pstg parameter.
  2630. // -Call GenerateRemVirtualDFTree to generate rest of tree, passing// it the new rootgenerated above and pIStorage.
  2631. // -If successful, call VirtualDF::Associate to associate this
  2632. // new root with the VirtualDF tree, else reassign *ppvcnRoot
  2633. // to NULL in case of failure.
  2634. //
  2635. // Please note that the Root storage opened during this call will
  2636. // be released during VirtualDF tree deletion that deletes all
  2637. // the VirtualCtrNodes in the tree & Destructor of VirtualCtrNodes
  2638. // does a final release on the storage pointers, if they are valid
  2639. // Also note that as result of this function, all other storage/
  2640. // streams are closed, except the Root storage.
  2641. //--------------------------------------------------------------------------
  2642. HRESULT GenerateVirtualDFFromDiskDF(
  2643. VirtualDF *pNewVirtualDF,
  2644. LPTSTR ptszRootDFName,
  2645. DWORD grfMode,
  2646. VirtualCtrNode **ppvcnRoot,
  2647. LPSTORAGE pIRootStg,
  2648. BOOL fDFOpened,
  2649. ULONG ulSeed)
  2650. {
  2651. HRESULT hr = S_OK;
  2652. LPSTORAGE pIStorage = NULL;
  2653. LPOLESTR pOleStrTemp = NULL;
  2654. ULONG i = 0;
  2655. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenerateVirtualDFFromDiskDF"));
  2656. DH_VDATESTRINGPTR(ptszRootDFName) ;
  2657. DH_VDATEPTROUT(ppvcnRoot, PVCTRNODE) ;
  2658. DH_VDATEPTROUT(pNewVirtualDF, VirtualDF) ;
  2659. DH_ASSERT(NULL != ptszRootDFName);
  2660. DH_ASSERT(NULL != ppvcnRoot);
  2661. DH_ASSERT(NULL != pNewVirtualDF);
  2662. if (fDFOpened)
  2663. {
  2664. DH_ASSERT(NULL != pIRootStg);
  2665. pIStorage = pIRootStg;
  2666. }
  2667. else
  2668. {
  2669. DH_ASSERT(0 != grfMode);
  2670. }
  2671. if ( S_OK == hr )
  2672. {
  2673. // Initialize out parameter
  2674. *ppvcnRoot = NULL;
  2675. }
  2676. if (!fDFOpened && (S_OK == hr))
  2677. {
  2678. // Convert TCHAR to OLECHAR
  2679. hr = TStringToOleString(ptszRootDFName, &pOleStrTemp);
  2680. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2681. }
  2682. if (!fDFOpened && (S_OK == hr))
  2683. {
  2684. // Try opening the docfile
  2685. // StgOpenStorage returns STG_E_LOCKVIOLATION is concurrent API calls
  2686. // are made, so this is the hack for workaround the problem.
  2687. // BUGBUG : Remove this loop once the feature is implemented in OLE.
  2688. // BUGBUG : ntbug#114779 Affects DCOM95 only. ntbug#41249 fixed
  2689. #if (WINVER<0x500) //NT5 is lockviolation fixed
  2690. for(i=0; i<NRETRIES; i++) // NRETRIES has been defined as 5
  2691. {
  2692. #endif
  2693. hr = StgOpenStorage(
  2694. pOleStrTemp,
  2695. NULL,
  2696. grfMode,
  2697. NULL,
  2698. 0,
  2699. &pIStorage);
  2700. #if (WINVER<0x500) //NT5 is lockviolation fixed
  2701. if ( (S_OK == hr) || (STG_E_LOCKVIOLATION != hr) )
  2702. {
  2703. break;
  2704. }
  2705. Sleep(NWAIT_TIME);
  2706. }
  2707. #endif
  2708. }
  2709. if ( S_OK == hr )
  2710. {
  2711. // Call to create the VirtualDF tree root.
  2712. hr = GenVirtualCtrNode(ptszRootDFName, ppvcnRoot);
  2713. DH_HRCHECK(hr, TEXT("GenerateVirtualDFRootFromDiskStg")) ;
  2714. }
  2715. if ( S_OK == hr )
  2716. {
  2717. // Create the remaining VirtualDF tree.
  2718. hr = GenerateRemVirtualDFTree(*ppvcnRoot, pIStorage);
  2719. DH_HRCHECK(hr, TEXT("CreateRemVirtualDFTree")) ;
  2720. }
  2721. if (S_OK != hr)
  2722. {
  2723. // The tree couldn't be successfully created, return NULL in out
  2724. // parameter.
  2725. *ppvcnRoot = NULL;
  2726. }
  2727. else
  2728. {
  2729. // Associate the root VirtualCtrNode with the VirtualDF tree.
  2730. hr = pNewVirtualDF->Associate(*ppvcnRoot, pIStorage, ulSeed);
  2731. DH_HRCHECK(hr, TEXT("VirtualDF::Associate")) ;
  2732. }
  2733. // Clean up
  2734. if(NULL != pOleStrTemp)
  2735. {
  2736. delete pOleStrTemp;
  2737. pOleStrTemp = NULL;
  2738. }
  2739. return hr;
  2740. }
  2741. //+-------------------------------------------------------------------------
  2742. // Function: GenerateVirtualDFFromDiskDF
  2743. //
  2744. // Synopsis: Enumerates a disk docfile and creates an in memory virtual
  2745. // DocFile tree for the docfile.
  2746. //
  2747. // Arguments: [pNewVirtualDF] - Pointer to new VirtualDF tree being made.
  2748. // [ptszRootDFName] - Pointer to name of root Disk file.
  2749. // [grfMode] - Mode to open the root storage
  2750. // [ppvcnRoot] - pointer to pointer to root of VirtualDF.
  2751. // [ulSeed] - pointer to pointer to root of VirtualDF.
  2752. //
  2753. // Notes: Call the above function with filled in params that are
  2754. // normally defaulted with the defaults. Seed is at the
  2755. // end, so we need them.
  2756. // This is a convenience function.
  2757. //
  2758. //--------------------------------------------------------------------------
  2759. HRESULT GenerateVirtualDFFromDiskDF(
  2760. VirtualDF *pNewVirtualDF,
  2761. LPTSTR ptszRootDFName,
  2762. DWORD grfMode,
  2763. VirtualCtrNode **ppvcnRoot,
  2764. ULONG ulSeed)
  2765. {
  2766. return GenerateVirtualDFFromDiskDF(
  2767. pNewVirtualDF,
  2768. ptszRootDFName,
  2769. grfMode,
  2770. ppvcnRoot,
  2771. NULL,
  2772. FALSE,
  2773. ulSeed);
  2774. }
  2775. //+-------------------------------------------------------------------------
  2776. // Function: GenerateRemVirtualDFTree
  2777. //
  2778. // Synopsis: Creates rest of in memory virtual DocFile tree for a given
  2779. // Disk Docfile. Internal function local to this file.
  2780. //
  2781. // Arguments: [pvcnParent] - pointer to root VirtualCtrNode
  2782. // [pIStgParent] - pointer to Disk IStorage assoc. with above.
  2783. //
  2784. // Returns: HRESULT
  2785. //
  2786. // History: 5-June-96 NarindK Created.
  2787. //
  2788. // Notes: -Call pIStgParent->Enumerate to get LPENUMSTATSTG for storage.
  2789. // -Call lpEnumStatStg->Next to get next element of enumeration.
  2790. // if it returns S_FALSE, that means there is nothing to enum-
  2791. // erate, so just return without nay error.
  2792. // -Else loop till hr is S_OK
  2793. // -If node is of type STGTY_STORAGE then
  2794. // -open this child storage.
  2795. // -Call GenVirtualCtrNode to create a corresponding
  2796. // VirtualCtrNode for this storage.
  2797. // -Call AppendChildCtr or AppendSisterCtr as case is.
  2798. // -Call parent's IncreaseChildrenStgCount to indicate
  2799. // a new VirtualCtrNode is added.
  2800. // -Make a recursive call to GenVirtualCtrNode.
  2801. // -Release the child storage pointer and remember the old
  2802. // sibling.
  2803. // -If node is of type STGSTY_STREAM then
  2804. // -Call GenVirtualStmNode to create a corresponding
  2805. // VirtualStmNode for this stream.
  2806. // -Call AppendChildStm or AppendSisterStm as case is.
  2807. // -Call parent's IncreaseChildrenStmCount to indicate
  2808. // a new VirtualStmNode is added.
  2809. // -Remember the old sibling.
  2810. // -Reinitialize local variables and call Next on the enumera-
  2811. // or. If it returns S_FALSE, then exist out of loop w/o
  2812. // any error.
  2813. // -Else go back to top of loop and repeat.
  2814. //--------------------------------------------------------------------------
  2815. HRESULT GenerateRemVirtualDFTree(
  2816. VirtualCtrNode *pvcnParent,
  2817. LPSTORAGE pIStgParent)
  2818. {
  2819. HRESULT hr = S_OK;
  2820. LPMALLOC pMalloc = NULL;
  2821. ULONG *pceltFetched = NULL;
  2822. LPSTORAGE pIStorageChild = NULL;
  2823. VirtualCtrNode *pvcnChild = NULL;
  2824. VirtualStmNode *pvsnChild = NULL;
  2825. VirtualCtrNode *pvcnOldSister = NULL;
  2826. VirtualStmNode *pvsnOldSister = NULL;
  2827. LPENUMSTATSTG lpEnumStatStg = NULL;
  2828. BOOL fFirstChild = TRUE;
  2829. BOOL fFirstStream = TRUE;
  2830. BOOL fIEnumNextFail = FALSE;
  2831. LPTSTR ptszNameStg = NULL;
  2832. LPTSTR ptszNameStm = NULL;
  2833. LPOLESTR pOleStrTemp = NULL;
  2834. STATSTG statStgEnum;
  2835. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenerateRemVirtualDFTree"));
  2836. // Initialization
  2837. statStgEnum.pwcsName = NULL;
  2838. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  2839. if ( S_OK == hr )
  2840. {
  2841. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  2842. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  2843. }
  2844. if ( S_OK == hr )
  2845. {
  2846. // Get an Enumerator for given IStorage
  2847. hr = pIStgParent->EnumElements(0, NULL, 0, &lpEnumStatStg);
  2848. DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
  2849. }
  2850. // if successful to get enumerator, get the first element of the enumeration
  2851. // sequence.
  2852. if ( S_OK == hr )
  2853. {
  2854. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2855. if(S_FALSE == hr)
  2856. {
  2857. fIEnumNextFail = TRUE;
  2858. }
  2859. }
  2860. while(S_OK == hr)
  2861. {
  2862. // If the element is an IStorage, open this and make a recursive call
  2863. // to self.
  2864. if (STGTY_STORAGE == statStgEnum.type)
  2865. {
  2866. if(S_OK == hr)
  2867. {
  2868. //Convert WCHAR to TCHAR
  2869. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
  2870. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2871. }
  2872. if(S_OK == hr)
  2873. {
  2874. // Convert TCHAR to OLECHAR
  2875. hr = TStringToOleString(ptszNameStg, &pOleStrTemp);
  2876. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2877. }
  2878. hr = pIStgParent->OpenStorage(
  2879. pOleStrTemp,
  2880. NULL,
  2881. STGM_READ | STGM_SHARE_EXCLUSIVE,
  2882. NULL,
  2883. 0,
  2884. &pIStorageChild);
  2885. DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
  2886. // Add to tree
  2887. if (S_OK == hr)
  2888. {
  2889. hr = GenVirtualCtrNode(
  2890. ptszNameStg,
  2891. &pvcnChild);
  2892. }
  2893. if (S_OK == hr)
  2894. {
  2895. if(fFirstChild == TRUE)
  2896. {
  2897. hr = pvcnParent->AppendChildCtr(pvcnChild);
  2898. pvcnParent->IncreaseChildrenStgCount();
  2899. fFirstChild = FALSE;
  2900. }
  2901. else
  2902. {
  2903. hr = pvcnOldSister->AppendSisterCtr(pvcnChild);
  2904. pvcnParent->IncreaseChildrenStgCount();
  2905. }
  2906. }
  2907. if (S_OK == hr)
  2908. {
  2909. // Recursive call to self
  2910. hr = GenerateRemVirtualDFTree(pvcnChild, pIStorageChild);
  2911. DH_HRCHECK(hr, TEXT("EnumerateDiskDocFile")) ;
  2912. }
  2913. // Release the storage pointer
  2914. if(NULL != pIStorageChild)
  2915. {
  2916. pIStorageChild->Release();
  2917. pIStorageChild = NULL;
  2918. }
  2919. // Remember the old sibling
  2920. pvcnOldSister = pvcnChild;
  2921. }
  2922. else
  2923. // The element is an IStream.
  2924. if (STGTY_STREAM == statStgEnum.type)
  2925. {
  2926. // Add to tree
  2927. if (S_OK == hr)
  2928. {
  2929. if(S_OK == hr)
  2930. {
  2931. // Convert WCHAR to TCHAR
  2932. hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
  2933. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2934. }
  2935. // BUGBUG:The cbSize used during creation is a DWORD. Assumption
  2936. // cbSize.LowPart contains the size information hence.
  2937. hr = GenVirtualStmNode(
  2938. ptszNameStm,
  2939. statStgEnum.cbSize.LowPart,
  2940. &pvsnChild);
  2941. }
  2942. if (S_OK == hr)
  2943. {
  2944. if(fFirstStream == TRUE)
  2945. {
  2946. hr = pvcnParent->AppendFirstChildStm(pvsnChild);
  2947. pvcnParent->IncreaseChildrenStmCount();
  2948. fFirstStream = FALSE;
  2949. }
  2950. else
  2951. {
  2952. hr = pvsnOldSister->AppendSisterStm(pvsnChild);
  2953. pvcnParent->IncreaseChildrenStmCount();
  2954. }
  2955. }
  2956. // Remember the old sibling
  2957. pvsnOldSister = pvsnChild;
  2958. }
  2959. else
  2960. // The element is neither IStorage nor IStream, report error.
  2961. {
  2962. hr = E_UNEXPECTED;
  2963. }
  2964. // Cleanup
  2965. if(NULL != statStgEnum.pwcsName)
  2966. {
  2967. pMalloc->Free(statStgEnum.pwcsName);
  2968. statStgEnum.pwcsName = NULL;
  2969. }
  2970. if(NULL != pOleStrTemp)
  2971. {
  2972. delete pOleStrTemp;
  2973. pOleStrTemp = NULL;
  2974. }
  2975. if(NULL != ptszNameStg)
  2976. {
  2977. delete ptszNameStg;
  2978. ptszNameStg = NULL;
  2979. }
  2980. if(NULL != ptszNameStm)
  2981. {
  2982. delete ptszNameStm;
  2983. ptszNameStm = NULL;
  2984. }
  2985. // Reinitialize the variables
  2986. pIStorageChild = NULL;
  2987. pvcnChild = NULL;
  2988. pvsnChild = NULL;
  2989. // Get the next element in the enumeration sequence
  2990. if(S_OK == hr)
  2991. {
  2992. hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
  2993. if(S_FALSE == hr)
  2994. {
  2995. fIEnumNextFail = TRUE;
  2996. }
  2997. }
  2998. }
  2999. // IEnumSTATSTG->Next returning S_FALSE indicates end of traversal in
  3000. // docfile hierarchy, not an error.
  3001. if(TRUE == fIEnumNextFail)
  3002. {
  3003. hr = S_OK;
  3004. }
  3005. // Clean up
  3006. if (NULL != lpEnumStatStg)
  3007. {
  3008. lpEnumStatStg->Release();
  3009. lpEnumStatStg = NULL;
  3010. }
  3011. if(NULL != pMalloc)
  3012. {
  3013. pMalloc->Release();
  3014. pMalloc = NULL;
  3015. }
  3016. return hr;
  3017. }
  3018. //+-------------------------------------------------------------------------
  3019. // Function: GenVirtualCtrNode
  3020. //
  3021. // Synopsis: Creates a VirtualCtrNode and initializes it
  3022. //
  3023. // Arguments: [ptcsName] - pointer to name for VirtualCtrNode
  3024. // [*ppvcnNew] - Returned VirtualCtrNode.
  3025. //
  3026. // Returns: HRESULT
  3027. //
  3028. // History: 5-June-96 NarindK Created.
  3029. //
  3030. // Notes: Creates a VirtualCtrNode and initializes it will pName that
  3031. // is passed in. _cChildren and _cStreams are initialized to
  3032. // zero.
  3033. //--------------------------------------------------------------------------
  3034. HRESULT GenVirtualCtrNode(
  3035. LPTSTR ptcsName,
  3036. VirtualCtrNode **ppvcnNew)
  3037. {
  3038. HRESULT hr = S_OK;
  3039. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenVirtualCtrNodeFromDiskStg"));
  3040. DH_VDATEPTRIN(ptcsName, TCHAR) ;
  3041. DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ;
  3042. DH_ASSERT(NULL != ptcsName);
  3043. DH_ASSERT(NULL != ppvcnNew);
  3044. // Generate VirtualCtrNode for the stg.
  3045. if(S_OK == hr)
  3046. {
  3047. // Initialize out parameter
  3048. *ppvcnNew = NULL;
  3049. // Create new VirtualCtrNode
  3050. *ppvcnNew = new VirtualCtrNode();
  3051. if (NULL == *ppvcnNew)
  3052. {
  3053. hr = E_OUTOFMEMORY;
  3054. }
  3055. }
  3056. if(S_OK == hr)
  3057. {
  3058. // Initialize VirtualCtrNode
  3059. hr = (*ppvcnNew)->Init(ptcsName, 0, 0);
  3060. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  3061. }
  3062. return hr;
  3063. }
  3064. //+-------------------------------------------------------------------------
  3065. // Function: GenVirtualStmNode
  3066. //
  3067. // Synopsis: Creates a VirtualStmNode and initializes it
  3068. //
  3069. // Arguments: [ptcsName] - pointer to name for VirtualStmNode
  3070. // [*ppvcnNew] - Returned VirtualStmNode.
  3071. //
  3072. // Returns: HRESULT
  3073. //
  3074. // History: 5-June-96 NarindK Created.
  3075. //
  3076. // Notes: -Creates a new VirtualStmNode and initializes it with name
  3077. // and size passed in.
  3078. //--------------------------------------------------------------------------
  3079. HRESULT GenVirtualStmNode(
  3080. LPTSTR ptcsName,
  3081. DWORD cbSize,
  3082. VirtualStmNode **ppvsnNew)
  3083. {
  3084. HRESULT hr = S_OK;
  3085. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenVirtualStmNode"));
  3086. DH_VDATEPTRIN(ptcsName, TCHAR) ;
  3087. DH_VDATEPTROUT(ppvsnNew, PVSTMNODE) ;
  3088. DH_ASSERT(NULL != ptcsName);
  3089. DH_ASSERT(NULL != ppvsnNew);
  3090. // Generate VirtualStmNode for the stream.
  3091. if(S_OK == hr)
  3092. {
  3093. *ppvsnNew = new VirtualStmNode();
  3094. if (NULL == *ppvsnNew)
  3095. {
  3096. hr = E_OUTOFMEMORY;
  3097. }
  3098. }
  3099. if(S_OK == hr)
  3100. {
  3101. hr = (*ppvsnNew)->Init(ptcsName, cbSize);
  3102. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
  3103. }
  3104. return hr;
  3105. }
  3106. //+-------------------------------------------------------------------
  3107. //
  3108. // Function: PrivAtol
  3109. //
  3110. // Synopsis: Private "atol" function for better error control
  3111. //
  3112. // Arguments: [pszNum] - The number string
  3113. //
  3114. // [plResult] - A place to put the result
  3115. //
  3116. // Returns: S_OK if the function succeeds, another HRESULT otherwise
  3117. //
  3118. // History: 28-Jul-1995 AlexE Created
  3119. // 20-May-1996 Narindk Adapted for stgbase tests.
  3120. //
  3121. //--------------------------------------------------------------------
  3122. HRESULT PrivAtol(char *pszNum, LONG *plResult)
  3123. {
  3124. LONG l = 0 ;
  3125. *plResult = 0 ;
  3126. while (0 != *pszNum)
  3127. {
  3128. if (*pszNum > '9' || *pszNum < '0')
  3129. {
  3130. return E_INVALIDARG ;
  3131. }
  3132. l = 10 * l + (LONG) ((*pszNum - '0')) ;
  3133. pszNum++ ;
  3134. }
  3135. *plResult = l ;
  3136. return S_OK ;
  3137. }
  3138. //+-------------------------------------------------------------------------
  3139. //
  3140. // Function: GenerateRandomString
  3141. //
  3142. // Synopsis: Generates a random string using datagen object. This function
  3143. // differs from the orginal GenerateRandomFunction in the fact
  3144. // that it doesn't generate a random extenstion.
  3145. //
  3146. // Arguments: [pgdu] - Pointer to DG_UNICODE object.
  3147. // [pptszName] - Pointer to pointer to returned string.
  3148. // [ulMinLen] - Minimum length of string
  3149. // [ulMaxLen] - Maximum length of string
  3150. //
  3151. // Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
  3152. //
  3153. // History: 17-Apr-96 NarindK Created.
  3154. // 31-July-96 Narindk Adapted to stgbase tests.
  3155. //
  3156. // Notes: BUGBUG: This function need to be enhance to handle different
  3157. // character sets.
  3158. // Please note that in GenerateRandomName, name gen may have an
  3159. // extension b/w 0 and FILEEXT_MAXLEN besides the length of name
  3160. // b/w ulMinLen and ulMax Len. But with this function, it will
  3161. // not have any extension, so the length would be b/w ulMinLen &
  3162. // ulMaxLen.
  3163. //
  3164. //--------------------------------------------------------------------------
  3165. HRESULT GenerateRandomString(
  3166. DG_STRING *pgds,
  3167. ULONG ulMinLen,
  3168. ULONG ulMaxLen,
  3169. LPTSTR *pptszName)
  3170. {
  3171. HRESULT hr = S_OK;
  3172. ULONG cTemp = 0;
  3173. USHORT usErr = 0;
  3174. ULONG ulActMaxLen = 0;
  3175. ULONG ulActMinLen = 0;
  3176. ULONG ulNameLen = 0;
  3177. LPTSTR ptszName = NULL;
  3178. LPWSTR pwszName = NULL;
  3179. TCHAR ptszFATCharSet[FAT_CHARSET_SIZE];
  3180. LPWSTR pwszFATCharSet = NULL;
  3181. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRandomString"));
  3182. DH_VDATEPTRIN(pgds, DG_STRING) ;
  3183. DH_VDATEPTROUT(pptszName, LPTSTR) ;
  3184. DH_ASSERT(NULL != pgds);
  3185. DH_ASSERT(NULL != pptszName);
  3186. if (S_OK == hr)
  3187. {
  3188. // Initialize out parameter.
  3189. *pptszName = NULL;
  3190. // Sanity check. Min length for name must be <= maximum length, if it
  3191. // isn't then make maximum length equal to minimum length.
  3192. if (ulMaxLen < ulMinLen)
  3193. {
  3194. ulMaxLen = ulMinLen;
  3195. }
  3196. // If Maximum length provided is 0, then default maximum length would
  3197. // be used. If Minimum length provided is zero, then 1 would be used
  3198. // for it.
  3199. // BUGBUG: We are using default maximum length for FAT system.
  3200. ulActMaxLen = (ulMaxLen == 0 ? DEF_FATNAME_MAXLEN : ulMaxLen);
  3201. ulActMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
  3202. // '\0', '\', '/', and ':' are invalid for IStorage/IStream names
  3203. // (For doc file)
  3204. // '*', '"' '<' '>' '?' are invalid for IStorage/IStream names on OFS
  3205. // Initialize valid character set for FAT file names
  3206. _tcscpy(ptszFATCharSet, _TEXT("abcdefghijklmnopqrstuvwxyz"));
  3207. _tcscat(ptszFATCharSet, _TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
  3208. _tcscat(ptszFATCharSet, _TEXT("0123456789"));
  3209. // Call DataGen to generate a random file name
  3210. // BUGBUG: We are using FAT character set to generate random names.
  3211. #ifdef _MAC
  3212. usErr = pgds->Generate(
  3213. (UCHAR **)&ptszName, // force compiler to chose the right
  3214. (UCHAR *)ptszFATCharSet, // version of Generate
  3215. ulActMinLen,
  3216. ulActMaxLen);
  3217. #else
  3218. if(S_OK == hr)
  3219. {
  3220. // Convert TCHAR to WCHAR
  3221. hr = TStrToWStr(ptszFATCharSet, &pwszFATCharSet);
  3222. DH_HRCHECK(hr, TEXT("TStrToWStr")) ;
  3223. }
  3224. usErr = pgds->Generate(
  3225. &pwszName,
  3226. pwszFATCharSet,
  3227. ulActMinLen,
  3228. ulActMaxLen);
  3229. #endif //_MAC
  3230. if (usErr != DG_RC_SUCCESS) // DataGen error
  3231. {
  3232. hr = E_FAIL;
  3233. }
  3234. }
  3235. #ifndef _MAC
  3236. if(S_OK == hr)
  3237. {
  3238. // Convert WCHAR to TCHAR
  3239. hr = WStrToTStr(pwszName, &ptszName);
  3240. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  3241. }
  3242. #endif //_MAC
  3243. if (S_OK == hr)
  3244. {
  3245. ulNameLen = _tcslen(ptszName);
  3246. // Construct the full name
  3247. *pptszName = new TCHAR[ulNameLen + 1];
  3248. if(NULL == *pptszName)
  3249. {
  3250. hr = E_OUTOFMEMORY;
  3251. }
  3252. }
  3253. if (S_OK == hr)
  3254. {
  3255. _tcscpy(*pptszName, ptszName);
  3256. }
  3257. // Clean up
  3258. if (NULL != ptszName)
  3259. {
  3260. delete ptszName;
  3261. ptszName = NULL;
  3262. }
  3263. if (NULL != pwszName)
  3264. {
  3265. delete pwszName;
  3266. pwszName = NULL;
  3267. }
  3268. if (NULL != pwszFATCharSet)
  3269. {
  3270. delete pwszFATCharSet;
  3271. pwszFATCharSet = NULL;
  3272. }
  3273. return hr;
  3274. }
  3275. //+-------------------------------------------------------------------------
  3276. // Function: GenerateRandomStreamData
  3277. //
  3278. // Synopsis: Generates a random data using datagen object.
  3279. //
  3280. // Arguments: [pgds] - Pointer to DG_STRING object.
  3281. // [pptszName] - Pointer to pointer to returned string.
  3282. // [ulMinLen] - Minimum length of string
  3283. // [ulMaxLen] - Maximum length of string
  3284. //
  3285. // Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
  3286. //
  3287. // History: 30-Mar-98 SCousens Created from GenerateRandomName
  3288. //
  3289. // Notes:
  3290. // -ulMaxLen is defaulted, so you dont need to specify
  3291. // both ulMinLen and ulMaxLen if you want a random buffer
  3292. // of a given length.
  3293. // -If ulMaxLen is less than ulMinLen, buffer will be
  3294. // ulMinLen bytes in length.
  3295. // -Generate a buffer upto CB_STMDATA_DATABUFFER bytes in
  3296. // length. Copy this buffer multiple times into actual
  3297. // returned buffer.
  3298. // -Alphabet currently ASCII 1-255
  3299. //--------------------------------------------------------------------------
  3300. HRESULT GenerateRandomStreamData(
  3301. DG_STRING *pgds,
  3302. LPTSTR *pptszData,
  3303. ULONG ulMinLen,
  3304. ULONG ulMaxLen)
  3305. {
  3306. HRESULT hr = S_OK;
  3307. UINT x;
  3308. USHORT usErr = 0;
  3309. ULONG cbBuffer = 0;
  3310. ULONG ulBufferLen = 0;
  3311. ULONG ulRndStart = 0;
  3312. ULONG ulBufStart = 0;
  3313. LPBYTE pbDataBuf = 0;
  3314. LPBYTE pbRndBuffer = 0;
  3315. DG_INTEGER *dgi; //we need to generate random numbers
  3316. #ifdef _MAC
  3317. CHAR szCharSet[CB_STMDATA_CHARSET];
  3318. #else
  3319. WCHAR szCharSet[CB_STMDATA_CHARSET];
  3320. #endif //_MAC
  3321. DH_FUNCENTRY (NULL, DH_LVL_DFLIB, TEXT("GenerateRandomStreamData"));
  3322. DH_VDATEPTRIN (pgds, DG_STRING) ;
  3323. DH_VDATEPTROUT (pptszData, LPTSTR) ;
  3324. DH_ASSERT (NULL != pgds);
  3325. DH_ASSERT (NULL != pptszData);
  3326. // use seed from given dgs, its the best we can do...
  3327. dgi = new DG_INTEGER (pgds->GetSeed ());
  3328. if (NULL == dgi)
  3329. {
  3330. hr = E_OUTOFMEMORY;
  3331. }
  3332. DH_HRCHECK (hr, TEXT("new DG_INTEGER"));
  3333. if (S_OK == hr)
  3334. {
  3335. // Initialize out parameter.
  3336. *pptszData = NULL;
  3337. // Sanity check. Min length for name must be <= maximum length.
  3338. // if used default params, make max same as min (it will be 0)
  3339. if (ulMaxLen < ulMinLen)
  3340. {
  3341. ulMaxLen = ulMinLen;
  3342. }
  3343. // If Maximum length provided is 0, then default to 512 (BUGBUG: hardcoded)
  3344. // If Minimum length provided is 0, then use 1
  3345. ulMaxLen = (ulMaxLen == 0 ? 512 : ulMaxLen);
  3346. ulMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
  3347. // Initialize character set (BUGBUG currenly only ASCII 01-255)
  3348. for (x=0; x<CB_STMDATA_CHARSET-1; x++)
  3349. {
  3350. szCharSet[x] = x+1; //omit NULL to start
  3351. }
  3352. // this is how many chars we will be putting into the stream.
  3353. // since dg_string::Generate chooses, and we are bypassin that,
  3354. // we need to choose a number between ulminlen, ulmaxlen.
  3355. dgi->Generate (&ulBufferLen, ulMinLen, ulMaxLen);
  3356. // If needed buffer is smaller than our buffer,
  3357. // just generate that many bytes.
  3358. cbBuffer = min (CB_STMDATA_DATABUFFER, ulBufferLen);
  3359. // make our buffer
  3360. #ifdef _MAC
  3361. usErr = pgds->Generate(
  3362. (UCHAR **)&pbRndBuffer, // force compiler to chose the right
  3363. (UCHAR *)szCharSet, // version of Generate
  3364. cbBuffer / sizeof (TCHAR), // need chars
  3365. cbBuffer / sizeof (TCHAR)); // cbBuffer is bytes
  3366. #else
  3367. usErr = pgds->Generate(
  3368. (LPWSTR*)&pbRndBuffer,
  3369. szCharSet,
  3370. cbBuffer+1 / sizeof (TCHAR), // need chars
  3371. cbBuffer+1 / sizeof (TCHAR)); // cbBuffer is bytes
  3372. #endif //_MAC
  3373. if (usErr != DG_RC_SUCCESS) // DataGen error
  3374. {
  3375. hr = E_FAIL;
  3376. }
  3377. DH_HRCHECK (hr, TEXT("pgds::Generate"));
  3378. }
  3379. // now allocate the data buffer
  3380. if (S_OK == hr)
  3381. {
  3382. pbDataBuf = new BYTE[ulBufferLen];
  3383. if (NULL == pbDataBuf)
  3384. {
  3385. hr = E_OUTOFMEMORY;
  3386. }
  3387. DH_HRCHECK (hr, TEXT("new BYTE"));
  3388. DH_TRACE ((DH_LVL_TRACE4,
  3389. TEXT("Data buffer (%#x) - allocated %x bytes, (%d bytes)"),
  3390. pbDataBuf,
  3391. ulBufferLen,
  3392. ulBufferLen));
  3393. }
  3394. if (S_OK == hr)
  3395. {
  3396. for (ulBufStart=0; ulBufStart<ulBufferLen; ulBufStart+=cbBuffer)
  3397. {
  3398. //generate a random starting point
  3399. dgi->Generate (&ulRndStart,
  3400. 0,
  3401. min (CB_STMDATA_DATABUFFER, ulBufferLen));
  3402. // Copy from rnd spot to end of buffer (provided we need it all)
  3403. cbBuffer = min (CB_STMDATA_DATABUFFER-ulRndStart, ulBufferLen-ulBufStart);
  3404. MoveMemory (&pbDataBuf[ulBufStart],
  3405. &pbRndBuffer[ulRndStart],
  3406. cbBuffer);
  3407. ulBufStart+=cbBuffer;
  3408. // Copy from begin of buffer to rnd spot (provided we need it)
  3409. cbBuffer = min (ulRndStart, ulBufferLen-ulBufStart);
  3410. if (0 != cbBuffer)
  3411. {
  3412. MoveMemory (&pbDataBuf[ulBufStart],
  3413. pbRndBuffer,
  3414. cbBuffer);
  3415. }
  3416. }
  3417. }
  3418. if (S_OK == hr)
  3419. {
  3420. *pptszData = (LPTSTR)pbDataBuf;
  3421. }
  3422. // Clean up
  3423. delete []pbRndBuffer;
  3424. return hr;
  3425. }
  3426. //-------------------------------------------------------------------------
  3427. // Function: ParseVirtualDFAndOpenAllSubStgsStms
  3428. //
  3429. // Synopsis: Given a storage, this function will recurse down the
  3430. // tree, opening all substorages and streams.
  3431. //
  3432. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  3433. // [dwStgMode] - Mode to open sub-storages
  3434. // [dwStmMode] - Mode to open streams
  3435. //
  3436. // Returns: HRESULT
  3437. //
  3438. // History: 27-January-97 SCousens Created.
  3439. //
  3440. // Notes: - provided VirtualCtrNode must already be open.
  3441. // - ALL substgs and stms must be closed before
  3442. // calling this, else access violations may occur
  3443. HRESULT ParseVirtualDFAndOpenAllSubStgsStms (VirtualCtrNode * pvcn,
  3444. DWORD dwStgMode,
  3445. DWORD dwStmMode)
  3446. {
  3447. HRESULT hr = S_OK;
  3448. VirtualCtrNode * pvcnTrav = NULL;
  3449. VirtualStmNode * pvsnTrav = NULL;
  3450. DH_VDATEPTRIN (pvcn, VirtualCtrNode);
  3451. DH_ASSERT (NULL != pvcn->GetIStoragePointer ()); //if not open _pstg will be null
  3452. // enumerate and open all stms in current stg.
  3453. pvsnTrav = pvcn->GetFirstChildVirtualStmNode ();
  3454. while(NULL != pvsnTrav && S_OK == hr)
  3455. {
  3456. if (NULL == pvsnTrav->GetIStreamPointer ())
  3457. {
  3458. hr = pvsnTrav->Open(NULL, dwStmMode, NULL);
  3459. }
  3460. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode ();
  3461. }
  3462. // enumerate and open all stgs in current stg.
  3463. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  3464. while(NULL != pvcnTrav && S_OK == hr)
  3465. {
  3466. if (NULL == pvcnTrav->GetIStoragePointer ())
  3467. {
  3468. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  3469. }
  3470. // then recursively open all elements in just opened stg.
  3471. if (S_OK == hr)
  3472. {
  3473. hr = ParseVirtualDFAndOpenAllSubStgsStms (pvcnTrav,
  3474. dwStgMode,
  3475. dwStmMode);
  3476. }
  3477. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode ();
  3478. }
  3479. return hr;
  3480. }
  3481. //+-------------------------------------------------------------------------
  3482. //
  3483. // Function: GetDocFileName
  3484. //
  3485. // Synopsis: Figures out name of docfile given the seed
  3486. //
  3487. // Arguments: [in] ulSeed - the seed value
  3488. // [out] ptszDocName - docfile name (needs to be deleted [])
  3489. //
  3490. // Returns: S_OK if all goes well, another HRESULT if not.
  3491. //
  3492. // History: 19-Mar-97 SCousens Created
  3493. //
  3494. // Notes: We can take advantage of the way VirtualDF gets the
  3495. // docfile name. Its the first string generated.
  3496. //
  3497. //--------------------------------------------------------------------------
  3498. HRESULT GetDocFileName (ULONG ulSeed, LPTSTR *pptszDocName)
  3499. {
  3500. HRESULT hr = E_FAIL;
  3501. DG_STRING *pdgs = NULL;
  3502. DH_FUNCENTRY(NULL, DH_LVL_TRACE1, TEXT("GetDocFileName"));
  3503. DH_VDATEPTROUT (pptszDocName, LPTSTR);
  3504. DH_ASSERT (NULL != ulSeed);
  3505. // init out stuff
  3506. *pptszDocName = NULL;
  3507. //get our datagen
  3508. pdgs = new DG_STRING (ulSeed);
  3509. if (NULL != pdgs)
  3510. {
  3511. // Generate random name for root
  3512. hr = GenerateRandomName(
  3513. pdgs,
  3514. MINLENGTH,
  3515. MAXLENGTH,
  3516. pptszDocName);
  3517. DH_HRCHECK (hr, TEXT("GenerateRandomName")) ;
  3518. }
  3519. // cleanup
  3520. delete pdgs;
  3521. return hr;
  3522. }
  3523. //-------------------------------------------------------------------------
  3524. // Function: CommitRandomVirtualCtrNodeStg
  3525. //
  3526. // Synopsis: Commits a VirtualCtrNode's IStorage and all ascedant
  3527. // IStorages. This traverses through all the parents
  3528. // and commit them excluding the root IStorage
  3529. //
  3530. // Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage
  3531. // is to be commited
  3532. // [grfCommitMode] - Commit mode
  3533. //
  3534. // Returns: HRESULT
  3535. //
  3536. // History: 16-Apr-97 BogdanT Created.
  3537. //
  3538. // Notes:
  3539. //--------------------------------------------------------------------------
  3540. HRESULT CommitRandomVirtualCtrNodeStg(VirtualCtrNode *pvcn,
  3541. DWORD grfCommitMode)
  3542. {
  3543. HRESULT hr = S_OK;
  3544. VirtualCtrNode *pvcnTrav = NULL;
  3545. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CommitRandomVirtualCtrNodeStg"));
  3546. DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
  3547. DH_ASSERT(NULL != pvcn);
  3548. pvcnTrav = pvcn;
  3549. if(S_OK == hr)
  3550. {
  3551. while((NULL != pvcnTrav->GetParentVirtualCtrNode()) && (S_OK == hr))
  3552. {
  3553. hr = pvcnTrav->Commit(grfCommitMode);
  3554. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit")) ;
  3555. pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
  3556. }
  3557. }
  3558. return hr;
  3559. }