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.

5990 lines
169 KiB

  1. //-------------------------------------------------------------------------
  2. //
  3. // Microsoft OLE
  4. // Copyright (C) Microsoft Corporation, 1994 - 1995.
  5. //
  6. // File: utl.cxx
  7. //
  8. // Contents: utilities for OLE storage base tests
  9. //
  10. // Functions:
  11. //
  12. // History: NarindK Created.
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <dfheader.hxx>
  16. #pragma hdrstop
  17. #include "init.hxx"
  18. //global array of interesting file sizes for IStream read/writes
  19. USHORT ausSIZE_ARRAY[] =
  20. {0,1,2,255,256,257,511,512,513,2047,2048,2049,4095,4096,4097};
  21. // externs
  22. extern BOOL g_fUseStdBlk;
  23. extern ULONG ulStreamSize;
  24. extern USHORT usIterations;
  25. extern LPTSTR ptszNames[MAX_DOCFILES];
  26. extern ULONG *ulSeekOffset;
  27. extern TIMEINFO Time[];
  28. //----------------------------------------------------------------------------
  29. //
  30. // Function: CountFilesInDirectory
  31. //
  32. // Synopsis: count number of files in directory matching wildcard mask
  33. //
  34. // Arguments: [pszWildMask] - wild card mask string of files to find
  35. //
  36. // Returns: number of files found
  37. //
  38. // History: 2-Jul-1996 Narindk Created
  39. //
  40. //-----------------------------------------------------------------------------
  41. ULONG CountFilesInDirectory(LPTSTR ptszWildMask)
  42. {
  43. #ifdef _MAC
  44. DH_LOG((
  45. LOG_INFO,
  46. TEXT("!!!!!!!!!!!!!!CountFilesInDirectory not implemented yet.\n")));
  47. return 0;
  48. #else
  49. ULONG culFilesInDirectory = 0;
  50. DWORD cChar = 0;
  51. HANDLE hFind = NULL;
  52. TCHAR ptszTmpFileDir[_MAX_PATH];
  53. TCHAR ptszTmpFilePath[_MAX_PATH];
  54. WIN32_FIND_DATA wfd;
  55. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CountFilesInDirectory"));
  56. cChar = GetEnvironmentVariable(
  57. TEXT("TMP"),
  58. ptszTmpFileDir,
  59. sizeof(ptszTmpFileDir));
  60. DH_ASSERT(0 != cChar);
  61. if (0 != cChar)
  62. {
  63. _tcscpy(ptszTmpFilePath, ptszTmpFileDir);
  64. _tcscat(ptszTmpFilePath, TEXT("\\"));
  65. }
  66. else
  67. {
  68. _tcscpy(ptszTmpFilePath, TEXT("C:\\"));
  69. }
  70. _tcscat(ptszTmpFilePath, ptszWildMask);
  71. DH_LOG((
  72. LOG_INFO,
  73. TEXT("Counting %s files in %s directory\n"),
  74. ptszWildMask,
  75. ptszTmpFileDir == NULL ? TEXT("C:\\") : ptszTmpFileDir));
  76. hFind = FindFirstFile(ptszTmpFilePath, &wfd);
  77. if(INVALID_HANDLE_VALUE != hFind)
  78. {
  79. do
  80. {
  81. if(wfd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
  82. {
  83. culFilesInDirectory++;
  84. }
  85. } while (FindNextFile(hFind, &wfd));
  86. FindClose(hFind);
  87. }
  88. DH_LOG((
  89. LOG_INFO,
  90. TEXT("Number of %s files in %s directory = %lu\n"),
  91. ptszWildMask,
  92. ptszTmpFileDir == NULL ? TEXT("C:\\") : ptszTmpFileDir,
  93. culFilesInDirectory));
  94. return culFilesInDirectory;
  95. #endif //_MAC
  96. }
  97. //----------------------------------------------------------------------------
  98. //
  99. // Function: GetRandomSeekOffset
  100. //
  101. // Synopsis: Gets a random seek offset from either standard array or a random
  102. // number
  103. //
  104. // Arguments: [plSeekPosition] - Pointer to seek position
  105. // [pdgi] - Pointer to data generator object
  106. //
  107. // Returns: HResult
  108. //
  109. // History: 5-Jul-1996 Narindk Created
  110. //
  111. //-----------------------------------------------------------------------------
  112. HRESULT GetRandomSeekOffset(LONG *plSeekPosition, DG_INTEGER *pdgi)
  113. {
  114. HRESULT hr = S_OK;
  115. ULONG cArrayIndex = 0;
  116. USHORT usErr = 0;
  117. LONG lSeekPosition = 0;
  118. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetRandomSeekOffset"));
  119. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  120. DH_VDATEPTRIN(plSeekPosition, LONG ) ;
  121. DH_ASSERT(NULL != pdgi);
  122. if(TRUE == g_fUseStdBlk)
  123. {
  124. // Pick up a random array element.
  125. usErr = pdgi->Generate(&cArrayIndex, 0, MAX_SIZE_ARRAY);
  126. if (DG_RC_SUCCESS != usErr)
  127. {
  128. hr = E_FAIL;
  129. }
  130. else
  131. {
  132. *plSeekPosition = *plSeekPosition + ausSIZE_ARRAY[cArrayIndex];
  133. }
  134. }
  135. else
  136. {
  137. // Pick up a random offset
  138. usErr = pdgi->Generate(
  139. &lSeekPosition,
  140. 0,
  141. ausSIZE_ARRAY[MAX_SIZE_ARRAY] * MAX_SIZE_MULTIPLIER );
  142. if (DG_RC_SUCCESS != usErr)
  143. {
  144. hr = E_FAIL;
  145. }
  146. else
  147. {
  148. *plSeekPosition = *plSeekPosition + lSeekPosition;
  149. }
  150. }
  151. return hr;
  152. }
  153. //----------------------------------------------------------------------------
  154. //
  155. // Function: SetItemsInStorage
  156. //
  157. // Synopsis: Does random SetClass / SetStateBits/ Commit / Revert operations
  158. // on passed IStorage.
  159. //
  160. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  161. // [pdgi] - Pointer to data generator object
  162. //
  163. // Returns: HResult
  164. //
  165. // History: 15-Jul-1996 Narindk Created
  166. //
  167. //-----------------------------------------------------------------------------
  168. HRESULT SetItemsInStorage(VirtualCtrNode *pvcn, DG_INTEGER *pdgi)
  169. {
  170. HRESULT hr = S_OK;
  171. USHORT usErr = 0;
  172. ULONG cRandomVar = 0;
  173. ULONG cRandomClsid = 0;
  174. ULONG cMinVar = 16;
  175. ULONG cMaxVar = 32;
  176. DWORD grfStateBits = 0;
  177. DWORD grfMask = 0;
  178. DWORD grfDesiredStateBits = 0;
  179. BOOL fStateBitsChanged = FALSE;
  180. BOOL fPass = TRUE;
  181. STATSTG statStgCommited;
  182. STATSTG statStgCurrent;
  183. STATSTG statStgNew;
  184. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("SetItemsInStorage"));
  185. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  186. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  187. DH_ASSERT(NULL != pvcn);
  188. DH_ASSERT(NULL != pdgi);
  189. if (S_OK == hr)
  190. {
  191. // Generate random number of variations.
  192. usErr = pdgi->Generate(&cRandomVar, cMinVar, cMaxVar);
  193. if (DG_RC_SUCCESS != usErr)
  194. {
  195. hr = E_FAIL;
  196. }
  197. }
  198. //initialize STATSTG containing info about what is on persistent store
  199. if(S_OK == hr)
  200. {
  201. hr = pvcn->Stat(&statStgCommited, STATFLAG_NONAME);
  202. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
  203. }
  204. if (S_OK == hr)
  205. {
  206. DH_LOG((
  207. LOG_INFO,
  208. TEXT("VirtualCtrNode::Stat completed successfully.\n")));
  209. }
  210. else
  211. {
  212. DH_LOG((
  213. LOG_INFO,
  214. TEXT("VirtualCtrNode::Stat unsuccessful, hr=0x%lx.\n"),
  215. hr));
  216. }
  217. // Start while loop
  218. while((S_OK == hr) && (0 != cRandomVar))
  219. {
  220. if(S_OK == hr)
  221. {
  222. hr = pvcn->Stat(&statStgCurrent, STATFLAG_NONAME);
  223. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
  224. }
  225. if(S_OK == hr)
  226. {
  227. // Randomly either change the CLSID or State Bits.
  228. if(0 == cRandomVar%2)
  229. {
  230. usErr = pdgi->Generate(&cRandomClsid, 1, 3);
  231. if (DG_RC_SUCCESS != usErr)
  232. {
  233. hr = E_FAIL;
  234. }
  235. if(S_OK == hr)
  236. {
  237. // Call Set Class to change CLSID
  238. switch(cRandomClsid)
  239. {
  240. case 1:
  241. {
  242. hr = pvcn->SetClass(IID_IUnknown);
  243. break;
  244. }
  245. case 2:
  246. {
  247. hr = pvcn->SetClass(IID_IStorage);
  248. break;
  249. }
  250. case 3:
  251. {
  252. hr = pvcn->SetClass(IID_IStream);
  253. break;
  254. }
  255. }
  256. DH_HRCHECK(hr, TEXT("VirtualCtrNode::SetClass")) ;
  257. }
  258. }
  259. else
  260. {
  261. // Set boolean to true indicatinng changing state bits
  262. fStateBitsChanged = TRUE;
  263. usErr = pdgi->Generate(&grfStateBits, 0, ULONG_MAX);
  264. if (DG_RC_SUCCESS != usErr)
  265. {
  266. hr = E_FAIL;
  267. }
  268. if(S_OK == hr)
  269. {
  270. usErr = pdgi->Generate(&grfMask, 0, ULONG_MAX);
  271. if (DG_RC_SUCCESS != usErr)
  272. {
  273. hr = E_FAIL;
  274. }
  275. }
  276. if(S_OK == hr)
  277. {
  278. grfDesiredStateBits = (grfStateBits & grfMask) |
  279. (statStgCurrent.grfStateBits & ~grfMask);
  280. // Call SetStateBits to change State Bits
  281. hr = pvcn->SetStateBits(grfStateBits, grfMask);
  282. DH_HRCHECK(hr, TEXT("VirtualCtrNode::SetStateBits")) ;
  283. }
  284. }
  285. }
  286. if(S_OK == hr)
  287. {
  288. // Get information about new state
  289. hr = pvcn->Stat(&statStgNew, STATFLAG_NONAME);
  290. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
  291. }
  292. // Verify the new State
  293. // Verify state bits
  294. if((S_OK == hr) && (TRUE == fStateBitsChanged))
  295. {
  296. if(statStgNew.grfStateBits != grfDesiredStateBits)
  297. {
  298. fPass = FALSE;
  299. DH_LOG((
  300. LOG_INFO,
  301. TEXT("State Bits not changed correctly.\n")));
  302. DH_LOG((
  303. LOG_INFO,
  304. TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
  305. statStgNew.grfStateBits,
  306. grfDesiredStateBits));
  307. }
  308. else
  309. {
  310. DH_LOG((
  311. LOG_INFO,
  312. TEXT("State Bits changed correctly.\n")));
  313. DH_LOG((
  314. LOG_INFO,
  315. TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
  316. statStgNew.grfStateBits,
  317. grfDesiredStateBits));
  318. }
  319. }
  320. // Verify CLSID
  321. if(S_OK == hr)
  322. {
  323. switch(cRandomClsid)
  324. {
  325. case 1:
  326. {
  327. if(!IsEqualCLSID(statStgNew.clsid, IID_IUnknown))
  328. {
  329. fPass = FALSE;
  330. DH_LOG((
  331. LOG_INFO,
  332. TEXT("SetClass didn't set CLSID IID_IUnknown.\n")));
  333. }
  334. else
  335. {
  336. DH_LOG((
  337. LOG_INFO,
  338. TEXT("SetClass set CLSID to IID_IUnknown.\n")));
  339. }
  340. break;
  341. }
  342. case 2:
  343. {
  344. if(!IsEqualCLSID(statStgNew.clsid, IID_IStorage))
  345. {
  346. fPass = FALSE;
  347. DH_LOG((
  348. LOG_INFO,
  349. TEXT("SetClass didn't set CLSID IID_IStorage.\n")));
  350. }
  351. else
  352. {
  353. DH_LOG((
  354. LOG_INFO,
  355. TEXT("SetClass set CLSID to IID_IStorage.\n")));
  356. }
  357. break;
  358. }
  359. case 3:
  360. {
  361. if(!IsEqualCLSID(statStgNew.clsid, IID_IStream))
  362. {
  363. fPass = FALSE;
  364. DH_LOG((
  365. LOG_INFO,
  366. TEXT("SetClass didn't set CLSID IID_IStream.\n")));
  367. }
  368. else
  369. {
  370. DH_LOG((
  371. LOG_INFO,
  372. TEXT("SetClass set CLSID to IID_IStream.\n")));
  373. }
  374. break;
  375. }
  376. }
  377. }
  378. // Modify hr if required based on fPass Value so that we can fall
  379. // out of this loop in error.
  380. if((S_OK == hr) && (FALSE == fPass))
  381. {
  382. hr = S_FALSE;
  383. }
  384. // Do random commit or revert operations and verify the State then
  385. if(S_OK == hr)
  386. {
  387. // Randomly either commit or Revert.
  388. if(0 == cRandomVar%2)
  389. {
  390. // Commit the changes
  391. DH_LOG((
  392. LOG_INFO,
  393. TEXT("Random Commit operation chosen.\n")));
  394. hr = pvcn->Commit(STGC_DEFAULT);
  395. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit")) ;
  396. if(S_OK == hr)
  397. {
  398. // Store the information in statStgCommited
  399. hr = pvcn->Stat(&statStgCommited, STATFLAG_NONAME);
  400. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
  401. }
  402. }
  403. else if(statStgNew.grfMode & STGM_TRANSACTED)
  404. {
  405. // Revert the changes
  406. DH_LOG((
  407. LOG_INFO,
  408. TEXT("Random Revert operation chosen.\n")));
  409. hr = pvcn->Revert();
  410. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Revert")) ;
  411. // Do Stat
  412. if(S_OK == hr)
  413. {
  414. hr = pvcn->Stat(&statStgNew, STATFLAG_NONAME);
  415. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
  416. }
  417. // Verify values after Revert
  418. if(S_OK == hr)
  419. {
  420. if(statStgNew.grfStateBits != statStgCommited.grfStateBits)
  421. {
  422. fPass = FALSE;
  423. DH_LOG((
  424. LOG_INFO,
  425. TEXT("State Bits after Revert not correct.\n")));
  426. DH_LOG((
  427. LOG_INFO,
  428. TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
  429. statStgNew.grfStateBits,
  430. statStgCommited.grfStateBits));
  431. }
  432. else
  433. {
  434. DH_LOG((
  435. LOG_INFO,
  436. TEXT("State Bits after Revert correct.\n")));
  437. }
  438. if(!IsEqualCLSID(statStgNew.clsid, statStgCommited.clsid))
  439. {
  440. fPass = FALSE;
  441. DH_LOG((
  442. LOG_INFO,
  443. TEXT("CLSID after Revert not correct.\n")));
  444. }
  445. else
  446. {
  447. DH_LOG((
  448. LOG_INFO,
  449. TEXT("CLSID after Revert correct.\n")));
  450. }
  451. }
  452. // Modify hr if reqd based on fPass Value so that we can fall
  453. // out of this loop in error.
  454. if((S_OK == hr) && (FALSE == fPass))
  455. {
  456. hr = S_FALSE;
  457. }
  458. }
  459. }
  460. // Reset the variables
  461. fStateBitsChanged = FALSE;
  462. cRandomClsid = 0;
  463. // Decrement counter
  464. cRandomVar--;
  465. }
  466. return hr;
  467. }
  468. //----------------------------------------------------------------------------
  469. //
  470. // Function: EnumerateDocFileInRandomChunks
  471. //
  472. // Synopsis: Enumerate DocFile in Random chunks and counts all the objects in
  473. // DocFile
  474. //
  475. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  476. // [pdgi] - Pointer to data generator object
  477. // [dwStgMode] - Mode for storage objects
  478. // [uNumObjs] - Max number of objs in DocFile to choose random
  479. // chunk number from
  480. // [pNumStg] - Out paramemter - Pointer to number of storages enum
  481. // [pNumStm] - Out paramemter - Pointer to number of streams enum
  482. //
  483. // Returns: HResult
  484. //
  485. // History: 23-Jul-1996 Narindk Created
  486. //
  487. //-----------------------------------------------------------------------------
  488. HRESULT EnumerateDocFileInRandomChunks(
  489. VirtualCtrNode *pvcn,
  490. DG_INTEGER *pdgi,
  491. DWORD dwStgMode,
  492. ULONG uNumObjs,
  493. ULONG *pNumStg,
  494. ULONG *pNumStm )
  495. {
  496. HRESULT hr = S_OK;
  497. ULONG cChildStg = 0;
  498. ULONG cChildStm = 0;
  499. USHORT usErr = 0;
  500. ULONG cRandomObjs = 0;
  501. VirtualCtrNode *pvcnTrav = NULL;
  502. LPENUMSTATSTG lpEnumStatStg = NULL;
  503. LPMALLOC pMalloc = NULL;
  504. ULONG celtFetched = 0;
  505. STATSTG *pstatStgEnum = NULL;
  506. ULONG ulRef = 0;
  507. ULONG counter = 0;
  508. LPTSTR ptszStatStgEnumName = NULL;
  509. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateDocFileInRandomChunks"));
  510. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  511. DH_VDATEPTROUT(pdgi, DG_INTEGER) ;
  512. DH_VDATEPTROUT(pNumStg, ULONG) ;
  513. DH_VDATEPTROUT(pNumStm, ULONG) ;
  514. DH_ASSERT(NULL != pvcn);
  515. DH_ASSERT(NULL != pdgi);
  516. DH_ASSERT(NULL != pNumStg);
  517. DH_ASSERT(NULL != pNumStm);
  518. if(S_OK == hr)
  519. {
  520. // Count the storage passed in.
  521. *pNumStg = 1;
  522. *pNumStm = 0;
  523. // Get enumerator
  524. hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
  525. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
  526. }
  527. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  528. if ( S_OK == hr )
  529. {
  530. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  531. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  532. }
  533. // Get random number of objects to be asked from through Next
  534. if(S_OK == hr)
  535. {
  536. // Generate random number
  537. usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
  538. if (DG_RC_SUCCESS != usErr)
  539. {
  540. hr = E_FAIL;
  541. }
  542. }
  543. // Allocate memory for STATSTG strcuture
  544. if(S_OK == hr)
  545. {
  546. pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
  547. if(NULL == pstatStgEnum)
  548. {
  549. hr = E_OUTOFMEMORY;
  550. }
  551. }
  552. // if successful to get enumerator, get the random element of the
  553. // enumeration sequence.
  554. if(S_OK == hr)
  555. {
  556. hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
  557. if(S_FALSE == hr)
  558. {
  559. hr = S_OK;
  560. }
  561. }
  562. while(0 < celtFetched)
  563. {
  564. for (counter = 0; counter < celtFetched; counter++)
  565. {
  566. if (STGTY_STORAGE == pstatStgEnum[counter].type)
  567. {
  568. hr = OleStringToTString(
  569. pstatStgEnum[counter].pwcsName,
  570. &ptszStatStgEnumName);
  571. // Find the respective VirtualCtrNode with the name and recurse
  572. // into it after opening it.
  573. if(S_OK == hr)
  574. {
  575. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  576. while((NULL != pvcnTrav) &&
  577. ( 0 != _tcscmp(
  578. ptszStatStgEnumName,
  579. pvcnTrav->GetVirtualCtrNodeName())))
  580. {
  581. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  582. }
  583. DH_ASSERT(NULL != pvcnTrav);
  584. if(NULL != pvcnTrav)
  585. {
  586. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  587. }
  588. }
  589. // Delete temp string
  590. if(NULL != ptszStatStgEnumName)
  591. {
  592. delete ptszStatStgEnumName;
  593. ptszStatStgEnumName = NULL;
  594. }
  595. if(S_OK == hr)
  596. {
  597. hr = EnumerateDocFileInRandomChunks(
  598. pvcnTrav,
  599. pdgi,
  600. dwStgMode,
  601. uNumObjs,
  602. &cChildStg,
  603. &cChildStm);
  604. }
  605. if(S_OK == hr)
  606. {
  607. hr = pvcnTrav->Close();
  608. }
  609. // Update number of nodes on basis of child nodes as found
  610. if(0 != cChildStg)
  611. {
  612. *pNumStg = *pNumStg + cChildStg;
  613. }
  614. if(0 != cChildStm)
  615. {
  616. *pNumStm = *pNumStm + cChildStm;
  617. }
  618. }
  619. else
  620. if (STGTY_STREAM == pstatStgEnum[counter].type)
  621. {
  622. (*pNumStm)++;
  623. }
  624. else
  625. // The element is neither IStorage nor IStream, report error.
  626. {
  627. hr = E_UNEXPECTED;
  628. }
  629. // Clean up
  630. if(NULL != pstatStgEnum[counter].pwcsName)
  631. {
  632. pMalloc->Free(pstatStgEnum[counter].pwcsName);
  633. pstatStgEnum[counter].pwcsName = NULL;
  634. }
  635. // Break out of loop in error
  636. if(S_OK != hr)
  637. {
  638. break;
  639. }
  640. }
  641. // Get the next random elements from the enumeration sequence
  642. if(S_OK == hr)
  643. {
  644. // Generate random number.
  645. usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
  646. if (DG_RC_SUCCESS != usErr)
  647. {
  648. hr = E_FAIL;
  649. }
  650. }
  651. if (NULL != pstatStgEnum)
  652. {
  653. delete [] pstatStgEnum;
  654. pstatStgEnum = NULL;
  655. }
  656. if(S_OK == hr)
  657. {
  658. pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
  659. if(NULL == pstatStgEnum)
  660. {
  661. hr = E_OUTOFMEMORY;
  662. }
  663. }
  664. if(S_OK == hr)
  665. {
  666. hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
  667. if(S_FALSE == hr)
  668. {
  669. hr = S_OK;
  670. }
  671. }
  672. // Reinitialize the variables
  673. cChildStg = 0;
  674. cChildStm = 0;
  675. }
  676. // Clean up
  677. if (NULL != pstatStgEnum)
  678. {
  679. delete [] pstatStgEnum;
  680. pstatStgEnum = NULL;
  681. }
  682. if (NULL != lpEnumStatStg)
  683. {
  684. ulRef = lpEnumStatStg->Release();
  685. DH_ASSERT(NULL == ulRef);
  686. lpEnumStatStg = NULL;
  687. }
  688. if(NULL != pMalloc)
  689. {
  690. pMalloc->Release();
  691. pMalloc = NULL;
  692. }
  693. return hr;
  694. }
  695. //----------------------------------------------------------------------------
  696. //
  697. // Function: CompareSTATSTG
  698. //
  699. // Synopsis: Compares contents of two STATSTG structs
  700. //
  701. // Arguments: [sstg1] - first STATSTG struct to be compared
  702. // [sstg2] - second STATSTG struct to be compared
  703. //
  704. // Returns: TRUE if storage buffers are the same; FALSE otherwise.
  705. //
  706. // History: 24-Jul-1996 Narindk Enhanced
  707. //
  708. //-----------------------------------------------------------------------------
  709. BOOL CompareSTATSTG(STATSTG sstg1, STATSTG sstg2)
  710. {
  711. HRESULT hr = S_OK;
  712. LPTSTR ptszStatStg1Name = NULL;
  713. LPTSTR ptszStatStg2Name = NULL;
  714. BOOL fEqual = FALSE;
  715. hr = OleStringToTString(sstg1.pwcsName, &ptszStatStg1Name);
  716. if(S_OK == hr)
  717. {
  718. hr = OleStringToTString(sstg2.pwcsName, &ptszStatStg2Name);
  719. }
  720. if(S_OK == hr)
  721. {
  722. fEqual=((!(_tcscmp(ptszStatStg1Name, ptszStatStg2Name)) &&
  723. (sstg1.type == sstg2.type) &&
  724. (ULIGetLow(sstg1.cbSize) == ULIGetLow(sstg2.cbSize)) &&
  725. (sstg1.mtime.dwLowDateTime == sstg2.mtime.dwLowDateTime) &&
  726. (sstg1.mtime.dwHighDateTime == sstg2.mtime.dwHighDateTime) &&
  727. (sstg1.ctime.dwLowDateTime == sstg2.ctime.dwLowDateTime) &&
  728. (sstg1.ctime.dwHighDateTime == sstg2.ctime.dwHighDateTime) &&
  729. (sstg1.atime.dwLowDateTime == sstg2.atime.dwLowDateTime) &&
  730. (sstg1.atime.dwHighDateTime == sstg2.atime.dwHighDateTime) &&
  731. (sstg1.grfMode == sstg2.grfMode) &&
  732. (sstg1.grfLocksSupported == sstg2.grfLocksSupported) &&
  733. (sstg1.grfStateBits == sstg2.grfStateBits) &&
  734. IsEqualCLSID(sstg1.clsid, sstg2.clsid)));
  735. }
  736. DH_ASSERT(S_OK == hr);
  737. // Delete temp strings
  738. if(NULL != ptszStatStg1Name)
  739. {
  740. delete ptszStatStg1Name;
  741. ptszStatStg1Name = NULL;
  742. }
  743. if(NULL != ptszStatStg2Name)
  744. {
  745. delete ptszStatStg2Name;
  746. ptszStatStg1Name = NULL;
  747. }
  748. return fEqual;
  749. }
  750. //----------------------------------------------------------------------------
  751. //
  752. // Function: EnumerateDocFileAndVerifyEnumCloneResetSkipNext
  753. //
  754. // Synopsis: Enumerate DocFile all at one level, Gets a clone of enumerator,
  755. // Uses Clone/Reset/Skip/Next method to get a Storage and verify that
  756. // with one obtained from original enumerator and counts all the
  757. // objects ath the level. If object is a storage, it is recursed
  758. // into and operation repeated.
  759. //
  760. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  761. // [dwStgMode] - Mode for storage objects
  762. // [uNumObjs] - Max number of objs in DocFile to choose random
  763. // chunk number from
  764. // [pNumStg] - Out paramemter - Pointer to number of storages enum
  765. // [pNumStm] - Out paramemter - Pointer to number of streams enum
  766. //
  767. // Returns: HResult
  768. //
  769. // History: 24-Jul-1996 Narindk Created
  770. //
  771. //-----------------------------------------------------------------------------
  772. HRESULT EnumerateDocFileAndVerifyEnumCloneResetSkipNext(
  773. VirtualCtrNode *pvcn,
  774. DWORD dwStgMode,
  775. ULONG uNumObjs,
  776. ULONG *pNumStg,
  777. ULONG *pNumStm )
  778. {
  779. HRESULT hr = S_OK;
  780. ULONG cChildStg = 0;
  781. ULONG cChildStm = 0;
  782. VirtualCtrNode *pvcnTrav = NULL;
  783. LPENUMSTATSTG lpEnumStatStg = NULL;
  784. LPENUMSTATSTG lpEnumStatStgClone = NULL;
  785. LPMALLOC pMalloc = NULL;
  786. ULONG celtFetched = 0;
  787. STATSTG *pstatStgEnum = NULL;
  788. ULONG ulRef = 0;
  789. LPTSTR ptszStatStgEnumName = NULL;
  790. BOOL fPass = FALSE;
  791. STATSTG statStgEnumClone;
  792. DH_FUNCENTRY(
  793. &hr,
  794. DH_LVL_DFLIB,
  795. _TEXT("EnumerateDocFileAndVerifyEnumCloneResetSkipNext"));
  796. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  797. DH_VDATEPTROUT(pNumStg, ULONG) ;
  798. DH_VDATEPTROUT(pNumStm, ULONG) ;
  799. DH_ASSERT(NULL != pvcn);
  800. DH_ASSERT(NULL != pNumStg);
  801. DH_ASSERT(NULL != pNumStm);
  802. if(S_OK == hr)
  803. {
  804. // Count the storage passed in.
  805. *pNumStg = 1;
  806. *pNumStm = 0;
  807. // Get enumerator
  808. hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
  809. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
  810. }
  811. // Make a clone of the enumerator
  812. if(S_OK == hr)
  813. {
  814. hr = lpEnumStatStg->Clone(&lpEnumStatStgClone);
  815. DH_ASSERT((S_OK == hr) && (NULL != lpEnumStatStgClone));
  816. }
  817. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  818. if ( S_OK == hr )
  819. {
  820. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  821. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  822. }
  823. // Allocate memory for STATSTG strcuture
  824. if(S_OK == hr)
  825. {
  826. // We are allocating memory for more number of STATSTG objects than
  827. // what might be required, but is safer.
  828. pstatStgEnum = (STATSTG *) new STATSTG [uNumObjs];
  829. if(NULL == pstatStgEnum)
  830. {
  831. hr = E_OUTOFMEMORY;
  832. }
  833. }
  834. // if successful to get enumerator, get all the element at same level of
  835. // the enumeration sequence.
  836. if(S_OK == hr)
  837. {
  838. hr = lpEnumStatStg->Next(uNumObjs, pstatStgEnum, &celtFetched);
  839. if(S_FALSE == hr)
  840. {
  841. hr = S_OK;
  842. }
  843. }
  844. while((0 < celtFetched--) && (S_OK == hr))
  845. {
  846. // for each element, ->Skip() from beginning of enumeration
  847. // sequence (of clone) and check that it is the same as
  848. // was returned with the original ->Next()
  849. // The Reset call always returns S_OK, so need to check hr
  850. hr = lpEnumStatStgClone->Reset();
  851. DH_ASSERT(S_OK == hr);
  852. // Skip celtFetched elements with Clone enumerator
  853. hr = lpEnumStatStgClone->Skip(celtFetched);
  854. DH_ASSERT(S_OK == hr);
  855. // Retrieve next element from this clone enumerator
  856. if(S_OK == hr)
  857. {
  858. hr = lpEnumStatStgClone->Next(1, &statStgEnumClone, NULL);
  859. DH_ASSERT(S_OK == hr);
  860. }
  861. if(S_OK == hr)
  862. {
  863. // Compare the STATSTG structures of one that is retrieved through
  864. // Clone and the one returned from original enumerator
  865. fPass = CompareSTATSTG(
  866. pstatStgEnum[celtFetched],
  867. statStgEnumClone);
  868. }
  869. if(FALSE == fPass)
  870. {
  871. hr = S_FALSE;
  872. DH_LOG((LOG_INFO, TEXT("The two STATSTG's don't match\n")));
  873. }
  874. else
  875. {
  876. DH_LOG((
  877. LOG_INFO,
  878. TEXT("IEnum org and Clone enumerator: two STATSTG's match\n")));
  879. }
  880. if(S_OK == hr)
  881. {
  882. if (STGTY_STORAGE == pstatStgEnum[celtFetched].type)
  883. {
  884. hr = OleStringToTString(
  885. pstatStgEnum[celtFetched].pwcsName,
  886. &ptszStatStgEnumName);
  887. // Find the respective VirtualCtrNode with the name and recurse
  888. // into it after opening it.
  889. if(S_OK == hr)
  890. {
  891. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  892. while((NULL != pvcnTrav) &&
  893. ( 0 != _tcscmp(
  894. ptszStatStgEnumName,
  895. pvcnTrav->GetVirtualCtrNodeName())))
  896. {
  897. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  898. }
  899. DH_ASSERT(NULL != pvcnTrav);
  900. if(NULL != pvcnTrav)
  901. {
  902. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  903. }
  904. }
  905. // Delete temp string
  906. if(NULL != ptszStatStgEnumName)
  907. {
  908. delete ptszStatStgEnumName;
  909. ptszStatStgEnumName = NULL;
  910. }
  911. if(S_OK == hr)
  912. {
  913. hr = EnumerateDocFileAndVerifyEnumCloneResetSkipNext(
  914. pvcnTrav,
  915. dwStgMode,
  916. uNumObjs,
  917. &cChildStg,
  918. &cChildStm);
  919. }
  920. if(S_OK == hr)
  921. {
  922. hr = pvcnTrav->Close();
  923. }
  924. // Update number of nodes on basis of child nodes as found
  925. if(0 != cChildStg)
  926. {
  927. *pNumStg = *pNumStg + cChildStg;
  928. }
  929. if(0 != cChildStm)
  930. {
  931. *pNumStm = *pNumStm + cChildStm;
  932. }
  933. }
  934. else
  935. if (STGTY_STREAM == pstatStgEnum[celtFetched].type)
  936. {
  937. (*pNumStm)++;
  938. }
  939. else
  940. // The element is neither IStorage nor IStream, report error.
  941. {
  942. hr = E_UNEXPECTED;
  943. }
  944. }
  945. // Clean up
  946. if(NULL != pstatStgEnum[celtFetched].pwcsName)
  947. {
  948. pMalloc->Free(pstatStgEnum[celtFetched].pwcsName);
  949. pstatStgEnum[celtFetched].pwcsName = NULL;
  950. }
  951. if(NULL != statStgEnumClone.pwcsName)
  952. {
  953. pMalloc->Free(statStgEnumClone.pwcsName);
  954. statStgEnumClone.pwcsName = NULL;
  955. }
  956. }
  957. // Clean up
  958. if (NULL != pstatStgEnum)
  959. {
  960. delete [] pstatStgEnum;
  961. pstatStgEnum = NULL;
  962. }
  963. if (NULL != lpEnumStatStg)
  964. {
  965. ulRef = lpEnumStatStg->Release();
  966. DH_ASSERT(NULL == ulRef);
  967. lpEnumStatStg = NULL;
  968. }
  969. if (NULL != lpEnumStatStgClone)
  970. {
  971. ulRef = lpEnumStatStgClone->Release();
  972. DH_ASSERT(NULL == ulRef);
  973. lpEnumStatStgClone = NULL;
  974. }
  975. if(NULL != pMalloc)
  976. {
  977. pMalloc->Release();
  978. pMalloc = NULL;
  979. }
  980. return hr;
  981. }
  982. //----------------------------------------------------------------------------
  983. //
  984. // Function: ModifyDocFile
  985. //
  986. // Synopsis: Enumerate DocFile and randomly recurses into child storages, or
  987. // randomly destroys or renames elements.
  988. //
  989. // Arguments: [pVirtualDF] - Pointer to VirtualDF tree
  990. // [pvcn] - Pointer to VirtualCtrNode
  991. // [pdgi] - Pointer to Data Integer object
  992. // [pdgu] - Pinter to Data Unicode objext
  993. // [fCommitRoot] - Bool to commit a root DocFile storage or not
  994. //
  995. // Returns: HResult
  996. //
  997. // History: 25-Jul-1996 Narindk Created
  998. //
  999. //----------------------------------------------------------------------------
  1000. HRESULT ModifyDocFile(
  1001. VirtualDF *pVirtualDF,
  1002. VirtualCtrNode *pvcn,
  1003. DG_INTEGER *pdgi,
  1004. DG_STRING *pdgu,
  1005. DWORD dwStgMode,
  1006. BOOL fCommitRoot)
  1007. {
  1008. HRESULT hr = S_OK;
  1009. VirtualCtrNode *pvcnTrav = NULL;
  1010. VirtualStmNode *pvsnTrav = NULL;
  1011. LPENUMSTATSTG lpEnumStatStg = NULL;
  1012. LPMALLOC pMalloc = NULL;
  1013. ULONG celtFetched = 0;
  1014. ULONG ulRef = 0;
  1015. USHORT usErr = 0;
  1016. LPTSTR ptszStatStgName = NULL;
  1017. LPTSTR ptszNewName = NULL;
  1018. UINT cRandVal0 = 0;
  1019. UINT cRandVal1 = 0;
  1020. UINT cRandRange0 = 0;
  1021. UINT cRandRange1 = 1;
  1022. UINT cRandRange2 = 2;
  1023. STATSTG statStg;
  1024. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ModifyDocFile"));
  1025. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1026. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  1027. DH_VDATEPTRIN(pdgu, DG_STRING) ;
  1028. DH_ASSERT(NULL != pvcn);
  1029. DH_ASSERT(NULL != pdgi);
  1030. DH_ASSERT(NULL != pdgu);
  1031. if(S_OK == hr)
  1032. {
  1033. // Get enumerator
  1034. hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
  1035. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
  1036. }
  1037. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  1038. if ( S_OK == hr )
  1039. {
  1040. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  1041. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  1042. }
  1043. while((S_OK == lpEnumStatStg->Next(1, &statStg, &celtFetched)) &&
  1044. (S_OK == hr))
  1045. {
  1046. hr = OleStringToTString(statStg.pwcsName, &ptszStatStgName);
  1047. // If the element is an IStorage, randmly either open this and make a
  1048. // recursive call to ModifyDocFile function or randomly choose to
  1049. // either rename or destory this element.
  1050. if ((STGTY_STORAGE == statStg.type) && (S_OK == hr))
  1051. {
  1052. // Find the respective VirtualCtrNode with the name and recurse
  1053. // into it after opening it.
  1054. if(S_OK == hr)
  1055. {
  1056. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  1057. while((NULL != pvcnTrav) &&
  1058. ( 0 != _tcscmp(
  1059. ptszStatStgName,
  1060. pvcnTrav->GetVirtualCtrNodeName())))
  1061. {
  1062. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  1063. }
  1064. DH_ASSERT(NULL != pvcnTrav);
  1065. }
  1066. // Cloose random number
  1067. if(S_OK == hr)
  1068. {
  1069. usErr = pdgi->Generate(&cRandVal0, cRandRange0, cRandRange2);
  1070. if (DG_RC_SUCCESS != usErr)
  1071. {
  1072. hr = E_FAIL;
  1073. }
  1074. }
  1075. // Randomly choose either to open/recurse and Modify the Storage
  1076. // or choose to either randomly rename or destory the storage
  1077. if((S_OK == hr) && (0 == cRandVal0))
  1078. {
  1079. if(NULL != pvcnTrav)
  1080. {
  1081. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  1082. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open")) ;
  1083. }
  1084. // Call ModifyDocFile recursively on this node
  1085. if(S_OK == hr)
  1086. {
  1087. hr = ModifyDocFile(
  1088. pVirtualDF,
  1089. pvcnTrav,
  1090. pdgi,
  1091. pdgu,
  1092. dwStgMode,
  1093. fCommitRoot);
  1094. }
  1095. // Close this storage
  1096. if(S_OK == hr)
  1097. {
  1098. hr = pvcnTrav->Close();
  1099. }
  1100. }
  1101. if((S_OK == hr) && (0 != cRandVal0))
  1102. {
  1103. // choose random number either to rename or destory this
  1104. // element
  1105. if(S_OK == hr)
  1106. {
  1107. usErr = pdgi->Generate(&cRandVal1,cRandRange1,cRandRange2);
  1108. if (DG_RC_SUCCESS != usErr)
  1109. {
  1110. hr = E_FAIL;
  1111. }
  1112. }
  1113. if(S_OK == hr)
  1114. {
  1115. switch(cRandVal1)
  1116. {
  1117. case 1:
  1118. {
  1119. hr = DestroyStorage(pVirtualDF, pvcnTrav);
  1120. DH_HRCHECK(hr, TEXT("DestoryStorage")) ;
  1121. break;
  1122. }
  1123. case 2:
  1124. {
  1125. // Generate random new name
  1126. hr = GenerateRandomName(pdgu,
  1127. MINLENGTH,
  1128. MAXLENGTH,
  1129. &ptszNewName);
  1130. if(S_OK == hr)
  1131. {
  1132. hr = pvcnTrav->Rename(ptszNewName);
  1133. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Rename")) ;
  1134. }
  1135. break;
  1136. }
  1137. }
  1138. }
  1139. }
  1140. }
  1141. // If the element is an IStream, randomly choose to either rename
  1142. // or destory this element.
  1143. else if ((STGTY_STREAM == statStg.type) && (S_OK == hr))
  1144. {
  1145. // Find the respective VirtualStmNode with the name
  1146. if(S_OK == hr)
  1147. {
  1148. pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
  1149. while((NULL != pvsnTrav) &&
  1150. ( 0 != _tcscmp(
  1151. ptszStatStgName,
  1152. pvsnTrav->GetVirtualStmNodeName())))
  1153. {
  1154. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
  1155. }
  1156. DH_ASSERT(NULL != pvsnTrav);
  1157. }
  1158. // choose random number either to rename or destory this element
  1159. if(S_OK == hr)
  1160. {
  1161. usErr = pdgi->Generate(&cRandVal1, cRandRange1, cRandRange2);
  1162. if (DG_RC_SUCCESS != usErr)
  1163. {
  1164. hr = E_FAIL;
  1165. }
  1166. }
  1167. if(S_OK == hr)
  1168. {
  1169. switch(cRandVal1)
  1170. {
  1171. case 1:
  1172. {
  1173. hr = DestroyStream(pVirtualDF, pvsnTrav);
  1174. DH_HRCHECK(hr, TEXT("DestroyStream")) ;
  1175. break;
  1176. }
  1177. case 2:
  1178. {
  1179. // Generate random new name
  1180. hr = GenerateRandomName(pdgu,
  1181. MINLENGTH,
  1182. MAXLENGTH,
  1183. &ptszNewName);
  1184. if(S_OK == hr)
  1185. {
  1186. hr = pvsnTrav->Rename(ptszNewName);
  1187. DH_HRCHECK(hr, TEXT("VirtualStmNode::Rename")) ;
  1188. }
  1189. break;
  1190. }
  1191. }
  1192. }
  1193. }
  1194. // Clean up
  1195. if(NULL != statStg.pwcsName)
  1196. {
  1197. pMalloc->Free(statStg.pwcsName);
  1198. statStg.pwcsName = NULL;
  1199. }
  1200. if(NULL != ptszStatStgName)
  1201. {
  1202. delete ptszStatStgName;
  1203. ptszStatStgName = NULL;
  1204. }
  1205. if(NULL != ptszNewName)
  1206. {
  1207. delete ptszNewName;
  1208. ptszNewName = NULL;
  1209. }
  1210. }
  1211. // Commit the passed in storage as case might be
  1212. if((S_OK == hr) &&
  1213. ((pvcn != pVirtualDF->GetVirtualDFRoot()) || (TRUE == fCommitRoot)))
  1214. {
  1215. hr = pvcn->Commit(STGC_DEFAULT);
  1216. }
  1217. // Clean up
  1218. if (NULL != lpEnumStatStg)
  1219. {
  1220. ulRef = lpEnumStatStg->Release();
  1221. DH_ASSERT(0 == ulRef);
  1222. lpEnumStatStg = NULL;
  1223. }
  1224. if(NULL != pMalloc)
  1225. {
  1226. pMalloc->Release();
  1227. pMalloc = NULL;
  1228. }
  1229. return hr;
  1230. }
  1231. //----------------------------------------------------------------------------
  1232. //
  1233. // Function: EnumerateAndWalkDocFile
  1234. //
  1235. // Synopsis: Enumerate /walks DocFile by either randomly skipping random
  1236. // number of elements or getting random number of elements, recursing
  1237. // if a child storage is found.
  1238. //
  1239. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  1240. // [pdgi] - Pointer to data generator object
  1241. // [dwStgMode] - Mode for storage objects
  1242. // [uNumObjs] - Max number of objs in DocFile to choose random
  1243. // chunk number from
  1244. //
  1245. // Returns: HResult
  1246. //
  1247. // History: 29-Jul-1996 Narindk Created
  1248. //
  1249. // Notes: This doesn't provide any form of verification, but checks for any
  1250. // unexpected errors/faults from ole while walking the docfile tree.
  1251. //-----------------------------------------------------------------------------
  1252. HRESULT EnumerateAndWalkDocFile(
  1253. VirtualCtrNode *pvcn,
  1254. DG_INTEGER *pdgi,
  1255. DWORD dwStgMode,
  1256. ULONG uNumObjs)
  1257. {
  1258. HRESULT hr = S_OK;
  1259. USHORT usErr = 0;
  1260. ULONG cRandomObjs = 0;
  1261. VirtualCtrNode *pvcnTrav = NULL;
  1262. LPENUMSTATSTG lpEnumStatStg = NULL;
  1263. LPMALLOC pMalloc = NULL;
  1264. ULONG celtFetched = 0;
  1265. STATSTG *pstatStgEnum = NULL;
  1266. ULONG ulRef = 0;
  1267. ULONG counter = 0;
  1268. LPTSTR ptszStatStgEnumName = NULL;
  1269. UINT cWhichOp = 0;
  1270. UINT cRandomOpMin = 1;
  1271. UINT cRandomOpMax = 3;
  1272. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateAndWalkDocFile"));
  1273. DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
  1274. DH_VDATEPTROUT(pdgi, DG_INTEGER) ;
  1275. DH_ASSERT(NULL != pvcn);
  1276. DH_ASSERT(NULL != pdgi);
  1277. if(S_OK == hr)
  1278. {
  1279. // Get enumerator
  1280. hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
  1281. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
  1282. }
  1283. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  1284. if ( S_OK == hr )
  1285. {
  1286. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  1287. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  1288. }
  1289. // Get random number of objects to be asked from through Next or Skip
  1290. if(S_OK == hr)
  1291. {
  1292. // Generate random number
  1293. usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
  1294. if (DG_RC_SUCCESS != usErr)
  1295. {
  1296. hr = E_FAIL;
  1297. }
  1298. }
  1299. // Get random number to determine whether to do skip or next operation.
  1300. // 67% Next operation would be done and 33% skip would be done.
  1301. if(S_OK == hr)
  1302. {
  1303. // Generate random number
  1304. usErr = pdgi->Generate(&cWhichOp, cRandomOpMin, cRandomOpMax);
  1305. if (DG_RC_SUCCESS != usErr)
  1306. {
  1307. hr = E_FAIL;
  1308. }
  1309. }
  1310. // Allocate memory for STATSTG strcuture
  1311. if(S_OK == hr)
  1312. {
  1313. pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
  1314. if(NULL == pstatStgEnum)
  1315. {
  1316. hr = E_OUTOFMEMORY;
  1317. }
  1318. }
  1319. // if successful to get enumerator, get the random element of the
  1320. // enumeration sequence. 33% do skip and 67% do Next.
  1321. if(S_OK == hr)
  1322. {
  1323. if(cRandomOpMin == cWhichOp)
  1324. {
  1325. hr = lpEnumStatStg->Skip(cRandomObjs);
  1326. if(S_OK == hr)
  1327. {
  1328. hr = lpEnumStatStg->Next(1, pstatStgEnum, &celtFetched);
  1329. }
  1330. }
  1331. else
  1332. {
  1333. hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
  1334. }
  1335. if(S_FALSE == hr)
  1336. {
  1337. hr = S_OK;
  1338. }
  1339. }
  1340. while(0 < celtFetched)
  1341. {
  1342. for (counter = 0; counter < celtFetched; counter++)
  1343. {
  1344. if (STGTY_STORAGE == pstatStgEnum[counter].type)
  1345. {
  1346. hr = OleStringToTString(
  1347. pstatStgEnum[counter].pwcsName,
  1348. &ptszStatStgEnumName);
  1349. // Find the respective VirtualCtrNode with the name and recurse
  1350. // into it after opening it.
  1351. if(S_OK == hr)
  1352. {
  1353. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  1354. while((NULL != pvcnTrav) &&
  1355. ( 0 != _tcscmp(
  1356. ptszStatStgEnumName,
  1357. pvcnTrav->GetVirtualCtrNodeName())))
  1358. {
  1359. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  1360. }
  1361. DH_ASSERT(NULL != pvcnTrav);
  1362. if(NULL != pvcnTrav)
  1363. {
  1364. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  1365. }
  1366. }
  1367. // Delete temp string
  1368. if(NULL != ptszStatStgEnumName)
  1369. {
  1370. delete ptszStatStgEnumName;
  1371. ptszStatStgEnumName = NULL;
  1372. }
  1373. if(S_OK == hr)
  1374. {
  1375. hr = EnumerateAndWalkDocFile(
  1376. pvcnTrav,
  1377. pdgi,
  1378. dwStgMode,
  1379. uNumObjs);
  1380. }
  1381. if(S_OK == hr)
  1382. {
  1383. hr = pvcnTrav->Close();
  1384. }
  1385. }
  1386. // Clean up
  1387. if(NULL != pstatStgEnum[counter].pwcsName)
  1388. {
  1389. pMalloc->Free(pstatStgEnum[counter].pwcsName);
  1390. pstatStgEnum[counter].pwcsName = NULL;
  1391. }
  1392. // Break out of loop in error
  1393. if(S_OK != hr)
  1394. {
  1395. break;
  1396. }
  1397. }
  1398. // Reset the variables
  1399. cWhichOp = 0;
  1400. cRandomObjs = 0;
  1401. celtFetched = 0;
  1402. // Get random number to determine whether to do skip or next operation.
  1403. // 67% Next operation would be done and 33% skip would be done.
  1404. if(S_OK == hr)
  1405. {
  1406. // Generate random number
  1407. usErr = pdgi->Generate(&cWhichOp, cRandomOpMin, cRandomOpMax);
  1408. if (DG_RC_SUCCESS != usErr)
  1409. {
  1410. hr = E_FAIL;
  1411. }
  1412. }
  1413. // Get the random number of elements from the enumeration sequence to
  1414. // skip or get.
  1415. if(S_OK == hr)
  1416. {
  1417. // Generate random number.
  1418. usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
  1419. if (DG_RC_SUCCESS != usErr)
  1420. {
  1421. hr = E_FAIL;
  1422. }
  1423. }
  1424. if (NULL != pstatStgEnum)
  1425. {
  1426. delete [] pstatStgEnum;
  1427. pstatStgEnum = NULL;
  1428. }
  1429. if(S_OK == hr)
  1430. {
  1431. pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
  1432. if(NULL == pstatStgEnum)
  1433. {
  1434. hr = E_OUTOFMEMORY;
  1435. }
  1436. }
  1437. if(S_OK == hr)
  1438. {
  1439. if(cRandomOpMin == cWhichOp)
  1440. {
  1441. hr = lpEnumStatStg->Skip(cRandomObjs);
  1442. if(S_OK == hr)
  1443. {
  1444. hr = lpEnumStatStg->Next(1, pstatStgEnum, &celtFetched);
  1445. }
  1446. }
  1447. else
  1448. {
  1449. hr = lpEnumStatStg->Next(cRandomObjs,pstatStgEnum,&celtFetched);
  1450. }
  1451. if(S_FALSE == hr)
  1452. {
  1453. hr = S_OK;
  1454. }
  1455. }
  1456. }
  1457. // Clean up
  1458. if (NULL != pstatStgEnum)
  1459. {
  1460. delete [] pstatStgEnum;
  1461. pstatStgEnum = NULL;
  1462. }
  1463. if (NULL != lpEnumStatStg)
  1464. {
  1465. ulRef = lpEnumStatStg->Release();
  1466. DH_ASSERT(NULL == ulRef);
  1467. lpEnumStatStg = NULL;
  1468. }
  1469. if(NULL != pMalloc)
  1470. {
  1471. pMalloc->Release();
  1472. pMalloc = NULL;
  1473. }
  1474. return hr;
  1475. }
  1476. //----------------------------------------------------------------------------
  1477. //
  1478. // Function: CreateNewObject
  1479. //
  1480. // Synopsis: Randomly creates a new storage or stream object in a DocFile
  1481. //
  1482. // Arguments: [pVirtualDF] - Pointer to VirtualDF tree
  1483. // [pvcn] - Pointer to VirtualCtrNode
  1484. // [dwStgMode] - Used for random creation of storage object
  1485. // [pdgi] - Pointer to data generator integer object
  1486. // [pdgu] - Pointer to data generator unicode object
  1487. //
  1488. // Returns: HResult
  1489. //
  1490. // History: 29-Jul-1996 Narindk Created
  1491. //
  1492. //----------------------------------------------------------------------------
  1493. HRESULT CreateNewObject(
  1494. LPSTORAGE pIStorage,
  1495. DWORD dwStgMode,
  1496. DG_INTEGER *pdgi,
  1497. DG_STRING *pdgu)
  1498. {
  1499. HRESULT hr = S_OK;
  1500. USHORT usErr = 0;
  1501. UINT cRandom = 0;
  1502. LPTSTR ptszNewName = NULL;
  1503. LPTSTR ptszNewData = NULL;
  1504. LPOLESTR poszNewName = NULL;
  1505. LPOLESTR poszNewData = NULL;
  1506. ULONG cb = 0;
  1507. ULONG culWritten = 0;
  1508. LPSTORAGE pIStorageNew = NULL;
  1509. LPSTREAM pIStreamNew = NULL;
  1510. ULONG ulRef = 0;
  1511. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CreateNewObject"));
  1512. DH_VDATEPTRIN(pIStorage, IStorage) ;
  1513. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  1514. DH_VDATEPTRIN(pdgu, DG_STRING) ;
  1515. DH_ASSERT(NULL != pIStorage);
  1516. DH_ASSERT(NULL != pdgi);
  1517. DH_ASSERT(NULL != pdgu);
  1518. // Pick up a random number. 33% chance to generate a new IStorage element,
  1519. // and 67% chance to generate a new IStream element.
  1520. usErr = pdgi->Generate(&cRandom, 0, 2);
  1521. if (DG_RC_SUCCESS != usErr)
  1522. {
  1523. hr = E_FAIL;
  1524. }
  1525. // flatfile only: storages are not allowed
  1526. if(StorageIsFlat())
  1527. {
  1528. cRandom = 2; // force it to create only streams
  1529. }
  1530. if(S_OK == hr)
  1531. {
  1532. hr = GenerateRandomName(pdgu, MINLENGTH, MAXLENGTH, &ptszNewName);
  1533. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  1534. }
  1535. if(S_OK == hr)
  1536. {
  1537. // Convert ptcsName to OLECHAR
  1538. hr = TStringToOleString(ptszNewName, &poszNewName);
  1539. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1540. }
  1541. if(S_OK == hr)
  1542. {
  1543. if(0 == cRandom)
  1544. {
  1545. // Create a new storage
  1546. hr = pIStorage->CreateStorage(
  1547. poszNewName,
  1548. dwStgMode | STGM_CREATE,
  1549. 0,
  1550. 0,
  1551. &pIStorageNew);
  1552. DH_HRCHECK(hr, TEXT("IStorage::CreateStorage")) ;
  1553. if(S_OK == hr)
  1554. {
  1555. // Close the new storage
  1556. ulRef = pIStorageNew->Release();
  1557. DH_ASSERT(0 == ulRef);
  1558. pIStorageNew = NULL;
  1559. }
  1560. }
  1561. else
  1562. {
  1563. usErr = pdgi->Generate(&cb, 1, SHRT_MAX);
  1564. if (DG_RC_SUCCESS != usErr)
  1565. {
  1566. hr = E_FAIL;
  1567. }
  1568. if(S_OK == hr)
  1569. {
  1570. // Create a new stream
  1571. hr = pIStorage->CreateStream(
  1572. poszNewName,
  1573. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  1574. 0,
  1575. 0,
  1576. &pIStreamNew);
  1577. DH_HRCHECK(hr, TEXT("IStorage::CreateStream")) ;
  1578. }
  1579. // Write into stream
  1580. if(S_OK == hr)
  1581. {
  1582. hr = GenerateRandomName(pdgu, cb, cb, &ptszNewData);
  1583. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  1584. }
  1585. if(S_OK == hr)
  1586. {
  1587. // Convert ptcsName to OLECHAR
  1588. hr = TStringToOleString(ptszNewData, &poszNewData);
  1589. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1590. }
  1591. if(S_OK == hr)
  1592. {
  1593. hr = pIStreamNew->Write(poszNewData, cb, &culWritten);
  1594. DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ;
  1595. }
  1596. // Close the stream
  1597. if(S_OK == hr)
  1598. {
  1599. ulRef = pIStreamNew->Release();
  1600. DH_ASSERT(0 == ulRef);
  1601. pIStreamNew = NULL;
  1602. }
  1603. }
  1604. }
  1605. // Clean up
  1606. if(NULL != ptszNewName)
  1607. {
  1608. delete ptszNewName;
  1609. ptszNewName = NULL;
  1610. }
  1611. if(NULL != poszNewName)
  1612. {
  1613. delete poszNewName;
  1614. poszNewName = NULL;
  1615. }
  1616. if(NULL != ptszNewData)
  1617. {
  1618. delete ptszNewData;
  1619. ptszNewData = NULL;
  1620. }
  1621. if(NULL != poszNewName)
  1622. {
  1623. delete poszNewName;
  1624. poszNewName = NULL;
  1625. }
  1626. return hr;
  1627. }
  1628. //----------------------------------------------------------------------------
  1629. //
  1630. // Function: ChangeStreamData
  1631. //
  1632. // Synopsis: Randomly changes size or data of an IStream object in a DocFile
  1633. //
  1634. // Arguments: [pIStorage] - Pointer to parent storage
  1635. // [pStatStg] - Pointer to STATSTG structure
  1636. // [pdgi] - Pointer to data generator integer object
  1637. // [pdgu] - Pointer to data generator unicode object
  1638. //
  1639. // Returns: HResult
  1640. //
  1641. // History: 29-Jul-1996 Narindk Created
  1642. //
  1643. //----------------------------------------------------------------------------
  1644. HRESULT ChangeStreamData(
  1645. LPSTORAGE pIStorage,
  1646. STATSTG *pStatStg,
  1647. DG_INTEGER *pdgi,
  1648. DG_STRING *pdgu)
  1649. {
  1650. HRESULT hr = S_OK;
  1651. USHORT usErr = 0;
  1652. LPTSTR ptszName = NULL;
  1653. LPOLESTR poszName = NULL;
  1654. LPTSTR ptszNewData = NULL;
  1655. LPOLESTR poszNewData = NULL;
  1656. ULONG cb = 0;
  1657. ULONG culWritten = 0;
  1658. ULONG ulStreamOffset = 0;
  1659. LONG lOffset = 0;
  1660. INT cSign = 0;
  1661. UINT cRandomVar = 0;
  1662. LPSTREAM pIStream = NULL;
  1663. ULONG ulRef = 0;
  1664. LARGE_INTEGER liStreamPos;
  1665. LARGE_INTEGER liSeek;
  1666. ULARGE_INTEGER uli;
  1667. ULARGE_INTEGER uliSetSize;
  1668. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChangeStreamData"));
  1669. DH_VDATEPTRIN(pIStorage, IStorage) ;
  1670. DH_VDATEPTRIN(pStatStg, STATSTG) ;
  1671. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  1672. DH_VDATEPTRIN(pdgu, DG_STRING) ;
  1673. DH_ASSERT(NULL != pIStorage);
  1674. DH_ASSERT(NULL != pStatStg);
  1675. DH_ASSERT(NULL != pdgi);
  1676. DH_ASSERT(NULL != pdgu);
  1677. if(S_OK == hr)
  1678. {
  1679. // Convert WCHAR to TCHAR
  1680. hr = OleStringToTString(pStatStg->pwcsName, &ptszName);
  1681. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  1682. }
  1683. if(S_OK == hr)
  1684. {
  1685. // Convert TCHAR to OLECHAR
  1686. hr = TStringToOleString(ptszName, &poszName);
  1687. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1688. }
  1689. // Open the stream if it is not open
  1690. if(S_OK == hr)
  1691. {
  1692. hr = pIStorage->OpenStream(
  1693. poszName,
  1694. NULL,
  1695. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  1696. 0,
  1697. &pIStream);
  1698. DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
  1699. }
  1700. // Seek to end of stream and get its size
  1701. if(S_OK == hr)
  1702. {
  1703. memset(&liStreamPos, 0, sizeof(LARGE_INTEGER));
  1704. // Position the stream header to the postion from begining
  1705. hr = pIStream->Seek(liStreamPos, STREAM_SEEK_END, &uli);
  1706. DH_HRCHECK(hr, TEXT("VirtualStmNode::Seek")) ;
  1707. ulStreamOffset = ULIGetLow(uli);
  1708. }
  1709. // Generate size and direction of change. Magnitude is 1- SHRT_MAX bytes
  1710. // or 1 - streamsize if SHRT_MAX is greater than stream size. 50 % of time,
  1711. // direction will be positive, and rest times negative.
  1712. if(S_OK == hr)
  1713. {
  1714. usErr = pdgi->Generate(&lOffset, 1, SHRT_MAX);
  1715. if (DG_RC_SUCCESS != usErr)
  1716. {
  1717. hr = E_FAIL;
  1718. }
  1719. }
  1720. if((S_OK == hr) && ((ULONG) lOffset > ulStreamOffset))
  1721. {
  1722. usErr = pdgi->Generate(&lOffset, 1, ulStreamOffset);
  1723. if (DG_RC_SUCCESS != usErr)
  1724. {
  1725. hr = E_FAIL;
  1726. }
  1727. }
  1728. if(S_OK == hr)
  1729. {
  1730. usErr = pdgi->Generate(&cSign, 1, 2);
  1731. if (DG_RC_SUCCESS != usErr)
  1732. {
  1733. hr = E_FAIL;
  1734. }
  1735. if(S_OK == hr)
  1736. {
  1737. cSign = (cSign == 1) ? 1 : -1;
  1738. }
  1739. }
  1740. // Generate Random number to do wither a SetSize or Seek/Write operation
  1741. // to change stream data
  1742. if(S_OK == hr)
  1743. {
  1744. usErr = pdgi->Generate(&cRandomVar, 1, 2);
  1745. if (DG_RC_SUCCESS != usErr)
  1746. {
  1747. hr = E_FAIL;
  1748. }
  1749. }
  1750. if(S_OK == hr)
  1751. {
  1752. switch (cRandomVar)
  1753. {
  1754. case 1:
  1755. {
  1756. ulStreamOffset = ulStreamOffset + (lOffset * cSign);
  1757. ULISet32(uliSetSize, ulStreamOffset);
  1758. hr = pIStream->SetSize(uliSetSize);
  1759. break;
  1760. }
  1761. case 2:
  1762. {
  1763. // Seek either beyond or before the curretn seek position and
  1764. // write a random number of bytes from there.
  1765. LISet32(liSeek, lOffset*cSign);
  1766. hr = pIStream->Seek(liSeek, STREAM_SEEK_CUR, &uli);
  1767. if(S_OK == hr)
  1768. {
  1769. hr = GenerateRandomName(pdgu, 1, SHRT_MAX, &ptszNewData);
  1770. DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
  1771. }
  1772. if(S_OK == hr)
  1773. {
  1774. // Convert ptcsName to OLECHAR
  1775. hr = TStringToOleString(ptszNewData, &poszNewData);
  1776. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1777. }
  1778. if(S_OK == hr)
  1779. {
  1780. hr = pIStream->Write(poszNewData, cb, &culWritten);
  1781. DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ;
  1782. }
  1783. break;
  1784. }
  1785. }
  1786. }
  1787. // Close the stream
  1788. if(S_OK == hr)
  1789. {
  1790. ulRef = pIStream->Release();
  1791. DH_ASSERT(0 == ulRef);
  1792. pIStream = NULL;
  1793. }
  1794. // Clean up
  1795. if(NULL != ptszName)
  1796. {
  1797. delete ptszName;
  1798. ptszName = NULL;
  1799. }
  1800. if(NULL != poszName)
  1801. {
  1802. delete poszName;
  1803. poszName = NULL;
  1804. }
  1805. if(NULL != ptszNewData)
  1806. {
  1807. delete ptszNewData;
  1808. ptszNewData = NULL;
  1809. }
  1810. if(NULL != poszNewData)
  1811. {
  1812. delete poszNewData;
  1813. poszNewData = NULL;
  1814. }
  1815. return hr;
  1816. }
  1817. //----------------------------------------------------------------------------
  1818. //
  1819. // Function: ChangeExistingObject
  1820. //
  1821. // Synopsis: Randomly destorys/renames a stream or storage object in a DocFile.
  1822. // Randomly changes data of object if it is a stream. This impl.
  1823. // is for case when it a storage object that needs to be changed
  1824. //
  1825. // Arguments: [pIStorage] - Pointer to parent storage
  1826. // [pStatStg] - Pointer to STATSTG structure
  1827. // [pdgi] - Pointer to data generator integer object
  1828. // [pdgu] - Pointer to data generator unicode object
  1829. // [fStgDeleted] - Out value to indicate storage is deleted
  1830. //
  1831. // Returns: HResult
  1832. //
  1833. // History: 29-Jul-1996 Narindk Created
  1834. //
  1835. //----------------------------------------------------------------------------
  1836. HRESULT ChangeExistingObject(
  1837. LPSTORAGE pIStorage,
  1838. STATSTG *pStatStg,
  1839. DG_INTEGER *pdgi,
  1840. DG_STRING *pdgu,
  1841. BOOL *pfStgDeleted)
  1842. {
  1843. HRESULT hr = S_OK;
  1844. USHORT usErr = 0;
  1845. UINT cRandomAction = 0;
  1846. LPTSTR ptszNewName = NULL;
  1847. LPOLESTR poszNewName = NULL;
  1848. LPTSTR ptszName = NULL;
  1849. LPOLESTR poszName = NULL;
  1850. LPSTORAGE pIStorageRenamed= NULL;
  1851. LPMALLOC pMalloc = NULL;
  1852. ULONG ulRef = 0;
  1853. BOOL fRenamed = FALSE;
  1854. STATSTG statStgRenamed;
  1855. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChangeExistingObject"));
  1856. DH_VDATEPTRIN(pIStorage, IStorage) ;
  1857. DH_VDATEPTRIN(pStatStg, STATSTG) ;
  1858. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  1859. DH_VDATEPTRIN(pdgu, DG_STRING) ;
  1860. DH_ASSERT(NULL != pIStorage);
  1861. DH_ASSERT(NULL != pStatStg);
  1862. DH_ASSERT(NULL != pdgi);
  1863. DH_ASSERT(NULL != pdgu);
  1864. if(S_OK == hr)
  1865. {
  1866. // Convert WCHAR to TCHAR
  1867. hr = OleStringToTString(pStatStg->pwcsName, &ptszName);
  1868. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1869. }
  1870. if(S_OK == hr)
  1871. {
  1872. // Convert TCHAR to OLECHAR
  1873. hr = TStringToOleString(ptszName, &poszName);
  1874. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1875. }
  1876. if(S_OK == hr)
  1877. {
  1878. usErr = pdgi->Generate(&cRandomAction, 1, 3);
  1879. if (DG_RC_SUCCESS != usErr)
  1880. {
  1881. hr = E_FAIL;
  1882. }
  1883. }
  1884. if(S_OK == hr)
  1885. {
  1886. switch (cRandomAction)
  1887. {
  1888. case 1:
  1889. {
  1890. hr = pIStorage->DestroyElement(poszName);
  1891. DH_HRCHECK(hr, TEXT("IStorage::DestoryElement")) ;
  1892. if(S_OK == hr)
  1893. {
  1894. *pfStgDeleted = TRUE;
  1895. }
  1896. if (S_OK != hr)
  1897. {
  1898. DH_LOG((
  1899. LOG_INFO,
  1900. TEXT("IStorage::DestroyElement failed, hr=0x%lx.\n"),
  1901. hr));
  1902. }
  1903. break;
  1904. }
  1905. case 2:
  1906. case 3:
  1907. {
  1908. // Generate random new name
  1909. hr = GenerateRandomName(
  1910. pdgu,
  1911. MINLENGTH,
  1912. MAXLENGTH,
  1913. &ptszNewName);
  1914. if(S_OK == hr)
  1915. {
  1916. // Convert TCHAR to OLECHAR
  1917. hr = TStringToOleString(ptszNewName, &poszNewName);
  1918. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  1919. }
  1920. if(S_OK == hr)
  1921. {
  1922. hr = pIStorage->RenameElement(
  1923. poszName,
  1924. poszNewName);
  1925. DH_HRCHECK(hr, TEXT("IStorage::Rename")) ;
  1926. if (S_OK != hr)
  1927. {
  1928. DH_LOG((
  1929. LOG_INFO,
  1930. TEXT("IStorage::RenameElem failed, hr=0x%lx.\n"),
  1931. hr));
  1932. }
  1933. }
  1934. if(S_OK == hr)
  1935. {
  1936. fRenamed = TRUE;
  1937. }
  1938. break;
  1939. }
  1940. case 4:
  1941. case 5:
  1942. case 6:
  1943. {
  1944. hr = ChangeStreamData(pIStorage, pStatStg, pdgi, pdgu);
  1945. DH_HRCHECK(hr, TEXT("ChangeStreamData")) ;
  1946. break;
  1947. }
  1948. }
  1949. }
  1950. // ----------- flatfile change ---------------
  1951. if( StorageIsFlat() &&
  1952. (0 == _wcsicmp(poszName, L"CONTENTS")) &&
  1953. (STG_E_ACCESSDENIED == hr))
  1954. {
  1955. DH_LOG((
  1956. LOG_INFO,
  1957. TEXT("ChangeExistingObject on %ws failed as exp, hr=0x%lx.\n"),
  1958. pStatStg->pwcsName,
  1959. hr));
  1960. hr = S_OK;
  1961. }
  1962. // ----------- flatfile change ---------------
  1963. if((S_OK == hr) &&
  1964. (TRUE == fRenamed) &&
  1965. (STGTY_STORAGE == pStatStg->type))
  1966. {
  1967. // Get pMalloc to free pwcsName of STATSTG struct.
  1968. if ( S_OK == hr )
  1969. {
  1970. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  1971. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  1972. }
  1973. // Free the pStatStg->pwcsName
  1974. if((S_OK == hr) && (NULL != pStatStg->pwcsName))
  1975. {
  1976. pMalloc->Free(pStatStg->pwcsName);
  1977. pStatStg->pwcsName = NULL;
  1978. }
  1979. // Open the storage and stat it, copy name and close it.
  1980. if(S_OK == hr)
  1981. {
  1982. hr = pIStorage->OpenStorage(
  1983. poszNewName,
  1984. NULL,
  1985. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1986. NULL,
  1987. 0,
  1988. &pIStorageRenamed);
  1989. if (S_OK != hr)
  1990. {
  1991. DH_LOG((
  1992. LOG_INFO,
  1993. TEXT("IStorage::OpenStorage failed, hr=0x%lx.\n"),
  1994. hr));
  1995. }
  1996. }
  1997. if(S_OK == hr)
  1998. {
  1999. hr = pIStorageRenamed->Stat(&statStgRenamed, STATFLAG_DEFAULT);
  2000. if (S_OK != hr)
  2001. {
  2002. DH_LOG((
  2003. LOG_INFO,
  2004. TEXT("IStorage::Stat failed, hr=0x%lx.\n"),
  2005. hr));
  2006. }
  2007. }
  2008. if(S_OK == hr)
  2009. {
  2010. pStatStg->pwcsName = statStgRenamed.pwcsName;
  2011. }
  2012. if(S_OK == hr)
  2013. {
  2014. ulRef = pIStorageRenamed->Release();
  2015. DH_ASSERT(0 == ulRef);
  2016. pIStorageRenamed = NULL;
  2017. }
  2018. }
  2019. // Clean up
  2020. if(NULL != pMalloc)
  2021. {
  2022. pMalloc->Release();
  2023. pMalloc = NULL;
  2024. }
  2025. if(NULL != ptszName)
  2026. {
  2027. delete ptszName;
  2028. ptszName = NULL;
  2029. }
  2030. if(NULL != poszName)
  2031. {
  2032. delete poszName;
  2033. poszName = NULL;
  2034. }
  2035. if(NULL != ptszNewName)
  2036. {
  2037. delete ptszNewName;
  2038. ptszNewName = NULL;
  2039. }
  2040. if(NULL != poszNewName)
  2041. {
  2042. delete poszNewName;
  2043. poszNewName = NULL;
  2044. }
  2045. return hr;
  2046. }
  2047. //----------------------------------------------------------------------------
  2048. //
  2049. // Function: EnumerateAndProcessIStorage
  2050. //
  2051. // Synopsis: Iterates through a supplied IStorage, recursing and changing
  2052. // objects.
  2053. //
  2054. // Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
  2055. // [pvcn] - Pointer to VirtualCtrNode
  2056. // [pdgi] - Pointer to data generator integer object
  2057. // [pdgu] - Pointer to data generator unicode object
  2058. //
  2059. // Returns: HResult
  2060. //
  2061. // History: 29-Jul-1996 Narindk Created
  2062. //
  2063. // Notes: The VirtualDF tree is not used in this function, because of over
  2064. // head of maintaining the tree as in several recursions of the
  2065. // DocFile, there will be several random reverts and commits.
  2066. //----------------------------------------------------------------------------
  2067. HRESULT EnumerateAndProcessIStorage(
  2068. LPSTORAGE pIStorage,
  2069. DWORD dwStgMode,
  2070. DG_INTEGER *pdgi,
  2071. DG_STRING *pdgu)
  2072. {
  2073. HRESULT hr = S_OK;
  2074. USHORT usErr = 0;
  2075. LPSTORAGE pIStorageChild = NULL;
  2076. LPMALLOC pMalloc = NULL;
  2077. LPENUMSTATSTG lpEnumStatStg = NULL;
  2078. BOOL fStorageDeleted = FALSE;
  2079. BOOL fCommit = FALSE;
  2080. UINT cRandomAction = 0;
  2081. ULONG ulRef = 0;
  2082. static USHORT usNumElementEnum= 0;
  2083. LPTSTR ptszName = NULL;
  2084. LPOLESTR poszName = NULL;
  2085. STATSTG statStg;
  2086. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateAndProcessIStorage"));
  2087. DH_VDATEPTRIN(pIStorage, IStorage) ;
  2088. DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
  2089. DH_VDATEPTRIN(pdgu, DG_STRING) ;
  2090. DH_ASSERT(NULL != pIStorage);
  2091. DH_ASSERT(NULL != pdgi);
  2092. DH_ASSERT(NULL != pdgu);
  2093. if(S_OK == hr)
  2094. {
  2095. // Get enumerator
  2096. hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
  2097. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
  2098. }
  2099. if (S_OK != hr)
  2100. {
  2101. DH_LOG((
  2102. LOG_INFO,
  2103. TEXT("IStorage::EnumElements unsuccessful, hr=0x%lx.\n"),
  2104. hr));
  2105. }
  2106. // Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
  2107. if ( S_OK == hr )
  2108. {
  2109. hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
  2110. DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
  2111. }
  2112. // Stat on passed storage
  2113. if(S_OK == hr)
  2114. {
  2115. hr = pIStorage->Stat(&statStg, STATFLAG_DEFAULT);
  2116. DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
  2117. }
  2118. if (S_OK != hr)
  2119. {
  2120. DH_LOG((
  2121. LOG_INFO,
  2122. TEXT("IStorage::Stat unsuccessful, hr=0x%lx.\n"),
  2123. hr));
  2124. }
  2125. // Free the statStg.pwcsName
  2126. if(NULL != statStg.pwcsName)
  2127. {
  2128. pMalloc->Free(statStg.pwcsName);
  2129. statStg.pwcsName = NULL;
  2130. }
  2131. // Loop to get next element
  2132. while((S_OK == lpEnumStatStg->Next(1, &statStg, NULL)) &&
  2133. (S_OK == hr))
  2134. {
  2135. // approx 10% chance of changing an element
  2136. if(S_OK == hr)
  2137. {
  2138. usErr = pdgi->Generate(&cRandomAction, 1, 10);
  2139. if (DG_RC_SUCCESS != usErr)
  2140. {
  2141. hr = E_FAIL;
  2142. }
  2143. }
  2144. if((S_OK == hr) && (cRandomAction == 1))
  2145. {
  2146. hr = ChangeExistingObject(
  2147. pIStorage,
  2148. &statStg,
  2149. pdgi,
  2150. pdgu,
  2151. &fStorageDeleted);
  2152. DH_HRCHECK(hr, TEXT("ChangeExistingObject")) ;
  2153. fCommit = TRUE;
  2154. if (S_OK != hr)
  2155. {
  2156. DH_LOG((
  2157. LOG_INFO,
  2158. TEXT("ChangeExistingObject unsuccessful, hr=0x%lx.\n"),
  2159. hr));
  2160. }
  2161. }
  2162. // every 1 to 64 objects enumerated, create a new object in current
  2163. // storage
  2164. if((S_OK == hr) && (0 == usNumElementEnum--))
  2165. {
  2166. usErr = pdgi->Generate(&usNumElementEnum, 1, 64);
  2167. if (DG_RC_SUCCESS != usErr)
  2168. {
  2169. hr = E_FAIL;
  2170. }
  2171. if(S_OK == hr)
  2172. {
  2173. hr = CreateNewObject(pIStorage, dwStgMode, pdgi, pdgu);
  2174. DH_HRCHECK(hr, TEXT("CreateNewObject")) ;
  2175. fCommit = TRUE;
  2176. }
  2177. if (S_OK != hr)
  2178. {
  2179. DH_LOG((
  2180. LOG_INFO,
  2181. TEXT("CreateNewObject unsuccessful, hr=0x%lx.\n"),
  2182. hr));
  2183. }
  2184. }
  2185. // Randomly commit the storage 50 % of time if it is not deleted
  2186. if((S_OK == hr) && (TRUE == fCommit))
  2187. {
  2188. usErr = pdgi->Generate(&cRandomAction, 1, 2);
  2189. if (DG_RC_SUCCESS != usErr)
  2190. {
  2191. hr = E_FAIL;
  2192. }
  2193. if((S_OK == hr) && (cRandomAction == 1))
  2194. {
  2195. // Commit
  2196. hr = pIStorage->Commit(STGC_DEFAULT);
  2197. // Reset variable
  2198. fCommit = FALSE;
  2199. }
  2200. if (S_OK != hr)
  2201. {
  2202. DH_LOG((
  2203. LOG_INFO,
  2204. TEXT("IStorage::Commit unsuccessful, hr=0x%lx.\n"),
  2205. hr));
  2206. }
  2207. }
  2208. // if current storage is an IStorage and it wasn't deleted, then
  2209. // recurse into it and process it.
  2210. if((S_OK == hr) &&
  2211. (STGTY_STORAGE == statStg.type) &&
  2212. (FALSE == fStorageDeleted))
  2213. {
  2214. // Convert WCHAR to TCHAR
  2215. hr = OleStringToTString(statStg.pwcsName, &ptszName);
  2216. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  2217. if(S_OK == hr)
  2218. {
  2219. // Convert TCHAR to OLECHAR
  2220. hr = TStringToOleString(ptszName, &poszName);
  2221. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  2222. }
  2223. if(S_OK == hr)
  2224. {
  2225. // Open storage
  2226. hr = pIStorage->OpenStorage(
  2227. poszName,
  2228. NULL,
  2229. dwStgMode,
  2230. NULL,
  2231. 0,
  2232. &pIStorageChild);
  2233. if (S_OK != hr)
  2234. {
  2235. DH_LOG((
  2236. LOG_INFO,
  2237. TEXT("IStorage::OpenStorage unsuccessful, hr=0x%lx.\n"),
  2238. hr));
  2239. }
  2240. }
  2241. if(S_OK == hr)
  2242. {
  2243. // Recurse into child storage and process it recursively.
  2244. hr = EnumerateAndProcessIStorage(
  2245. pIStorageChild,
  2246. dwStgMode,
  2247. pdgi,
  2248. pdgu);
  2249. if (S_OK != hr)
  2250. {
  2251. DH_LOG((
  2252. LOG_INFO,
  2253. TEXT("EnumerateAndProcessIStorage failed, hr=0x%lx.\n"),
  2254. hr));
  2255. }
  2256. }
  2257. // Close the storage
  2258. if(S_OK == hr)
  2259. {
  2260. ulRef = pIStorageChild->Release();
  2261. DH_ASSERT(0 == ulRef);
  2262. pIStorageChild = NULL;
  2263. }
  2264. }
  2265. // Free the statStg.pwcsName
  2266. if(NULL != statStg.pwcsName)
  2267. {
  2268. pMalloc->Free(statStg.pwcsName);
  2269. statStg.pwcsName = NULL;
  2270. }
  2271. if(NULL != ptszName)
  2272. {
  2273. delete ptszName;
  2274. ptszName = NULL;
  2275. }
  2276. if(NULL != poszName)
  2277. {
  2278. delete poszName;
  2279. poszName = NULL;
  2280. }
  2281. // Reset variables
  2282. fStorageDeleted = FALSE;
  2283. }
  2284. // Randomly commit changes
  2285. if(S_OK == hr)
  2286. {
  2287. usErr = pdgi->Generate(&cRandomAction, 0, 3);
  2288. if (DG_RC_SUCCESS != usErr)
  2289. {
  2290. hr = E_FAIL;
  2291. }
  2292. }
  2293. if(S_OK == hr)
  2294. {
  2295. if(0 != cRandomAction)
  2296. {
  2297. hr = pIStorage->Commit(STGC_DEFAULT);
  2298. if (S_OK != hr)
  2299. {
  2300. DH_LOG((
  2301. LOG_INFO,
  2302. TEXT("IStorage::Commit unsuccessful, hr=0x%lx.\n"),
  2303. hr));
  2304. }
  2305. }
  2306. else
  2307. {
  2308. hr = pIStorage->Revert();
  2309. if (S_OK != hr)
  2310. {
  2311. DH_LOG((
  2312. LOG_INFO,
  2313. TEXT("IStorage::Revert unsuccessful, hr=0x%lx.\n"),
  2314. hr));
  2315. }
  2316. }
  2317. }
  2318. // Cleanup
  2319. if (NULL != lpEnumStatStg)
  2320. {
  2321. ulRef = lpEnumStatStg->Release();
  2322. DH_ASSERT(NULL == ulRef);
  2323. lpEnumStatStg = NULL;
  2324. }
  2325. if(NULL != pMalloc)
  2326. {
  2327. pMalloc->Release();
  2328. pMalloc = NULL;
  2329. }
  2330. return hr;
  2331. }
  2332. // Function: IsEqualStream
  2333. //
  2334. // Synopsis: Determines whether the two streams passed as arguments
  2335. // are identical in length and content.
  2336. //
  2337. // Arguments: [pIOrigional] - Origional Stream
  2338. // [pICompare] - The stream to compare with Origional
  2339. // Stream
  2340. //
  2341. // Returns: HRESULT
  2342. //
  2343. // History: July 31, 1996 T-Scottg Created
  2344. //
  2345. // Note: Although a more elegent solution can be created using
  2346. // CRCs, this particular implementation has been designed
  2347. // so that it better tests the HGLOBAL implementation
  2348. // of IStream
  2349. //
  2350. //+-------------------------------------------------------------------------
  2351. HRESULT IsEqualStream(IStream * pIOrigional, IStream * pICompare)
  2352. {
  2353. HRESULT hr = S_OK;
  2354. BYTE * pbOrigionalBuf = NULL;
  2355. BYTE * pbCompareBuf = NULL;
  2356. STATSTG statOrigional;
  2357. STATSTG statCompare;
  2358. LARGE_INTEGER liSeek;
  2359. DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IsEqualStream"));
  2360. DH_VDATEPTRIN(pIOrigional, IStream *);
  2361. DH_VDATEPTRIN(pICompare, IStream *);
  2362. DH_ASSERT(NULL != pIOrigional);
  2363. DH_ASSERT(NULL != pICompare);
  2364. // Note: STATFLAG_NONAME is passed to IStream::Stat(...).
  2365. // This requests that the statistics not include the pwcsName member
  2366. // of the STATSTG structure. Hence, there is no need for pwcsName to
  2367. // be freed after use.
  2368. if (S_OK == hr)
  2369. {
  2370. hr = pIOrigional->Stat(&statOrigional, STATFLAG_NONAME);
  2371. DH_HRCHECK(hr, TEXT("IsEqualStream: pIOrigional->Stat Failure"));
  2372. }
  2373. if (S_OK == hr)
  2374. {
  2375. hr = pICompare->Stat(&statCompare, STATFLAG_NONAME);
  2376. DH_HRCHECK(hr, TEXT("IsEqualStream: pICompare->Stat Failure"));
  2377. }
  2378. // If the size of the two streams is not equal, then the streams
  2379. // can't be equal.
  2380. if (S_OK == hr)
  2381. {
  2382. if (statOrigional.cbSize.LowPart != statCompare.cbSize.LowPart)
  2383. {
  2384. hr = S_FALSE;
  2385. DH_HRCHECK(hr, TEXT("Stream Sizes Not Equal"));
  2386. }
  2387. }
  2388. // Allocate buffer to hold the stream contents
  2389. if (S_OK == hr)
  2390. {
  2391. pbOrigionalBuf = new BYTE [statOrigional.cbSize.LowPart];
  2392. if (NULL == pbOrigionalBuf)
  2393. {
  2394. hr = E_OUTOFMEMORY;
  2395. }
  2396. DH_HRCHECK(hr, TEXT("IsEqualStream: new pbOrigionalBuf failed"));
  2397. }
  2398. // Initialize Buffer
  2399. if (S_OK == hr)
  2400. {
  2401. DH_ASSERT(NULL != pbOrigionalBuf);
  2402. memset(pbOrigionalBuf, '\0', statOrigional.cbSize.LowPart);
  2403. }
  2404. // Allocate buffer to hold the stream contents
  2405. if (S_OK == hr)
  2406. {
  2407. pbCompareBuf = new BYTE [statCompare.cbSize.LowPart];
  2408. if (NULL == pbCompareBuf)
  2409. {
  2410. hr = E_OUTOFMEMORY;
  2411. }
  2412. DH_HRCHECK(hr, TEXT("IsEqualStream: new pbCompareBuf failed"));
  2413. }
  2414. // Initialize Buffer
  2415. if (S_OK == hr)
  2416. {
  2417. DH_ASSERT(NULL != pbOrigionalBuf);
  2418. memset(pbOrigionalBuf, '\0', statOrigional.cbSize.LowPart);
  2419. }
  2420. // Set Origional Seek pointer back to beginning of stream
  2421. if (S_OK == hr)
  2422. {
  2423. LISet32(liSeek, 0);
  2424. hr = pIOrigional->Seek(liSeek, STREAM_SEEK_SET, NULL);
  2425. DH_HRCHECK(hr, TEXT("IStream::Seek Failed"));
  2426. }
  2427. // Set Compare Seek pointer back to beginning of stream
  2428. if (S_OK == hr)
  2429. {
  2430. LISet32(liSeek, 0);
  2431. hr = pICompare->Seek(liSeek, STREAM_SEEK_SET, NULL);
  2432. DH_HRCHECK(hr, TEXT("IStream::Seek Failed"));
  2433. }
  2434. // Read pIOrigional Stream data into buffer.
  2435. if (S_OK == hr)
  2436. {
  2437. hr = pIOrigional->Read( pbOrigionalBuf,
  2438. statOrigional.cbSize.LowPart,
  2439. NULL );
  2440. DH_HRCHECK(hr, TEXT("IsEqualStream: pIOrigional->Read Failure"));
  2441. }
  2442. // Read pICompare Stream data into buffer.
  2443. if (S_OK == hr)
  2444. {
  2445. hr = pICompare->Read( pbCompareBuf,
  2446. statCompare.cbSize.LowPart,
  2447. NULL );
  2448. DH_HRCHECK(hr, TEXT("IsEqualStream: pICompare->Read Failure"));
  2449. }
  2450. // Compare memory buffers. If they are not equal, set hr to S_FALSE;
  2451. if (S_OK == hr)
  2452. {
  2453. if (0 != memcmp( pbOrigionalBuf,
  2454. pbCompareBuf,
  2455. statOrigional.cbSize.LowPart ))
  2456. {
  2457. hr = S_FALSE;
  2458. }
  2459. DH_HRCHECK(hr, TEXT("Buffer data not equal"));
  2460. }
  2461. // Cleanup dynamic memory
  2462. if (NULL != pbOrigionalBuf)
  2463. {
  2464. delete [] pbOrigionalBuf;
  2465. pbOrigionalBuf = NULL;
  2466. }
  2467. if (NULL != pbCompareBuf)
  2468. {
  2469. delete [] pbCompareBuf;
  2470. pbCompareBuf = NULL;
  2471. }
  2472. // Log if errors occur
  2473. if (S_OK != hr)
  2474. {
  2475. DH_LOG((LOG_FAIL, TEXT("IsEqualStream Failed, hr = 0x%Lx"), hr));
  2476. }
  2477. return hr;
  2478. }
  2479. //+-------------------------------------------------------------------------
  2480. //
  2481. // Function: ILockBytesWriteTest
  2482. //
  2483. // Synopsis: Writes data to the provided ILockBytes (calling
  2484. // ILockBytes::Flush in between writes). When all data
  2485. // is written, the function verifies that the ILockBytes
  2486. // is of the correct length.
  2487. //
  2488. // Arguments: [pILockBytes] - ILockBytes to Write Data to
  2489. // [dwSeed] - Seed to Randomizer
  2490. // [dwSize] - Byte count of data to write to ILockBytes
  2491. //
  2492. // Returns: HRESULT
  2493. //
  2494. // History: Heavily Modified T-Scottg 7/30/96
  2495. // Created Venkatesan Viswanathan
  2496. //
  2497. //+-------------------------------------------------------------------------
  2498. HRESULT ILockBytesWriteTest ( ILockBytes * pILockBytes,
  2499. DWORD dwSeed,
  2500. DWORD dwSize )
  2501. {
  2502. HRESULT hr = S_OK;
  2503. CHAR * pbBuffer = NULL;
  2504. DWORD dwWritten = 0;
  2505. DWORD dwIdx = 0;
  2506. ULARGE_INTEGER li;
  2507. STATSTG LockBytesStat;
  2508. DG_ASCII dga(dwSeed);
  2509. DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("ILockBytesWriteTest"));
  2510. DH_VDATEPTRIN(pILockBytes, ILockBytes *);
  2511. DH_ASSERT(NULL != pILockBytes);
  2512. // Create Data Buffer with Random Data in It
  2513. if (0 != (dga.Generate( &pbBuffer,
  2514. DG_APRINT_MIN,
  2515. DG_APRINT_MAX,
  2516. dwSize,
  2517. dwSize )))
  2518. {
  2519. hr = S_FALSE;
  2520. DH_HRCHECK(hr, TEXT("dgi.Generate Failed"));
  2521. }
  2522. // Write Data into ILockBytes
  2523. if (S_OK == hr)
  2524. {
  2525. for (dwIdx = 0; (dwIdx + HGLOBAL_PACKET_SIZE) <= dwSize; dwIdx += HGLOBAL_PACKET_SIZE)
  2526. {
  2527. ULISet32(li, dwIdx);
  2528. hr = pILockBytes->WriteAt( li,
  2529. pbBuffer,
  2530. HGLOBAL_PACKET_SIZE,
  2531. &dwWritten );
  2532. DH_HRCHECK(hr, TEXT("pILockBytes->WriteAt Failed"));
  2533. // Verify that all of the data was written
  2534. if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
  2535. {
  2536. hr = S_FALSE;
  2537. DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
  2538. }
  2539. // Flush ILockBytes to Memory
  2540. if (S_OK == hr)
  2541. {
  2542. hr = pILockBytes->Flush();
  2543. DH_HRCHECK(hr, TEXT("pILockBytes->Flush Failed"));
  2544. }
  2545. // Break out of loop if error occurs
  2546. if (S_OK != hr)
  2547. {
  2548. break;
  2549. }
  2550. }
  2551. }
  2552. // Obtain STATSTG structure from ILockBytes
  2553. if (S_OK == hr)
  2554. {
  2555. hr = pILockBytes->Stat( &LockBytesStat,
  2556. STATFLAG_NONAME );
  2557. DH_HRCHECK(hr, TEXT("pILockBytes->Stat Failed"));
  2558. }
  2559. // Verify that the ILockBytes is of the correct length
  2560. if (S_OK == hr)
  2561. {
  2562. if (LockBytesStat.cbSize.LowPart != dwSize)
  2563. {
  2564. hr = S_FALSE;
  2565. DH_HRCHECK(hr, TEXT("ILockBytes not of correct length"));
  2566. }
  2567. }
  2568. // Free dynamic memory
  2569. if (NULL != pbBuffer)
  2570. {
  2571. delete [] pbBuffer;
  2572. pbBuffer = NULL;
  2573. }
  2574. // Log if errors occur
  2575. if (S_OK != hr)
  2576. {
  2577. DH_LOG((LOG_FAIL, TEXT("ILockBytesWriteTest Failed, hr = 0x%Lx"), hr));
  2578. }
  2579. return hr;
  2580. }
  2581. //+-------------------------------------------------------------------------
  2582. //
  2583. // Function: ILockBytesReadTest
  2584. //
  2585. // Synopsis: Reads data from the provided ILockBytes
  2586. //
  2587. // Arguments: [pILockBytes] - ILockBytes to Read Data from
  2588. // [dwSize] - Byte count of data to read from ILockBytes
  2589. //
  2590. // Returns: HRESULT
  2591. //
  2592. // History: Heavily Modified T-Scottg 7/30/96
  2593. // Created Venkatesan Viswanathan
  2594. //
  2595. //+-------------------------------------------------------------------------
  2596. HRESULT ILockBytesReadTest (ILockBytes * pILockBytes, DWORD dwSize)
  2597. {
  2598. HRESULT hr = S_OK;
  2599. BYTE * pbBuffer = NULL;
  2600. DWORD dwRead = 0;
  2601. DWORD dwIndex = 0;
  2602. ULARGE_INTEGER li;
  2603. DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("ILockBytesReadTest"));
  2604. DH_VDATEPTRIN(pILockBytes, ILockBytes *);
  2605. DH_ASSERT(NULL != pILockBytes);
  2606. // Create buffer to hold data
  2607. if (S_OK == hr)
  2608. {
  2609. pbBuffer = new BYTE[HGLOBAL_PACKET_SIZE];
  2610. if (NULL == pbBuffer)
  2611. {
  2612. hr = E_OUTOFMEMORY;
  2613. }
  2614. DH_HRCHECK(hr, TEXT("new BYTE call failed"));
  2615. }
  2616. // Initialize Buffer
  2617. if (S_OK == hr)
  2618. {
  2619. DH_ASSERT(NULL != pbBuffer);
  2620. memset(pbBuffer, '\0', HGLOBAL_PACKET_SIZE);
  2621. }
  2622. // Read Data from ILockBytes
  2623. if (S_OK == hr)
  2624. {
  2625. for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
  2626. {
  2627. ULISet32(li, dwIndex);
  2628. hr = pILockBytes->ReadAt( li,
  2629. pbBuffer,
  2630. HGLOBAL_PACKET_SIZE,
  2631. &dwRead );
  2632. DH_HRCHECK(hr, TEXT("pILockBytes->ReadAt Failed"));
  2633. // Verify that all of the data was written
  2634. if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwRead))
  2635. {
  2636. hr = S_FALSE;
  2637. DH_HRCHECK(hr, TEXT("Read Data length mismatch"));
  2638. }
  2639. // Break out of loop if error occurs
  2640. if (S_OK != hr)
  2641. {
  2642. break;
  2643. }
  2644. }
  2645. }
  2646. // Free dynamic memory
  2647. if (NULL != pbBuffer)
  2648. {
  2649. delete [] pbBuffer;
  2650. pbBuffer = NULL;
  2651. }
  2652. // Log if errors occur
  2653. if (S_OK != hr)
  2654. {
  2655. DH_LOG((LOG_FAIL, TEXT("ILockBytesReadTest Failed, hr = 0x%Lx"), hr));
  2656. }
  2657. return hr;
  2658. }
  2659. //+-------------------------------------------------------------------------
  2660. //
  2661. // Function: IStreamWriteTest
  2662. //
  2663. // Synopsis: Writes data to the provided IStream
  2664. //
  2665. // Arguments: [pIStream] - IStream to Write Data to
  2666. // [dwSize] - Byte count of data to write to IStream
  2667. //
  2668. // Returns: HRESULT
  2669. //
  2670. // History: Heavily Modified T-Scottg 7/30/96
  2671. // Created Venkatesan Viswanathan
  2672. //
  2673. //+-------------------------------------------------------------------------
  2674. HRESULT IStreamWriteTest ( IStream * pIStream,
  2675. DWORD dwSeed,
  2676. DWORD dwSize )
  2677. {
  2678. HRESULT hr = S_OK;
  2679. CHAR * pbBuffer = NULL;
  2680. DWORD dwWritten = 0;
  2681. DWORD dwIndex = 0;
  2682. LARGE_INTEGER li;
  2683. STATSTG StreamStat;
  2684. DG_ASCII dga(dwSeed);
  2685. DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IStreamWriteTest"));
  2686. DH_VDATEPTRIN(pIStream, IStream *);
  2687. DH_ASSERT(NULL != pIStream);
  2688. // Create Data Buffer with Random Data in It
  2689. if (0 != (dga.Generate( &pbBuffer,
  2690. DG_APRINT_MIN,
  2691. DG_APRINT_MAX,
  2692. dwSize,
  2693. dwSize )))
  2694. {
  2695. hr = S_FALSE;
  2696. DH_HRCHECK(hr, TEXT("dgi.Generate Failed"));
  2697. }
  2698. // Write Data into IStream
  2699. if (S_OK == hr)
  2700. {
  2701. for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
  2702. {
  2703. // Assign seek index to Large Integer Structure
  2704. LISet32(li, dwIndex);
  2705. // Seek to correct position in stream
  2706. if (S_OK == hr)
  2707. {
  2708. hr = pIStream->Seek( li,
  2709. STREAM_SEEK_SET,
  2710. NULL );
  2711. DH_HRCHECK(hr, TEXT("pIStream->Seek Failed"));
  2712. }
  2713. // Write Data to stream
  2714. if (S_OK == hr)
  2715. {
  2716. hr = pIStream->Write( pbBuffer,
  2717. HGLOBAL_PACKET_SIZE,
  2718. &dwWritten );
  2719. DH_HRCHECK(hr, TEXT("pIStream->Write Failed"));
  2720. }
  2721. // Verify that all of the data was written
  2722. if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
  2723. {
  2724. hr = S_FALSE;
  2725. DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
  2726. }
  2727. // Break out of loop if error occurs
  2728. if (S_OK != hr)
  2729. {
  2730. break;
  2731. }
  2732. }
  2733. }
  2734. // Obtain STATSTG structure from ILockBytes
  2735. if (S_OK == hr)
  2736. {
  2737. hr = pIStream->Stat( &StreamStat,
  2738. STATFLAG_NONAME );
  2739. DH_HRCHECK(hr, TEXT("pIStream->Stat Failed"));
  2740. }
  2741. // Verify that the IStream is of the correct length
  2742. if (S_OK == hr)
  2743. {
  2744. if (StreamStat.cbSize.LowPart != dwSize)
  2745. {
  2746. hr = S_FALSE;
  2747. DH_HRCHECK(hr, TEXT("IStream not of correct length"));
  2748. }
  2749. }
  2750. // Free dynamic memory
  2751. if (NULL != pbBuffer)
  2752. {
  2753. delete [] pbBuffer;
  2754. pbBuffer = NULL;
  2755. }
  2756. // Log if errors occur
  2757. if (S_OK != hr)
  2758. {
  2759. DH_LOG((LOG_FAIL, TEXT("IStreamWriteTest Failed, hr = 0x%Lx"), hr));
  2760. }
  2761. return hr;
  2762. }
  2763. //+-------------------------------------------------------------------------
  2764. //
  2765. // Function: IStreamReadTest
  2766. //
  2767. // Synopsis: Reads data from the provided IStream
  2768. //
  2769. // Arguments: [pIStream] - IStream to Read Data From
  2770. // [dwSize] - Byte count of data to read from IStream
  2771. //
  2772. // Returns: HRESULT
  2773. //
  2774. // History: Heavily Modified T-Scottg 7/30/96
  2775. // Created Venkatesan Viswanathan
  2776. //
  2777. //+-------------------------------------------------------------------------
  2778. HRESULT IStreamReadTest (IStream * pIStream, DWORD dwSize)
  2779. {
  2780. HRESULT hr = S_OK;
  2781. BYTE * pbBuffer = NULL;
  2782. DWORD dwWritten = 0;
  2783. DWORD dwIndex = 0;
  2784. LARGE_INTEGER li;
  2785. DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IStreamReadTest"));
  2786. DH_VDATEPTRIN(pIStream, IStream *);
  2787. DH_ASSERT(NULL != pIStream);
  2788. // Create buffer to hold data
  2789. if (S_OK == hr)
  2790. {
  2791. pbBuffer = new BYTE[HGLOBAL_PACKET_SIZE];
  2792. if (NULL == pbBuffer)
  2793. {
  2794. hr = E_OUTOFMEMORY;
  2795. }
  2796. DH_HRCHECK(hr, TEXT("new BYTE call failed"));
  2797. }
  2798. // Initialize Buffer
  2799. if (S_OK == hr)
  2800. {
  2801. DH_ASSERT(NULL != pbBuffer);
  2802. memset(pbBuffer, '\0', HGLOBAL_PACKET_SIZE);
  2803. }
  2804. // Read Data from IStream
  2805. if (S_OK == hr)
  2806. {
  2807. for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
  2808. {
  2809. // Assign seek index to Large Integer Structure
  2810. LISet32(li, dwIndex);
  2811. // Seek to correct position in stream
  2812. if (S_OK == hr)
  2813. {
  2814. hr = pIStream->Seek( li,
  2815. STREAM_SEEK_SET,
  2816. NULL );
  2817. DH_HRCHECK(hr, TEXT("pIStream->Seek Failed"));
  2818. }
  2819. // Read Data from stream
  2820. if (S_OK == hr)
  2821. {
  2822. hr = pIStream->Read( pbBuffer,
  2823. HGLOBAL_PACKET_SIZE,
  2824. &dwWritten );
  2825. DH_HRCHECK(hr, TEXT("pIStream->Read Failed"));
  2826. }
  2827. // Verify that all of the data was written
  2828. if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
  2829. {
  2830. hr = S_FALSE;
  2831. DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
  2832. }
  2833. // Break out of loop if error occurs
  2834. if (S_OK != hr)
  2835. {
  2836. break;
  2837. }
  2838. }
  2839. }
  2840. // Free dynamic memory
  2841. if (NULL != pbBuffer)
  2842. {
  2843. delete [] pbBuffer;
  2844. pbBuffer = NULL;
  2845. }
  2846. // Log if errors occur
  2847. if (S_OK != hr)
  2848. {
  2849. DH_LOG((LOG_FAIL, TEXT("IStreamReadTest Failed, hr = 0x%Lx"), hr));
  2850. }
  2851. return hr;
  2852. }
  2853. //----------------------------------------------------------------------------
  2854. //
  2855. // Function: TraverseDocFileAndWriteOrReadSNB
  2856. //
  2857. // Synopsis: Traverse DocFile one level and either writes/reads SNB
  2858. //
  2859. // Effects: Traverse the children storages and streams of root storage,
  2860. // when fSelectObjectsToExclude == TRUE, then for each object
  2861. // returned, there is a 50% chance that the object name will
  2862. // be added to an SNB block of names to exclude upon reinstantiation,
  2863. // when fIllegitFlag == TRUE, then there is a 50% change that a
  2864. // bogus name instead of ture object name will be generated and
  2865. // be added into SNB block. When fSelectObjectsToExclude == FALSE,
  2866. // then each object name returned is checked to see if it exists in
  2867. // the SNB. If an object name is returned that *is* in the SNB,
  2868. // that object is checked to ensure that its contents are empty.
  2869. //
  2870. // Arguments: [pvcn] - Pointer to VirtualCtrNode
  2871. // [pdgi] - Pointer to Data Integer object
  2872. // [pdgu] - Pointer to Data Unicode object
  2873. // [dwStgMode] - Access Mode for the storage
  2874. // [snbNamesToExclude] - SNB specifying elements to be excluded
  2875. // [fIllegitFlag] - Indicating whether it's a legit or illegit
  2876. // limited test: if TRUE, it is a illegit one,
  2877. // otherwise, it is a legit one.
  2878. // [fSelectObjectsToExclude] - if TRUE, the function builds the
  2879. // SNB, otherwise the function checks
  2880. // names against the SNB.
  2881. //
  2882. // Returns: HResult
  2883. //
  2884. // History: 29-Jul-1996 JiminLi Created
  2885. //
  2886. //-----------------------------------------------------------------------------
  2887. HRESULT TraverseDocfileAndWriteOrReadSNB(
  2888. VirtualCtrNode *pvcn,
  2889. DG_INTEGER *pdgi,
  2890. DG_STRING *pdgu,
  2891. DWORD dwStgMode,
  2892. SNB snbNamesToExclude,
  2893. BOOL fIllegitFlag,
  2894. BOOL fSelectObjectsToExclude)
  2895. {
  2896. HRESULT hr = S_OK;
  2897. ULONG culRandomExclude = 0;
  2898. ULONG culRandomBogus = 0;
  2899. ULONG culThisName = 0;
  2900. ULONG ulRef = 0;
  2901. ULONG ulStmLength = 0;
  2902. USHORT usErr = 0;
  2903. LPTSTR ptszStgName = NULL;
  2904. LPTSTR ptszBogusName = NULL;
  2905. LPTSTR ptszStmName = NULL;
  2906. LPTSTR pTStr = NULL;
  2907. VirtualCtrNode *pvcnTrav = NULL;
  2908. VirtualStmNode *pvsnTrav = NULL;
  2909. LPENUMSTATSTG lpEnumStatStg = NULL;
  2910. STATSTG *pstatStgEnum = NULL;
  2911. BOOL fLocalPass = TRUE;
  2912. LARGE_INTEGER liZero;
  2913. ULARGE_INTEGER uli;
  2914. SNB snbIndex;
  2915. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("TraverseDocfileAndWriteOrReadSNB"));
  2916. DH_VDATEPTRIN(pvcn, VirtualCtrNode);
  2917. DH_VDATEPTRIN(pdgi, DG_INTEGER);
  2918. DH_VDATEPTRIN(pdgu, DG_STRING);
  2919. DH_ASSERT(NULL != pvcn);
  2920. DH_ASSERT(NULL != pdgi);
  2921. DH_ASSERT(NULL != pdgu);
  2922. // pointer SNB to start of global SNB
  2923. snbIndex = snbNamesToExclude;
  2924. // First traverse the child storages of the root storage
  2925. pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
  2926. while ((S_OK == hr) && (NULL != pvcnTrav))
  2927. {
  2928. if (TRUE == fSelectObjectsToExclude)
  2929. {
  2930. // 50% chance of adding name to SNB for exclude on reinstantiation
  2931. // when a name is added to the SNB, memory is allocated for that
  2932. // name, the name of current VirtualCtrNode name is copied in, and
  2933. // the SNB index is incremented to point to the location for the
  2934. // next OLECHAR string.
  2935. usErr = pdgi->Generate(&culRandomExclude, 1, 100);
  2936. if (DG_RC_SUCCESS != usErr)
  2937. {
  2938. hr = E_FAIL;
  2939. }
  2940. if ((S_OK == hr) && (culRandomExclude > 50))
  2941. {
  2942. // 50% chance of placing a bogus name in the snbExclude block
  2943. ptszStgName = pvcnTrav->GetVirtualCtrNodeName();
  2944. DH_ASSERT(NULL != ptszStgName);
  2945. culThisName = _tcslen(ptszStgName);
  2946. if (S_OK == hr)
  2947. {
  2948. if (TRUE == fIllegitFlag)
  2949. {
  2950. // if it is a illegit test, then 50% chance that
  2951. // a bogus name will generated instead of true
  2952. // object name
  2953. usErr = pdgi->Generate(&culRandomBogus, 1, 100);
  2954. if (DG_RC_SUCCESS != usErr)
  2955. {
  2956. hr = E_FAIL;
  2957. }
  2958. }
  2959. else
  2960. {
  2961. // if it is a legit test, then make sure culRandomBogus
  2962. // greater than 50,i.e. use the true object name
  2963. culRandomBogus = 100;
  2964. }
  2965. }
  2966. if (S_OK == hr)
  2967. {
  2968. if (culRandomBogus > 50)
  2969. {
  2970. hr = TStringToOleString(ptszStgName, snbIndex);
  2971. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  2972. }
  2973. else
  2974. {
  2975. hr = GenerateRandomString(
  2976. pdgu,
  2977. culThisName,
  2978. culThisName,
  2979. &ptszBogusName);
  2980. DH_HRCHECK(hr, TEXT("GenerateRandomString"));
  2981. if (S_OK == hr)
  2982. {
  2983. hr = TStringToOleString(ptszBogusName, snbIndex);
  2984. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  2985. }
  2986. if (NULL != ptszBogusName)
  2987. {
  2988. delete []ptszBogusName;
  2989. ptszBogusName = NULL;
  2990. }
  2991. }
  2992. }
  2993. snbIndex++;
  2994. }
  2995. }
  2996. else
  2997. {
  2998. // Starting with the first entry in the SNB, loop through and
  2999. // compare the current name of the VirtualCtrNode against
  3000. // each name in the SNB. If there is a match, check the
  3001. // storage and verify that its contents are empty.
  3002. ptszStgName = pvcnTrav->GetVirtualCtrNodeName();
  3003. snbIndex = snbNamesToExclude;
  3004. hr = OleStringToTString(*snbIndex, &pTStr);
  3005. DH_HRCHECK(hr, TEXT("OleStringToTString"));
  3006. while ((S_OK == hr) && (*snbIndex))
  3007. {
  3008. if (0 == _tcscmp(pTStr, ptszStgName))
  3009. {
  3010. hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
  3011. DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open"));
  3012. if (S_OK == hr)
  3013. {
  3014. hr = pvcnTrav->EnumElements(0, NULL, 0, &lpEnumStatStg);
  3015. DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements"));
  3016. }
  3017. // Allocate memory for STASTG structure
  3018. if (S_OK == hr)
  3019. {
  3020. pstatStgEnum = (STATSTG *) new STATSTG;
  3021. if (NULL == pstatStgEnum)
  3022. {
  3023. hr = E_OUTOFMEMORY;
  3024. }
  3025. }
  3026. if (S_OK == hr)
  3027. {
  3028. if (S_OK == lpEnumStatStg->Next(1, pstatStgEnum, NULL))
  3029. {
  3030. DH_LOG((
  3031. LOG_INFO,
  3032. TEXT("Should no objects in excluded Stg.\n")));
  3033. fLocalPass = FALSE;
  3034. }
  3035. }
  3036. if (NULL != pstatStgEnum)
  3037. {
  3038. delete [] pstatStgEnum;
  3039. pstatStgEnum = NULL;
  3040. }
  3041. if (NULL != lpEnumStatStg)
  3042. {
  3043. ulRef = lpEnumStatStg->Release();
  3044. DH_ASSERT(NULL == ulRef);
  3045. lpEnumStatStg = NULL;
  3046. }
  3047. break;
  3048. }
  3049. snbIndex++;
  3050. }
  3051. }
  3052. if (NULL != pTStr)
  3053. {
  3054. delete []pTStr;
  3055. pTStr = NULL;
  3056. }
  3057. if ((S_OK == hr) && (TRUE == fLocalPass))
  3058. {
  3059. pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
  3060. }
  3061. else
  3062. {
  3063. break;
  3064. }
  3065. }
  3066. // Now, traverse the child streams of the root storage
  3067. pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
  3068. while ((S_OK == hr) && (TRUE == fLocalPass) && (NULL != pvsnTrav))
  3069. {
  3070. if (TRUE == fSelectObjectsToExclude)
  3071. {
  3072. // 50% chance of adding name to SNB for exclude on reinstantiation
  3073. // when a name is added to the SNB, memory is allocated for that
  3074. // name, the name of current VirtualStmNode name is copied in, and
  3075. // the SNB index is incremented to point to the location for the
  3076. // next OLECHAR string.
  3077. usErr = pdgi->Generate(&culRandomExclude, 1, 100);
  3078. if (DG_RC_SUCCESS != usErr)
  3079. {
  3080. hr = E_FAIL;
  3081. }
  3082. if ((S_OK == hr) && (culRandomExclude > 50))
  3083. {
  3084. // 50% chance of placing a bogus name in the snbExclude block
  3085. ptszStmName = pvsnTrav->GetVirtualStmNodeName();
  3086. DH_ASSERT(NULL != ptszStmName);
  3087. culThisName = _tcslen(ptszStmName);
  3088. if (S_OK == hr)
  3089. {
  3090. if (TRUE == fIllegitFlag)
  3091. {
  3092. // if it is a illegit test, then 50% chance that
  3093. // a bogus name will generated instead of true
  3094. // object name
  3095. usErr = pdgi->Generate(&culRandomBogus, 1, 100);
  3096. if (DG_RC_SUCCESS != usErr)
  3097. {
  3098. hr = E_FAIL;
  3099. }
  3100. }
  3101. else
  3102. {
  3103. // if it is a legit test, then make sure culRandomBogus
  3104. // greater than 50,i.e. use the true object name
  3105. culRandomBogus = 100;
  3106. }
  3107. }
  3108. if (S_OK == hr)
  3109. {
  3110. if (culRandomBogus > 50)
  3111. {
  3112. hr = TStringToOleString(ptszStmName, snbIndex);
  3113. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  3114. }
  3115. else
  3116. {
  3117. hr = GenerateRandomString(
  3118. pdgu,
  3119. culThisName,
  3120. culThisName,
  3121. &ptszBogusName);
  3122. DH_HRCHECK(hr, TEXT("GenerateRandomString"));
  3123. if (S_OK == hr)
  3124. {
  3125. hr = TStringToOleString(ptszBogusName, snbIndex);
  3126. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  3127. }
  3128. if (NULL != ptszBogusName)
  3129. {
  3130. delete []ptszBogusName;
  3131. ptszBogusName = NULL;
  3132. }
  3133. }
  3134. }
  3135. snbIndex++;
  3136. }
  3137. }
  3138. else
  3139. {
  3140. // Starting with the first entry in the SNB, loop through and
  3141. // compare the current name of the VirtualStmNode against
  3142. // each name in the SNB. If there is a match, check the
  3143. // stream and verify that its length is zero.
  3144. snbIndex = snbNamesToExclude;
  3145. ptszStmName = pvsnTrav->GetVirtualStmNodeName();
  3146. hr = OleStringToTString(*snbIndex, &pTStr);
  3147. DH_HRCHECK(hr, TEXT("OleStringToTString"));
  3148. while ((S_OK == hr) && (*snbIndex))
  3149. {
  3150. if (0 == _tcscmp(pTStr, ptszStmName))
  3151. {
  3152. LISet32(liZero, 0L);
  3153. hr = pvsnTrav->Open(
  3154. NULL,
  3155. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  3156. 0);
  3157. DH_HRCHECK(hr, TEXT("VirutalStmNode::Open"));
  3158. if (S_OK == hr)
  3159. {
  3160. hr = pvsnTrav->Seek(liZero, STREAM_SEEK_END, &uli);
  3161. ulStmLength = ULIGetLow(uli);
  3162. DH_HRCHECK(hr, TEXT("VirtualStmNode::Seek")) ;
  3163. }
  3164. if (S_OK != hr)
  3165. {
  3166. DH_LOG((
  3167. LOG_INFO,
  3168. TEXT("VirtualStmNode::Seek not Ok, hr=0x%lx\n"),
  3169. hr));
  3170. }
  3171. if (0 != ulStmLength)
  3172. {
  3173. DH_LOG((
  3174. LOG_INFO,
  3175. TEXT("The length of excluded Stm should be 0.\n")));
  3176. fLocalPass = FALSE;
  3177. }
  3178. break;
  3179. }
  3180. snbIndex++;
  3181. }
  3182. }
  3183. if (NULL != pTStr)
  3184. {
  3185. delete []pTStr;
  3186. pTStr = NULL;
  3187. }
  3188. if ((S_OK == hr) && (TRUE == fLocalPass))
  3189. {
  3190. pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
  3191. }
  3192. else
  3193. {
  3194. break;
  3195. }
  3196. }
  3197. if ((S_OK == hr) && (TRUE == fSelectObjectsToExclude))
  3198. {
  3199. // Last entry in SNB block is NIL to designate the end
  3200. *snbIndex = NULL;
  3201. }
  3202. if (FALSE == fLocalPass)
  3203. {
  3204. hr = E_FAIL;
  3205. }
  3206. return hr;
  3207. }
  3208. //----------------------------------------------------------------------------
  3209. //
  3210. // Function: GetSeedFromCmdLineArgs
  3211. //
  3212. // Synopsis: Gets the seed value from command line args if required for test
  3213. //
  3214. // Arguments: [argc] - arg count
  3215. // [argv] - arg list
  3216. //
  3217. // Returns: ULONG
  3218. //
  3219. // History: 2-Aug-1996 Narindk Made into separate func.
  3220. //
  3221. //-----------------------------------------------------------------------------
  3222. ULONG GetSeedFromCmdLineArgs(int argc, char *argv[])
  3223. {
  3224. HRESULT hr = S_OK ;
  3225. ULONG ulSeed = 0;
  3226. CCmdline CCmdlineArgs(argc, argv);
  3227. CUlongCmdlineObj Seed(OLESTR("seed"), OLESTR(""), OLESTR("0")) ;
  3228. CBaseCmdlineObj *CArgList[] = {&Seed} ;
  3229. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetSeedFromCmdLineArgs"));
  3230. // Verify that the CCmdlineArgs object was constructed without
  3231. // problems
  3232. if (CMDLINE_NO_ERROR != CCmdlineArgs.QueryError())
  3233. {
  3234. hr = E_FAIL ;
  3235. }
  3236. // Parse Commandline Arguments
  3237. if (S_OK == hr)
  3238. {
  3239. if (CMDLINE_NO_ERROR != CCmdlineArgs.Parse(CArgList,
  3240. sizeof(CArgList) / sizeof(CArgList[0]),
  3241. FALSE) )
  3242. {
  3243. hr = E_FAIL ;
  3244. }
  3245. }
  3246. // Obtain Seed from CommandLine
  3247. if (S_OK == hr)
  3248. {
  3249. if ( ulSeed != *(Seed.GetValue()) )
  3250. {
  3251. ulSeed = *(Seed.GetValue());
  3252. }
  3253. }
  3254. return ulSeed;
  3255. }
  3256. //----------------------------------------------------------------------------
  3257. //
  3258. // Function: StreamCreate
  3259. //
  3260. // Synopsis: Create a stream or a file in a docfile or C-runtime condition,
  3261. // and record the time of creation in both cases: the stream or
  3262. // file existing and not existing.
  3263. //
  3264. // Arguments: [dwRootMode] - Access modes to root storage
  3265. // [pdgu] - Pointer to Data Unicode object
  3266. // [usTimeIndex] - Indicate which category this test is
  3267. // [dwFlags] - Indicate DOCFILE or RUNTIME file and also
  3268. // the stream or file exists or not
  3269. // [usNumCreates] - Indicate this is usNumCreates'th creation
  3270. //
  3271. // Returns: HResult
  3272. //
  3273. // History: 8-Aug-1996 JiminLi Created
  3274. //
  3275. //-----------------------------------------------------------------------------
  3276. HRESULT StreamCreate(
  3277. DWORD dwRootMode,
  3278. DG_STRING *pdgu,
  3279. USHORT usTimeIndex,
  3280. DWORD dwFlags,
  3281. USHORT usNumCreates)
  3282. {
  3283. HRESULT hr = S_OK;
  3284. LPSTORAGE pstgRoot = NULL;
  3285. LPSTREAM pstmStream = NULL;
  3286. LPOLESTR pOleName = NULL;
  3287. ULONG bufferSize = 0;
  3288. FILE *fileFile = NULL;
  3289. DWORD StartTime = 0;
  3290. DWORD EndTime = 0;
  3291. DWORD dwModifiers = 0;
  3292. ULONG ulRef = 0;
  3293. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("StreamCreate"));
  3294. DH_VDATEPTRIN(pdgu, DG_STRING);
  3295. DH_ASSERT(NULL != pdgu);
  3296. while ((S_OK == hr) && (0 < usNumCreates))
  3297. {
  3298. usNumCreates--;
  3299. hr = GenerateRandomName(
  3300. pdgu,
  3301. MINLENGTH,
  3302. MAXLENGTH,
  3303. &ptszNames[0]);
  3304. DH_HRCHECK(hr, TEXT("GenerateRandomName"));
  3305. if ((S_OK == hr) && (dwFlags & DOCFILE))
  3306. {
  3307. // Create a docfile
  3308. hr = TStringToOleString(ptszNames[0], &pOleName);
  3309. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  3310. if (S_OK == hr)
  3311. {
  3312. hr = StgCreateDocfile(
  3313. pOleName,
  3314. dwRootMode | STGM_CREATE,
  3315. 0,
  3316. &pstgRoot);
  3317. DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
  3318. }
  3319. }
  3320. if ((S_OK == hr) && (dwFlags & EXIST))
  3321. {
  3322. dwFlags |= CREATE;
  3323. if (dwFlags & DOCFILE)
  3324. {
  3325. // Create existing stream
  3326. if (S_OK == hr)
  3327. {
  3328. hr = pstgRoot->CreateStream(
  3329. pOleName,
  3330. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  3331. 0,
  3332. 0,
  3333. &pstmStream);
  3334. DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
  3335. }
  3336. if (S_OK == hr)
  3337. {
  3338. ulRef = pstmStream->Release();
  3339. DH_ASSERT(0 == ulRef);
  3340. pstmStream = NULL;
  3341. }
  3342. }
  3343. else
  3344. {
  3345. #if (defined _NT1X_ && !defined _MAC)
  3346. // Create existing file
  3347. fileFile = _wfopen(ptszNames[0],TEXT("w"));
  3348. if (NULL == fileFile)
  3349. {
  3350. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  3351. hr = E_FAIL;
  3352. }
  3353. #else
  3354. fileFile = fopen(ptszNames[0],"w");
  3355. if (NULL == fileFile)
  3356. {
  3357. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  3358. hr = E_FAIL;
  3359. }
  3360. #endif
  3361. if (S_OK == hr)
  3362. {
  3363. fclose(fileFile);
  3364. }
  3365. }
  3366. }
  3367. if (S_OK == hr)
  3368. {
  3369. dwModifiers |= (dwFlags & CREATE ? STGM_CREATE : STGM_FAILIFTHERE);
  3370. if (dwFlags & DOCFILE)
  3371. {
  3372. if (S_OK == hr)
  3373. {
  3374. GET_TIME(StartTime);
  3375. hr = pstgRoot->CreateStream(
  3376. pOleName,
  3377. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | dwModifiers,
  3378. 0,
  3379. 0,
  3380. &pstmStream);
  3381. GET_TIME(EndTime);
  3382. Time[usTimeIndex].plDocfileTime[usNumCreates] =
  3383. DiffTime(EndTime, StartTime);
  3384. DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
  3385. }
  3386. if ((S_OK == hr) && (dwFlags & COMMIT))
  3387. {
  3388. hr = pstgRoot->Commit(STGC_DEFAULT);
  3389. DH_HRCHECK(hr, TEXT("IStorage::Commit"));
  3390. }
  3391. if (S_OK == hr)
  3392. {
  3393. ulRef = pstmStream->Release();
  3394. DH_ASSERT(0 == ulRef);
  3395. pstmStream = NULL;
  3396. ulRef = pstgRoot->Release();
  3397. DH_ASSERT(0 == ulRef);
  3398. pstgRoot = NULL;
  3399. }
  3400. if (NULL != pOleName)
  3401. {
  3402. delete []pOleName;
  3403. pOleName = NULL;
  3404. }
  3405. }
  3406. else
  3407. {
  3408. #if (defined _NT1X_ && !defined _MAC)
  3409. GET_TIME(StartTime);
  3410. fileFile = _wfopen(ptszNames[0], TEXT("w+b"));
  3411. GET_TIME(EndTime);
  3412. #else
  3413. GET_TIME(StartTime);
  3414. fileFile = fopen(ptszNames[0], "w+b");
  3415. GET_TIME(EndTime);
  3416. #endif
  3417. Time[usTimeIndex].plRuntimeTime[usNumCreates] =
  3418. DiffTime(EndTime,StartTime);
  3419. if (NULL == fileFile)
  3420. {
  3421. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  3422. hr = E_FAIL;
  3423. }
  3424. if (S_OK == hr)
  3425. {
  3426. fclose(fileFile);
  3427. }
  3428. }
  3429. }
  3430. if (NULL != ptszNames[0])
  3431. {
  3432. if(FALSE == DeleteFile(ptszNames[0]))
  3433. {
  3434. hr = HRESULT_FROM_WIN32(GetLastError()) ;
  3435. DH_HRCHECK(hr, TEXT("DeleteFile")) ;
  3436. }
  3437. }
  3438. if (NULL != ptszNames[0])
  3439. {
  3440. delete []ptszNames[0];
  3441. ptszNames[0] = NULL;
  3442. }
  3443. }
  3444. return hr;
  3445. }
  3446. //----------------------------------------------------------------------------
  3447. //
  3448. // Function: DocfileCreate
  3449. //
  3450. // Synopsis: Create a docfile is similar to creating a directory in C-runtime,
  3451. // this test measures the time in several cases of creating a docfile,
  3452. // like create a existing or non-exist or NULL docfile. RUNTIME only
  3453. // support creating a non-exist directory.
  3454. //
  3455. // Arguments: [dwRootMode] - Access modes to root storage
  3456. // [pdgu] - Pointer to Data Unicode object
  3457. // [usTimeIndex] - Indicate which category this test is
  3458. // [dwFlags] - Indicate DOCFILE or RUNTIME file and also
  3459. // the stream or file exists or not
  3460. // [usNumCreates] - Indicate this is usNumCreates'th creation
  3461. //
  3462. // Returns: HResult
  3463. //
  3464. // History: 6-Aug-1996 JiminLi Created
  3465. //
  3466. //-----------------------------------------------------------------------------
  3467. HRESULT DocfileCreate(
  3468. DWORD dwRootMode,
  3469. DG_STRING *pdgu,
  3470. USHORT usTimeIndex,
  3471. DWORD dwFlags,
  3472. USHORT usNumCreates)
  3473. {
  3474. HRESULT hr = S_OK;
  3475. LPSTORAGE pstgRoot = NULL;
  3476. LPSTREAM pstmStream = NULL;
  3477. LPOLESTR pOleName = NULL;
  3478. LPTSTR ptTmpName = NULL;
  3479. LPTSTR ptszCurDir = NULL;
  3480. int Temp = 0;
  3481. ULONG bufferSize = 0;
  3482. DWORD StartTime = 0;
  3483. DWORD EndTime = 0;
  3484. DWORD dwModifiers = 0;
  3485. ULONG ulRef = 0;
  3486. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DocfileCreate"));
  3487. DH_VDATEPTRIN(pdgu, DG_STRING);
  3488. DH_ASSERT(NULL != pdgu);
  3489. while ((S_OK == hr) && (0 < usNumCreates))
  3490. {
  3491. usNumCreates--;
  3492. if ((dwFlags & DOCFILE) && (dwFlags & NONAME))
  3493. {
  3494. ptszNames[0] = NULL;
  3495. }
  3496. else
  3497. {
  3498. hr = GenerateRandomName(
  3499. pdgu,
  3500. MINLENGTH,
  3501. MAXLENGTH,
  3502. &ptszNames[0]);
  3503. DH_HRCHECK(hr, TEXT("GenerateRandomName"));
  3504. if (S_OK == hr)
  3505. {
  3506. hr = TStringToOleString(ptszNames[0], &pOleName);
  3507. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  3508. }
  3509. }
  3510. if ((S_OK == hr) && (dwFlags & DOCFILE) && (dwFlags & EXIST)
  3511. && ~(dwFlags & NONAME))
  3512. {
  3513. // Create a existing docfile
  3514. dwFlags |= CREATE;
  3515. hr = StgCreateDocfile(
  3516. pOleName,
  3517. dwRootMode | STGM_CREATE,
  3518. 0,
  3519. &pstgRoot);
  3520. DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
  3521. if (S_OK == hr)
  3522. {
  3523. ulRef = pstgRoot->Release();
  3524. DH_ASSERT(0 == ulRef);
  3525. pstgRoot = NULL;
  3526. }
  3527. }
  3528. if (S_OK == hr)
  3529. {
  3530. dwModifiers |= (dwFlags & CREATE ? STGM_CREATE : STGM_FAILIFTHERE);
  3531. if (dwFlags & DOCFILE)
  3532. {
  3533. GET_TIME(StartTime);
  3534. hr = StgCreateDocfile(
  3535. pOleName,
  3536. dwRootMode | dwModifiers,
  3537. 0,
  3538. &pstgRoot);
  3539. GET_TIME(EndTime);
  3540. Time[usTimeIndex].plDocfileTime[usNumCreates] =
  3541. DiffTime(EndTime, StartTime);
  3542. DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
  3543. if ((S_OK == hr) && (dwFlags & COMMIT))
  3544. {
  3545. hr = pstgRoot->Commit(STGC_DEFAULT);
  3546. DH_HRCHECK(hr, TEXT("IStorage::Commit"));
  3547. }
  3548. // if NONAME, we need to get the name so we can
  3549. // delete the file when we are done.
  3550. if (S_OK == hr && (dwFlags & NONAME))
  3551. {
  3552. STATSTG statstg;
  3553. hr = pstgRoot->Stat (&statstg, STATFLAG_DEFAULT);
  3554. DH_HRCHECK (hr, TEXT("IStorage::Stat"));
  3555. if (S_OK == hr)
  3556. {
  3557. //retrieve the filename
  3558. OleStringToTString (statstg.pwcsName, &ptTmpName);
  3559. DH_HRCHECK (hr, TEXT("OleStringToTString"));
  3560. //now that we have the name, it up from statstg
  3561. CoTaskMemFree (statstg.pwcsName);
  3562. }
  3563. }
  3564. if (S_OK == hr)
  3565. {
  3566. ulRef = pstgRoot->Release();
  3567. DH_ASSERT(0 == ulRef);
  3568. pstgRoot = NULL;
  3569. }
  3570. }
  3571. else
  3572. {
  3573. if (~(dwFlags & NONAME) && ~(dwFlags & EXIST))
  3574. {
  3575. #if (defined _NT1X_ && !defined _MAC)
  3576. ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
  3577. if (NULL == ptszCurDir)
  3578. {
  3579. hr = E_OUTOFMEMORY;
  3580. }
  3581. if (S_OK == hr)
  3582. {
  3583. memset(ptszCurDir,'\0',MAX_PATH_LENGTH*sizeof(TCHAR));
  3584. if (NULL == _wgetcwd(ptszCurDir, MAX_PATH_LENGTH))
  3585. {
  3586. DH_LOG((
  3587. LOG_INFO,
  3588. TEXT("Error in getting Current directory\n")));
  3589. hr = E_FAIL;
  3590. }
  3591. }
  3592. if (S_OK == hr)
  3593. {
  3594. GET_TIME(StartTime);
  3595. Temp = _wmkdir(ptszNames[0]);
  3596. GET_TIME(EndTime);
  3597. Time[usTimeIndex].plRuntimeTime[usNumCreates] =
  3598. DiffTime(EndTime, StartTime);
  3599. if (0 != Temp)
  3600. {
  3601. DH_LOG((
  3602. LOG_INFO,
  3603. TEXT("Error in creating a directory\n")));
  3604. hr = E_FAIL;
  3605. }
  3606. }
  3607. // Clean up
  3608. if (S_OK == hr)
  3609. {
  3610. if (0 != _wchdir(ptszCurDir))
  3611. {
  3612. DH_LOG((
  3613. LOG_INFO,
  3614. TEXT("Error in changing directory\n")));
  3615. hr = E_FAIL;
  3616. }
  3617. if (S_OK == hr)
  3618. {
  3619. if (0 != _wrmdir(ptszNames[0]))
  3620. {
  3621. DH_LOG((
  3622. LOG_INFO,
  3623. TEXT("Error in removing directory\n")));
  3624. hr = E_FAIL;
  3625. }
  3626. }
  3627. if (NULL != ptszCurDir)
  3628. {
  3629. delete []ptszCurDir;
  3630. ptszCurDir = NULL;
  3631. }
  3632. }
  3633. #else
  3634. ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
  3635. if (NULL == ptszCurDir)
  3636. {
  3637. hr = E_OUTOFMEMORY;
  3638. }
  3639. if (S_OK == hr)
  3640. {
  3641. memset(ptszCurDir,'\0',MAX_PATH_LENGTH*sizeof(TCHAR));
  3642. if (NULL == _getcwd(ptszCurDir, MAX_PATH_LENGTH))
  3643. {
  3644. DH_LOG((
  3645. LOG_INFO,
  3646. TEXT("Error in getting Current directory\n")));
  3647. hr = E_FAIL;
  3648. }
  3649. }
  3650. if (S_OK == hr)
  3651. {
  3652. GET_TIME(StartTime);
  3653. Temp = _mkdir(ptszNames[0]);
  3654. GET_TIME(EndTime);
  3655. Time[usTimeIndex].plRuntimeTime[usNumCreates] =
  3656. DiffTime(EndTime, StartTime);
  3657. if (0 != Temp)
  3658. {
  3659. DH_LOG((
  3660. LOG_INFO,
  3661. TEXT("Error in creating a directory\n")));
  3662. hr = E_FAIL;
  3663. }
  3664. }
  3665. // Clean up
  3666. if (S_OK == hr)
  3667. {
  3668. if (0 != _chdir(ptszCurDir))
  3669. {
  3670. DH_LOG((
  3671. LOG_INFO,
  3672. TEXT("Error in changing directory\n")));
  3673. hr = E_FAIL;
  3674. }
  3675. if (S_OK == hr)
  3676. {
  3677. if (0 != _rmdir(ptszNames[0]))
  3678. {
  3679. DH_LOG((
  3680. LOG_INFO,
  3681. TEXT("Error in removing directory\n")));
  3682. hr = E_FAIL;
  3683. }
  3684. }
  3685. if (NULL != ptszCurDir)
  3686. {
  3687. delete []ptszCurDir;
  3688. ptszCurDir = NULL;
  3689. }
  3690. }
  3691. #endif
  3692. }
  3693. else
  3694. {
  3695. DH_LOG((
  3696. LOG_INFO,
  3697. TEXT("RUNTIME not supported this function\n")));
  3698. hr = E_FAIL;
  3699. }
  3700. }
  3701. }
  3702. // Clean up
  3703. if (NULL != pOleName)
  3704. {
  3705. delete []pOleName;
  3706. pOleName = NULL;
  3707. }
  3708. if ((NULL != ptszNames[0]) && (dwFlags & DOCFILE))
  3709. {
  3710. if (FALSE == DeleteFile(ptszNames[0]))
  3711. {
  3712. hr = HRESULT_FROM_WIN32(GetLastError()) ;
  3713. DH_HRCHECK(hr, TEXT("DeleteFile")) ;
  3714. }
  3715. }
  3716. else if (NULL != ptTmpName)
  3717. {
  3718. if (FALSE == DeleteFile(ptTmpName))
  3719. {
  3720. hr = HRESULT_FROM_WIN32(GetLastError()) ;
  3721. DH_HRCHECK(hr, TEXT("DeleteFile")) ;
  3722. }
  3723. delete []ptTmpName;
  3724. ptTmpName = NULL;
  3725. }
  3726. if (NULL != ptszNames[0])
  3727. {
  3728. delete []ptszNames[0];
  3729. ptszNames[0] = NULL;
  3730. }
  3731. }
  3732. return hr;
  3733. }
  3734. //----------------------------------------------------------------------------
  3735. //
  3736. // Function: StreamOpen
  3737. //
  3738. // Synopsis: Open a stroage and its child stream is similar to find a directory
  3739. // and open a file in this directory in C-runtime. This test measures
  3740. // the time in opening both storage and stream or opening stream only
  3741. // and also the time in corresponding C-runtime operations.
  3742. //
  3743. // Arguments: [dwRootMode] - Access modes to root storage
  3744. // [pdgu] - Pointer to Data Unicode object
  3745. // [usTimeIndex] - Indicate which category this test is
  3746. // [dwFlags] - Indicate DOCFILE or RUNTIME file and also
  3747. // open both storage and stream or not.
  3748. // [usNumOpens] - Indicate this is usNumOpens'th opening
  3749. //
  3750. // Returns: HResult
  3751. //
  3752. // History: 9-Aug-1996 JiminLi Created
  3753. //
  3754. //-----------------------------------------------------------------------------
  3755. HRESULT StreamOpen(
  3756. DWORD dwRootMode,
  3757. DG_STRING *pdgu,
  3758. USHORT usTimeIndex,
  3759. DWORD dwFlags,
  3760. USHORT usNumOpens)
  3761. {
  3762. HRESULT hr = S_OK;
  3763. LPSTORAGE pstgRoot = NULL;
  3764. LPSTREAM pstmStream = NULL;
  3765. LPOLESTR pOleName = NULL;
  3766. LPTSTR ptszCurDir = NULL;
  3767. LPTSTR ptszNewDir = NULL;
  3768. ULONG bufferSize = 0;
  3769. DWORD StartTime = 0;
  3770. DWORD EndTime = 0;
  3771. FILE *fileFile = NULL;
  3772. ULONG ulRef = 0;
  3773. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("StreamOpen"));
  3774. DH_VDATEPTRIN(pdgu, DG_STRING);
  3775. DH_ASSERT(NULL != pdgu);
  3776. while ((S_OK == hr) && (0 < usNumOpens))
  3777. {
  3778. usNumOpens--;
  3779. hr = GenerateRandomName(
  3780. pdgu,
  3781. MINLENGTH,
  3782. MAXLENGTH,
  3783. &ptszNames[0]);
  3784. DH_HRCHECK(hr, TEXT("GenerateRandomName"));
  3785. if (S_OK == hr)
  3786. {
  3787. hr = TStringToOleString(ptszNames[0], &pOleName);
  3788. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  3789. }
  3790. if (S_OK == hr)
  3791. {
  3792. if (dwFlags & DOCFILE)
  3793. {
  3794. // Create a root storage and a stream inside it.
  3795. hr = StgCreateDocfile(
  3796. pOleName,
  3797. dwRootMode | STGM_CREATE,
  3798. 0,
  3799. &pstgRoot);
  3800. DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
  3801. if (S_OK == hr)
  3802. {
  3803. hr = pstgRoot->CreateStream(
  3804. pOleName,
  3805. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  3806. 0,
  3807. 0,
  3808. &pstmStream);
  3809. DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
  3810. }
  3811. if ((S_OK == hr) && (dwFlags & COMMIT))
  3812. {
  3813. hr = pstgRoot->Commit(STGC_DEFAULT);
  3814. DH_HRCHECK(hr, TEXT("IStorage::Commit"));
  3815. }
  3816. if (S_OK == hr)
  3817. {
  3818. ulRef = pstmStream->Release();
  3819. DH_ASSERT(0 == ulRef);
  3820. pstmStream = NULL;
  3821. ulRef = pstgRoot->Release();
  3822. DH_ASSERT(0 == ulRef);
  3823. pstgRoot = NULL;
  3824. }
  3825. }
  3826. else
  3827. {
  3828. // Create a directory and a file under it.
  3829. ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
  3830. ptszNewDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
  3831. if ((NULL == ptszCurDir) || (NULL == ptszNewDir))
  3832. {
  3833. hr = E_OUTOFMEMORY;
  3834. }
  3835. if (S_OK == hr)
  3836. {
  3837. memset(ptszCurDir,'\0',MAX_PATH_LENGTH * sizeof(TCHAR));
  3838. memset(ptszNewDir,'\0',MAX_PATH_LENGTH * sizeof(TCHAR));
  3839. }
  3840. #if (defined _NT1X_ && !defined _MAC)
  3841. if (NULL == _wgetcwd(ptszCurDir, MAX_PATH_LENGTH))
  3842. {
  3843. DH_LOG((
  3844. LOG_INFO,
  3845. TEXT("Error in getting Current directory\n")));
  3846. hr = E_FAIL;
  3847. }
  3848. if (S_OK == hr)
  3849. {
  3850. if (0 != _wmkdir(ptszNames[0]))
  3851. {
  3852. DH_LOG((
  3853. LOG_INFO,
  3854. TEXT("Error in creating a directory\n")));
  3855. hr = E_FAIL;
  3856. }
  3857. }
  3858. if (S_OK == hr)
  3859. {
  3860. _tcscpy(ptszNewDir, ptszCurDir);
  3861. _tcscat(ptszNewDir, TEXT("\\"));
  3862. _tcscat(ptszNewDir, ptszNames[0]);
  3863. }
  3864. if (S_OK == hr)
  3865. {
  3866. if (0 != _wchdir(ptszNewDir))
  3867. {
  3868. DH_LOG((
  3869. LOG_INFO,
  3870. TEXT("Error in changing directory\n")));
  3871. hr = E_FAIL;
  3872. }
  3873. }
  3874. if (S_OK == hr)
  3875. {
  3876. fileFile = _wfopen(ptszNames[0],TEXT("w"));
  3877. if (NULL == fileFile)
  3878. {
  3879. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  3880. hr = E_FAIL;
  3881. }
  3882. }
  3883. #else
  3884. if (NULL == _getcwd(ptszCurDir, MAX_PATH_LENGTH))
  3885. {
  3886. DH_LOG((
  3887. LOG_INFO,
  3888. TEXT("Error in getting Current directory\n")));
  3889. hr = E_FAIL;
  3890. }
  3891. if (S_OK == hr)
  3892. {
  3893. if (0 != _mkdir(ptszNames[0]))
  3894. {
  3895. DH_LOG((
  3896. LOG_INFO,
  3897. TEXT("Error in creating a directory\n")));
  3898. hr = E_FAIL;
  3899. }
  3900. }
  3901. if (S_OK == hr)
  3902. {
  3903. _tcscpy(ptszNewDir, ptszCurDir);
  3904. _tcscat(ptszNewDir, TEXT("\\"));
  3905. _tcscat(ptszNewDir, ptszNames[0]);
  3906. }
  3907. if (S_OK == hr)
  3908. {
  3909. if (0 != _chdir(ptszNewDir))
  3910. {
  3911. DH_LOG((
  3912. LOG_INFO,
  3913. TEXT("Error in changing directory\n")));
  3914. hr = E_FAIL;
  3915. }
  3916. }
  3917. if (S_OK == hr)
  3918. {
  3919. fileFile = fopen(ptszNames[0],"w");
  3920. if (NULL == fileFile)
  3921. {
  3922. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  3923. hr = E_FAIL;
  3924. }
  3925. }
  3926. #endif
  3927. if (S_OK == hr)
  3928. {
  3929. fclose(fileFile);
  3930. }
  3931. }
  3932. }
  3933. if (S_OK == hr)
  3934. {
  3935. if (dwFlags & DOCFILE)
  3936. {
  3937. if (dwFlags & OPENBOTH)
  3938. {
  3939. GET_TIME(StartTime);
  3940. hr = StgOpenStorage(
  3941. pOleName,
  3942. NULL,
  3943. dwRootMode,
  3944. NULL,
  3945. 0,
  3946. &pstgRoot);
  3947. if (S_OK == hr)
  3948. {
  3949. hr = pstgRoot->OpenStream(
  3950. pOleName,
  3951. NULL,
  3952. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  3953. 0,
  3954. &pstmStream);
  3955. GET_TIME(EndTime);
  3956. Time[usTimeIndex].plDocfileTime[usNumOpens] =
  3957. DiffTime(EndTime, StartTime);
  3958. }
  3959. if (S_OK != hr)
  3960. {
  3961. DH_LOG((
  3962. LOG_INFO,
  3963. TEXT("Open storage or stream, hr=0x%lx\n"),
  3964. hr));
  3965. }
  3966. }
  3967. else
  3968. {
  3969. hr = StgOpenStorage(
  3970. pOleName,
  3971. NULL,
  3972. dwRootMode,
  3973. NULL,
  3974. 0,
  3975. &pstgRoot);
  3976. if (S_OK == hr)
  3977. {
  3978. GET_TIME(StartTime);
  3979. hr = pstgRoot->OpenStream(
  3980. pOleName,
  3981. NULL,
  3982. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  3983. 0,
  3984. &pstmStream);
  3985. GET_TIME(EndTime);
  3986. Time[usTimeIndex].plDocfileTime[usNumOpens] =
  3987. DiffTime(EndTime, StartTime);
  3988. }
  3989. if (S_OK != hr)
  3990. {
  3991. DH_LOG((
  3992. LOG_INFO,
  3993. TEXT("Open storage or stream, hr=0x%lx\n"),
  3994. hr));
  3995. }
  3996. }
  3997. if (S_OK == hr)
  3998. {
  3999. ulRef = pstmStream->Release();
  4000. DH_ASSERT(0 == ulRef);
  4001. pstmStream = NULL;
  4002. ulRef = pstgRoot->Release();
  4003. DH_ASSERT(0 == ulRef);
  4004. pstgRoot = NULL;
  4005. }
  4006. }
  4007. else
  4008. {
  4009. if (dwFlags & OPENBOTH)
  4010. {
  4011. #if (defined _NT1X_ && !defined _MAC)
  4012. GET_TIME(StartTime);
  4013. if (0 != _wchdir(ptszNewDir))
  4014. {
  4015. DH_LOG((
  4016. LOG_INFO,
  4017. TEXT("Error in changing directory\n")));
  4018. hr = E_FAIL;
  4019. }
  4020. if (S_OK == hr)
  4021. {
  4022. fileFile = _wfopen(ptszNames[0],TEXT("r+"));
  4023. GET_TIME(EndTime);
  4024. Time[usTimeIndex].plRuntimeTime[usNumOpens] =
  4025. DiffTime(EndTime, StartTime);
  4026. if (NULL == fileFile)
  4027. {
  4028. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4029. hr = E_FAIL;
  4030. }
  4031. }
  4032. #else
  4033. GET_TIME(StartTime);
  4034. if (0 != _chdir(ptszNewDir))
  4035. {
  4036. DH_LOG((
  4037. LOG_INFO,
  4038. TEXT("Error in changing directory\n")));
  4039. hr = E_FAIL;
  4040. }
  4041. if (S_OK == hr)
  4042. {
  4043. fileFile = fopen(ptszNames[0],"r+");
  4044. GET_TIME(EndTime);
  4045. Time[usTimeIndex].plRuntimeTime[usNumOpens] =
  4046. DiffTime(EndTime, StartTime);
  4047. if (NULL == fileFile)
  4048. {
  4049. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4050. hr = E_FAIL;
  4051. }
  4052. }
  4053. #endif
  4054. if (S_OK == hr)
  4055. {
  4056. fclose(fileFile);
  4057. }
  4058. }
  4059. else
  4060. {
  4061. #if (defined _NT1X_ && !defined _MAC)
  4062. if (0 != _wchdir(ptszNewDir))
  4063. {
  4064. DH_LOG((
  4065. LOG_INFO,
  4066. TEXT("Error in changing directory\n")));
  4067. hr = E_FAIL;
  4068. }
  4069. if (S_OK == hr)
  4070. {
  4071. GET_TIME(StartTime);
  4072. fileFile = _wfopen(ptszNames[0],TEXT("r+"));
  4073. GET_TIME(EndTime);
  4074. Time[usTimeIndex].plRuntimeTime[usNumOpens] =
  4075. DiffTime(EndTime, StartTime);
  4076. if (NULL == fileFile)
  4077. {
  4078. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4079. hr = E_FAIL;
  4080. }
  4081. }
  4082. #else
  4083. if (0 != _chdir(ptszNewDir))
  4084. {
  4085. DH_LOG((
  4086. LOG_INFO,
  4087. TEXT("Error in changing directory\n")));
  4088. hr = E_FAIL;
  4089. }
  4090. if (S_OK == hr)
  4091. {
  4092. GET_TIME(StartTime);
  4093. fileFile = fopen(ptszNames[0],"r+");
  4094. GET_TIME(EndTime);
  4095. Time[usTimeIndex].plRuntimeTime[usNumOpens] =
  4096. DiffTime(EndTime, StartTime);
  4097. if (NULL == fileFile)
  4098. {
  4099. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4100. hr = E_FAIL;
  4101. }
  4102. }
  4103. #endif
  4104. if (S_OK == hr)
  4105. {
  4106. fclose(fileFile);
  4107. }
  4108. }
  4109. }
  4110. }
  4111. // Clean up
  4112. if ((S_OK == hr) && (dwFlags & RUNTIME))
  4113. {
  4114. // Remove the directory and the file under it
  4115. if ((S_OK == hr) && (NULL != ptszNames[0]))
  4116. {
  4117. if (FALSE == DeleteFile(ptszNames[0]))
  4118. {
  4119. hr = HRESULT_FROM_WIN32(GetLastError()) ;
  4120. DH_HRCHECK(hr, TEXT("DeleteFile")) ;
  4121. }
  4122. }
  4123. #if (defined _NT1X_ && !defined _MAC)
  4124. if (0 != _wchdir(ptszCurDir))
  4125. {
  4126. DH_LOG((
  4127. LOG_INFO,
  4128. TEXT("Error in changing directory\n")));
  4129. hr = E_FAIL;
  4130. }
  4131. if (S_OK == hr)
  4132. {
  4133. if (0 != _wrmdir(ptszNames[0]))
  4134. {
  4135. DH_LOG((
  4136. LOG_INFO,
  4137. TEXT("Error in removing directory\n")));
  4138. hr = E_FAIL;
  4139. }
  4140. }
  4141. #else
  4142. if (0 != _chdir(ptszCurDir))
  4143. {
  4144. DH_LOG((
  4145. LOG_INFO,
  4146. TEXT("Error in changing directory\n")));
  4147. hr = E_FAIL;
  4148. }
  4149. if (S_OK == hr)
  4150. {
  4151. if (0 != _rmdir(ptszNames[0]))
  4152. {
  4153. DH_LOG((
  4154. LOG_INFO,
  4155. TEXT("Error in removing directory\n")));
  4156. hr = E_FAIL;
  4157. }
  4158. }
  4159. #endif
  4160. if (NULL != ptszNewDir)
  4161. {
  4162. delete []ptszNewDir;
  4163. ptszNewDir = NULL;
  4164. }
  4165. if (NULL != ptszCurDir)
  4166. {
  4167. delete []ptszCurDir;
  4168. ptszCurDir = NULL;
  4169. }
  4170. }
  4171. if (NULL != pOleName)
  4172. {
  4173. delete []pOleName;
  4174. pOleName = NULL;
  4175. }
  4176. if ((NULL != ptszNames[0]) && (dwFlags & DOCFILE))
  4177. {
  4178. if (FALSE == DeleteFile(ptszNames[0]))
  4179. {
  4180. hr = HRESULT_FROM_WIN32(GetLastError()) ;
  4181. DH_HRCHECK(hr, TEXT("DeleteFile")) ;
  4182. }
  4183. }
  4184. if (NULL != ptszNames[0])
  4185. {
  4186. delete []ptszNames[0];
  4187. ptszNames[0] = NULL;
  4188. }
  4189. }
  4190. return hr;
  4191. }
  4192. //----------------------------------------------------------------------------
  4193. //
  4194. // Function: WriteStreamInSameSizeChunks
  4195. //
  4196. // Synopsis: Create and open all the docfiles or C-runtime files, and then
  4197. // write data in the same size chunks to docfiles or C-runtime
  4198. // files, also record the time of the all the write operations
  4199. // in Time[]. Each WRITE could be RANDOM_WRITE or SEQUENTIAL_WRITE.
  4200. //
  4201. // Arguments: [dwRootMode] - The access mode for the root docfile
  4202. // [pdgu] - Pointer to Data Unicode object
  4203. // [usTimeIndex] - Indicate it is RANDOM_WRITE or SEQUENTIAL_WRITE
  4204. // [dwFlags] - Indicate write to DOCFILE or RUNTIME file
  4205. // [ulChunkSize] - The size of each chunk to write
  4206. // [usIteration] - Indicate this is the usIteration'th write
  4207. //
  4208. // Returns: HResult
  4209. //
  4210. // History: 6-Aug-1996 JiminLi Created
  4211. //
  4212. //-----------------------------------------------------------------------------
  4213. HRESULT WriteStreamInSameSizeChunks(
  4214. DWORD dwRootMode,
  4215. DG_STRING *pdgu,
  4216. USHORT usTimeIndex,
  4217. DWORD dwFlags,
  4218. ULONG ulChunkSize,
  4219. USHORT usIteration)
  4220. {
  4221. HRESULT hr = S_OK;
  4222. DWORD StartTime = 0;
  4223. DWORD EndTime = 0;
  4224. ULONG culBytesLeftToWrite = 0;
  4225. LPTSTR ptcsBuffer = NULL;
  4226. LPOLESTR pOleName = NULL;
  4227. ULONG pcbCount = 0;
  4228. USHORT usSeekIndex = 0;
  4229. USHORT usIndex = 0;
  4230. ULONG ulUserChunk = 0;
  4231. ULONG bufferSize = 0;
  4232. DWORD dwWriteCRC = 0;
  4233. DWORD dwReadCRC = 0;
  4234. ULONG ulRef = 0;
  4235. LPSTORAGE pstgRoot[MAX_DOCFILES];
  4236. LPSTREAM pstmStream[MAX_DOCFILES];
  4237. FILE *fileFile[MAX_DOCFILES];
  4238. LARGE_INTEGER liStreamPos;
  4239. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("WriteStreamInSameSizeChunks"));
  4240. DH_VDATEPTRIN(pdgu, DG_STRING);
  4241. DH_ASSERT(NULL != pdgu);
  4242. // Initialization
  4243. culBytesLeftToWrite = ulStreamSize;
  4244. ulUserChunk = ulChunkSize;
  4245. // Create & open all the docfiles or C-runtime files
  4246. if (S_OK == hr)
  4247. {
  4248. for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
  4249. {
  4250. if (dwFlags & DOCFILE)
  4251. {
  4252. hr = TStringToOleString(ptszNames[usIndex], &pOleName);
  4253. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  4254. if (S_OK == hr)
  4255. {
  4256. hr = StgCreateDocfile(
  4257. pOleName,
  4258. dwRootMode | STGM_CREATE,
  4259. 0,
  4260. &pstgRoot[usIndex]);
  4261. DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
  4262. }
  4263. if (S_OK == hr)
  4264. {
  4265. hr = pstgRoot[usIndex]->CreateStream(
  4266. pOleName,
  4267. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  4268. 0,
  4269. 0,
  4270. &pstmStream[usIndex]);
  4271. DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
  4272. }
  4273. if (S_OK == hr)
  4274. {
  4275. hr = pstgRoot[usIndex]->Commit(STGC_DEFAULT);
  4276. DH_HRCHECK(hr, TEXT("IStorage::Commit"));
  4277. }
  4278. if (NULL != pOleName)
  4279. {
  4280. delete []pOleName;
  4281. pOleName = NULL;
  4282. }
  4283. if (S_OK != hr)
  4284. {
  4285. break;
  4286. }
  4287. }
  4288. else
  4289. {
  4290. #if (defined _NT1X_ && !defined _MAC)
  4291. fileFile[usIndex] = _wfopen(ptszNames[usIndex],TEXT("w+b"));
  4292. if (NULL == fileFile[usIndex])
  4293. {
  4294. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4295. hr = E_FAIL;
  4296. break;
  4297. }
  4298. #else
  4299. fileFile[usIndex] = fopen(ptszNames[usIndex],"w+b");
  4300. if (NULL == fileFile[usIndex])
  4301. {
  4302. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4303. hr = E_FAIL;
  4304. break;
  4305. }
  4306. #endif
  4307. }
  4308. }
  4309. }
  4310. if (S_OK == hr)
  4311. {
  4312. hr = GenerateRandomString(
  4313. pdgu,
  4314. ulChunkSize,
  4315. ulChunkSize,
  4316. &ptcsBuffer);
  4317. DH_HRCHECK(hr, TEXT("GenerateRandomString"));
  4318. }
  4319. if (S_OK == hr)
  4320. {
  4321. GET_TIME(StartTime);
  4322. // Perform write operations on each of the MAX_DOCFILES files
  4323. for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
  4324. {
  4325. culBytesLeftToWrite = ulStreamSize;
  4326. usSeekIndex = 0;
  4327. ulChunkSize = ulUserChunk;
  4328. while (0 != culBytesLeftToWrite)
  4329. {
  4330. if (ulChunkSize > culBytesLeftToWrite)
  4331. {
  4332. ulChunkSize = culBytesLeftToWrite;
  4333. }
  4334. culBytesLeftToWrite -= ulChunkSize;
  4335. if (dwFlags & DOCFILE)
  4336. {
  4337. if (RANDOM_WRITE == usTimeIndex)
  4338. {
  4339. LISet32(liStreamPos,ulSeekOffset[usSeekIndex]);
  4340. usSeekIndex++;
  4341. hr = pstmStream[usIndex]->Seek(
  4342. liStreamPos,
  4343. STREAM_SEEK_SET,
  4344. NULL);
  4345. DH_HRCHECK(hr, TEXT("IStream::Seek"));
  4346. }
  4347. if (S_OK == hr)
  4348. {
  4349. hr = pstmStream[usIndex]->Write(
  4350. (LPBYTE)ptcsBuffer,
  4351. ulChunkSize,
  4352. &pcbCount);
  4353. DH_HRCHECK(hr, TEXT("IStream::Write"));
  4354. }
  4355. }
  4356. else
  4357. {
  4358. if (RANDOM_WRITE == usTimeIndex)
  4359. {
  4360. fseek(
  4361. fileFile[usIndex],
  4362. (LONG) ulSeekOffset[usSeekIndex++],
  4363. SEEK_SET);
  4364. if (ferror(fileFile[usIndex]))
  4365. {
  4366. DH_LOG((LOG_INFO, TEXT("Error seeking file\n")));
  4367. hr = E_FAIL;
  4368. }
  4369. }
  4370. if (S_OK == hr)
  4371. {
  4372. fwrite(
  4373. (LPBYTE)ptcsBuffer,
  4374. (size_t)ulChunkSize,
  4375. 1,
  4376. fileFile[usIndex]);
  4377. if (ferror(fileFile[usIndex]))
  4378. {
  4379. DH_LOG((LOG_INFO, TEXT("Error writing file\n")));
  4380. hr = E_FAIL;
  4381. }
  4382. }
  4383. }
  4384. if (S_OK != hr)
  4385. {
  4386. break;
  4387. }
  4388. }
  4389. if (S_OK == hr)
  4390. {
  4391. if (dwFlags & DOCFILE)
  4392. {
  4393. if (dwFlags & COMMIT)
  4394. {
  4395. hr = pstgRoot[usIndex]->Commit(STGC_DEFAULT);
  4396. DH_HRCHECK(hr, TEXT("IStorage::Commit"));
  4397. }
  4398. if (S_OK == hr)
  4399. {
  4400. ulRef = pstmStream[usIndex]->Release();
  4401. DH_ASSERT(0 == ulRef);
  4402. pstmStream[usIndex] = NULL;
  4403. ulRef = pstgRoot[usIndex]->Release();
  4404. DH_ASSERT(0 == ulRef);
  4405. pstgRoot[usIndex] = NULL;
  4406. }
  4407. }
  4408. else
  4409. {
  4410. fclose(fileFile[usIndex]);
  4411. }
  4412. }
  4413. if (S_OK != hr)
  4414. {
  4415. break;
  4416. }
  4417. }
  4418. if (S_OK == hr)
  4419. {
  4420. GET_TIME(EndTime);
  4421. if (dwFlags & DOCFILE)
  4422. {
  4423. Time[usTimeIndex].plDocfileTime[usIteration] =
  4424. DiffTime(EndTime, StartTime) / MAX_DOCFILES;
  4425. }
  4426. else
  4427. {
  4428. Time[usTimeIndex].plRuntimeTime[usIteration] =
  4429. DiffTime(EndTime, StartTime) / MAX_DOCFILES;
  4430. }
  4431. }
  4432. }
  4433. if (NULL != ptcsBuffer)
  4434. {
  4435. delete []ptcsBuffer;
  4436. ptcsBuffer = NULL;
  4437. }
  4438. return hr;
  4439. }
  4440. //----------------------------------------------------------------------------
  4441. //
  4442. // Function: ReadStreamInSameSizeChunks
  4443. //
  4444. // Synopsis: Open all the docfiles or C-runtime files created before, then
  4445. // read data in the same size chunks from docfiles or C-runtime
  4446. // files, also record the time of the all the read operations
  4447. // in Time[]. Each READ could be RANDOM_READ or SEQUENTIAL_READ.
  4448. //
  4449. // Arguments: [dwRootMode] - Access Mode for the root storage
  4450. // [usTimeIndex] - Indicate it is RANDOM_WRITE or SEQUENTIAL_WRITE
  4451. // [dwFlags] - Indicate reading from DOCFILE or RUNTIME file
  4452. // [ulChunkSize] - The size of each chunk to read
  4453. // [usIteration] - Indicate this is the usIteration'th read
  4454. //
  4455. // Returns: HResult
  4456. //
  4457. // History: 8-Aug-1996 JiminLi Created
  4458. //
  4459. //-----------------------------------------------------------------------------
  4460. HRESULT ReadStreamInSameSizeChunks(
  4461. DWORD dwRootMode,
  4462. USHORT usTimeIndex,
  4463. DWORD dwFlags,
  4464. ULONG ulChunkSize,
  4465. USHORT usIteration)
  4466. {
  4467. HRESULT hr = S_OK;
  4468. DWORD StartTime = 0;
  4469. DWORD EndTime = 0;
  4470. ULONG culBytesLeftToRead = 0;
  4471. LPBYTE pbBuffer = NULL;
  4472. LPOLESTR pOleName = NULL;
  4473. ULONG pcbCount = 0;
  4474. USHORT usSeekIndex = 0;
  4475. USHORT usIndex = 0;
  4476. ULONG ulUserChunk = 0;
  4477. ULONG bufferSize = 0;
  4478. DWORD dwWriteCRC = 0;
  4479. DWORD dwReadCRC = 0;
  4480. ULONG ulRef = 0;
  4481. LPSTORAGE pstgRoot[MAX_DOCFILES];
  4482. LPSTREAM pstmStream[MAX_DOCFILES];
  4483. FILE *fileFile[MAX_DOCFILES];
  4484. LARGE_INTEGER liStreamPos;
  4485. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ReadStreamInSameSizeChunks"));
  4486. // Initialization
  4487. culBytesLeftToRead = ulStreamSize;
  4488. ulUserChunk = ulChunkSize;
  4489. // Open all the docfiles or C-runtime files
  4490. if (S_OK == hr)
  4491. {
  4492. for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
  4493. {
  4494. if (dwFlags & DOCFILE)
  4495. {
  4496. hr = TStringToOleString(ptszNames[usIndex], &pOleName);
  4497. DH_HRCHECK(hr, TEXT("TStringToOleString"));
  4498. if (S_OK == hr)
  4499. {
  4500. hr = StgOpenStorage(
  4501. pOleName,
  4502. NULL,
  4503. dwRootMode,
  4504. NULL,
  4505. 0,
  4506. &pstgRoot[usIndex]);
  4507. DH_HRCHECK(hr, TEXT("StgOpenStorage"));
  4508. }
  4509. if (S_OK == hr)
  4510. {
  4511. hr = pstgRoot[usIndex]->OpenStream(
  4512. pOleName,
  4513. NULL,
  4514. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  4515. 0,
  4516. &pstmStream[usIndex]);
  4517. DH_HRCHECK(hr, TEXT("IStorage::OpenStream"));
  4518. }
  4519. if (NULL != pOleName)
  4520. {
  4521. delete []pOleName;
  4522. pOleName = NULL;
  4523. }
  4524. if (S_OK != hr)
  4525. {
  4526. break;
  4527. }
  4528. }
  4529. else
  4530. {
  4531. #if (defined _NT1X_ && !defined _MAC)
  4532. fileFile[usIndex] = _wfopen(ptszNames[usIndex], TEXT("r+b"));
  4533. if (NULL == fileFile[usIndex])
  4534. {
  4535. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4536. hr = E_FAIL;
  4537. break;
  4538. }
  4539. #else
  4540. fileFile[usIndex] = fopen(ptszNames[usIndex],"r+b");
  4541. if (NULL == fileFile[usIndex])
  4542. {
  4543. DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
  4544. hr = E_FAIL;
  4545. break;
  4546. }
  4547. #endif
  4548. }
  4549. }
  4550. }
  4551. if (S_OK == hr)
  4552. {
  4553. GET_TIME(StartTime);
  4554. // Perform write operations on each of the MAX_DOCFILES files
  4555. for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
  4556. {
  4557. culBytesLeftToRead = ulStreamSize;
  4558. usSeekIndex = 0;
  4559. ulChunkSize = ulUserChunk;
  4560. while (0 != culBytesLeftToRead)
  4561. {
  4562. if (ulChunkSize > culBytesLeftToRead)
  4563. {
  4564. ulChunkSize = culBytesLeftToRead;
  4565. }
  4566. culBytesLeftToRead -= ulChunkSize;
  4567. pbBuffer = new BYTE[ulChunkSize];
  4568. if (NULL == pbBuffer)
  4569. {
  4570. hr = E_OUTOFMEMORY;
  4571. }
  4572. if (S_OK == hr)
  4573. {
  4574. memset(pbBuffer, '\0', ulChunkSize * sizeof(BYTE));
  4575. }
  4576. if ((S_OK == hr) && (dwFlags & DOCFILE))
  4577. {
  4578. if (RANDOM_READ == usTimeIndex)
  4579. {
  4580. LISet32(liStreamPos,ulSeekOffset[usSeekIndex]);
  4581. usSeekIndex++;
  4582. hr = pstmStream[usIndex]->Seek(
  4583. liStreamPos,
  4584. STREAM_SEEK_SET,
  4585. NULL);
  4586. DH_HRCHECK(hr, TEXT("IStream::Seek"));
  4587. }
  4588. if (S_OK == hr)
  4589. {
  4590. hr = pstmStream[usIndex]->Read(
  4591. pbBuffer,
  4592. ulChunkSize,
  4593. &pcbCount);
  4594. DH_HRCHECK(hr, TEXT("IStream::Read"));
  4595. }
  4596. }
  4597. else
  4598. {
  4599. if ((S_OK == hr) && (RANDOM_READ == usTimeIndex))
  4600. {
  4601. fseek(
  4602. fileFile[usIndex],
  4603. (LONG) ulSeekOffset[usSeekIndex++],
  4604. SEEK_SET);
  4605. if (ferror(fileFile[usIndex]))
  4606. {
  4607. DH_LOG((LOG_INFO, TEXT("Error seeking file\n")));
  4608. hr = E_FAIL;
  4609. }
  4610. }
  4611. if (S_OK == hr)
  4612. {
  4613. fread(
  4614. pbBuffer,
  4615. (size_t)ulChunkSize,
  4616. 1,
  4617. fileFile[usIndex]);
  4618. if (ferror(fileFile[usIndex]))
  4619. {
  4620. DH_LOG((LOG_INFO, TEXT("Error reading file\n")));
  4621. hr = E_FAIL;
  4622. }
  4623. }
  4624. }
  4625. if (NULL != pbBuffer)
  4626. {
  4627. delete []pbBuffer;
  4628. pbBuffer = NULL;
  4629. }
  4630. if (S_OK != hr)
  4631. {
  4632. break;
  4633. }
  4634. }
  4635. if (S_OK != hr)
  4636. {
  4637. break;
  4638. }
  4639. }
  4640. if (S_OK == hr)
  4641. {
  4642. GET_TIME(EndTime);
  4643. for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
  4644. {
  4645. if (dwFlags & DOCFILE)
  4646. {
  4647. ulRef = pstmStream[usIndex]->Release();
  4648. DH_ASSERT(0 == ulRef);
  4649. pstmStream[usIndex] = NULL;
  4650. ulRef = pstgRoot[usIndex]->Release();
  4651. DH_ASSERT(0 == ulRef);
  4652. pstgRoot[usIndex] = NULL;
  4653. }
  4654. else
  4655. {
  4656. fclose(fileFile[usIndex]);
  4657. }
  4658. }
  4659. }
  4660. if (S_OK == hr)
  4661. {
  4662. if (dwFlags & DOCFILE)
  4663. {
  4664. Time[usTimeIndex].plDocfileTime[usIteration] =
  4665. DiffTime(EndTime, StartTime) / MAX_DOCFILES;
  4666. }
  4667. else
  4668. {
  4669. Time[usTimeIndex].plRuntimeTime[usIteration] =
  4670. DiffTime(EndTime, StartTime) / MAX_DOCFILES;
  4671. }
  4672. }
  4673. }
  4674. return hr;
  4675. }
  4676. //----------------------------------------------------------------------------
  4677. //
  4678. // Function: Statistics
  4679. //
  4680. // Synopsis: Generate statistics data: average, total and square difference.
  4681. //
  4682. // Arguments: [pdData] - pointer to data
  4683. // [usItems] - Number of data items
  4684. // [pdAverage] - Average value of data
  4685. // [pdTotal] - Total value of data
  4686. // [pdSD] - Square difference of data
  4687. //
  4688. // Returns: None
  4689. //
  4690. // History: 6-Aug-1996 JiminLi Created
  4691. //
  4692. //-----------------------------------------------------------------------------
  4693. void Statistics(
  4694. double *pdData,
  4695. USHORT usItems,
  4696. double *pdAverage,
  4697. double *pdTotal,
  4698. double *pdSD)
  4699. {
  4700. USHORT usIndex = 0;
  4701. double dTemp;
  4702. *pdTotal = 0;
  4703. for (usIndex=0; usIndex<usItems; usIndex++)
  4704. {
  4705. *pdTotal += pdData[usIndex];
  4706. }
  4707. *pdAverage = *pdTotal / usItems;
  4708. *pdSD = 0;
  4709. for (usIndex=0; usIndex<usItems; usIndex++)
  4710. {
  4711. dTemp = (pdData[usIndex] - *pdAverage);
  4712. *pdSD += (dTemp * dTemp);
  4713. }
  4714. if (usItems > 1)
  4715. {
  4716. *pdSD = *pdSD / (usItems - 1);
  4717. }
  4718. *pdSD = sqrt(*pdSD);
  4719. }
  4720. //----------------------------------------------------------------------------
  4721. //
  4722. // Function: Statistics
  4723. //
  4724. // Synopsis: Generate statistics data: average, total and square difference.
  4725. //
  4726. // Arguments: [pdData] - pointer to data
  4727. // [usItems] - Number of data items
  4728. // [pdAverage] - Average value of data
  4729. // [pdTotal] - Total value of data
  4730. // [pdSD] - Square difference of data
  4731. //
  4732. // Returns: None
  4733. //
  4734. // History: 6-Aug-1996 JiminLi Created
  4735. //
  4736. //-----------------------------------------------------------------------------
  4737. void Statistics(
  4738. LONG *plData,
  4739. USHORT usItems,
  4740. LONG *plAverage,
  4741. double *pdTotal,
  4742. double *pdSD)
  4743. {
  4744. USHORT usIndex = 0;
  4745. double dAverage;
  4746. double *pdData;
  4747. pdData = new double[usItems];
  4748. for (usIndex=0; usIndex<usItems; usIndex++)
  4749. {
  4750. pdData[usIndex] = plData[usIndex];
  4751. }
  4752. Statistics(pdData, usItems, &dAverage, pdTotal, pdSD);
  4753. *plAverage = (LONG)dAverage;
  4754. delete [] pdData;
  4755. }
  4756. //----------------------------------------------------------------------------
  4757. //
  4758. // Function: DiffTime
  4759. //
  4760. // Synopsis: Calculate and return the difference of two time.
  4761. //
  4762. // Arguments: [EndTime] - the time when an operation ended
  4763. // [StartTime] - the time when an operation started
  4764. //
  4765. // Returns: LONG
  4766. //
  4767. // History: 6-Aug-1996 JiminLi Created
  4768. //
  4769. //-----------------------------------------------------------------------------
  4770. LONG DiffTime(DWORD EndTime, DWORD StartTime)
  4771. {
  4772. LONG lResult = 0;
  4773. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DiffTime"));
  4774. DH_ASSERT(StartTime <= EndTime);
  4775. lResult = EndTime - StartTime;
  4776. return lResult;
  4777. }