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.

1937 lines
54 KiB

  1. //-------------------------------------------------------------------------
  2. // Microsoft OLE
  3. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  4. // All rights reserved.
  5. //
  6. // File: chancedf.cxx
  7. //
  8. // Contents: Implementation for ChanceDF object.
  9. //
  10. // Classes: ChanceDF
  11. //
  12. // Functions: ChanceDF (public)
  13. // ~ChanceDF (public)
  14. // CreateFromParams (public)
  15. // CreateFromSize, multiple (public)
  16. // CreateFromFile (public)
  17. // Create (public)
  18. // GetSeed (public)
  19. // Generate (protected)
  20. // GenerateRoot (protected)
  21. // Init, multiple (public)
  22. // ParseRange(protected)
  23. // DeleteChanceDocFileTree (public)
  24. // GetModes (public)
  25. // AppendChildNode (protected)
  26. // AppendSisterNode (protected)
  27. // DeleteChanceDocFileSubTree (protected)
  28. // GetDocFileNameFromCmdline (private)
  29. // GetRandomChanceNode (protected)
  30. // GetDepthOfNode (private)
  31. //
  32. // History: DeanE 12-Mar-96 Created
  33. // Narindk 20-Apr-96 Added more functions, enhanced.
  34. // BogdanT 30-Oct-96 Mac porting changes
  35. //--------------------------------------------------------------------------
  36. #include <dfheader.hxx>
  37. #pragma hdrstop
  38. // Debug object declaration
  39. DH_DECLARE;
  40. #define WSZ_DEF_VAL OLESTR("none")
  41. //--------------------------------------------------------------------------
  42. // Member: ChanceDF::ChanceDF, public
  43. //
  44. // Synopsis: Constructor. Initializes variables but real work is
  45. // done in ::Create*() methods. This method cannot fail.
  46. //
  47. // Arguments: None.
  48. //
  49. // Returns: Nothing.
  50. //
  51. // History: DeanE 12-Mar-96 Created
  52. //---------------------------------------------------------------------------
  53. ChanceDF::ChanceDF() : _pdgi(NULL),
  54. _pcnRoot(NULL),
  55. _pcdfd(NULL),
  56. _ptszName(NULL)
  57. {
  58. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF ctor"));
  59. }
  60. //+--------------------------------------------------------------------------
  61. // Member: ChanceDF::~ChanceDF, public
  62. //
  63. // Synopsis: Destructor. Frees memory and releases objects.
  64. //
  65. // Arguments: None.
  66. //
  67. // Returns: Nothing.
  68. //
  69. // History: DeanE 12-Mar-96 Created
  70. //---------------------------------------------------------------------------
  71. ChanceDF::~ChanceDF()
  72. {
  73. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF dtor"));
  74. if(NULL != _pcdfd)
  75. {
  76. delete _pcdfd;
  77. _pcdfd = NULL;
  78. }
  79. if(NULL != _pdgi)
  80. {
  81. delete _pdgi;
  82. _pdgi = NULL;
  83. }
  84. if(NULL != _ptszName)
  85. {
  86. delete _ptszName;
  87. _ptszName = NULL;
  88. }
  89. }
  90. //--------------------------------------------------------------------------
  91. // Member: ChanceDF::Init, public
  92. //
  93. // Synopsis: Initializes _pcdfd field in the ChanceDF object with default
  94. // values
  95. //
  96. // Arguments:
  97. //
  98. //
  99. // Returns: HRESULT
  100. //
  101. // History: t-leonr 26-Jul-97 Created
  102. //
  103. // Notes:
  104. //
  105. //---------------------------------------------------------------------------
  106. HRESULT ChanceDF::Init()
  107. {
  108. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::Init()"));
  109. if (NULL == _pcdfd)
  110. {
  111. _pcdfd = new CDFD;
  112. if (NULL == _pcdfd)
  113. {
  114. return(E_OUTOFMEMORY);
  115. }
  116. }
  117. _pcdfd->cDepthMin = 0;
  118. _pcdfd->cDepthMax = 2;
  119. _pcdfd->cStgMin = 0;
  120. _pcdfd->cStgMax = 3;
  121. _pcdfd->cStmMin = 0;
  122. _pcdfd->cStmMax = 5;
  123. _pcdfd->cbStmMin = 0;
  124. _pcdfd->cbStmMax = 5000;
  125. _pcdfd->ulSeed = 0;
  126. _pcdfd->dwRootMode = _pcdfd->dwStgMode = _pcdfd->dwStmMode =
  127. STGM_READWRITE |
  128. STGM_DIRECT |
  129. STGM_SHARE_EXCLUSIVE;
  130. return(S_OK);
  131. }
  132. //--------------------------------------------------------------------------
  133. // Member: ChanceDF::Init, public
  134. //
  135. // Synopsis: Initializes the _pcdfd field in the ChanceDF object with the
  136. // values passed in the pcdfd.
  137. //
  138. // Arguments: pcdfd
  139. //
  140. //
  141. // Returns: HRESULT
  142. //
  143. // History: t-leonr 26-Jul-97 Created
  144. //
  145. // Notes:
  146. //
  147. //---------------------------------------------------------------------------
  148. HRESULT ChanceDF::Init(CDFD *pcdfd)
  149. {
  150. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::Init(pcdfd)"));
  151. if (NULL == _pcdfd)
  152. {
  153. _pcdfd = new CDFD;
  154. if (NULL == _pcdfd)
  155. {
  156. return(E_OUTOFMEMORY);
  157. }
  158. }
  159. memcpy(_pcdfd, pcdfd, sizeof(CDFD));
  160. return (S_OK);
  161. }
  162. //--------------------------------------------------------------------------
  163. // Member: ChanceDF::CreateFromParams, public
  164. //
  165. // Synopsis: Creates the DocFile from the command line parameters.
  166. //
  167. // Arguments: [argc]
  168. // [argv]
  169. //
  170. // Returns: HRESULT
  171. //
  172. // History: DeanE 12-Mar-96 Created
  173. // Narindk 20-Apr-96 Enhanced
  174. // t-leonr 27-Jul-97 Add stuff about Init()
  175. //
  176. // Notes:
  177. // Precedence of switches in the event of conflicts:
  178. // 1) /dfsize:tiny, huge, etc
  179. // 2) /dftemp:<template file name>
  180. // 3) /dfdepth:min-max /dfstg:min-max /dfstm:min-max
  181. // /dfstmlen:min-max
  182. // 4) /dfRootMode:<mode> /dfStgMode:<mode> /dfStmMode:<mode>
  183. // 5) /dfname:name for Root DocFile
  184. //
  185. //---------------------------------------------------------------------------
  186. HRESULT ChanceDF::CreateFromParams(int argc, char **argv, LPTSTR ptName)
  187. {
  188. HRESULT hr = E_FAIL;
  189. int nErr;
  190. LPTSTR ptszCmdSize = NULL;
  191. LPTSTR ptszCmdDepth = NULL;
  192. LPTSTR ptszCmdStg = NULL;
  193. LPTSTR ptszCmdStm = NULL;
  194. LPTSTR ptszCmdTemp = NULL;
  195. LPTSTR ptszCmdStmLen = NULL;
  196. LPTSTR ptszCmdName = NULL;
  197. LPTSTR ptszCmdRootMode = NULL;
  198. LPTSTR ptszCmdStgMode = NULL;
  199. LPTSTR ptszCmdStmMode = NULL;
  200. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::CreateFromParams"));
  201. if (NULL == _pcdfd)
  202. {
  203. hr = Init();
  204. DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
  205. if (FAILED(hr))
  206. {
  207. return hr;
  208. }
  209. }
  210. CBaseCmdlineObj cmdOpenDF(OLESTR("Distrib"), OLESTR(""), WSZ_DEF_VAL);
  211. CBaseCmdlineObj cmdSize (OLESTR("dfsize"), OLESTR(""), WSZ_DEF_VAL);
  212. CBaseCmdlineObj cmdDepth (OLESTR("dfdepth"), OLESTR(""), WSZ_DEF_VAL);
  213. CBaseCmdlineObj cmdStg (OLESTR("dfstg"), OLESTR(""), WSZ_DEF_VAL);
  214. CBaseCmdlineObj cmdStm (OLESTR("dfstm"), OLESTR(""), WSZ_DEF_VAL);
  215. CBaseCmdlineObj cmdStmLen(OLESTR("dfstmlen"),OLESTR(""), WSZ_DEF_VAL);
  216. CBaseCmdlineObj cmdTemp (OLESTR("dftemp"), OLESTR(""), WSZ_DEF_VAL);
  217. CUlongCmdlineObj cmdSeed (OLESTR("seed"), OLESTR(""), _TEXTN("0"));
  218. CBaseCmdlineObj cmdName (OLESTR("dfname"), OLESTR(""), WSZ_DEF_VAL);
  219. CBaseCmdlineObj cmdRootMode (OLESTR("dfRootMode"), OLESTR(""), WSZ_DEF_VAL);
  220. CBaseCmdlineObj cmdStgMode (OLESTR("dfStgMode"), OLESTR(""), WSZ_DEF_VAL);
  221. CBaseCmdlineObj cmdStmMode (OLESTR("dfStmMode"), OLESTR(""), WSZ_DEF_VAL);
  222. CBaseCmdlineObj *aAllArgs[] = {
  223. &cmdOpenDF,
  224. &cmdSize,
  225. &cmdDepth,
  226. &cmdStg,
  227. &cmdStm,
  228. &cmdStmLen,
  229. &cmdTemp,
  230. &cmdSeed,
  231. &cmdName,
  232. &cmdRootMode,
  233. &cmdStgMode,
  234. &cmdStmMode
  235. };
  236. CCmdline cmdline(argc, argv);
  237. nErr = cmdline.QueryError();
  238. if (CMDLINE_NO_ERROR != nErr)
  239. {
  240. DH_TRACE((DH_LVL_ERROR,_TEXT("CCmdline creation error = %d"),nErr));
  241. goto CleanUpExit;
  242. }
  243. // Parse the actual arguments
  244. // ignore any extra parameters; last param==FALSE will
  245. // do this
  246. //
  247. nErr = cmdline.Parse(aAllArgs,
  248. sizeof(aAllArgs)/sizeof(CBaseCmdlineObj *),
  249. FALSE);
  250. if (CMDLINE_NO_ERROR != nErr)
  251. {
  252. DH_TRACE((DH_LVL_ERROR,
  253. _TEXT("Command line parsing error = %d"),
  254. nErr));
  255. goto CleanUpExit;
  256. }
  257. // Initialize the seed value first - we'll always have a value
  258. // for this
  259. //
  260. if (0 != *cmdSeed.GetValue())
  261. {
  262. // only set seed from cmdline if it has not been put
  263. // into the cdfd earlier. (permits repro with new testdriver)
  264. if (0 == _pcdfd->ulSeed || -1 == _pcdfd->ulSeed)
  265. {
  266. _pcdfd->ulSeed = *cmdSeed.GetValue();
  267. }
  268. }
  269. // Next, hunt for arguments we actually got
  270. // Are we creating our docfile to test?
  271. _uOpenCreateDF = FL_DISTRIB_NONE;
  272. if (TRUE == cmdOpenDF.IsFound ())
  273. {
  274. LPTSTR ptszCmdOpen;
  275. //Convert OLECHAR to TCHAR
  276. hr = OleStringToTString (cmdOpenDF.GetValue (), &ptszCmdOpen);
  277. DH_HRCHECK (hr, TEXT("OleStringToTString"));
  278. if (S_OK == hr)
  279. {
  280. if (NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_OPEN)) ||
  281. NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_OPENNODELETE)))
  282. {
  283. _uOpenCreateDF = FL_DISTRIB_OPEN;
  284. }
  285. else if (NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_CREATE)))
  286. {
  287. _uOpenCreateDF = FL_DISTRIB_CREATE;
  288. }
  289. }
  290. delete ptszCmdOpen;
  291. ptszCmdOpen = 0;
  292. }
  293. // Initialize the mode values
  294. if(0 != olestrcmp(cmdRootMode.GetValue(), WSZ_DEF_VAL))
  295. {
  296. if(NULL != *cmdRootMode.GetValue())
  297. {
  298. //Convert OLECHAR to TCHAR
  299. hr = OleStringToTString(cmdRootMode.GetValue(), &ptszCmdRootMode);
  300. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  301. if(S_OK == hr)
  302. {
  303. hr = GetModes(&(_pcdfd->dwRootMode), ptszCmdRootMode);
  304. DH_HRCHECK(hr, TEXT("GetModes - dwRootMode")) ;
  305. }
  306. }
  307. if (FAILED(hr))
  308. {
  309. goto CleanUpExit;
  310. }
  311. }
  312. if(0 != olestrcmp(cmdStgMode.GetValue(), WSZ_DEF_VAL))
  313. {
  314. if(NULL != *cmdStgMode.GetValue())
  315. {
  316. //Convert OLECHAR to TCHAR
  317. hr = OleStringToTString(cmdStgMode.GetValue(), &ptszCmdStgMode);
  318. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  319. if(S_OK == hr)
  320. {
  321. hr = GetModes(&(_pcdfd->dwStgMode), ptszCmdStgMode);
  322. DH_HRCHECK(hr, TEXT("GetModes - dwStgMode")) ;
  323. }
  324. }
  325. if (FAILED(hr))
  326. {
  327. goto CleanUpExit;
  328. }
  329. }
  330. if(0 != olestrcmp(cmdStmMode.GetValue(), WSZ_DEF_VAL))
  331. {
  332. if(NULL != *cmdStmMode.GetValue())
  333. {
  334. //Convert OLECHAR to TCHAR
  335. hr = OleStringToTString(cmdStmMode.GetValue(), &ptszCmdStmMode);
  336. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  337. if(S_OK == hr)
  338. {
  339. hr = GetModes(&(_pcdfd->dwStmMode), ptszCmdStmMode);
  340. DH_HRCHECK(hr, TEXT("GetModes - dwStmMode")) ;
  341. }
  342. }
  343. if (FAILED(hr))
  344. {
  345. goto CleanUpExit;
  346. }
  347. }
  348. // Initialize the name value
  349. if(0 != olestrcmp(cmdName.GetValue(), WSZ_DEF_VAL))
  350. {
  351. if(NULL != *cmdName.GetValue())
  352. {
  353. //Convert OLECHAR to TCHAR
  354. hr = OleStringToTString(cmdName.GetValue(), &ptszCmdName);
  355. DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
  356. }
  357. if (FAILED(hr))
  358. {
  359. goto CleanUpExit;
  360. }
  361. }
  362. // if nothing on cmdline, put in what was given to us
  363. if (NULL != ptName && NULL == ptszCmdName)
  364. {
  365. ptszCmdName = new TCHAR[_tcslen (ptName) + 1];
  366. if (NULL != ptszCmdName)
  367. {
  368. _tcscpy (ptszCmdName, ptName);
  369. }
  370. }
  371. // Check if dfsize or dftemp given on command line - the call appropriate
  372. // functions
  373. if(0 != olestrcmp(cmdSize.GetValue(), WSZ_DEF_VAL))
  374. {
  375. if(NULL != *cmdSize.GetValue())
  376. {
  377. hr = OleStringToTString(cmdSize.GetValue(), &ptszCmdSize);
  378. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  379. if(S_OK == hr)
  380. {
  381. hr = CreateFromSize(
  382. ptszCmdSize,
  383. _pcdfd->ulSeed,
  384. _pcdfd->dwRootMode, // non existing values
  385. _pcdfd->dwStgMode, // for seed and modes
  386. _pcdfd->dwStmMode,
  387. ptszCmdName);
  388. goto CleanUpExit;
  389. }
  390. }
  391. if (FAILED(hr))
  392. {
  393. goto CleanUpExit;
  394. }
  395. }
  396. else
  397. if(0 != olestrcmp(cmdTemp.GetValue(), WSZ_DEF_VAL))
  398. {
  399. if(NULL != *cmdTemp.GetValue())
  400. {
  401. //Convert OLECHAR to TCHAR
  402. hr = OleStringToTString(cmdTemp.GetValue(), &ptszCmdTemp);
  403. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  404. if(S_OK == hr)
  405. {
  406. hr = CreateFromFile(ptszCmdTemp, _pcdfd->ulSeed);
  407. goto CleanUpExit;
  408. }
  409. }
  410. if (FAILED(hr))
  411. {
  412. goto CleanUpExit;
  413. }
  414. }
  415. // If a size or template file were not specified, we'll need to
  416. // hunt for specific values on the command line, using defaults
  417. // for any we don't get
  418. //
  419. if(0 != olestrcmp(cmdDepth.GetValue(), WSZ_DEF_VAL))
  420. {
  421. if(NULL != *cmdDepth.GetValue())
  422. {
  423. //Convert OLECHAR to TCHAR
  424. hr = OleStringToTString(cmdDepth.GetValue(), &ptszCmdDepth);
  425. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  426. if(S_OK == hr)
  427. {
  428. hr = ParseRange(ptszCmdDepth, &(_pcdfd->cDepthMin), &(_pcdfd->cDepthMax));
  429. DH_HRCHECK(hr, TEXT("ParseRange - cmdDepth")) ;
  430. }
  431. }
  432. if (FAILED(hr))
  433. {
  434. goto CleanUpExit;
  435. }
  436. }
  437. if(0 != olestrcmp(cmdStg.GetValue(), WSZ_DEF_VAL))
  438. {
  439. if(NULL != *cmdStg.GetValue())
  440. {
  441. //Convert OLECHAR to TCHAR
  442. hr = OleStringToTString(cmdStg.GetValue(), &ptszCmdStg);
  443. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  444. if(S_OK == hr)
  445. {
  446. hr = ParseRange(ptszCmdStg, &(_pcdfd->cStgMin), &(_pcdfd->cStgMax));
  447. DH_HRCHECK(hr, TEXT("ParseRange - cmdStg")) ;
  448. }
  449. }
  450. if (FAILED(hr))
  451. {
  452. goto CleanUpExit;
  453. }
  454. }
  455. if(0 != olestrcmp(cmdStm.GetValue(), WSZ_DEF_VAL))
  456. {
  457. if(NULL != *cmdStm.GetValue())
  458. {
  459. //Convert OLECHAR to TCHAR
  460. hr = OleStringToTString(cmdStm.GetValue(), &ptszCmdStm);
  461. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  462. if(S_OK == hr)
  463. {
  464. hr = ParseRange(ptszCmdStm, &(_pcdfd->cStmMin), &(_pcdfd->cStmMax));
  465. DH_HRCHECK(hr, TEXT("ParseRange - cmdStm")) ;
  466. }
  467. }
  468. if (FAILED(hr))
  469. {
  470. goto CleanUpExit;
  471. }
  472. }
  473. if(0 != olestrcmp(cmdStmLen.GetValue(), WSZ_DEF_VAL))
  474. {
  475. if(NULL != *cmdStmLen.GetValue())
  476. {
  477. //Convert OLECHAR to TCHAR
  478. hr = OleStringToTString(cmdStmLen.GetValue(), &ptszCmdStmLen);
  479. DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
  480. if(S_OK == hr)
  481. {
  482. hr = ParseRange(ptszCmdStmLen, &(_pcdfd->cbStmMin), &(_pcdfd->cbStmMax));
  483. DH_HRCHECK(hr, TEXT("ParseRange - cmdStmLen")) ;
  484. }
  485. }
  486. if (FAILED(hr))
  487. {
  488. goto CleanUpExit;
  489. }
  490. }
  491. hr = Create(NULL, ptszCmdName);
  492. DH_HRCHECK(hr, TEXT("Create")) ;
  493. CleanUpExit:
  494. // Clean up
  495. if(NULL != ptszCmdSize)
  496. {
  497. delete ptszCmdSize;
  498. ptszCmdSize =NULL;
  499. }
  500. if(NULL != ptszCmdDepth)
  501. {
  502. delete ptszCmdDepth;
  503. ptszCmdDepth =NULL;
  504. }
  505. if(NULL != ptszCmdStg)
  506. {
  507. delete ptszCmdStg;
  508. ptszCmdStg =NULL;
  509. }
  510. if(NULL != ptszCmdStm)
  511. {
  512. delete ptszCmdStm;
  513. ptszCmdStm =NULL;
  514. }
  515. if(NULL != ptszCmdStmLen)
  516. {
  517. delete ptszCmdStmLen;
  518. ptszCmdStmLen =NULL;
  519. }
  520. if(NULL != ptszCmdName)
  521. {
  522. delete ptszCmdName;
  523. ptszCmdName =NULL;
  524. }
  525. if(NULL != ptszCmdRootMode)
  526. {
  527. delete ptszCmdRootMode;
  528. ptszCmdRootMode =NULL;
  529. }
  530. if(NULL != ptszCmdStgMode)
  531. {
  532. delete ptszCmdStgMode;
  533. ptszCmdStgMode =NULL;
  534. }
  535. if(NULL != ptszCmdStmMode)
  536. {
  537. delete ptszCmdStmMode;
  538. ptszCmdStmMode =NULL;
  539. }
  540. return(hr);
  541. }
  542. //+--------------------------------------------------------------------------
  543. // Member: ChanceDF::CreateFromSize, public
  544. //
  545. // Synopsis: Creates the DocFile from size option
  546. //
  547. // Arguments: [tszSize] - Size of DocFile. Must be given.
  548. // [ulSeed] - Seed value.
  549. // [dwRootMode] - Mode for Root Storage.
  550. // [dwStgMode] - Mode for IStorage(s).
  551. // [dwStmMode] - Mode for IStream(s).
  552. // [ptszDocName] - Name of DocFile.
  553. //
  554. // Returns: HRESULT
  555. //
  556. // History: DeanE 12-Mar-96 Created
  557. // Narindk 2-July-96 Enhanced
  558. //
  559. // Notes: If the value for dwRootMode/dwStgMode/dwStmMode are not given
  560. // i.e. zero, then default values for the modes would be used.
  561. // If ptszDocName is NULL, then a random name is chosen for Doc
  562. // File in VirtualDF creation.
  563. //---------------------------------------------------------------------------
  564. HRESULT ChanceDF::CreateFromSize(
  565. LPCTSTR tszSize,
  566. ULONG ulSeed,
  567. DWORD dwRootMode,
  568. DWORD dwStgMode,
  569. DWORD dwStmMode,
  570. LPTSTR ptszDocName)
  571. {
  572. DFSIZE dfs = DF_ERROR;
  573. DH_FUNCENTRY(NULL,
  574. DH_LVL_DFLIB,
  575. _TEXT("ChanceDF::CreateFromSize - string"));
  576. DH_ASSERT(NULL != tszSize);
  577. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_TINY))
  578. {
  579. dfs = DF_TINY;
  580. }
  581. else
  582. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_SMALL))
  583. {
  584. dfs = DF_SMALL;
  585. }
  586. else
  587. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_MEDIUM))
  588. {
  589. dfs = DF_MEDIUM;
  590. }
  591. else
  592. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_LARGE))
  593. {
  594. dfs = DF_LARGE;
  595. }
  596. else
  597. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_HUGE))
  598. {
  599. dfs = DF_HUGE;
  600. }
  601. else
  602. if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_DIF))
  603. {
  604. dfs = DF_DIF;
  605. }
  606. if (DF_ERROR == dfs)
  607. {
  608. return(E_FAIL);
  609. }
  610. return(CreateFromSize(
  611. dfs,
  612. ulSeed,
  613. dwRootMode,
  614. dwStgMode,
  615. dwStmMode,
  616. ptszDocName));
  617. }
  618. //+--------------------------------------------------------------------------
  619. // Member: ChanceDF::CreateFromSize, public
  620. //
  621. // Synopsis: Creates DocFile from size option.
  622. //
  623. // Arguments: [dfs] - DocFile size.
  624. // [ulSeed] - Seed value.
  625. // [dwRootMode] - Mode for Root Storage.
  626. // [dwStgMode] - Mode for IStorage(s).
  627. // [dwStmMode] - Mode for IStream(s).
  628. // [ptszDocName] - Name of DocFile.
  629. //
  630. // Returns: HRESULT
  631. //
  632. // History: DeanE 12-Mar-96 Created
  633. // Narindk 20-Apr-96 Enhanced
  634. // t-leonr 27-Jul-97 Add stuff about Init(), use _pcdfd
  635. //
  636. // Notes: If the value for dwRootMode/dwStgMode/dwStmMode are not given
  637. // i.e. zero, then default values for the modes would be used.
  638. // If ptszDocName is NULL, then a random name is chosen for Doc
  639. // File in VirtualDF creation.
  640. //---------------------------------------------------------------------------
  641. HRESULT ChanceDF::CreateFromSize(
  642. DFSIZE dfs,
  643. ULONG ulSeed,
  644. DWORD dwRootMode,
  645. DWORD dwStgMode,
  646. DWORD dwStmMode,
  647. LPTSTR ptszDocName)
  648. {
  649. HRESULT hr = S_OK;
  650. DH_FUNCENTRY(&hr,
  651. DH_LVL_DFLIB,
  652. _TEXT("ChanceDF::CreateFromSize - dfs"));
  653. if (NULL == _pcdfd)
  654. {
  655. hr = Init();
  656. DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
  657. if (FAILED(hr))
  658. {
  659. return hr;
  660. }
  661. }
  662. _pcdfd->ulSeed = ulSeed;
  663. if(0 == dwRootMode)
  664. {
  665. _pcdfd->dwRootMode = STGM_READWRITE |
  666. STGM_DIRECT |
  667. STGM_SHARE_EXCLUSIVE;
  668. }
  669. else
  670. {
  671. _pcdfd->dwRootMode = dwRootMode;
  672. }
  673. if(0 == dwStgMode)
  674. {
  675. _pcdfd->dwStgMode = STGM_READWRITE |
  676. STGM_DIRECT |
  677. STGM_SHARE_EXCLUSIVE;
  678. }
  679. else
  680. {
  681. _pcdfd->dwStgMode = dwStgMode;
  682. }
  683. if(0 == dwStmMode)
  684. {
  685. _pcdfd->dwStmMode = STGM_READWRITE |
  686. STGM_DIRECT |
  687. STGM_SHARE_EXCLUSIVE;
  688. }
  689. else
  690. {
  691. _pcdfd->dwStmMode = dwStmMode;
  692. }
  693. switch (dfs)
  694. {
  695. case DF_TINY:
  696. _pcdfd->cDepthMin = 0;
  697. _pcdfd->cDepthMax = 0;
  698. _pcdfd->cStgMin = 0;
  699. _pcdfd->cStgMax = 0;
  700. _pcdfd->cStmMin = 0;
  701. _pcdfd->cStmMax = 3;
  702. _pcdfd->cbStmMin = 0;
  703. _pcdfd->cbStmMax = 100;
  704. break;
  705. case DF_SMALL:
  706. _pcdfd->cDepthMin = 0;
  707. _pcdfd->cDepthMax = 1;
  708. _pcdfd->cStgMin = 0;
  709. _pcdfd->cStgMax = 1;
  710. _pcdfd->cStmMin = 0;
  711. _pcdfd->cStmMax = 5;
  712. _pcdfd->cbStmMin = 0;
  713. _pcdfd->cbStmMax = 4000;
  714. break;
  715. case DF_MEDIUM:
  716. _pcdfd->cDepthMin = 1;
  717. _pcdfd->cDepthMax = 3;
  718. _pcdfd->cStgMin = 1;
  719. _pcdfd->cStgMax = 4;
  720. _pcdfd->cStmMin = 1;
  721. _pcdfd->cStmMax = 6;
  722. _pcdfd->cbStmMin = 0;
  723. _pcdfd->cbStmMax = 10240;
  724. break;
  725. case DF_LARGE:
  726. _pcdfd->cDepthMin = 2;
  727. _pcdfd->cDepthMax = 5;
  728. _pcdfd->cStgMin = 2;
  729. _pcdfd->cStgMax = 10;
  730. _pcdfd->cStmMin = 0;
  731. _pcdfd->cStmMax = 8;
  732. _pcdfd->cbStmMin = 0;
  733. _pcdfd->cbStmMax = 20480;
  734. break;
  735. case DF_HUGE:
  736. _pcdfd->cDepthMin = 5;
  737. _pcdfd->cDepthMax = 10;
  738. _pcdfd->cStgMin = 5;
  739. _pcdfd->cStgMax = 30;
  740. _pcdfd->cStmMin = 0;
  741. _pcdfd->cStmMax = 10;
  742. _pcdfd->cbStmMin = 0;
  743. _pcdfd->cbStmMax = 40000;
  744. break;
  745. case DF_DIF:
  746. _pcdfd->cDepthMin = 5;
  747. _pcdfd->cDepthMax = 10;
  748. _pcdfd->cStgMin = 7;
  749. _pcdfd->cStgMax = 10;
  750. _pcdfd->cStmMin = 10;
  751. _pcdfd->cStmMax = 15;
  752. _pcdfd->cbStmMin = 100000;
  753. _pcdfd->cbStmMax = 150000;
  754. break;
  755. case DF_ERROR: // Fall through to error condition
  756. default:
  757. hr = E_FAIL;
  758. break;
  759. }
  760. if (SUCCEEDED(hr))
  761. {
  762. hr = Create(NULL, ptszDocName);
  763. DH_HRCHECK(hr, TEXT("Create")) ;
  764. }
  765. return(hr);
  766. }
  767. //+--------------------------------------------------------------------------
  768. // Member: ChanceDF::CreateFromFile, public
  769. //
  770. // Synopsis: Creates DocFile through a given ini file.
  771. //
  772. // Arguments: [tszIni]
  773. // [ulSeed]
  774. //
  775. // Returns: HRESULT
  776. //
  777. // History: DeanE 12-Mar-96 Created
  778. //---------------------------------------------------------------------------
  779. HRESULT ChanceDF::CreateFromFile(
  780. LPCTSTR /* UNREF tszIni */,
  781. ULONG /* UNREF ulSeed */)
  782. {
  783. DH_FUNCENTRY(NULL,
  784. DH_LVL_DFLIB,
  785. _TEXT("ChanceDF::CreateFromFile - NYI!"));
  786. DH_ASSERT(!_TEXT("::CreateFromFile NYI!"));
  787. return(E_FAIL);
  788. }
  789. //+--------------------------------------------------------------------------
  790. // Member: ChanceDF::Create, public
  791. //
  792. // Synopsis: Creates the ChanceDocFile tree.
  793. //
  794. // Arguments: [pcdfd] - pointer to CDFD structure.
  795. // [ptszDocName] - Name for DocFile. May be NULL.
  796. //
  797. // Returns: HRESULT
  798. //
  799. // History: DeanE 12-Mar-96 Created
  800. // t-leonr 27-Jul-97 Add stuff about Init()
  801. //
  802. // Notes: Destructor will clean up a partially-created object so we
  803. // don't have to do a bunch of cleanup as we go
  804. //
  805. // If ptszDocName is NULL, then a random name is chosen for Doc
  806. // File in VirtualDF creation.
  807. //---------------------------------------------------------------------------
  808. HRESULT ChanceDF::Create(CDFD *pcdfd, LPTSTR ptszDocName)
  809. {
  810. HRESULT hr = S_OK;
  811. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::Create"));
  812. if (NULL != pcdfd)
  813. {
  814. hr = Init(pcdfd);
  815. DH_HRCHECK(hr, TEXT("ChanceDF::Init(pcdfd)"));
  816. }
  817. else if (NULL == _pcdfd)
  818. {
  819. hr = Init();
  820. DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
  821. }
  822. if (FAILED(hr))
  823. {
  824. return hr;
  825. }
  826. // Create a DataGen object that will allow us to fill the count
  827. // parameters of all the ChanceDF components
  828. //
  829. _pdgi = new DG_INTEGER(_pcdfd->ulSeed);
  830. if (NULL == _pdgi)
  831. {
  832. return(E_OUTOFMEMORY);
  833. }
  834. // Store the actual seed value we used to create this tree - we'll
  835. // need it to initialize other DG objects later
  836. //
  837. _pdgi->GetSeed(&_pcdfd->ulSeed);
  838. // Report the Seed value so this structure can be recreated
  839. DH_LOG((LOG_INFO, _TEXT("ChanceDF::Create - Seed=%lu"), _pcdfd->ulSeed));
  840. // Finally, we must generate the ChanceDF tree
  841. hr = Generate();
  842. DH_HRCHECK(hr, TEXT("Generate")) ;
  843. //Store the name of docfile, if provided by user.
  844. if((S_OK == hr) && (NULL != ptszDocName))
  845. {
  846. hr = GetDocFileNameFromCmdline(ptszDocName);
  847. DH_HRCHECK(hr, TEXT("GetDocFileNameFromCmdline")) ;
  848. }
  849. return(hr);
  850. }
  851. //+--------------------------------------------------------------------------
  852. // Member: ChanceDF::ParseRange, public
  853. //
  854. // Synopsis: Parses the range given from command line for different params.
  855. //
  856. // Arguments: [tszSwitch]
  857. // [pulMin]
  858. // [pulMax]
  859. //
  860. // Returns: HRESULT
  861. //
  862. // History: DeanE 12-Mar-96 Created
  863. // Narindk 20-Apr-96 Enhanced
  864. //
  865. // Notes: tszSwitch is of the format '/switch:min-max
  866. //---------------------------------------------------------------------------
  867. HRESULT ChanceDF::ParseRange(LPCTSTR tszSwitch, ULONG *pulMin, ULONG *pulMax)
  868. {
  869. HRESULT hr = E_FAIL;
  870. LPCTSTR ptszMin = tszSwitch;
  871. LPCTSTR ptszMax = tszSwitch;
  872. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::ParseRange"));
  873. DH_ASSERT(NULL != tszSwitch);
  874. DH_ASSERT(NULL != pulMin);
  875. DH_ASSERT(NULL != pulMax);
  876. // Advance the maximum pointer past the dash delimeter after
  877. // the minimum value
  878. //
  879. ptszMax = ptszMin;
  880. while ((*ptszMax != L'\0') && (*ptszMax++ != L'-'))
  881. {
  882. ;
  883. }
  884. // If neither of our pointers is pointing at the null
  885. // terminator, we can safely get the values
  886. //
  887. if ((L'\0' != *ptszMin) && (L'\0' != *ptszMax))
  888. {
  889. *pulMin = _ttol(ptszMin);
  890. *pulMax = _ttol(ptszMax);
  891. if (*pulMin <= *pulMax)
  892. {
  893. hr = S_OK;
  894. }
  895. }
  896. return (hr);
  897. }
  898. //+--------------------------------------------------------------------------
  899. // Member: ChanceDF::Generate, protected
  900. //
  901. // Synopsis: Generates the ChanceDocFile tree consisting of ChanceNodes.
  902. //
  903. // Arguments: void
  904. //
  905. // Returns: HRESULT
  906. //
  907. // History: DeanE 12-Mar-96 Created
  908. // Narindk 20-Apr-96 Enhanced
  909. // Notes:
  910. // Check the creation parameters
  911. // Generate the first child node at each level
  912. // Choose children nodes randomly to create additional siblings,
  913. // or children, if necessary. In growing the chance docfile tree,
  914. // take care not to make sister of root node and do not increase
  915. // depth of the tree by making child of nodes at max depth.
  916. //
  917. // Called privately by public creation methods
  918. //
  919. //---------------------------------------------------------------------------
  920. HRESULT ChanceDF::Generate()
  921. {
  922. HRESULT hr = E_FAIL;
  923. ULONG cDepth = 0;
  924. ULONG cRemStg = 0;
  925. USHORT usErr = 0;
  926. ChanceNode **apcnFirstBorn = NULL;
  927. ChanceNode *pcnRemStg = NULL;
  928. ULONG ulLoop;
  929. ChanceNode *pcnOldNode = NULL;
  930. UINT cTypeNode = 0;
  931. ULONG cNumOfNodes = 0;
  932. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::Generate"));
  933. // Sanity check parameters
  934. // minimums for each category must be <= maximums
  935. // must have at least as many storages as the minimum depth
  936. // must have at least as many storages as the maximum depth
  937. //
  938. if ((_pcdfd->cDepthMin > _pcdfd->cDepthMax) ||
  939. (_pcdfd->cStgMin > _pcdfd->cStgMax) ||
  940. (_pcdfd->cStmMin > _pcdfd->cStmMax) ||
  941. (_pcdfd->cbStmMin > _pcdfd->cbStmMax) ||
  942. (_pcdfd->cDepthMin > _pcdfd->cStgMin) ||
  943. (_pcdfd->cDepthMax > _pcdfd->cStgMax))
  944. {
  945. goto ErrExit;
  946. }
  947. // Determine the exact depth of the docfile
  948. //
  949. usErr = _pdgi->Generate(&cDepth, _pcdfd->cDepthMin, _pcdfd->cDepthMax);
  950. if (DG_RC_SUCCESS != usErr)
  951. {
  952. hr = E_FAIL;
  953. goto ErrExit;
  954. }
  955. // Adjust minimum and maximum number of storages to create down
  956. // by the number that would be created by cDepth.
  957. //
  958. _pcdfd->cStgMin = max(0, (LONG)(_pcdfd->cStgMin-cDepth));
  959. _pcdfd->cStgMax = max(0, (LONG)(_pcdfd->cStgMax-cDepth));
  960. // Calculate the number of extra storages to create
  961. //
  962. usErr = _pdgi->Generate(&cRemStg, _pcdfd->cStgMin, _pcdfd->cStgMax);
  963. if (DG_RC_SUCCESS != usErr)
  964. {
  965. hr = E_FAIL;
  966. goto ErrExit;
  967. }
  968. // Check if cDepth is zero, but cRemStg is >0, then make cDepth atleast 1,
  969. // becoz' we wouldn't have siblings of root.
  970. cDepth = ((cDepth == 0 && cRemStg > 0) ? 1 : cDepth);
  971. // Allocate a table of pointers to the first children at each
  972. // level
  973. //
  974. apcnFirstBorn = new ChanceNode*[cDepth+1];
  975. if (NULL == apcnFirstBorn)
  976. {
  977. hr = E_OUTOFMEMORY;
  978. goto ErrExit;
  979. }
  980. // Create root node - if this succeeds, we point our root
  981. // to it and if any subsequent errors occur while building the
  982. // rest of the tree the destructor will clean it up
  983. //
  984. hr = GenerateRoot();
  985. DH_HRCHECK(hr, TEXT("GenerateRoot")) ;
  986. if (FAILED(hr))
  987. {
  988. goto ErrExit;
  989. }
  990. apcnFirstBorn[0] = _pcnRoot;
  991. // Create levels of children nodes
  992. //
  993. hr = S_OK;
  994. ulLoop = 1;
  995. while ((ulLoop<=cDepth) && SUCCEEDED(hr))
  996. {
  997. hr = AppendChildNode(&apcnFirstBorn[ulLoop], apcnFirstBorn[ulLoop-1]);
  998. DH_HRCHECK(hr, TEXT("AppendChildNode")) ;
  999. ulLoop++;
  1000. }
  1001. if (FAILED(hr))
  1002. {
  1003. goto ErrExit;
  1004. }
  1005. // Now, fill in any remaining storage nodes that we need to
  1006. //
  1007. cNumOfNodes = ulLoop;
  1008. ulLoop = 0;
  1009. while ((ulLoop<cRemStg) && SUCCEEDED(hr))
  1010. {
  1011. usErr = _pdgi->Generate(&cTypeNode, SISTERNODE, CHILDNODE);
  1012. if (DG_RC_SUCCESS != usErr)
  1013. {
  1014. hr = E_FAIL;
  1015. }
  1016. if(S_OK == hr)
  1017. {
  1018. hr = GetRandomChanceNode(cNumOfNodes, &pcnOldNode);
  1019. DH_HRCHECK(hr, TEXT("FindRandomChanceNode")) ;
  1020. }
  1021. if (SUCCEEDED(hr))
  1022. {
  1023. // In growing the chance docfile tree, take care not to make
  1024. // sister of root node and do not increase max depth of the tree
  1025. // by making child of nodes at max depth.
  1026. if((SISTERNODE == cTypeNode) && (_pcnRoot != pcnOldNode))
  1027. {
  1028. hr = AppendSisterNode(&pcnRemStg, pcnOldNode);
  1029. DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
  1030. }
  1031. else
  1032. {
  1033. // Both conditons CHILDNODE == cTypeNode and
  1034. // ((SISTERNODE == cTypeNode) && (_pcnRoot == pcnOldNode))
  1035. // handled here
  1036. if(NULL == pcnOldNode->_pcnChild)
  1037. {
  1038. if(GetDepthOfNode(pcnOldNode) < cDepth)
  1039. {
  1040. hr = AppendChildNode(&pcnRemStg, pcnOldNode);
  1041. DH_HRCHECK(hr, TEXT("AppendChildNode")) ;
  1042. }
  1043. else
  1044. {
  1045. hr = AppendSisterNode(&pcnRemStg, pcnOldNode);
  1046. DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
  1047. }
  1048. }
  1049. else
  1050. {
  1051. hr = AppendSisterNode(&pcnRemStg,pcnOldNode->_pcnChild);
  1052. DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
  1053. }
  1054. }
  1055. }
  1056. ulLoop++;
  1057. cNumOfNodes++;
  1058. }
  1059. ErrExit:
  1060. // All nodes are saved in the tree itself pointed to by _pcnRoot, and
  1061. // we can safely delete this temporary scaffolding
  1062. //
  1063. delete []apcnFirstBorn;
  1064. return(hr);
  1065. }
  1066. //+--------------------------------------------------------------------------
  1067. // Member: ChanceDF::GenerateRoot, protected
  1068. //
  1069. // Synopsis: Generates the root of ChanceDocFile tree.
  1070. //
  1071. // Arguments: void
  1072. //
  1073. // Returns: HRESULT
  1074. //
  1075. // History: DeanE 12-Mar-96 Created
  1076. // Narindk 20-Apr-96 Enhanced
  1077. //---------------------------------------------------------------------------
  1078. HRESULT ChanceDF::GenerateRoot()
  1079. {
  1080. USHORT usErr;
  1081. ULONG cStreams;
  1082. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRoot"));
  1083. // Generate the number of streams the root will have
  1084. usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
  1085. if (DG_RC_SUCCESS != usErr)
  1086. {
  1087. return(E_FAIL);
  1088. }
  1089. _pcnRoot = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
  1090. if (NULL == _pcnRoot)
  1091. {
  1092. return(E_OUTOFMEMORY);
  1093. }
  1094. return(S_OK);
  1095. }
  1096. //+--------------------------------------------------------------------------
  1097. // Member: ChanceDF::AppendChildNode, protected
  1098. //
  1099. // Synopsis: Appends the Child node to parent.
  1100. //
  1101. // Arguments: [ppcnNew]
  1102. // [pcnParent]
  1103. //
  1104. // Returns: HRESULT
  1105. //
  1106. // History: DeanE 12-Mar-96 Created
  1107. // Narindk 20-Apr-96 Enhanced
  1108. //
  1109. // Notes: Attach new node as a child of the parent node at the end of the
  1110. // end of parents child chain. If the parent is NULL, do nothing
  1111. // with this node.
  1112. //
  1113. //---------------------------------------------------------------------------
  1114. HRESULT ChanceDF::AppendChildNode(ChanceNode **ppcnNew, ChanceNode *pcnParent)
  1115. {
  1116. HRESULT hr = E_FAIL;
  1117. ULONG cStreams= 0;
  1118. USHORT usErr = 0;
  1119. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendChildNode"));
  1120. DH_ASSERT(NULL != pcnParent)
  1121. DH_ASSERT(NULL != ppcnNew);
  1122. *ppcnNew = NULL;
  1123. // Determine number of streams to create
  1124. usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
  1125. if (DG_RC_SUCCESS != usErr)
  1126. {
  1127. hr = E_FAIL;
  1128. goto ErrExit;
  1129. }
  1130. // Allocate and initialize the new node
  1131. *ppcnNew = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
  1132. if (NULL == *ppcnNew)
  1133. {
  1134. hr = E_OUTOFMEMORY;
  1135. goto ErrExit;
  1136. }
  1137. // Append the new node to the list of sisters in the parent
  1138. //
  1139. hr = pcnParent->AppendChildStorage(*ppcnNew);
  1140. DH_HRCHECK(hr, TEXT("AppendChildStorage")) ;
  1141. ErrExit:
  1142. if (FAILED(hr))
  1143. {
  1144. delete *ppcnNew;
  1145. *ppcnNew = NULL;
  1146. }
  1147. return(hr);
  1148. }
  1149. //+--------------------------------------------------------------------------
  1150. // Member: ChanceDF::AppendSisterNode, protected
  1151. //
  1152. // Synopsis: Appends the new node as sister of ChanceNode.
  1153. //
  1154. // Arguments: [ppcnNew]
  1155. // [pcnSister]
  1156. //
  1157. // Returns: HRESULT
  1158. //
  1159. // History: DeanE 12-Mar-96 Created
  1160. // Narindk 20-Apr-96 Enhanced
  1161. //---------------------------------------------------------------------------
  1162. HRESULT ChanceDF::AppendSisterNode(
  1163. ChanceNode **ppcnNew,
  1164. ChanceNode *pcnSister)
  1165. {
  1166. HRESULT hr = E_FAIL;
  1167. ULONG cStreams= 0;
  1168. USHORT usErr = 0;
  1169. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendSisterNode"));
  1170. DH_ASSERT(NULL != pcnSister)
  1171. DH_ASSERT(NULL != ppcnNew);
  1172. *ppcnNew = NULL;
  1173. // Determine number of streams to create
  1174. usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
  1175. if (DG_RC_SUCCESS != usErr)
  1176. {
  1177. hr = E_FAIL;
  1178. goto ErrExit;
  1179. }
  1180. // Allocate and initialize the new node
  1181. *ppcnNew = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
  1182. if (NULL == *ppcnNew)
  1183. {
  1184. hr = E_OUTOFMEMORY;
  1185. goto ErrExit;
  1186. }
  1187. // Append the new node to the list of sisters in the parent
  1188. //
  1189. hr = pcnSister->AppendSisterStorage(*ppcnNew);
  1190. DH_HRCHECK(hr, TEXT("AppendSisterStorage")) ;
  1191. ErrExit:
  1192. if (FAILED(hr))
  1193. {
  1194. delete *ppcnNew;
  1195. *ppcnNew = NULL;
  1196. }
  1197. return(hr);
  1198. }
  1199. //+--------------------------------------------------------------------------
  1200. // Member: ChanceDF::GetSeed, public
  1201. //
  1202. // Synopsis: Returns the seed value
  1203. //
  1204. // Arguments: void
  1205. //
  1206. // Returns: ULONG
  1207. //
  1208. // History: DeanE 12-Mar-96 Created
  1209. //---------------------------------------------------------------------------
  1210. ULONG ChanceDF::GetSeed()
  1211. {
  1212. ULONG ulSeed = 0;
  1213. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GetSeed"));
  1214. if (NULL != _pdgi)
  1215. {
  1216. _pdgi->GetSeed(&ulSeed);
  1217. }
  1218. return(ulSeed);
  1219. }
  1220. //+--------------------------------------------------------------------------
  1221. // Member: ChanceDF::DeleteChanceDocFileTree, public
  1222. //
  1223. // Synopsis: Deletes the ChanceDocFile tree
  1224. //
  1225. // Arguments: [pcnTrav] - Pointer to ChanceNode
  1226. //
  1227. // Returns: HRESULT
  1228. //
  1229. // History: Narindk 24-Apr-96 Created
  1230. //
  1231. // Notes: First step is to check if the whole tree needs to be deleted or
  1232. // just a part of it. In case only a part of tree is to be
  1233. // deleted, isolate the node from the remaining tree by readjusting
  1234. // the pointers in the remaining tree. Then call the function
  1235. // DeleteChanceDocFileSubTree to delete the subtree. In case,
  1236. // the complete tree needs to be deleted, we call the function
  1237. // DeleteChanceDocFileSubTree directly to delete the complete
  1238. // tree.
  1239. //---------------------------------------------------------------------------
  1240. HRESULT ChanceDF::DeleteChanceDocFileTree(ChanceNode *pcnTrav)
  1241. {
  1242. HRESULT hr = S_OK;
  1243. ChanceNode *pTempNode = NULL;
  1244. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("DeleteChanceDocFileTree"));
  1245. DH_VDATEPTRIN(pcnTrav, ChanceNode);
  1246. DH_ASSERT(NULL != pcnTrav);
  1247. if(S_OK == hr)
  1248. {
  1249. // This basically readjusts the tree, in case some other node except
  1250. // for root of ChanceDocFile tree is passed, so only a part of tree is
  1251. // getting deleted.
  1252. if(NULL != pcnTrav->_pcnParent)
  1253. {
  1254. // Find its previous node whose pointers would need readjustment.
  1255. pTempNode = pcnTrav->_pcnParent->_pcnChild;
  1256. while ((pcnTrav != pcnTrav->_pcnParent->_pcnChild) &&
  1257. (pcnTrav != pTempNode->_pcnSister))
  1258. {
  1259. pTempNode = pTempNode->_pcnSister;
  1260. DH_ASSERT(NULL != pTempNode);
  1261. }
  1262. // Readjust the child pointer or sister pointer as the case may be.
  1263. pcnTrav->_pcnParent->_pcnChild = (pcnTrav == pTempNode) ?
  1264. pcnTrav->_pcnSister : pcnTrav->_pcnParent->_pcnChild;
  1265. pTempNode->_pcnSister = pcnTrav->_pcnSister;
  1266. }
  1267. }
  1268. if(S_OK == hr)
  1269. {
  1270. // Call the function to delete the tree now.
  1271. hr = DeleteChanceDocFileSubTree(&pcnTrav);
  1272. DH_HRCHECK(hr, TEXT("DeleteChanceDocFileSubTree")) ;
  1273. }
  1274. return hr;
  1275. }
  1276. //--------------------------------------------------------------------------
  1277. // Member: ChanceDF::DeleteChanceDocFileSubTree, protected
  1278. //
  1279. // Synopsis: Does the real work of deletion of ChanceNodes in the tree.
  1280. //
  1281. // Arguments: [ppcnTrav] - Pointer to pointer to ChanceNode
  1282. //
  1283. // Returns: HRESULT
  1284. //
  1285. // History: Narindk 24-Apr-96 Created
  1286. //
  1287. // Notes: This function is called only through DeleteChanceDocFileTree.
  1288. //
  1289. // Assign the passed in ChanceNode to a variable pTempRoot.
  1290. // NULL the pTempRoot's parent.
  1291. // Loop till the pTempRoot is not NULL to delete tree ieratively.
  1292. // - Assign pTempRoot to a temp variable pTempNode.
  1293. // - Traverse the tree to make pTempNode point to last child
  1294. // (_pcnChild).
  1295. // - Assign pTempNode's _pcnParent to pTempRoot
  1296. // - Assign the pTempRoot's _pcnChild pointer to point to the
  1297. // sister of pTempNode's _pcnSister rather than to itself,
  1298. // therby isolating itself.
  1299. // - Decrement the _cStorages of pTempRoot (used to verify).
  1300. // - Assign pTempNode's _pcnSister to NULL.
  1301. // - Assert to ensure the pTempNode's _cStorages is zero
  1302. // before deleting it.
  1303. // - Delete pTempNode.
  1304. // - Go back to top of loop and repeat till all nodes are
  1305. // deleted.
  1306. //---------------------------------------------------------------------------
  1307. HRESULT ChanceDF::DeleteChanceDocFileSubTree(ChanceNode **ppcnTrav)
  1308. {
  1309. HRESULT hr = S_OK;
  1310. ChanceNode *pTempRoot = NULL;
  1311. ChanceNode *pTempNode = NULL;
  1312. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("DeleteChanceDocFileSubTree"));
  1313. DH_VDATEPTRIN(ppcnTrav, PCHANCENODE);
  1314. DH_ASSERT(NULL != *ppcnTrav);
  1315. if(S_OK == hr)
  1316. {
  1317. pTempRoot = *ppcnTrav;
  1318. pTempRoot->_pcnParent = NULL;
  1319. // Code to delete the tree iteratively
  1320. while(NULL != pTempRoot)
  1321. {
  1322. pTempNode = pTempRoot;
  1323. while(NULL != pTempNode->_pcnChild)
  1324. {
  1325. pTempNode = pTempNode->_pcnChild;
  1326. }
  1327. pTempRoot = pTempNode->_pcnParent;
  1328. if(pTempRoot != NULL)
  1329. {
  1330. pTempRoot->_pcnChild = pTempNode->_pcnSister;
  1331. // Decrease the storage count. This would be used to verify
  1332. // before deleting the ChanceNode.
  1333. pTempRoot->_cStorages--;
  1334. }
  1335. pTempNode->_pcnSister = NULL;
  1336. // Verify that number of children of this node are zero. Assert if
  1337. // not.
  1338. DH_ASSERT(0 == pTempNode->_cStorages);
  1339. // Delete the node
  1340. delete pTempNode;
  1341. pTempNode = NULL;
  1342. }
  1343. }
  1344. return hr;
  1345. }
  1346. //--------------------------------------------------------------------------
  1347. // Member: ChanceDF::GetModes, public
  1348. //
  1349. // Synopsis: Gets the creation modes for Root Storage, child storages,
  1350. // streams if provided on command line parameters.
  1351. //
  1352. // Arguments: [pDFMode]
  1353. // [ptcsModeFlags]
  1354. //
  1355. // Returns: HRESULT
  1356. //
  1357. // History: Narindk 2-May-96 Created
  1358. //---------------------------------------------------------------------------
  1359. HRESULT ChanceDF::GetModes(
  1360. DWORD *pDFMode,
  1361. LPCTSTR ptcsModeFlags)
  1362. {
  1363. HRESULT hr = S_OK;
  1364. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetModes"));
  1365. DH_VDATESTRINGPTR(ptcsModeFlags);
  1366. DH_VDATEPTROUT(pDFMode, DWORD);
  1367. DH_ASSERT(NULL != pDFMode);
  1368. if(S_OK == hr)
  1369. {
  1370. if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADSHEX))
  1371. {
  1372. *pDFMode = STGM_READ |
  1373. STGM_DIRECT |
  1374. STGM_SHARE_EXCLUSIVE;
  1375. }
  1376. else
  1377. if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRWRITESHEX))
  1378. {
  1379. *pDFMode = STGM_WRITE |
  1380. STGM_DIRECT |
  1381. STGM_SHARE_EXCLUSIVE;
  1382. }
  1383. else
  1384. if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADSHDENYW))
  1385. {
  1386. *pDFMode = STGM_READ |
  1387. STGM_DIRECT |
  1388. STGM_SHARE_DENY_WRITE;
  1389. }
  1390. else
  1391. if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADWRITESHEX))
  1392. {
  1393. *pDFMode = STGM_READWRITE |
  1394. STGM_DIRECT |
  1395. STGM_SHARE_EXCLUSIVE;
  1396. }
  1397. else
  1398. if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADWRITESHDENYN))
  1399. {
  1400. *pDFMode = STGM_READWRITE |
  1401. STGM_DIRECT |
  1402. STGM_SHARE_DENY_NONE;
  1403. }
  1404. else
  1405. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHEX))
  1406. {
  1407. *pDFMode = STGM_READWRITE |
  1408. STGM_TRANSACTED |
  1409. STGM_SHARE_EXCLUSIVE;
  1410. }
  1411. else
  1412. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYW))
  1413. {
  1414. *pDFMode = STGM_READWRITE |
  1415. STGM_TRANSACTED |
  1416. STGM_SHARE_DENY_WRITE;
  1417. }
  1418. else
  1419. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYN))
  1420. {
  1421. *pDFMode = STGM_READWRITE |
  1422. STGM_TRANSACTED |
  1423. STGM_SHARE_DENY_NONE;
  1424. }
  1425. else
  1426. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYR))
  1427. {
  1428. *pDFMode = STGM_READWRITE |
  1429. STGM_TRANSACTED |
  1430. STGM_SHARE_DENY_READ;
  1431. }
  1432. else
  1433. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYN))
  1434. {
  1435. *pDFMode = STGM_READ |
  1436. STGM_TRANSACTED |
  1437. STGM_SHARE_DENY_NONE;
  1438. }
  1439. else
  1440. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYR))
  1441. {
  1442. *pDFMode = STGM_READ |
  1443. STGM_TRANSACTED |
  1444. STGM_SHARE_DENY_READ;
  1445. }
  1446. else
  1447. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYW))
  1448. {
  1449. *pDFMode = STGM_READ |
  1450. STGM_TRANSACTED |
  1451. STGM_SHARE_DENY_WRITE;
  1452. }
  1453. else
  1454. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHEX))
  1455. {
  1456. *pDFMode = STGM_READ |
  1457. STGM_TRANSACTED |
  1458. STGM_SHARE_EXCLUSIVE;
  1459. }
  1460. else
  1461. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYN))
  1462. {
  1463. *pDFMode = STGM_WRITE |
  1464. STGM_TRANSACTED |
  1465. STGM_SHARE_DENY_NONE;
  1466. }
  1467. else
  1468. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYR))
  1469. {
  1470. *pDFMode = STGM_WRITE |
  1471. STGM_TRANSACTED |
  1472. STGM_SHARE_DENY_READ;
  1473. }
  1474. else
  1475. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYW))
  1476. {
  1477. *pDFMode = STGM_WRITE |
  1478. STGM_TRANSACTED |
  1479. STGM_SHARE_DENY_WRITE;
  1480. }
  1481. else
  1482. if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHEX))
  1483. {
  1484. *pDFMode = STGM_WRITE |
  1485. STGM_TRANSACTED |
  1486. STGM_SHARE_EXCLUSIVE;
  1487. }
  1488. else
  1489. {
  1490. hr = E_INVALIDARG ;
  1491. DH_ASSERT(!TEXT("ChanceDF::GetModes: Invalid Mode")) ;
  1492. }
  1493. }
  1494. return hr;
  1495. }
  1496. //--------------------------------------------------------------------------
  1497. // Member: ChanceDF::GetDocFileNameFromCmdline, private
  1498. //
  1499. // Synopsis: Gets the user provided name for docfile to be created.
  1500. //
  1501. // Arguments: [tszName]
  1502. //
  1503. // Returns: HRESULT
  1504. //
  1505. // History: Narindk 2-May-96 Created
  1506. //---------------------------------------------------------------------------
  1507. HRESULT ChanceDF::GetDocFileNameFromCmdline(LPCTSTR tszName)
  1508. {
  1509. HRESULT hr = S_OK;
  1510. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::GetDocFileName"));
  1511. DH_VDATESTRINGPTR(tszName);
  1512. _ptszName = new TCHAR[_tcslen(tszName)+1];
  1513. if (_ptszName == NULL)
  1514. {
  1515. hr = E_OUTOFMEMORY;
  1516. }
  1517. else
  1518. {
  1519. _tcscpy(_ptszName, tszName);
  1520. }
  1521. return hr;
  1522. }
  1523. //--------------------------------------------------------------------------
  1524. // Member: ChanceDF::GetRandomChanceNode, protected
  1525. //
  1526. // Synopsis: Gets a random ChanceNode from the ChanceDocFile tree to which
  1527. // a new ChanceNode would be added as Child or Sister during
  1528. // generation of ChanceDF tree.
  1529. //
  1530. // Arguments: [cNumOfNodes] : Total number of ChanceNodes in ChanceDF tree
  1531. // [ppcn] : Out parameter to return random ChanceNode found.
  1532. //
  1533. // Returns: HRESULT
  1534. //
  1535. // History: Narindk 2-July-96 Created
  1536. //
  1537. // Notes: -Find a random number between 1 and total number of nodes in
  1538. // the tree cNumOfNodes
  1539. // -Initialize counter to 1.
  1540. // -Initialze temp variable pcnTrav to _pcnRoot.
  1541. // -In a infinite for loop-
  1542. // -while pcnTrav's _pcnChild is not NULL and counter is less
  1543. // than cRandomNode, loop and update pcnTrav and counter.
  1544. // -If cRandomNode is equal to counter, then break out of
  1545. // for loop.
  1546. // -while pcnTrav's _pcnSister is NULL, loop and keep assign
  1547. // ing pcnTrav's _pcnParent to pcnTrav.
  1548. // -When pcnTrav's _pcnSister is not NULL, assign it to
  1549. // pcnTrav, increment counter and go back to top of loop.
  1550. //
  1551. // Pl. note that if cNumNodes is incorrectly given as more than
  1552. // actual number of nodes in tree, then this function will throw
  1553. // asserts.
  1554. //---------------------------------------------------------------------------
  1555. HRESULT ChanceDF::GetRandomChanceNode(ULONG cNumOfNodes, ChanceNode **ppcn)
  1556. {
  1557. HRESULT hr = S_OK;
  1558. ChanceNode *pcnTrav = NULL;
  1559. ULONG cRandomNode = 0;
  1560. ULONG counter = 1;
  1561. USHORT usErr = 0;
  1562. DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::GetRandomChanceNode"));
  1563. DH_VDATEPTROUT(ppcn, PCHANCENODE);
  1564. DH_ASSERT(NULL != ppcn);
  1565. DH_ASSERT(NULL != _pcnRoot);
  1566. DH_ASSERT(NULL != _pdgi);
  1567. DH_ASSERT(0 != cNumOfNodes);
  1568. if(S_OK == hr)
  1569. {
  1570. // Initialize out parameter
  1571. *ppcn = NULL;
  1572. usErr = _pdgi->Generate(&cRandomNode, 1, cNumOfNodes);
  1573. if (DG_RC_SUCCESS != usErr)
  1574. {
  1575. hr = E_FAIL;
  1576. }
  1577. }
  1578. if(S_OK == hr)
  1579. {
  1580. pcnTrav = _pcnRoot;
  1581. for(;;)
  1582. {
  1583. DH_ASSERT((NULL != pcnTrav) && (counter <= cRandomNode));
  1584. while((pcnTrav->_pcnChild != NULL) && (counter < cRandomNode))
  1585. {
  1586. pcnTrav = pcnTrav->_pcnChild;
  1587. counter++;
  1588. }
  1589. if(cRandomNode == counter)
  1590. {
  1591. break;
  1592. }
  1593. while(NULL == pcnTrav->_pcnSister)
  1594. {
  1595. pcnTrav = pcnTrav->_pcnParent;
  1596. DH_ASSERT(NULL != pcnTrav);
  1597. }
  1598. DH_ASSERT(NULL != pcnTrav->_pcnSister);
  1599. pcnTrav = pcnTrav->_pcnSister;
  1600. counter++;
  1601. }
  1602. }
  1603. if(S_OK == hr)
  1604. {
  1605. *ppcn = pcnTrav;
  1606. }
  1607. return hr;
  1608. }
  1609. //--------------------------------------------------------------------------
  1610. // Member: ChanceDF::GetDepthOfNode, private
  1611. //
  1612. // Synopsis: Gets the depth of a ChanceNode in a ChanceDF tree
  1613. //
  1614. // Arguments: [pcn] - ChanceNode whose depth needs to be determined.
  1615. //
  1616. // Returns: HRESULT
  1617. //
  1618. // History: Narindk 2-July-96 Created
  1619. //
  1620. // Notes: -Assigned passed in ChanceNode to temp variable pcnTrav.
  1621. // -Initialize cNodeDepth to zero.
  1622. // -Loop till pcnTrav's _pcnParent is not NULL and keep on
  1623. // updating pcnTrav and cNodeDepth.
  1624. // -Depth returned is 0 to n-1 for 1 to nth level nodes.
  1625. //---------------------------------------------------------------------------
  1626. ULONG ChanceDF::GetDepthOfNode(ChanceNode *pcn)
  1627. {
  1628. ChanceNode *pcnTrav = NULL;
  1629. ULONG cNodeDepth = 0;
  1630. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::GetDepthOfNode"));
  1631. DH_ASSERT(NULL != pcn);
  1632. pcnTrav = pcn;
  1633. while(NULL != pcnTrav->_pcnParent)
  1634. {
  1635. cNodeDepth++;
  1636. pcnTrav = pcnTrav->_pcnParent;
  1637. }
  1638. return cNodeDepth;
  1639. }