Source code of Windows XP (NT5)
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.

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