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.

3644 lines
84 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: memstm.cpp
  7. //
  8. // Contents: Implementations of IStream and ILockBytes on memory
  9. // (versus the file system)
  10. //
  11. // Classes: CMemStm
  12. // CMemBytes
  13. // CMarshalMemStm
  14. // CMarshalMemBytes
  15. //
  16. // Functions: CreateMemStm
  17. // CloneMemStm
  18. // ReleaseMemStm
  19. // CreateStreamOnHGlobal
  20. // GetHGlobalFromStream
  21. // CMemStmUnMarshal
  22. // CMemBytesUnMarshall
  23. //
  24. // History: dd-mmm-yy Author Comment
  25. // 31-Jan-95 t-ScottH added Dump methods to CMemStm and CMemBytes
  26. // (_DEBUG only)
  27. // added DumpCMemStm and CMemBytes APIs
  28. // 04-Nov-94 ricksa Made CMemStm class multithread safe.
  29. // 24-Jan-94 alexgo first pass at converting to Cairo-style
  30. // memory allocation
  31. // 11-Jan-94 alexgo added VDATEHEAP macros to every function &
  32. // method, fixed compile warnings, removed
  33. // custom marshalling code. Memory streams
  34. // and ILockBytes now use standard
  35. // marshalling.
  36. // 16-Dec-93 alexgo fixed memory reference bugs (bad pointer)
  37. // 02-Dec-93 alexgo 32bit port, implement CMemStm::CopyTo
  38. // 11/22/93 - ChrisWe - replace overloaded ==, != with
  39. // IsEqualIID and IsEqualCLSID
  40. //
  41. // Notes:
  42. //
  43. //--------------------------------------------------------------------------
  44. #include <le2int.h>
  45. #pragma SEG(memstm)
  46. #include <nturtl.h>
  47. #include "memstm.h"
  48. #include "sem.hxx"
  49. #include <reterr.h>
  50. #ifdef _DEBUG
  51. #include "dbgdump.h"
  52. #endif // _DEBUG
  53. NAME_SEG(CMemStm)
  54. ASSERTDATA
  55. // CRefMutexSem implementation
  56. //
  57. // Instances of this class are shared among all CMemStm objects
  58. // cloned from a common CMemStm object, as well as their parent.
  59. //
  60. // This guarantees synchronization between all instances of CMemStm that share common data
  61. CRefMutexSem::CRefMutexSem() : m_lRefs(1)
  62. {
  63. // Note: we begin life with one reference
  64. }
  65. CRefMutexSem* CRefMutexSem::CreateInstance()
  66. {
  67. CRefMutexSem* prefMutexSem = NULL;
  68. prefMutexSem = new CRefMutexSem();
  69. if (prefMutexSem != NULL)
  70. {
  71. if (prefMutexSem->FInit() == FALSE)
  72. {
  73. ASSERT(FALSE);
  74. delete prefMutexSem;
  75. prefMutexSem = NULL;
  76. }
  77. }
  78. return prefMutexSem;
  79. }
  80. BOOL CRefMutexSem::FInit()
  81. {
  82. return m_mxs.FInit();
  83. }
  84. ULONG CRefMutexSem::AddRef()
  85. {
  86. return InterlockedIncrement (&m_lRefs);
  87. }
  88. ULONG CRefMutexSem::Release()
  89. {
  90. LONG lRefs = InterlockedDecrement (&m_lRefs);
  91. if (lRefs == 0)
  92. {
  93. delete this;
  94. }
  95. return lRefs;
  96. }
  97. void CRefMutexSem::RequestCS()
  98. {
  99. m_mxs.Request();
  100. }
  101. void CRefMutexSem::ReleaseCS()
  102. {
  103. m_mxs.Release();
  104. }
  105. const CMutexSem2* CRefMutexSem::GetMutexSem()
  106. {
  107. return &m_mxs;
  108. }
  109. inline CRefMutexAutoLock::CRefMutexAutoLock (CRefMutexSem* pmxs)
  110. {
  111. Win4Assert (pmxs != NULL);
  112. m_pmxs = pmxs;
  113. m_pmxs->RequestCS();
  114. END_CONSTRUCTION (CRefMutexAutoLock);
  115. }
  116. inline CRefMutexAutoLock::~CRefMutexAutoLock()
  117. {
  118. m_pmxs->ReleaseCS();
  119. }
  120. // Shared memory IStream implementation
  121. //
  122. //+-------------------------------------------------------------------------
  123. //
  124. // Member: CMemStm::CMemStm
  125. //
  126. // Synopsis: constructor for memory stream
  127. //
  128. // Arguments: none
  129. //
  130. // History: 20-Dec-94 Rickhi moved from h file
  131. //
  132. //--------------------------------------------------------------------------
  133. CMemStm::CMemStm()
  134. {
  135. m_hMem = NULL;
  136. m_pData = NULL;
  137. m_pos = 0;
  138. m_refs = 0;
  139. m_pmxs = NULL;
  140. }
  141. CMemStm::~CMemStm()
  142. {
  143. if (m_pmxs != NULL)
  144. {
  145. m_pmxs->Release();
  146. }
  147. }
  148. //+-------------------------------------------------------------------------
  149. //
  150. // Member: CMemStm::QueryInterface
  151. //
  152. // Synopsis: retrieves the requested interface
  153. //
  154. // Effects:
  155. //
  156. // Arguments: [iidInterface] -- the requested interface ID
  157. // [ppvObj] -- where to put the interface pointer
  158. //
  159. // Requires:
  160. //
  161. // Returns: NOERROR, E_OUTOFMEMORY, E_NOINTERFACE
  162. //
  163. // Signals:
  164. //
  165. // Modifies:
  166. //
  167. // Derivation: IStream
  168. //
  169. // Algorithm:
  170. //
  171. // History: dd-mmm-yy Author Comment
  172. // 04-Nov-94 ricksa Modified for multithreading
  173. // 11-Jan-94 alexgo removed QI for IMarshal so that
  174. // the standard marshaller is used.
  175. // This is fix marshalling across
  176. // process on 32bit platforms.
  177. // 02-Dec-93 alexgo 32bit port
  178. //
  179. // Notes:
  180. //
  181. //--------------------------------------------------------------------------
  182. #pragma SEG(CMemStm_QueryInterface)
  183. STDMETHODIMP CMemStm::QueryInterface(REFIID iidInterface,
  184. void FAR* FAR* ppvObj)
  185. {
  186. VDATEHEAP();
  187. HRESULT error;
  188. VDATEPTROUT( ppvObj, LPVOID );
  189. *ppvObj = NULL;
  190. VDATEIID( iidInterface );
  191. // Two interfaces supported: IUnknown, IStream
  192. if (m_pData != NULL && (IsEqualIID(iidInterface, IID_IStream) ||
  193. IsEqualIID(iidInterface, IID_ISequentialStream) ||
  194. IsEqualIID(iidInterface, IID_IUnknown)))
  195. {
  196. AddRef(); // A pointer to this object is returned
  197. *ppvObj = this;
  198. error = NOERROR;
  199. }
  200. #ifndef WIN32
  201. else if (IsEqualIID(iidInterface, IID_IMarshal))
  202. {
  203. *ppvObj = (LPVOID) CMarshalMemStm::Create(this);
  204. if (*ppvObj != NULL)
  205. {
  206. error = NOERROR;
  207. }
  208. else
  209. {
  210. error = ResultFromScode(E_OUTOFMEMORY);
  211. }
  212. }
  213. #endif
  214. else
  215. { // Not accessible or unsupported interface
  216. *ppvObj = NULL;
  217. error = ResultFromScode(E_NOINTERFACE);
  218. }
  219. return error;
  220. }
  221. //+-------------------------------------------------------------------------
  222. //
  223. // Member: CMemStm::AddRef
  224. //
  225. // Synopsis: increments the reference count
  226. //
  227. // Effects:
  228. //
  229. // Arguments: void
  230. //
  231. // Requires:
  232. //
  233. // Returns: ULONG -- the new reference count
  234. //
  235. // Signals:
  236. //
  237. // Modifies:
  238. //
  239. // Derivation: IStream
  240. //
  241. // Algorithm:
  242. //
  243. // History: dd-mmm-yy Author Comment
  244. // 02-Dec-93 alexgo 32bit port
  245. // 04-Nov-94 ricksa Modified for multithreading
  246. //
  247. // Notes:
  248. //
  249. //--------------------------------------------------------------------------
  250. #pragma SEG(CMemStm_AddRef)
  251. STDMETHODIMP_(ULONG) CMemStm::AddRef(void)
  252. {
  253. VDATEHEAP();
  254. return InterlockedIncrement((LONG *) &m_refs);
  255. }
  256. //+-------------------------------------------------------------------------
  257. //
  258. // Member: CMemStm::Release
  259. //
  260. // Synopsis: decrements the reference count
  261. //
  262. // Effects: deletes the object when ref count == 0
  263. //
  264. // Arguments: void
  265. //
  266. // Requires:
  267. //
  268. // Returns: ULONG -- the new ref count
  269. //
  270. // Signals:
  271. //
  272. // Modifies:
  273. //
  274. // Derivation: IStream
  275. //
  276. // Algorithm:
  277. //
  278. // History: dd-mmm-yy Author Comment
  279. // 04-Nov-94 ricksa Modified for multithreading
  280. // 16-Dec-93 alexgo added GlobalUnlock of the MEMSTM handle
  281. // 02-Dec-93 alexgo 32bit port
  282. //
  283. // Notes:
  284. //
  285. //--------------------------------------------------------------------------
  286. #pragma SEG(CMemStm_Release)
  287. STDMETHODIMP_(ULONG) CMemStm::Release(void)
  288. {
  289. VDATEHEAP();
  290. // The reason for this here is that there is a race when releasing
  291. // this object. If two threads are trying to release this object
  292. // at the same time, there is a case where the first one dec's
  293. // the ref count & then loses the processor to the second thread.
  294. // This second thread decrements the reference count to 0 and frees
  295. // the memory. The first thread can no longer safely examine the
  296. // internal state of the object.
  297. ULONG ulResult = InterlockedDecrement((LONG *) &m_refs);
  298. if (ulResult == 0)
  299. {
  300. // this MEMSTM handle was GlobalLock'ed in ::Create
  301. // we unlock it here, as we no longer need it.
  302. GlobalUnlock(m_hMem);
  303. ReleaseMemStm(&m_hMem);
  304. delete this;
  305. }
  306. return ulResult;
  307. }
  308. //+-------------------------------------------------------------------------
  309. //
  310. // Member: CMemStm::Read
  311. //
  312. // Synopsis: reads [cb] bytes from the stream
  313. //
  314. // Effects:
  315. //
  316. // Arguments: [pb] -- where to put the data read
  317. // [cb] -- the number of bytes to read
  318. // [pcbRead] -- where to put the actual number of bytes
  319. // read
  320. //
  321. // Requires:
  322. //
  323. // Returns: HRESULT
  324. //
  325. // Signals:
  326. //
  327. // Modifies:
  328. //
  329. // Derivation: IStream
  330. //
  331. // Algorithm: uses xmemcpy
  332. //
  333. // History: dd-mmm-yy Author Comment
  334. // 04-Nov-94 ricksa Modified for multithreading
  335. // 02-Dec-93 alexgo 32bit port
  336. //
  337. // Notes:
  338. //
  339. //--------------------------------------------------------------------------
  340. #pragma SEG(CMemStm_Read)
  341. STDMETHODIMP CMemStm::Read(void HUGEP* pb, ULONG cb, ULONG FAR* pcbRead)
  342. {
  343. VDATEHEAP();
  344. HRESULT error = NOERROR;
  345. ULONG cbRead = cb;
  346. if(cb)
  347. {
  348. VDATEPTROUT( pb, char);
  349. }
  350. // Single thread
  351. CRefMutexAutoLock lck(m_pmxs);
  352. if (pcbRead)
  353. {
  354. VDATEPTROUT( pcbRead, ULONG );
  355. *pcbRead = 0L;
  356. }
  357. // cbRead + m_pos could cause roll-over.
  358. if ( ( (cbRead + m_pos) > m_pData->cb) || ( (cbRead + m_pos) < m_pos) )
  359. {
  360. // Caller is asking for more bytes than we have left
  361. if(m_pData->cb > m_pos)
  362. cbRead = m_pData->cb - m_pos;
  363. else
  364. cbRead = 0;
  365. }
  366. if (cbRead > 0)
  367. {
  368. Assert (m_pData->hGlobal);
  369. BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
  370. m_pData->hGlobal);
  371. if (NULL==pGlobal)
  372. {
  373. LEERROR(1, "GlobalLock Failed!");
  374. return ResultFromScode (STG_E_READFAULT);
  375. }
  376. // overlap is currently considered a bug (see the discussion
  377. // on the Write method
  378. _xmemcpy(pb, pGlobal + m_pos, cbRead);
  379. GlobalUnlock (m_pData->hGlobal);
  380. m_pos += cbRead;
  381. }
  382. if (pcbRead != NULL)
  383. {
  384. *pcbRead = cbRead;
  385. }
  386. return error;
  387. }
  388. //+-------------------------------------------------------------------------
  389. //
  390. // Member: CMemStm::Write
  391. //
  392. // Synopsis: Writes [cb] bytes into the stream
  393. //
  394. // Effects:
  395. //
  396. // Arguments: [pb] -- the bytes to write
  397. // [cb] -- the number of bytes to write
  398. // [pcbWritten] -- where to put the number of bytes written
  399. //
  400. // Requires:
  401. //
  402. // Returns: HRESULT
  403. //
  404. // Signals:
  405. //
  406. // Modifies:
  407. //
  408. // Derivation: IStream
  409. //
  410. // Algorithm: resizes the internal buffer (if needed), then uses xmemcpy
  411. //
  412. // History: dd-mmm-yy Author Comment
  413. // 04-Nov-94 ricksa Modified for multithreading
  414. // 02-Dec-93 alexgo 32bit port, fixed bug dealing with
  415. // 0-byte sized memory
  416. // 06-Dec-93 alexgo handle overlap case.
  417. //
  418. // Notes:
  419. //
  420. //--------------------------------------------------------------------------
  421. #pragma SEG(CMemStm_Write)
  422. STDMETHODIMP CMemStm::Write(void const HUGEP* pb, ULONG cb,
  423. ULONG FAR* pcbWritten)
  424. {
  425. VDATEHEAP();
  426. HRESULT error = NOERROR;
  427. ULONG cbWritten = cb;
  428. ULARGE_INTEGER ularge_integer;
  429. BYTE HUGEP* pGlobal;
  430. if(cb)
  431. {
  432. VDATEPTRIN( pb , char );
  433. }
  434. // Single thread
  435. CRefMutexAutoLock lck(m_pmxs);
  436. if (pcbWritten != NULL)
  437. {
  438. *pcbWritten = 0;
  439. }
  440. if (cbWritten + m_pos > m_pData->cb)
  441. {
  442. ULISet32( ularge_integer, m_pos+cbWritten );
  443. error = SetSize(ularge_integer);
  444. if (error != NOERROR)
  445. {
  446. goto Exit;
  447. }
  448. }
  449. // we don't write anything if 0 bytes are asked for for two
  450. // reasons: 1. optimization, 2. m_pData->hGlobal could be a
  451. // handle to a zero-byte memory block, in which case GlobalLock
  452. // will fail.
  453. if( cbWritten > 0 )
  454. {
  455. pGlobal = (BYTE HUGEP *)GlobalLock (m_pData->hGlobal);
  456. if (NULL==pGlobal)
  457. {
  458. LEERROR(1, "GlobalLock Failed!");
  459. return ResultFromScode (STG_E_WRITEFAULT);
  460. }
  461. // we use memmove here instead of memcpy to handle the
  462. // overlap case. Recall that the app originally gave
  463. // use the memory for the memstm. He could (either through
  464. // a CopyTo or through really strange code), be giving us
  465. // this region to read from, so we have to handle the overlapp
  466. // case. The same argument also applies for Read, but for
  467. // now, we'll consider overlap on Read a bug.
  468. _xmemmove(pGlobal + m_pos, pb, cbWritten);
  469. GlobalUnlock (m_pData->hGlobal);
  470. m_pos += cbWritten;
  471. }
  472. if (pcbWritten != NULL)
  473. {
  474. *pcbWritten = cbWritten;
  475. }
  476. Exit:
  477. return error;
  478. }
  479. //+-------------------------------------------------------------------------
  480. //
  481. // Member: CMemStm::Seek
  482. //
  483. // Synopsis: Moves the internal seek pointer
  484. //
  485. // Effects:
  486. //
  487. // Arguments: [dlibMoveIN] -- the amount to move by
  488. // [dwOrigin] -- flags to control whether seeking is
  489. // relative to the current postion or
  490. // the begging/end.
  491. // [plibNewPosition] -- where to put the new position
  492. //
  493. // Requires:
  494. //
  495. // Returns: HRESULT
  496. //
  497. // Signals:
  498. //
  499. // Modifies:
  500. //
  501. // Derivation: IStream
  502. //
  503. // Algorithm:
  504. //
  505. // History: dd-mmm-yy Author Comment
  506. // 04-Nov-94 ricksa Modified for multithreading
  507. // 02-Dec-93 alexgo 32bit port
  508. //
  509. // Notes:
  510. //
  511. //--------------------------------------------------------------------------
  512. #pragma SEG(CMemStm_Seek)
  513. STDMETHODIMP CMemStm::Seek(LARGE_INTEGER dlibMoveIN, DWORD dwOrigin,
  514. ULARGE_INTEGER FAR* plibNewPosition)
  515. {
  516. VDATEHEAP();
  517. HRESULT error = NOERROR;
  518. LONG dlibMove = dlibMoveIN.LowPart ;
  519. ULONG cbNewPos = dlibMove;
  520. // Single thread
  521. CRefMutexAutoLock lck(m_pmxs);
  522. if (plibNewPosition != NULL)
  523. {
  524. VDATEPTROUT( plibNewPosition, ULONG );
  525. ULISet32(*plibNewPosition, m_pos);
  526. }
  527. switch(dwOrigin)
  528. {
  529. case STREAM_SEEK_SET:
  530. if (dlibMove >= 0)
  531. {
  532. m_pos = dlibMove;
  533. }
  534. else
  535. {
  536. error = ResultFromScode(STG_E_SEEKERROR);
  537. }
  538. break;
  539. case STREAM_SEEK_CUR:
  540. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
  541. {
  542. m_pos += dlibMove;
  543. }
  544. else
  545. {
  546. error = ResultFromScode(STG_E_SEEKERROR);
  547. }
  548. break;
  549. case STREAM_SEEK_END:
  550. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pData->cb))
  551. {
  552. m_pos = m_pData->cb + dlibMove;
  553. }
  554. else
  555. {
  556. error = ResultFromScode(STG_E_SEEKERROR);
  557. }
  558. break;
  559. default:
  560. error = ResultFromScode(STG_E_SEEKERROR);
  561. }
  562. if (plibNewPosition != NULL)
  563. {
  564. ULISet32(*plibNewPosition, m_pos);
  565. }
  566. return error;
  567. }
  568. //+-------------------------------------------------------------------------
  569. //
  570. // Member: CMemStm::SetSize
  571. //
  572. // Synopsis: Sets the size of our memory
  573. //
  574. // Effects:
  575. //
  576. // Arguments: [cb] -- the new size
  577. //
  578. // Requires:
  579. //
  580. // Returns: HRESULT
  581. //
  582. // Signals:
  583. //
  584. // Modifies:
  585. //
  586. // Derivation: IStream
  587. //
  588. // Algorithm: calls GlobalRealloc
  589. //
  590. // History: dd-mmm-yy Author Comment
  591. // 04-Nov-94 ricksa Modified for multithreading
  592. // 02-Dec-93 alexgo 32bit port, added assert
  593. //
  594. // Notes:
  595. //
  596. //--------------------------------------------------------------------------
  597. #pragma SEG(CMemStm_SetSize)
  598. STDMETHODIMP CMemStm::SetSize(ULARGE_INTEGER cb)
  599. {
  600. VDATEHEAP();
  601. HANDLE hMemNew;
  602. // Single thread
  603. CRefMutexAutoLock lck(m_pmxs);
  604. // make sure we aren't in overflow conditions.
  605. AssertSz(cb.HighPart == 0,
  606. "MemStream::More than 2^32 bytes asked for");
  607. if (m_pData->cb == cb.LowPart)
  608. {
  609. return NOERROR;
  610. }
  611. hMemNew = GlobalReAlloc(m_pData->hGlobal, max (cb.LowPart,1),
  612. GMEM_SHARE | GMEM_MOVEABLE);
  613. if (hMemNew == NULL)
  614. {
  615. return ResultFromScode (E_OUTOFMEMORY);
  616. }
  617. m_pData->hGlobal = hMemNew;
  618. m_pData->cb = cb.LowPart;
  619. return NOERROR;
  620. }
  621. //+-------------------------------------------------------------------------
  622. //
  623. // Member: CMemStm::CopyTo
  624. //
  625. // Synopsis: Copies data from [this] stream to [pstm]
  626. //
  627. // Effects:
  628. //
  629. // Arguments: [pstm] -- the stream to copy to
  630. // [cb] -- the number of bytes to copy
  631. // [pcbRead] -- where to return the number of bytes read
  632. // [pcbWritten] -- where to return the number of bytes written
  633. //
  634. // Requires:
  635. //
  636. // Returns: HRESULT
  637. //
  638. // Signals:
  639. //
  640. // Modifies:
  641. //
  642. // Derivation: IStream
  643. //
  644. // Algorithm: does an IStream->Write to the given stream
  645. //
  646. // History: dd-mmm-yy Author Comment
  647. // 04-Nov-94 ricksa Modified for multithreading
  648. // 03-Dec-93 alexgo original implementation
  649. //
  650. // Notes: This implementation assumes that the address space
  651. // is not greater than ULARGE_INTEGER.LowPart (which is
  652. // for for 32bit operating systems). 64bit NT may need
  653. // to revisit this code.
  654. //
  655. //--------------------------------------------------------------------------
  656. #pragma SEG(CMemStm_CopyTo)
  657. STDMETHODIMP CMemStm::CopyTo(IStream FAR *pstm, ULARGE_INTEGER cb,
  658. ULARGE_INTEGER FAR * pcbRead, ULARGE_INTEGER FAR * pcbWritten)
  659. {
  660. VDATEHEAP();
  661. ULONG cbRead = cb.LowPart;
  662. ULONG cbWritten = 0;
  663. HRESULT hresult = NOERROR;
  664. // pstm cannot be NULL
  665. VDATEPTRIN(pstm, LPSTREAM);
  666. // Single thread
  667. CRefMutexAutoLock lck(m_pmxs);
  668. // the spec says that if cb is it's maximum value (all bits set,
  669. // since it's unsigned), then we will simply read the copy of
  670. // this stream
  671. if ( ~(cb.LowPart) == 0 && ~(cb.HighPart) == 0 )
  672. {
  673. cbRead = m_pData->cb - m_pos;
  674. }
  675. else if ( cb.HighPart > 0 )
  676. {
  677. // we assume that our memory stream cannot
  678. // be large enough to accomodate very large (>32bit)
  679. // copy to requests. Since this is probably an error
  680. // on the caller's part, we assert.
  681. AssertSz(0, "WARNING: CopyTo request exceeds 32 bits");
  682. // set the Read value to what's left, so that "Ignore"ing
  683. // the assert works properly.
  684. cbRead = m_pData->cb - m_pos;
  685. }
  686. else if ( cbRead + m_pos > m_pData->cb )
  687. {
  688. // more bytes were requested to read than we had left.
  689. // cbRead is set to the amount remaining.
  690. cbRead = m_pData->cb - m_pos;
  691. }
  692. // now write the data to the stream
  693. if ( cbRead > 0 )
  694. {
  695. BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
  696. m_pData->hGlobal);
  697. if( pGlobal == NULL )
  698. {
  699. LEERROR(1, "GlobalLock failed");
  700. return ResultFromScode(STG_E_INSUFFICIENTMEMORY);
  701. }
  702. hresult = pstm->Write(pGlobal + m_pos, cbRead, &cbWritten);
  703. // in the error case, the spec says that the return values
  704. // may be meaningless, so we do not need to do any special
  705. // error handling here
  706. GlobalUnlock(m_pData->hGlobal);
  707. }
  708. // increment our seek pointer and set the out parameters
  709. m_pos += cbRead;
  710. if( pcbRead )
  711. {
  712. ULISet32(*pcbRead, cbRead);
  713. }
  714. if( pcbWritten )
  715. {
  716. ULISet32(*pcbWritten, cbWritten);
  717. }
  718. return hresult;
  719. }
  720. //+-------------------------------------------------------------------------
  721. //
  722. // Member: CMemStm::Commit
  723. //
  724. // Synopsis: Does nothing, no transactions available on memory streams
  725. //
  726. // Effects:
  727. //
  728. // Arguments: [grfCommitFlags]
  729. //
  730. // Requires:
  731. //
  732. // Returns: NOERROR
  733. //
  734. // Signals:
  735. //
  736. // Modifies:
  737. //
  738. // Derivation: IStream
  739. //
  740. // Algorithm:
  741. //
  742. // History: dd-mmm-yy Author Comment
  743. // 03-Dec-93 alexgo 32bit port
  744. //
  745. // Notes:
  746. //
  747. //--------------------------------------------------------------------------
  748. #pragma SEG(CMemStm_Commit)
  749. STDMETHODIMP CMemStm::Commit(DWORD grfCommitFlags)
  750. {
  751. VDATEHEAP();
  752. return NOERROR;
  753. }
  754. //+-------------------------------------------------------------------------
  755. //
  756. // Member: CMemStm::Revert
  757. //
  758. // Synopsis: does nothing, as no transactions are supported on memory
  759. // streams
  760. //
  761. // Effects:
  762. //
  763. // Arguments: void
  764. //
  765. // Requires:
  766. //
  767. // Returns: NOERROR
  768. //
  769. // Signals:
  770. //
  771. // Modifies:
  772. //
  773. // Derivation: IStream
  774. //
  775. // Algorithm:
  776. //
  777. // History: dd-mmm-yy Author Comment
  778. // 03-Dec-93 alexgo 32bit port
  779. //
  780. // Notes:
  781. //
  782. //--------------------------------------------------------------------------
  783. #pragma SEG(CMemStm_Revert)
  784. STDMETHODIMP CMemStm::Revert(void)
  785. {
  786. VDATEHEAP();
  787. return NOERROR;
  788. }
  789. //+-------------------------------------------------------------------------
  790. //
  791. // Member: CMemStm::LockRegion
  792. //
  793. // Synopsis: not supported in OLE2.01
  794. //
  795. // Effects:
  796. //
  797. // Arguments: [libOffset]
  798. // [cb]
  799. // [dwLockType]
  800. //
  801. // Requires:
  802. //
  803. // Returns: STG_E_INVALIDFUNCTION
  804. //
  805. // Signals:
  806. //
  807. // Modifies:
  808. //
  809. // Derivation: IStream
  810. //
  811. // Algorithm:
  812. //
  813. // History: dd-mmm-yy Author Comment
  814. // 03-Dec-93 alexgo 32bit port
  815. //
  816. // Notes:
  817. //
  818. //--------------------------------------------------------------------------
  819. #pragma SEG(CMemStm_LockRegion)
  820. STDMETHODIMP CMemStm::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  821. DWORD dwLockType)
  822. {
  823. VDATEHEAP();
  824. return ResultFromScode(STG_E_INVALIDFUNCTION);
  825. }
  826. //+-------------------------------------------------------------------------
  827. //
  828. // Member: CMemStm::UnlockRegion
  829. //
  830. // Synopsis: not implemented for OLE2.01
  831. //
  832. // Effects:
  833. //
  834. // Arguments: [libOffset]
  835. // [cb]
  836. // [dwLockType]
  837. //
  838. // Requires:
  839. //
  840. // Returns: STG_E_INVALIDFUNCTION
  841. //
  842. // Signals:
  843. //
  844. // Modifies:
  845. //
  846. // Derivation: IStream
  847. //
  848. // Algorithm:
  849. //
  850. // History: dd-mmm-yy Author Comment
  851. // 03-Dec-93 alexgo 32bit port
  852. //
  853. // Notes:
  854. //
  855. //--------------------------------------------------------------------------
  856. #pragma SEG(CMemStm_UnlockRegion)
  857. STDMETHODIMP CMemStm::UnlockRegion(ULARGE_INTEGER libOffset,
  858. ULARGE_INTEGER cb, DWORD dwLockType)
  859. {
  860. VDATEHEAP();
  861. return ResultFromScode(STG_E_INVALIDFUNCTION);
  862. }
  863. //+-------------------------------------------------------------------------
  864. //
  865. // Member: CMemStm::Stat
  866. //
  867. // Synopsis: Returns info about this stream
  868. //
  869. // Effects:
  870. //
  871. // Arguments: [pstatstg] -- the STATSTG to fill with info
  872. // [statflag] -- status flags, unused
  873. //
  874. // Requires:
  875. //
  876. // Returns: NOERROR, E_INVALIDARG
  877. //
  878. // Signals:
  879. //
  880. // Modifies:
  881. //
  882. // Derivation: IStream
  883. //
  884. // Algorithm:
  885. //
  886. // History: dd-mmm-yy Author Comment
  887. // 03-Dec-93 alexgo 32bit port
  888. // 01-Jun-94 AlexT Set type correctly
  889. //
  890. // Notes:
  891. //
  892. //--------------------------------------------------------------------------
  893. #pragma SEG(CMemStm_Stat)
  894. STDMETHODIMP CMemStm::Stat(STATSTG FAR *pstatstg, DWORD statflag)
  895. {
  896. VDATEHEAP();
  897. VDATEPTROUT( pstatstg, STATSTG );
  898. memset ( pstatstg, 0, sizeof(STATSTG) );
  899. pstatstg->type = STGTY_STREAM;
  900. pstatstg->cbSize.LowPart = m_pData->cb;
  901. return NOERROR;
  902. }
  903. //+-------------------------------------------------------------------------
  904. //
  905. // Member: CMemStm::Clone
  906. //
  907. // Synopsis: creates a new instance of this stream pointing to the
  908. // same data at the same position (same seek pointer)
  909. //
  910. // Effects:
  911. //
  912. // Arguments: [ppstm] -- where to put the new CMemStm pointer
  913. //
  914. // Requires:
  915. //
  916. // Returns: NOERROR, E_OUTOFMEMORY
  917. //
  918. // Signals:
  919. //
  920. // Modifies:
  921. //
  922. // Derivation: IStream
  923. //
  924. // Algorithm:
  925. //
  926. // History: dd-mmm-yy Author Comment
  927. // 03-Dec-93 alexgo 32bit port
  928. //
  929. // Notes:
  930. //
  931. //--------------------------------------------------------------------------
  932. #pragma SEG(CMemStm_Clone)
  933. STDMETHODIMP CMemStm::Clone(IStream FAR * FAR *ppstm)
  934. {
  935. VDATEHEAP();
  936. CMemStm FAR* pCMemStm;
  937. VDATEPTROUT (ppstm, LPSTREAM);
  938. *ppstm = pCMemStm = CMemStm::Create(m_hMem, m_pmxs);
  939. if (pCMemStm == NULL)
  940. {
  941. return ResultFromScode(E_OUTOFMEMORY);
  942. }
  943. pCMemStm->m_pos = m_pos;
  944. return NOERROR;
  945. }
  946. //+-------------------------------------------------------------------------
  947. //
  948. // Member: CMemStm::Create
  949. //
  950. // Synopsis: Creates a new CMemStm. [hMem] must be a handle to a MEMSTM
  951. // block.
  952. //
  953. // Effects:
  954. //
  955. // Arguments: [hMem] -- handle to a MEMSTM block
  956. //
  957. // Requires:
  958. //
  959. // Returns: CMemStm *
  960. //
  961. // Signals:
  962. //
  963. // Modifies:
  964. //
  965. // Derivation:
  966. //
  967. // Algorithm:
  968. //
  969. // History: dd-mmm-yy Author Comment
  970. // 15-Dec-93 alexgo fixed memory access bug
  971. // 03-Dec-93 alexgo 32bit port
  972. // 20-Sep-2000 mfeingol Added Mutex inheritance
  973. //
  974. // Notes:
  975. //
  976. //--------------------------------------------------------------------------
  977. #pragma SEG(CMemStm_Create)
  978. STDSTATICIMP_(CMemStm FAR*) CMemStm::Create(HANDLE hMem, CRefMutexSem* pmxs)
  979. {
  980. VDATEHEAP();
  981. CMemStm FAR* pCMemStm = NULL;
  982. struct MEMSTM FAR* pData;
  983. pData = (MEMSTM FAR*) GlobalLock(hMem);
  984. if (pData != NULL)
  985. {
  986. pCMemStm = new CMemStm;
  987. if (pCMemStm != NULL)
  988. {
  989. // Initialize CMemStm
  990. pCMemStm->m_hMem = hMem;
  991. InterlockedIncrement ((LPLONG) &(pCMemStm->m_pData = pData)->cRef); // AddRefMemStm
  992. pCMemStm->m_refs = 1;
  993. pCMemStm->m_dwSig = STREAM_SIG;
  994. if (pmxs != NULL)
  995. {
  996. // Addref the input
  997. pmxs->AddRef();
  998. }
  999. else
  1000. {
  1001. // Create a new mutex (implicit addref)
  1002. pmxs = CRefMutexSem::CreateInstance();
  1003. }
  1004. if (pmxs != NULL)
  1005. {
  1006. // Give the CMemStm a mutex
  1007. pCMemStm->m_pmxs = pmxs;
  1008. }
  1009. else
  1010. {
  1011. // uh-oh, low on memory
  1012. delete pCMemStm;
  1013. pCMemStm = NULL;
  1014. GlobalUnlock(hMem);
  1015. }
  1016. }
  1017. else
  1018. {
  1019. // uh-oh, low on memory
  1020. GlobalUnlock(hMem);
  1021. }
  1022. }
  1023. // we do *not* unlock the memory now, the memstm structure should
  1024. // be locked for the lifetime of any CMemStm's that refer to it.
  1025. // when the CMemStm is destroyed, we will release our lock on
  1026. // hMem.
  1027. return pCMemStm;
  1028. }
  1029. //+-------------------------------------------------------------------------
  1030. //
  1031. // Member: CMemStm::Dump, public (_DEBUG only)
  1032. //
  1033. // Synopsis: return a string containing the contents of the data members
  1034. //
  1035. // Effects:
  1036. //
  1037. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1038. // [ulFlag] - flag determining prefix of all newlines of the
  1039. // out character array (default is 0 - no prefix)
  1040. // [nIndentLevel] - will add a indent prefix after the other prefix
  1041. // for ALL newlines (including those with no prefix)
  1042. //
  1043. // Requires:
  1044. //
  1045. // Returns: HRESULT
  1046. //
  1047. // Signals:
  1048. //
  1049. // Modifies: [ppsz] - argument
  1050. //
  1051. // Derivation:
  1052. //
  1053. // Algorithm: use dbgstream to create a string containing information on the
  1054. // content of data structures
  1055. //
  1056. // History: dd-mmm-yy Author Comment
  1057. // 20-Jan-95 t-ScottH author
  1058. //
  1059. // Notes:
  1060. //
  1061. //--------------------------------------------------------------------------
  1062. #ifdef _DEBUG
  1063. HRESULT CMemStm::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1064. {
  1065. int i;
  1066. char *pszPrefix;
  1067. char *pszMEMSTM;
  1068. char *pszCMutexSem;
  1069. dbgstream dstrPrefix;
  1070. dbgstream dstrDump(400);
  1071. // determine prefix of newlines
  1072. if ( ulFlag & DEB_VERBOSE )
  1073. {
  1074. dstrPrefix << this << " _VB ";
  1075. }
  1076. // determine indentation prefix for all newlines
  1077. for (i = 0; i < nIndentLevel; i++)
  1078. {
  1079. dstrPrefix << DUMPTAB;
  1080. }
  1081. pszPrefix = dstrPrefix.str();
  1082. // put data members in stream
  1083. dstrDump << pszPrefix << "Impl. Signature = " << m_dwSig << endl;
  1084. dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
  1085. dstrDump << pszPrefix << "Seek pointer = " << m_pos << endl;
  1086. dstrDump << pszPrefix << "Memory handle = " << m_hMem << endl;
  1087. if (m_pData != NULL)
  1088. {
  1089. pszMEMSTM = DumpMEMSTM(m_pData, ulFlag, nIndentLevel + 1);
  1090. dstrDump << pszPrefix << "MEMSTM:" << endl;
  1091. dstrDump << pszMEMSTM;
  1092. CoTaskMemFree(pszMEMSTM);
  1093. }
  1094. else
  1095. {
  1096. dstrDump << pszPrefix << "MEMSTM = " << m_pData << endl;
  1097. }
  1098. pszCMutexSem = DumpCMutexSem ((CMutexSem2*) m_pmxs->GetMutexSem());
  1099. dstrDump << pszPrefix << "Mutex = " << pszCMutexSem << endl;
  1100. CoTaskMemFree(pszCMutexSem);
  1101. // cleanup and provide pointer to character array
  1102. *ppszDump = dstrDump.str();
  1103. if (*ppszDump == NULL)
  1104. {
  1105. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1106. }
  1107. CoTaskMemFree(pszPrefix);
  1108. return NOERROR;
  1109. }
  1110. #endif // _DEBUG
  1111. //+-------------------------------------------------------------------------
  1112. //
  1113. // Function: DumpCMemStm, public (_DEBUG only)
  1114. //
  1115. // Synopsis: calls the CMemStm::Dump method, takes care of errors and
  1116. // returns the zero terminated string
  1117. //
  1118. // Effects:
  1119. //
  1120. // Arguments: [pMS] - pointer to CMemStm
  1121. // [ulFlag] - flag determining prefix of all newlines of the
  1122. // out character array (default is 0 - no prefix)
  1123. // [nIndentLevel] - will add a indent prefix after the other prefix
  1124. // for ALL newlines (including those with no prefix)
  1125. //
  1126. // Requires:
  1127. //
  1128. // Returns: character array of structure dump or error (null terminated)
  1129. //
  1130. // Signals:
  1131. //
  1132. // Modifies:
  1133. //
  1134. // Algorithm:
  1135. //
  1136. // History: dd-mmm-yy Author Comment
  1137. // 20-Jan-95 t-ScottH author
  1138. //
  1139. // Notes:
  1140. //
  1141. //--------------------------------------------------------------------------
  1142. #ifdef _DEBUG
  1143. char *DumpCMemStm(CMemStm *pMS, ULONG ulFlag, int nIndentLevel)
  1144. {
  1145. HRESULT hresult;
  1146. char *pszDump;
  1147. if (pMS == NULL)
  1148. {
  1149. return UtDupStringA(szDumpBadPtr);
  1150. }
  1151. hresult = pMS->Dump(&pszDump, ulFlag, nIndentLevel);
  1152. if (hresult != NOERROR)
  1153. {
  1154. CoTaskMemFree(pszDump);
  1155. return DumpHRESULT(hresult);
  1156. }
  1157. return pszDump;
  1158. }
  1159. #endif // _DEBUG
  1160. //+-------------------------------------------------------------------------
  1161. //
  1162. // Function: CreateMemStm
  1163. //
  1164. // Synopsis: Allocates memory and creates a CMemStm for it.
  1165. //
  1166. // Effects:
  1167. //
  1168. // Arguments: [cb] -- the number of bytes to allocate
  1169. // [phMem] -- where to put a handle to the MEMSTM structure
  1170. //
  1171. // Requires:
  1172. //
  1173. // Returns: LPSTREAM to the CMemStream
  1174. //
  1175. // Signals:
  1176. //
  1177. // Modifies:
  1178. //
  1179. // Algorithm:
  1180. //
  1181. // History: dd-mmm-yy Author Comment
  1182. // 03-Dec-93 alexgo 32bit port
  1183. //
  1184. // Notes: phMem must be free'd with ReleaseMemStm (because of ref
  1185. // counting and the nested handle)
  1186. //
  1187. //--------------------------------------------------------------------------
  1188. #pragma SEG(CreateMemStm)
  1189. STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem)
  1190. {
  1191. VDATEHEAP();
  1192. HANDLE h;
  1193. LPSTREAM pstm = NULL;
  1194. if (phMem)
  1195. {
  1196. *phMem = NULL;
  1197. }
  1198. h = GlobalAlloc (GMEM_SHARE | GMEM_MOVEABLE, cb);
  1199. if (NULL==h)
  1200. {
  1201. return NULL;
  1202. }
  1203. if (CreateStreamOnHGlobal (h, TRUE, &pstm) != NOERROR)
  1204. {
  1205. GlobalFree(h); // COM+ 22886
  1206. return NULL;
  1207. }
  1208. if (phMem)
  1209. {
  1210. // retrieve handle from just-created CMemStm
  1211. *phMem = ((CMemStm FAR*)pstm)->m_hMem;
  1212. // use pointer to bump ref count
  1213. Assert(((CMemStm FAR*)pstm)->m_pData != NULL);
  1214. InterlockedIncrement ((LPLONG) &((CMemStm FAR*)pstm)->m_pData->cRef); // AddRefMemStm
  1215. }
  1216. return pstm;
  1217. }
  1218. //+-------------------------------------------------------------------------
  1219. //
  1220. // Function: CloneMemStm
  1221. //
  1222. // Synopsis: Clones a memory stream
  1223. //
  1224. // Effects:
  1225. //
  1226. // Arguments: [hMem] -- a handle to the MEMSTM block
  1227. //
  1228. // Requires:
  1229. //
  1230. // Returns: LPSTREAM
  1231. //
  1232. // Signals:
  1233. //
  1234. // Modifies:
  1235. //
  1236. // Algorithm:
  1237. //
  1238. // History: dd-mmm-yy Author Comment
  1239. // 05-Dec-93 alexgo 32bit port
  1240. //
  1241. // Notes:
  1242. //
  1243. //--------------------------------------------------------------------------
  1244. #pragma SEG(CloneMemStm)
  1245. STDAPI_(LPSTREAM) CloneMemStm(HANDLE hMem)
  1246. {
  1247. VDATEHEAP();
  1248. return CMemStm::Create(hMem, NULL); // Create the stream
  1249. }
  1250. //+-------------------------------------------------------------------------
  1251. //
  1252. // Function: ReleaseMemStm
  1253. //
  1254. // Synopsis: Releases the memory used by a MEMSTM structure (including
  1255. // the nested handle)
  1256. //
  1257. // Effects:
  1258. //
  1259. // Arguments: [phMem] -- pointer the MEMSTM handle
  1260. // [fInternalOnly] -- if TRUE, then only the actual memory
  1261. // that MEMSTM refers to is freed
  1262. // (not the MEMSTM structure itself)
  1263. //
  1264. // Requires:
  1265. //
  1266. // Returns: void
  1267. //
  1268. // Signals:
  1269. //
  1270. // Modifies: sets *phMem to NULL on success
  1271. //
  1272. // Algorithm:
  1273. //
  1274. // History: dd-mmm-yy Author Comment
  1275. // 05-Dec-93 alexgo 32bit port and fixed bad memory access
  1276. // bug
  1277. //
  1278. // Notes: REVIEW32: look at taking out the second argument
  1279. //
  1280. //--------------------------------------------------------------------------
  1281. #pragma SEG(ReleaseMemStm)
  1282. STDAPI_(void) ReleaseMemStm (LPHANDLE phMem, BOOL fInternalOnly)
  1283. {
  1284. VDATEHEAP();
  1285. struct MEMSTM FAR* pData;
  1286. pData = (MEMSTM FAR*) GlobalLock(*phMem);
  1287. // check for NULL pointer in case handle got freed already
  1288. // decrement ref count and free if no refs left
  1289. if (pData != NULL && InterlockedDecrement ((LPLONG) &pData->cRef) == 0)
  1290. {
  1291. if (pData->fDeleteOnRelease)
  1292. {
  1293. Verify (0==GlobalFree (pData->hGlobal));
  1294. }
  1295. if (!fInternalOnly)
  1296. {
  1297. GlobalUnlock(*phMem);
  1298. Verify (0==GlobalFree(*phMem));
  1299. goto End;
  1300. }
  1301. }
  1302. GlobalUnlock(*phMem);
  1303. End:
  1304. *phMem = NULL;
  1305. }
  1306. //+-------------------------------------------------------------------------
  1307. //
  1308. // Function: CreateStreamOnHGlobal
  1309. //
  1310. // Synopsis: Creates a CMemStm from the given hGlobal (if [hGlobal] is
  1311. // NULL, we allocate a zero byte one)
  1312. //
  1313. // Effects:
  1314. //
  1315. // Arguments: [hGlobal] -- the memory
  1316. // [fDeleteOnRelease] -- whether the memory should be
  1317. // release on delete
  1318. // [ppstm] -- where to put the stream
  1319. //
  1320. // Requires:
  1321. //
  1322. // Returns: HRESULT
  1323. //
  1324. // Signals:
  1325. //
  1326. // Modifies:
  1327. //
  1328. // Algorithm:
  1329. //
  1330. // History: dd-mmm-yy Author Comment
  1331. // 11-Jan-93 alexgo removed initialization of cbSize to -1
  1332. // to fix compile warning
  1333. // 05-Dec-93 alexgo 32bit port
  1334. //
  1335. // Notes:
  1336. //
  1337. //--------------------------------------------------------------------------
  1338. #pragma SEG(CreateStreamOnHGlobal)
  1339. STDAPI CreateStreamOnHGlobal(HANDLE hGlobal, BOOL fDeleteOnRelease,
  1340. LPSTREAM FAR* ppstm)
  1341. {
  1342. OLETRACEIN((API_CreateStreamOnHGlobal, PARAMFMT("hGlobal= %h, fDeleteOnRelease= %B, ppstm= %p"),
  1343. hGlobal, fDeleteOnRelease, ppstm));
  1344. VDATEHEAP();
  1345. HANDLE hMem = NULL;
  1346. struct MEMSTM FAR* pData = NULL;
  1347. LPSTREAM pstm = NULL;
  1348. DWORD cbSize;
  1349. BOOL fAllocated = FALSE;
  1350. HRESULT hresult;
  1351. VDATEPTROUT_LABEL (ppstm, LPSTREAM, SafeExit, hresult);
  1352. *ppstm = NULL;
  1353. if (NULL==hGlobal)
  1354. {
  1355. hGlobal = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, 0);
  1356. if (hGlobal == NULL)
  1357. {
  1358. goto FreeMem;
  1359. }
  1360. cbSize = 0;
  1361. fAllocated = TRUE;
  1362. }
  1363. else
  1364. {
  1365. cbSize = (ULONG) GlobalSize (hGlobal);
  1366. // Is there a way to verify a zero-sized handle?
  1367. // we currently do no verification for them
  1368. if (cbSize!=0)
  1369. {
  1370. // verify validity of passed-in handle
  1371. if (NULL==GlobalLock(hGlobal))
  1372. {
  1373. // bad handle
  1374. hresult = ResultFromScode (E_INVALIDARG);
  1375. goto SafeExit;
  1376. }
  1377. GlobalUnlock (hGlobal);
  1378. }
  1379. }
  1380. hMem = GlobalAlloc (GMEM_SHARE | GMEM_MOVEABLE, sizeof (MEMSTM));
  1381. if (hMem == NULL)
  1382. {
  1383. goto FreeMem;
  1384. }
  1385. pData = (MEMSTM FAR*) GlobalLock(hMem);
  1386. if (pData == NULL)
  1387. {
  1388. GlobalUnlock(hMem);
  1389. goto FreeMem;
  1390. }
  1391. pData->cRef = 0;
  1392. pData->cb = cbSize;
  1393. pData->fDeleteOnRelease = fDeleteOnRelease;
  1394. pData->hGlobal = hGlobal;
  1395. GlobalUnlock(hMem);
  1396. pstm = CMemStm::Create(hMem, NULL);
  1397. if (pstm == NULL)
  1398. {
  1399. goto FreeMem;
  1400. }
  1401. *ppstm = pstm;
  1402. CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)ppstm);
  1403. hresult = NOERROR;
  1404. goto SafeExit;
  1405. FreeMem:
  1406. if (hGlobal && fAllocated)
  1407. {
  1408. Verify(0==GlobalFree(hGlobal));
  1409. }
  1410. if (hMem)
  1411. {
  1412. Verify(0==GlobalFree(hMem));
  1413. }
  1414. LEERROR(1, "Out of memory!");
  1415. hresult = ResultFromScode(E_OUTOFMEMORY);
  1416. SafeExit:
  1417. OLETRACEOUT((API_CreateStreamOnHGlobal, hresult));
  1418. return hresult;
  1419. }
  1420. //+-------------------------------------------------------------------------
  1421. //
  1422. // Function: GetHGlobalFromStream
  1423. //
  1424. // Synopsis: Retrieves the HGLOBAL to the memory from the given stream
  1425. // pointer (must be a pointer to a CMemByte structure)
  1426. //
  1427. // Effects:
  1428. //
  1429. // Arguments: [pstm] -- pointer to the CMemByte
  1430. // [phglobal] -- where to put the hglobal
  1431. //
  1432. // Requires:
  1433. //
  1434. // Returns: HRESULT (E_INVALIDARG, E_OUTOFMEMORY, NOERROR)
  1435. //
  1436. // Signals:
  1437. //
  1438. // Modifies:
  1439. //
  1440. // Algorithm:
  1441. //
  1442. // History: dd-mmm-yy Author Comment
  1443. // 05-Dec-93 alexgo 32bit port
  1444. //
  1445. // Notes:
  1446. //
  1447. //--------------------------------------------------------------------------
  1448. #pragma SEG(GetHGlobalFromStream)
  1449. STDAPI GetHGlobalFromStream(LPSTREAM pstm, HGLOBAL FAR* phglobal)
  1450. {
  1451. OLETRACEIN((API_GetHGlobalFromStream, PARAMFMT("pstm= %p, phglobal= %p"),
  1452. pstm, phglobal));
  1453. VDATEHEAP();
  1454. HRESULT hresult;
  1455. CMemStm FAR* pCMemStm;
  1456. MEMSTM FAR* pMem;
  1457. VDATEIFACE_LABEL (pstm, errRtn, hresult);
  1458. VDATEPTROUT_LABEL(phglobal, HANDLE, errRtn, hresult);
  1459. CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pstm);
  1460. pCMemStm = (CMemStm FAR*) pstm;
  1461. if (!IsValidReadPtrIn (&(pCMemStm->m_dwSig), sizeof(ULONG))
  1462. || pCMemStm->m_dwSig != STREAM_SIG)
  1463. {
  1464. // we were passed someone else's implementation of ILockBytes
  1465. hresult = ResultFromScode (E_INVALIDARG);
  1466. goto errRtn;
  1467. }
  1468. pMem= pCMemStm->m_pData;
  1469. if (NULL==pMem)
  1470. {
  1471. LEERROR(1, "Out of memory!");
  1472. hresult = ResultFromScode (E_OUTOFMEMORY);
  1473. goto errRtn;
  1474. }
  1475. Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
  1476. Verify (*phglobal = pMem->hGlobal);
  1477. hresult = NOERROR;
  1478. errRtn:
  1479. OLETRACEOUT((API_GetHGlobalFromStream, hresult));
  1480. return hresult;
  1481. }
  1482. //////////////////////////////////////////////////////////////////////////
  1483. //
  1484. // Shared memory ILockBytes implementation
  1485. //
  1486. //+-------------------------------------------------------------------------
  1487. //
  1488. // Member: CMemBytes::QueryInterface
  1489. //
  1490. // Synopsis: returns the requested interface pointer
  1491. //
  1492. // Effects: a CMarshalMemBytes will be created if IID_IMarshal is
  1493. // requested
  1494. //
  1495. // Arguments: [iidInterface] -- the requested interface ID
  1496. // [ppvObj] -- where to put the interface pointer
  1497. //
  1498. // Requires:
  1499. //
  1500. // Returns: NOERROR, E_OUTOFMEMORY, E_NOINTERFACE
  1501. //
  1502. // Signals:
  1503. //
  1504. // Modifies:
  1505. //
  1506. // Derivation: ILockBytes
  1507. //
  1508. // Algorithm:
  1509. //
  1510. // History: dd-mmm-yy Author Comment
  1511. // 11-Jan-94 alexgo removed QI for IMarshal so that
  1512. // the standard marshaller will be used.
  1513. // This is to enable correct operation on
  1514. // 32bit platforms.
  1515. // 05-Dec-93 alexgo 32bit port
  1516. //
  1517. // Notes:
  1518. //
  1519. //--------------------------------------------------------------------------
  1520. #pragma SEG(CMemBytes_QueryInterface)
  1521. STDMETHODIMP CMemBytes::QueryInterface(REFIID iidInterface,
  1522. void FAR* FAR* ppvObj)
  1523. {
  1524. VDATEHEAP();
  1525. HRESULT error;
  1526. VDATEPTROUT( ppvObj, LPVOID );
  1527. *ppvObj = NULL;
  1528. VDATEIID( iidInterface );
  1529. if (m_pData != NULL && (IsEqualIID(iidInterface, IID_ILockBytes) ||
  1530. IsEqualIID(iidInterface, IID_IUnknown)))
  1531. {
  1532. InterlockedIncrement ((LPLONG) &m_refs); // A pointer to this object is returned
  1533. *ppvObj = this;
  1534. error = NOERROR;
  1535. }
  1536. // this is not an else if because m_pData can be NULL and we
  1537. // allow creating a CMarshalMemBytes. REVIEW32: We may want
  1538. // to remove this behavior.
  1539. #ifndef WIN32
  1540. if (IsEqualIID(iidInterface, IID_IMarshal))
  1541. {
  1542. *ppvObj = (LPVOID) CMarshalMemBytes::Create(this);
  1543. if (*ppvObj != NULL)
  1544. {
  1545. error = NOERROR;
  1546. }
  1547. else
  1548. {
  1549. error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
  1550. }
  1551. }
  1552. #endif
  1553. else
  1554. {
  1555. *ppvObj = NULL;
  1556. error = ResultFromScode(E_NOINTERFACE);
  1557. }
  1558. return error;
  1559. }
  1560. //+-------------------------------------------------------------------------
  1561. //
  1562. // Member: CMemBytes::AddRef
  1563. //
  1564. // Synopsis: Incrememts the reference count
  1565. //
  1566. // Effects:
  1567. //
  1568. // Arguments: void
  1569. //
  1570. // Requires:
  1571. //
  1572. // Returns: ULONG -- the new reference count
  1573. //
  1574. // Signals:
  1575. //
  1576. // Modifies:
  1577. //
  1578. // Derivation: ILockBytes
  1579. //
  1580. // Algorithm:
  1581. //
  1582. // History: dd-mmm-yy Author Comment
  1583. // 05-Dec-93 alexgo 32bit port
  1584. //
  1585. // Notes:
  1586. //
  1587. //--------------------------------------------------------------------------
  1588. STDMETHODIMP_(ULONG) CMemBytes::AddRef(void)
  1589. {
  1590. VDATEHEAP();
  1591. return InterlockedIncrement ((LPLONG) &m_refs);
  1592. }
  1593. //+-------------------------------------------------------------------------
  1594. //
  1595. // Member: CMemBytes::Release
  1596. //
  1597. // Synopsis: decrements the reference count
  1598. //
  1599. // Effects:
  1600. //
  1601. // Arguments: void
  1602. //
  1603. // Requires:
  1604. //
  1605. // Returns: ULONG -- the new reference count
  1606. //
  1607. // Signals:
  1608. //
  1609. // Modifies:
  1610. //
  1611. // Derivation: ILockBytes
  1612. //
  1613. // Algorithm:
  1614. //
  1615. // History: dd-mmm-yy Author Comment
  1616. // 16-Dec-93 alexgo added GlobalUnlock to match the Global
  1617. // Lock in Create
  1618. // 05-Dec-93 alexgo 32bit port
  1619. //
  1620. // Notes:
  1621. //
  1622. //--------------------------------------------------------------------------
  1623. STDMETHODIMP_(ULONG) CMemBytes::Release(void)
  1624. {
  1625. VDATEHEAP();
  1626. ULONG ulRefs = InterlockedDecrement ((LPLONG) &m_refs);
  1627. if (ulRefs != 0)
  1628. {
  1629. return ulRefs;
  1630. }
  1631. // GlobalUnlock the m_hMem that we GlobalLocke'd in Create
  1632. GlobalUnlock(m_hMem);
  1633. ReleaseMemStm(&m_hMem);
  1634. delete this;
  1635. return 0;
  1636. }
  1637. //+-------------------------------------------------------------------------
  1638. //
  1639. // Member: CMemBytes::ReadAt
  1640. //
  1641. // Synopsis: reads [cb] bytes from starting position [ulOffset]
  1642. //
  1643. // Effects:
  1644. //
  1645. // Arguments: [ulOffset] -- the offset to start reading from
  1646. // [pb] -- where to put the data
  1647. // [cb] -- the number of bytes to read
  1648. // [pcbRead] -- where to put the number of bytes actually
  1649. // read
  1650. //
  1651. // Requires:
  1652. //
  1653. // Returns: HRESULT
  1654. //
  1655. // Signals:
  1656. //
  1657. // Modifies:
  1658. //
  1659. // Derivation: ILockBytes
  1660. //
  1661. // Algorithm: just calls xmemcpy
  1662. //
  1663. // History: dd-mmm-yy Author Comment
  1664. // 05-Dec-93 alexgo 32bit port
  1665. //
  1666. // Notes:
  1667. //
  1668. //--------------------------------------------------------------------------
  1669. #pragma SEG(CMemBytes_ReadAt)
  1670. STDMETHODIMP CMemBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP* pb,
  1671. ULONG cb, ULONG FAR* pcbRead)
  1672. {
  1673. VDATEHEAP();
  1674. HRESULT error = NOERROR;
  1675. ULONG cbRead = cb;
  1676. VDATEPTROUT( pb, char );
  1677. // make sure we don't offset out of the address space!
  1678. AssertSz(ulOffset.HighPart == 0,
  1679. "CMemBytes: offset greater than 2^32");
  1680. if (pcbRead)
  1681. {
  1682. *pcbRead = 0L;
  1683. }
  1684. if (cbRead + ulOffset.LowPart > m_pData->cb)
  1685. {
  1686. if (ulOffset.LowPart > m_pData->cb)
  1687. {
  1688. // the offset overruns the size of the memory
  1689. cbRead = 0;
  1690. }
  1691. else
  1692. {
  1693. // just read what's left
  1694. cbRead = m_pData->cb - ulOffset.LowPart;
  1695. }
  1696. }
  1697. if (cbRead > 0)
  1698. {
  1699. BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
  1700. m_pData->hGlobal);
  1701. if (NULL==pGlobal)
  1702. {
  1703. LEERROR(1, "GlobalLock failed!");
  1704. return ResultFromScode (STG_E_READFAULT);
  1705. }
  1706. _xmemcpy(pb, pGlobal + ulOffset.LowPart, cbRead);
  1707. GlobalUnlock (m_pData->hGlobal);
  1708. }
  1709. if (pcbRead != NULL)
  1710. {
  1711. *pcbRead = cbRead;
  1712. }
  1713. return error;
  1714. }
  1715. //+-------------------------------------------------------------------------
  1716. //
  1717. // Member: CMemBytes::WriteAt
  1718. //
  1719. // Synopsis: writes [cb] bytes at [ulOffset] in the stream
  1720. //
  1721. // Effects:
  1722. //
  1723. // Arguments: [ulOffset] -- the offset at which to start writing
  1724. // [pb] -- the buffer to read from
  1725. // [cb] -- the number of bytes to write
  1726. // [pcbWritten] -- where to put the number of bytes written
  1727. //
  1728. // Requires:
  1729. //
  1730. // Returns: HRESULT
  1731. //
  1732. // Signals:
  1733. //
  1734. // Modifies:
  1735. //
  1736. // Derivation: ILockBytes
  1737. //
  1738. // Algorithm:
  1739. //
  1740. // History: dd-mmm-yy Author Comment
  1741. // 05-Dec-93 alexgo 32bit port
  1742. //
  1743. // Notes:
  1744. //
  1745. //--------------------------------------------------------------------------
  1746. #pragma SEG(CMemBytes_WriteAt)
  1747. STDMETHODIMP CMemBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP* pb,
  1748. ULONG cb, ULONG FAR* pcbWritten)
  1749. {
  1750. VDATEHEAP();
  1751. HRESULT error = NOERROR;
  1752. ULONG cbWritten = cb;
  1753. BYTE HUGEP* pGlobal;
  1754. VDATEPTRIN( pb, char );
  1755. // make sure the offset doesn't go beyond our address space!
  1756. AssertSz(ulOffset.HighPart == 0, "WriteAt, offset greater than 2^32");
  1757. if (pcbWritten)
  1758. {
  1759. *pcbWritten = 0;
  1760. }
  1761. if (cbWritten + ulOffset.LowPart > m_pData->cb)
  1762. {
  1763. ULARGE_INTEGER ularge_integer;
  1764. ULISet32( ularge_integer, ulOffset.LowPart + cbWritten);
  1765. error = SetSize( ularge_integer );
  1766. if (error != NOERROR)
  1767. {
  1768. goto Exit;
  1769. }
  1770. }
  1771. // CMemBytes does not allow zero-sized memory handles
  1772. pGlobal = (BYTE HUGEP *)GlobalLock (m_pData->hGlobal);
  1773. if (NULL==pGlobal)
  1774. {
  1775. LEERROR(1, "GlobalLock failed!");
  1776. return ResultFromScode (STG_E_WRITEFAULT);
  1777. }
  1778. _xmemcpy(pGlobal + ulOffset.LowPart, pb, cbWritten);
  1779. GlobalUnlock (m_pData->hGlobal);
  1780. if (pcbWritten != NULL)
  1781. {
  1782. *pcbWritten = cbWritten;
  1783. }
  1784. Exit:
  1785. return error;
  1786. }
  1787. //+-------------------------------------------------------------------------
  1788. //
  1789. // Member: CMemBytes::Flush
  1790. //
  1791. // Synopsis: Flushes internal state to disk
  1792. // Not needed for memory ILockBytes
  1793. //
  1794. // Effects:
  1795. //
  1796. // Arguments: void
  1797. //
  1798. // Requires:
  1799. //
  1800. // Returns: NOERROR
  1801. //
  1802. // Signals:
  1803. //
  1804. // Modifies:
  1805. //
  1806. // Derivation: ILockBytes
  1807. //
  1808. // Algorithm:
  1809. //
  1810. // History: dd-mmm-yy Author Comment
  1811. // 05-Dec-93 alexgo 32bit port
  1812. //
  1813. // Notes:
  1814. //
  1815. //--------------------------------------------------------------------------
  1816. #pragma SEG(CMemBytes_Flush)
  1817. STDMETHODIMP CMemBytes::Flush(void)
  1818. {
  1819. VDATEHEAP();
  1820. return NOERROR;
  1821. }
  1822. //+-------------------------------------------------------------------------
  1823. //
  1824. // Member: CMemBytes::SetSize
  1825. //
  1826. // Synopsis: Sets the size of the memory buffer
  1827. //
  1828. // Effects:
  1829. //
  1830. // Arguments: [cb] -- the new size
  1831. //
  1832. // Requires:
  1833. //
  1834. // Returns: NOERROR, E_OUTOFMEMORY
  1835. //
  1836. // Signals:
  1837. //
  1838. // Modifies:
  1839. //
  1840. // Derivation: ILockBytes
  1841. //
  1842. // Algorithm:
  1843. //
  1844. // History: dd-mmm-yy Author Comment
  1845. // 05-Dec-93 alexgo 32bit port
  1846. //
  1847. // Notes:
  1848. //
  1849. //--------------------------------------------------------------------------
  1850. #pragma SEG(CMemBytes_SetSize)
  1851. STDMETHODIMP CMemBytes::SetSize(ULARGE_INTEGER cb)
  1852. {
  1853. VDATEHEAP();
  1854. HANDLE hMemNew;
  1855. AssertSz(cb.HighPart == 0,
  1856. "SetSize: trying to set to more than 2^32 bytes");
  1857. if (m_pData->cb == cb.LowPart)
  1858. {
  1859. return NOERROR;
  1860. }
  1861. hMemNew = GlobalReAlloc(m_pData->hGlobal, max (cb.LowPart, 1),
  1862. GMEM_SHARE | GMEM_MOVEABLE);
  1863. if (hMemNew == NULL)
  1864. {
  1865. return ResultFromScode(E_OUTOFMEMORY);
  1866. }
  1867. m_pData->hGlobal = hMemNew;
  1868. m_pData->cb = cb.LowPart;
  1869. return NOERROR;
  1870. }
  1871. //+-------------------------------------------------------------------------
  1872. //
  1873. // Member: CMemBytes::LockRegion
  1874. //
  1875. // Synopsis: Locks a region. Since only we have access to the memory,
  1876. // nothing needs to be done (note that the *app* also may
  1877. // access, but there's not much we can do about that)
  1878. //
  1879. // Effects:
  1880. //
  1881. // Arguments: [libOffset] -- offset to start with
  1882. // [cb] -- the number of bytes in the locked region
  1883. // [dwLockType] -- the type of lock to use
  1884. //
  1885. // Requires:
  1886. //
  1887. // Returns: NOERROR
  1888. //
  1889. // Signals:
  1890. //
  1891. // Modifies:
  1892. //
  1893. // Derivation: ILockBytes
  1894. //
  1895. // Algorithm:
  1896. //
  1897. // History: dd-mmm-yy Author Comment
  1898. // 05-Dec-93 alexgo 32bit port
  1899. //
  1900. // Notes:
  1901. //
  1902. //--------------------------------------------------------------------------
  1903. #pragma SEG(CMemBytes_LockRegion)
  1904. STDMETHODIMP CMemBytes::LockRegion(ULARGE_INTEGER libOffset,
  1905. ULARGE_INTEGER cb, DWORD dwLockType)
  1906. {
  1907. VDATEHEAP();
  1908. return NOERROR;
  1909. }
  1910. //+-------------------------------------------------------------------------
  1911. //
  1912. // Member: CMemBytes::UnlockRegion
  1913. //
  1914. // Synopsis: Unlocks a region; since only we have access to the memory,
  1915. // nothing needs to be done.
  1916. //
  1917. // Effects:
  1918. //
  1919. // Arguments: [libOffset] -- the offset to start with
  1920. // [cb] -- the number of bytes in the region
  1921. // [dwLockType] -- the lock type
  1922. //
  1923. // Requires:
  1924. //
  1925. // Returns: NOERROR
  1926. //
  1927. // Signals:
  1928. //
  1929. // Modifies:
  1930. //
  1931. // Derivation: ILockBytes
  1932. //
  1933. // Algorithm:
  1934. //
  1935. // History: dd-mmm-yy Author Comment
  1936. // 05-Dec-93 alexgo 32bit port
  1937. //
  1938. // Notes:
  1939. //
  1940. //--------------------------------------------------------------------------
  1941. #pragma SEG(CMemBytes_UnlockRegion)
  1942. STDMETHODIMP CMemBytes::UnlockRegion(ULARGE_INTEGER libOffset,
  1943. ULARGE_INTEGER cb, DWORD dwLockType)
  1944. {
  1945. VDATEHEAP();
  1946. return NOERROR;
  1947. }
  1948. //+-------------------------------------------------------------------------
  1949. //
  1950. // Member: CMemBytes::Stat
  1951. //
  1952. // Synopsis: returns status information
  1953. //
  1954. // Effects:
  1955. //
  1956. // Arguments: [pstatstg] -- where to put the status info
  1957. // [statflag] -- status flags (ignored)
  1958. //
  1959. // Requires:
  1960. //
  1961. // Returns: NOERROR, E_INVALIDARG
  1962. //
  1963. // Signals:
  1964. //
  1965. // Modifies:
  1966. //
  1967. // Derivation: ILockBytes
  1968. //
  1969. // Algorithm:
  1970. //
  1971. // History: dd-mmm-yy Author Comment
  1972. // 05-Dec-93 alexgo 32bit port
  1973. // 01-Jun-94 AlexT Set type correctly
  1974. //
  1975. // Notes:
  1976. //
  1977. //--------------------------------------------------------------------------
  1978. #pragma SEG(CMemBytes_Stat)
  1979. STDMETHODIMP CMemBytes::Stat(STATSTG FAR *pstatstg, DWORD statflag)
  1980. {
  1981. VDATEHEAP();
  1982. VDATEPTROUT( pstatstg, STATSTG );
  1983. memset ( pstatstg, 0, sizeof(STATSTG) );
  1984. pstatstg->type = STGTY_LOCKBYTES;
  1985. pstatstg->cbSize.LowPart = m_pData->cb;
  1986. return NOERROR;
  1987. }
  1988. //+-------------------------------------------------------------------------
  1989. //
  1990. // Member: CMemBytes::Create
  1991. //
  1992. // Synopsis: Creates an instance of CMemBytes
  1993. //
  1994. // Effects:
  1995. //
  1996. // Arguments: [hMem] -- handle to the memory (must be a MEMSTM block)
  1997. //
  1998. // Requires:
  1999. //
  2000. // Returns: CMemBytes *
  2001. //
  2002. // Signals:
  2003. //
  2004. // Modifies:
  2005. //
  2006. // Derivation:
  2007. //
  2008. // Algorithm:
  2009. //
  2010. // History: dd-mmm-yy Author Comment
  2011. // 16-Dec-93 alexgo fixed bad pointer bug (took out
  2012. // GlobalUnlock)
  2013. // 05-Dec-93 alexgo 32bit port
  2014. //
  2015. // Notes:
  2016. //
  2017. //--------------------------------------------------------------------------
  2018. #pragma SEG(CMemBytes_Create)
  2019. STDSTATICIMP_(CMemBytes FAR*) CMemBytes::Create(HANDLE hMem)
  2020. {
  2021. VDATEHEAP();
  2022. CMemBytes FAR* pCMemBytes = NULL;
  2023. struct MEMSTM FAR* pData;
  2024. pData = (MEMSTM FAR*) GlobalLock(hMem);
  2025. if (pData != NULL)
  2026. {
  2027. Assert (pData->hGlobal);
  2028. pCMemBytes = new CMemBytes;
  2029. if (pCMemBytes != NULL)
  2030. {
  2031. // Initialize CMemBytes
  2032. pCMemBytes->m_dwSig = LOCKBYTE_SIG;
  2033. pCMemBytes->m_hMem = hMem;
  2034. InterlockedIncrement ((LPLONG) &(pCMemBytes->m_pData = pData)->cRef); // AddRefMemStm
  2035. pCMemBytes->m_refs = 1;
  2036. CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_ILockBytes,
  2037. (IUnknown **)&pCMemBytes);
  2038. }
  2039. else
  2040. {
  2041. // uh-oh, low on memory
  2042. GlobalUnlock(hMem);
  2043. }
  2044. }
  2045. // we don't GlobalUnlock(hMem) until we destory this CMemBytes
  2046. return pCMemBytes;
  2047. }
  2048. //+-------------------------------------------------------------------------
  2049. //
  2050. // Member: CMemBytes::Dump, public (_DEBUG only)
  2051. //
  2052. // Synopsis: return a string containing the contents of the data members
  2053. //
  2054. // Effects:
  2055. //
  2056. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  2057. // [ulFlag] - flag determining prefix of all newlines of the
  2058. // out character array (default is 0 - no prefix)
  2059. // [nIndentLevel] - will add a indent prefix after the other prefix
  2060. // for ALL newlines (including those with no prefix)
  2061. //
  2062. // Requires:
  2063. //
  2064. // Returns: HRESULT
  2065. //
  2066. // Signals:
  2067. //
  2068. // Modifies: [ppsz] - argument
  2069. //
  2070. // Derivation:
  2071. //
  2072. // Algorithm: use dbgstream to create a string containing information on the
  2073. // content of data structures
  2074. //
  2075. // History: dd-mmm-yy Author Comment
  2076. // 20-Jan-95 t-ScottH author
  2077. //
  2078. // Notes:
  2079. //
  2080. //--------------------------------------------------------------------------
  2081. #ifdef _DEBUG
  2082. HRESULT CMemBytes::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  2083. {
  2084. int i;
  2085. char *pszPrefix;
  2086. char *pszMEMSTM;
  2087. dbgstream dstrPrefix;
  2088. dbgstream dstrDump(400);
  2089. // determine prefix of newlines
  2090. if ( ulFlag & DEB_VERBOSE )
  2091. {
  2092. dstrPrefix << this << " _VB ";
  2093. }
  2094. // determine indentation prefix for all newlines
  2095. for (i = 0; i < nIndentLevel; i++)
  2096. {
  2097. dstrPrefix << DUMPTAB;
  2098. }
  2099. pszPrefix = dstrPrefix.str();
  2100. // put data members in stream
  2101. dstrDump << pszPrefix << "Impl. Signature = " << m_dwSig << endl;
  2102. dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
  2103. dstrDump << pszPrefix << "Memory handle = " << m_hMem << endl;
  2104. if (m_pData != NULL)
  2105. {
  2106. pszMEMSTM = DumpMEMSTM(m_pData, ulFlag, nIndentLevel + 1);
  2107. dstrDump << pszPrefix << "MEMSTM:" << endl;
  2108. dstrDump << pszMEMSTM;
  2109. CoTaskMemFree(pszMEMSTM);
  2110. }
  2111. else
  2112. {
  2113. dstrDump << pszPrefix << "MEMSTM = " << m_pData << endl;
  2114. }
  2115. // cleanup and provide pointer to character array
  2116. *ppszDump = dstrDump.str();
  2117. if (*ppszDump == NULL)
  2118. {
  2119. *ppszDump = UtDupStringA(szDumpErrorMessage);
  2120. }
  2121. CoTaskMemFree(pszPrefix);
  2122. return NOERROR;
  2123. }
  2124. #endif // _DEBUG
  2125. //+-------------------------------------------------------------------------
  2126. //
  2127. // Function: DumpCMemBytes, public (_DEBUG only)
  2128. //
  2129. // Synopsis: calls the CMemBytes::Dump method, takes care of errors and
  2130. // returns the zero terminated string
  2131. //
  2132. // Effects:
  2133. //
  2134. // Arguments: [pMB] - pointer to CMemBytes
  2135. // [ulFlag] - flag determining prefix of all newlines of the
  2136. // out character array (default is 0 - no prefix)
  2137. // [nIndentLevel] - will add a indent prefix after the other prefix
  2138. // for ALL newlines (including those with no prefix)
  2139. //
  2140. // Requires:
  2141. //
  2142. // Returns: character array of structure dump or error (null terminated)
  2143. //
  2144. // Signals:
  2145. //
  2146. // Modifies:
  2147. //
  2148. // Algorithm:
  2149. //
  2150. // History: dd-mmm-yy Author Comment
  2151. // 20-Jan-95 t-ScottH author
  2152. //
  2153. // Notes:
  2154. //
  2155. //--------------------------------------------------------------------------
  2156. #ifdef _DEBUG
  2157. char *DumpCMemBytes(CMemBytes *pMB, ULONG ulFlag, int nIndentLevel)
  2158. {
  2159. HRESULT hresult;
  2160. char *pszDump;
  2161. if (pMB == NULL)
  2162. {
  2163. return UtDupStringA(szDumpBadPtr);
  2164. }
  2165. hresult = pMB->Dump(&pszDump, ulFlag, nIndentLevel);
  2166. if (hresult != NOERROR)
  2167. {
  2168. CoTaskMemFree(pszDump);
  2169. return DumpHRESULT(hresult);
  2170. }
  2171. return pszDump;
  2172. }
  2173. #endif // _DEBUG
  2174. // --------------------------------------------------------------------
  2175. // EVERYTHING BELOW HERE HAS BEEN REMOVED FROM WIN32 VERSIONS.
  2176. #ifndef WIN32
  2177. // CMemStm object's IMarshal implementation
  2178. //
  2179. //+-------------------------------------------------------------------------
  2180. //
  2181. // Member: CMarshalMemStm::QueryInterface
  2182. //
  2183. // Synopsis: returns the requested interface ID
  2184. //
  2185. // Effects:
  2186. //
  2187. // Arguments: [iidInterface] -- the requested interface
  2188. // [ppvObj] -- where to put the interface pointer
  2189. //
  2190. // Requires:
  2191. //
  2192. // Returns: NOERROR, E_NOINTERFACE
  2193. //
  2194. // Signals:
  2195. //
  2196. // Modifies:
  2197. //
  2198. // Derivation: IMarshal
  2199. //
  2200. // Algorithm:
  2201. //
  2202. // History: dd-mmm-yy Author Comment
  2203. // 05-Dec-93 alexgo 32bit port
  2204. //
  2205. // Notes:
  2206. //
  2207. //--------------------------------------------------------------------------
  2208. #pragma SEG(CMarshalMemStm_QueryInterface)
  2209. STDMETHODIMP CMarshalMemStm::QueryInterface(REFIID iidInterface,
  2210. void FAR* FAR* ppvObj)
  2211. {
  2212. VDATEHEAP();
  2213. HRESULT error;
  2214. VDATEPTROUT( ppvObj, LPVOID );
  2215. *ppvObj = NULL;
  2216. VDATEIID( iidInterface );
  2217. // Two interfaces supported: IUnknown, IMarshal
  2218. if (IsEqualIID(iidInterface, IID_IMarshal) ||
  2219. IsEqualIID(iidInterface, IID_IUnknown))
  2220. {
  2221. InterlockedIncrement (&m_refs); // A pointer to this object is returned
  2222. *ppvObj = this;
  2223. error = NOERROR;
  2224. }
  2225. else
  2226. {
  2227. // Not accessible or unsupported interface
  2228. *ppvObj = NULL;
  2229. error = ResultFromScode (E_NOINTERFACE);
  2230. }
  2231. return error;
  2232. }
  2233. //+-------------------------------------------------------------------------
  2234. //
  2235. // Member: CMarshalMemstm::AddRef
  2236. //
  2237. // Synopsis: increments the reference count
  2238. //
  2239. // Effects:
  2240. //
  2241. // Arguments: void
  2242. //
  2243. // Requires:
  2244. //
  2245. // Returns: ULONG -- the new reference count
  2246. //
  2247. // Signals:
  2248. //
  2249. // Modifies:
  2250. //
  2251. // Derivation: IMarshal
  2252. //
  2253. // Algorithm:
  2254. //
  2255. // History: dd-mmm-yy Author Comment
  2256. // 05-Dec-93 alexgo 32bit port
  2257. //
  2258. // Notes:
  2259. //
  2260. //--------------------------------------------------------------------------
  2261. #pragma SEG(CMarshalMemStm_AddRef)
  2262. STDMETHODIMP_(ULONG) CMarshalMemStm::AddRef(void)
  2263. {
  2264. VDATEHEAP();
  2265. return InterlockedIncrement (&m_refs);
  2266. }
  2267. //+-------------------------------------------------------------------------
  2268. //
  2269. // Member: CMarshalMemStm::Release
  2270. //
  2271. // Synopsis: decrements the reference count
  2272. //
  2273. // Effects:
  2274. //
  2275. // Arguments: void
  2276. //
  2277. // Requires:
  2278. //
  2279. // Returns: ULONG -- the new reference count
  2280. //
  2281. // Signals:
  2282. //
  2283. // Modifies:
  2284. //
  2285. // Derivation: IMarshal
  2286. //
  2287. // Algorithm:
  2288. //
  2289. // History: dd-mmm-yy Author Comment
  2290. // 05-Dec-93 alexgo 32bit port
  2291. //
  2292. // Notes:
  2293. //
  2294. //--------------------------------------------------------------------------
  2295. #pragma SEG(CMarshalMemStm_Release)
  2296. STDMETHODIMP_(ULONG) CMarshalMemStm::Release(void)
  2297. {
  2298. VDATEHEAP();
  2299. ULONG ulRefs = InterlockedDecrement (&m_refs);
  2300. if (ulRefs != 0)
  2301. {
  2302. return ulRefs;
  2303. }
  2304. if (m_pMemStm != NULL)
  2305. {
  2306. m_pMemStm->Release();
  2307. }
  2308. delete this; // Free storage
  2309. return 0;
  2310. }
  2311. //+-------------------------------------------------------------------------
  2312. //
  2313. // Member: CMarshalMemStm::GetUnmarshalClass
  2314. //
  2315. // Synopsis: returns the object class that should be used to create
  2316. // the proxy in the unmarshalling process (CLSID_StdMemStm)
  2317. //
  2318. // Effects:
  2319. //
  2320. // Arguments: [riid] -- the interface ID of the object to be
  2321. // marshalled
  2322. // [pv] -- pointer to the object
  2323. // [dwDestContext] -- marshalling context (such a no shared mem)
  2324. // [pvDestContext] -- reserved
  2325. // [mshlfags] -- marshalling flags (e.g. NORMAL)
  2326. // [pCid] -- where to put the class ID
  2327. //
  2328. // Requires:
  2329. //
  2330. // Returns: NOERROR
  2331. //
  2332. // Signals:
  2333. //
  2334. // Modifies:
  2335. //
  2336. // Derivation: IMarshal
  2337. //
  2338. // Algorithm:
  2339. //
  2340. // History: dd-mmm-yy Author Comment
  2341. // 05-Dec-93 alexgo 32bit port
  2342. //
  2343. // Notes:
  2344. //
  2345. //--------------------------------------------------------------------------
  2346. #pragma SEG(CMarshalMemStm_GetUnmarshalClass)
  2347. STDMETHODIMP CMarshalMemStm::GetUnmarshalClass(REFIID riid, LPVOID pv,
  2348. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
  2349. CLSID FAR* pCid)
  2350. {
  2351. VDATEHEAP();
  2352. VDATEPTROUT( pCid, CLSID);
  2353. *pCid = CLSID_StdMemStm;
  2354. return NOERROR;
  2355. }
  2356. //+-------------------------------------------------------------------------
  2357. //
  2358. // Member: CMarshalMemStm::GetUnmarshalSizeMax
  2359. //
  2360. // Synopsis: returns the amount of memory needed to marshal the data
  2361. // (in this case, the hglobal)
  2362. //
  2363. // Effects:
  2364. //
  2365. // Arguments: [riid] -- the interface of the object
  2366. // [pv] -- pointer to the object
  2367. // [dwDestContext] -- marshalling context (such a no shared mem)
  2368. // [pvDestContext] -- reserved
  2369. // [mshlfags] -- marshalling flags (e.g. NORMAL)
  2370. // [pSize] -- where to put the size
  2371. //
  2372. // Requires:
  2373. //
  2374. // Returns: NOERROR, E_INVALIDARG
  2375. //
  2376. // Signals:
  2377. //
  2378. // Modifies:
  2379. //
  2380. // Derivation: IMarshal
  2381. //
  2382. // Algorithm:
  2383. //
  2384. // History: dd-mmm-yy Author Comment
  2385. // 05-Dec-93 alexgo 32bit port
  2386. //
  2387. // Notes:
  2388. //
  2389. //--------------------------------------------------------------------------
  2390. #pragma SEG(CMarshalMemStm_GetMarshalSizeMax)
  2391. STDMETHODIMP CMarshalMemStm::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  2392. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
  2393. DWORD FAR* pSize)
  2394. {
  2395. VDATEHEAP();
  2396. VDATEPTROUT(pSize, DWORD);
  2397. *pSize = sizeof(m_pMemStm->m_hMem);
  2398. return NOERROR;
  2399. }
  2400. //+-------------------------------------------------------------------------
  2401. //
  2402. // Member: CMarshalMemStm::MarshalInterface
  2403. //
  2404. // Synopsis: marshals a reference of the objects interface into [pStm]
  2405. //
  2406. // Effects:
  2407. //
  2408. // Arguments: [pStm] -- the stream into which the object should
  2409. // be marshalled
  2410. // [riid] -- the interface ID of the object to be
  2411. // marshalled
  2412. // [pv] -- points to the interface
  2413. // [dwDestContext] -- the marshalling context
  2414. // [pvDestContext] -- unused
  2415. // [mshlflags] -- marshalling flags
  2416. //
  2417. // Requires:
  2418. //
  2419. // Returns: HRESULT
  2420. //
  2421. // Signals:
  2422. //
  2423. // Modifies:
  2424. //
  2425. // Derivation: IMarshal
  2426. //
  2427. // Algorithm:
  2428. //
  2429. // History: dd-mmm-yy Author Comment
  2430. // 05-Dec-93 alexgo 32bit port
  2431. //
  2432. // Notes:
  2433. //
  2434. //--------------------------------------------------------------------------
  2435. #pragma SEG(CMarshalMemStm_MarshalInterface)
  2436. STDMETHODIMP CMarshalMemStm::MarshalInterface(IStream FAR* pStm,
  2437. REFIID riid, void FAR* pv, DWORD dwDestContext,
  2438. LPVOID pvDestContext, DWORD mshlflags)
  2439. {
  2440. VDATEHEAP();
  2441. VDATEPTRIN( pStm, IStream );
  2442. VDATEIID( riid );
  2443. VDATEIFACE( pv );
  2444. if (m_pMemStm == NULL)
  2445. {
  2446. return ResultFromScode(E_UNSPEC);
  2447. }
  2448. if ((!IsEqualIID(riid, IID_IStream) &&
  2449. !IsEqualIID(riid, IID_IUnknown)) || pv != m_pMemStm)
  2450. {
  2451. return ReportResult(0, E_INVALIDARG, 0, 0);
  2452. }
  2453. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  2454. HRESULT error;
  2455. if ((error = pStm->Write(&m_pMemStm->m_hMem,
  2456. sizeof(m_pMemStm->m_hMem), NULL)) == NOERROR)
  2457. {
  2458. InterlockedIncrement (&m_pMemStm->m_pData->cRef); // AddRefMemStm
  2459. }
  2460. return error;
  2461. }
  2462. //+-------------------------------------------------------------------------
  2463. //
  2464. // Member: CMarshalMemStm::UnmarshalInterface
  2465. //
  2466. // Synopsis: Unmarshals an the object from the given stream
  2467. //
  2468. // Effects:
  2469. //
  2470. // Arguments: [pStm] -- the stream to read data from
  2471. // [riid] -- the interface the caller wants from the
  2472. // object
  2473. // [ppvObj] -- where to put a pointer to the object
  2474. //
  2475. // Requires:
  2476. //
  2477. // Returns: HRESULT
  2478. //
  2479. // Signals:
  2480. //
  2481. // Modifies:
  2482. //
  2483. // Derivation: IMarshal
  2484. //
  2485. // Algorithm:
  2486. //
  2487. // History: dd-mmm-yy Author Comment
  2488. // 05-Dec-93 alexgo 32bit port
  2489. //
  2490. // Notes:
  2491. //
  2492. //--------------------------------------------------------------------------
  2493. #pragma SEG(CMarshalMemStm_UnmarshalInterface)
  2494. STDMETHODIMP CMarshalMemStm::UnmarshalInterface(IStream FAR* pStm,
  2495. REFIID riid, void FAR* FAR* ppv)
  2496. {
  2497. VDATEHEAP();
  2498. HRESULT error;
  2499. HANDLE hMem;
  2500. VDATEPTROUT( ppv, LPVOID );
  2501. *ppv = NULL;
  2502. VDATEPTRIN( pStm, IStream );
  2503. VDATEIID( riid );
  2504. if (!IsEqualIID(riid, IID_IStream) && !IsEqualIID(riid, IID_IUnknown))
  2505. {
  2506. return ResultFromScode(E_INVALIDARG);
  2507. }
  2508. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  2509. if (error != NOERROR)
  2510. {
  2511. return error;
  2512. }
  2513. if (m_pMemStm != NULL)
  2514. {
  2515. if (hMem != m_pMemStm->m_hMem)
  2516. {
  2517. return ResultFromScode(E_UNSPEC);
  2518. }
  2519. }
  2520. else
  2521. {
  2522. m_pMemStm = (CMemStm FAR*) CloneMemStm(hMem);
  2523. if (m_pMemStm == NULL)
  2524. {
  2525. return ResultFromScode(E_OUTOFMEMORY);
  2526. }
  2527. }
  2528. m_pMemStm->AddRef();
  2529. *ppv = (LPVOID) m_pMemStm;
  2530. return NOERROR;
  2531. }
  2532. //+-------------------------------------------------------------------------
  2533. //
  2534. // Member: CMarshalMemStm::ReleaseMarshalData
  2535. //
  2536. // Synopsis: releases the marshalling data (takes away ref count on
  2537. // hglobal)
  2538. //
  2539. // Effects:
  2540. //
  2541. // Arguments:
  2542. //
  2543. // Requires:
  2544. //
  2545. // Returns:
  2546. //
  2547. // Signals:
  2548. //
  2549. // Modifies:
  2550. //
  2551. // Derivation:
  2552. //
  2553. // Algorithm:
  2554. //
  2555. // History: dd-mmm-yy Author Comment
  2556. //
  2557. // Notes:
  2558. //
  2559. //--------------------------------------------------------------------------
  2560. #pragma SEG(CMarshalMemStm_ReleaseMarshalData)
  2561. STDMETHODIMP CMarshalMemStm::ReleaseMarshalData(IStream FAR* pStm)
  2562. {
  2563. VDATEHEAP();
  2564. // reduce ref count on hglobal (matches that done in MarshalInterface)
  2565. HRESULT error;
  2566. HANDLE hMem;
  2567. VDATEIFACE( pStm );
  2568. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  2569. if (error == NOERROR)
  2570. ReleaseMemStm(&hMem);
  2571. return error;
  2572. }
  2573. //+-------------------------------------------------------------------------
  2574. //
  2575. // Member:
  2576. //
  2577. // Synopsis:
  2578. //
  2579. // Effects:
  2580. //
  2581. // Arguments:
  2582. //
  2583. // Requires:
  2584. //
  2585. // Returns:
  2586. //
  2587. // Signals:
  2588. //
  2589. // Modifies:
  2590. //
  2591. // Derivation:
  2592. //
  2593. // Algorithm:
  2594. //
  2595. // History: dd-mmm-yy Author Comment
  2596. //
  2597. // Notes:
  2598. //
  2599. //--------------------------------------------------------------------------
  2600. #pragma SEG(CMarshalMemStm_DisconnectObject)
  2601. STDMETHODIMP CMarshalMemStm::DisconnectObject(DWORD dwReserved)
  2602. {
  2603. VDATEHEAP();
  2604. return NOERROR;
  2605. }
  2606. //+-------------------------------------------------------------------------
  2607. //
  2608. // Member:
  2609. //
  2610. // Synopsis:
  2611. //
  2612. // Effects:
  2613. //
  2614. // Arguments:
  2615. //
  2616. // Requires:
  2617. //
  2618. // Returns:
  2619. //
  2620. // Signals:
  2621. //
  2622. // Modifies:
  2623. //
  2624. // Derivation:
  2625. //
  2626. // Algorithm:
  2627. //
  2628. // History: dd-mmm-yy Author Comment
  2629. //
  2630. // Notes:
  2631. //
  2632. //--------------------------------------------------------------------------
  2633. #pragma SEG(CMarshalMemStm_Create)
  2634. STDSTATICIMP_(CMarshalMemStm FAR*) CMarshalMemStm::Create(CMemStm FAR* pMemStm)
  2635. {
  2636. VDATEHEAP();
  2637. CMarshalMemStm FAR* pMMS;
  2638. //VDATEPTRIN rejects NULL
  2639. if( pMemStm )
  2640. GEN_VDATEPTRIN( pMemStm, CMemStm, (CMarshalMemStm FAR *) NULL );
  2641. pMMS = new(MEMCTX_TASK, NULL) CMarshalMemStm;
  2642. if (pMMS == NULL)
  2643. return NULL;
  2644. if (pMemStm != NULL) {
  2645. pMMS->m_pMemStm = pMemStm;
  2646. pMMS->m_pMemStm->AddRef();
  2647. }
  2648. pMMS->m_refs = 1;
  2649. return pMMS;
  2650. }
  2651. //+-------------------------------------------------------------------------
  2652. //
  2653. // Function:
  2654. //
  2655. // Synopsis:
  2656. //
  2657. // Effects:
  2658. //
  2659. // Arguments:
  2660. //
  2661. // Requires:
  2662. //
  2663. // Returns:
  2664. //
  2665. // Signals:
  2666. //
  2667. // Modifies:
  2668. //
  2669. // Algorithm:
  2670. //
  2671. // History: dd-mmm-yy Author Comment
  2672. //
  2673. // Notes:
  2674. //
  2675. //--------------------------------------------------------------------------
  2676. #pragma SEG(CMemStmUnMarshal)
  2677. STDAPI_(IUnknown FAR*) CMemStmUnMarshal(void)
  2678. {
  2679. VDATEHEAP();
  2680. return CMarshalMemStm::Create(NULL);
  2681. }
  2682. // CMemBytes object's IMarshal implementation
  2683. //
  2684. //+-------------------------------------------------------------------------
  2685. //
  2686. // Member:
  2687. //
  2688. // Synopsis:
  2689. //
  2690. // Effects:
  2691. //
  2692. // Arguments:
  2693. //
  2694. // Requires:
  2695. //
  2696. // Returns:
  2697. //
  2698. // Signals:
  2699. //
  2700. // Modifies:
  2701. //
  2702. // Derivation:
  2703. //
  2704. // Algorithm:
  2705. //
  2706. // History: dd-mmm-yy Author Comment
  2707. //
  2708. // Notes:
  2709. //
  2710. //--------------------------------------------------------------------------
  2711. #pragma SEG(CMarshalMemBytes_QueryInterface)
  2712. STDMETHODIMP CMarshalMemBytes::QueryInterface(REFIID iidInterface,
  2713. void FAR* FAR* ppvObj)
  2714. {
  2715. VDATEHEAP();
  2716. HRESULT error;
  2717. VDATEIID( iidInterface );
  2718. VDATEPTROUT( ppvObj, LPVOID );
  2719. *ppvObj = NULL;
  2720. // Two interfaces supported: IUnknown, IMarshal
  2721. if (IsEqualIID(iidInterface, IID_IMarshal)
  2722. || IsEqualIID(iidInterface, IID_IUnknown))
  2723. {
  2724. InterlockedIncrement (&m_refs); // A pointer to this object is returned
  2725. *ppvObj = this;
  2726. error = NOERROR;
  2727. }
  2728. else
  2729. { // Not accessible or unsupported interface
  2730. *ppvObj = NULL;
  2731. error = ReportResult(0, E_NOINTERFACE, 0, 0);
  2732. }
  2733. return error;
  2734. }
  2735. //+-------------------------------------------------------------------------
  2736. //
  2737. // Member:
  2738. //
  2739. // Synopsis:
  2740. //
  2741. // Effects:
  2742. //
  2743. // Arguments:
  2744. //
  2745. // Requires:
  2746. //
  2747. // Returns:
  2748. //
  2749. // Signals:
  2750. //
  2751. // Modifies:
  2752. //
  2753. // Derivation:
  2754. //
  2755. // Algorithm:
  2756. //
  2757. // History: dd-mmm-yy Author Comment
  2758. //
  2759. // Notes:
  2760. //
  2761. //--------------------------------------------------------------------------
  2762. // Called when CMarshalMemBytes is referenced by an additional pointer.
  2763. //
  2764. #pragma SEG(CMarshalMemBytes_AddRef)
  2765. STDMETHODIMP_(ULONG) CMarshalMemBytes::AddRef(void)
  2766. {
  2767. VDATEHEAP();
  2768. return InterlockedIncrement (&m_refs);
  2769. }
  2770. //+-------------------------------------------------------------------------
  2771. //
  2772. // Member:
  2773. //
  2774. // Synopsis:
  2775. //
  2776. // Effects:
  2777. //
  2778. // Arguments:
  2779. //
  2780. // Requires:
  2781. //
  2782. // Returns:
  2783. //
  2784. // Signals:
  2785. //
  2786. // Modifies:
  2787. //
  2788. // Derivation:
  2789. //
  2790. // Algorithm:
  2791. //
  2792. // History: dd-mmm-yy Author Comment
  2793. //
  2794. // Notes:
  2795. //
  2796. //--------------------------------------------------------------------------
  2797. #pragma SEG(CMarshalMemBytes_Release)
  2798. // Called when a pointer to this CMarshalMemBytes is discarded
  2799. //
  2800. STDMETHODIMP_(ULONG) CMarshalMemBytes::Release(void)
  2801. {
  2802. VDATEHEAP();
  2803. ULONG ulRefs = InterlockedDecrement (&m_refs);
  2804. if (ulRefs != 0) // Still used by others
  2805. return ulRefs;
  2806. if (m_pMemBytes != NULL)
  2807. m_pMemBytes->Release();
  2808. delete this; // Free storage
  2809. return 0;
  2810. }
  2811. //+-------------------------------------------------------------------------
  2812. //
  2813. // Member:
  2814. //
  2815. // Synopsis:
  2816. //
  2817. // Effects:
  2818. //
  2819. // Arguments:
  2820. //
  2821. // Requires:
  2822. //
  2823. // Returns:
  2824. //
  2825. // Signals:
  2826. //
  2827. // Modifies:
  2828. //
  2829. // Derivation:
  2830. //
  2831. // Algorithm:
  2832. //
  2833. // History: dd-mmm-yy Author Comment
  2834. //
  2835. // Notes:
  2836. //
  2837. //--------------------------------------------------------------------------
  2838. #pragma SEG(CMarshalMemBytes_GetUnmarshalClass)
  2839. // Returns the clsid of the object that created this CMarshalMemBytes.
  2840. //
  2841. STDMETHODIMP CMarshalMemBytes::GetUnmarshalClass(REFIID riid, LPVOID pv,
  2842. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
  2843. {
  2844. VDATEHEAP();
  2845. VDATEIID( riid );
  2846. VDATEIFACE( pv );
  2847. *pCid = CLSID_StdMemBytes;
  2848. return NOERROR;
  2849. }
  2850. //+-------------------------------------------------------------------------
  2851. //
  2852. // Member:
  2853. //
  2854. // Synopsis:
  2855. //
  2856. // Effects:
  2857. //
  2858. // Arguments:
  2859. //
  2860. // Requires:
  2861. //
  2862. // Returns:
  2863. //
  2864. // Signals:
  2865. //
  2866. // Modifies:
  2867. //
  2868. // Derivation:
  2869. //
  2870. // Algorithm:
  2871. //
  2872. // History: dd-mmm-yy Author Comment
  2873. //
  2874. // Notes:
  2875. //
  2876. //--------------------------------------------------------------------------
  2877. #pragma SEG(CMarshalMemBytes_GetMarshalSizeMax)
  2878. STDMETHODIMP CMarshalMemBytes::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  2879. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
  2880. {
  2881. VDATEHEAP();
  2882. VDATEPTROUT( pSize, DWORD );
  2883. VDATEIID( riid );
  2884. VDATEIFACE( pv );
  2885. *pSize = sizeof(m_pMemBytes->m_hMem);
  2886. return NOERROR;
  2887. }
  2888. //+-------------------------------------------------------------------------
  2889. //
  2890. // Member:
  2891. //
  2892. // Synopsis:
  2893. //
  2894. // Effects:
  2895. //
  2896. // Arguments:
  2897. //
  2898. // Requires:
  2899. //
  2900. // Returns:
  2901. //
  2902. // Signals:
  2903. //
  2904. // Modifies:
  2905. //
  2906. // Derivation:
  2907. //
  2908. // Algorithm:
  2909. //
  2910. // History: dd-mmm-yy Author Comment
  2911. //
  2912. // Notes:
  2913. //
  2914. //--------------------------------------------------------------------------
  2915. #pragma SEG(CMarshalMemBytes_MarshalInterface)
  2916. STDMETHODIMP CMarshalMemBytes::MarshalInterface(IStream FAR* pStm,
  2917. REFIID riid, void FAR* pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
  2918. {
  2919. VDATEHEAP();
  2920. VDATEPTRIN(pStm, IStream );
  2921. VDATEIID( riid );
  2922. if ( pv )
  2923. VDATEPTRIN( pv , char );
  2924. if (m_pMemBytes == NULL)
  2925. return ReportResult(0, E_UNSPEC, 0, 0);
  2926. if ((!IsEqualIID(riid, IID_ILockBytes) &&
  2927. !IsEqualIID(riid, IID_IUnknown)) || pv != m_pMemBytes)
  2928. return ReportResult(0, E_INVALIDARG, 0, 0);
  2929. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  2930. HRESULT error;
  2931. if ((error = pStm->Write(&m_pMemBytes->m_hMem,
  2932. sizeof(m_pMemBytes->m_hMem), NULL)) == NOERROR)
  2933. InterlockedIncrement (&m_pMemBytes->m_pData->cRef); // AddRefMemStm
  2934. return error;
  2935. }
  2936. //+-------------------------------------------------------------------------
  2937. //
  2938. // Member:
  2939. //
  2940. // Synopsis:
  2941. //
  2942. // Effects:
  2943. //
  2944. // Arguments:
  2945. //
  2946. // Requires:
  2947. //
  2948. // Returns:
  2949. //
  2950. // Signals:
  2951. //
  2952. // Modifies:
  2953. //
  2954. // Derivation:
  2955. //
  2956. // Algorithm:
  2957. //
  2958. // History: dd-mmm-yy Author Comment
  2959. //
  2960. // Notes:
  2961. //
  2962. //--------------------------------------------------------------------------
  2963. #pragma SEG(CMarshalMemBytes_UnmarshalInterface)
  2964. STDMETHODIMP CMarshalMemBytes::UnmarshalInterface(IStream FAR* pStm,
  2965. REFIID riid, void FAR* FAR* ppv)
  2966. {
  2967. VDATEHEAP();
  2968. HRESULT error;
  2969. HANDLE hMem;
  2970. VDATEPTROUT( ppv , LPVOID );
  2971. *ppv = NULL;
  2972. VDATEIFACE( pStm );
  2973. VDATEIID( riid );
  2974. if (!IsEqualIID(riid, IID_ILockBytes) &&
  2975. !IsEqualIID(riid, IID_IUnknown))
  2976. return ReportResult(0, E_INVALIDARG, 0, 0);
  2977. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  2978. if (error != NOERROR)
  2979. return error;
  2980. if (m_pMemBytes != NULL)
  2981. {
  2982. if (hMem != m_pMemBytes->m_hMem)
  2983. return ReportResult(0, E_UNSPEC, 0, 0);
  2984. }
  2985. else
  2986. {
  2987. m_pMemBytes = CMemBytes::Create(hMem); // Create the lockbytes
  2988. if (m_pMemBytes == NULL)
  2989. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  2990. }
  2991. m_pMemBytes->AddRef();
  2992. *ppv = (LPVOID) m_pMemBytes;
  2993. return NOERROR;
  2994. }
  2995. //+-------------------------------------------------------------------------
  2996. //
  2997. // Member:
  2998. //
  2999. // Synopsis:
  3000. //
  3001. // Effects:
  3002. //
  3003. // Arguments:
  3004. //
  3005. // Requires:
  3006. //
  3007. // Returns:
  3008. //
  3009. // Signals:
  3010. //
  3011. // Modifies:
  3012. //
  3013. // Derivation:
  3014. //
  3015. // Algorithm:
  3016. //
  3017. // History: dd-mmm-yy Author Comment
  3018. //
  3019. // Notes:
  3020. //
  3021. //--------------------------------------------------------------------------
  3022. STDMETHODIMP CMarshalMemBytes::ReleaseMarshalData(IStream FAR* pStm)
  3023. {
  3024. VDATEHEAP();
  3025. // reduce ref count on hglobal (matches that done in MarshalInterface)
  3026. HRESULT error;
  3027. HANDLE hMem;
  3028. VDATEIFACE( pStm );
  3029. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  3030. if (error == NOERROR)
  3031. ReleaseMemStm(&hMem);
  3032. return error;
  3033. }
  3034. //+-------------------------------------------------------------------------
  3035. //
  3036. // Member:
  3037. //
  3038. // Synopsis:
  3039. //
  3040. // Effects:
  3041. //
  3042. // Arguments:
  3043. //
  3044. // Requires:
  3045. //
  3046. // Returns:
  3047. //
  3048. // Signals:
  3049. //
  3050. // Modifies:
  3051. //
  3052. // Derivation:
  3053. //
  3054. // Algorithm:
  3055. //
  3056. // History: dd-mmm-yy Author Comment
  3057. //
  3058. // Notes:
  3059. //
  3060. //--------------------------------------------------------------------------
  3061. #pragma SEG(CMarshalMemBytes_DisconnectObject)
  3062. STDMETHODIMP CMarshalMemBytes::DisconnectObject(DWORD dwReserved)
  3063. {
  3064. VDATEHEAP();
  3065. return NOERROR;
  3066. }
  3067. //+-------------------------------------------------------------------------
  3068. //
  3069. // Member:
  3070. //
  3071. // Synopsis:
  3072. //
  3073. // Effects:
  3074. //
  3075. // Arguments:
  3076. //
  3077. // Requires:
  3078. //
  3079. // Returns:
  3080. //
  3081. // Signals:
  3082. //
  3083. // Modifies:
  3084. //
  3085. // Derivation:
  3086. //
  3087. // Algorithm:
  3088. //
  3089. // History: dd-mmm-yy Author Comment
  3090. //
  3091. // Notes:
  3092. //
  3093. //--------------------------------------------------------------------------
  3094. #pragma SEG(CMarshalMemBytes_Create)
  3095. STDSTATICIMP_(CMarshalMemBytes FAR*) CMarshalMemBytes::Create(
  3096. CMemBytes FAR* pMemBytes)
  3097. {
  3098. VDATEHEAP();
  3099. CMarshalMemBytes FAR* pMMB;
  3100. //VDATEPTRIN rejects NULL
  3101. if( pMemBytes )
  3102. GEN_VDATEPTRIN( pMemBytes, CMemBytes,
  3103. (CMarshalMemBytes FAR *)NULL);
  3104. pMMB = new(MEMCTX_TASK, NULL) CMarshalMemBytes;
  3105. if (pMMB == NULL)
  3106. return NULL;
  3107. if (pMemBytes != NULL)
  3108. {
  3109. pMMB->m_pMemBytes = pMemBytes;
  3110. pMMB->m_pMemBytes->AddRef();
  3111. }
  3112. pMMB->m_refs = 1;
  3113. return pMMB;
  3114. }
  3115. //+-------------------------------------------------------------------------
  3116. //
  3117. // Member:
  3118. //
  3119. // Synopsis:
  3120. //
  3121. // Effects:
  3122. //
  3123. // Arguments:
  3124. //
  3125. // Requires:
  3126. //
  3127. // Returns:
  3128. //
  3129. // Signals:
  3130. //
  3131. // Modifies:
  3132. //
  3133. // Derivation:
  3134. //
  3135. // Algorithm:
  3136. //
  3137. // History: dd-mmm-yy Author Comment
  3138. //
  3139. // Notes:
  3140. //
  3141. //--------------------------------------------------------------------------
  3142. #pragma SEG(CMemBytesUnMarshal)
  3143. STDAPI_(IUnknown FAR*) CMemBytesUnMarshal(void)
  3144. {
  3145. VDATEHEAP();
  3146. return CMarshalMemBytes::Create(NULL);
  3147. }
  3148. #endif // !WIN32 -- win32 builds use standard marshalling for
  3149. // streams and lockbytes.