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.

963 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: psetstg.cxx
  7. //
  8. // Contents: Implementation of common class DocFile
  9. // IPropertySetStorage
  10. //
  11. // Classes: CPropertySetStorage
  12. // CEnumSTATPROPSETSTG
  13. //
  14. // Notes:
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "pch.cxx"
  18. #include "prophdr.hxx"
  19. //
  20. // debugging support
  21. //
  22. #if DBG
  23. CHAR *
  24. DbgFmtId(REFFMTID rfmtid, CHAR *pszBuf)
  25. {
  26. PropSprintfA(pszBuf, "rfmtid=%08X.%04X.%04X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X",
  27. rfmtid.Data1,
  28. rfmtid.Data2,
  29. rfmtid.Data3,
  30. rfmtid.Data4[0],
  31. rfmtid.Data4[1],
  32. rfmtid.Data4[2],
  33. rfmtid.Data4[3],
  34. rfmtid.Data4[4],
  35. rfmtid.Data4[5],
  36. rfmtid.Data4[6],
  37. rfmtid.Data4[7]);
  38. return(pszBuf);
  39. }
  40. CHAR *
  41. DbgMode(DWORD grfMode, CHAR *psz)
  42. {
  43. *psz = 0;
  44. if (grfMode & STGM_TRANSACTED)
  45. strcat(psz, "STGM_TRANSACTED | ");
  46. else
  47. strcat(psz, "STGM_DIRECT | ");
  48. if (grfMode & STGM_SIMPLE)
  49. strcat(psz, "STGM_SIMPLE | ");
  50. switch (grfMode & 3)
  51. {
  52. case STGM_READ:
  53. strcat(psz, "STGM_READ |");
  54. break;
  55. case STGM_WRITE:
  56. strcat(psz, "STGM_WRITE |");
  57. break;
  58. case STGM_READWRITE:
  59. strcat(psz, "STGM_READWRITE |");
  60. break;
  61. default:
  62. strcat(psz, "BAD grfMode |");
  63. break;
  64. }
  65. switch (grfMode & 0x70)
  66. {
  67. case STGM_SHARE_DENY_NONE:
  68. strcat(psz, "STGM_SHARE_DENY_NONE |");
  69. break;
  70. case STGM_SHARE_DENY_READ:
  71. strcat(psz, "STGM_SHARE_DENY_READ |");
  72. break;
  73. case STGM_SHARE_DENY_WRITE:
  74. strcat(psz, "STGM_SHARE_DENY_WRITE |");
  75. break;
  76. case STGM_SHARE_EXCLUSIVE:
  77. strcat(psz, "STGM_SHARE_EXCLUSIVE |");
  78. break;
  79. default:
  80. strcat(psz, "BAD grfMode | ");
  81. break;
  82. }
  83. if (grfMode & STGM_PRIORITY)
  84. strcat(psz, "STGM_PRIORITY | ");
  85. if (grfMode & STGM_DELETEONRELEASE)
  86. strcat(psz, "STGM_DELETEONRELEASE | ");
  87. if (grfMode & STGM_NOSCRATCH)
  88. strcat(psz, "STGM_NOSCRATCH | ");
  89. if (grfMode & STGM_CREATE)
  90. strcat(psz, "STGM_CREATE | ");
  91. if (grfMode & STGM_CONVERT)
  92. strcat(psz, "STGM_CONVERT | ");
  93. if (grfMode & STGM_FAILIFTHERE)
  94. strcat(psz, "STGM_FAILIFTHERE | ");
  95. return(psz);
  96. }
  97. CHAR *
  98. DbgFlags(DWORD grfFlags, CHAR *psz)
  99. {
  100. strcpy(psz, "grfFlags=");
  101. if (grfFlags & PROPSETFLAG_NONSIMPLE)
  102. strcat(psz, "PROPSETFLAG_NONSIMPLE |");
  103. else
  104. strcat(psz, "PROPSETFLAG_SIMPLE |");
  105. if (grfFlags & PROPSETFLAG_ANSI)
  106. strcat(psz, "PROPSETFLAG_ANSI |");
  107. else
  108. strcat(psz, "PROPSETFLAG_WIDECHAR |");
  109. return(psz);
  110. }
  111. #endif
  112. //+-------------------------------------------------------------------
  113. //
  114. // Member: CPropertySetStorage::QueryInterface, AddRef, Release
  115. //
  116. // Synopsis: IUnknown members
  117. //
  118. // Notes: Send the calls to the root.
  119. //
  120. //--------------------------------------------------------------------
  121. HRESULT CPropertySetStorage::QueryInterface( REFIID riid, void **ppvObject)
  122. {
  123. HRESULT hr;
  124. // ----------
  125. // Validation
  126. // ----------
  127. if (S_OK != (hr = Validate()))
  128. return(hr);
  129. VDATEREADPTRIN( &riid, IID );
  130. VDATEPTROUT( ppvObject, void* );
  131. // -----
  132. // Query
  133. // -----
  134. return(_pprivstg->GetStorage()->QueryInterface(riid, ppvObject));
  135. }
  136. ULONG CPropertySetStorage::AddRef(void)
  137. {
  138. if (S_OK != Validate())
  139. return(0);
  140. return(_pprivstg->GetStorage()->AddRef());
  141. }
  142. ULONG CPropertySetStorage::Release(void)
  143. {
  144. if (S_OK != Validate())
  145. return(0);
  146. return(_pprivstg->GetStorage()->Release());
  147. }
  148. //+-------------------------------------------------------------------
  149. //
  150. // Member: CPropertySetStorage::Create
  151. //
  152. // Synopsis: Create a property set for outermost client of
  153. // IPropertSetStorage.
  154. //
  155. // Arguments: Passed through to CPropertyStorage ctor.
  156. //
  157. // Returns: S_OK or failure code.
  158. //
  159. // Notes: Create a new CPropertyStorage object which will
  160. // implement IPropertyStorage. The _pprivstg parameter
  161. // passed into CPropertyStorage::CPropertyStorage is
  162. // used to create (via QI) a matching type of mapped
  163. // stream for docfile properies
  164. //
  165. //--------------------------------------------------------------------
  166. HRESULT CPropertySetStorage::Create( REFFMTID rfmtid,
  167. const CLSID * pclsid,
  168. DWORD grfFlags,
  169. DWORD grfMode,
  170. IPropertyStorage ** ppprstg)
  171. {
  172. HRESULT hr;
  173. DBGBUF(buf1);
  174. DBGBUF(buf2);
  175. DBGBUF(buf3);
  176. // ----------
  177. // Validation
  178. // ----------
  179. if (S_OK != (hr = Validate()))
  180. goto errRet;
  181. GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
  182. GEN_VDATEPTRIN_LABEL(pclsid, CLSID, E_INVALIDARG, errRet, hr);
  183. GEN_VDATEPTROUT_LABEL( ppprstg, IPropertyStorage*, E_INVALIDARG, errRet, hr);
  184. // ---------------------------
  185. // Create the Property Storage
  186. // ---------------------------
  187. hr = STG_E_INSUFFICIENTMEMORY;
  188. *ppprstg = NULL;
  189. *ppprstg = new CPropertyStorage(_pprivstg,
  190. rfmtid,
  191. pclsid,
  192. grfFlags,
  193. grfMode,
  194. &hr);
  195. if (FAILED(hr))
  196. {
  197. delete (CPropertyStorage*) *ppprstg;
  198. *ppprstg = NULL;
  199. }
  200. // ----
  201. // Exit
  202. // ----
  203. errRet:
  204. if( E_INVALIDARG != hr )
  205. {
  206. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Create(%s, %s, %s, retif=%08X, hr = %08X\n",
  207. this, DbgFmtId(rfmtid, buf1), DbgFlags(grfFlags, buf2), DbgMode(grfMode, buf3), *ppprstg, hr));
  208. }
  209. else
  210. {
  211. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Create(%08X, %s, %s, retif=%08X, hr = %08X\n",
  212. this, &rfmtid, DbgFlags(grfFlags, buf2), DbgMode(grfMode, buf3), ppprstg, hr));
  213. }
  214. return(hr);
  215. }
  216. //+-------------------------------------------------------------------
  217. //
  218. // Member: CPropertySetStorage::Open
  219. //
  220. // Synopsis: Open a property set for outermost client.
  221. //
  222. // Arguments: passed through to CPropertyStorage ctor.
  223. //
  224. // Returns: S_OK or error.
  225. //
  226. // Notes: Creates a CPropertyStorage which will use the passed
  227. // pstg to create a mapped stream of the correct type
  228. // in its implementation.
  229. //
  230. //--------------------------------------------------------------------
  231. HRESULT CPropertySetStorage::Open( REFFMTID rfmtid,
  232. DWORD grfMode,
  233. IPropertyStorage ** ppprstg)
  234. {
  235. HRESULT hr;
  236. DBGBUF(buf1);
  237. DBGBUF(buf2);
  238. // ----------
  239. // Validation
  240. // ----------
  241. // Validate 'this'
  242. if (S_OK != (hr = Validate()))
  243. goto errRet;
  244. // Validate inputs
  245. GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
  246. GEN_VDATEPTROUT_LABEL( ppprstg, IPropertyStorage*, E_INVALIDARG, errRet, hr);
  247. // -------------------------
  248. // Open the Property Storage
  249. // -------------------------
  250. hr = STG_E_INSUFFICIENTMEMORY;
  251. *ppprstg = NULL;
  252. *ppprstg = new CPropertyStorage(_pprivstg, rfmtid, grfMode,
  253. FALSE, // Don't delete this section
  254. &hr);
  255. if (FAILED(hr))
  256. {
  257. delete (CPropertyStorage*) *ppprstg;
  258. *ppprstg = NULL;
  259. }
  260. // ----
  261. // Exit
  262. // ----
  263. errRet:
  264. if( E_INVALIDARG != hr )
  265. {
  266. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Open(%s, %s) retif=%08X, hr=%08X\n",
  267. this, DbgFmtId(rfmtid, buf1), DbgMode(grfMode, buf2), *ppprstg, hr));
  268. }
  269. else
  270. {
  271. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Open(), hr=%08X\n",
  272. this, hr));
  273. }
  274. return(hr);
  275. }
  276. //+-------------------------------------------------------------------
  277. //
  278. // Member: CPropertySetStorage::Delete
  279. //
  280. // Synopsis: Delete the specified property set.
  281. //
  282. // Arguments: [rfmtid] -- format id of property set to delete.
  283. //
  284. // Returns: S_OK if successful, error otherwise.
  285. //
  286. // Notes: Get the matching name and try the element deletion.
  287. //
  288. //--------------------------------------------------------------------
  289. HRESULT CPropertySetStorage::Delete( REFFMTID rfmtid)
  290. {
  291. HRESULT hr;
  292. DBGBUF(buf);
  293. // ----------
  294. // Validation
  295. // ----------
  296. // Validate 'this'
  297. if (S_OK != (hr = Validate()))
  298. goto errRet;
  299. // Validate the input
  300. GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
  301. // --------------------------
  302. // Delete the PropertyStorage
  303. // --------------------------
  304. // Check for the special-case
  305. if( IsEqualIID( rfmtid, FMTID_UserDefinedProperties ))
  306. {
  307. // This property set is actually the second section of the Document
  308. // Summary Information property set. We must delete this
  309. // section, but we can't delete the Stream because it
  310. // still contain the first section.
  311. CPropertyStorage* pprstg;
  312. pprstg = new CPropertyStorage(_pprivstg,
  313. rfmtid,
  314. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  315. TRUE, // Delete this section.
  316. &hr);
  317. if (pprstg != NULL)
  318. {
  319. pprstg->Release();
  320. }
  321. pprstg = NULL;
  322. } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 ))
  323. else
  324. {
  325. // This is not a special case, so we can just delete
  326. // the Stream. Note that if the rfmtid represents the first
  327. // section of the DocumentSummaryInformation set, we might be
  328. // deleting the second section here as well.
  329. CPropSetName psn(rfmtid);
  330. hr = _pprivstg->GetStorage()->DestroyElement(psn.GetPropSetName());
  331. } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 )) ... else
  332. // ----
  333. // Exit
  334. // ----
  335. errRet:
  336. if( E_INVALIDARG != hr )
  337. {
  338. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Delete(%s) hr = %08X\n",
  339. this, DbgFmtId(rfmtid, buf), hr));
  340. }
  341. else
  342. {
  343. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Delete(%08X) hr = %08X\n",
  344. this, &rfmtid, hr));
  345. }
  346. return(hr);
  347. }
  348. //+-------------------------------------------------------------------
  349. //
  350. // Member: CPropertySetStorage::Enum
  351. //
  352. // Synopsis: Create an enumerator over the property set
  353. //
  354. // Arguments: [ppenum] -- where to return the pointer to the
  355. // enumerator.
  356. //
  357. // Returns: S_OK if ok, error otherwise.
  358. //
  359. // Notes: [ppenum] is NULL on error.
  360. //
  361. //--------------------------------------------------------------------
  362. HRESULT CPropertySetStorage::Enum( IEnumSTATPROPSETSTG ** ppenum)
  363. {
  364. HRESULT hr;
  365. // ----------
  366. // Validation
  367. // ----------
  368. // Validate 'this'
  369. if (S_OK != (hr = Validate()))
  370. goto errRet;
  371. // Validate the input
  372. GEN_VDATEPTROUT_LABEL( ppenum, IEnumSTATPROPSETSTG*, E_INVALIDARG, errRet, hr);
  373. // --------------------
  374. // Create the enuerator
  375. // --------------------
  376. hr = STG_E_INSUFFICIENTMEMORY;
  377. *ppenum = NULL; // for access violation
  378. *ppenum = new CEnumSTATPROPSETSTG(_pprivstg->GetStorage(), &hr);
  379. if (FAILED(hr))
  380. {
  381. delete (CEnumSTATPROPSETSTG*) *ppenum;
  382. *ppenum = NULL;
  383. }
  384. // ----
  385. // Exit
  386. // ----
  387. errRet:
  388. if( E_INVALIDARG != hr )
  389. {
  390. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Enum(retif=%08X), hr = %08X\n",
  391. this, *ppenum, hr));
  392. }
  393. else
  394. {
  395. PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Enum(), hr = %08X\n",
  396. this, hr));
  397. }
  398. return(hr);
  399. }
  400. //+-------------------------------------------------------------------
  401. //
  402. // Member: CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG
  403. //
  404. // Synopsis: Constructor which is used to implement
  405. // IPropertySetStorage::Enum
  406. //
  407. // Arguments: [pstg] -- the storage of the container to enumerate.
  408. // [phr] -- place to return HRESULT, S_OK or error.
  409. //
  410. // Notes: We use an STATSTG enumerator over the actual storage
  411. // to get the information about the property sets.
  412. //
  413. //--------------------------------------------------------------------
  414. CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG(IStorage *pstg, HRESULT *phr)
  415. {
  416. HRESULT & hr = *phr;
  417. _ulSig = ENUMSTATPROPSETSTG_SIG;
  418. _cRefs = 1;
  419. hr = pstg->EnumElements(FALSE, NULL, 0, &_penumSTATSTG);
  420. if (FAILED(hr))
  421. _penumSTATSTG = NULL;
  422. _cstatTotalInArray = 0;
  423. _istatNextToRead = 0;
  424. }
  425. //+-------------------------------------------------------------------
  426. //
  427. // Member: CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG
  428. //
  429. // Synopsis: Copy constructor which is used to implement
  430. // IEnumSTATPROPSETSTG::Clone.
  431. //
  432. // Arguments: [Other] -- The CEnumSTATPROPSETSTG to clone.
  433. // [phr] -- place to return HRESULT, S_OK or error.
  434. //
  435. //--------------------------------------------------------------------
  436. CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG( CEnumSTATPROPSETSTG &Other,
  437. HRESULT *phr)
  438. {
  439. HRESULT & hr = *phr;
  440. _ulSig = ENUMSTATPROPSETSTG_SIG;
  441. _cRefs = 1;
  442. _cstatTotalInArray = 0;
  443. _istatNextToRead = Other._istatNextToRead;
  444. hr = Other._penumSTATSTG->Clone(&_penumSTATSTG);
  445. if (hr == S_OK)
  446. {
  447. // Copy the data in the buffer
  448. memcpy(_statarray, Other._statarray, sizeof(_statarray));
  449. _cstatTotalInArray = Other._cstatTotalInArray;
  450. // Copy the strings in the buffer
  451. for (ULONG i=0; i<_cstatTotalInArray; i++)
  452. {
  453. _statarray[i].pwcsName =
  454. (OLECHAR*)CoTaskMemAlloc(sizeof(OLECHAR)*(ocslen(Other._statarray[i].pwcsName)+1));
  455. if (_statarray[i].pwcsName == NULL)
  456. {
  457. _cstatTotalInArray = i;
  458. hr = STG_E_INSUFFICIENTMEMORY;
  459. break;
  460. }
  461. else
  462. {
  463. ocscpy(_statarray[i].pwcsName, Other._statarray[i].pwcsName);
  464. }
  465. }
  466. }
  467. // note: destructor will cleanup the the strings or enumerator left behind
  468. // in the error case
  469. }
  470. //+-------------------------------------------------------------------
  471. //
  472. // Member: CEnumSTATPROPSETSTG::~CEnumSTATPROPSETSTG
  473. //
  474. // Synopsis: Delete the enumerator.
  475. //
  476. // Notes: Just releases the contained IEnumSTATSTG
  477. //
  478. //--------------------------------------------------------------------
  479. CEnumSTATPROPSETSTG::~CEnumSTATPROPSETSTG()
  480. {
  481. _ulSig = ENUMSTATPROPSETSTG_SIGDEL;
  482. if (_penumSTATSTG != NULL)
  483. _penumSTATSTG->Release();
  484. CleanupStatArray();
  485. }
  486. //+-------------------------------------------------------------------
  487. //
  488. // Member: CEnumSTATPROPSETSTG::QueryInterface, AddRef, Release
  489. //
  490. // Synopsis: IUnknown
  491. //
  492. // Arguments: The usual thing.
  493. //
  494. //--------------------------------------------------------------------
  495. HRESULT CEnumSTATPROPSETSTG::QueryInterface( REFIID riid, void **ppvObject)
  496. {
  497. HRESULT hr;
  498. if (S_OK != (hr = Validate()))
  499. return(hr);
  500. *ppvObject = NULL;
  501. if (IsEqualIID(riid, IID_IEnumSTATPROPSETSTG))
  502. {
  503. *ppvObject = (IEnumSTATPROPSETSTG *)this;
  504. CEnumSTATPROPSETSTG::AddRef();
  505. }
  506. else
  507. if (IsEqualIID(riid, IID_IUnknown))
  508. {
  509. *ppvObject = (IUnknown *)this;
  510. CEnumSTATPROPSETSTG::AddRef();
  511. }
  512. else
  513. {
  514. hr = E_NOINTERFACE;
  515. }
  516. return(hr);
  517. }
  518. //+-------------------------------------------------------------------
  519. //
  520. // Member: CEnumSTATPROPSETSTG::AddRef
  521. //
  522. //--------------------------------------------------------------------
  523. ULONG CEnumSTATPROPSETSTG::AddRef(void)
  524. {
  525. if (S_OK != Validate())
  526. return(0);
  527. InterlockedIncrement(&_cRefs);
  528. return(_cRefs);
  529. }
  530. //+-------------------------------------------------------------------
  531. //
  532. // Member: CEnumSTATPROPSETSTG::Release
  533. //
  534. //--------------------------------------------------------------------
  535. ULONG CEnumSTATPROPSETSTG::Release(void)
  536. {
  537. LONG lRet;
  538. if (S_OK != Validate())
  539. return(0);
  540. lRet = InterlockedDecrement(&_cRefs);
  541. if (lRet == 0)
  542. {
  543. delete this;
  544. }
  545. else
  546. if (lRet <0)
  547. {
  548. lRet = 0;
  549. }
  550. return(lRet);
  551. }
  552. //+-------------------------------------------------------------------
  553. //
  554. // Member: CEnumSTATPROPSETSTG::Next
  555. //
  556. // Synopsis: Implement IEnumSTATPROPSETSTG for docfile.
  557. //
  558. // Arguments: [celt] -- Count of elements to attempt to retrieve.
  559. // [rgelt] -- Where to put the results. Must be valid for at least
  560. // celt * sizeof(STATPROPSETSTG) bytes in length.
  561. // [pceltFetched] -- Count of elements returned is put here if
  562. // the pointer is non-null. If celt > 1, pceltFetched must
  563. // be valid non-NULL. If pcelt is non-NULL, it must be valid.
  564. // if pcelt is NULL, celt must be 1.
  565. //
  566. // Returns: S_OK if ok, error otherwise.
  567. //
  568. // Notes: We use a stack buffer to get more stuff per call to
  569. // underlying storage IEnumSTATSTG::Next. We then copy
  570. // data from the STATSTG's to STATPROPSETSTG's.
  571. //
  572. // An outer loop enumerates into statarray and then an
  573. // inner loop copies each batch into the [rgelt] buffer.
  574. //
  575. //--------------------------------------------------------------------
  576. HRESULT CEnumSTATPROPSETSTG::Next(ULONG celt,
  577. STATPROPSETSTG * rgelt,
  578. ULONG * pceltFetched)
  579. {
  580. HRESULT hr;
  581. ULONG celtCallerTotal;
  582. // ----------
  583. // Validation
  584. // ----------
  585. // Validate 'this'
  586. if (S_OK != (hr = Validate()))
  587. return(hr);
  588. // Validate inputs
  589. if (NULL == pceltFetched)
  590. {
  591. if (1 != celt)
  592. return(STG_E_INVALIDPARAMETER);
  593. }
  594. else
  595. {
  596. VDATEPTROUT( pceltFetched, ULONG );
  597. *pceltFetched = 0;
  598. }
  599. if (0 == celt)
  600. return(hr);
  601. if( !IsValidPtrOut(rgelt, celt * sizeof(rgelt[0])) )
  602. return( E_INVALIDARG );
  603. // -----------------------
  604. // Perform the enumeration
  605. // -----------------------
  606. celtCallerTotal = 0;
  607. //
  608. // we do this loop until we have what the caller wanted or error, or
  609. // no more.
  610. //
  611. do
  612. {
  613. //
  614. // If our internal buffer is empty, we (re)load it
  615. //
  616. if (_istatNextToRead == _cstatTotalInArray)
  617. {
  618. if (_cstatTotalInArray != 0)
  619. CleanupStatArray();
  620. hr = _penumSTATSTG->Next(sizeof(_statarray)/sizeof(_statarray[0]),
  621. _statarray,
  622. &_cstatTotalInArray);
  623. }
  624. // S_OK or S_FALSE indicate that we got something
  625. if (SUCCEEDED(hr))
  626. {
  627. //
  628. // we loop reading out of this buffer until either we have
  629. // all that the caller asked for, or we have exhausted the
  630. // buffer.
  631. //
  632. for (; celtCallerTotal < celt &&
  633. _istatNextToRead < _cstatTotalInArray ;
  634. _istatNextToRead++)
  635. {
  636. OLECHAR *pocsName = _statarray[_istatNextToRead].pwcsName;
  637. BOOL fDone = FALSE;
  638. PROPASSERT(pocsName != NULL);
  639. if (pocsName[0] == 5)
  640. {
  641. // *** get fmtid *** //
  642. if (!NT_SUCCESS(RtlPropertySetNameToGuid(
  643. ocslen(pocsName), pocsName, &rgelt->fmtid)))
  644. {
  645. ZeroMemory(&rgelt->fmtid, sizeof(rgelt->fmtid));
  646. }
  647. // *** get clsid *** //
  648. // *** get grfFlags *** //
  649. if (_statarray[_istatNextToRead].type == STGTY_STORAGE)
  650. {
  651. rgelt->clsid = _statarray[_istatNextToRead].clsid;
  652. rgelt->grfFlags = PROPSETFLAG_NONSIMPLE;
  653. }
  654. else
  655. {
  656. ZeroMemory(&rgelt->clsid, sizeof(rgelt->clsid));
  657. rgelt->grfFlags = 0;
  658. }
  659. // *** get mtime *** //
  660. rgelt->mtime = _statarray[_istatNextToRead].mtime;
  661. // *** get ctime *** //
  662. rgelt->ctime = _statarray[_istatNextToRead].ctime;
  663. // *** get atime *** //
  664. rgelt->atime = _statarray[_istatNextToRead].atime;
  665. // *** default the OS Version *** //
  666. rgelt->dwOSVersion = PROPSETHDR_OSVERSION_UNKNOWN;
  667. rgelt ++;
  668. celtCallerTotal ++;
  669. }
  670. }
  671. }
  672. }
  673. while (celtCallerTotal < celt && hr == S_OK);
  674. if (SUCCEEDED(hr))
  675. {
  676. hr = celt == celtCallerTotal ? S_OK : S_FALSE;
  677. PROPASSERT(hr == S_OK || celtCallerTotal < celt);
  678. if (pceltFetched != NULL)
  679. *pceltFetched = celtCallerTotal;
  680. }
  681. return(hr);
  682. }
  683. //+-------------------------------------------------------------------
  684. //
  685. // Member: CEnumSTATPROPSETSTG::Skip
  686. //
  687. // Synopsis: Skip the requested number of elements.
  688. //
  689. // Arguments: [celt] -- number to skip.
  690. //
  691. // Returns: S_OK if all skipped, S_FALSE if less than requested
  692. // number skipped, error otherwise.
  693. //
  694. // Notes:
  695. //
  696. //--------------------------------------------------------------------
  697. HRESULT CEnumSTATPROPSETSTG::Skip(ULONG celt)
  698. {
  699. HRESULT hr;
  700. STATPROPSETSTG stat;
  701. ULONG celtCallerTotal = 0;
  702. if (S_OK != (hr = Validate()))
  703. return(hr);
  704. do
  705. {
  706. hr = Next(1, &stat, NULL);
  707. } while ( hr == S_OK && ++celtCallerTotal < celt );
  708. if (SUCCEEDED(hr))
  709. hr = celt == celtCallerTotal ? S_OK : S_FALSE;
  710. return(hr);
  711. }
  712. //+-------------------------------------------------------------------
  713. //
  714. // Member: CEnumSTATPROPSETSTG::CleanupStatArray
  715. //
  716. // Synopsis: Free any strings in the array.
  717. //
  718. //--------------------------------------------------------------------
  719. VOID CEnumSTATPROPSETSTG::CleanupStatArray()
  720. {
  721. for (ULONG i=0; i<_cstatTotalInArray; i++)
  722. {
  723. CoTaskMemFree(_statarray[i].pwcsName);
  724. _statarray[i].pwcsName = NULL;
  725. }
  726. _istatNextToRead = 0;
  727. _cstatTotalInArray = 0;
  728. }
  729. //+-------------------------------------------------------------------
  730. //
  731. // Member: CEnumSTATPROPSETSTG::Reset
  732. //
  733. // Synopsis: Reset the enumerator.
  734. //
  735. // Notes: Merely resetting the underlying enumerator should be
  736. // adequate,
  737. //
  738. //--------------------------------------------------------------------
  739. HRESULT CEnumSTATPROPSETSTG::Reset()
  740. {
  741. HRESULT hr;
  742. if (S_OK != (hr = Validate()))
  743. return(hr);
  744. hr = _penumSTATSTG->Reset();
  745. if (hr == S_OK)
  746. {
  747. CleanupStatArray();
  748. }
  749. return(hr);
  750. }
  751. //+-------------------------------------------------------------------
  752. //
  753. // Member: CEnumSTATPROPSETSTG::Clone
  754. //
  755. // Synopsis: Copy the enumeration state of this enumerator.
  756. //
  757. // Arguments: [ppenum] -- where to put the pointer to the clone
  758. //
  759. // Returns: S_OK if ok, error otherwise.
  760. //
  761. // Notes: We end up just calling IEnumSTATSTG::Clone in the
  762. // CEnumSTATPROPSETSTG constructor.
  763. //
  764. //--------------------------------------------------------------------
  765. HRESULT CEnumSTATPROPSETSTG::Clone(IEnumSTATPROPSETSTG ** ppenum)
  766. {
  767. HRESULT hr;
  768. // ----------
  769. // Validation
  770. // ----------
  771. // Validate 'this'
  772. if (S_OK != (hr = Validate()))
  773. return(hr);
  774. // Validate inputs
  775. VDATEPTROUT( ppenum, IEnumSTATPROPSETSTG* );
  776. // --------------------
  777. // Clone the enumerator
  778. // --------------------
  779. hr = STG_E_INSUFFICIENTMEMORY;
  780. *ppenum = new CEnumSTATPROPSETSTG(*this, &hr);
  781. if (FAILED(hr))
  782. {
  783. delete (CEnumSTATPROPSETSTG*) *ppenum;
  784. *ppenum = NULL;
  785. }
  786. return(hr);
  787. }