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.

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