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.

1013 lines
23 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // utstream.cpp
  5. //
  6. // Contents:
  7. // Ole stream utilities
  8. //
  9. // Classes:
  10. //
  11. // Functions:
  12. //
  13. // History:
  14. // 10-May-94 KevinRo Added ansi versions of StringStream stuff
  15. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  16. // memory allocations.
  17. // 01/11/94 - alexgo - added VDATEHEAP macros to every function
  18. // 12/07/93 - ChrisWe - file inspection and cleanup; fixed
  19. // String reading and writing to cope with OLESTR, and
  20. // with differing alignment requirements
  21. // 06/23/93 - SriniK - moved ReadStringStream(),
  22. // WriteStringStream(), and OpenOrCreateStream() here
  23. // from api.cpp and ole2.cpp
  24. // 03/14/92 - SriniK - created
  25. //
  26. //-----------------------------------------------------------------------------
  27. #include <le2int.h>
  28. #pragma SEG(utstream)
  29. #include <reterr.h>
  30. #include <limits.h>
  31. NAME_SEG(UtStream)
  32. ASSERTDATA
  33. // this constant is used to size string buffers when we attempt to write out
  34. // a string and its length in one write call
  35. #define UTSTRINGBUF_SIZE 100
  36. // REVIEW, I thought that OpenStream already had an option to do this. If
  37. // so, this function shouldn't be used in our code. But we can't remove it
  38. // because it is exported to the outside.
  39. // this is exported to the outside
  40. #pragma SEG(OpenOrCreateStream)
  41. STDAPI OpenOrCreateStream(IStorage FAR * pstg, LPCOLESTR pwcsName,
  42. IStream FAR* FAR* ppstm)
  43. {
  44. VDATEHEAP();
  45. HRESULT error;
  46. error = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE,
  47. 0, 0, ppstm);
  48. if (GetScode(error) == STG_E_FILEALREADYEXISTS)
  49. error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
  50. return(error);
  51. }
  52. // returns S_OK when string read and allocated (even if zero length)
  53. STDAPI ReadStringStream(CStmBufRead & StmRead, LPOLESTR FAR * ppsz)
  54. {
  55. VDATEHEAP();
  56. ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
  57. HRESULT hresult;
  58. // initialize the the string pointer for error returns
  59. *ppsz = NULL;
  60. if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
  61. return hresult;
  62. // is string empty?
  63. if (cb == 0)
  64. return(NOERROR);
  65. // allocate memory to hold the string
  66. if (!(*ppsz = (LPOLESTR)PubMemAlloc(cb)))
  67. return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
  68. // read the string; this includes a trailing NULL
  69. if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
  70. goto errRtn;
  71. return(NOERROR);
  72. errRtn:
  73. // delete the string, and return without one
  74. PubMemFree(*ppsz);
  75. *ppsz = NULL;
  76. return(hresult);
  77. }
  78. //+---------------------------------------------------------------------------
  79. //
  80. // Function: ReadStringStreamA
  81. //
  82. // Synopsis: Read a ANSI stream from the stream
  83. //
  84. // Effects:
  85. //
  86. // Arguments: [pstm] -- Stream to read from
  87. // [ppsz] -- Output pointer
  88. //
  89. // Requires:
  90. //
  91. // Returns:
  92. //
  93. // Signals:
  94. //
  95. // Modifies:
  96. //
  97. // Algorithm:
  98. //
  99. // History: 5-12-94 kevinro Created
  100. // 2-20-95 KentCe Converted to buffer stream reads.
  101. //
  102. // Notes:
  103. //
  104. //----------------------------------------------------------------------------
  105. STDAPI ReadStringStreamA(CStmBufRead & StmRead, LPSTR FAR * ppsz)
  106. {
  107. VDATEHEAP();
  108. ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
  109. HRESULT hresult;
  110. // initialize the the string pointer for error returns
  111. *ppsz = NULL;
  112. if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
  113. return hresult;
  114. // is string empty?
  115. if (cb == 0)
  116. return(NOERROR);
  117. // allocate memory to hold the string
  118. if (!(*ppsz = (LPSTR)PubMemAlloc(cb)))
  119. return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
  120. // read the string; this includes a trailing NULL
  121. if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
  122. goto errRtn;
  123. return(NOERROR);
  124. errRtn:
  125. // delete the string, and return without one
  126. PubMemFree(*ppsz);
  127. *ppsz = NULL;
  128. return(hresult);
  129. }
  130. // this is exported to the outside
  131. STDAPI WriteStringStream(CStmBufWrite & StmWrite, LPCOLESTR psz)
  132. {
  133. VDATEHEAP();
  134. HRESULT error;
  135. ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
  136. // if the string pointer is NULL, use zero length
  137. if (!psz)
  138. cb = 0;
  139. else
  140. {
  141. // count is length of string, plus terminating null
  142. cb = (1 + _xstrlen(psz))*sizeof(OLECHAR);
  143. // if possible, do a single write instead of two
  144. if (cb <= UTSTRINGBUF_SIZE)
  145. {
  146. BYTE bBuf[sizeof(ULONG)+
  147. UTSTRINGBUF_SIZE*sizeof(OLECHAR)];
  148. // buffer for count and string
  149. // we have to use _xmemcpy to copy the length into
  150. // the buffer to avoid potential boundary faults,
  151. // since bBuf might not be aligned strictly enough
  152. // to do *((ULONG FAR *)bBuf) = cb;
  153. _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
  154. sizeof(cb));
  155. _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
  156. (const void FAR *)psz, cb);
  157. // write contents of buffer all at once
  158. return( StmWrite.Write((VOID FAR *)bBuf,
  159. cb+sizeof(ULONG)));
  160. }
  161. }
  162. // if we got here, our buffer isn't large enough, so we do two writes
  163. // first, write the length
  164. if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
  165. return error;
  166. // are we are done writing the string?
  167. if (psz == NULL)
  168. return NOERROR;
  169. // write the string
  170. return(StmWrite.Write((VOID FAR *)psz, cb));
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Function: WriteStringStreamA
  175. //
  176. // Synopsis: Writes an ANSI string to a stream in a length prefixed format.
  177. //
  178. // Effects:
  179. //
  180. // Arguments: [pstm] -- Stream
  181. // [psz] -- Ansi string to write
  182. //
  183. // Requires:
  184. //
  185. // Returns:
  186. //
  187. // Signals:
  188. //
  189. // Modifies:
  190. //
  191. // Algorithm:
  192. //
  193. // History: 5-12-94 kevinro Created
  194. // 2-20-95 KentCe Converted to buffer stream writes.
  195. //
  196. // Notes:
  197. //
  198. //----------------------------------------------------------------------------
  199. FARINTERNAL_(HRESULT) WriteStringStreamA(CStmBufWrite & StmWrite, LPCSTR psz)
  200. {
  201. VDATEHEAP();
  202. HRESULT error;
  203. ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
  204. // if the string pointer is NULL, use zero length
  205. if (!psz)
  206. cb = 0;
  207. else
  208. {
  209. // count is length of string, plus terminating null
  210. cb = (1 + strlen(psz));
  211. // if possible, do a single write instead of two
  212. if (cb <= UTSTRINGBUF_SIZE)
  213. {
  214. BYTE bBuf[sizeof(ULONG)+
  215. UTSTRINGBUF_SIZE];
  216. // buffer for count and string
  217. // we have to use _xmemcpy to copy the length into
  218. // the buffer to avoid potential boundary faults,
  219. // since bBuf might not be aligned strictly enough
  220. // to do *((ULONG FAR *)bBuf) = cb;
  221. _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
  222. sizeof(cb));
  223. _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
  224. (const void FAR *)psz, cb);
  225. // write contents of buffer all at once
  226. return(StmWrite.Write((VOID FAR *)bBuf,
  227. cb+sizeof(ULONG)));
  228. }
  229. }
  230. // if we got here, our buffer isn't large enough, so we do two writes
  231. // first, write the length
  232. if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
  233. return error;
  234. // are we are done writing the string?
  235. if (psz == NULL)
  236. return NOERROR;
  237. // write the string
  238. return(StmWrite.Write((VOID FAR *)psz, cb));
  239. }
  240. //+-------------------------------------------------------------------------
  241. //
  242. // Function: StRead
  243. //
  244. // Synopsis: Stream read that only succeeds if all requested bytes read
  245. //
  246. // Arguments: [pStm] -- source stream
  247. // [pvBuffer] -- destination buffer
  248. // [ulcb] -- bytes to read
  249. //
  250. // Returns: S_OK if successful, else error code
  251. //
  252. // Algorithm:
  253. //
  254. // History: 18-May-94 AlexT Added header block, fixed S_FALSE case
  255. //
  256. // Notes:
  257. //
  258. //--------------------------------------------------------------------------
  259. #pragma SEG(StRead)
  260. FARINTERNAL_(HRESULT) StRead(IStream FAR * pStm, LPVOID pvBuffer, ULONG ulcb)
  261. {
  262. VDATEHEAP();
  263. HRESULT hr;
  264. ULONG cbRead;
  265. hr = pStm->Read(pvBuffer, ulcb, &cbRead);
  266. if (FAILED(hr))
  267. {
  268. return(hr);
  269. }
  270. if (ulcb == cbRead)
  271. {
  272. return(S_OK);
  273. }
  274. // We got a success code but not enough bytes - turn it into an error
  275. return(STG_E_READFAULT);
  276. }
  277. // if fRelative is FALSE then dwSize is the size of the stream
  278. // if it is TRUE then find the current seek position and add dwSize to that
  279. // and then set it as the stream size.
  280. FARINTERNAL StSetSize(LPSTREAM pstm, DWORD dwSize, BOOL fRelative)
  281. {
  282. VDATEHEAP();
  283. LARGE_INTEGER large_int; // indicates where to seek to
  284. ULARGE_INTEGER ularge_int; // indicates absolute position
  285. ULARGE_INTEGER ularge_integer; // the size we will set for the stream
  286. HRESULT error;
  287. LISet32(large_int, 0);
  288. ULISet32(ularge_integer, dwSize);
  289. if (fRelative)
  290. {
  291. if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int))
  292. return(error);
  293. // REVIEW: is there a routine to do 64 bit addition ???
  294. ularge_integer.LowPart += ularge_int.LowPart;
  295. }
  296. return(pstm->SetSize(ularge_integer));
  297. }
  298. // REVIEW, is this actually used?
  299. #pragma SEG(StSave10NativeData)
  300. FARINTERNAL_(HRESULT) StSave10NativeData(IStorage FAR* pstgSave,
  301. HANDLE hNative, BOOL fIsOle1Interop)
  302. {
  303. VDATEHEAP();
  304. DWORD dwSize;
  305. HRESULT error;
  306. if (!hNative)
  307. return ReportResult(0, E_UNSPEC, 0, 0);
  308. if (!(dwSize = (ULONG) GlobalSize (hNative)))
  309. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  310. #ifdef OLE1INTEROP
  311. if ( fIsOle1Interop )
  312. {
  313. LPLOCKBYTES plkbyt;
  314. LPSTORAGE pstgNative= NULL;
  315. const DWORD grfStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
  316. | STGM_DIRECT ;
  317. if ((error = CreateILockBytesOnHGlobal (hNative, FALSE, &plkbyt))!=NOERROR)
  318. goto errRtn;
  319. if ((error = StgOpenStorageOnILockBytes (plkbyt, (LPSTORAGE)NULL, grfStg,
  320. (SNB)NULL, 0, &pstgNative)) != NOERROR){
  321. error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
  322. plkbyt->Release();
  323. goto errRtn;
  324. }
  325. pstgNative->CopyTo (0, NULL, 0, pstgSave);
  326. plkbyt->Release();
  327. pstgNative->Release();
  328. }
  329. else
  330. #endif
  331. {
  332. LPSTREAM lpstream = NULL;
  333. if (error = OpenOrCreateStream(pstgSave, OLE10_NATIVE_STREAM, &lpstream))
  334. goto errRtn;
  335. if (error = StWrite(lpstream, &dwSize, sizeof(DWORD))) {
  336. lpstream->Release();
  337. goto errRtn;
  338. }
  339. error = UtHGLOBALtoStm(hNative, dwSize, lpstream);
  340. lpstream->Release();
  341. }
  342. errRtn:
  343. return error;
  344. }
  345. #pragma SEG(StSave10ItemName)
  346. FARINTERNAL StSave10ItemName
  347. (IStorage FAR* pstg,
  348. LPCSTR szItemNameAnsi)
  349. {
  350. VDATEHEAP();
  351. CStmBufWrite StmWrite;
  352. HRESULT hresult;
  353. if ((hresult = StmWrite.OpenOrCreateStream(pstg, OLE10_ITEMNAME_STREAM))
  354. != NOERROR)
  355. {
  356. return hresult;
  357. }
  358. hresult = WriteStringStreamA(StmWrite, szItemNameAnsi);
  359. if (FAILED(hresult))
  360. {
  361. goto errRtn;
  362. }
  363. hresult = StmWrite.Flush();
  364. errRtn:
  365. StmWrite.Release();
  366. return hresult;
  367. }
  368. #pragma SEG(StRead10NativeData)
  369. FARINTERNAL StRead10NativeData
  370. (IStorage FAR* pstg,
  371. HANDLE FAR* phNative)
  372. {
  373. DWORD dwSize;
  374. LPSTREAM pstream = NULL;
  375. HRESULT hresult;
  376. HANDLE hBits = NULL;
  377. void FAR *lpBits = NULL;
  378. VDATEHEAP();
  379. *phNative = NULL;
  380. RetErr (pstg->OpenStream (OLE10_NATIVE_STREAM, NULL, STGM_SALL, 0, &pstream));
  381. ErrRtnH (StRead (pstream, &dwSize, sizeof (DWORD)));
  382. // initialize this for error return cases
  383. // allocate a new handle
  384. if (!(hBits = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dwSize)) // going to pass this to DDE.
  385. || !(lpBits = (BYTE *)GlobalLock(hBits)))
  386. {
  387. hresult = ResultFromScode(E_OUTOFMEMORY);
  388. goto errRtn;
  389. }
  390. // read the stream into the allocated memory
  391. if (hresult = StRead(pstream, lpBits, dwSize))
  392. goto errRtn;
  393. // if we got this far, return new handle
  394. *phNative = hBits;
  395. errRtn:
  396. // unlock the handle, if it was successfully locked
  397. if (lpBits)
  398. GlobalUnlock(hBits);
  399. // free the handle if there was an error
  400. if ((hresult != NOERROR) && hBits)
  401. GlobalFree(hBits);
  402. if (pstream)
  403. pstream->Release();
  404. return hresult;
  405. }
  406. //+---------------------------------------------------------------------------
  407. //
  408. // Member: CStmBuf::CStmBuf, public
  409. //
  410. // Synopsis: Constructor.
  411. //
  412. // Arguments: None.
  413. //
  414. // Returns: None.
  415. //
  416. // History: 20-Feb-95 KentCe Created
  417. //
  418. // Notes:
  419. //
  420. //----------------------------------------------------------------------------
  421. CStmBuf::CStmBuf(void)
  422. {
  423. m_pStm = NULL;
  424. }
  425. //+---------------------------------------------------------------------------
  426. //
  427. // Member: CStmBuf::~CStmBuf, public
  428. //
  429. // Synopsis: Destructor.
  430. //
  431. // Arguments: None.
  432. //
  433. // Returns: None.
  434. //
  435. // History: 20-Feb-95 KentCe Created
  436. //
  437. // Notes:
  438. //
  439. //----------------------------------------------------------------------------
  440. CStmBuf::~CStmBuf(void)
  441. {
  442. //
  443. // Verify that the programmer released the stream interface.
  444. //
  445. Assert(m_pStm == NULL);
  446. }
  447. //+---------------------------------------------------------------------------
  448. //
  449. // Member: CStmBufRead::Init, public
  450. //
  451. // Synopsis: Define the stream interface to read from.
  452. //
  453. // Arguments: [pstm] -- Pointer to stream to read.
  454. //
  455. // Returns: None.
  456. //
  457. // History: 20-Feb-95 KentCe Created
  458. //
  459. // Notes: Release method must be called.
  460. //
  461. //----------------------------------------------------------------------------
  462. void CStmBufRead::Init(IStream * pstm)
  463. {
  464. Assert(m_pStm == NULL);
  465. m_pStm = pstm;
  466. m_pStm->AddRef();
  467. Reset();
  468. }
  469. //+---------------------------------------------------------------------------
  470. //
  471. // Member: CStmBufRead::OpenStream, public
  472. //
  473. // Synopsis: Open a stream for reading.
  474. //
  475. // Arguments: [pstg] -- Pointer to storage that contains stream to open.
  476. // [pwcsName] -- Name of stream to open.
  477. //
  478. // Returns: HRESULT.
  479. //
  480. // History: 20-Feb-95 KentCe Created
  481. //
  482. // Notes: Release method must be called.
  483. //
  484. //----------------------------------------------------------------------------
  485. HRESULT CStmBufRead::OpenStream(IStorage * pstg, const OLECHAR * pwcsName)
  486. {
  487. VDATEHEAP();
  488. HRESULT hr;
  489. Assert(m_pStm == NULL);
  490. hr = pstg->OpenStream(pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
  491. &m_pStm);
  492. Reset();
  493. return hr;
  494. }
  495. //+---------------------------------------------------------------------------
  496. //
  497. // Member: CStmBufRead::Read, public
  498. //
  499. // Synopsis: Read data from the stream.
  500. //
  501. // Arguments: [pBuf] - Address to store read bytes in.
  502. // [cBuf] - Maximum number of bytes to read.
  503. //
  504. // Returns: HRESULT.
  505. //
  506. // History: 20-Feb-95 KentCe Created
  507. //
  508. // Notes:
  509. //
  510. //----------------------------------------------------------------------------
  511. HRESULT CStmBufRead::Read(PVOID pBuf, ULONG cBuf)
  512. {
  513. ULONG cnt;
  514. HRESULT hr;
  515. //
  516. // While more bytes to read.
  517. //
  518. while (cBuf)
  519. {
  520. //
  521. // If our buffer is empty, read more data.
  522. //
  523. if (m_cBuffer == 0)
  524. {
  525. hr = m_pStm->Read(m_aBuffer, sizeof(m_aBuffer), &m_cBuffer);
  526. if (FAILED(hr))
  527. return hr;
  528. if (m_cBuffer == 0)
  529. return STG_E_READFAULT;
  530. m_pBuffer = m_aBuffer;
  531. }
  532. //
  533. // Determine number of bytes to read.
  534. //
  535. cnt = min(m_cBuffer, cBuf);
  536. //
  537. // Copy the input from the input buffer, update variables.
  538. //
  539. memcpy(pBuf, m_pBuffer, cnt);
  540. pBuf = (PBYTE)pBuf + cnt;
  541. cBuf -= cnt;
  542. m_pBuffer += cnt;
  543. m_cBuffer -= cnt;
  544. }
  545. return S_OK;
  546. }
  547. //+---------------------------------------------------------------------------
  548. //
  549. // Member: CStmBufRead::ReadLong, public
  550. //
  551. // Synopsis: Read a long value from the stream.
  552. //
  553. // Arguments: [plValue] - Address of long to fill.
  554. //
  555. // Returns: HRESULT.
  556. //
  557. // History: 20-Feb-95 KentCe Created
  558. //
  559. // Notes:
  560. //
  561. //----------------------------------------------------------------------------
  562. HRESULT CStmBufRead::ReadLong(LONG * plValue)
  563. {
  564. return Read(plValue, sizeof(LONG));
  565. }
  566. //+---------------------------------------------------------------------------
  567. //
  568. // Member: CStmBufRead::Reset
  569. //
  570. // Synopsis: Reset buffer variables.
  571. //
  572. // Arguments: None.
  573. //
  574. // Returns: None.
  575. //
  576. // History: 20-Feb-95 KentCe Created
  577. //
  578. // Notes:
  579. //
  580. //----------------------------------------------------------------------------
  581. void CStmBufRead::Reset(void)
  582. {
  583. m_pBuffer = m_aBuffer;
  584. m_cBuffer = 0;
  585. }
  586. //+---------------------------------------------------------------------------
  587. //
  588. // Member: CStmBufRead::Release, public
  589. //
  590. // Synopsis: Release read stream interface.
  591. //
  592. // Arguments: None.
  593. //
  594. // Returns: None.
  595. //
  596. // History: 20-Feb-95 KentCe Created
  597. //
  598. // Notes:
  599. //
  600. //----------------------------------------------------------------------------
  601. void CStmBufRead::Release()
  602. {
  603. if (m_pStm)
  604. {
  605. m_pStm->Release();
  606. m_pStm = NULL;
  607. }
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // Member: CStmBufWrite::Init, public
  612. //
  613. // Synopsis: Define the stream interface to write to.
  614. //
  615. // Arguments: [pstm] -- Pointer to stream to write.
  616. //
  617. // Returns: None.
  618. //
  619. // History: 20-Feb-95 KentCe Created
  620. //
  621. // Notes: Release method must be called.
  622. //
  623. //----------------------------------------------------------------------------
  624. void CStmBufWrite::Init(IStream * pstm)
  625. {
  626. Assert(m_pStm == NULL);
  627. m_pStm = pstm;
  628. m_pStm->AddRef();
  629. Reset();
  630. }
  631. //+---------------------------------------------------------------------------
  632. //
  633. // Member: CStmBufRead::OpenOrCreateStream, public
  634. //
  635. // Synopsis: Open/Create a stream for writing.
  636. //
  637. // Arguments: [pstg] -- Pointer to storage that contains stream to open.
  638. // [pwcsName] -- Name of stream to open.
  639. //
  640. // Returns: HRESULT.
  641. //
  642. // History: 20-Feb-95 KentCe Created
  643. //
  644. // Notes: Release method must be called.
  645. //
  646. //----------------------------------------------------------------------------
  647. HRESULT CStmBufWrite::OpenOrCreateStream(IStorage * pstg,
  648. const OLECHAR * pwcsName)
  649. {
  650. VDATEHEAP();
  651. HRESULT hr;
  652. hr = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE, 0, 0,
  653. &m_pStm);
  654. if (hr == STG_E_FILEALREADYEXISTS)
  655. {
  656. hr = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, &m_pStm);
  657. }
  658. Reset();
  659. return hr;
  660. }
  661. //+---------------------------------------------------------------------------
  662. //
  663. // Member: CStmBufRead::CreateStream, public
  664. //
  665. // Synopsis: Create a stream for writing.
  666. //
  667. // Arguments: [pstg] -- Pointer storage that contains stream to create.
  668. // [pwcsName] -- Name of stream to create.
  669. //
  670. // Returns: HRESULT.
  671. //
  672. // History: 20-Feb-95 KentCe Created
  673. //
  674. // Notes: Release method must be called.
  675. //
  676. //----------------------------------------------------------------------------
  677. HRESULT CStmBufWrite::CreateStream(IStorage * pstg, const OLECHAR * pwcsName)
  678. {
  679. VDATEHEAP();
  680. HRESULT hr;
  681. hr = pstg->CreateStream(pwcsName, STGM_CREATE | STGM_READWRITE |
  682. STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStm);
  683. Reset();
  684. return hr;
  685. }
  686. //+---------------------------------------------------------------------------
  687. //
  688. // Member: CStmBufWrite::Write, public
  689. //
  690. // Synopsis: Write data to the stream.
  691. //
  692. // Arguments: [pBuf] - Address to store write bytes to.
  693. // [cBuf] - Maximum number of bytes to write.
  694. //
  695. // Returns: HRESULT.
  696. //
  697. // History: 20-Feb-95 KentCe Created
  698. //
  699. // Notes:
  700. //
  701. //----------------------------------------------------------------------------
  702. HRESULT CStmBufWrite::Write(void const * pBuf, ULONG cBuf)
  703. {
  704. ULONG cnt;
  705. HRESULT hr;
  706. //
  707. // Keep writing until the caller's buffer is empty.
  708. //
  709. while (cBuf)
  710. {
  711. //
  712. // Compute the number of bytes to copy.
  713. //
  714. cnt = min(m_cBuffer, cBuf);
  715. //
  716. // Copy to the internal write buffer and update variables.
  717. //
  718. memcpy(m_pBuffer, pBuf, cnt);
  719. pBuf = (PBYTE)pBuf + cnt;
  720. cBuf -= cnt;
  721. m_pBuffer += cnt;
  722. m_cBuffer -= cnt;
  723. //
  724. // On full internal buffer, flush.
  725. //
  726. if (m_cBuffer == 0)
  727. {
  728. LEDebugOut((DEB_WARN, "WARNING: Multiple buffer flushes.\n"));
  729. hr = Flush();
  730. if (FAILED(hr))
  731. {
  732. return hr;
  733. }
  734. }
  735. }
  736. return S_OK;
  737. }
  738. //+---------------------------------------------------------------------------
  739. //
  740. // Member: CStmBufWrite::WriteLong, public
  741. //
  742. // Synopsis: Write long value to the stream.
  743. //
  744. // Arguments: [lValue] - Long value to write.
  745. //
  746. // Returns: HRESULT.
  747. //
  748. // History: 20-Feb-95 KentCe Created
  749. //
  750. // Notes:
  751. //
  752. //----------------------------------------------------------------------------
  753. HRESULT CStmBufWrite::WriteLong(LONG lValue)
  754. {
  755. return Write(&lValue, sizeof(LONG));
  756. }
  757. //+---------------------------------------------------------------------------
  758. //
  759. // Member: CStmBufWrite::Flush, public
  760. //
  761. // Synopsis: Flush write buffer to the system.
  762. //
  763. // Arguments: None.
  764. //
  765. // Returns: HRESULT.
  766. //
  767. // History: 20-Feb-95 KentCe Created
  768. //
  769. // Notes: Performs a write of the stream buffer to the system, does not
  770. // force a flush to disk.
  771. //
  772. //----------------------------------------------------------------------------
  773. HRESULT CStmBufWrite::Flush(void)
  774. {
  775. ULONG cnt;
  776. HRESULT hr;
  777. //
  778. // This might be an overactive assert, but shouldn't happen.
  779. //
  780. Assert(m_cBuffer != sizeof(m_aBuffer));
  781. hr = m_pStm->Write(m_aBuffer, sizeof(m_aBuffer) - m_cBuffer, &cnt);
  782. if (FAILED(hr))
  783. {
  784. return hr;
  785. }
  786. if (cnt != sizeof(m_aBuffer) - m_cBuffer)
  787. {
  788. return STG_E_MEDIUMFULL;
  789. }
  790. Reset();
  791. return S_OK;
  792. }
  793. //+---------------------------------------------------------------------------
  794. //
  795. // Member: CStmBufWrite::Reset, public
  796. //
  797. // Synopsis: Reset buffer variables.
  798. //
  799. // Arguments: None.
  800. //
  801. // Returns: None.
  802. //
  803. // History: 20-Feb-95 KentCe Created
  804. //
  805. // Notes:
  806. //
  807. //----------------------------------------------------------------------------
  808. void CStmBufWrite::Reset(void)
  809. {
  810. m_pBuffer = m_aBuffer;
  811. m_cBuffer = sizeof(m_aBuffer);
  812. }
  813. //+---------------------------------------------------------------------------
  814. //
  815. // Member: CStmBufWrite::Release, public
  816. //
  817. // Synopsis: Release write stream interface.
  818. //
  819. // Arguments: None.
  820. //
  821. // Returns: None.
  822. //
  823. // History: 20-Feb-95 KentCe Created
  824. //
  825. // Notes:
  826. //
  827. //----------------------------------------------------------------------------
  828. void CStmBufWrite::Release()
  829. {
  830. if (m_pStm)
  831. {
  832. //
  833. // Verify that flush was called.
  834. //
  835. Assert(m_cBuffer == sizeof(m_aBuffer));
  836. m_pStm->Release();
  837. m_pStm = NULL;
  838. }
  839. }