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.

1521 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) 1992, Microsoft Corporation.
  5. //
  6. // File: expst.cxx
  7. //
  8. // Contents: CExposedStream code
  9. //
  10. // Notes: See the header file expst.hxx for details
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "exphead.cxx"
  14. #include "expst.hxx"
  15. #include "logfile.hxx"
  16. //+--------------------------------------------------------------
  17. //
  18. // Member: CExposedStream::CExposedStream, public
  19. //
  20. // Synopsis: Empty object constructor
  21. //
  22. //---------------------------------------------------------------
  23. CExposedStream::CExposedStream()
  24. {
  25. olDebugOut((DEB_ITRACE, "In CExposedStream::CExposedStream()\n"));
  26. _cReferences = 0;
  27. _ulAccessLockBase = 0;
  28. _ulPos = 0;
  29. _pst = NULL;
  30. _pdfParent = NULL;
  31. _fDirty = FALSE;
  32. #ifdef NEWPROPS
  33. _pb = NULL;
  34. _cbUsed = 0;
  35. _cbOriginalStreamSize = 0;
  36. _fChangePending = FALSE;
  37. #endif
  38. olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
  39. }
  40. //+--------------------------------------------------------------
  41. //
  42. // Member: CExposedStream::Init, public
  43. //
  44. // Synopsis: Base constructor
  45. //
  46. // Arguments: [pst] - Direct stream
  47. // [pdfParent] - the storage parent
  48. // [df] - Permission flags
  49. // [pdfn] - name of stream
  50. // [ulPos] - offset
  51. //
  52. // Returns: Appropriate status code
  53. //
  54. // Note: We add "this" as a child to the parent to
  55. // 1) Check for multiple instantiation of a child
  56. // 2) Uses the RevertFromAbove() function to check
  57. // for reverted state.
  58. //
  59. //---------------------------------------------------------------
  60. SCODE CExposedStream::Init(CDirectStream *pst,
  61. CExposedDocFile* pdfParent,
  62. const DFLAGS df,
  63. const CDfName *pdfn,
  64. const ULONGLONG ulPos)
  65. {
  66. olDebugOut((DEB_ITRACE, "In CExposedStream::Init("
  67. "%p, %lu)\n", pst, ulPos));
  68. _ulPos = ulPos;
  69. _pst = pst;
  70. _pdfParent = pdfParent;
  71. _df = df;
  72. _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
  73. olAssert(pdfParent);
  74. _pdfParent->AddChild(this);
  75. _cReferences = 1;
  76. _sig = CEXPOSEDSTREAM_SIG;
  77. olDebugOut((DEB_ITRACE, "Out CExposedStream::Init\n"));
  78. return S_OK;
  79. }
  80. //+--------------------------------------------------------------
  81. //
  82. // Member: CExposedStream::Read, public
  83. //
  84. // Synopsis: Read from a stream
  85. //
  86. // Arguments: [pb] - Buffer
  87. // [cb] - Count of bytes to read
  88. // [pcbRead] - Return number of bytes read
  89. //
  90. // Returns: Appropriate status code
  91. //
  92. // Modifies: [pcbRead]
  93. //
  94. //---------------------------------------------------------------
  95. STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
  96. {
  97. SCODE sc;
  98. ULONG cbRead = 0;
  99. olLog(("%p::In CExposedStream::Read(%p, %lu, %p)\n",
  100. this, pb, cb, pcbRead));
  101. olDebugOut((DEB_ITRACE, "In CExposedStream::Read(%p,%lu,%p)\n",
  102. pb, cb, pcbRead));
  103. TRY
  104. {
  105. if (pcbRead)
  106. olChkTo(EH_BadPtr, ValidateOutBuffer(pcbRead, sizeof(ULONG)));
  107. olChk(ValidateHugeOutBuffer(pb, cb));
  108. olChk(Validate());
  109. olChk(CheckReverted());
  110. if (!P_READ(_df))
  111. sc = STG_E_ACCESSDENIED;
  112. else
  113. sc = _pst->ReadAt(_ulPos, pb, cb,
  114. (ULONG STACKBASED *)&cbRead);
  115. _ulPos+=cbRead;
  116. }
  117. CATCH(CException, e)
  118. {
  119. sc = e.GetErrorCode();
  120. }
  121. END_CATCH
  122. olDebugOut((DEB_ITRACE, "Out CExposedStream::Read => %lu\n", cbRead));
  123. EH_Err:
  124. if (pcbRead)
  125. {
  126. *pcbRead = cbRead;
  127. olLog(("%p::Out CExposedStream::Read() *pcbRead==%lu, ret=%lx\n",
  128. this, SAFE_DREF(pcbRead), sc));
  129. }
  130. else
  131. {
  132. olLog(("%p::Out CExposedStream::Read(). ret == %lx\n", this, sc));
  133. }
  134. EH_BadPtr:
  135. return ResultFromScode(sc);
  136. }
  137. //+--------------------------------------------------------------
  138. //
  139. // Member: CExposedStream::Write, public
  140. //
  141. // Synopsis: Write to a stream
  142. //
  143. // Arguments: [pb] - Buffer
  144. // [cb] - Count of bytes to write
  145. // [pcbWritten] - Return of bytes written
  146. //
  147. // Returns: Appropriate status code
  148. //
  149. // Modifies: [pcbWritten]
  150. //
  151. //---------------------------------------------------------------
  152. STDMETHODIMP CExposedStream::Write(
  153. VOID const HUGEP *pb,
  154. ULONG cb,
  155. ULONG *pcbWritten)
  156. {
  157. SCODE sc;
  158. ULONG cbWritten = 0;
  159. olLog(("%p::In CExposedStream::Write(%p, %lu, %p)\n",
  160. this, pb, cb, pcbWritten));
  161. olDebugOut((DEB_ITRACE,
  162. "In CExposedStream::Write(%p, %lu, %p)\n",
  163. pb, cb, pcbWritten));
  164. TRY
  165. {
  166. if (pcbWritten)
  167. {
  168. olChkTo(EH_BadPtr,
  169. ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
  170. }
  171. olChk(ValidateHugeBuffer(pb, cb));
  172. olChk(Validate());
  173. olChk(CheckReverted());
  174. if (!P_WRITE(_df))
  175. sc = STG_E_ACCESSDENIED;
  176. else
  177. {
  178. sc = _pst->WriteAt(_ulPos, pb, cb,
  179. (ULONG STACKBASED *)&cbWritten);
  180. if (SUCCEEDED(sc))
  181. SetDirty();
  182. }
  183. _ulPos += cbWritten;
  184. }
  185. CATCH(CException, e)
  186. {
  187. sc = e.GetErrorCode();
  188. }
  189. END_CATCH
  190. olDebugOut((DEB_ITRACE, "Out CExposedStream::Write => %lu\n",
  191. cbWritten));
  192. EH_Err:
  193. if (pcbWritten)
  194. {
  195. *pcbWritten = cbWritten;
  196. olLog(("%p::Out CExposedStream::Write(). *pcbWritten == %lu, ret = %lx\n",
  197. this, *pcbWritten, sc));
  198. }
  199. else
  200. {
  201. olLog(("%p::Out CExposedStream::Write(). ret == %lx\n",this, sc));
  202. }
  203. EH_BadPtr:
  204. return ResultFromScode(sc);
  205. }
  206. //+--------------------------------------------------------------
  207. //
  208. // Member: CExposedStream::Seek, public
  209. //
  210. // Synopsis: Seek to a point in a stream
  211. //
  212. // Arguments: [dlibMove] - Offset to move by
  213. // [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
  214. // [plibNewPosition] - Return of new offset
  215. //
  216. // Returns: Appropriate status code
  217. //
  218. // Modifies: [plibNewPosition]
  219. //
  220. //---------------------------------------------------------------
  221. STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
  222. DWORD dwOrigin,
  223. ULARGE_INTEGER *plibNewPosition)
  224. {
  225. SCODE sc;
  226. LONGLONG lMove;
  227. ULARGE_INTEGER ulPos;
  228. olDebugOut((DEB_ITRACE, "In CExposedStream::Seek(%ld%ld, %lu, %p)\n",
  229. dlibMove.QuadPart, dwOrigin, plibNewPosition));
  230. TRY
  231. {
  232. if (plibNewPosition)
  233. {
  234. olChk(ValidateOutBuffer(plibNewPosition, sizeof(ULARGE_INTEGER)));
  235. ULISet32(*plibNewPosition, 0);
  236. }
  237. if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
  238. dwOrigin != STREAM_SEEK_END)
  239. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  240. lMove = dlibMove.QuadPart;
  241. olChk(Validate());
  242. olChk(CheckReverted());
  243. ULISet32(ulPos, _ulPos);
  244. switch(dwOrigin)
  245. {
  246. case STREAM_SEEK_SET:
  247. ulPos.QuadPart = lMove;
  248. break;
  249. case STREAM_SEEK_END:
  250. ULONGLONG cbSize;
  251. olChk(GetSize(&cbSize));
  252. if (lMove < 0)
  253. {
  254. if ((ULONGLONG)(-lMove) > cbSize)
  255. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  256. }
  257. ulPos.QuadPart = cbSize+lMove;
  258. break;
  259. case STREAM_SEEK_CUR:
  260. if (lMove < 0)
  261. {
  262. if ((ULONGLONG)(-lMove) > _ulPos)
  263. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  264. }
  265. ulPos.QuadPart = _ulPos+lMove;
  266. break;
  267. }
  268. _ulPos = ulPos.QuadPart;
  269. if (plibNewPosition)
  270. *plibNewPosition = ulPos;
  271. }
  272. CATCH(CException, e)
  273. {
  274. sc = e.GetErrorCode();
  275. }
  276. END_CATCH
  277. olDebugOut((DEB_ITRACE, "Out CExposedStream::Seek => %lu%lu\n",
  278. ulPos.QuadPart));
  279. EH_Err:
  280. return ResultFromScode(sc);
  281. }
  282. //+--------------------------------------------------------------
  283. //
  284. // Member: CExposedStream::SetSize, public
  285. //
  286. // Synopsis: Sets the size of a stream
  287. //
  288. // Arguments: [ulNewSize] - New size
  289. //
  290. // Returns: Appropriate status code
  291. //
  292. //---------------------------------------------------------------
  293. SCODE CExposedStream::SetSize(ULONGLONG cb)
  294. {
  295. olDebugOut((DEB_ITRACE, "In CExposedStream::SetSize(%lu%lu)\n", cb));
  296. SCODE sc;
  297. TRY
  298. {
  299. olChk(Validate());
  300. olChk(CheckReverted());
  301. if (!P_WRITE(_df))
  302. sc = STG_E_ACCESSDENIED;
  303. else
  304. {
  305. olChk(_pst->SetSize(cb));
  306. SetDirty();
  307. }
  308. }
  309. CATCH(CException, e)
  310. {
  311. sc = e.GetErrorCode();
  312. }
  313. END_CATCH
  314. EH_Err:
  315. olDebugOut((DEB_ITRACE, "Out CExposedStream::SetSize()\n"));
  316. return sc;
  317. }
  318. //+--------------------------------------------------------------
  319. //
  320. // Member: CExposedStream::SetSize, public
  321. //
  322. // Synopsis: Sets the size of a stream
  323. //
  324. // Arguments: [ulNewSize] - New size
  325. //
  326. // Returns: Appropriate status code
  327. //
  328. //---------------------------------------------------------------
  329. STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
  330. {
  331. SCODE sc;
  332. olDebugOut((DEB_ITRACE, "In CExposedStream::SetSize(%lu%lu)\n",
  333. ulNewSize.QuadPart));
  334. TRY
  335. {
  336. olChk(SetSize(ulNewSize.QuadPart));
  337. }
  338. CATCH(CException, e)
  339. {
  340. sc = e.GetErrorCode();
  341. }
  342. END_CATCH
  343. olDebugOut((DEB_ITRACE, "Out CExposedStream::SetSize\n"));
  344. EH_Err:
  345. olLog(("%p::Out CExposedStream::SetSize(). ret == %lx\n", this, sc));
  346. return ResultFromScode(sc);
  347. }
  348. //+--------------------------------------------------------------
  349. //
  350. // Member: CExposedStream::CopyTo, public
  351. //
  352. // Synopsis: Copies information from one stream to another
  353. //
  354. // Arguments: [pstm] - Destination
  355. // [cb] - Number of bytes to copy
  356. // [pcbRead] - Return number of bytes read
  357. // [pcbWritten] - Return number of bytes written
  358. //
  359. // Returns: Appropriate status code
  360. //
  361. // Modifies: [pcbRead]
  362. // [pcbWritten]
  363. //
  364. // Notes: We do our best to handle overlap correctly. This allows
  365. // CopyTo to be used to insert and remove space within a
  366. // stream.
  367. //
  368. // In the error case, we make no gurantees as to the
  369. // validity of pcbRead, pcbWritten, or either stream's
  370. // seek position.
  371. //
  372. //---------------------------------------------------------------
  373. STDMETHODIMP CExposedStream::CopyTo(IStream *pstm,
  374. ULARGE_INTEGER cb,
  375. ULARGE_INTEGER *pcbRead,
  376. ULARGE_INTEGER *pcbWritten)
  377. {
  378. SCODE sc;
  379. ULONGLONG ulCopySize;
  380. ULONGLONG ulSrcSize;
  381. ULONGLONG ulSrcOrig;
  382. ULARGE_INTEGER uliDestOrig;
  383. LARGE_INTEGER liDestPos;
  384. BYTE *pb = NULL;
  385. BOOL fOverlap;
  386. ULONG ulBytesCopied = 0;
  387. olDebugOut((DEB_TRACE, "In CExposedStream::CopyTo("
  388. "%p, %lu%lu, %p, %p)\n", pstm, cb.QuadPart,
  389. pcbRead, pcbWritten));
  390. TRY
  391. {
  392. if (pcbRead) // okay to set to NULL => not interested
  393. {
  394. olChk(ValidateOutBuffer(pcbRead, sizeof(ULARGE_INTEGER)));
  395. ULISet32(*pcbRead, 0);
  396. }
  397. if (pcbWritten) // okay to set to NULL => not interested
  398. {
  399. olChk(ValidateOutBuffer(pcbWritten, sizeof(ULARGE_INTEGER)));
  400. ULISet32(*pcbWritten, 0);
  401. }
  402. olChk(ValidateInterface(pstm, IID_IStream));
  403. olChk(Validate());
  404. olChk(CheckReverted());
  405. ulCopySize = cb.QuadPart;
  406. // We can only copy what's available in the source stream
  407. olChk(GetSize(&ulSrcSize));
  408. ulSrcOrig = _ulPos;
  409. if (ulSrcSize < ulSrcOrig)
  410. {
  411. // Nothing in source to copy
  412. ulCopySize = 0;
  413. }
  414. else if ((ulSrcSize - ulSrcOrig) < ulCopySize)
  415. {
  416. // Shrink ulCopySize to fit bytes in source
  417. ulCopySize = ulSrcSize - ulSrcOrig;
  418. }
  419. // 3. We can only copy what will fit in the destination
  420. LISet32(liDestPos, 0);
  421. olHChk(pstm->Seek(liDestPos, STREAM_SEEK_CUR, &uliDestOrig));
  422. // We are allowed to fail here with out-of-memory
  423. olMem(pb = new BYTE[STREAMBUFFERSIZE]);
  424. // Since we have no reliable way to determine if the source and
  425. // destination represent the same stream, we assume they
  426. // do and always handle overlap.
  427. fOverlap = (uliDestOrig.QuadPart > ulSrcOrig &&
  428. uliDestOrig.QuadPart < ulSrcOrig + ulCopySize);
  429. ULONGLONG ulSrcCopyOffset = 0;
  430. ULONGLONG ulDstCopyOffset = 0;
  431. if (fOverlap)
  432. {
  433. // We're going to copy back to front, so determine the
  434. // stream end positions
  435. ulSrcCopyOffset = ulSrcOrig + ulCopySize;
  436. // uliDestOrig is the destination starting offset
  437. ulDstCopyOffset = uliDestOrig.QuadPart + ulCopySize;
  438. }
  439. while (ulCopySize > 0)
  440. {
  441. // We can only copy up to STREAMBUFFERSIZE bytes at a time
  442. ULONG cbPart = (ULONG) min(ulCopySize, STREAMBUFFERSIZE);
  443. if (fOverlap)
  444. {
  445. // We're copying back to front so we need to seek to
  446. // set up the streams correctly
  447. ulSrcCopyOffset -= cbPart;
  448. ulDstCopyOffset -= cbPart;
  449. // Set source stream position
  450. _ulPos = ulSrcCopyOffset;
  451. // Set destination stream position
  452. liDestPos.QuadPart = ulDstCopyOffset;
  453. olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
  454. }
  455. {
  456. ULONG ulRead;
  457. olHChk(Read(pb, cbPart, &ulRead));
  458. if (cbPart != ulRead)
  459. {
  460. // There was no error, but we were unable to read cbPart
  461. // bytes. Something's wrong (the underlying ILockBytes?)
  462. // but we can't control it; just return an error.
  463. olErr(EH_Err, STG_E_READFAULT);
  464. }
  465. }
  466. {
  467. ULONG ulWritten;
  468. olHChk(pstm->Write(pb, cbPart, &ulWritten));
  469. if (cbPart != ulWritten)
  470. {
  471. // There was no error, but we were unable to write
  472. // ulWritten bytes. We can't trust the pstm
  473. // implementation, so all we can do here is return
  474. // an error.
  475. olErr(EH_Err, STG_E_WRITEFAULT);
  476. }
  477. }
  478. olAssert(ulCopySize >= cbPart);
  479. ulCopySize -= cbPart;
  480. ulBytesCopied += cbPart;
  481. }
  482. if (fOverlap)
  483. {
  484. // Set the seek pointers to the correct location
  485. _ulPos = ulSrcOrig + ulBytesCopied;
  486. liDestPos.QuadPart = uliDestOrig.QuadPart + ulBytesCopied;
  487. olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
  488. }
  489. if (pcbRead)
  490. ULISet32(*pcbRead, ulBytesCopied);
  491. if (pcbWritten)
  492. ULISet32(*pcbWritten, ulBytesCopied);
  493. }
  494. CATCH(CException, e)
  495. {
  496. sc = e.GetErrorCode();
  497. }
  498. END_CATCH
  499. olDebugOut((DEB_ITRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
  500. pcbRead ? pcbRead->QuadPart : 0,
  501. pcbWritten ? pcbWritten->QuadPart : 0));
  502. // Fall through
  503. EH_Err:
  504. delete [] pb;
  505. return ResultFromScode(sc);
  506. }
  507. //+--------------------------------------------------------------
  508. //
  509. // Member: CExposedStream::Release, public
  510. //
  511. // Synopsis: Releases a stream
  512. //
  513. // Returns: Appropriate status code
  514. //
  515. //---------------------------------------------------------------
  516. STDMETHODIMP_(ULONG) CExposedStream::Release(void)
  517. {
  518. LONG lRet;
  519. olLog(("%p::In CExposedStream::Release()\n", this));
  520. olDebugOut((DEB_ITRACE, "In CExposedStream::Release()\n"));
  521. TRY
  522. {
  523. if (FAILED(Validate()))
  524. return 0;
  525. olAssert(_cReferences > 0);
  526. lRet = AtomicDec(&_cReferences);
  527. if (lRet == 0)
  528. {
  529. Commit(0); // flush data
  530. delete this;
  531. }
  532. else if (lRet < 0)
  533. lRet = 0;
  534. }
  535. CATCH(CException, e)
  536. {
  537. UNREFERENCED_PARM(e);
  538. lRet = 0;
  539. }
  540. END_CATCH
  541. olDebugOut((DEB_ITRACE, "Out CExposedStream::Release\n"));
  542. olLog(("%p::Out CExposedStream::Release(). ret == %lu\n", this, lRet));
  543. FreeLogFile();
  544. return lRet;
  545. }
  546. //+--------------------------------------------------------------
  547. //
  548. // Member: CExposedStream::Stat, public
  549. //
  550. // Synopsis: Fills in a buffer of information about this object
  551. //
  552. // Arguments: [pstatstg] - Buffer
  553. //
  554. // Returns: Appropriate status code
  555. //
  556. // Modifies: [pstatstg]
  557. //
  558. //---------------------------------------------------------------
  559. STDMETHODIMP_(SCODE) CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
  560. {
  561. SCODE sc;
  562. olLog(("%p::In CExposedStream::Stat(%p)\n", this, pstatstg));
  563. olDebugOut((DEB_ITRACE, "In CExposedStream::Stat(%p)\n",
  564. pstatstg));
  565. TRY
  566. {
  567. olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
  568. olChk(VerifyStatFlag(grfStatFlag));
  569. olChk(Validate());
  570. olChk(CheckReverted());
  571. pstatstg->grfMode = DFlagsToMode(_df);
  572. pstatstg->clsid = CLSID_NULL; // irrelevant for streams
  573. pstatstg->grfStateBits = 0; // irrelevant for streams
  574. pstatstg->type = STGTY_STREAM;
  575. pstatstg->grfLocksSupported = 0;
  576. pstatstg->reserved = 0;
  577. // we null these values 'cos they are not interesting for
  578. // direct streams ...
  579. pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
  580. pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
  581. pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
  582. pstatstg->pwcsName = NULL;
  583. if ((grfStatFlag & STATFLAG_NONAME) == 0)
  584. { // fill in name
  585. olChk(DfAllocWCS((WCHAR *)_dfn.GetBuffer(),
  586. &pstatstg->pwcsName));
  587. wcscpy(pstatstg->pwcsName, (WCHAR *)_dfn.GetBuffer());
  588. }
  589. ULONGLONG cbSize;
  590. GetSize(&cbSize);
  591. pstatstg->cbSize.QuadPart = cbSize;
  592. }
  593. CATCH(CException, e)
  594. {
  595. sc = e.GetErrorCode();
  596. }
  597. END_CATCH
  598. olDebugOut((DEB_ITRACE, "Out CExposedStream::Stat\n"));
  599. EH_Err:
  600. if (FAILED(sc))
  601. memset(pstatstg, 0, sizeof(STATSTGW));
  602. EH_RetSc:
  603. olLog(("%p::Out CExposedStream::Stat(). ret == %lx\n",
  604. this, sc));
  605. return sc;
  606. }
  607. //+--------------------------------------------------------------
  608. //
  609. // Member: CExposedStream::Clone, public
  610. //
  611. // Synopsis: Clones a stream
  612. //
  613. // Returns: Appropriate status code
  614. //
  615. //---------------------------------------------------------------
  616. STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
  617. {
  618. CExposedStream *pst;
  619. SCODE sc;
  620. olLog(("%p::In CExposedStream::Clone(%p)\n", this, ppstm));
  621. olDebugOut((DEB_ITRACE, "In CExposedStream::Clone(%p)\n", ppstm));
  622. TRY
  623. {
  624. olChk(ValidateOutPtrBuffer(ppstm));
  625. *ppstm = NULL;
  626. olChk(Validate());
  627. olChk(CheckReverted());
  628. olMemTo(EH_pst, pst = new CExposedStream);
  629. olChkTo(EH_pst, pst->Init(_pst, _pdfParent, _df, &_dfn, _ulPos));
  630. _pst->AddRef();
  631. *ppstm = pst;
  632. }
  633. CATCH(CException, e)
  634. {
  635. sc = e.GetErrorCode();
  636. }
  637. END_CATCH
  638. olDebugOut((DEB_ITRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
  639. return ResultFromScode(sc);
  640. EH_pst:
  641. delete pst;
  642. EH_Err:
  643. olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
  644. this, SAFE_DREFppstm, sc));
  645. return ResultFromScode(sc);
  646. }
  647. //+--------------------------------------------------------------
  648. //
  649. // Member: CExposedStream::AddRef, public
  650. //
  651. // Synopsis: Increments the ref count
  652. //
  653. // Returns: Appropriate status code
  654. //
  655. //---------------------------------------------------------------
  656. STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
  657. {
  658. ULONG ulRet;
  659. olLog(("%p::In CExposedStream::AddRef()\n", this));
  660. olDebugOut((DEB_ITRACE, "In CExposedStream::AddRef()\n"));
  661. TRY
  662. {
  663. if (FAILED(Validate()))
  664. return 0;
  665. AtomicInc(&_cReferences);
  666. ulRet = _cReferences;
  667. }
  668. CATCH(CException, e)
  669. {
  670. UNREFERENCED_PARM(e);
  671. ulRet = 0;
  672. }
  673. END_CATCH
  674. olDebugOut((DEB_ITRACE, "Out CExposedStream::AddRef\n"));
  675. olLog(("%p::Out CExposedStream::AddRef(). ret == %lu\n", this, ulRet));
  676. return ulRet;
  677. }
  678. //+--------------------------------------------------------------
  679. //
  680. // Member: CExposedStream::LockRegion, public
  681. //
  682. // Synopsis: Nonfunctional
  683. //
  684. // Returns: Appropriate status code
  685. //
  686. //---------------------------------------------------------------
  687. STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
  688. ULARGE_INTEGER cb,
  689. DWORD dwLockType)
  690. {
  691. olDebugOut((DEB_ITRACE, "In CExposedStream::LockRegion("
  692. "%lu, %lu\n", cb.QuadPart, dwLockType));
  693. olDebugOut((DEB_ITRACE, "Out CExposedStream::LockRegion\n"));
  694. olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
  695. UNREFERENCED_PARM(libOffset);
  696. UNREFERENCED_PARM(cb);
  697. UNREFERENCED_PARM(dwLockType);
  698. olAssert(FALSE && aMsg("function not implemented!"));
  699. return ResultFromScode(STG_E_INVALIDFUNCTION);
  700. }
  701. //+--------------------------------------------------------------
  702. //
  703. // Member: CExposedStream::UnlockRegion, public
  704. //
  705. // Synopsis: Nonfunctional
  706. //
  707. // Returns: Appropriate status code
  708. //
  709. //---------------------------------------------------------------
  710. STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
  711. ULARGE_INTEGER cb,
  712. DWORD dwLockType)
  713. {
  714. olDebugOut((DEB_ITRACE, "In CExposedStream::UnlockRegion(%lu, %lu)\n",
  715. cb.QuadPart, dwLockType));
  716. olDebugOut((DEB_ITRACE, "Out CExposedStream::UnlockRegion\n"));
  717. olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
  718. UNREFERENCED_PARM(libOffset);
  719. UNREFERENCED_PARM(cb);
  720. UNREFERENCED_PARM(dwLockType);
  721. olAssert(FALSE && aMsg("function not implemented!"));
  722. return ResultFromScode(STG_E_INVALIDFUNCTION);
  723. }
  724. //+--------------------------------------------------------------
  725. //
  726. // Member: CExposedStream::Commit, public
  727. //
  728. // Returns: Appropriate status code
  729. //
  730. //---------------------------------------------------------------
  731. STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
  732. {
  733. SCODE sc;
  734. olDebugOut((DEB_ITRACE, "In CExposedStream::Commit(%lu)\n",
  735. grfCommitFlags));
  736. olLog(("%p::In CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
  737. TRY
  738. {
  739. olChk(Validate());
  740. olChk(CheckReverted());
  741. if (_fDirty)
  742. { // We're a stream so we must have a parent
  743. // We dirty all parents up to the next
  744. // transacted storage
  745. _pdfParent->SetDirty();
  746. sc = _pdfParent->GetBaseMS()
  747. ->Flush(FLUSH_CACHE(grfCommitFlags));
  748. }
  749. }
  750. CATCH(CException, e)
  751. {
  752. sc = e.GetErrorCode();
  753. }
  754. END_CATCH
  755. olDebugOut((DEB_ITRACE, "Out CExposedStream::Commit\n"));
  756. EH_Err:
  757. olLog(("%p::Out CExposedStream::Commit(). ret == %lx", this, sc));
  758. return ResultFromScode(sc);
  759. }
  760. //+--------------------------------------------------------------
  761. //
  762. // Member: CExposedStream::Revert, public
  763. //
  764. // Synopsis: No-op in current implementation
  765. //
  766. // Returns: Appropriate status code
  767. //
  768. //---------------------------------------------------------------
  769. STDMETHODIMP CExposedStream::Revert(void)
  770. {
  771. olDebugOut((DEB_ITRACE, "In CExposedStream::Revert()\n"));
  772. olDebugOut((DEB_ITRACE, "Out CExposedStream::Revert\n"));
  773. olLog(("%p::In CExposedStream::Revert()\n", this));
  774. olLog(("%p::Out CExposedStream::Revert(). ret == %lx", this, S_OK));
  775. return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
  776. }
  777. //+--------------------------------------------------------------
  778. //
  779. // Member: CExposedStream::QueryInterface, public
  780. //
  781. // Synopsis: Returns an object for the requested interface
  782. //
  783. // Arguments: [iid] - Interface ID
  784. // [ppvObj] - Object return
  785. //
  786. // Returns: Appropriate status code
  787. //
  788. // Modifies: [ppvObj]
  789. //
  790. //---------------------------------------------------------------
  791. STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
  792. {
  793. SCODE sc;
  794. olLog(("%p::In CExposedStream::QueryInterface(?, %p)\n",
  795. this, ppvObj));
  796. olDebugOut((DEB_ITRACE, "In CExposedStream::QueryInterface(?, %p)\n",
  797. ppvObj));
  798. TRY
  799. {
  800. olChk(ValidateOutPtrBuffer(ppvObj));
  801. *ppvObj = NULL;
  802. olChk(ValidateIid(iid));
  803. olChk(Validate());
  804. olChk(CheckReverted());
  805. if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
  806. {
  807. olChk(AddRef());
  808. *ppvObj = this;
  809. }
  810. else
  811. olErr(EH_Err, E_NOINTERFACE);
  812. sc = S_OK;
  813. }
  814. CATCH(CException, e)
  815. {
  816. sc = e.GetErrorCode();
  817. }
  818. END_CATCH
  819. olDebugOut((DEB_ITRACE, "Out CExposedStream::QueryInterface => %p\n",
  820. ppvObj));
  821. EH_Err:
  822. olLog(("%p::Out CExposedStream::QueryInterface(). *ppvObj == %p, ret == %lx\n",
  823. this, *ppvObj, sc));
  824. return ResultFromScode(sc);
  825. }
  826. //+--------------------------------------------------------------
  827. //
  828. // Member: CExposedStream::RevertFromAbove, public (virtual)
  829. //
  830. // Synopsis: Parent has asked for reversion
  831. //
  832. //---------------------------------------------------------------
  833. void CExposedStream::RevertFromAbove(void)
  834. {
  835. msfDebugOut((DEB_ITRACE,
  836. "In CExposedStream::RevertFromAbove:%p()\n", this));
  837. _df |= DF_REVERTED;
  838. _pst->Release();
  839. #if DBG == 1
  840. _pst = NULL;
  841. #endif
  842. msfDebugOut((DEB_ITRACE, "Out CExposedStream::RevertFromAbove\n"));
  843. }
  844. #ifdef NEWPROPS
  845. //+-------------------------------------------------------------------
  846. //
  847. // Member: CExposedStream::Open
  848. //
  849. // Synopsis: Opens mapped view of exposed stream. Called by
  850. // NtCreatePropertySet et al.
  851. //
  852. // Notes: Gets the size of the underlying stream and reads it
  853. // into memory so that it can be "mapped."
  854. //
  855. //--------------------------------------------------------------------
  856. VOID CExposedStream::Open(IN VOID *powner, OUT LONG *phr)
  857. {
  858. LONG& sc = *phr;
  859. sc = S_OK;
  860. // If given a pointer to the owner of this mapped stream,
  861. // save it. This could be NULL. (i.e. when called from ReOpen)
  862. if( NULL != powner )
  863. _powner = (BYTE*) powner;
  864. if (_pb == NULL)
  865. {
  866. ULONGLONG ulSize;
  867. VOID *pv;
  868. _cbUsed = 0;
  869. olChk(CheckReverted());
  870. _pst->GetSize(&ulSize);
  871. if (ulSize > CBMAXPROPSETSTREAM)
  872. olErr(EH_Err, STG_E_INVALIDHEADER);
  873. _cbOriginalStreamSize = (ULONG) ulSize;
  874. _cbUsed = _cbOriginalStreamSize;
  875. olMemTo(EH_Err, pv = new BYTE[_cbOriginalStreamSize]);
  876. _pb = (BYTE*) pv;
  877. olChkTo(EH_Read,
  878. _pst->ReadAt(0, pv, _cbOriginalStreamSize, &_cbUsed));
  879. olAssert(_cbOriginalStreamSize == _cbUsed &&
  880. "CExposedStream did not read in all the info!");
  881. // Notify our owner that we have new data
  882. if (*phr == S_OK && _powner != NULL && 0 != _cbUsed)
  883. {
  884. *phr = RtlOnMappedStreamEvent((VOID*)_powner, pv, _cbUsed );
  885. }
  886. }
  887. olDebugOut((DEB_PROP_MAP, "CExposedStream(%X):Open returns normally\n", this));
  888. return;
  889. // Error handling
  890. EH_Read:
  891. delete[] _pb;
  892. _pb = NULL;
  893. _cbUsed = 0;
  894. EH_Err:
  895. olDebugOut((DEB_PROP_MAP,
  896. "CExposedStream(%X):Open exception returns %08X\n",
  897. this, *phr));
  898. return;
  899. }
  900. //+-------------------------------------------------------------------
  901. //
  902. // Member: CExposedStream::Close
  903. //
  904. // Synopsis: Operates on mapped view of exposed stream. Called by
  905. // NtCreatePropertySet et al.
  906. //
  907. // Notes: Does nothing because the object may be mapped in
  908. // another process.
  909. //
  910. //--------------------------------------------------------------------
  911. VOID CExposedStream::Close(OUT LONG *phr)
  912. {
  913. // Write the changes. We don't need to Commit them,
  914. // they will be implicitely committed when the
  915. // Stream is Released.
  916. *phr = Write();
  917. if( FAILED(*phr) )
  918. {
  919. olDebugOut( (DEB_PROP_MAP,
  920. "CPubStream(%08X)::Close exception returns %08X\n",
  921. this, *phr));
  922. }
  923. return;
  924. }
  925. //+-------------------------------------------------------------------
  926. //
  927. // Member: CExposedStream::ReOpen
  928. //
  929. // Synopsis: Operates on mapped view of exposed stream. Called by
  930. // NtCreatePropertySet et al.
  931. //
  932. // Notes: Combined open and map.
  933. //
  934. //--------------------------------------------------------------------
  935. VOID CExposedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
  936. {
  937. *ppv = NULL;
  938. Open( (void*)NULL, // unspecified owner
  939. phr);
  940. if ( SUCCEEDED(*phr) )
  941. *ppv = _pb;
  942. }
  943. //+-------------------------------------------------------------------
  944. //
  945. // Member: CExposedStream::Quiesce
  946. //
  947. // Synopsis: Operates on mapped view of exposed stream. Called by
  948. // NtCreatePropertySet et al.
  949. //
  950. // Notes: Meaningless for docfile mapped stream.
  951. //
  952. //--------------------------------------------------------------------
  953. VOID CExposedStream::Quiesce(VOID)
  954. {
  955. olAssert(_pb != NULL);
  956. DfpdbgCheckUnusedMemory();
  957. }
  958. //+-------------------------------------------------------------------
  959. //
  960. // Member: CExposedStream::Map
  961. //
  962. // Synopsis: Operates on mapped view of exposed stream. Called by
  963. // NtCreatePropertySet et al.
  964. //
  965. // Notes: Return the address of the "mapping" buffer.
  966. //
  967. //--------------------------------------------------------------------
  968. VOID CExposedStream::Map(BOOLEAN fCreate, VOID **ppv)
  969. {
  970. UNREFERENCED_PARM(fCreate);
  971. olAssert(_pb != NULL);
  972. DfpdbgCheckUnusedMemory();
  973. *ppv = _pb;
  974. }
  975. //+-------------------------------------------------------------------
  976. //
  977. // Member: CExposedStream::Unmap
  978. //
  979. // Synopsis: Operates on mapped view of exposed stream. Called by
  980. // NtCreatePropertySet et al.
  981. //
  982. // Notes: Unmapping is merely zeroing the pointer. We don't
  983. // flush because that's done explicitly by the
  984. // CPropertyStorage class.
  985. //
  986. //
  987. //--------------------------------------------------------------------
  988. VOID CExposedStream::Unmap(BOOLEAN fFlush, VOID **pv)
  989. {
  990. UNREFERENCED_PARM(fFlush);
  991. DfpdbgCheckUnusedMemory();
  992. *pv = NULL;
  993. }
  994. //+-------------------------------------------------------------------
  995. //
  996. // Member: CExposedStream::Flush
  997. //
  998. // Synopsis: Operates on mapped view of exposed stream. Called by
  999. // NtCreatePropertySet et al.
  1000. // Flush the memory property set to disk and commit it.
  1001. //
  1002. //--------------------------------------------------------------------
  1003. VOID CExposedStream::Flush(OUT LONG *phr)
  1004. {
  1005. *phr = S_OK;
  1006. // write out any data we have cached to the stream
  1007. if (S_OK == (*phr = Write()))
  1008. {
  1009. // commit the stream
  1010. (*phr) = Commit(STGC_DEFAULT);
  1011. }
  1012. return;
  1013. }
  1014. //+-------------------------------------------------------------------
  1015. //
  1016. // Member: CExposedStream::GetSize
  1017. //
  1018. // Synopsis: Returns size of exposed stream. Called by
  1019. // NtCreatePropertySet et al.
  1020. //
  1021. // Notes:
  1022. //--------------------------------------------------------------------
  1023. ULONG CExposedStream::GetSize(OUT LONG *phr)
  1024. {
  1025. *phr = S_OK;
  1026. if (_pb == NULL)
  1027. Open((void*)NULL, // unspecified owner
  1028. phr);
  1029. if( SUCCEEDED(*phr) )
  1030. {
  1031. olAssert(_pb != NULL);
  1032. DfpdbgCheckUnusedMemory();
  1033. }
  1034. return _cbUsed;
  1035. }
  1036. //+-------------------------------------------------------------------
  1037. //
  1038. // Member: CExposedStream::SetSize
  1039. //
  1040. // Synopsis: Sets size of "map." Called by
  1041. // NtCreatePropertySet et al.
  1042. //
  1043. // Arguments: [cb] -- requested size.
  1044. // [fPersistent] -- FALSE if expanding in-memory read-only image
  1045. // [ppv] -- new mapped address.
  1046. //
  1047. // Signals: Not enough disk space.
  1048. //
  1049. //
  1050. //--------------------------------------------------------------------
  1051. VOID CExposedStream::SetSize(ULONG cb, IN BOOLEAN fPersistent,
  1052. VOID **ppv, OUT LONG *phr)
  1053. {
  1054. *phr = S_OK;
  1055. LONG& sc=*phr;
  1056. BYTE *pbNew;
  1057. olAssert(cb != 0);
  1058. DfpdbgCheckUnusedMemory();
  1059. olChk(CheckReverted());
  1060. //
  1061. // if we are growing the data, we should grow the stream
  1062. //
  1063. if (fPersistent && cb > _cbUsed)
  1064. {
  1065. olChk(_pst->SetSize(cb));
  1066. }
  1067. olMem(pbNew = new BYTE[cb]);
  1068. memcpy(pbNew, _pb, (cb < _cbUsed) ? cb : _cbUsed); // smaller of the 2
  1069. delete[] _pb;
  1070. _pb = pbNew;
  1071. _cbUsed = cb;
  1072. *ppv = _pb;
  1073. DfpdbgFillUnusedMemory();
  1074. EH_Err:
  1075. olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):SetSize %s returns hr=%08X\n",
  1076. this, *phr != S_OK ? "exception" : "", *phr));
  1077. return;
  1078. }
  1079. //+-------------------------------------------------------------------
  1080. //
  1081. // Member: CExposedStream::QueryTimeStamps
  1082. //
  1083. // Synopsis: Operates on mapped view of exposed stream. Called by
  1084. // NtCreatePropertySet et al.
  1085. //
  1086. // Notes:
  1087. //
  1088. //--------------------------------------------------------------------
  1089. VOID CExposedStream::QueryTimeStamps(STATPROPSETSTG *pspss,
  1090. BOOLEAN fNonSimple) const
  1091. {
  1092. UNREFERENCED_PARM(fNonSimple);
  1093. UNREFERENCED_PARM(pspss);
  1094. }
  1095. //+-------------------------------------------------------------------
  1096. //
  1097. // Member: CExposedStream::QueryModifyTime
  1098. //
  1099. // Synopsis: Operates on mapped view of exposed stream. Called by
  1100. // NtCreatePropertySet et al.
  1101. //
  1102. // Notes:
  1103. //
  1104. //--------------------------------------------------------------------
  1105. BOOLEAN CExposedStream::QueryModifyTime(OUT LONGLONG *pll) const
  1106. {
  1107. UNREFERENCED_PARM(pll);
  1108. return (FALSE);
  1109. }
  1110. //+-------------------------------------------------------------------
  1111. //
  1112. // Member: CExposedStream::QuerySecurity
  1113. //
  1114. // Synopsis: Operates on mapped view of exposed stream. Called by
  1115. // NtCreatePropertySet et al.
  1116. //
  1117. // Notes:
  1118. //
  1119. //--------------------------------------------------------------------
  1120. BOOLEAN CExposedStream::QuerySecurity(OUT ULONG *pul) const
  1121. {
  1122. UNREFERENCED_PARM(pul);
  1123. return FALSE;
  1124. }
  1125. //+-------------------------------------------------------------------
  1126. //
  1127. // Member: CExposedStream::IsWriteable
  1128. //
  1129. // Synopsis: Operates on mapped view of exposed stream. Called by
  1130. // NtCreatePropertySet et al.
  1131. //
  1132. // Notes:
  1133. //
  1134. //--------------------------------------------------------------------
  1135. BOOLEAN CExposedStream::IsWriteable() const
  1136. {
  1137. return TRUE;
  1138. }
  1139. //+-------------------------------------------------------------------
  1140. //
  1141. // Member: CExposedStream::SetChangePending
  1142. //
  1143. // Synopsis: Operates on mapped view of exposed stream. Called by
  1144. // NtCreatePropertySet et al.
  1145. //
  1146. // Notes:
  1147. //
  1148. //--------------------------------------------------------------------
  1149. #if DBGPROP
  1150. BOOLEAN CExposedStream::SetChangePending(BOOLEAN f)
  1151. {
  1152. _fChangePending = f;
  1153. return(_fChangePending);
  1154. }
  1155. #endif
  1156. //+-------------------------------------------------------------------
  1157. //
  1158. // Member: CExposedStream::IsNtMappedStream
  1159. //
  1160. // Synopsis: Operates on mapped view of exposed stream. Called by
  1161. // NtCreatePropertySet et al.
  1162. //
  1163. // Notes:
  1164. //
  1165. //--------------------------------------------------------------------
  1166. #if DBGPROP
  1167. BOOLEAN CExposedStream::IsNtMappedStream(VOID) const
  1168. {
  1169. return FALSE;
  1170. }
  1171. #endif
  1172. //+-------------------------------------------------------------------
  1173. //
  1174. // Member: CExposedStream::GetHandle
  1175. //
  1176. // Synopsis: Operates on mapped view of exposed stream. Called by
  1177. // NtCreatePropertySet et al.
  1178. //
  1179. // Notes:
  1180. //
  1181. //--------------------------------------------------------------------
  1182. HANDLE CExposedStream::GetHandle(VOID) const
  1183. {
  1184. return INVALID_HANDLE_VALUE;
  1185. }
  1186. //+-------------------------------------------------------------------
  1187. //
  1188. // Member: CExposedStream::SetModified
  1189. //
  1190. // Synopsis: Operates on mapped view of exposed stream. Called by
  1191. // NtCreatePropertySet et al.
  1192. //
  1193. // Notes:
  1194. //
  1195. //--------------------------------------------------------------------
  1196. VOID CExposedStream::SetModified(VOID)
  1197. {
  1198. _fDirty = TRUE;
  1199. }
  1200. //+-------------------------------------------------------------------
  1201. //
  1202. // Member: CExposedStream::IsModified
  1203. //
  1204. // Synopsis: Operates on mapped view of exposed stream. Called by
  1205. // NtCreatePropertySet et al.
  1206. //
  1207. // Notes:
  1208. //
  1209. //--------------------------------------------------------------------
  1210. BOOLEAN CExposedStream::IsModified(VOID) const
  1211. {
  1212. return _fDirty;
  1213. }
  1214. #if DBG
  1215. //+-------------------------------------------------------------------
  1216. //
  1217. // Member: CExposedStream::DfpdbgFillUnusedMemory
  1218. //
  1219. //--------------------------------------------------------------------
  1220. VOID CExposedStream::DfpdbgFillUnusedMemory(VOID)
  1221. {
  1222. if (_pb == NULL)
  1223. return;
  1224. BYTE * pbEndPlusOne = _pb + BytesCommitted();
  1225. for (BYTE *pbUnused = _pb + _cbUsed;
  1226. pbUnused < pbEndPlusOne;
  1227. pbUnused++)
  1228. {
  1229. *pbUnused = (BYTE)(DWORD)pbUnused;
  1230. }
  1231. }
  1232. //+-------------------------------------------------------------------
  1233. //
  1234. // Member: CExposedStream::DfpdbgCheckUnusedMemory
  1235. //
  1236. //--------------------------------------------------------------------
  1237. VOID CExposedStream::DfpdbgCheckUnusedMemory(VOID)
  1238. {
  1239. if (_pb == NULL)
  1240. return;
  1241. if (_cbUsed == 0)
  1242. return;
  1243. BYTE * pbEndPlusOne = _pb + BytesCommitted();
  1244. for (BYTE *pbUnused = _pb + _cbUsed;
  1245. pbUnused < pbEndPlusOne;
  1246. pbUnused ++)
  1247. {
  1248. olAssert(*pbUnused == (BYTE)(DWORD)pbUnused);
  1249. }
  1250. }
  1251. #endif // DBG
  1252. //+-------------------------------------------------------------------
  1253. //
  1254. // Member: CExposedStream::Write, private
  1255. //
  1256. // Synopsis: Writes a mapped view of an exposed Stream to the
  1257. // underlying Stream. Used by RtlCreatePropertySet et al.
  1258. //
  1259. // Notes: The Stream is not commited. To commit the Stream, in
  1260. // addition to writing it, the Flush method should be used.
  1261. // The Commit is omitted so that it can be skipped in
  1262. // the Property Set Close path, thus eliminating a
  1263. // performance penalty.
  1264. //
  1265. //--------------------------------------------------------------------
  1266. HRESULT CExposedStream::Write(VOID)
  1267. {
  1268. HRESULT hr;
  1269. ULONG cbWritten;
  1270. if (!_fDirty ||!_pb)
  1271. {
  1272. olDebugOut((DEB_PROP_MAP,
  1273. "CExposedStream(%08X):Flush returns with not-dirty\n", this));
  1274. // flushing a stream which isn't a property stream
  1275. // this could be optimized by propagating a 'no property streams'
  1276. // flag up the storage hierachy such that FlushBufferedData is
  1277. // not even called for non-property streams.
  1278. return S_OK;
  1279. }
  1280. hr=CheckReverted();
  1281. if (S_OK!=hr) goto Exit;
  1282. olAssert( _pst != NULL );
  1283. olAssert( _pb != NULL );
  1284. olAssert( _powner != NULL );
  1285. // notify our owner that we are about to perform a write
  1286. hr = RtlOnMappedStreamEvent( (void*)_powner, (void*) _pb, _cbUsed );
  1287. if ( S_OK != hr ) goto Exit;
  1288. hr = _pst->WriteAt(0, _pb, _cbUsed, &cbWritten);
  1289. if( S_OK != hr ) goto Exit;
  1290. // notify our owner that we are done with the write
  1291. hr = RtlOnMappedStreamEvent( (VOID*)_powner, (VOID *) _pb, _cbUsed );
  1292. if( S_OK != hr ) goto Exit;
  1293. if (_cbUsed < _cbOriginalStreamSize)
  1294. {
  1295. // if the stream is shrinking, this is a good time to do it.
  1296. hr = _pst->SetSize(_cbUsed);
  1297. if (S_OK!=hr) goto Exit;
  1298. }
  1299. Exit:
  1300. if (hr == S_OK || hr == STG_E_REVERTED)
  1301. {
  1302. _fDirty = FALSE;
  1303. }
  1304. olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):Flush %s returns hr=%08X\n",
  1305. this, hr != S_OK ? "exception" : "", hr));
  1306. return hr;
  1307. }
  1308. //+--------------------------------------------------------------
  1309. //
  1310. // Member: CExposedStream::FlushBufferedData, public
  1311. //
  1312. // Synopsis: Flush out the property buffers.
  1313. //
  1314. //---------------------------------------------------------------
  1315. SCODE CExposedStream::FlushBufferedData()
  1316. {
  1317. SCODE sc = S_OK;
  1318. olDebugOut((DEB_ITRACE, "In CExposedStream::FlushBufferedData:%p()\n",
  1319. this));
  1320. Flush(&sc);
  1321. olDebugOut((DEB_PROP_MAP,
  1322. "CExposedStream(%08X):FlushBufferedData returns %08X\n",
  1323. this, sc));
  1324. return sc;
  1325. }
  1326. #endif // ifdef NEWPROPS