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.

2273 lines
76 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: hpalette.cxx
  7. //
  8. // Contents: Support for Windows/OLE data types for oleprx32.dll.
  9. // Used to be transmit_as routines, now user_marshal routines.
  10. //
  11. // This file contains support for STGMEDIUM, FLAG_STGMEDIUM, and
  12. // ASYNC_STGMEDIUM.
  13. //
  14. // Functions:
  15. // STGMEDIUM_UserSize
  16. // STGMEDIUM_UserMarshal
  17. // STGMEDIUM_UserUnmarshal
  18. // STGMEDIUM_UserFree
  19. // STGMEDIUM_UserSize64
  20. // STGMEDIUM_UserMarshal64
  21. // STGMEDIUM_UserUnmarshal64
  22. // STGMEDIUM_UserFree64
  23. // FLAG_STGMEDIUM_UserSize
  24. // FLAG_STGMEDIUM_UserMarshal
  25. // FLAG_STGMEDIUM_UserUnmarshal
  26. // FLAG_STGMEDIUM_UserFree
  27. // FLAG_STGMEDIUM_UserSize64
  28. // FLAG_STGMEDIUM_UserMarshal64
  29. // FLAG_STGMEDIUM_UserUnmarshal64
  30. // FLAG_STGMEDIUM_UserFree64
  31. // ASYNC_STGMEDIUM_UserSize
  32. // ASYNC_STGMEDIUM_UserMarshal
  33. // ASYNC_STGMEDIUM_UserUnmarshal
  34. // ASYNC_STGMEDIUM_UserFree
  35. // ASYNC_STGMEDIUM_UserSize64
  36. // ASYNC_STGMEDIUM_UserMarshal64
  37. // ASYNC_STGMEDIUM_UserUnmarshal64
  38. // ASYNC_STGMEDIUM_UserFree64
  39. //
  40. // History: 13-Dec-00 JohnDoty Migrated from transmit.cxx,
  41. // created NDR64 functions
  42. //
  43. //--------------------------------------------------------------------------
  44. #include "stdrpc.hxx"
  45. #pragma hdrstop
  46. #include <oleauto.h>
  47. #include <objbase.h>
  48. #include "transmit.hxx"
  49. #include <rpcwdt.h>
  50. #include <storext.h>
  51. #include "widewrap.h"
  52. #include <valid.h>
  53. #include <obase.h>
  54. #include <stream.hxx>
  55. #include "carefulreader.hxx"
  56. // PROTOTYPES FOR OTHER USERMARSHAL ROUTINES, TO HELP US!
  57. EXTERN_C unsigned long __stdcall __RPC_USER WdtpInterfacePointer_UserSize (USER_MARSHAL_CB * pContext, unsigned long Flags, unsigned long Offset, IUnknown *pIf, const IID &IId );
  58. EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall WdtpInterfacePointer_UserMarshal (USER_MARSHAL_CB * pContext, unsigned long Flags, unsigned char *pBuffer, IUnknown *pIf, const IID &IId );
  59. EXTERN_C unsigned long __stdcall __RPC_USER WdtpInterfacePointer_UserSize64 (USER_MARSHAL_CB * pContext, unsigned long Flags, unsigned long Offset, IUnknown *pIf, const IID &IId );
  60. EXTERN_C unsigned char __RPC_FAR * __RPC_USER __stdcall WdtpInterfacePointer_UserMarshal64 (USER_MARSHAL_CB * pContext, unsigned long Flags, unsigned char *pBuffer, IUnknown *pIf, const IID &IId );
  61. unsigned char __RPC_FAR * __RPC_USER WdtpInterfacePointer_UserUnmarshalWorker (USER_MARSHAL_CB * pContext, unsigned char * pBuffer, IUnknown ** ppIf, const IID &IId, ULONG_PTR BufferSize, BOOL fNDR64 );
  62. unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshalWorker (unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict, ULONG_PTR BufferSize);
  63. unsigned char __RPC_FAR * __RPC_USER HMETAFILEPICT_UserUnmarshalWorker64 (unsigned long * pFlags, unsigned char * pBuffer, HMETAFILEPICT * pHMetaFilePict, ULONG_PTR BufferSize);
  64. unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshalWorker (unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHMetaFilePict, ULONG_PTR BufferSize);
  65. unsigned char __RPC_FAR * __RPC_USER HENHMETAFILE_UserUnmarshalWorker64 (unsigned long * pFlags, unsigned char * pBuffer, HENHMETAFILE * pHMetaFilePict, ULONG_PTR BufferSize);
  66. unsigned char __RPC_FAR * __RPC_USER HBITMAP_UserUnmarshalWorker (unsigned long * pFlags, unsigned char * pBuffer, HBITMAP * pHMetaFilePict, ULONG_PTR BufferSize);
  67. unsigned char __RPC_FAR * __RPC_USER HBITMAP_UserUnmarshalWorker64 (unsigned long * pFlags, unsigned char * pBuffer, HBITMAP * pHMetaFilePict, ULONG_PTR BufferSize);
  68. unsigned char __RPC_FAR * __RPC_USER HPALETTE_UserUnmarshalWorker (unsigned long * pFlags, unsigned char * pBuffer, HPALETTE * pHMetaFilePict, ULONG_PTR BufferSize);
  69. unsigned char __RPC_FAR * __RPC_USER HPALETTE_UserUnmarshalWorker64 (unsigned long * pFlags, unsigned char * pBuffer, HPALETTE * pHMetaFilePict, ULONG_PTR BufferSize);
  70. unsigned char __RPC_FAR * __RPC_USER WdtpGlobalUnmarshal (unsigned long * pFlags, unsigned char * pBuffer, HGLOBAL * pGlobal, BOOL fCanReallocate, ULONG_PTR BufferSize);
  71. unsigned char __RPC_FAR * __RPC_USER WdtpGlobalUnmarshal64 (unsigned long * pFlags, unsigned char * pBuffer, HGLOBAL * pGlobal, BOOL fCanReallocate, ULONG_PTR BufferSize);
  72. //+-------------------------------------------------------------------------
  73. //
  74. // class: CPunkForRelease
  75. //
  76. // purpose: special IUnknown for remoted STGMEDIUMs
  77. //
  78. // history: 02-Mar-94 Rickhi Created
  79. //
  80. // notes: This class is used to do the cleanup correctly when certain
  81. // types of storages are passed between processes or machines
  82. // in Nt and Chicago.
  83. //
  84. // On NT, GLOBAL, GDI, and BITMAP handles cannot be passed between
  85. // processes, so we actually copy the whole data and create a
  86. // new handle in the receiving process. However, STGMEDIUMs have
  87. // this weird behaviour where if PunkForRelease is non-NULL then
  88. // the sender is responsible for cleanup, not the receiver. Since
  89. // we create a new handle in the receiver, we would leak handles
  90. // if we didnt do some special processing. So, we do the
  91. // following...
  92. //
  93. // During STGMEDIUM_UserUnmarshal, if there is a pUnkForRelease
  94. // replace it with a CPunkForRelease. When Release is called
  95. // on the CPunkForRelease, do the necessary cleanup work,
  96. // then call the real PunkForRelease.
  97. //
  98. //+-------------------------------------------------------------------------
  99. class CPunkForRelease : public IUnknown
  100. {
  101. public:
  102. CPunkForRelease( STGMEDIUM *pStgMed, ulong fTopLayerOnly);
  103. // IUnknown Methods
  104. STDMETHOD(QueryInterface)(REFIID riid, void **ppunk);
  105. STDMETHOD_(ULONG, AddRef)(void);
  106. STDMETHOD_(ULONG, Release)(void);
  107. private:
  108. ~CPunkForRelease(void);
  109. ULONG _cRefs; // reference count
  110. ULONG _fTopLayerMFP:1; // optimisation flag for Chicago
  111. STGMEDIUM _stgmed; // storage medium
  112. IUnknown * _pUnkForRelease; // real pUnkForRelease
  113. };
  114. inline CPunkForRelease::CPunkForRelease(
  115. STGMEDIUM * pStgMed,
  116. ulong fTopLayerMFPict
  117. ) :
  118. _cRefs(1),
  119. _fTopLayerMFP( fTopLayerMFPict),
  120. _stgmed(*pStgMed)
  121. {
  122. // NOTE: we assume the caller has verified pStgMed is not NULL,
  123. // and the pUnkForRelease is non-null, otherwise there is no
  124. // point in constructing this object. The tymed must also be
  125. // one of the special ones.
  126. UserNdrAssert(pStgMed);
  127. UserNdrAssert(pStgMed->tymed == TYMED_HGLOBAL ||
  128. pStgMed->tymed == TYMED_GDI ||
  129. pStgMed->tymed == TYMED_MFPICT ||
  130. pStgMed->tymed == TYMED_ENHMF);
  131. _pUnkForRelease = pStgMed->pUnkForRelease;
  132. }
  133. inline CPunkForRelease::~CPunkForRelease()
  134. {
  135. // since we really have our own copies of these handles' data, just
  136. // pretend like the callee is responsible for the release, and
  137. // recurse into ReleaseStgMedium to do the cleanup.
  138. _stgmed.pUnkForRelease = NULL;
  139. // There is this weird optimized case of Chicago MFPICT when we have two
  140. // layers with a HENHMETAFILE handle inside. Top layer is an HGLOBAL.
  141. if ( _fTopLayerMFP )
  142. GlobalFree( _stgmed.hGlobal );
  143. else
  144. ReleaseStgMedium( &_stgmed );
  145. // release the callers punk
  146. _pUnkForRelease->Release();
  147. }
  148. STDMETHODIMP_(ULONG) CPunkForRelease::AddRef(void)
  149. {
  150. InterlockedIncrement((LONG *)&_cRefs);
  151. return _cRefs;
  152. }
  153. STDMETHODIMP_(ULONG) CPunkForRelease::Release(void)
  154. {
  155. long Ref = _cRefs - 1;
  156. UserNdrAssert( _cRefs );
  157. if (InterlockedDecrement((LONG *)&_cRefs) == 0)
  158. {
  159. // null out the vtable.
  160. long * p = (long *)this;
  161. *p = 0;
  162. delete this;
  163. return 0;
  164. }
  165. else
  166. return Ref;
  167. }
  168. STDMETHODIMP CPunkForRelease::QueryInterface(REFIID riid, void **ppv)
  169. {
  170. if (IsEqualIID(riid, IID_IUnknown))
  171. {
  172. *ppv = (void *)(IUnknown *) this;
  173. AddRef();
  174. return S_OK;
  175. }
  176. else
  177. {
  178. *ppv = NULL;
  179. return E_NOINTERFACE;
  180. }
  181. }
  182. //+-------------------------------------------------------------------------
  183. //
  184. // Function: SetContextFlagsForAsyncCall
  185. //
  186. // Synopsis: Forces correct flags for an async stgmed call.
  187. //
  188. // history: May-97 Ryszardk Created.
  189. //
  190. // We used to force MSHCTX_DIFFERENTMACHINE context on every
  191. // async stgmedium call because of problems with handles - for a truly
  192. // async call passing a handle, the client may free the handle before
  193. // the server can use it.
  194. // That is still needed. However, we cannot force the different machine
  195. // flags on IStream and IStorage as that prevents custom marshaler from
  196. // running.
  197. //
  198. //--------------------------------------------------------------------------
  199. void inline
  200. SetContextFlagsForAsyncCall(
  201. unsigned long * pFlags,
  202. STGMEDIUM * pStgmed )
  203. {
  204. if ( *pFlags & USER_CALL_IS_ASYNC )
  205. {
  206. // Additional considerations for async calls.
  207. switch( pStgmed->tymed )
  208. {
  209. case TYMED_NULL:
  210. case TYMED_MFPICT:
  211. case TYMED_ENHMF:
  212. case TYMED_GDI:
  213. case TYMED_HGLOBAL:
  214. case TYMED_FILE:
  215. default:
  216. if (!REMOTE_CALL(*pFlags))
  217. {
  218. *pFlags &= ~0xff;
  219. *pFlags |= MSHCTX_DIFFERENTMACHINE;
  220. }
  221. break;
  222. case TYMED_ISTREAM:
  223. case TYMED_ISTORAGE:
  224. // Dont force remote.
  225. break;
  226. }
  227. }
  228. }
  229. //+-------------------------------------------------------------------------
  230. //
  231. // Function: STGMEDIUM_UserSize
  232. //
  233. // Synopsis: Sizes a stgmedium pbject for RPC marshalling.
  234. //
  235. // history: May-95 Ryszardk Created.
  236. //
  237. //--------------------------------------------------------------------------
  238. unsigned long __RPC_USER
  239. STGMEDIUM_UserSize(
  240. unsigned long * pFlags,
  241. unsigned long Offset,
  242. STGMEDIUM * pStgmed )
  243. {
  244. if ( ! pStgmed )
  245. return Offset;
  246. LENGTH_ALIGN( Offset, 3 );
  247. // Both handle and pUnk are represented by a long.
  248. if ( pStgmed->tymed == TYMED_NULL )
  249. Offset += sizeof(long) + sizeof(long); // switch, (empty arm), pUnk
  250. else
  251. Offset += sizeof(long) + 2 * sizeof(long); // switch, handle, pUnk
  252. // Pointee of the union arm.
  253. // Only if the handle/pointer field is non-null.
  254. if ( pStgmed->hGlobal )
  255. {
  256. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  257. switch( pStgmed->tymed )
  258. {
  259. case TYMED_NULL:
  260. break;
  261. case TYMED_MFPICT:
  262. Offset = HMETAFILEPICT_UserSize( pFlags,
  263. Offset,
  264. &pStgmed->hMetaFilePict );
  265. break;
  266. case TYMED_ENHMF:
  267. Offset = HENHMETAFILE_UserSize( pFlags,
  268. Offset,
  269. &pStgmed->hEnhMetaFile );
  270. break;
  271. case TYMED_GDI:
  272. // A GDI object is not necesarrily a BITMAP. Therefore, we handle
  273. // those types we know about based on the object type, and reject
  274. // those which we do not support.
  275. // switch for object type.
  276. Offset += sizeof(long);
  277. switch( GetObjectType( (HGDIOBJ)pStgmed->hBitmap ) )
  278. {
  279. case OBJ_BITMAP:
  280. Offset = HBITMAP_UserSize( pFlags,
  281. Offset,
  282. &pStgmed->hBitmap );
  283. break;
  284. case OBJ_PAL:
  285. Offset = HPALETTE_UserSize( pFlags,
  286. Offset,
  287. (HPALETTE *) & pStgmed->hBitmap );
  288. break;
  289. default:
  290. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  291. break;
  292. }
  293. break;
  294. case TYMED_HGLOBAL:
  295. Offset = HGLOBAL_UserSize( pFlags,
  296. Offset,
  297. &pStgmed->hGlobal );
  298. break;
  299. case TYMED_FILE:
  300. {
  301. ulong ulDataSize = lstrlenW(pStgmed->lpszFileName) + 1;
  302. Offset += 3 * sizeof(long); // [string]
  303. Offset += ulDataSize * sizeof(wchar_t);
  304. }
  305. break;
  306. case TYMED_ISTREAM:
  307. case TYMED_ISTORAGE:
  308. Offset = WdtpInterfacePointer_UserSize(
  309. (USER_MARSHAL_CB *)pFlags,
  310. *pFlags,
  311. Offset,
  312. pStgmed->pstg,
  313. ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream
  314. : IID_IStorage));
  315. break;
  316. default:
  317. break;
  318. }
  319. }
  320. // pUnkForRelease, if not null.
  321. if ( pStgmed->pUnkForRelease )
  322. Offset = WdtpInterfacePointer_UserSize( (USER_MARSHAL_CB *)pFlags,
  323. *pFlags,
  324. Offset,
  325. pStgmed->pUnkForRelease,
  326. IID_IUnknown );
  327. return( Offset );
  328. }
  329. //+-------------------------------------------------------------------------
  330. //
  331. // Function: STGMEDIUM_UserMarshal
  332. //
  333. // Synopsis: Marshals a stgmedium pbject for RPC.
  334. //
  335. // history: May-95 Ryszardk Created.
  336. //
  337. //--------------------------------------------------------------------------
  338. unsigned char __RPC_FAR * __RPC_USER
  339. STGMEDIUM_UserMarshal(
  340. unsigned long * pFlags,
  341. unsigned char * pBufferStart,
  342. STGMEDIUM * pStgmed )
  343. {
  344. unsigned char * pBuffer;
  345. unsigned char * pUnionArmMark;
  346. if ( ! pStgmed )
  347. return pBufferStart;
  348. UserNdrDebugOut((
  349. UNDR_FORCE,
  350. "--STGMEDIUM_UserMarshal: %s\n",
  351. WdtpGetStgmedName(pStgmed)));
  352. pBuffer = pBufferStart;
  353. ALIGN( pBuffer, 3 );
  354. // userSTGMEDIUM: switch, union arm, pUnk ptr.
  355. *( PULONG_LV_CAST pBuffer)++ = pStgmed->tymed;
  356. pUnionArmMark = pBuffer;
  357. if ( pStgmed->tymed != TYMED_NULL )
  358. {
  359. // hGlobal stands for any of these handles.
  360. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( pStgmed->hGlobal );
  361. }
  362. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( pStgmed->pUnkForRelease );
  363. // Now the pointee of the union arm.
  364. // We need to marshal only if the handle/pointer field is non null.
  365. // Otherwise it is already in the buffer.
  366. if ( pStgmed->hGlobal )
  367. {
  368. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  369. switch( pStgmed->tymed )
  370. {
  371. case TYMED_NULL:
  372. break;
  373. case TYMED_MFPICT:
  374. pBuffer = HMETAFILEPICT_UserMarshal( pFlags,
  375. pBuffer,
  376. &pStgmed->hMetaFilePict );
  377. break;
  378. case TYMED_ENHMF:
  379. pBuffer = HENHMETAFILE_UserMarshal( pFlags,
  380. pBuffer,
  381. &pStgmed->hEnhMetaFile );
  382. break;
  383. case TYMED_GDI:
  384. {
  385. // A GDI object is not necesarrily a BITMAP. Therefore, we handle
  386. // those types we know about based on the object type, and reject
  387. // those which we do not support.
  388. ulong GdiObjectType = GetObjectType( (HGDIOBJ)pStgmed->hBitmap );
  389. // GDI_OBJECT
  390. *( PULONG_LV_CAST pBuffer)++ = GdiObjectType;
  391. switch( GdiObjectType )
  392. {
  393. case OBJ_BITMAP:
  394. pBuffer = HBITMAP_UserMarshal( pFlags,
  395. pBuffer,
  396. &pStgmed->hBitmap );
  397. break;
  398. case OBJ_PAL:
  399. pBuffer = HPALETTE_UserMarshal( pFlags,
  400. pBuffer,
  401. (HPALETTE *) & pStgmed->hBitmap );
  402. break;
  403. default:
  404. RpcRaiseException(DV_E_TYMED);
  405. }
  406. }
  407. break;
  408. case TYMED_HGLOBAL:
  409. pBuffer = HGLOBAL_UserMarshal( pFlags,
  410. pBuffer,
  411. & pStgmed->hGlobal );
  412. break;
  413. case TYMED_FILE:
  414. {
  415. // We marshal it as a [string].
  416. ulong Count = (pStgmed->lpszFileName)
  417. ? lstrlenW(pStgmed->lpszFileName) + 1
  418. : 0;
  419. *( PULONG_LV_CAST pBuffer)++ = Count;
  420. *( PULONG_LV_CAST pBuffer)++ = 0;
  421. *( PULONG_LV_CAST pBuffer)++ = Count;
  422. memcpy( pBuffer, pStgmed->lpszFileName, Count * sizeof(wchar_t) );
  423. pBuffer += Count * sizeof(wchar_t);
  424. }
  425. break;
  426. case TYMED_ISTREAM:
  427. case TYMED_ISTORAGE:
  428. pBuffer = WdtpInterfacePointer_UserMarshal(
  429. ((USER_MARSHAL_CB *)pFlags),
  430. *pFlags,
  431. pBuffer,
  432. pStgmed->pstg,
  433. ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream
  434. : IID_IStorage));
  435. break;
  436. default:
  437. break;
  438. }
  439. }
  440. // Marker for this pointer is already in the buffer.
  441. if ( pStgmed->pUnkForRelease )
  442. pBuffer = WdtpInterfacePointer_UserMarshal( ((USER_MARSHAL_CB *)pFlags
  443. ),
  444. *pFlags,
  445. pBuffer,
  446. pStgmed->pUnkForRelease,
  447. IID_IUnknown );
  448. return( pBuffer );
  449. }
  450. //+-------------------------------------------------------------------------
  451. //
  452. // Function: STGMEDIUM_UserUnmarshalWorker
  453. //
  454. // Synopsis: Unmarshals a stgmedium object for RPC.
  455. //
  456. // history: Aug-99 JohnStra Created.
  457. //
  458. //--------------------------------------------------------------------------
  459. unsigned char __RPC_FAR * __RPC_USER
  460. STGMEDIUM_UserUnmarshalWorker(
  461. unsigned long * pFlags,
  462. unsigned char * pBuffer,
  463. STGMEDIUM * pStgmed,
  464. ULONG_PTR BufferSize )
  465. {
  466. unsigned long fUnkForRelease;
  467. LONG_PTR Handle = 0;
  468. // Align the buffer and save the fixup size.
  469. UCHAR* pBufferStart = pBuffer;
  470. ALIGN( pBuffer, 3 );
  471. ULONG_PTR cbFixup = (ULONG_PTR) (pBuffer - pBufferStart);
  472. // Check for EOB.
  473. CHECK_BUFFER_SIZE( BufferSize, cbFixup + sizeof( ULONG ) );
  474. // switch, union arm, pUnk.
  475. pStgmed->tymed = *( PULONG_LV_CAST pBuffer)++;
  476. UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal: %s\n",
  477. WdtpGetStgmedName(pStgmed) ));
  478. ULONG_PTR cbData = cbFixup + (2 * sizeof( ULONG ));
  479. if ( pStgmed->tymed != TYMED_NULL )
  480. {
  481. cbData += sizeof( ULONG );
  482. CHECK_BUFFER_SIZE( BufferSize, cbData );
  483. // This value is just a marker for the handle - a long.
  484. Handle = *( PLONG_LV_CAST pBuffer)++;
  485. }
  486. else
  487. {
  488. CHECK_BUFFER_SIZE( BufferSize, cbData );
  489. }
  490. // pUnkForRelease pointer marker.
  491. fUnkForRelease = *( PULONG_LV_CAST pBuffer)++;
  492. // First pointee
  493. // Union arm pointee.
  494. // We need to unmarshal only if the handle/pointer field was not NULL.
  495. if ( Handle )
  496. {
  497. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  498. LONG* pBuf = (LONG*)pBuffer;
  499. switch( pStgmed->tymed )
  500. {
  501. case TYMED_NULL:
  502. break;
  503. case TYMED_MFPICT:
  504. #if defined(_WIN64)
  505. if ( IS_DATA_MARKER( pBuf[0] ) )
  506. {
  507. CHECK_BUFFER_SIZE( BufferSize, cbData + (2 * sizeof( ULONG )) );
  508. if ( Handle != pBuf[1] )
  509. {
  510. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  511. }
  512. }
  513. else
  514. {
  515. //Inproc should always have marked this as handle64....
  516. //Out-of-proc should always have marked this with a data marker....
  517. if (!IS_HANDLE64_MARKER(pBuf[0]))
  518. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  519. // Align to 64b.
  520. PBYTE pbBuf = (PBYTE)( pBuf + 1 );
  521. PBYTE pbBufStart = pbBuf;
  522. ALIGN( pbBuf, 7 );
  523. // Make sure we don't step off the end of the buffer.
  524. CHECK_BUFFER_SIZE( BufferSize, cbData +
  525. (ULONG_PTR)(pbBuf - pbBufStart) +
  526. (sizeof(__int64)) );
  527. // Verify that the handle put on the wire matches the
  528. // first instance of the handle on the wire.
  529. if ( Handle != (LONG_PTR) (*(LONG *)pbBuf ) )
  530. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  531. }
  532. #else
  533. CHECK_BUFFER_SIZE( BufferSize, cbData + (2 * sizeof(ULONG)) );
  534. if ( Handle != pBuf[1] )
  535. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  536. #endif
  537. pBuffer = HMETAFILEPICT_UserUnmarshalWorker(
  538. pFlags,
  539. pBuffer,
  540. &pStgmed->hMetaFilePict,
  541. BufferSize - cbData );
  542. break;
  543. case TYMED_ENHMF:
  544. // Must be room in buffer to do lookahead check.
  545. CHECK_BUFFER_SIZE( BufferSize, cbData + (2 * sizeof( ULONG )) );
  546. // validate the handle.
  547. if ( Handle != pBuf[1] )
  548. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  549. pBuffer = HENHMETAFILE_UserUnmarshalWorker( pFlags,
  550. pBuffer,
  551. &pStgmed->hEnhMetaFile,
  552. BufferSize - cbData );
  553. break;
  554. case TYMED_GDI:
  555. {
  556. // A GDI object is not necesarrily a BITMAP. Therefore, we
  557. // handle those types we know about based on the object type,
  558. // and reject those which we do not support.
  559. // Make sure we don't walk off the end of the buffer.
  560. CHECK_BUFFER_SIZE( BufferSize, cbData + (3 * sizeof( ULONG )) );
  561. cbData += sizeof( ULONG );
  562. DWORD GdiObjectType = *( PULONG_LV_CAST pBuffer)++;
  563. switch( GdiObjectType )
  564. {
  565. case OBJ_BITMAP:
  566. // Lookahead validaton of the handle. We look at
  567. // the 3rd DWORD: GDI type, DISC, Handle.
  568. if ( Handle != pBuf[2] )
  569. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  570. pBuffer = HBITMAP_UserUnmarshalWorker( pFlags,
  571. pBuffer,
  572. &pStgmed->hBitmap,
  573. BufferSize - cbData );
  574. break;
  575. case OBJ_PAL:
  576. // Lookahead validaton of the handle.
  577. if ( Handle != pBuf[2] )
  578. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  579. pBuffer = HPALETTE_UserUnmarshalWorker( pFlags,
  580. pBuffer,
  581. (HPALETTE *) & pStgmed->hBitmap,
  582. BufferSize - cbData );
  583. break;
  584. default:
  585. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  586. }
  587. }
  588. break;
  589. case TYMED_HGLOBAL:
  590. {
  591. // reallocation is forbidden for [in-out] hglobal in STGMEDIUM.
  592. #if defined(_WIN64)
  593. if ( IS_DATA_MARKER( pBuf[0] ) )
  594. {
  595. CHECK_BUFFER_SIZE( BufferSize, cbData + (2 * sizeof( ULONG )) );
  596. if ( Handle != pBuf[1] )
  597. {
  598. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  599. }
  600. }
  601. else
  602. {
  603. // Align to 64b.
  604. PBYTE pbBuf = (PBYTE)( pBuf + 1 );
  605. PBYTE pbBufStart = pbBuf;
  606. ALIGN( pbBuf, 7 );
  607. // Make sure we don't step off the end of the buffer.
  608. CHECK_BUFFER_SIZE( BufferSize, cbData +
  609. (ULONG_PTR)(pbBuf - pbBufStart) +
  610. (sizeof(__int64)) );
  611. // Verify that the handle put on the wire matches the
  612. // first instance of the handle on the wire.
  613. if ( Handle != (LONG_PTR) (*(LONG *)pbBuf ) )
  614. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  615. }
  616. #else
  617. CHECK_BUFFER_SIZE( BufferSize, cbData + (2 * sizeof(ULONG)) );
  618. if ( Handle != pBuf[1] )
  619. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  620. #endif
  621. pBuffer = WdtpGlobalUnmarshal( pFlags,
  622. pBuffer,
  623. & pStgmed->hGlobal,
  624. FALSE,
  625. BufferSize - cbData);
  626. break;
  627. }
  628. case TYMED_FILE:
  629. {
  630. // Must be room in buffer for header.
  631. CHECK_BUFFER_SIZE( BufferSize, cbData + (3 * sizeof(ULONG)) );
  632. // We marshal it as a [string].
  633. ulong Count = *( PULONG_LV_CAST pBuffer)++;
  634. if ( *( PULONG_LV_CAST pBuffer)++ != 0 ||
  635. *( PULONG_LV_CAST pBuffer)++ != Count )
  636. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  637. if ( ! pStgmed->lpszFileName )
  638. pStgmed->lpszFileName = (LPOLESTR)
  639. WdtpAllocate( pFlags,
  640. Count * sizeof(wchar_t) );
  641. // Must be room in the buffer for the string.
  642. CHECK_BUFFER_SIZE(
  643. BufferSize,
  644. cbData + (3 * sizeof( ULONG )) + (Count * sizeof( wchar_t )) );
  645. memcpy(pStgmed->lpszFileName, pBuffer, Count * sizeof(wchar_t));
  646. pBuffer += Count * sizeof(wchar_t);
  647. }
  648. break;
  649. case TYMED_ISTREAM:
  650. case TYMED_ISTORAGE:
  651. // Non null pointer, retrieve the interface pointer
  652. pBuffer = WdtpInterfacePointer_UserUnmarshalWorker(
  653. (USER_MARSHAL_CB *)pFlags,
  654. pBuffer,
  655. (IUnknown **) &pStgmed->pstm,
  656. ((pStgmed->tymed == TYMED_ISTREAM)
  657. ? IID_IStream
  658. : IID_IStorage),
  659. BufferSize - cbData,
  660. FALSE );
  661. break;
  662. default:
  663. break;
  664. }
  665. }
  666. else
  667. {
  668. // New handle/pointer field is null, so release the previous one
  669. // if it wasn't null.
  670. if ( pStgmed->hGlobal )
  671. {
  672. // This should never happen for GetDataHere.
  673. // Note, that we release the handle field, not the stgmedium itself.
  674. // Accordingly, we don't follow punkForRelease.
  675. UserNdrDebugOut((
  676. UNDR_FORCE,
  677. "--STGMEDIUM_UserUnmarshal: %s: NULL in, freeing old one\n",
  678. WdtpGetStgmedName(pStgmed)));
  679. STGMEDIUM TmpStg = *pStgmed;
  680. TmpStg.pUnkForRelease = NULL;
  681. if ( pStgmed->tymed == TYMED_HGLOBAL )
  682. {
  683. // Cannot reallocate.
  684. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  685. }
  686. else
  687. {
  688. ReleaseStgMedium( &TmpStg );
  689. }
  690. }
  691. pStgmed->hGlobal = 0;
  692. }
  693. // Fixup the buffer size so if fUnkForRelease is set, we
  694. // pass the correct BufferSize to the unmarshal routine.
  695. BufferSize -= (ULONG_PTR)(pBuffer - pBufferStart);
  696. if ( fUnkForRelease )
  697. {
  698. // There is an interface pointer on the wire.
  699. pBuffer = WdtpInterfacePointer_UserUnmarshalWorker(
  700. (USER_MARSHAL_CB *)pFlags,
  701. pBuffer,
  702. &pStgmed->pUnkForRelease,
  703. IID_IUnknown,
  704. BufferSize,
  705. FALSE );
  706. }
  707. if ( pStgmed->pUnkForRelease )
  708. {
  709. // Replace the app's punkForRelease with our custom release
  710. // handler for special situations.
  711. // The special situation is when a handle is remoted with data
  712. // and so we have to clean up a side effect of having a data copy
  713. // around. UserFree does it properly but we need that for the callee.
  714. // When the callee releases a stgmed, it would invoke
  715. // ReleaseStgMedium and this API doesn't do anything for handles
  716. // when the punkForRelease is not NULL.
  717. ULONG fHandleWithData = 0;
  718. ULONG fTopLevelOnly = 0;
  719. switch ( pStgmed->tymed )
  720. {
  721. case TYMED_HGLOBAL:
  722. fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
  723. break;
  724. case TYMED_ENHMF:
  725. case TYMED_GDI:
  726. fHandleWithData = GDI_DATA_PASSING( *pFlags );
  727. break;
  728. case TYMED_MFPICT:
  729. fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
  730. fTopLevelOnly = fHandleWithData &&
  731. ! GDI_DATA_PASSING( *pFlags );
  732. break;
  733. default:
  734. break;
  735. }
  736. if ( fHandleWithData )
  737. {
  738. IUnknown *
  739. punkTmp = (IUnknown *) new CPunkForRelease( pStgmed,
  740. fTopLevelOnly );
  741. if (!punkTmp)
  742. {
  743. RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
  744. }
  745. pStgmed->pUnkForRelease = punkTmp;
  746. }
  747. }
  748. return( pBuffer );
  749. }
  750. //+-------------------------------------------------------------------------
  751. //
  752. // Function: STGMEDIUM_UserUnmarshal
  753. //
  754. // Synopsis: Unmarshals a stgmedium object for RPC.
  755. //
  756. // history: May-95 Ryszardk Created.
  757. // Aug-99 JohnStra Factored bulk of code out into a
  758. // worker routine in order to add
  759. // consistency checks.
  760. //
  761. //--------------------------------------------------------------------------
  762. unsigned char __RPC_FAR * __RPC_USER
  763. STGMEDIUM_UserUnmarshal(
  764. unsigned long * pFlags,
  765. unsigned char * pBuffer,
  766. STGMEDIUM * pStgmed )
  767. {
  768. // Init buffer size and ptr to buffer.
  769. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  770. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  771. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  772. pBuffer = STGMEDIUM_UserUnmarshalWorker( pFlags,
  773. pBufferStart,
  774. pStgmed,
  775. BufferSize );
  776. return( pBuffer );
  777. }
  778. //+-------------------------------------------------------------------------
  779. //
  780. // Function: STGMEDIUM_UserFree
  781. //
  782. // Synopsis: Frees a stgmedium object for RPC.
  783. //
  784. // history: May-95 Ryszardk Created.
  785. //
  786. // Note: This routine is called from the freeing walk at server
  787. // or from the SetData *proxy*, when ownership has been passed.
  788. //
  789. //--------------------------------------------------------------------------
  790. EXTERN_C
  791. void NukeHandleAndReleasePunk(
  792. STGMEDIUM * pStgmed )
  793. {
  794. pStgmed->hGlobal = NULL;
  795. pStgmed->tymed = TYMED_NULL;
  796. if (pStgmed->pUnkForRelease)
  797. {
  798. pStgmed->pUnkForRelease->Release();
  799. pStgmed->pUnkForRelease = 0;
  800. }
  801. }
  802. void __RPC_USER
  803. STGMEDIUM_UserFree(
  804. unsigned long * pFlags,
  805. STGMEDIUM * pStgmed )
  806. {
  807. UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserFree: %s\n", WdtpGetStgmedName(pStgmed)));
  808. if( pStgmed )
  809. {
  810. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  811. switch ( pStgmed->tymed )
  812. {
  813. case TYMED_FILE:
  814. WdtpFree( pFlags, pStgmed->lpszFileName);
  815. NukeHandleAndReleasePunk( pStgmed );
  816. break;
  817. case TYMED_NULL:
  818. case TYMED_ISTREAM:
  819. case TYMED_ISTORAGE:
  820. ReleaseStgMedium( pStgmed );
  821. break;
  822. case TYMED_GDI:
  823. case TYMED_ENHMF:
  824. if ( GDI_HANDLE_PASSING(*pFlags) )
  825. {
  826. NukeHandleAndReleasePunk( pStgmed );
  827. }
  828. else
  829. {
  830. // Handle w/data: there is a side effect to clean up.
  831. // For punk !=0, this will go to our CPunk object.
  832. ReleaseStgMedium( pStgmed );
  833. }
  834. break;
  835. case TYMED_HGLOBAL:
  836. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  837. {
  838. NukeHandleAndReleasePunk( pStgmed );
  839. }
  840. else
  841. {
  842. // Handle w/data: there is a side effect to clean up.
  843. // For punk ==0, this will just release the data.
  844. // For punk !=0, this will go to our CPunk object,
  845. // release the data, and then call the original punk.
  846. ReleaseStgMedium( pStgmed );
  847. }
  848. break;
  849. case TYMED_MFPICT:
  850. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  851. {
  852. NukeHandleAndReleasePunk( pStgmed );
  853. }
  854. else if ( GDI_HANDLE_PASSING(*pFlags) )
  855. {
  856. if ( pStgmed->pUnkForRelease )
  857. {
  858. pStgmed->pUnkForRelease->Release();
  859. }
  860. else
  861. {
  862. if ( pStgmed->hGlobal )
  863. GlobalFree( pStgmed->hGlobal );
  864. pStgmed->hGlobal = NULL;
  865. pStgmed->tymed = TYMED_NULL;
  866. }
  867. }
  868. else
  869. {
  870. // Handle w/data: there is a side effect to clean up.
  871. // For punk !=0, this will go to our CPunk object.
  872. ReleaseStgMedium( pStgmed );
  873. }
  874. break;
  875. default:
  876. RAISE_RPC_EXCEPTION( E_INVALIDARG );
  877. break;
  878. }
  879. }
  880. }
  881. //+-------------------------------------------------------------------------
  882. //
  883. // Function: FLAG_STGMEDIUM_UserSize
  884. //
  885. // Synopsis: Sizes a wrapper for stgmedium.
  886. //
  887. // history: May-95 Ryszardk Created.
  888. //
  889. //--------------------------------------------------------------------------
  890. unsigned long __RPC_USER
  891. FLAG_STGMEDIUM_UserSize(
  892. unsigned long * pFlags,
  893. unsigned long Offset,
  894. FLAG_STGMEDIUM* pFlagStgmed )
  895. {
  896. if ( ! pFlagStgmed )
  897. return Offset;
  898. LENGTH_ALIGN( Offset, 3 );
  899. Offset += 2 * sizeof(long);
  900. Offset = STGMEDIUM_UserSize( pFlags, Offset, & pFlagStgmed->Stgmed );
  901. return( Offset );
  902. }
  903. //+-------------------------------------------------------------------------
  904. //
  905. // Function: FLAG_STGMEDIUM_UserMarshal
  906. //
  907. // Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
  908. //
  909. // history: May-95 Ryszardk Created.
  910. //
  911. //--------------------------------------------------------------------------
  912. unsigned char __RPC_FAR * __RPC_USER
  913. FLAG_STGMEDIUM_UserMarshal(
  914. unsigned long * pFlags,
  915. unsigned char * pBuffer,
  916. FLAG_STGMEDIUM* pFlagStgmed )
  917. {
  918. if ( ! pFlagStgmed )
  919. return pBuffer;
  920. ALIGN( pBuffer, 3 );
  921. // Flags: we need them when freeing in the client call_as routine
  922. pFlagStgmed->ContextFlags = *pFlags;
  923. *( PULONG_LV_CAST pBuffer)++ = *pFlags;
  924. *( PULONG_LV_CAST pBuffer)++ = pFlagStgmed->fPassOwnership;
  925. pBuffer = STGMEDIUM_UserMarshal( pFlags,
  926. pBuffer,
  927. & pFlagStgmed->Stgmed );
  928. return( pBuffer );
  929. }
  930. //+-------------------------------------------------------------------------
  931. //
  932. // Function: FLAG_STGMEDIUM_UserUnmarshal
  933. //
  934. // Synopsis: Unmarshals a wrapper for stgmedium.
  935. //
  936. // history: May-95 Ryszardk Created.
  937. //
  938. //--------------------------------------------------------------------------
  939. unsigned char __RPC_FAR * __RPC_USER
  940. FLAG_STGMEDIUM_UserUnmarshal(
  941. unsigned long * pFlags,
  942. unsigned char * pBuffer,
  943. FLAG_STGMEDIUM* pFlagStgmed )
  944. {
  945. // Init buffer size.
  946. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  947. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  948. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  949. UCHAR* pBufferPtr = pBufferStart;
  950. // Align the buffer.
  951. ALIGN( pBufferPtr, 3 );
  952. ULONG_PTR cbFixup = (ULONG_PTR)(pBufferPtr - pBufferStart);
  953. // BufferSize must not be less than the
  954. // alignment fixup + ContextFlags + fPassOwnership + tymed.
  955. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (2 * sizeof( ULONG )) );
  956. // Flags and buffer marker
  957. pFlagStgmed->ContextFlags = *( PULONG_LV_CAST pBufferPtr)++;
  958. // Flags: we need them when freeing in the client call_as routine
  959. // We need that in the Proxy, when we call the user free routine.
  960. pFlagStgmed->fPassOwnership = *( PULONG_LV_CAST pBufferPtr)++;
  961. pFlagStgmed->ContextFlags = *pFlags;
  962. // Needed to handle both GDI handles and Istream/IStorage correctly.
  963. // Subtract alignment fixup + 2 DWORDs from BufferSize.
  964. BufferSize -= cbFixup + (2 * sizeof( ULONG ));
  965. pBuffer = STGMEDIUM_UserUnmarshalWorker( pFlags,
  966. pBufferPtr,
  967. & pFlagStgmed->Stgmed,
  968. BufferSize );
  969. return( pBuffer );
  970. }
  971. //+-------------------------------------------------------------------------
  972. //
  973. // Function: FLAG_STGMEDIUM_UserFree
  974. //
  975. // Synopsis: Freess a wrapper for stgmedium.
  976. //
  977. // history: May-95 Ryszardk Created.
  978. //
  979. //--------------------------------------------------------------------------
  980. void __RPC_USER
  981. FLAG_STGMEDIUM_UserFree(
  982. unsigned long * pFlags,
  983. FLAG_STGMEDIUM* pFlagsStgmed )
  984. {
  985. if ( ! pFlagsStgmed->fPassOwnership )
  986. STGMEDIUM_UserFree( pFlags, & pFlagsStgmed->Stgmed );
  987. // else the callee is supposed to release the stg medium.
  988. }
  989. //+-------------------------------------------------------------------------
  990. //
  991. // Function: ASYNC_STGMEDIUM_UserSize
  992. //
  993. // Synopsis: Sizes a wrapper for stgmedium.
  994. //
  995. // history: May-95 Ryszardk Created.
  996. // May-97 Ryszardk introduced the async flag to optimize
  997. //
  998. //--------------------------------------------------------------------------
  999. unsigned long __RPC_USER
  1000. ASYNC_STGMEDIUM_UserSize(
  1001. unsigned long * pFlags,
  1002. unsigned long Offset,
  1003. ASYNC_STGMEDIUM* pAsyncStgmed )
  1004. {
  1005. if ( ! pAsyncStgmed )
  1006. return Offset;
  1007. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1008. // BTW: This is needed only as a workaround because the [async] attr
  1009. // has been temporarily removed from objidl.idl. (May 1997).
  1010. // After we have the new [async] in place, this code is unnecessary
  1011. // as the NDR engine is setting the same flag for every async call.
  1012. *pFlags |= USER_CALL_IS_ASYNC;
  1013. Offset = STGMEDIUM_UserSize( pFlags, Offset, pAsyncStgmed );
  1014. return( Offset );
  1015. }
  1016. //+-------------------------------------------------------------------------
  1017. //
  1018. // Function: ASYNC_STGMEDIUM_UserMarshal
  1019. //
  1020. // Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
  1021. //
  1022. // history: May-95 Ryszardk Created.
  1023. //
  1024. //--------------------------------------------------------------------------
  1025. unsigned char __RPC_FAR * __RPC_USER
  1026. ASYNC_STGMEDIUM_UserMarshal(
  1027. unsigned long * pFlags,
  1028. unsigned char * pBuffer,
  1029. ASYNC_STGMEDIUM* pAsyncStgmed )
  1030. {
  1031. if ( ! pAsyncStgmed )
  1032. return pBuffer;
  1033. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1034. *pFlags |= USER_CALL_IS_ASYNC;
  1035. pBuffer = STGMEDIUM_UserMarshal( pFlags,
  1036. pBuffer,
  1037. pAsyncStgmed );
  1038. return( pBuffer );
  1039. }
  1040. //+-------------------------------------------------------------------------
  1041. //
  1042. // Function: ASYNC_STGMEDIUM_UserUnmarshal
  1043. //
  1044. // Synopsis: Unmarshals a wrapper for stgmedium.
  1045. //
  1046. // history: May-95 Ryszardk Created.
  1047. //
  1048. //--------------------------------------------------------------------------
  1049. unsigned char __RPC_FAR * __RPC_USER
  1050. ASYNC_STGMEDIUM_UserUnmarshal(
  1051. unsigned long * pFlags,
  1052. unsigned char * pBuffer,
  1053. ASYNC_STGMEDIUM* pAsyncStgmed )
  1054. {
  1055. // Init buffer size.
  1056. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  1057. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  1058. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  1059. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1060. *pFlags |= USER_CALL_IS_ASYNC;
  1061. pBuffer = STGMEDIUM_UserUnmarshalWorker( pFlags,
  1062. pBufferStart,
  1063. pAsyncStgmed,
  1064. BufferSize );
  1065. return( pBuffer );
  1066. }
  1067. //+-------------------------------------------------------------------------
  1068. //
  1069. // Function: ASYNC_STGMEDIUM_UserFree
  1070. //
  1071. // Synopsis: Freess a wrapper for stgmedium.
  1072. //
  1073. // history: May-95 Ryszardk Created.
  1074. //
  1075. //--------------------------------------------------------------------------
  1076. void __RPC_USER
  1077. ASYNC_STGMEDIUM_UserFree(
  1078. unsigned long * pFlags,
  1079. ASYNC_STGMEDIUM* pAsyncStgmed )
  1080. {
  1081. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1082. *pFlags |= USER_CALL_IS_ASYNC;
  1083. STGMEDIUM_UserFree( pFlags, pAsyncStgmed );
  1084. }
  1085. #if defined(_WIN64)
  1086. //
  1087. // NDR64 Support routines.
  1088. //
  1089. //+-------------------------------------------------------------------------
  1090. //
  1091. // Function: STGMEDIUM_UserSize64
  1092. //
  1093. // Synopsis: Sizes a stgmedium pbject for RPC marshalling.
  1094. //
  1095. // history: Dec-00 JohnDoty Created based on 32b function.
  1096. //
  1097. //--------------------------------------------------------------------------
  1098. unsigned long __RPC_USER
  1099. STGMEDIUM_UserSize64 (
  1100. unsigned long * pFlags,
  1101. unsigned long Offset,
  1102. STGMEDIUM * pStgmed )
  1103. {
  1104. if ( ! pStgmed )
  1105. return Offset;
  1106. LENGTH_ALIGN( Offset, 7 );
  1107. // tymed is 4 bytes, plus 4 bytes padding, plus potentially the handle (8 bytes),
  1108. // plus the pUnk.
  1109. if ( pStgmed->tymed == TYMED_NULL )
  1110. Offset += 4 + 4 + 8; // switch, pad, (empty arm), pUnk
  1111. else
  1112. {
  1113. Offset += 4 + 4 + 8 + 8; // switch, pad, handle, pUnk
  1114. // Pointee of the union arm.
  1115. // Only if the handle/pointer field is non-null.
  1116. if ( pStgmed->hGlobal )
  1117. {
  1118. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  1119. switch( pStgmed->tymed )
  1120. {
  1121. case TYMED_NULL:
  1122. break;
  1123. case TYMED_MFPICT:
  1124. Offset = HMETAFILEPICT_UserSize64( pFlags,
  1125. Offset,
  1126. &pStgmed->hMetaFilePict );
  1127. break;
  1128. case TYMED_ENHMF:
  1129. Offset = HENHMETAFILE_UserSize64( pFlags,
  1130. Offset,
  1131. &pStgmed->hEnhMetaFile );
  1132. break;
  1133. case TYMED_GDI:
  1134. // A GDI object is not necesarrily a BITMAP. Therefore, we handle
  1135. // those types we know about based on the object type, and reject
  1136. // those which we do not support.
  1137. // 4 bytes for disc, plus 4 bytes pad, plus 8 bytes pointer?
  1138. Offset += 4 + 4 + 8;
  1139. switch( GetObjectType( (HGDIOBJ)pStgmed->hBitmap ) )
  1140. {
  1141. case OBJ_BITMAP:
  1142. Offset = HBITMAP_UserSize64( pFlags,
  1143. Offset,
  1144. &pStgmed->hBitmap );
  1145. break;
  1146. case OBJ_PAL:
  1147. Offset = HPALETTE_UserSize64( pFlags,
  1148. Offset,
  1149. (HPALETTE *) & pStgmed->hBitmap );
  1150. break;
  1151. default:
  1152. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  1153. break;
  1154. }
  1155. break;
  1156. case TYMED_HGLOBAL:
  1157. Offset = HGLOBAL_UserSize64( pFlags,
  1158. Offset,
  1159. &pStgmed->hGlobal );
  1160. break;
  1161. case TYMED_FILE:
  1162. {
  1163. ulong ulDataSize = 0;
  1164. if (pStgmed->lpszFileName)
  1165. ulDataSize = lstrlenW(pStgmed->lpszFileName) + 1;
  1166. Offset += 3 * 8; // max size, offset, conformance
  1167. Offset += ulDataSize * sizeof(wchar_t);
  1168. }
  1169. break;
  1170. case TYMED_ISTREAM:
  1171. Offset = WdtpInterfacePointer_UserSize64((USER_MARSHAL_CB *)pFlags,
  1172. *pFlags,
  1173. Offset,
  1174. pStgmed->pstm,
  1175. IID_IStream);
  1176. break;
  1177. case TYMED_ISTORAGE:
  1178. Offset = WdtpInterfacePointer_UserSize64((USER_MARSHAL_CB *)pFlags,
  1179. *pFlags,
  1180. Offset,
  1181. pStgmed->pstg,
  1182. IID_IStorage);
  1183. break;
  1184. default:
  1185. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  1186. break;
  1187. }
  1188. }
  1189. }
  1190. // pUnkForRelease, if not null.
  1191. if ( pStgmed->pUnkForRelease )
  1192. Offset = WdtpInterfacePointer_UserSize64( (USER_MARSHAL_CB *)pFlags,
  1193. *pFlags,
  1194. Offset,
  1195. pStgmed->pUnkForRelease,
  1196. IID_IUnknown );
  1197. return( Offset );
  1198. }
  1199. //+-------------------------------------------------------------------------
  1200. //
  1201. // Function: STGMEDIUM_UserMarshal64
  1202. //
  1203. // Synopsis: Marshals a stgmedium pbject for RPC.
  1204. //
  1205. // history: Dec-00 JohnDoty Created based on 32b function.
  1206. //
  1207. //--------------------------------------------------------------------------
  1208. unsigned char __RPC_FAR * __RPC_USER
  1209. STGMEDIUM_UserMarshal64 (
  1210. unsigned long * pFlags,
  1211. unsigned char * pBufferStart,
  1212. STGMEDIUM * pStgmed )
  1213. {
  1214. unsigned char * pBuffer;
  1215. unsigned char * pUnionArmMark;
  1216. DWORD tymed;
  1217. if ( ! pStgmed )
  1218. return pBufferStart;
  1219. UserNdrDebugOut((
  1220. UNDR_FORCE,
  1221. "--STGMEDIUM_UserMarshal64: %s\n",
  1222. WdtpGetStgmedName(pStgmed)));
  1223. pBuffer = pBufferStart;
  1224. ALIGN( pBuffer, 7 );
  1225. // userSTGMEDIUM: switch, union arm, pUnk ptr.
  1226. tymed = pStgmed->tymed;
  1227. *( PULONG_LV_CAST pBuffer)++ = tymed;
  1228. ALIGN( pBuffer, 7 );
  1229. pUnionArmMark = pBuffer;
  1230. if ( tymed != TYMED_NULL )
  1231. {
  1232. // hGlobal stands for any of these handles.
  1233. *(PHYPER_LV_CAST pBuffer)++ = (hyper)( pStgmed->hGlobal );
  1234. }
  1235. *(PHYPER_LV_CAST pBuffer)++ = (hyper)( pStgmed->pUnkForRelease );
  1236. // Now the pointee of the union arm.
  1237. // We need to marshal only if the handle/pointer field is non null.
  1238. // Otherwise it is already in the buffer.
  1239. if ( pStgmed->hGlobal )
  1240. {
  1241. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  1242. switch( pStgmed->tymed )
  1243. {
  1244. case TYMED_NULL:
  1245. break;
  1246. case TYMED_MFPICT:
  1247. pBuffer = HMETAFILEPICT_UserMarshal64( pFlags,
  1248. pBuffer,
  1249. &pStgmed->hMetaFilePict );
  1250. break;
  1251. case TYMED_ENHMF:
  1252. pBuffer = HENHMETAFILE_UserMarshal64( pFlags,
  1253. pBuffer,
  1254. &pStgmed->hEnhMetaFile );
  1255. break;
  1256. case TYMED_GDI:
  1257. {
  1258. // A GDI object is not necesarrily a BITMAP. Therefore, we handle
  1259. // those types we know about based on the object type, and reject
  1260. // those which we do not support.
  1261. ulong GdiObjectType = GetObjectType( (HGDIOBJ)pStgmed->hBitmap );
  1262. // GDI_OBJECT
  1263. *(PULONG_LV_CAST pBuffer)++ = GdiObjectType;
  1264. ALIGN( pBuffer, 7 );
  1265. *(PHYPER_LV_CAST pBuffer)++ = (hyper)(pStgmed->hBitmap);
  1266. switch( GdiObjectType )
  1267. {
  1268. case OBJ_BITMAP:
  1269. pBuffer = HBITMAP_UserMarshal64( pFlags,
  1270. pBuffer,
  1271. &pStgmed->hBitmap );
  1272. break;
  1273. case OBJ_PAL:
  1274. pBuffer = HPALETTE_UserMarshal64( pFlags,
  1275. pBuffer,
  1276. (HPALETTE *) & pStgmed->hBitmap );
  1277. break;
  1278. default:
  1279. RpcRaiseException(DV_E_TYMED);
  1280. }
  1281. }
  1282. break;
  1283. case TYMED_HGLOBAL:
  1284. pBuffer = HGLOBAL_UserMarshal64( pFlags,
  1285. pBuffer,
  1286. &pStgmed->hGlobal );
  1287. break;
  1288. case TYMED_FILE:
  1289. {
  1290. // We marshal it as a [string].
  1291. ulong Count = 0;
  1292. if (pStgmed->lpszFileName)
  1293. Count = lstrlenW(pStgmed->lpszFileName) + 1;
  1294. *( PHYPER_LV_CAST pBuffer)++ = Count;
  1295. *( PHYPER_LV_CAST pBuffer)++ = 0;
  1296. *( PHYPER_LV_CAST pBuffer)++ = Count;
  1297. memcpy( pBuffer, pStgmed->lpszFileName, Count * sizeof(wchar_t) );
  1298. pBuffer += Count * sizeof(wchar_t);
  1299. }
  1300. break;
  1301. case TYMED_ISTREAM:
  1302. pBuffer = WdtpInterfacePointer_UserMarshal64(((USER_MARSHAL_CB *)pFlags),
  1303. *pFlags,
  1304. pBuffer,
  1305. pStgmed->pstm,
  1306. IID_IStream);
  1307. break;
  1308. case TYMED_ISTORAGE:
  1309. pBuffer = WdtpInterfacePointer_UserMarshal64(((USER_MARSHAL_CB *)pFlags),
  1310. *pFlags,
  1311. pBuffer,
  1312. pStgmed->pstg,
  1313. IID_IStorage);
  1314. break;
  1315. default:
  1316. RpcRaiseException(DV_E_TYMED);
  1317. break;
  1318. }
  1319. }
  1320. // Marker for this pointer is already in the buffer.
  1321. if ( pStgmed->pUnkForRelease )
  1322. pBuffer = WdtpInterfacePointer_UserMarshal64( ((USER_MARSHAL_CB *)pFlags),
  1323. *pFlags,
  1324. pBuffer,
  1325. pStgmed->pUnkForRelease,
  1326. IID_IUnknown );
  1327. return( pBuffer );
  1328. }
  1329. //+-------------------------------------------------------------------------
  1330. //
  1331. // Function: STGMEDIUM_UserUnmarshalWorker64
  1332. //
  1333. // Synopsis: Unmarshals a stgmedium object for RPC.
  1334. //
  1335. // history: Dec-00 JohnDoty Created based on 32b function.
  1336. //
  1337. //--------------------------------------------------------------------------
  1338. unsigned char __RPC_FAR * __RPC_USER
  1339. STGMEDIUM_UserUnmarshalWorker64 (
  1340. unsigned long * pFlags,
  1341. unsigned char * pBuffer,
  1342. STGMEDIUM * pStgmed,
  1343. ULONG_PTR BufferSize )
  1344. {
  1345. CarefulBufferReader stream(pBuffer, BufferSize);
  1346. LONG_PTR fUnkForRelease;
  1347. LONG_PTR Handle = 0;
  1348. unsigned char *mark = NULL;
  1349. // Align the buffer and save the fixup size.
  1350. stream.Align(8);
  1351. // switch, union arm, pUnk.
  1352. pStgmed->tymed = stream.ReadULONGNA();
  1353. UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal64: %s\n",
  1354. WdtpGetStgmedName(pStgmed) ));
  1355. // (Force the align here so we only align once)
  1356. stream.Align(8);
  1357. if ( pStgmed->tymed != TYMED_NULL )
  1358. {
  1359. // This value is just a marker for the handle - a long.
  1360. Handle = stream.ReadHYPERNA();
  1361. }
  1362. // pUnkForRelease pointer marker.
  1363. fUnkForRelease = stream.ReadHYPERNA();
  1364. // First pointee
  1365. // Union arm pointee.
  1366. // We need to unmarshal only if the handle/pointer field was not NULL.
  1367. if ( Handle )
  1368. {
  1369. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  1370. hyper* pBuf = (hyper*)stream.GetBuffer();
  1371. switch( pStgmed->tymed )
  1372. {
  1373. case TYMED_NULL:
  1374. break;
  1375. case TYMED_MFPICT:
  1376. // validate the handle...
  1377. stream.CheckSize( 4 + 4 + 8 ); // enc. union: 4b switch + 4b pad + 8b handle
  1378. if ( Handle != pBuf[1] )
  1379. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1380. mark = HMETAFILEPICT_UserUnmarshalWorker64 (pFlags,
  1381. stream.GetBuffer(),
  1382. &pStgmed->hMetaFilePict,
  1383. stream.BytesRemaining() );
  1384. stream.AdvanceTo(mark);
  1385. break;
  1386. case TYMED_ENHMF:
  1387. // validate the handle...
  1388. stream.CheckSize( 4 + 4 + 8 ); // enc. union: 4b switch + 4b pad + 8b handle
  1389. if ( Handle != pBuf[1] )
  1390. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1391. mark = HENHMETAFILE_UserUnmarshalWorker64 ( pFlags,
  1392. stream.GetBuffer(),
  1393. &pStgmed->hEnhMetaFile,
  1394. stream.BytesRemaining() );
  1395. stream.AdvanceTo(mark);
  1396. break;
  1397. case TYMED_GDI:
  1398. {
  1399. // A GDI object is not necesarrily a BITMAP. Therefore, we
  1400. // handle those types we know about based on the object type,
  1401. // and reject those which we do not support.
  1402. DWORD GdiObjectType = stream.ReadULONGNA();
  1403. Handle = stream.ReadHYPER();
  1404. switch( GdiObjectType )
  1405. {
  1406. case OBJ_BITMAP:
  1407. // Lookahead validation of the handle.
  1408. stream.CheckSize( 4 + 4 + 8 );
  1409. pBuf = (hyper*)stream.GetBuffer();
  1410. if ( Handle != pBuf[1] )
  1411. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1412. mark = HBITMAP_UserUnmarshalWorker64( pFlags,
  1413. stream.GetBuffer(),
  1414. &pStgmed->hBitmap,
  1415. stream.BytesRemaining() );
  1416. stream.AdvanceTo(mark);
  1417. break;
  1418. case OBJ_PAL:
  1419. // Lookahead validaton of the handle.
  1420. stream.CheckSize( 4 + 4 + 8 );
  1421. pBuf = (hyper*)stream.GetBuffer();
  1422. if ( Handle != pBuf[1] )
  1423. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1424. mark = HPALETTE_UserUnmarshalWorker64( pFlags,
  1425. stream.GetBuffer(),
  1426. (HPALETTE *) & pStgmed->hBitmap,
  1427. stream.BytesRemaining() );
  1428. stream.AdvanceTo(mark);
  1429. break;
  1430. default:
  1431. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1432. }
  1433. }
  1434. break;
  1435. case TYMED_HGLOBAL:
  1436. // reallocation is forbidden for [in-out] hglobal in STGMEDIUM.
  1437. // validate the handle.
  1438. stream.CheckSize( 4 + 4 + 8 ); // enc. union: 4b switch + 4b pad + 8b handle
  1439. if ( Handle != pBuf[1] )
  1440. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1441. mark = WdtpGlobalUnmarshal64( pFlags,
  1442. stream.GetBuffer(),
  1443. & pStgmed->hGlobal,
  1444. FALSE,
  1445. stream.BytesRemaining() );
  1446. stream.AdvanceTo(mark);
  1447. break;
  1448. case TYMED_FILE:
  1449. {
  1450. // Must be room in buffer for header.
  1451. ulong Count = (ulong)stream.ReadHYPERNA();
  1452. // We marshal it as a [string].
  1453. if ( stream.ReadHYPERNA() != 0 )
  1454. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1455. if ( stream.ReadHYPERNA() != Count )
  1456. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1457. if ( ! pStgmed->lpszFileName )
  1458. pStgmed->lpszFileName = (LPOLESTR) WdtpAllocate( pFlags, Count * sizeof(wchar_t) );
  1459. // Must be room in the buffer for the string.
  1460. stream.CheckSize( Count * sizeof(WCHAR) );
  1461. memcpy(pStgmed->lpszFileName,
  1462. stream.GetBuffer(),
  1463. Count * sizeof(wchar_t));
  1464. stream.Advance( Count * sizeof(WCHAR) );
  1465. }
  1466. break;
  1467. case TYMED_ISTREAM:
  1468. mark = WdtpInterfacePointer_UserUnmarshalWorker((USER_MARSHAL_CB *)pFlags,
  1469. stream.GetBuffer(),
  1470. (IUnknown **) &pStgmed->pstm,
  1471. IID_IStream,
  1472. stream.BytesRemaining(),
  1473. TRUE);
  1474. stream.AdvanceTo(mark);
  1475. break;
  1476. case TYMED_ISTORAGE:
  1477. mark = WdtpInterfacePointer_UserUnmarshalWorker((USER_MARSHAL_CB *)pFlags,
  1478. stream.GetBuffer(),
  1479. (IUnknown **) &pStgmed->pstg,
  1480. IID_IStorage,
  1481. stream.BytesRemaining(),
  1482. TRUE);
  1483. stream.AdvanceTo(mark);
  1484. break;
  1485. default:
  1486. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  1487. break;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. // New handle/pointer field is null, so release the previous one
  1493. // if it wasn't null.
  1494. if ( pStgmed->hGlobal )
  1495. {
  1496. // This should never happen for GetDataHere.
  1497. // Note, that we release the handle field, not the stgmedium itself.
  1498. // Accordingly, we don't follow punkForRelease.
  1499. UserNdrDebugOut((
  1500. UNDR_FORCE,
  1501. "--STGMEDIUM_UserUnmarshal64: %s: NULL in, freeing old one\n",
  1502. WdtpGetStgmedName(pStgmed)));
  1503. STGMEDIUM TmpStg = *pStgmed;
  1504. TmpStg.pUnkForRelease = NULL;
  1505. if ( pStgmed->tymed == TYMED_HGLOBAL )
  1506. {
  1507. // Cannot reallocate.
  1508. RAISE_RPC_EXCEPTION(DV_E_TYMED);
  1509. }
  1510. else
  1511. {
  1512. ReleaseStgMedium( &TmpStg );
  1513. }
  1514. }
  1515. pStgmed->hGlobal = 0;
  1516. }
  1517. if ( fUnkForRelease )
  1518. {
  1519. // There is an interface pointer on the wire.
  1520. mark = WdtpInterfacePointer_UserUnmarshalWorker((USER_MARSHAL_CB *)pFlags,
  1521. stream.GetBuffer(),
  1522. &pStgmed->pUnkForRelease,
  1523. IID_IUnknown,
  1524. stream.BytesRemaining(),
  1525. TRUE);
  1526. stream.AdvanceTo(mark);
  1527. }
  1528. if ( pStgmed->pUnkForRelease )
  1529. {
  1530. // Replace the app's punkForRelease with our custom release
  1531. // handler for special situations.
  1532. // The special situation is when a handle is remoted with data
  1533. // and so we have to clean up a side effect of having a data copy
  1534. // around. UserFree does it properly but we need that for the callee.
  1535. // When the callee releases a stgmed, it would invoke
  1536. // ReleaseStgMedium and this API doesn't do anything for handles
  1537. // when the punkForRelease is not NULL.
  1538. ULONG fHandleWithData = 0;
  1539. ULONG fTopLevelOnly = 0;
  1540. switch ( pStgmed->tymed )
  1541. {
  1542. case TYMED_HGLOBAL:
  1543. fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
  1544. break;
  1545. case TYMED_ENHMF:
  1546. case TYMED_GDI:
  1547. fHandleWithData = GDI_DATA_PASSING( *pFlags );
  1548. break;
  1549. case TYMED_MFPICT:
  1550. fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
  1551. fTopLevelOnly = fHandleWithData && !GDI_DATA_PASSING( *pFlags );
  1552. break;
  1553. default:
  1554. break;
  1555. }
  1556. if ( fHandleWithData )
  1557. {
  1558. IUnknown *
  1559. punkTmp = (IUnknown *) new CPunkForRelease( pStgmed,
  1560. fTopLevelOnly );
  1561. if (!punkTmp)
  1562. {
  1563. RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
  1564. }
  1565. pStgmed->pUnkForRelease = punkTmp;
  1566. }
  1567. }
  1568. return( stream.GetBuffer() );
  1569. }
  1570. //+-------------------------------------------------------------------------
  1571. //
  1572. // Function: STGMEDIUM_UserUnmarshal64
  1573. //
  1574. // Synopsis: Unmarshals a stgmedium object for RPC.
  1575. //
  1576. // history: Dec-00 JohnDoty Created based on 32b function.
  1577. //
  1578. //--------------------------------------------------------------------------
  1579. unsigned char __RPC_FAR * __RPC_USER
  1580. STGMEDIUM_UserUnmarshal64 (
  1581. unsigned long * pFlags,
  1582. unsigned char * pBuffer,
  1583. STGMEDIUM * pStgmed )
  1584. {
  1585. // Init buffer size and ptr to buffer.
  1586. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  1587. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  1588. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  1589. pBuffer = STGMEDIUM_UserUnmarshalWorker64( pFlags,
  1590. pBufferStart,
  1591. pStgmed,
  1592. BufferSize );
  1593. return( pBuffer );
  1594. }
  1595. //+-------------------------------------------------------------------------
  1596. //
  1597. // Function: STGMEDIUM_UserFree64
  1598. //
  1599. // Synopsis: Frees a stgmedium object for RPC.
  1600. //
  1601. // history: Dec-00 JohnDoty Created based on 32b function.
  1602. //
  1603. // Note: This routine is called from the freeing walk at server
  1604. // or from the SetData *proxy*, when ownership has been passed.
  1605. //
  1606. //--------------------------------------------------------------------------
  1607. void __RPC_USER
  1608. STGMEDIUM_UserFree64 (
  1609. unsigned long * pFlags,
  1610. STGMEDIUM * pStgmed )
  1611. {
  1612. UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserFree64: %s\n", WdtpGetStgmedName(pStgmed)));
  1613. if( pStgmed )
  1614. {
  1615. SetContextFlagsForAsyncCall( pFlags, pStgmed );
  1616. switch ( pStgmed->tymed )
  1617. {
  1618. case TYMED_FILE:
  1619. WdtpFree( pFlags, pStgmed->lpszFileName);
  1620. NukeHandleAndReleasePunk( pStgmed );
  1621. break;
  1622. case TYMED_NULL:
  1623. case TYMED_ISTREAM:
  1624. case TYMED_ISTORAGE:
  1625. ReleaseStgMedium( pStgmed );
  1626. break;
  1627. case TYMED_GDI:
  1628. case TYMED_ENHMF:
  1629. if ( GDI_HANDLE_PASSING(*pFlags) )
  1630. {
  1631. NukeHandleAndReleasePunk( pStgmed );
  1632. }
  1633. else
  1634. {
  1635. // Handle w/data: there is a side effect to clean up.
  1636. // For punk !=0, this will go to our CPunk object.
  1637. ReleaseStgMedium( pStgmed );
  1638. }
  1639. break;
  1640. case TYMED_HGLOBAL:
  1641. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  1642. {
  1643. NukeHandleAndReleasePunk( pStgmed );
  1644. }
  1645. else
  1646. {
  1647. // Handle w/data: there is a side effect to clean up.
  1648. // For punk ==0, this will just release the data.
  1649. // For punk !=0, this will go to our CPunk object,
  1650. // release the data, and then call the original punk.
  1651. ReleaseStgMedium( pStgmed );
  1652. }
  1653. break;
  1654. case TYMED_MFPICT:
  1655. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  1656. {
  1657. NukeHandleAndReleasePunk( pStgmed );
  1658. }
  1659. else if ( GDI_HANDLE_PASSING(*pFlags) )
  1660. {
  1661. if ( pStgmed->pUnkForRelease )
  1662. {
  1663. pStgmed->pUnkForRelease->Release();
  1664. }
  1665. else
  1666. {
  1667. if ( pStgmed->hGlobal )
  1668. GlobalFree( pStgmed->hGlobal );
  1669. pStgmed->hGlobal = NULL;
  1670. pStgmed->tymed = TYMED_NULL;
  1671. }
  1672. }
  1673. else
  1674. {
  1675. // Handle w/data: there is a side effect to clean up.
  1676. // For punk !=0, this will go to our CPunk object.
  1677. ReleaseStgMedium( pStgmed );
  1678. }
  1679. break;
  1680. default:
  1681. RAISE_RPC_EXCEPTION( E_INVALIDARG );
  1682. break;
  1683. }
  1684. }
  1685. }
  1686. //+-------------------------------------------------------------------------
  1687. //
  1688. // Function: FLAG_STGMEDIUM_UserSize64
  1689. //
  1690. // Synopsis: Sizes a wrapper for stgmedium.
  1691. //
  1692. // history: Dec-00 JohnDoty Created based on 32b function.
  1693. //
  1694. //--------------------------------------------------------------------------
  1695. unsigned long __RPC_USER
  1696. FLAG_STGMEDIUM_UserSize64 (
  1697. unsigned long * pFlags,
  1698. unsigned long Offset,
  1699. FLAG_STGMEDIUM* pFlagStgmed )
  1700. {
  1701. if ( ! pFlagStgmed )
  1702. return Offset;
  1703. LENGTH_ALIGN( Offset, 7 );
  1704. Offset += 2 * sizeof(long);
  1705. Offset = STGMEDIUM_UserSize64 ( pFlags, Offset, & pFlagStgmed->Stgmed );
  1706. return( Offset );
  1707. }
  1708. //+-------------------------------------------------------------------------
  1709. //
  1710. // Function: FLAG_STGMEDIUM_UserMarshal64
  1711. //
  1712. // Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
  1713. //
  1714. // history: Dec-00 JohnDoty Created based on 32b function.
  1715. //
  1716. //--------------------------------------------------------------------------
  1717. unsigned char __RPC_FAR * __RPC_USER
  1718. FLAG_STGMEDIUM_UserMarshal64 (
  1719. unsigned long * pFlags,
  1720. unsigned char * pBuffer,
  1721. FLAG_STGMEDIUM* pFlagStgmed )
  1722. {
  1723. if ( ! pFlagStgmed )
  1724. return pBuffer;
  1725. ALIGN( pBuffer, 7 );
  1726. // Flags: we need them when freeing in the client call_as routine
  1727. pFlagStgmed->ContextFlags = *pFlags;
  1728. *( PULONG_LV_CAST pBuffer)++ = *pFlags;
  1729. *( PULONG_LV_CAST pBuffer)++ = pFlagStgmed->fPassOwnership;
  1730. pBuffer = STGMEDIUM_UserMarshal64( pFlags,
  1731. pBuffer,
  1732. & pFlagStgmed->Stgmed );
  1733. return( pBuffer );
  1734. }
  1735. //+-------------------------------------------------------------------------
  1736. //
  1737. // Function: FLAG_STGMEDIUM_UserUnmarshal64
  1738. //
  1739. // Synopsis: Unmarshals a wrapper for stgmedium.
  1740. //
  1741. // history: Dec-00 JohnDoty Created based on 32b function.
  1742. //
  1743. //--------------------------------------------------------------------------
  1744. unsigned char __RPC_FAR * __RPC_USER
  1745. FLAG_STGMEDIUM_UserUnmarshal64 (
  1746. unsigned long * pFlags,
  1747. unsigned char * pBuffer,
  1748. FLAG_STGMEDIUM* pFlagStgmed )
  1749. {
  1750. // Init buffer size.
  1751. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  1752. CarefulBufferReader stream(pBuffer, MarshalInfo.GetBufferSize());
  1753. // Align the buffer.
  1754. stream.Align(8);
  1755. // Flags and buffer marker
  1756. pFlagStgmed->ContextFlags = stream.ReadULONGNA();
  1757. // Flags: we need them when freeing in the client call_as routine
  1758. // We need that in the Proxy, when we call the user free routine.
  1759. pFlagStgmed->fPassOwnership = stream.ReadULONGNA();
  1760. pFlagStgmed->ContextFlags = *pFlags;
  1761. pBuffer = STGMEDIUM_UserUnmarshalWorker64( pFlags,
  1762. stream.GetBuffer(),
  1763. & pFlagStgmed->Stgmed,
  1764. stream.BytesRemaining() );
  1765. return( pBuffer );
  1766. }
  1767. //+-------------------------------------------------------------------------
  1768. //
  1769. // Function: FLAG_STGMEDIUM_UserFree64
  1770. //
  1771. // Synopsis: Freess a wrapper for stgmedium.
  1772. //
  1773. // history: Dec-00 JohnDoty Created based on 32b function.
  1774. //
  1775. //--------------------------------------------------------------------------
  1776. void __RPC_USER
  1777. FLAG_STGMEDIUM_UserFree64 (
  1778. unsigned long * pFlags,
  1779. FLAG_STGMEDIUM* pFlagsStgmed )
  1780. {
  1781. if ( ! pFlagsStgmed->fPassOwnership )
  1782. STGMEDIUM_UserFree64 ( pFlags, & pFlagsStgmed->Stgmed );
  1783. // else the callee is supposed to release the stg medium.
  1784. }
  1785. //+-------------------------------------------------------------------------
  1786. //
  1787. // Function: ASYNC_STGMEDIUM_UserSize64
  1788. //
  1789. // Synopsis: Sizes a wrapper for stgmedium.
  1790. //
  1791. // history: Dec-00 JohnDoty Created based on 32b function.
  1792. //
  1793. //--------------------------------------------------------------------------
  1794. unsigned long __RPC_USER
  1795. ASYNC_STGMEDIUM_UserSize64 (
  1796. unsigned long * pFlags,
  1797. unsigned long Offset,
  1798. ASYNC_STGMEDIUM* pAsyncStgmed )
  1799. {
  1800. if ( ! pAsyncStgmed )
  1801. return Offset;
  1802. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1803. // BTW: This is needed only as a workaround because the [async] attr
  1804. // has been temporarily removed from objidl.idl. (May 1997).
  1805. // After we have the new [async] in place, this code is unnecessary
  1806. // as the NDR engine is setting the same flag for every async call.
  1807. *pFlags |= USER_CALL_IS_ASYNC;
  1808. Offset = STGMEDIUM_UserSize64 ( pFlags, Offset, pAsyncStgmed );
  1809. return( Offset );
  1810. }
  1811. //+-------------------------------------------------------------------------
  1812. //
  1813. // Function: ASYNC_STGMEDIUM_UserMarshal64
  1814. //
  1815. // Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
  1816. //
  1817. // history: Dec-00 JohnDoty Created based on 32b function.
  1818. //
  1819. //--------------------------------------------------------------------------
  1820. unsigned char __RPC_FAR * __RPC_USER
  1821. ASYNC_STGMEDIUM_UserMarshal64 (
  1822. unsigned long * pFlags,
  1823. unsigned char * pBuffer,
  1824. ASYNC_STGMEDIUM* pAsyncStgmed )
  1825. {
  1826. if ( ! pAsyncStgmed )
  1827. return pBuffer;
  1828. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1829. *pFlags |= USER_CALL_IS_ASYNC;
  1830. pBuffer = STGMEDIUM_UserMarshal64( pFlags,
  1831. pBuffer,
  1832. pAsyncStgmed );
  1833. return( pBuffer );
  1834. }
  1835. //+-------------------------------------------------------------------------
  1836. //
  1837. // Function: ASYNC_STGMEDIUM_UserUnmarshal64
  1838. //
  1839. // Synopsis: Unmarshals a wrapper for stgmedium.
  1840. //
  1841. // history: Dec-00 JohnDoty Created based on 32b function
  1842. //
  1843. //--------------------------------------------------------------------------
  1844. unsigned char __RPC_FAR * __RPC_USER
  1845. ASYNC_STGMEDIUM_UserUnmarshal64(
  1846. unsigned long * pFlags,
  1847. unsigned char * pBuffer,
  1848. ASYNC_STGMEDIUM* pAsyncStgmed )
  1849. {
  1850. // Init buffer size.
  1851. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  1852. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  1853. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  1854. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1855. *pFlags |= USER_CALL_IS_ASYNC;
  1856. pBuffer = STGMEDIUM_UserUnmarshalWorker64( pFlags,
  1857. pBufferStart,
  1858. pAsyncStgmed,
  1859. BufferSize );
  1860. return( pBuffer );
  1861. }
  1862. //+-------------------------------------------------------------------------
  1863. //
  1864. // Function: ASYNC_STGMEDIUM_UserFree64
  1865. //
  1866. // Synopsis: Freess a wrapper for stgmedium.
  1867. //
  1868. // history: Dec-00 JohnDoty Created based on 32b function.
  1869. //
  1870. //--------------------------------------------------------------------------
  1871. void __RPC_USER
  1872. ASYNC_STGMEDIUM_UserFree64(
  1873. unsigned long * pFlags,
  1874. ASYNC_STGMEDIUM* pAsyncStgmed )
  1875. {
  1876. // Needed to handle both GDI handles and Istream/IStorage correctly.
  1877. *pFlags |= USER_CALL_IS_ASYNC;
  1878. STGMEDIUM_UserFree64( pFlags, pAsyncStgmed );
  1879. }
  1880. #endif