Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1326 lines
31 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: memstm.cxx
  7. //
  8. // Contents: memstm.cpp from OLE2
  9. //
  10. // History: 11-Apr-94 DrewB Copied from OLE2
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. #include <ole2int.h>
  16. #include "memstm.h"
  17. #include <reterr.h>
  18. static const UINT grfMem = GMEM_SHARE | GMEM_MOVEABLE;
  19. // REVIEW: there is a lot of duplicate code. There used to be two separate
  20. // but identical structs: MEMSTM and MEMBYTES; the structs have be merged and
  21. // common code should be pulled out including: Release, AddRef, marshal, SetSize
  22. // Shared memory IStream implementation
  23. //
  24. OLEMETHODIMP CMemStm::QueryInterface(REFIID iidInterface, void FAR* FAR* ppvObj)
  25. {
  26. M_PROLOG(this);
  27. HRESULT error;
  28. VDATEPTROUT( ppvObj, LPVOID );
  29. *ppvObj = NULL;
  30. VDATEIID( iidInterface );
  31. // Two interfaces supported: IUnknown, IStream
  32. if (m_pData != NULL &&
  33. (iidInterface == IID_IStream || iidInterface == IID_IUnknown)) {
  34. m_refs++; // A pointer to this object is returned
  35. *ppvObj = this;
  36. error = NOERROR;
  37. } else
  38. //
  39. // BUGBUG - Renable this once CraigWi seperates Custom Marshalling stuff from
  40. // standard identity stuff. (Right now you can't get in between the standard
  41. // marshaller and the code which calls it, you're either completely custom
  42. // marshalling, or your not). Once it is better organized, we could marshall
  43. // a heap handle and the custom marshalling stuff. Then when unmarshalling in
  44. // the same wow, we unmarshal the heap handle, when not in the same wow, then
  45. // use the standard marshalling stuff.
  46. // Same goes for ILockBytesonHglobal below...
  47. //
  48. #define BOBDAY_DISABLE_MARSHAL_FOR_NOW
  49. #ifdef BOBDAY_DISABLE_MARSHAL_FOR_NOW
  50. #else
  51. if (iidInterface == IID_IMarshal) {
  52. *ppvObj = (LPVOID) CMarshalMemStm::Create(this);
  53. if (*ppvObj != NULL)
  54. error = NOERROR;
  55. else
  56. error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
  57. }
  58. else
  59. #endif
  60. { // Not accessible or unsupported interface
  61. *ppvObj = NULL;
  62. error = ReportResult(0, E_NOINTERFACE, 0, 0);
  63. }
  64. return error;
  65. }
  66. // Called when CMemStm is referenced by an additional pointer.
  67. //
  68. OLEMETHODIMP_(ULONG) CMemStm::AddRef(void)
  69. {
  70. M_PROLOG(this);
  71. return ++m_refs;
  72. }
  73. // Called when a pointer to this CMemStm is discarded
  74. //
  75. OLEMETHODIMP_(ULONG) CMemStm::Release(void)
  76. {
  77. M_PROLOG(this);
  78. if (--m_refs != 0) // Still used by others
  79. return m_refs;
  80. ReleaseMemStm(&m_hMem);
  81. delete this; // Free storage
  82. return 0;
  83. }
  84. OLEMETHODIMP CMemStm::Read(void HUGEP* pb, ULONG cb, ULONG FAR* pcbRead)
  85. {
  86. M_PROLOG(this);
  87. thkDebugOut((DEB_ITRACE,
  88. "%p _IN CMemStm16::Read(pb=%p,cb=%lx)\n",
  89. this,pb,cb));
  90. HRESULT error = NOERROR;
  91. ULONG cbRead = cb;
  92. VDATEPTROUT( pb, char);
  93. if (pcbRead) {
  94. VDATEPTROUT( pcbRead, ULONG );
  95. *pcbRead = 0L;
  96. }
  97. if (pcbRead != NULL)
  98. *pcbRead = 0;
  99. if (cbRead + m_pos > m_pData->cb)
  100. {
  101. // Caller is asking for more bytes than we have left
  102. cbRead = m_pData->cb - m_pos;
  103. }
  104. if (cbRead > 0)
  105. {
  106. Assert (m_pData->hGlobal);
  107. char HUGEP* pGlobal = GlobalLock (m_pData->hGlobal);
  108. if (NULL==pGlobal)
  109. {
  110. Assert (0);
  111. error = ResultFromScode (STG_E_READFAULT);
  112. goto exitRtn;
  113. }
  114. UtMemCpy (pb, pGlobal + m_pos, cbRead);
  115. GlobalUnlock (m_pData->hGlobal);
  116. m_pos += cbRead;
  117. }
  118. if (pcbRead != NULL)
  119. *pcbRead = cbRead;
  120. exitRtn:
  121. thkDebugOut((DEB_ITRACE,
  122. "%p OUT CMemStm16::Read() returns %lx\n",
  123. this,error));
  124. return error;
  125. }
  126. OLEMETHODIMP CMemStm::Write(void const HUGEP* pb, ULONG cb, ULONG FAR* pcbWritten)
  127. {
  128. A5_PROLOG(this);
  129. HRESULT error = NOERROR;
  130. thkDebugOut((DEB_ITRACE,
  131. "%p _IN CMemStm16::Write(pb=%p,cb=%lx)\n",
  132. this,pb,cb));
  133. ULONG cbWritten = cb;
  134. ULARGE_INTEGER ularge_integer;
  135. char HUGEP* pGlobal;
  136. if ( pcbWritten ) {
  137. VDATEPTROUT( pcbWritten, ULONG );
  138. *pcbWritten = 0L;
  139. }
  140. VDATEPTRIN( pb , char );
  141. if (pcbWritten != NULL)
  142. *pcbWritten = 0;
  143. if (cbWritten + m_pos > m_pData->cb) {
  144. ULISet32( ularge_integer, m_pos+cbWritten );
  145. error = SetSize(ularge_integer);
  146. if (error != NOERROR)
  147. goto Exit;
  148. }
  149. pGlobal = GlobalLock (m_pData->hGlobal);
  150. if (NULL==pGlobal)
  151. {
  152. Assert (0);
  153. error = ResultFromScode (STG_E_WRITEFAULT);
  154. goto Exit;
  155. }
  156. UtMemCpy (pGlobal + m_pos, pb, cbWritten);
  157. GlobalUnlock (m_pData->hGlobal);
  158. m_pos += cbWritten;
  159. if (pcbWritten != NULL)
  160. *pcbWritten = cbWritten;
  161. Exit:
  162. RESTORE_A5();
  163. thkDebugOut((DEB_ITRACE,
  164. "%p OUT CMemStm16::Write() returns %lx\n",
  165. this,error));
  166. return error;
  167. }
  168. OLEMETHODIMP CMemStm::Seek(LARGE_INTEGER dlibMoveIN, DWORD dwOrigin, ULARGE_INTEGER FAR* plibNewPosition)
  169. {
  170. M_PROLOG(this);
  171. thkDebugOut((DEB_ITRACE,"%p _IN CMemStm16::Seek()\n",this));
  172. HRESULT error = NOERROR;
  173. LONG dlibMove = dlibMoveIN.LowPart ;
  174. ULONG cbNewPos = dlibMove;
  175. if (plibNewPosition != NULL){
  176. VDATEPTROUT( plibNewPosition, ULONG );
  177. ULISet32(*plibNewPosition, m_pos);
  178. }
  179. switch(dwOrigin) {
  180. case STREAM_SEEK_SET:
  181. if (dlibMove >= 0)
  182. m_pos = dlibMove;
  183. else
  184. error = ReportResult(0, E_UNSPEC, 0, 0); // should return invalid seek
  185. break;
  186. case STREAM_SEEK_CUR:
  187. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
  188. m_pos += dlibMove;
  189. else
  190. error = ReportResult(0, E_UNSPEC, 0, 0); // should return invalid seek
  191. break;
  192. case STREAM_SEEK_END:
  193. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pData->cb))
  194. m_pos = m_pData->cb + dlibMove;
  195. else
  196. error = ReportResult(0, E_UNSPEC, 0, 0); // should return invalid seek
  197. break;
  198. default:
  199. error = ReportResult(0, E_UNSPEC, 0, 0); // should return invalid seek mode
  200. }
  201. if (plibNewPosition != NULL)
  202. ULISet32(*plibNewPosition, m_pos);
  203. thkDebugOut((DEB_ITRACE,"%p OUT CMemStm16::Seek() returns %lx\n",this,error));
  204. return error;
  205. }
  206. OLEMETHODIMP CMemStm::SetSize(ULARGE_INTEGER cb)
  207. {
  208. M_PROLOG(this);
  209. thkDebugOut((DEB_ITRACE,
  210. "%p _IN CMemStm16::SetSize(cb=%lx%lx)\n",
  211. this,cb.HighPart,cb.LowPart));
  212. HANDLE hMemNew;
  213. HRESULT hresult = NOERROR;
  214. if (m_pData->cb == cb.LowPart)
  215. {
  216. goto errRtn;
  217. }
  218. hMemNew = GlobalReAlloc(m_pData->hGlobal,max (cb.LowPart,1),grfMem);
  219. if (hMemNew == NULL)
  220. {
  221. hresult = ResultFromScode (E_OUTOFMEMORY);
  222. goto errRtn;
  223. }
  224. m_pData->hGlobal = hMemNew;
  225. m_pData->cb = cb.LowPart;
  226. errRtn:
  227. thkDebugOut((DEB_ITRACE,
  228. "%p OUT CMemStm16::SetSize() returns %lx\n",
  229. this,
  230. hresult));
  231. return hresult;
  232. }
  233. OLEMETHODIMP CMemStm::CopyTo(IStream FAR *pstm,
  234. ULARGE_INTEGER cb,
  235. ULARGE_INTEGER FAR * pcbRead,
  236. ULARGE_INTEGER FAR * pcbWritten)
  237. {
  238. thkDebugOut((DEB_ITRACE,
  239. "%p _IN CMemStm16::CopyTo(pstm=%p)\n",
  240. this,
  241. pstm));
  242. ULONG cbRead = cb.LowPart;
  243. ULONG cbWritten = 0;
  244. HRESULT hresult = NOERROR;
  245. // pstm cannot be NULL
  246. VDATEPTRIN(pstm, LPSTREAM);
  247. // the spec says that if cb is it's maximum value (all bits set,
  248. // since it's unsigned), then we will simply read the copy of
  249. // this stream
  250. if ( ~(cb.LowPart) == 0 && ~(cb.HighPart) == 0 )
  251. {
  252. cbRead = m_pData->cb - m_pos;
  253. }
  254. else if ( cb.HighPart > 0 )
  255. {
  256. // we assume that our memory stream cannot
  257. // be large enough to accomodate very large (>32bit)
  258. // copy to requests. Since this is probably an error
  259. // on the caller's part, we assert.
  260. thkAssert(!"WARNING: CopyTo request exceeds 32 bits");
  261. // set the Read value to what's left, so that "Ignore"ing
  262. // the assert works properly.
  263. cbRead = m_pData->cb - m_pos;
  264. }
  265. else if ( cbRead + m_pos > m_pData->cb )
  266. {
  267. // more bytes were requested to read than we had left.
  268. // cbRead is set to the amount remaining.
  269. cbRead = m_pData->cb - m_pos;
  270. }
  271. // now write the data to the stream
  272. if ( cbRead > 0 )
  273. {
  274. BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
  275. m_pData->hGlobal);
  276. if( pGlobal == NULL )
  277. {
  278. thkAssert(!"GlobalLock failed");
  279. hresult = (HRESULT)STG_E_INSUFFICIENTMEMORY;
  280. goto errRtn;
  281. }
  282. hresult = pstm->Write(pGlobal + m_pos, cbRead, &cbWritten);
  283. // in the error case, the spec says that the return values
  284. // may be meaningless, so we do not need to do any special
  285. // error handling here
  286. GlobalUnlock(m_pData->hGlobal);
  287. }
  288. // increment our seek pointer and set the out parameters
  289. m_pos += cbRead;
  290. if( pcbRead )
  291. {
  292. ULISet32(*pcbRead, cbRead);
  293. }
  294. if( pcbWritten )
  295. {
  296. ULISet32(*pcbWritten, cbWritten);
  297. }
  298. errRtn:
  299. thkDebugOut((DEB_ITRACE,
  300. "%p OUT CMemStm16::CopyTo(pstm=%p) returns %lx\n",
  301. this,
  302. pstm,
  303. hresult));
  304. return hresult;
  305. }
  306. OLEMETHODIMP CMemStm::Commit(DWORD grfCommitFlags)
  307. {
  308. M_PROLOG(this);
  309. return NOERROR; // since this stream is not transacted, no error
  310. }
  311. OLEMETHODIMP CMemStm::Revert(void)
  312. {
  313. M_PROLOG(this);
  314. return NOERROR; // nothing done
  315. }
  316. OLEMETHODIMP CMemStm::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  317. {
  318. M_PROLOG(this);
  319. return ResultFromScode(STG_E_INVALIDFUNCTION);
  320. }
  321. OLEMETHODIMP CMemStm::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  322. {
  323. M_PROLOG(this);
  324. return ResultFromScode(STG_E_INVALIDFUNCTION);
  325. }
  326. OLEMETHODIMP CMemStm::Stat(STATSTG FAR *pstatstg, DWORD statflag)
  327. {
  328. M_PROLOG(this);
  329. VDATEPTROUT( pstatstg, STATSTG );
  330. pstatstg->pwcsName = NULL;
  331. pstatstg->type = 0;
  332. pstatstg->cbSize.HighPart = 0;
  333. pstatstg->cbSize.LowPart = m_pData->cb;
  334. pstatstg->mtime.dwLowDateTime = 0;
  335. pstatstg->mtime.dwHighDateTime = 0;
  336. pstatstg->ctime.dwLowDateTime = 0;
  337. pstatstg->ctime.dwHighDateTime = 0;
  338. pstatstg->atime.dwLowDateTime = 0;
  339. pstatstg->atime.dwHighDateTime = 0;
  340. pstatstg->grfMode = 0;
  341. pstatstg->grfLocksSupported = 0;
  342. pstatstg->clsid = CLSID_NULL;
  343. pstatstg->grfStateBits = 0;
  344. pstatstg->reserved = 0;
  345. return NOERROR;
  346. }
  347. // returns new instance of pstm pointing to same data at same position.
  348. OLEMETHODIMP CMemStm::Clone(IStream FAR * FAR *ppstm)
  349. {
  350. M_PROLOG(this);
  351. CMemStm FAR* pCMemStm;
  352. VDATEPTROUT (ppstm, LPSTREAM);
  353. *ppstm = pCMemStm = CMemStm::Create(m_hMem);
  354. if (pCMemStm == NULL)
  355. return ResultFromScode(E_OUTOFMEMORY);
  356. pCMemStm->m_pos = m_pos;
  357. return NOERROR;
  358. }
  359. // Create CMemStm. Handle must be a MEMSTM block.
  360. //
  361. OLESTATICIMP_(CMemStm FAR*) CMemStm::Create(HANDLE hMem)
  362. {
  363. CMemStm FAR* pCMemStm;
  364. struct MEMSTM FAR* pData;
  365. pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
  366. if (pData == NULL)
  367. return NULL;
  368. pCMemStm = new CMemStm;
  369. if (pCMemStm == NULL)
  370. return NULL;
  371. // Initialize CMemStm
  372. //
  373. pCMemStm->m_hMem = hMem;
  374. (pCMemStm->m_pData = pData)->cRef++; // AddRefMemStm
  375. pCMemStm->m_refs = 1;
  376. pCMemStm->m_dwSig = STREAM_SIG;
  377. return pCMemStm;
  378. }
  379. // Allocate shared memory and create CMemStm on top of it.
  380. // Return pointer to the stream if done, NULL if error.
  381. // If the handle is returned, it must be free with ReleaseMemStm
  382. // (because of ref counting and the nested global handle).
  383. //
  384. OLEAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem)
  385. {
  386. HANDLE h;
  387. thkDebugOut((DEB_ITRACE,
  388. "%p _IN CreateMemStm16(cb=%lx,phMem=%p\n",0,cb,phMem));
  389. LPSTREAM pstm = NULL;
  390. if (phMem)
  391. {
  392. *phMem = NULL;
  393. }
  394. h = GlobalAlloc (grfMem, cb);
  395. if (NULL==h)
  396. {
  397. goto errRtn;
  398. }
  399. if (CreateStreamOnHGlobal (h, TRUE, &pstm) != NOERROR)
  400. {
  401. pstm = NULL;
  402. goto errRtn;
  403. }
  404. if (phMem)
  405. {
  406. // retrieve handle from just-created CMemStm
  407. *phMem = ((CMemStm FAR*)pstm)->m_hMem;
  408. // use pointer to bump ref count
  409. Assert(((CMemStm FAR*)pstm)->m_pData != NULL);
  410. ((CMemStm FAR*)pstm)->m_pData->cRef++; // AddRefMemStm
  411. }
  412. errRtn:
  413. thkDebugOut((DEB_ITRACE,
  414. "%p OUT CreateMemStm16(cb=%lx,phMem=%p) returns %p\n",0,pstm));
  415. return pstm;
  416. }
  417. // Create CMemStm on top of the specified hMem (which must be a MEMSTM block).
  418. // Return pointer to the stream if done, NULL if error.
  419. //
  420. OLEAPI_(LPSTREAM) CloneMemStm(HANDLE hMem)
  421. {
  422. return CMemStm::Create(hMem); // Create the stream
  423. }
  424. OLEAPI_(void) ReleaseMemStm (LPHANDLE phMem, BOOL fInternalOnly)
  425. {
  426. struct MEMSTM FAR* pData;
  427. pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(*phMem)));
  428. // check for NULL pointer in case handle got freed already
  429. // decrement ref count and free if no refs left
  430. if (pData != NULL && --pData->cRef == 0)
  431. {
  432. if (pData->fDeleteOnRelease)
  433. {
  434. Verify (0==GlobalFree (pData->hGlobal));
  435. }
  436. if (!fInternalOnly)
  437. {
  438. Verify (0==GlobalFree(*phMem));
  439. }
  440. }
  441. *phMem = NULL;
  442. }
  443. OLEAPI CreateStreamOnHGlobal
  444. (HANDLE hGlobal,
  445. BOOL fDeleteOnRelease,
  446. LPSTREAM FAR* ppstm)
  447. {
  448. thkDebugOut((DEB_ITRACE,
  449. "%p _IN CreateStreamOnHGlobal16(hGlobal=%x)\n",0,hGlobal));
  450. HANDLE hMem = NULL; // point to
  451. struct MEMSTM FAR* pData = NULL; // a struct MEMSTM
  452. LPSTREAM pstm = NULL;
  453. DWORD cbSize = -1L;
  454. VDATEPTRIN (ppstm, LPSTREAM);
  455. *ppstm = NULL;
  456. if (NULL==hGlobal)
  457. {
  458. hGlobal = GlobalAlloc(grfMem, 0);
  459. if (hGlobal == NULL)
  460. goto ErrorExit;
  461. cbSize = 0;
  462. }
  463. else
  464. {
  465. cbSize = GlobalSize (hGlobal);
  466. // Is there a way to verify a zero-sized handle?
  467. if (cbSize!=0)
  468. {
  469. // verify validity of passed-in handle
  470. if (NULL==GlobalLock(hGlobal))
  471. {
  472. // bad handle
  473. return ResultFromScode (E_INVALIDARG);
  474. }
  475. GlobalUnlock (hGlobal);
  476. }
  477. }
  478. hMem = GlobalAlloc (grfMem, sizeof (MEMSTM));
  479. if (hMem == NULL)
  480. goto ErrorExit;
  481. pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
  482. if (pData == NULL)
  483. goto FreeMem;
  484. pData->cRef = 0;
  485. pData->cb = cbSize;
  486. pData->fDeleteOnRelease = fDeleteOnRelease;
  487. pData->hGlobal = hGlobal;
  488. pstm = CMemStm::Create(hMem);
  489. if (pstm == NULL)
  490. goto FreeMem;
  491. *ppstm = pstm;
  492. thkDebugOut((DEB_ITRACE,
  493. "%p OUT CreateStreamOnHGlobal16() returns NOERROR\n",0));
  494. return NOERROR;
  495. FreeMem:
  496. if (hMem)
  497. {
  498. Verify(0==GlobalFree(hMem));
  499. }
  500. ErrorExit:
  501. Assert (0);
  502. thkDebugOut((DEB_ITRACE,
  503. "%p OUT CreateStreamOnHGlobal16() returns E_OUTOFMEMORY\n",0));
  504. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  505. }
  506. OLEAPI GetHGlobalFromStream
  507. (LPSTREAM pstm,
  508. HGLOBAL FAR* phglobal)
  509. {
  510. VDATEIFACE (pstm);
  511. VDATEPTRIN (phglobal, HANDLE);
  512. CMemStm FAR* pCMemStm = (CMemStm FAR*) pstm;
  513. if (IsBadReadPtr (&(pCMemStm->m_dwSig), sizeof(ULONG))
  514. || pCMemStm->m_dwSig != STREAM_SIG)
  515. {
  516. // we were passed someone else's implementation of ILockBytes
  517. return ResultFromScode (E_INVALIDARG);
  518. }
  519. MEMSTM FAR* pMem= pCMemStm->m_pData;
  520. if (NULL==pMem)
  521. {
  522. Assert (0);
  523. return ResultFromScode (E_OUTOFMEMORY);
  524. }
  525. Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
  526. Verify (*phglobal = pMem->hGlobal);
  527. return NOERROR;
  528. }
  529. //////////////////////////////////////////////////////////////////////////
  530. //
  531. // Shared memory ILockBytes implementation
  532. //
  533. OLEMETHODIMP CMemBytes::QueryInterface(REFIID iidInterface,
  534. void FAR* FAR* ppvObj)
  535. {
  536. M_PROLOG(this);
  537. HRESULT error;
  538. VDATEPTROUT( ppvObj, LPVOID );
  539. *ppvObj = NULL;
  540. VDATEIID( iidInterface );
  541. // Two interfaces supported: IUnknown, ILockBytes
  542. if (m_pData != NULL &&
  543. (iidInterface == IID_ILockBytes || iidInterface == IID_IUnknown)) {
  544. m_refs++; // A pointer to this object is returned
  545. *ppvObj = this;
  546. error = NOERROR;
  547. } else
  548. //
  549. // BUGBUG - See comment above for CMemStm::Queryinterface and IID_IMarshal
  550. //
  551. #ifdef BOBDAY_DISABLE_MARSHAL_FOR_NOW
  552. #else
  553. if (iidInterface == IID_IMarshal) {
  554. *ppvObj = (LPVOID) CMarshalMemBytes::Create(this);
  555. if (*ppvObj != NULL)
  556. error = NOERROR;
  557. else
  558. error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
  559. }
  560. else
  561. #endif
  562. { // Not accessible or unsupported interface
  563. *ppvObj = NULL;
  564. error = ReportResult(0, E_NOINTERFACE, 0, 0);
  565. }
  566. return error;
  567. }
  568. // Called when CMemBytes is referenced by an additional pointer.
  569. //
  570. OLEMETHODIMP_(ULONG) CMemBytes::AddRef(void)
  571. {
  572. M_PROLOG(this);
  573. return ++m_refs;
  574. }
  575. // Called when a pointer to this CMemBytes is discarded
  576. //
  577. OLEMETHODIMP_(ULONG) CMemBytes::Release(void)
  578. {
  579. M_PROLOG(this);
  580. if (--m_refs != 0) // Still used by others
  581. return m_refs;
  582. ReleaseMemStm(&m_hMem);
  583. delete this; // Free storage
  584. return 0;
  585. }
  586. OLEMETHODIMP CMemBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP* pb,
  587. ULONG cb, ULONG FAR* pcbRead)
  588. {
  589. M_PROLOG(this);
  590. HRESULT error = NOERROR;
  591. ULONG cbRead = cb;
  592. VDATEPTROUT( pb, char );
  593. if (pcbRead) {
  594. VDATEPTROUT( pcbRead, ULONG );
  595. *pcbRead = 0L;
  596. }
  597. if (cbRead + ulOffset.LowPart > m_pData->cb) {
  598. if (ulOffset.LowPart > m_pData->cb)
  599. cbRead = 0;
  600. else
  601. cbRead = m_pData->cb - ulOffset.LowPart;
  602. }
  603. if (cbRead > 0)
  604. {
  605. char HUGEP* pGlobal = GlobalLock (m_pData->hGlobal);
  606. if (NULL==pGlobal)
  607. {
  608. Assert (0);
  609. return ResultFromScode (STG_E_READFAULT);
  610. }
  611. UtMemCpy (pb, pGlobal + ulOffset.LowPart, cbRead);
  612. GlobalUnlock (m_pData->hGlobal);
  613. }
  614. if (pcbRead != NULL)
  615. *pcbRead = cbRead;
  616. return error;
  617. }
  618. OLEMETHODIMP CMemBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP* pb,
  619. ULONG cb, ULONG FAR* pcbWritten)
  620. {
  621. A5_PROLOG(this);
  622. HRESULT error = NOERROR;
  623. ULONG cbWritten = cb;
  624. char HUGEP* pGlobal;
  625. VDATEPTRIN( pb, char );
  626. if (pcbWritten) {
  627. VDATEPTROUT( pcbWritten, ULONG );
  628. *pcbWritten = 0;
  629. }
  630. if (cbWritten + ulOffset.LowPart > m_pData->cb) {
  631. ULARGE_INTEGER ularge_integer;
  632. ULISet32( ularge_integer, ulOffset.LowPart + cbWritten);
  633. error = SetSize( ularge_integer );
  634. if (error != NOERROR)
  635. goto Exit;
  636. }
  637. pGlobal = GlobalLock (m_pData->hGlobal);
  638. if (NULL==pGlobal)
  639. {
  640. Assert (0);
  641. return ResultFromScode (STG_E_WRITEFAULT);
  642. }
  643. UtMemCpy (pGlobal + ulOffset.LowPart, pb, cbWritten);
  644. GlobalUnlock (m_pData->hGlobal);
  645. if (pcbWritten != NULL)
  646. *pcbWritten = cbWritten;
  647. Exit:
  648. RESTORE_A5();
  649. return error;
  650. }
  651. OLEMETHODIMP CMemBytes::Flush(void)
  652. {
  653. M_PROLOG(this);
  654. return NOERROR;
  655. }
  656. OLEMETHODIMP CMemBytes::SetSize(ULARGE_INTEGER cb)
  657. {
  658. M_PROLOG(this);
  659. HANDLE hMemNew;
  660. if (m_pData->cb == cb.LowPart)
  661. return NOERROR;
  662. hMemNew = GlobalReAlloc(m_pData->hGlobal,
  663. max (cb.LowPart, 1),
  664. grfMem);
  665. if (hMemNew == NULL)
  666. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  667. m_pData->hGlobal = hMemNew;
  668. m_pData->cb = cb.LowPart;
  669. return NOERROR;
  670. }
  671. OLEMETHODIMP CMemBytes::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  672. {
  673. // REVIEW - Docfile bug. Must return NOERROR for StgCreateDocfileOnILockbytes
  674. M_PROLOG(this);
  675. return NOERROR;
  676. }
  677. OLEMETHODIMP CMemBytes::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  678. DWORD dwLockType)
  679. {
  680. // REVIEW - Docfiel bug. Must return NOERROR for StgCreateDocfileOnILockbytes
  681. M_PROLOG(this);
  682. return NOERROR;
  683. }
  684. OLEMETHODIMP CMemBytes::Stat(STATSTG FAR *pstatstg, DWORD statflag)
  685. {
  686. M_PROLOG(this);
  687. VDATEPTROUT( pstatstg, STATSTG );
  688. pstatstg->pwcsName = NULL;
  689. pstatstg->type = 0;
  690. pstatstg->cbSize.HighPart = 0;
  691. pstatstg->cbSize.LowPart = m_pData->cb;
  692. pstatstg->mtime.dwLowDateTime = 0;
  693. pstatstg->mtime.dwHighDateTime = 0;
  694. pstatstg->ctime.dwLowDateTime = 0;
  695. pstatstg->ctime.dwHighDateTime = 0;
  696. pstatstg->atime.dwLowDateTime = 0;
  697. pstatstg->atime.dwHighDateTime = 0;
  698. pstatstg->grfMode = 0;
  699. pstatstg->grfLocksSupported = 0;
  700. pstatstg->clsid = CLSID_NULL;
  701. pstatstg->grfStateBits = 0;
  702. pstatstg->reserved = 0;
  703. return NOERROR;
  704. }
  705. // Create CMemBytes. Handle must be a MEMSTM block.
  706. //
  707. OLESTATICIMP_(CMemBytes FAR*) CMemBytes::Create(HANDLE hMem)
  708. {
  709. CMemBytes FAR* pCMemBytes;
  710. struct MEMSTM FAR* pData;
  711. pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
  712. if (pData == NULL)
  713. return NULL;
  714. Assert (pData->hGlobal);
  715. pCMemBytes = new CMemBytes;
  716. if (pCMemBytes == NULL)
  717. return NULL;
  718. // Initialize CMemBytes
  719. //
  720. pCMemBytes->m_dwSig = LOCKBYTE_SIG;
  721. pCMemBytes->m_hMem = hMem;
  722. (pCMemBytes->m_pData = pData)->cRef++; // AddRefMemStm
  723. pCMemBytes->m_refs = 1;
  724. return pCMemBytes;
  725. }
  726. // CMemStm object's IMarshal implementation
  727. //
  728. OLEMETHODIMP CMarshalMemStm::QueryInterface(REFIID iidInterface,
  729. void FAR* FAR* ppvObj)
  730. {
  731. M_PROLOG(this);
  732. HRESULT error;
  733. VDATEPTROUT( ppvObj, LPVOID );
  734. *ppvObj = NULL;
  735. VDATEIID( iidInterface );
  736. // Two interfaces supported: IUnknown, IMarshal
  737. if (iidInterface == IID_IMarshal || iidInterface == IID_IUnknown) {
  738. m_refs++; // A pointer to this object is returned
  739. *ppvObj = this;
  740. error = NOERROR;
  741. }
  742. else { // Not accessible or unsupported interface
  743. *ppvObj = NULL;
  744. error = ResultFromScode (E_NOINTERFACE);
  745. }
  746. return error;
  747. }
  748. // Called when CMarshalMemStm is referenced by an additional pointer.
  749. //
  750. OLEMETHODIMP_(ULONG) CMarshalMemStm::AddRef(void)
  751. {
  752. M_PROLOG(this);
  753. return ++m_refs;
  754. }
  755. // Called when a pointer to this CMarshalMemStm is discarded
  756. //
  757. OLEMETHODIMP_(ULONG) CMarshalMemStm::Release(void)
  758. {
  759. M_PROLOG(this);
  760. if (--m_refs != 0) // Still used by others
  761. return m_refs;
  762. if (m_pMemStm != NULL)
  763. m_pMemStm->Release();
  764. delete this; // Free storage
  765. return 0;
  766. }
  767. // Returns the clsid of the object that created this CMarshalMemStm.
  768. //
  769. OLEMETHODIMP CMarshalMemStm::GetUnmarshalClass(REFIID riid, LPVOID pv,
  770. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
  771. {
  772. M_PROLOG(this);
  773. VDATEPTROUT( pCid, CLSID);
  774. VDATEIID( riid );
  775. *pCid = m_clsid;
  776. return NOERROR;
  777. }
  778. OLEMETHODIMP CMarshalMemStm::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  779. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
  780. {
  781. M_PROLOG(this);
  782. VDATEIID( riid );
  783. VDATEIFACE( pv );
  784. if (pSize) {
  785. VDATEPTROUT( pSize, DWORD );
  786. *pSize = NULL;
  787. }
  788. *pSize = sizeof(m_pMemStm->m_hMem);
  789. return NOERROR;
  790. }
  791. OLEMETHODIMP CMarshalMemStm::MarshalInterface(IStream FAR* pStm,
  792. REFIID riid, void FAR* pv,
  793. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
  794. {
  795. M_PROLOG(this);
  796. VDATEPTRIN( pStm, IStream );
  797. VDATEIID( riid );
  798. VDATEIFACE( pv );
  799. if (m_pMemStm == NULL)
  800. return ReportResult(0, E_UNSPEC, 0, 0);
  801. if ((riid != IID_IStream && riid != IID_IUnknown) || pv != m_pMemStm)
  802. return ReportResult(0, E_INVALIDARG, 0, 0);
  803. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  804. HRESULT error;
  805. if ((error = pStm->Write(&m_pMemStm->m_hMem, sizeof(m_pMemStm->m_hMem),
  806. NULL)) == NOERROR)
  807. m_pMemStm->m_pData->cRef++; // AddRefMemStm
  808. return error;
  809. }
  810. OLEMETHODIMP CMarshalMemStm::UnmarshalInterface(IStream FAR* pStm,
  811. REFIID riid, void FAR* FAR* ppv)
  812. {
  813. M_PROLOG(this);
  814. HRESULT error;
  815. HANDLE hMem;
  816. VDATEPTROUT( ppv, LPVOID );
  817. *ppv = NULL;
  818. VDATEPTRIN( pStm, IStream );
  819. VDATEIID( riid );
  820. if (riid != IID_IStream && riid != IID_IUnknown)
  821. return ReportResult(0, E_INVALIDARG, 0, 0);
  822. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  823. if (error != NOERROR)
  824. return error;
  825. if (m_pMemStm != NULL) {
  826. if (hMem != m_pMemStm->m_hMem)
  827. return ReportResult(0, E_UNSPEC, 0, 0);
  828. }
  829. else {
  830. m_pMemStm = (CMemStm FAR*) CloneMemStm(hMem);
  831. if (m_pMemStm == NULL)
  832. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  833. }
  834. m_pMemStm->AddRef();
  835. *ppv = (LPVOID) m_pMemStm;
  836. return NOERROR;
  837. }
  838. OLEMETHODIMP CMarshalMemStm::ReleaseMarshalData(IStream FAR* pStm)
  839. {
  840. M_PROLOG(this);
  841. // reduce ref count on hglobal (matches that done in MarshalInterface)
  842. HRESULT error;
  843. HANDLE hMem;
  844. VDATEIFACE( pStm );
  845. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  846. if (error == NOERROR)
  847. ReleaseMemStm(&hMem);
  848. return error;
  849. }
  850. OLEMETHODIMP CMarshalMemStm::DisconnectObject(DWORD dwReserved)
  851. {
  852. M_PROLOG(this);
  853. return NOERROR;
  854. }
  855. OLESTATICIMP_(CMarshalMemStm FAR*) CMarshalMemStm::Create(CMemStm FAR* pMemStm)
  856. {
  857. CMarshalMemStm FAR* pMMS;
  858. //VDATEPTRIN rejects NULL
  859. if( pMemStm )
  860. GEN_VDATEPTRIN( pMemStm, CMemStm, (CMarshalMemStm FAR *) NULL );
  861. pMMS = new CMarshalMemStm;
  862. if (pMMS == NULL)
  863. return NULL;
  864. if (pMemStm != NULL) {
  865. pMMS->m_pMemStm = pMemStm;
  866. pMMS->m_pMemStm->AddRef();
  867. }
  868. pMMS->m_clsid = CLSID_StdMemStm;
  869. pMMS->m_refs = 1;
  870. return pMMS;
  871. }
  872. OLEAPI_(IUnknown FAR*) CMemStmUnMarshal(void)
  873. {
  874. return CMarshalMemStm::Create(NULL);
  875. }
  876. // CMemBytes object's IMarshal implementation
  877. //
  878. OLEMETHODIMP CMarshalMemBytes::QueryInterface(REFIID iidInterface,
  879. void FAR* FAR* ppvObj)
  880. {
  881. M_PROLOG(this);
  882. HRESULT error;
  883. VDATEIID( iidInterface );
  884. VDATEPTROUT( ppvObj, LPVOID );
  885. *ppvObj = NULL;
  886. // Two interfaces supported: IUnknown, IMarshal
  887. if (iidInterface == IID_IMarshal || iidInterface == IID_IUnknown) {
  888. m_refs++; // A pointer to this object is returned
  889. *ppvObj = this;
  890. error = NOERROR;
  891. }
  892. else { // Not accessible or unsupported interface
  893. *ppvObj = NULL;
  894. error = ReportResult(0, E_NOINTERFACE, 0, 0);
  895. }
  896. return error;
  897. }
  898. // Called when CMarshalMemBytes is referenced by an additional pointer.
  899. //
  900. OLEMETHODIMP_(ULONG) CMarshalMemBytes::AddRef(void)
  901. {
  902. M_PROLOG(this);
  903. return ++m_refs;
  904. }
  905. // Called when a pointer to this CMarshalMemBytes is discarded
  906. //
  907. OLEMETHODIMP_(ULONG) CMarshalMemBytes::Release(void)
  908. {
  909. M_PROLOG(this);
  910. if (--m_refs != 0) // Still used by others
  911. return m_refs;
  912. if (m_pMemBytes != NULL)
  913. m_pMemBytes->Release();
  914. delete this; // Free storage
  915. return 0;
  916. }
  917. // Returns the clsid of the object that created this CMarshalMemBytes.
  918. //
  919. OLEMETHODIMP CMarshalMemBytes::GetUnmarshalClass(REFIID riid, LPVOID pv,
  920. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
  921. {
  922. M_PROLOG(this);
  923. VDATEIID( riid );
  924. VDATEIFACE( pv );
  925. *pCid = m_clsid;
  926. return NOERROR;
  927. }
  928. OLEMETHODIMP CMarshalMemBytes::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  929. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
  930. {
  931. M_PROLOG(this);
  932. VDATEPTROUT( pSize, DWORD );
  933. VDATEIID( riid );
  934. VDATEIFACE( pv );
  935. *pSize = sizeof(m_pMemBytes->m_hMem);
  936. return NOERROR;
  937. }
  938. OLEMETHODIMP CMarshalMemBytes::MarshalInterface(IStream FAR* pStm,
  939. REFIID riid, void FAR* pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
  940. {
  941. M_PROLOG(this);
  942. VDATEPTRIN(pStm, IStream );
  943. VDATEIID( riid );
  944. if ( pv )
  945. VDATEPTRIN( pv , char );
  946. if (m_pMemBytes == NULL)
  947. return ReportResult(0, E_UNSPEC, 0, 0);
  948. if ((riid != IID_ILockBytes && riid != IID_IUnknown) || pv != m_pMemBytes)
  949. return ReportResult(0, E_INVALIDARG, 0, 0);
  950. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  951. HRESULT error;
  952. if ((error = pStm->Write(&m_pMemBytes->m_hMem, sizeof(m_pMemBytes->m_hMem),
  953. NULL)) == NOERROR)
  954. m_pMemBytes->m_pData->cRef++; // AddRefMemStm
  955. return error;
  956. }
  957. OLEMETHODIMP CMarshalMemBytes::UnmarshalInterface(IStream FAR* pStm,
  958. REFIID riid, void FAR* FAR* ppv)
  959. {
  960. M_PROLOG(this);
  961. HRESULT error;
  962. HANDLE hMem;
  963. VDATEPTROUT( ppv , LPVOID );
  964. *ppv = NULL;
  965. VDATEIFACE( pStm );
  966. VDATEIID( riid );
  967. if (riid != IID_ILockBytes && riid != IID_IUnknown)
  968. return ReportResult(0, E_INVALIDARG, 0, 0);
  969. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  970. if (error != NOERROR)
  971. return error;
  972. if (m_pMemBytes != NULL) {
  973. if (hMem != m_pMemBytes->m_hMem)
  974. return ReportResult(0, E_UNSPEC, 0, 0);
  975. }
  976. else {
  977. m_pMemBytes = CMemBytes::Create(hMem); // Create the lockbytes
  978. if (m_pMemBytes == NULL)
  979. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  980. }
  981. m_pMemBytes->AddRef();
  982. *ppv = (LPVOID) m_pMemBytes;
  983. return NOERROR;
  984. }
  985. OLEMETHODIMP CMarshalMemBytes::ReleaseMarshalData(IStream FAR* pStm)
  986. {
  987. // reduce ref count on hglobal (matches that done in MarshalInterface)
  988. M_PROLOG(this);
  989. HRESULT error;
  990. MEMSTM FAR* pData;
  991. HANDLE hMem;
  992. VDATEIFACE( pStm );
  993. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  994. if (error == NOERROR)
  995. ReleaseMemStm(&hMem);
  996. return error;
  997. }
  998. OLEMETHODIMP CMarshalMemBytes::DisconnectObject(DWORD dwReserved)
  999. {
  1000. M_PROLOG(this);
  1001. return NOERROR;
  1002. }
  1003. OLESTATICIMP_(CMarshalMemBytes FAR*) CMarshalMemBytes::Create(
  1004. CMemBytes FAR* pMemBytes)
  1005. {
  1006. CMarshalMemBytes FAR* pMMB;
  1007. //VDATEPTRIN rejects NULL
  1008. if( pMemBytes )
  1009. GEN_VDATEPTRIN( pMemBytes, CMemBytes, (CMarshalMemBytes FAR *)NULL );
  1010. pMMB = new CMarshalMemBytes;
  1011. if (pMMB == NULL)
  1012. return NULL;
  1013. if (pMemBytes != NULL) {
  1014. pMMB->m_pMemBytes = pMemBytes;
  1015. pMMB->m_pMemBytes->AddRef();
  1016. }
  1017. pMMB->m_clsid = CLSID_StdMemBytes;
  1018. pMMB->m_refs = 1;
  1019. return pMMB;
  1020. }
  1021. OLEAPI_(IUnknown FAR*) CMemBytesUnMarshal(void)
  1022. {
  1023. return CMarshalMemBytes::Create(NULL);
  1024. }