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.

1004 lines
20 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: memstm.cxx
  4. //
  5. // Contents: test class for IStream
  6. //
  7. // Classes: CMemStm
  8. //
  9. // History: 23-Nov-92 Rickhi Created
  10. //
  11. //--------------------------------------------------------------------
  12. #include <pch.cxx>
  13. #pragma hdrstop
  14. #include "memstm.h"
  15. extern "C" {
  16. const GUID CLSID_StdMemStm =
  17. {0x00000301,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
  18. const GUID CLSID_StdMemBytes =
  19. {0x00000302,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
  20. }
  21. // Shared memory IStream implementation
  22. //
  23. STDMETHODIMP CMemStm::QueryInterface(REFIID iidInterface, void **ppvObj)
  24. {
  25. SCODE error;
  26. *ppvObj = NULL;
  27. // Two interfaces supported: IUnknown, IStream
  28. if (m_pData != NULL &&
  29. (IsEqualIID(iidInterface,IID_IStream) ||
  30. IsEqualIID(iidInterface,IID_IUnknown)))
  31. {
  32. m_refs++; // A pointer to this object is returned
  33. *ppvObj = this;
  34. error = S_OK;
  35. }
  36. else
  37. { // Not accessible or unsupported interface
  38. *ppvObj = NULL;
  39. error = E_NOINTERFACE;
  40. }
  41. return error;
  42. }
  43. STDMETHODIMP_(ULONG) CMemStm::AddRef(void)
  44. {
  45. ++ m_refs;
  46. return m_refs;
  47. }
  48. STDMETHODIMP_(ULONG) CMemStm::Release(void)
  49. {
  50. --m_refs;
  51. if (m_refs != 0) // Still used by others
  52. return m_refs;
  53. // Matches the allocation in CMemStm::Create().
  54. //
  55. if (--m_pData->cRef == 0)
  56. {
  57. GlobalUnlock(m_hMem);
  58. GlobalFree(m_hMem);
  59. }
  60. else
  61. GlobalUnlock(m_hMem);
  62. delete this; // Free storage
  63. return 0;
  64. }
  65. STDMETHODIMP CMemStm::Read(void HUGEP* pb, ULONG cb, ULONG * pcbRead)
  66. {
  67. SCODE error = S_OK;
  68. ULONG cbRead = cb;
  69. if (pcbRead)
  70. *pcbRead = 0L;
  71. if (cbRead + m_pos > m_pData->cb)
  72. {
  73. cbRead = m_pData->cb - m_pos;
  74. error = E_FAIL;
  75. }
  76. // BUGBUG - size_t limit
  77. memcpy(pb,m_pData->buf + m_pos,(size_t) cbRead);
  78. m_pos += cbRead;
  79. if (pcbRead != NULL)
  80. *pcbRead = cbRead;
  81. return error;
  82. }
  83. STDMETHODIMP CMemStm::Write(void const HUGEP* pb, ULONG cb, ULONG * pcbWritten)
  84. {
  85. SCODE error = S_OK;
  86. ULONG cbWritten = cb;
  87. ULARGE_INTEGER ularge_integer;
  88. if (pcbWritten)
  89. *pcbWritten = 0L;
  90. if (cbWritten + m_pos > m_pData->cb)
  91. {
  92. ULISet32( ularge_integer, m_pos+cbWritten );
  93. error = SetSize(ularge_integer);
  94. if (error != S_OK)
  95. return error;
  96. }
  97. // BUGBUG - size_t limit
  98. memcpy(m_pData->buf + m_pos,pb,(size_t) cbWritten);
  99. m_pos += cbWritten;
  100. if (pcbWritten != NULL)
  101. *pcbWritten = cbWritten;
  102. return error;
  103. }
  104. STDMETHODIMP CMemStm::Seek(LARGE_INTEGER dlibMoveIN, DWORD dwOrigin, ULARGE_INTEGER * plibNewPosition)
  105. {
  106. SCODE error = S_OK;
  107. LONG dlibMove = dlibMoveIN.LowPart ;
  108. ULONG cbNewPos = dlibMove;
  109. if (plibNewPosition != NULL)
  110. {
  111. ULISet32(*plibNewPosition, m_pos);
  112. }
  113. switch(dwOrigin)
  114. {
  115. case STREAM_SEEK_SET:
  116. if (dlibMove >= 0)
  117. m_pos = dlibMove;
  118. else
  119. error = E_FAIL;
  120. break;
  121. case STREAM_SEEK_CUR:
  122. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
  123. m_pos += dlibMove;
  124. else
  125. error = E_FAIL;
  126. break;
  127. case STREAM_SEEK_END:
  128. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pData->cb))
  129. m_pos = m_pData->cb + dlibMove;
  130. else
  131. error = E_FAIL;
  132. break;
  133. default:
  134. error = E_FAIL;
  135. }
  136. if (plibNewPosition != NULL)
  137. ULISet32(*plibNewPosition, m_pos);
  138. return error;
  139. }
  140. STDMETHODIMP CMemStm::SetSize(ULARGE_INTEGER cb)
  141. {
  142. HANDLE hMemNew;
  143. struct MEMSTM * pDataNew;
  144. if (m_pData->cb == cb.LowPart)
  145. return S_OK;
  146. if (GlobalUnlock(m_hMem) != 0)
  147. return E_FAIL;
  148. hMemNew = GlobalReAlloc(m_hMem,sizeof(MEMSTM) -
  149. sizeof(m_pData->buf) + cb.LowPart,GMEM_DDESHARE | GMEM_MOVEABLE);
  150. if (hMemNew == NULL)
  151. {
  152. GlobalLock(m_hMem);
  153. return E_OUTOFMEMORY;
  154. }
  155. pDataNew = (MEMSTM *) GlobalLock(hMemNew);
  156. if (pDataNew == NULL) // Completely hosed
  157. return E_FAIL;
  158. m_hMem = hMemNew;
  159. pDataNew->cb = cb.LowPart;
  160. m_pData = pDataNew;
  161. return S_OK;
  162. }
  163. STDMETHODIMP CMemStm::CopyTo(IStream *pstm, ULARGE_INTEGER cb,
  164. ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
  165. {
  166. SCODE hRslt;
  167. ULONG cbWritten = 0;
  168. if (!pstm)
  169. return E_FAIL;
  170. // write our data into the stream.
  171. hRslt = pstm->Write(m_pData->buf, cb.LowPart, &cbWritten);
  172. pcbRead->LowPart = cb.LowPart;
  173. pcbRead->HighPart = 0;
  174. pcbWritten->LowPart = cbWritten;
  175. pcbWritten->HighPart = 0;
  176. return hRslt;
  177. }
  178. STDMETHODIMP CMemStm::Commit(DWORD grfCommitFlags)
  179. {
  180. return E_FAIL;
  181. }
  182. STDMETHODIMP CMemStm::Revert(void)
  183. {
  184. return E_FAIL;
  185. }
  186. STDMETHODIMP CMemStm::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  187. {
  188. return E_FAIL;
  189. }
  190. STDMETHODIMP CMemStm::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  191. {
  192. return E_FAIL;
  193. }
  194. STDMETHODIMP CMemStm::Stat(STATSTG *pstatstg, DWORD statflag)
  195. {
  196. pstatstg->pwcsName = NULL;
  197. pstatstg->type = 0;
  198. pstatstg->cbSize.HighPart = 0;
  199. pstatstg->cbSize.LowPart = m_pData->cb;
  200. pstatstg->mtime.dwLowDateTime = 0;
  201. pstatstg->mtime.dwHighDateTime = 0;
  202. pstatstg->ctime.dwLowDateTime = 0;
  203. pstatstg->ctime.dwHighDateTime = 0;
  204. pstatstg->atime.dwLowDateTime = 0;
  205. pstatstg->atime.dwHighDateTime = 0;
  206. pstatstg->grfMode = 0;
  207. pstatstg->grfLocksSupported = 0;
  208. pstatstg->clsid = CLSID_NULL;
  209. pstatstg->grfStateBits = 0;
  210. #ifdef CAIROLE_DOWNLEVEL
  211. pstatstg->reserved = 0;
  212. #else
  213. pstatstg->dwStgFmt = 0;
  214. #endif
  215. return S_OK;
  216. }
  217. STDMETHODIMP CMemStm::Clone(IStream * *ppstm)
  218. {
  219. SCODE hRslt = E_FAIL;
  220. // create a new stream
  221. IStream *pIStm = CreateMemStm(m_pData->cb, NULL);
  222. if (pIStm)
  223. {
  224. // copy data to it
  225. ULARGE_INTEGER cbRead, cbWritten;
  226. ULARGE_INTEGER cb;
  227. cb.LowPart = m_pData->cb;
  228. cb.HighPart = 0;
  229. hRslt = CopyTo(pIStm, cb, &cbRead, &cbWritten);
  230. if (hRslt == S_OK)
  231. {
  232. *ppstm = pIStm;
  233. }
  234. }
  235. return hRslt;
  236. }
  237. // Create CMemStm.
  238. //
  239. CMemStm * CMemStm::Create(HANDLE hMem)
  240. {
  241. CMemStm * pCMemStm;
  242. struct MEMSTM * pData;
  243. pData = (MEMSTM *) GlobalLock(hMem);
  244. if (pData == NULL)
  245. return NULL;
  246. pCMemStm = new CMemStm;
  247. if (pCMemStm == NULL)
  248. {
  249. GlobalUnlock(hMem);
  250. return NULL;
  251. }
  252. // Initialize CMemStm
  253. //
  254. pCMemStm->m_hMem = hMem;
  255. (pCMemStm->m_pData = pData)->cRef++;
  256. pCMemStm->m_refs = 1;
  257. return pCMemStm;
  258. }
  259. // Allocate shared memory and create CMemStm on top of it.
  260. // Return pointer to the stream if done, NULL if error.
  261. //
  262. STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem)
  263. {
  264. HANDLE hMem;
  265. struct MEMSTM * pData;
  266. IStream * pStm;
  267. if ( phMem )
  268. *phMem = NULL;
  269. // Get shared memory
  270. hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
  271. sizeof(MEMSTM) - sizeof(pData->buf) + cb);
  272. if (hMem == NULL)
  273. return NULL;
  274. pData = (MEMSTM *) GlobalLock(hMem);
  275. if (pData == NULL)
  276. goto FreeMem;
  277. pData->cb = cb;
  278. // If caller doesn't ask for the memory handle
  279. // Release() should free the memory.
  280. //
  281. pData->cRef = (phMem == NULL) ? 0 : 1;
  282. GlobalUnlock(hMem);
  283. pStm = CMemStm::Create(hMem); // Create the stream
  284. if (pStm == NULL)
  285. goto FreeMem;
  286. if (phMem)
  287. *phMem = hMem;
  288. return pStm;
  289. FreeMem:
  290. GlobalFree(hMem);
  291. return NULL;
  292. }
  293. // Create CMemStm on top of the specified hMem.
  294. // Return pointer to the stream if done, NULL if error.
  295. //
  296. STDAPI_(LPSTREAM) CloneMemStm(HANDLE hMem)
  297. {
  298. return CMemStm::Create(hMem); // Create the stream
  299. }
  300. //////////////////////////////////////////////////////////////////////////
  301. // Shared memory ILockBytes implementation
  302. //
  303. STDMETHODIMP CMemBytes::QueryInterface(REFIID iidInterface,
  304. void **ppvObj)
  305. {
  306. SCODE error = S_OK;
  307. *ppvObj = NULL;
  308. // Two interfaces supported: IUnknown, ILockBytes
  309. if (m_pData != NULL &&
  310. (IsEqualIID(iidInterface,IID_ILockBytes) ||
  311. IsEqualIID(iidInterface,IID_IUnknown)))
  312. {
  313. m_refs++; // A pointer to this object is returned
  314. *ppvObj = this;
  315. }
  316. else if (IsEqualIID(iidInterface,IID_IMarshal))
  317. {
  318. *ppvObj = (LPVOID) CMarshalMemBytes::Create(this);
  319. if (*ppvObj == NULL)
  320. error = E_OUTOFMEMORY;
  321. }
  322. else
  323. { // Not accessible or unsupported interface
  324. *ppvObj = NULL;
  325. error = E_NOINTERFACE;
  326. }
  327. return error;
  328. }
  329. STDMETHODIMP_(ULONG) CMemBytes::AddRef(void)
  330. {
  331. return ++m_refs;
  332. }
  333. STDMETHODIMP_(ULONG) CMemBytes::Release(void)
  334. {
  335. if (--m_refs != 0) // Still used by others
  336. return m_refs;
  337. // Matches the allocation in CMemBytes::Create().
  338. //
  339. if (--m_pData->cRef == 0)
  340. {
  341. if (m_pData->fDeleteOnRelease)
  342. {
  343. GlobalFree(m_pData->hGlobal);
  344. }
  345. GlobalUnlock(m_hMem);
  346. GlobalFree(m_hMem);
  347. }
  348. else
  349. GlobalUnlock(m_hMem);
  350. delete this; // Free storage
  351. return 0;
  352. }
  353. STDMETHODIMP CMemBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP* pb,
  354. ULONG cb, ULONG * pcbRead)
  355. {
  356. SCODE error = S_OK;
  357. ULONG cbRead = cb;
  358. if (pcbRead)
  359. *pcbRead = 0L;
  360. if (cbRead + ulOffset.LowPart > m_pData->cb)
  361. {
  362. if (ulOffset.LowPart > m_pData->cb)
  363. cbRead = 0;
  364. else
  365. cbRead = m_pData->cb - ulOffset.LowPart;
  366. error = E_FAIL;
  367. }
  368. char HUGEP* pGlobal = (char HUGEP*) GlobalLock (m_pData->hGlobal);
  369. if (NULL==pGlobal)
  370. {
  371. return STG_E_READFAULT;
  372. }
  373. memcpy(pb, pGlobal + ulOffset.LowPart, cbRead);
  374. GlobalUnlock (m_pData->hGlobal);
  375. if (pcbRead != NULL)
  376. *pcbRead = cbRead;
  377. return error;
  378. }
  379. STDMETHODIMP CMemBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP* pb,
  380. ULONG cb, ULONG * pcbWritten)
  381. {
  382. SCODE error = S_OK;
  383. ULONG cbWritten = cb;
  384. char HUGEP* pGlobal;
  385. if (pcbWritten)
  386. *pcbWritten = 0;
  387. if (cbWritten + ulOffset.LowPart > m_pData->cb)
  388. {
  389. ULARGE_INTEGER ularge_integer;
  390. ULISet32( ularge_integer, ulOffset.LowPart + cbWritten);
  391. error = SetSize( ularge_integer );
  392. if (error != S_OK)
  393. return error;
  394. }
  395. pGlobal = (char HUGEP*) GlobalLock (m_pData->hGlobal);
  396. if (NULL==pGlobal)
  397. {
  398. return STG_E_WRITEFAULT;
  399. }
  400. memcpy(pGlobal + ulOffset.LowPart, pb, cbWritten);
  401. GlobalUnlock (m_pData->hGlobal);
  402. if (pcbWritten != NULL)
  403. *pcbWritten = cbWritten;
  404. return error;
  405. }
  406. STDMETHODIMP CMemBytes::Flush(void)
  407. {
  408. return S_OK;
  409. }
  410. STDMETHODIMP CMemBytes::SetSize(ULARGE_INTEGER cb)
  411. {
  412. HANDLE hMemNew;
  413. if (m_pData->cb == cb.LowPart)
  414. return S_OK;
  415. hMemNew = GlobalReAlloc(m_pData->hGlobal,
  416. cb.LowPart,
  417. GMEM_DDESHARE | GMEM_MOVEABLE);
  418. if (hMemNew == NULL)
  419. return E_OUTOFMEMORY;
  420. m_pData->hGlobal = hMemNew;
  421. m_pData->cb = cb.LowPart;
  422. return S_OK;
  423. }
  424. STDMETHODIMP CMemBytes::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  425. {
  426. return S_OK;
  427. }
  428. STDMETHODIMP CMemBytes::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  429. DWORD dwLockType)
  430. {
  431. return S_OK;
  432. }
  433. STDMETHODIMP CMemBytes::Stat(STATSTG *pstatstg, DWORD statflag)
  434. {
  435. pstatstg->pwcsName = NULL;
  436. pstatstg->type = 0;
  437. pstatstg->cbSize.HighPart = 0;
  438. pstatstg->cbSize.LowPart = m_pData->cb;
  439. pstatstg->mtime.dwLowDateTime = 0;
  440. pstatstg->mtime.dwHighDateTime = 0;
  441. pstatstg->ctime.dwLowDateTime = 0;
  442. pstatstg->ctime.dwHighDateTime = 0;
  443. pstatstg->atime.dwLowDateTime = 0;
  444. pstatstg->atime.dwHighDateTime = 0;
  445. pstatstg->grfMode = 0;
  446. pstatstg->grfLocksSupported = 0;
  447. pstatstg->clsid = CLSID_NULL;
  448. pstatstg->grfStateBits = 0;
  449. #ifdef CAIROLE_DOWNLEVEL
  450. pstatstg->reserved = 0;
  451. #else
  452. pstatstg->dwStgFmt = 0;
  453. #endif
  454. return S_OK;
  455. }
  456. // Create CMemBytes.
  457. //
  458. CMemBytes * CMemBytes::Create(HANDLE hMem)
  459. {
  460. CMemBytes * pCMemBytes;
  461. struct MEMBYTES * pData;
  462. pData = (MEMBYTES *) GlobalLock(hMem);
  463. if (pData == NULL)
  464. return NULL;
  465. pCMemBytes = new CMemBytes;
  466. if (pCMemBytes == NULL)
  467. {
  468. GlobalUnlock(hMem);
  469. return NULL;
  470. }
  471. // Initialize CMemBytes
  472. //
  473. pCMemBytes->m_dwSig = LOCKBYTE_SIG;
  474. pCMemBytes->m_hMem = hMem;
  475. (pCMemBytes->m_pData = pData)->cRef++;
  476. pCMemBytes->m_refs = 1;
  477. return pCMemBytes;
  478. }
  479. STDAPI_(LPLOCKBYTES) CreateMemLockBytes(DWORD cb, LPHANDLE phMem)
  480. {
  481. HANDLE h;
  482. LPLOCKBYTES plb = NULL;
  483. if (phMem)
  484. *phMem = NULL;
  485. h = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cb);
  486. if (NULL==h)
  487. return NULL;
  488. if (CreateILockBytesOnHGlobal (h, phMem==NULL, &plb) != S_OK)
  489. return NULL;
  490. if (phMem)
  491. GetHGlobalFromILockBytes (plb, phMem);
  492. return plb;
  493. }
  494. // Create CMemBytes on top of the specified hMem.
  495. // Return pointer to the stream if done, NULL if error.
  496. //
  497. STDAPI_(LPLOCKBYTES) CloneMemLockbytes(HANDLE hMem)
  498. {
  499. return CMemBytes::Create(hMem); // Create the lockbytes
  500. }
  501. // CMemStm object's IMarshal implementation
  502. //
  503. STDMETHODIMP CMarshalMemStm::QueryInterface(REFIID iidInterface,
  504. void * * ppvObj)
  505. {
  506. SCODE error = S_OK;
  507. *ppvObj = NULL;
  508. // Two interfaces supported: IUnknown, IMarshal
  509. if (IsEqualIID(iidInterface,IID_IMarshal) ||
  510. IsEqualIID(iidInterface,IID_IUnknown))
  511. {
  512. m_refs++; // A pointer to this object is returned
  513. *ppvObj = this;
  514. }
  515. else
  516. { // Not accessible or unsupported interface
  517. *ppvObj = NULL;
  518. error = E_NOINTERFACE;
  519. }
  520. return error;
  521. }
  522. STDMETHODIMP_(ULONG) CMarshalMemStm::AddRef(void)
  523. {
  524. return ++m_refs;
  525. }
  526. STDMETHODIMP_(ULONG) CMarshalMemStm::Release(void)
  527. {
  528. if (--m_refs != 0) // Still used by others
  529. return m_refs;
  530. if (m_pMemStm)
  531. m_pMemStm->Release();
  532. delete this; // Free storage
  533. return 0;
  534. }
  535. // Returns the clsid of the object that created this CMarshalMemStm.
  536. //
  537. STDMETHODIMP CMarshalMemStm::GetUnmarshalClass(REFIID riid, LPVOID pv,
  538. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID * pCid)
  539. {
  540. *pCid = m_clsid;
  541. return S_OK;
  542. }
  543. STDMETHODIMP CMarshalMemStm::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  544. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD * pSize)
  545. {
  546. *pSize = sizeof(m_pMemStm->m_hMem);
  547. return S_OK;
  548. }
  549. STDMETHODIMP CMarshalMemStm::MarshalInterface(IStream * pStm,
  550. REFIID riid, void * pv,
  551. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
  552. {
  553. if (m_pMemStm == NULL)
  554. return E_FAIL;
  555. if ((!IsEqualIID(riid,IID_IStream) &&
  556. !IsEqualIID(riid,IID_IUnknown)) || pv != m_pMemStm)
  557. return E_INVALIDARG;
  558. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  559. SCODE error;
  560. error = pStm->Write(&m_pMemStm->m_hMem,sizeof(m_pMemStm->m_hMem), NULL);
  561. if (error == S_OK)
  562. m_pMemStm->m_pData->cRef++;
  563. return error;
  564. }
  565. STDMETHODIMP CMarshalMemStm::UnmarshalInterface(IStream * pStm,
  566. REFIID riid, void * * ppv)
  567. {
  568. SCODE error;
  569. HANDLE hMem;
  570. *ppv = NULL;
  571. if (!IsEqualIID(riid,IID_IStream) && !IsEqualIID(riid,IID_IUnknown))
  572. return E_INVALIDARG;
  573. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  574. if (error != S_OK)
  575. return error;
  576. if (m_pMemStm != NULL)
  577. {
  578. if (hMem != m_pMemStm->m_hMem)
  579. return E_FAIL;
  580. }
  581. else
  582. {
  583. m_pMemStm = (CMemStm *) CloneMemStm(hMem);
  584. if (m_pMemStm == NULL)
  585. return E_OUTOFMEMORY;
  586. }
  587. m_pMemStm->AddRef();
  588. *ppv = (LPVOID) m_pMemStm;
  589. return S_OK;
  590. }
  591. STDMETHODIMP CMarshalMemStm::ReleaseMarshalData(IStream * pStm)
  592. {
  593. // reduce ref count on hglobal (matches that done in MarshalInterface)
  594. SCODE error;
  595. MEMSTM * pData;
  596. HANDLE hMem;
  597. error = pStm->Read(&hMem,sizeof(hMem),NULL);
  598. if (error != S_OK)
  599. return error;
  600. pData = (MEMSTM *) GlobalLock(hMem);
  601. if (pData == NULL)
  602. return E_FAIL;
  603. if (--pData->cRef == 0)
  604. {
  605. GlobalUnlock(hMem);
  606. GlobalFree(hMem);
  607. } else
  608. // still used by one or more CMemStm in one or more processes
  609. GlobalUnlock(hMem);
  610. return S_OK;
  611. }
  612. STDMETHODIMP CMarshalMemStm::DisconnectObject(DWORD dwReserved)
  613. {
  614. return S_OK;
  615. }
  616. CMarshalMemStm * CMarshalMemStm::Create(CMemStm * pMemStm)
  617. {
  618. CMarshalMemStm * pMMS = new CMarshalMemStm;
  619. if (pMMS == NULL)
  620. return NULL;
  621. if (pMemStm != NULL)
  622. {
  623. pMMS->m_pMemStm = pMemStm;
  624. pMMS->m_pMemStm->AddRef();
  625. }
  626. pMMS->m_clsid = CLSID_StdMemStm;
  627. pMMS->m_refs = 1;
  628. return pMMS;
  629. }
  630. STDAPI_(IUnknown *) CMemStmUnMarshal(void)
  631. {
  632. return CMarshalMemStm::Create(NULL);
  633. }
  634. // CMemBytes object's IMarshal implementation
  635. //
  636. STDMETHODIMP CMarshalMemBytes::QueryInterface(REFIID iidInterface,
  637. void * * ppvObj)
  638. {
  639. SCODE error = S_OK;
  640. *ppvObj = NULL;
  641. // Two interfaces supported: IUnknown, IMarshal
  642. if (IsEqualIID(iidInterface,IID_IMarshal) ||
  643. IsEqualIID(iidInterface,IID_IUnknown))
  644. {
  645. m_refs++; // A pointer to this object is returned
  646. *ppvObj = this;
  647. }
  648. else
  649. { // Not accessible or unsupported interface
  650. *ppvObj = NULL;
  651. error = E_NOINTERFACE;
  652. }
  653. return error;
  654. }
  655. STDMETHODIMP_(ULONG) CMarshalMemBytes::AddRef(void)
  656. {
  657. return ++m_refs;
  658. }
  659. STDMETHODIMP_(ULONG) CMarshalMemBytes::Release(void)
  660. {
  661. if (--m_refs != 0) // Still used by others
  662. return m_refs;
  663. if (m_pMemBytes != NULL)
  664. m_pMemBytes->Release();
  665. delete this; // Free storage
  666. return 0;
  667. }
  668. // Returns the clsid of the object that created this CMarshalMemBytes.
  669. //
  670. STDMETHODIMP CMarshalMemBytes::GetUnmarshalClass(REFIID riid, LPVOID pv,
  671. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID * pCid)
  672. {
  673. *pCid = m_clsid;
  674. return S_OK;
  675. }
  676. STDMETHODIMP CMarshalMemBytes::GetMarshalSizeMax(REFIID riid, LPVOID pv,
  677. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD * pSize)
  678. {
  679. *pSize = sizeof(m_pMemBytes->m_hMem);
  680. return S_OK;
  681. }
  682. STDMETHODIMP CMarshalMemBytes::MarshalInterface(IStream * pStm,
  683. REFIID riid, void * pv,
  684. DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
  685. {
  686. if (m_pMemBytes == NULL)
  687. return E_FAIL;
  688. if ((!IsEqualIID(riid,IID_ILockBytes) &&
  689. !IsEqualIID(riid,IID_IUnknown)) || pv != m_pMemBytes)
  690. return E_INVALIDARG;
  691. // increase ref count on hglobal (ReleaseMarshalData has -- to match)
  692. SCODE error;
  693. error = pStm->Write(&m_pMemBytes->m_hMem,sizeof(m_pMemBytes->m_hMem),NULL);
  694. if (error == S_OK)
  695. m_pMemBytes->m_pData->cRef++;
  696. return error;
  697. }
  698. STDMETHODIMP CMarshalMemBytes::UnmarshalInterface(IStream * pStm,
  699. REFIID riid, void * * ppv)
  700. {
  701. HANDLE hMem;
  702. *ppv = NULL;
  703. if (!IsEqualIID(riid,IID_ILockBytes) && !IsEqualIID(riid,IID_IUnknown))
  704. return E_INVALIDARG;
  705. SCODE error = pStm->Read(&hMem,sizeof(hMem),NULL);
  706. if (error != S_OK)
  707. return error;
  708. if (m_pMemBytes != NULL)
  709. {
  710. if (hMem != m_pMemBytes->m_hMem)
  711. return E_FAIL;
  712. }
  713. else
  714. {
  715. m_pMemBytes = (CMemBytes *) CloneMemLockbytes(hMem);
  716. if (m_pMemBytes == NULL)
  717. return E_OUTOFMEMORY;
  718. }
  719. m_pMemBytes->AddRef();
  720. *ppv = (LPVOID) m_pMemBytes;
  721. return S_OK;
  722. }
  723. STDMETHODIMP CMarshalMemBytes::ReleaseMarshalData(IStream * pStm)
  724. {
  725. // reduce ref count on hglobal (matches that done in MarshalInterface)
  726. MEMBYTES *pData;
  727. HANDLE hMem;
  728. SCODE error = pStm->Read(&hMem,sizeof(hMem),NULL);
  729. if (error != S_OK)
  730. return error;
  731. pData = (MEMBYTES *) GlobalLock(hMem);
  732. if (pData == NULL)
  733. return E_FAIL;
  734. if (--pData->cRef == 0)
  735. {
  736. GlobalUnlock(hMem);
  737. GlobalFree(hMem);
  738. }
  739. else
  740. {
  741. // still used by one or more CMemStm in one or more processes
  742. GlobalUnlock(hMem);
  743. }
  744. return S_OK;
  745. }
  746. STDMETHODIMP CMarshalMemBytes::DisconnectObject(DWORD dwReserved)
  747. {
  748. return S_OK;
  749. }
  750. CMarshalMemBytes *CMarshalMemBytes::Create(CMemBytes *pMemBytes)
  751. {
  752. CMarshalMemBytes *pMMB = new CMarshalMemBytes;
  753. if (pMMB == NULL)
  754. return NULL;
  755. if (pMemBytes != NULL)
  756. {
  757. pMMB->m_pMemBytes = pMemBytes;
  758. pMMB->m_pMemBytes->AddRef();
  759. }
  760. pMMB->m_clsid = CLSID_StdMemBytes;
  761. pMMB->m_refs = 1;
  762. return pMMB;
  763. }
  764. STDAPI_(IUnknown *) CMemBytesUnMarshal(void)
  765. {
  766. return CMarshalMemBytes::Create(NULL);
  767. }