diff options
Diffstat (limited to 'private/ole32/oleprx32/proxy/transmit.cxx')
-rw-r--r-- | private/ole32/oleprx32/proxy/transmit.cxx | 4246 |
1 files changed, 4246 insertions, 0 deletions
diff --git a/private/ole32/oleprx32/proxy/transmit.cxx b/private/ole32/oleprx32/proxy/transmit.cxx new file mode 100644 index 000000000..8d3e7a75d --- /dev/null +++ b/private/ole32/oleprx32/proxy/transmit.cxx @@ -0,0 +1,4246 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: transmit.cxx +// +// Contents: Support for Windows/OLE data types for oleprx32.dll. +// Used to be transmit_as routines, now user_marshal routines. +// +// Functions: HGLOBAL_UserSize +// HGLOBAL_UserMarshal +// HGLOBAL_UserUnmarshal +// HGLOBAL_UserFree +// HMETAFILEPICT_UserSize +// HMETAFILEPICT_UserMarshal +// HMETAFILEPICT_UserUnmarshal +// HMETAFILEPICT_UserFree +// HENHMETAFILE_UserSize +// HENHMETAFILE_UserMarshal +// HENHMETAFILE_UserUnmarshal +// HENHMETAFILE_UserFree +// HBITMAP_UserSize +// HBITMAP_UserMarshal +// HBITMAP_UserUnmarshal +// HBITMAP_UserFree +// HBRUSH_UserSize +// HBRUSH_UserMarshal +// HBRUSH_UserUnmarshal +// HBRUSH_UserFree +// STGMEDIUM_UserSize +// STGMEDIUM_UserMarshal +// STGMEDIUM_UserUnmarshal +// STGMEDIUM_UserFree +// HACCEL_UserSize +// HACCEL_UserMarshal +// HACCEL_UserUnmarshal +// HACCEL_UserFree +// HWND_UserSize +// HWND_UserMarshal +// HWND_UserUnmarshal +// HWND_UserFree +// HMENU_UserSize +// HMENU_UserMarshal +// HMENU_UserUnmarshal +// HMENU_UserFree +// CLIPFORMAT_UserSize +// CLIPFORMAT_UserMarshal +// CLIPFORMAT_UserUnmarshal +// CLIPFORMAT_UserFree +// +// History: 24-Aug-93 ShannonC Created +// 24-Nov-93 ShannonC Added HGLOBAL +// 14-May-94 DavePl Added HENHMETAFILE +// 18-May-94 ShannonC Added HACCEL, UINT, WPARAM +// 19-May-94 DavePl Added HENHMETAFILE to STGMEDIUM code +// May-95 Ryszardk Wrote all the _User* routines +// Feb-96 Ryszardk Added CLIPFORMAT support +// +//-------------------------------------------------------------------------- +#include "stdrpc.hxx" +#pragma hdrstop + +#include <oleauto.h> +#include <objbase.h> +#include "transmit.h" +#include <rpcwdt.h> +#include <storext.h> +#include "widewrap.h" + + +WINOLEAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pStgMed); + +#pragma code_seg(".orpc") + +EXTERN_C const CLSID CLSID_MyPSFactoryBuffer = {0x6f11fe5c,0x2fc5,0x101b,{0x9e,0x45,0x00,0x00,0x0b,0x65,0xc7,0xef}}; + + + +//+------------------------------------------------------------------------- +// +// class: CPunkForRelease +// +// purpose: special IUnknown for remoted STGMEDIUMs +// +// history: 02-Mar-94 Rickhi Created +// +// notes: This class is used to do the cleanup correctly when certain +// types of storages are passed between processes or machines +// in Nt and Chicago. +// +// On NT, GLOBAL, GDI, and BITMAP handles cannot be passed between +// processes, so we actually copy the whole data and create a +// new handle in the receiving process. However, STGMEDIUMs have +// this weird behaviour where if PunkForRelease is non-NULL then +// the sender is responsible for cleanup, not the receiver. Since +// we create a new handle in the receiver, we would leak handles +// if we didnt do some special processing. So, we do the +// following... +// +// During STGMEDIUM_UserUnmarshal, if there is a pUnkForRelease +// replace it with a CPunkForRelease. When Release is called +// on the CPunkForRelease, do the necessary cleanup work, +// then call the real PunkForRelease. +// +//+------------------------------------------------------------------------- + +class CPunkForRelease : public IUnknown +{ +public: + CPunkForRelease( STGMEDIUM *pStgMed, ulong fTopLayerOnly); + + // IUnknown Methods + STDMETHOD(QueryInterface)(REFIID riid, void **ppunk); + STDMETHOD_(ULONG, AddRef)(void); + STDMETHOD_(ULONG, Release)(void); + +private: + ~CPunkForRelease(void); + + ULONG _cRefs; // reference count + ULONG _fTopLayerMFP:1; // optimisation flag for Chicago + STGMEDIUM _stgmed; // storage medium + IUnknown * _pUnkForRelease; // real pUnkForRelease +}; + + +inline CPunkForRelease::CPunkForRelease( + STGMEDIUM * pStgMed, + ulong fTopLayerMFPict + ) : + _cRefs(1), + _fTopLayerMFP( fTopLayerMFPict), + _stgmed(*pStgMed) +{ + // NOTE: we assume the caller has verified pStgMed is not NULL, + // and the pUnkForRelease is non-null, otherwise there is no + // point in constructing this object. The tymed must also be + // one of the special ones. + + UserNdrAssert(pStgMed); + UserNdrAssert(pStgMed->tymed == TYMED_HGLOBAL || + pStgMed->tymed == TYMED_GDI || + pStgMed->tymed == TYMED_MFPICT || + pStgMed->tymed == TYMED_ENHMF); + + _pUnkForRelease = pStgMed->pUnkForRelease; +} + + +inline CPunkForRelease::~CPunkForRelease() +{ + // since we really have our own copies of these handles' data, just + // pretend like the callee is responsible for the release, and + // recurse into ReleaseStgMedium to do the cleanup. + + _stgmed.pUnkForRelease = NULL; + + // There is this weird optimized case of Chicago MFPICT when we have two + // layers with a HENHMETAFILE handle inside. Top layer is an HGLOBAL. + + if ( _fTopLayerMFP ) + GlobalFree( _stgmed.hGlobal ); + else + ReleaseStgMedium( &_stgmed ); + + // release the callers punk + _pUnkForRelease->Release(); +} + +STDMETHODIMP_(ULONG) CPunkForRelease::AddRef(void) +{ + InterlockedIncrement((LONG *)&_cRefs); + return _cRefs; +} + +STDMETHODIMP_(ULONG) CPunkForRelease::Release(void) +{ + long Ref = _cRefs - 1; + + UserNdrAssert( _cRefs ); + + if (InterlockedDecrement((LONG *)&_cRefs) == 0) + { + // null out the vtable. + long * p = (long *)this; + *p = 0; + + delete this; + return 0; + } + else + return Ref; +} + +STDMETHODIMP CPunkForRelease::QueryInterface(REFIID riid, void **ppv) +{ + if (IsEqualIID(riid, IID_IUnknown)) + { + *ppv = (void *)(IUnknown *) this; + AddRef(); + return S_OK; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } +} + + +// These methods are needed as the object is used for interface marshaling. + +/***************************************************************************/ +STDMETHODIMP_(ULONG) CStreamOnMessage::AddRef( THIS ) +{ + return ref_count += 1; +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Clone(THIS_ IStream * *ppstm) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Commit(THIS_ DWORD grfCommitFlags) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::CopyTo(THIS_ IStream *pstm, + ULARGE_INTEGER cb, + ULARGE_INTEGER *pcbRead, + ULARGE_INTEGER *pcbWritten) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +CStreamOnMessage::CStreamOnMessage(unsigned char **ppMessageBuffer) + : ref_count(1), ppBuffer(ppMessageBuffer), cbMaxStreamLength(0xFFFFFFFF) +{ + pStartOfStream = *ppMessageBuffer; +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::LockRegion(THIS_ ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown)) + { + *ppvObj = (IUnknown *) this; + ref_count += 1; + return ResultFromScode(S_OK); + } + else if (IsEqualIID(riid, IID_IStream)) + { + *ppvObj = (IStream *) this; + ref_count += 1; + return ResultFromScode(S_OK); + } + else + return ResultFromScode(E_NOINTERFACE); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Read(THIS_ VOID HUGEP *pv, + ULONG cb, ULONG *pcbRead) +{ + memcpy( pv, *ppBuffer, cb ); + *ppBuffer += cb; + if (pcbRead != NULL) + *pcbRead = cb; + return ResultFromScode(S_OK); +} + +/***************************************************************************/ +STDMETHODIMP_(ULONG) CStreamOnMessage::Release( THIS ) +{ + ref_count -= 1; + if (ref_count == 0) + { + delete this; + return 0; + } + else + return ref_count; + +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Revert(THIS) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Seek(THIS_ LARGE_INTEGER dlibMove, + DWORD dwOrigin, + ULARGE_INTEGER *plibNewPosition) +{ + ULONG pos; + + // Verify that the offset isn't out of range. + if (dlibMove.HighPart != 0) + return ResultFromScode( E_FAIL ); + + // Determine the new seek pointer. + switch (dwOrigin) + { + case STREAM_SEEK_SET: + pos = dlibMove.LowPart; + break; + + case STREAM_SEEK_CUR: + /* Must use signed math here. */ + pos = *ppBuffer - pStartOfStream; + if ((long) dlibMove.LowPart < 0 && + pos < (unsigned long) - (long) dlibMove.LowPart) + return ResultFromScode( E_FAIL ); + pos += (long) dlibMove.LowPart; + break; + + case STREAM_SEEK_END: + return ResultFromScode(E_NOTIMPL); + break; + + default: + return ResultFromScode( E_FAIL ); + } + + // Set the seek pointer. + *ppBuffer = pStartOfStream + pos; + if (plibNewPosition != NULL) + { + plibNewPosition->LowPart = pos; + plibNewPosition->HighPart = 0; + } + return ResultFromScode(S_OK); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::SetSize(THIS_ ULARGE_INTEGER libNewSize) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Stat(THIS_ STATSTG *pstatstg, DWORD grfStatFlag) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::UnlockRegion(THIS_ ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) +{ + return ResultFromScode(E_NOTIMPL); +} + +/***************************************************************************/ +STDMETHODIMP CStreamOnMessage::Write(THIS_ VOID const HUGEP *pv, + ULONG cb, + ULONG *pcbWritten) +{ + // Write the data. + memcpy( *ppBuffer, pv, cb ); + if (pcbWritten != NULL) + *pcbWritten = cb; + *ppBuffer += cb; + return ResultFromScode(S_OK); +} + + +//+------------------------------------------------------------------------- +// +// Function: CLIPFORMAT_UserSize +// +// Synopsis: Sizes a CLIPFORMAT. +// +// Derivation: A union of a long and a string. +// +// history: Feb-96 Ryszardk Created +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +CLIPFORMAT_UserSize( + unsigned long * pFlags, + unsigned long Offset, + CLIPFORMAT * pObject ) +{ + if ( !pObject ) + return( Offset ); + + // userCLIPFORMAT is an encapsulated union with a string. + + LENGTH_ALIGN( Offset, 3); + Offset += sizeof(long) + sizeof(void *); + + if ( REMOTE_CLIPFORMAT( pFlags, pObject ) ) + { + wchar_t temp[CLIPFORMAT_BUFFER_MAX]; + + int ret = GetClipboardFormatName( *pObject, + temp, + CLIPFORMAT_BUFFER_MAX - 1 ); + + if ( ret ) + { + Offset += 3 * sizeof(long) + ret * sizeof(wchar_t); + } + else + RpcRaiseException( DV_E_CLIPFORMAT ); + } + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: CLIPFORMAT_UserMarshal +// +// Synopsis: Marshals a CLIPFORMAT. +// +// Derivation: A union of a long and a string. +// +// history: Feb-96 Ryszardk Created +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +CLIPFORMAT_UserMarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + CLIPFORMAT * pObject ) +{ + if ( !pObject ) + return pBuffer; + + // userCLIPFORMAT is an encapsulated union with a string. + + ALIGN( pBuffer, 3); + + if ( REMOTE_CLIPFORMAT( pFlags, pObject ) ) + { + // sending a wide string + + unsigned long ret; + + // Custom clipformat is between c000 and ffff. + + *(PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject; + + // On Chicago this is GetClipboardFormatNameX. + // When the buffer is too short, this call would still + // return a decent, null terminated, truncated string. + // + + ret = (ulong) GetClipboardFormatName( *pObject, + (wchar_t *)(pBuffer + 12), + CLIPFORMAT_BUFFER_MAX - 1 + ) + 1; + + // conformat size etc. for string. + + *(PULONG_LV_CAST pBuffer)++ = ret; + *(PULONG_LV_CAST pBuffer)++ = 0; + *(PULONG_LV_CAST pBuffer)++ = ret; + + if ( ret ) + { + // skip the string in the bbuffer, including the terminator + + pBuffer += ret * sizeof(wchar_t); + } + else + RpcRaiseException( DV_E_CLIPFORMAT ); + } + else + { + // sending the number itself + + *(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject; + } + + return( pBuffer ); +} + + +//+------------------------------------------------------------------------- +// +// Function: CLIPFORMAT_UserUnmarshal +// +// Synopsis: Unmarshals a CLIPFORMAT; registers if needed. +// +// Derivation: A union of a long and a string. +// +// history: Feb-96 Ryszardk Created +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +CLIPFORMAT_UserUnmarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + CLIPFORMAT * pObject ) +{ + ulong UnionDisc; + UINT cf; + + ALIGN( pBuffer, 3); + + UnionDisc = *(PULONG_LV_CAST pBuffer)++; + cf = (WORD) *(PULONG_LV_CAST pBuffer)++; + + if ( WDT_DATA_MARKER == UnionDisc ) + { + ulong ConfSize = *(ulong*)pBuffer; + + // skip to the beginning of the string + + pBuffer += 3 * sizeof(long); + + // The string in the buffer terminates with null. + // + // On Chicago this is RegisterClipboardFormatX. + + cf = RegisterClipboardFormat( (wchar_t *)pBuffer ); + + if ( cf == 0 ) + RpcRaiseException( DV_E_CLIPFORMAT ); + + pBuffer += ConfSize * sizeof(wchar_t); + } + + *pObject = cf; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: CLIPFORMAT_UserUnmarshal +// +// Synopsis: Frees remnants of CLIPFORMAT. +// +// Derivation: A union of a long and a string. +// +// history: Feb-96 Ryszardk Created +// +//-------------------------------------------------------------------------- + +void __RPC_USER +CLIPFORMAT_UserFree( + unsigned long * pFlags, + CLIPFORMAT * pObject ) +{ + // Nothing to free, as nothing gets allocated when we unmarshal. +} + + + +//+------------------------------------------------------------------------- +// +// Function: SNB_UserSize +// +// Synopsis: Sizes an SNB. +// +// Derivation: An array of strings in one block of memory. +// +// history: June-95 Ryszardk Created, based on SNB_*_xmit. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +SNB_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + SNB * pSnb ) +{ + if ( ! pSnb ) + return Offset; + + // calculate the number of strings and characters (with their terminators) + + ULONG ulCntStr = 0; + ULONG ulCntChar = 0; + + if (pSnb && *pSnb) + { + SNB snb = *pSnb; + + WCHAR *psz = *snb; + while (psz) + { + ulCntChar += lstrlenW(psz) + 1; + ulCntStr++; + snb++; + psz = *snb; + } + } + + // The wire size is: conf size, 2 fields and the wchars. + + LENGTH_ALIGN( Offset, 3 ); + + return ( Offset + 3 * sizeof(long) + ulCntChar * sizeof( WCHAR ) ); +} + +//+------------------------------------------------------------------------- +// +// Function: SNB_UserMarshall +// +// Synopsis: Marshalls an SNB into the RPC buffer. +// +// Derivation: An array of strings in one block of memory. +// +// history: June-95 Ryszardk Created, based on SNB_*_xmit. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +SNB_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + SNB * pSnb ) +{ + UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n")); + + if ( ! pSnb ) + return pBuffer; + + // calculate the number of strings and characters (with their terminators) + + ULONG ulCntStr = 0; + ULONG ulCntChar = 0; + + if (pSnb && *pSnb) + { + SNB snb = *pSnb; + + WCHAR *psz = *snb; + while (psz) + { + ulCntChar += lstrlenW(psz) + 1; + ulCntStr++; + snb++; + psz = *snb; + } + } + + // conformant size + + ALIGN( pBuffer, 3 ); + *( PULONG_LV_CAST pBuffer)++ = ulCntChar; + + // fields + + *( PULONG_LV_CAST pBuffer)++ = ulCntStr; + *( PULONG_LV_CAST pBuffer)++ = ulCntChar; + + // actual strings only + + if ( pSnb && *pSnb ) + { + // There is a NULL string pointer to mark the end of the pointer array. + // However, the strings don't have to follow tightly. + // Hence, we have to copy one string at a time. + + SNB snb = *pSnb; + WCHAR *pszSrc; + + while (pszSrc = *snb++) + { + ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR); + + WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen ); + pBuffer += ulCopyLen; + } + } + + return pBuffer; +} + +//+------------------------------------------------------------------------- +// +// Function: SNB_UserUnmarshall +// +// Synopsis: Unmarshalls an SNB from the RPC buffer. +// +// Derivation: An array of strings in one block of memory. +// +// history: June-95 Ryszardk Created, based on SNB_*_xmit. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +SNB_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + SNB * pSnb ) +{ + UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n")); + + ALIGN( pBuffer, 3 ); + + // conf size + + unsigned long ulCntChar = *( PULONG_LV_CAST pBuffer)++; + + // fields + + unsigned long ulCntStr = *( PULONG_LV_CAST pBuffer)++; + pBuffer += sizeof(long); + + // no reusage of pSNB. + + if ( *pSnb ) + WdtpFree( pFlags, *pSnb ); + + if ( ulCntStr == 0 ) + { + *pSnb = NULL; + return pBuffer; + } + + // construct the SNB. + + SNB Snb = (SNB) WdtpAllocate( pFlags, + ( (ulCntStr + 1) * sizeof(WCHAR *) + + ulCntChar * sizeof(WCHAR)) ); + + *pSnb = Snb; + + if (Snb) + { + // create the pointer array within the SNB. + + WCHAR *pszSrc = (WCHAR *) pBuffer; + WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array + + for (ULONG i = ulCntStr; i > 0; i--) + { + *Snb++ = pszTgt; + + ULONG ulLen = lstrlenW(pszSrc) + 1; + pszSrc += ulLen; + pszTgt += ulLen; + } + + *Snb++ = NULL; + + // Copy the actual strings. + // We can do a block copy here as we packed them tight in the buffer. + // Snb points right behind the lastarray of pointers within the SNB. + + WdtpMemoryCopy( Snb, pBuffer, ulCntChar * sizeof(WCHAR) ); + pBuffer += ulCntChar * sizeof(WCHAR); + } + + return pBuffer; +} + +//+------------------------------------------------------------------------- +// +// Function: SNB_UserFree +// +// Synopsis: Frees an SNB. +// +// Derivation: An array of strings in one block of memory. +// +// history: June-95 Ryszardk Created, based on SNB_*_xmit. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +SNB_UserFree( + unsigned long * pFlags, + SNB * pSnb ) +{ + if ( pSnb && *pSnb ) + WdtpFree( pFlags, *pSnb ); +} + + +// ######################################################################### +// +// WdtpVoidStar helper +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: WdtpVoidStar_UserSize +// +// Synopsis: Sizes a remotable void star as ulong. +// +// history: June-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +WdtpVoidStar_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + unsigned long * pVoid ) +{ + if ( !pVoid ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + return( Offset + 4 ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpVoidStar_UserMarshall +// +// Synopsis: Marshalls a remotable void star as ulong. +// +// history: June-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpVoidStar_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + unsigned long * pVoid ) +{ + if ( !pVoid ) + return pBuffer; + + ALIGN( pBuffer, 3 ); + + *( PULONG_LV_CAST pBuffer)++ = *pVoid; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpVoidStar_UserUnmarshall +// +// Synopsis: Unmarshalls a remotable void star as ulong. +// +// history: June-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpVoidStar_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + unsigned long * pVoid ) +{ + ALIGN( pBuffer, 3 ); + + *pVoid= *( PULONG_LV_CAST pBuffer)++; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpVoidStar_UserFree +// +//-------------------------------------------------------------------------- + +void __RPC_USER +WdtpVoidStar_UserFree( + unsigned long * pFlags, + unsigned long * pVoid ) +{ +} + + +// ######################################################################### +// +// WdtpRemotableHandle helper +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: WdtpRemotableHandle_UserSize +// +// Synopsis: Sizes a void star handle as a union with ulong. +// +// history: Dec-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +WdtpRemotableHandle_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + unsigned long * pHandle ) +{ + if ( !pHandle ) + return Offset; + + if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) ) + RpcRaiseException( RPC_S_INVALID_TAG ); + + LENGTH_ALIGN( Offset, 3 ); + + return( Offset + 8 ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpRemotableHandle_UserMarshall +// +// Synopsis: Marshalls a handle a union with ulong. +// +// history: Dec-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpRemotableHandle_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + unsigned long * pHandle ) +{ + if ( !pHandle ) + return pBuffer; + + if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) ) + RpcRaiseException( RPC_S_INVALID_TAG ); + + ALIGN( pBuffer, 3 ); + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = *pHandle; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpRemotableHandle_UserUnmarshall +// +// Synopsis: Unmarshalls a remotable void star as union with ulong. +// +// history: Dec-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpRemotableHandle_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + unsigned long * pHandle ) +{ + unsigned long HandleMarker; + + ALIGN( pBuffer, 3 ); + + HandleMarker = *( PULONG_LV_CAST pBuffer)++; + + if ( HandleMarker == WDT_HANDLE_MARKER ) + *pHandle = *( PULONG_LV_CAST pBuffer)++; + else + RpcRaiseException( RPC_S_INVALID_TAG ); + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpRemotableHandle_UserFree +// +//-------------------------------------------------------------------------- + +void __RPC_USER +WdtpRemotableHandle_UserFree( + unsigned long * pFlags, + unsigned long * pHandle ) +{ +} + +//+------------------------------------------------------------------------- + +// +// Function: HWND_UserSize +// +// Synopsis: Sizes an HWND handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HWND_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HWND * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HWND_UserMarshall +// +// Synopsis: Marshalls an HWND handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HWND_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HWND * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HWND_UserUnmarshall +// +// Synopsis: Unmarshalls an HWND handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HWND_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HWND * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HWND_UserFree +// +// Synopsis: Shouldn't be called. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HWND_UserFree( + unsigned long * pFlags, + HWND * pH ) +{ +} + +//+------------------------------------------------------------------------- +// +// Function: HMENU_UserSize +// +// Synopsis: Sizes an HMENU handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HMENU_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HMENU * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMENU_UserMarshall +// +// Synopsis: Marshalls an HMENU handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMENU_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HMENU * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMENU_UserUnmarshall +// +// Synopsis: Unmarshalls an HMENU handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMENU_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HMENU * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMENU_UserFree +// +// Synopsis: Free an HMENU. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HMENU_UserFree( + unsigned long * pFlags, + HMENU * pH ) +{ +} + +//+------------------------------------------------------------------------- +// +// Function: HACCEL_UserSize +// +// Synopsis: Sizes an HACCEL handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HACCEL_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HACCEL * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HACCEL_UserMarshall +// +// Synopsis: Marshalls an HACCEL handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HACCEL_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HACCEL * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HACCEL_UserUnmarshall +// +// Synopsis: Unmarshalls an HACCEL handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HACCEL_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HACCEL * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HACCEL_UserFree +// +// Synopsis: Free an HACCEL. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HACCEL_UserFree( + unsigned long * pFlags, + HACCEL * pH ) +{ +} + +//+------------------------------------------------------------------------- +// +// Function: HBRUSH_UserSize +// +// Synopsis: Sizes an HBRUSH handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HBRUSH_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HBRUSH * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HBRUSH_UserMarshall +// +// Synopsis: Marshalls an HBRUSH handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HBRUSH_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HBRUSH * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HBRUSH_UserUnmarshall +// +// Synopsis: Unmarshalls an HBRUSH handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HBRUSH_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HBRUSH * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HBRUSH_UserFree +// +// Synopsis: Free an HBRUSH. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HBRUSH_UserFree( + unsigned long * pFlags, + HBRUSH * pH ) +{ +} + +//+------------------------------------------------------------------------- +// +// Function: HICON_UserSize +// +// Synopsis: Sizes an HICON handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HICON_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HICON * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HICON_UserMarshall +// +// Synopsis: Marshalls an HICON handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HICON_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HICON * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HICON_UserUnmarshall +// +// Synopsis: Unmarshalls an HICON handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HICON_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HICON * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HICON_UserFree +// +// Synopsis: Free an HICON. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HICON_UserFree( + unsigned long * pFlags, + HICON * pH ) +{ +} + + +// ######################################################################### +// +// HGLOBAL. +// See transmit.h for explanation of global data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HGLOBAL_UserSize +// +// Synopsis: Get the wire size the HGLOBAL handle and data. +// +// Derivation: Conformant struct with a flag field: +// align + 12 + data size. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HGLOBAL_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HGLOBAL * pGlobal) +{ + if ( !pGlobal ) + return Offset; + + // userHGLOBAL: the encapsulated union. + // Discriminant and then handle or pointer from the union arm. + + LENGTH_ALIGN( Offset, 3 ); + + Offset += sizeof(long) + sizeof(void*); + + if ( ! *pGlobal ) + return Offset; + + if ( HGLOBAL_DATA_PASSING(*pFlags) ) + { + unsigned long ulDataSize = GlobalSize( *pGlobal ); + + Offset += 3 * sizeof(long) + ulDataSize; + } + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: HGLOBAL_UserMarshall +// +// Synopsis: Marshalls an HGLOBAL object into the RPC buffer. +// +// Derivation: Conformant struct with a flag field: +// align, size, null flag, size, data (bytes, if any) +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HGLOBAL_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HGLOBAL * pGlobal) +{ + if ( !pGlobal ) + return pBuffer; + + // We marshal a null handle, too. + + UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( HGLOBAL_DATA_PASSING(*pFlags) ) + { + unsigned long ulDataSize; + + // userHGLOBAL + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pGlobal; + + if ( ! *pGlobal ) + return pBuffer; + + // FLAGGED_BYTE_BLOB + + ulDataSize = GlobalSize( *pGlobal ); + + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + + // Handle is the non-null flag + + *( PULONG_LV_CAST pBuffer)++ = (ulong)*pGlobal; + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + + if( ulDataSize ) + { + void * pData = GlobalLock( *pGlobal); + memcpy( pBuffer, pData, ulDataSize ); + GlobalUnlock( *pGlobal); + } + + pBuffer += ulDataSize; + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pGlobal; + } + + return( pBuffer ); +} + + +//+------------------------------------------------------------------------- +// +// Function: WdtpGlobalUnmarshal +// +// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer. +// +// Derivation: Conformant struct with a flag field: +// align, size, null flag, size, data (bytes, if any) +// +// Note: Reallocation is forbidden when the hglobal is part of +// an [in,out] STGMEDIUM in IDataObject::GetDataHere. +// This affects only data passing with old handles being +// non null. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpGlobalUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HGLOBAL * pGlobal, + BOOL fCanReallocate ) +{ + unsigned long ulDataSize, fHandle, UnionDisc; + HGLOBAL hGlobal; + + ALIGN( pBuffer, 3 ); + + UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hGlobal = (HGLOBAL) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + if ( ! hGlobal ) + { + if ( *pGlobal ) + GlobalFree( *pGlobal ); + *pGlobal = NULL; + return pBuffer; + } + + // There is a handle data on wire. + + ulDataSize = *( PULONG_LV_CAST pBuffer)++; + // fhandle and data size again. + pBuffer += 8; + + if ( *pGlobal ) + { + // Check for reallocation + + if ( GlobalSize( *pGlobal ) == ulDataSize ) + hGlobal = *pGlobal; + else + { + if ( fCanReallocate ) + { + // hGlobal = GlobalReAlloc( *pGlobal, ulDataSize, GMEM_MOVEABLE ); + + GlobalFree( *pGlobal ); + hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize ); + } + else + { + if ( GlobalSize(*pGlobal) < ulDataSize ) + RpcRaiseException( STG_E_MEDIUMFULL ); + else + hGlobal = *pGlobal; + } + } + } + else + { + // allocate a new block + + hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize ); + } + + if ( hGlobal == NULL ) + RpcRaiseException(E_OUTOFMEMORY); + else + { + void * pData = GlobalLock( hGlobal); + memcpy( pData, pBuffer, ulDataSize ); + pBuffer += ulDataSize; + GlobalUnlock( hGlobal); + } + } + else + { + // Sending a handle only. + // Reallocation problem doesn't apply to handle passing. + + if ( *pGlobal != hGlobal && *pGlobal ) + GlobalFree( *pGlobal ); + } + + *pGlobal = hGlobal; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HGLOBAL_UserUnmarshall +// +// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer. +// +// Derivation: Conformant struct with a flag field: +// align, size, null flag, size, data (bytes, if any) +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HGLOBAL_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HGLOBAL * pGlobal) +{ + return( WdtpGlobalUnmarshal( pFlags, + pBuffer, + pGlobal, + TRUE ) ); // reallocation possible +} + +//+------------------------------------------------------------------------- +// +// Function: HGLOBAL_UserFree +// +// Synopsis: Free an HGLOBAL. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HGLOBAL_UserFree( + unsigned long * pFlags, + HGLOBAL * pGlobal) +{ + if( pGlobal && *pGlobal ) + { + if ( HGLOBAL_DATA_PASSING(*pFlags) ) + GlobalFree( *pGlobal); + } +} + + +// ######################################################################### +// +// HMETAFILEPICT +// See transmit.h for explanation of hglobal vs. gdi data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILEPICT_UserSize +// +// Synopsis: Get the wire size the HMETAFILEPICT handle and data. +// +// Derivation: Union of a long and the meta file pict handle. +// Then struct with top layer (and a hmetafile handle). +// The the representation of the metafile. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HMETAFILEPICT_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HMETAFILEPICT * pHMetaFilePict ) +{ + if ( !pHMetaFilePict ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + // Discriminant of the encapsulated union and the union arm. + + Offset += 8; + + if ( ! *pHMetaFilePict ) + return Offset; + + if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) + return Offset; + + // Now, this is a two layer object with HGLOBAL on top. + // Upper layer - hglobal part - needs to be sent as data. + + METAFILEPICT * + pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); + + if ( pMFP == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + // Upper layer: 3 long fields + ptr marker + enc. union + + Offset += 4 * sizeof(long) + sizeof(userHMETAFILE); + + // The lower part is a metafile handle. + + if ( GDI_DATA_PASSING( *pFlags) ) + { + ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); + + Offset += 12 + ulDataSize; + } + + GlobalUnlock( *(HANDLE *)pHMetaFilePict ); + + return( Offset ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILEPICT_UserMarshal +// +// Synopsis: Marshalls an HMETAFILEPICT object into the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMETAFILEPICT_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HMETAFILEPICT * pHMetaFilePict ) +{ + if ( !pHMetaFilePict ) + return pBuffer; + + UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) + { + // Sending only the top level global handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong)*(HANDLE*)pHMetaFilePict; + + return pBuffer; + } + + // userHMETAFILEPICT + // We need to send the data from the top (hglobal) layer. + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong)*pHMetaFilePict; + + if ( ! *pHMetaFilePict ) + return pBuffer; + + // remoteHMETAFILEPICT + + METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( + *(HANDLE *)pHMetaFilePict ); + if ( pMFP == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + *( PULONG_LV_CAST pBuffer)++ = pMFP->mm; + *( PULONG_LV_CAST pBuffer)++ = pMFP->xExt; + *( PULONG_LV_CAST pBuffer)++ = pMFP->yExt; + *( PULONG_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER; + + // See if the HMETAFILE needs to be sent as data, too. + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // userHMETAFILE + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) pMFP->hMF; + + if ( pMFP->hMF ) + { + ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL ); + + // conformant size then the size field + + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + + GetMetaFileBitsEx( pMFP->hMF, ulDataSize , pBuffer ); + + pBuffer += ulDataSize; + }; + } + else + { + // Sending only an HMETAFILE handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) pMFP->hMF; + } + + GlobalUnlock( *(HANDLE *)pHMetaFilePict ); + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILEPICT_UserUnmarshal +// +// Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMETAFILEPICT_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBufferStart, + HMETAFILEPICT * pHMetaFilePict ) +{ + unsigned long ulDataSize, fHandle; + unsigned char * pBuffer; + HMETAFILEPICT hMetaFilePict; + + UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserUnmarshal\n")); + + pBuffer = pBufferStart; + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hMetaFilePict = (HMETAFILEPICT) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) && hMetaFilePict ) + { + unsigned long PtrMarker; + + HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) ); + hMetaFilePict = (HMETAFILEPICT) hGlobal; + + if ( hMetaFilePict == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock( + (HANDLE) hMetaFilePict ); + if ( pMFP == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + pMFP->mm = *( PULONG_LV_CAST pBuffer)++; + pMFP->xExt = *( PULONG_LV_CAST pBuffer)++; + pMFP->yExt = *( PULONG_LV_CAST pBuffer)++; + PtrMarker = *( PULONG_LV_CAST pBuffer)++; // skip marker + + UnionDisc = *( PULONG_LV_CAST pBuffer)++; + pMFP->hMF = (HMETAFILE) *( PULONG_LV_CAST pBuffer)++; + + if ( pMFP->hMF && IS_DATA_MARKER( UnionDisc ) ) + { + // conformant size then the size field + + ulong ulDataSize = *( PULONG_LV_CAST pBuffer)++; + pBuffer += 4; + + pMFP->hMF = SetMetaFileBitsEx( ulDataSize, (uchar*)pBuffer ); + + pBuffer += ulDataSize; + } + + GlobalUnlock( (HANDLE) hMetaFilePict ); + } + + // no reusage, just release the previous one. + + if ( *pHMetaFilePict ) + { + // This may happen on the client only and doesn't depend on + // how the other one was passed. + + METAFILEPICT * + pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); + + if ( pMFP == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + if ( pMFP->hMF ) + DeleteMetaFile( pMFP->hMF ); + + GlobalUnlock( *pHMetaFilePict ); + GlobalFree( *pHMetaFilePict ); + } + + *pHMetaFilePict = hMetaFilePict; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILEPICT_UserFree +// +// Synopsis: Free an HMETAFILEPICT. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HMETAFILEPICT_UserFree( + unsigned long * pFlags, + HMETAFILEPICT * pHMetaFilePict ) +{ + UserNdrDebugOut((UNDR_FORCE, "HMETAFILEPICT_UserFree\n")); + + if( pHMetaFilePict && *pHMetaFilePict ) + { + if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) + return; + + // Need to free the upper hglobal part. + + METAFILEPICT * + pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict ); + + if ( pMFP == NULL ) + RpcRaiseException( E_OUTOFMEMORY ); + + // See if we need to free the hglobal, too. + + if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) ) + DeleteMetaFile( pMFP->hMF ); + + GlobalUnlock( *pHMetaFilePict ); + GlobalFree( *pHMetaFilePict ); + } +} + + + +// ######################################################################### +// +// HENHMETAFILE +// See transmit.h for explanation of gdi data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HENHMETAFILE_UserSize +// +// Synopsis: Get the wire size the HENHMETAFILE handle and data. +// +// Derivation: Union of a long and the meta file handle and then struct. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HENHMETAFILE_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HENHMETAFILE * pHEnhMetafile ) +{ + if ( !pHEnhMetafile ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + // The encapsulated union. + // Discriminant and then handle or pointer from the union arm. + + Offset += sizeof(long) + sizeof(void*); + + if ( ! *pHEnhMetafile ) + return Offset; + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // Pointee of the union arm for the remote case. + // Byte blob : conformant size, size field, data + + Offset += 2 * sizeof(long); + + ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); + Offset += ulDataSize; + } + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: HENHMETAFILE_UserMarshall +// +// Synopsis: Marshalls an HENHMETAFILE object into the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HENHMETAFILE_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HENHMETAFILE * pHEnhMetafile ) +{ + if ( !pHEnhMetafile ) + return pBuffer; + + UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // userHENHMETAFILE + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHEnhMetafile; + + if ( !*pHEnhMetafile ) + return pBuffer; + + // BYTE_BLOB: conformant size, size field, data + + ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL ); + + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + + if ( 0 == GetEnhMetaFileBits( *pHEnhMetafile, + ulDataSize, + (uchar*)pBuffer ) ) + RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); + + pBuffer += ulDataSize; + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHEnhMetafile; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HENHMETAFILE_UserUnmarshall +// +// Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HENHMETAFILE_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HENHMETAFILE * pHEnhMetafile ) +{ + HENHMETAFILE hEnhMetafile; + + UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserUnmarshal\n")); + + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hEnhMetafile = (HENHMETAFILE) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + if ( hEnhMetafile ) + { + // Byte blob : conformant size, size field, data + + ulong ulDataSize = *(ulong*)pBuffer; + pBuffer += 8; + hEnhMetafile = SetEnhMetaFileBits( ulDataSize, (uchar*) pBuffer ); + pBuffer += ulDataSize; + } + } + + // No reusage of the old object. + + if (*pHEnhMetafile) + DeleteEnhMetaFile( *pHEnhMetafile ); + + *pHEnhMetafile = hEnhMetafile; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HENHMETAFILE_UserFree +// +// Synopsis: Free an HENHMETAFILE. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HENHMETAFILE_UserFree( + unsigned long * pFlags, + HENHMETAFILE * pHEnhMetafile ) +{ + UserNdrDebugOut((UNDR_FORCE, "HENHMETAFILE_UserFree\n")); + + if( pHEnhMetafile && *pHEnhMetafile ) + { + if ( GDI_DATA_PASSING(*pFlags) ) + { + DeleteEnhMetaFile( *pHEnhMetafile ); + } + } +} + + +// ######################################################################### +// +// HMETAFILE +// See transmit.h for explanation of gdi data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILE_UserSize +// +// Synopsis: Get the wire size the HMETAFILE handle and data. +// +// Derivation: Same wire layout as HENHMETAFILE +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HMETAFILE_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HMETAFILE * pHMetafile ) +{ + if ( !pHMetafile ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + // The encapsulated union. + // Discriminant and then handle or pointer from the union arm. + + Offset += sizeof(long) + sizeof(void*); + + if ( ! *pHMetafile ) + return Offset; + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // Pointee of the union arm for the remote case. + // Byte blob : conformant size, size field, data + + Offset += 2 * sizeof(long); + + ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); + Offset += ulDataSize; + } + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILE_UserMarshal +// +// Synopsis: Marshals an HMETAFILE object into the RPC buffer. +// +// Derivation: Same wire layout as HENHMETAFILE +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMETAFILE_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HMETAFILE * pHMetafile ) +{ + if ( !pHMetafile ) + return pBuffer; + + UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // userHMETAFILE + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHMetafile; + + if ( !*pHMetafile ) + return pBuffer; + + // BYTE_BLOB: conformant size, size field, data + + ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL ); + + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + *( PULONG_LV_CAST pBuffer)++ = ulDataSize; + + if ( 0 == GetMetaFileBitsEx( *pHMetafile, + ulDataSize, + (uchar*)pBuffer ) ) + RpcRaiseException( HRESULT_FROM_WIN32(GetLastError())); + + pBuffer += ulDataSize; + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHMetafile; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILE_UserUnmarshal +// +// Synopsis: Unmarshalls an HMETAFILE object from the RPC buffer. +// +// Derivation: Same wire layout as HENHMETAFILE +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HMETAFILE_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HMETAFILE * pHMetafile ) +{ + HMETAFILE hMetafile; + + UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserUnmarshal\n")); + + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hMetafile = (HMETAFILE) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + if ( hMetafile ) + { + // Byte blob : conformant size, size field, data + + ulong ulDataSize = *(ulong*)pBuffer; + pBuffer += 8; + hMetafile = SetMetaFileBitsEx( ulDataSize, (uchar*) pBuffer ); + pBuffer += ulDataSize; + } + } + + // No reusage of the old object. + + if (*pHMetafile) + DeleteMetaFile( *pHMetafile ); + + *pHMetafile = hMetafile; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HMETAFILE_UserFree +// +// Synopsis: Free an HMETAFILE. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HMETAFILE_UserFree( + unsigned long * pFlags, + HMETAFILE * pHMetafile ) +{ + UserNdrDebugOut((UNDR_FORCE, "HMETAFILE_UserFree\n")); + + if( pHMetafile && *pHMetafile ) + { + if ( GDI_DATA_PASSING(*pFlags) ) + { + DeleteMetaFile( *pHMetafile ); + } + } +} + + +// ######################################################################### +// +// HBITMAP +// See transmit.h for explanation of gdi data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HBITMAP_UserSize +// +// Synopsis: Get the wire size the HBITMAP handle and data. +// +// Derivation: Union of a long and the bitmap handle and then struct. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HBITMAP_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HBITMAP * pHBitmap ) +{ + if ( !pHBitmap ) + return Offset; + + BITMAP bm; + HBITMAP hBitmap = *pHBitmap; + + LENGTH_ALIGN( Offset, 3 ); + + // The encapsulated union. + // Discriminant and then handle or pointer from the union arm. + + Offset += sizeof(long) + sizeof(void*); + + if ( ! *pHBitmap ) + return Offset; + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // Pointee of the union arm for the remote case. + // Conformat size, 6 fields, size, conf array. + + Offset += 4 + 4 * sizeof(LONG) + 2 * sizeof(WORD) + 4; + + // Get information about the bitmap + + #if defined(_CHICAGO_) + if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm)) + #else + if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm)) + #endif + { + RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); + } + + ULONG ulDataSize = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes; + + Offset += ulDataSize; + } + + return( Offset ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: HBITMAP_UserMarshall +// +// Synopsis: Marshalls an HBITMAP object into the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HBITMAP_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HBITMAP * pHBitmap ) +{ + if ( !pHBitmap ) + return pBuffer; + + UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // userHBITMAP + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHBitmap; + + if ( ! *pHBitmap ) + return pBuffer; + + // Get information about the bitmap + + BITMAP bm; + HBITMAP hBitmap = *pHBitmap; + + #if defined(_CHICAGO_) + if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm)) + #else + if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm)) + #endif + { + RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); + } + + DWORD dwCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes; + + *( PULONG_LV_CAST pBuffer)++ = dwCount; + + // Get the bm structure fields. + + ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD ); + + memcpy( pBuffer, (void *) &bm, ulBmSize ); + pBuffer += ulBmSize; + + // Get the raw bits. + + if (0 == GetBitmapBits( hBitmap, dwCount, pBuffer ) ) + { + RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); + } + pBuffer += dwCount; + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHBitmap; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HBITMAP_UserUnmarshall +// +// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HBITMAP_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HBITMAP * pHBitmap ) +{ + HBITMAP hBitmap; + + UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserUnmarshal\n")); + + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hBitmap = (HBITMAP) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + if ( hBitmap ) + { + DWORD dwCount = *( PULONG_LV_CAST pBuffer)++; + BITMAP * pBm = (BITMAP *) pBuffer; + + ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD ); + + pBuffer += ulBmSize; + + // Create a bitmap based on the BITMAP structure and the raw bits in + // the transmission buffer + + hBitmap = CreateBitmap( pBm->bmWidth, + pBm->bmHeight, + pBm->bmPlanes, + pBm->bmBitsPixel, + pBuffer ); + + pBuffer += dwCount; + } + } + + // A new bitmap handle is ready, destroy the old one, if needed. + + if ( *pHBitmap ) + DeleteObject( *pHBitmap ); + + *pHBitmap = hBitmap; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HBITMAP_UserFree +// +// Synopsis: Free an HBITMAP. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HBITMAP_UserFree( + unsigned long * pFlags, + HBITMAP * pHBitmap ) +{ + UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserFree\n")); + + if( pHBitmap && *pHBitmap ) + { + if ( GDI_DATA_PASSING(*pFlags) ) + { + DeleteObject( *pHBitmap ); + } + } +} + + +// ######################################################################### +// +// HPALETTE +// See transmit.h for explanation of gdi data/handle passing. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: HPALETTE_UserSize +// +// Synopsis: Get the wire size the HPALETTE handle and data. +// +// Derivation: Union of a long and the hpalette handle. +// Then the struct represents hpalette. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HPALETTE_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HPALETTE * pHPalette ) +{ + if ( !pHPalette ) + return Offset; + + BITMAP bm; + + LENGTH_ALIGN( Offset, 3 ); + + // The encapsulated union. + // Discriminant and then handle or pointer from the union arm. + + Offset += sizeof(long) + sizeof(void*); + + if ( ! *pHPalette ) + return Offset; + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // Conformat struct with version and size and conf array of entries. + + Offset += sizeof(long) + 2 * sizeof(short); + + // Determine the number of color entries in the palette + + DWORD cEntries = GetPaletteEntries(*pHPalette, 0, 0, NULL); + + Offset += cEntries * sizeof(PALETTEENTRY); + } + + return( Offset ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: HPALETTE_UserMarshall +// +// Synopsis: Marshalls an HPALETTE object into the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HPALETTE_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HPALETTE * pHPalette ) +{ + if ( !pHPalette ) + return pBuffer; + + UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserMarshal\n")); + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( GDI_DATA_PASSING(*pFlags) ) + { + // userHPALETTE + + *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHPalette; + + if ( ! *pHPalette ) + return pBuffer; + + // rpcLOGPALETTE + // Logpalette is a conformant struct with a version field, + // size filed and conformant array of palentries. + + // Determine the number of color entries in the palette + + DWORD cEntries = GetPaletteEntries(*pHPalette, 0, 0, NULL); + + // Conformant size + + *( PULONG_LV_CAST pBuffer)++ = cEntries; + + // Fields: both are short! + // The old code was just setting the version number. + // They say it has to be that way. + + *( PUSHORT_LV_CAST pBuffer)++ = (ushort) 0x300; + *( PUSHORT_LV_CAST pBuffer)++ = (ushort) cEntries; + + // Entries: each entry is a struct with 4 bytes. + // Calculate the resultant data size + + DWORD cbData = cEntries * sizeof(PALETTEENTRY); + + if (cbData) + { + if (0 == GetPaletteEntries( *pHPalette, + 0, + cEntries, + (PALETTEENTRY *)pBuffer ) ) + { + RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); + } + pBuffer += cbData; + } + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHPalette; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HPALETTE_UserUnmarshall +// +// Synopsis: Unmarshalls an HPALETTE object from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HPALETTE_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HPALETTE * pHPalette ) +{ + HPALETTE hPalette; + + UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserUnmarshal\n")); + + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + hPalette = (HPALETTE) *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + if ( hPalette ) + { + // Get the conformant size. + + DWORD cEntries = *( PULONG_LV_CAST pBuffer)++; + LOGPALETTE * pLogPal; + + // If there are 0 color entries, we need to allocate the LOGPALETTE + // structure with the one dummy entry (it's a variably sized struct). + // Otherwise, we need to allocate enough space for the extra n-1 + // entries at the tail of the structure + + if (0 == cEntries) + { + pLogPal = (LOGPALETTE *) WdtpAllocate( pFlags, + sizeof(LOGPALETTE)); + } + else + { + pLogPal = (LOGPALETTE *) + WdtpAllocate( pFlags, + sizeof(LOGPALETTE) + + (cEntries - 1) * sizeof(PALETTEENTRY)); + } + + pLogPal->palVersion = *( PUSHORT_LV_CAST pBuffer)++; + pLogPal->palNumEntries = *( PUSHORT_LV_CAST pBuffer)++; + + // If there are entries, move them into out LOGPALETTE structure + + if (cEntries) + { + memcpy( &(pLogPal->palPalEntry[0]), + pBuffer, + cEntries * sizeof(PALETTEENTRY) ); + pBuffer += cEntries * sizeof(PALETTEENTRY); + } + + // Attempt to create the palette + + hPalette = CreatePalette(pLogPal); + + // Success or failure, we're done with the LOGPALETTE structure + + WdtpFree( pFlags, pLogPal ); + + // If the creation failed, raise an exception + + if (NULL == hPalette) + { + RpcRaiseException(HRESULT_FROM_WIN32(GetLastError())); + } + } + } + + // A new palette is ready, destroy the old one, if needed. + + if ( *pHPalette ) + DeleteObject( *pHPalette ); + + *pHPalette = hPalette; + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: HPALETTE_UserFree +// +// Synopsis: Free an HPALETTE. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HPALETTE_UserFree( + unsigned long * pFlags, + HPALETTE * pHPalette ) +{ + UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserFree\n")); + + if( pHPalette && *pHPalette ) + { + if ( GDI_DATA_PASSING(*pFlags) ) + { + DeleteObject( *pHPalette ); + } + } +} + + +// ######################################################################### +// +// NON REMOTABLE GDI and other HANDLES +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: WdtpNonRemotableHandle_UserSize +// +// Synopsis: Get the wire size for a non remotable GDI handle. +// +// Derivation: Union of a long and nothing. +// It is union just in case some remoting is needed. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +WdtpNonRemotableHandle_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HANDLE * pHandle ) +{ + if ( !pHandle || *pHandle == NULL ) + return Offset; + + if ( HGLOBAL_DATA_PASSING(*pFlags) ) + RpcRaiseException(E_INVALIDARG ); + + LENGTH_ALIGN( Offset, 3 ); + + // The encapsulated union. + // No remote case on any platform. + + return( Offset + 8 ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpNonRemotableHandle_UserMarshal +// +// Synopsis: Marshalls a non-remotable handle into the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpNonRemotableHandle_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HANDLE * pHandle ) +{ + if ( !pHandle || *pHandle == NULL ) + return pBuffer; + + ALIGN( pBuffer, 3 ); + + // Discriminant of the encapsulated union and union arm. + + if ( HGLOBAL_DATA_PASSING(*pFlags) ) + { + RpcRaiseException(E_INVALIDARG ); + } + else + { + // Sending a handle. + + *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER; + *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHandle; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpNonRemotableHandle_UserUnmarshal +// +// Synopsis: Unmarshalls a non-remotable handle from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpNonRemotableHandle_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HANDLE * pHandle ) +{ + ALIGN( pBuffer, 3 ); + + unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++; + + if ( IS_DATA_MARKER( UnionDisc) ) + { + RpcRaiseException(E_INVALIDARG ); + } + else + { + // Sending a handle. + + *pHandle = (HANDLE) *( PULONG_LV_CAST pBuffer)++; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpNonRemotableHandle_UserFree +// +// Synopsis: Nothing to free. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +WdtpNonRemotableGdiHandle_UserFree( + unsigned long * pFlags, + HANDLE * pHandle ) +{ +} + + + +// ######################################################################### +// +// Interface pointers. +// +// ######################################################################### + +//+------------------------------------------------------------------------- +// +// Function: WdtpInterfacePointer_UserSize +// +// Synopsis: Get the wire size for an interface pointer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +WdtpInterfacePointer_UserSize ( + USER_MARSHAL_CB * pContext, + unsigned long Flags, + unsigned long Offset, + IUnknown * pIf, + const IID & IId ) +{ + if ( pIf ) + { + LENGTH_ALIGN( Offset, 3 ); + + //Leave space for array bounds and length + + Offset += 2 * sizeof(long); + + HRESULT hr; + unsigned long cbSize = 0; + + hr = CoGetMarshalSizeMax( &cbSize, + IId, + pIf, + USER_CALL_CTXT_MASK( Flags ), + pContext->pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL ); + if ( FAILED(hr) ) + RpcRaiseException( hr ); + + Offset += cbSize; + } + + return( Offset ) ; +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpInterfacePointer_UserMarshal +// +// Synopsis: Marshalls an interface pointer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpInterfacePointer_UserMarshal ( + USER_MARSHAL_CB * pContext, + unsigned long Flags, + unsigned char * pBuffer, + IUnknown * pIf, + const IID & IId ) +{ + unsigned long * pMaxCount, *pSize; + unsigned long cbData = 0; + + UserNdrDebugOut((UNDR_OUT1, "WdtpInterface_PointerMarshal\n")); + + if ( pIf ) + { + // Always marshaled because of the apartment model. + + CStreamOnMessage MemStream( (unsigned char **) &pBuffer ); + + ALIGN( pBuffer, 3 ); + + pMaxCount = (unsigned long *) pBuffer; + pBuffer += 4; + + // Leave space for length + + pSize = (unsigned long *) pBuffer; + pBuffer += 4; + + HRESULT hr; + unsigned char * pBufferMark = pBuffer; + + hr = CoMarshalInterface( &MemStream, + IId, + pIf, + USER_CALL_CTXT_MASK( Flags ), + pContext->pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL ); + if( FAILED(hr) ) + { + RpcRaiseException(hr); + } + + // Calculate the size of the data written + + DWORD cbData = pBuffer - pBufferMark; + + // Update the array bounds. + + *pMaxCount = cbData; + *pSize = cbData; + } + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpInterfacePointer_UserUnmarshal +// +// Synopsis: Unmarshalls an interface pointer from the RPC buffer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +WdtpInterfacePointer_UserUnmarshal ( + USER_MARSHAL_CB * pContext, + unsigned char * pBuffer, + IUnknown ** ppIf, + const IID & IId ) +{ + unsigned long *pMaxCount, *pSize; + unsigned long cbData = 0; + + UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointerUnmarshal\n")); + + // Always unmarshaled because of the apartment model. + + CStreamOnMessage MemStream((unsigned char **) &pBuffer); + + ALIGN( pBuffer, 3 ); + + pMaxCount = (unsigned long *) pBuffer; + pBuffer += sizeof(long); + + //Unmarshal count + pSize = (unsigned long *) pBuffer; + pBuffer += sizeof(long); + + // Release the old pointer after unmarshalling the new one + // to prevent object from getting released too early. + // Then release the old one only when successful. + + IUnknown * punkTemp = 0; + + HRESULT hr = CoUnmarshalInterface( &MemStream, + IId, + (void **) &punkTemp ); + if(FAILED(hr)) + RpcRaiseException(hr); + else + { + // On the client side, release the [in,out] interface pointer. + // The pointer may be different from NULL only on the client side. + + // release the old one, keep the new one. + + if ( *ppIf ) + (*ppIf)->Release(); + *ppIf = punkTemp; + } + + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: WdtpInterfacePointer_UserFree +// +// Synopsis: Releases an interface pointer. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +WdtpInterfacePointer_UserFree( + IUnknown * pIf ) +{ + UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointer_UserFree\n")); + + if( pIf ) + { + pIf->Release(); + } +} + + + +//+------------------------------------------------------------------------- +// +// Function: STGMEDIUM_UserSize +// +// Synopsis: Sizes a stgmedium pbject for RPC marshalling. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +STGMEDIUM_UserSize( + unsigned long * pFlags, + unsigned long Offset, + STGMEDIUM * pStgmed ) +{ + if ( ! pStgmed ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + if ( pStgmed->tymed == TYMED_NULL ) + Offset += sizeof(long) + sizeof(void*); // switch, (empty arm), pUnk + else + Offset += sizeof(long) + 2 * sizeof(void*); // switch, handle, pUnk + + // Pointee of the union arm. + // Only if the handle/pointer field is non-null. + + if ( pStgmed->hGlobal ) + { + switch( pStgmed->tymed ) + { + case TYMED_NULL: + break; + case TYMED_MFPICT: + Offset = HMETAFILEPICT_UserSize( pFlags, + Offset, + &pStgmed->hMetaFilePict ); + break; + case TYMED_ENHMF: + Offset = HENHMETAFILE_UserSize( pFlags, + Offset, + &pStgmed->hEnhMetaFile ); + break; + case TYMED_GDI: + + // A GDI object is not necesarrily a BITMAP. Therefore, we handle + // those types we know about based on the object type, and reject + // those which we do not support. + + // switch for object type. + + Offset += sizeof(long); + + switch( GetObjectType( (HGDIOBJ)pStgmed->hBitmap ) ) + { + case OBJ_BITMAP: + Offset = HBITMAP_UserSize( pFlags, + Offset, + &pStgmed->hBitmap ); + break; + + case OBJ_PAL: + Offset = HPALETTE_UserSize( pFlags, + Offset, + (HPALETTE *) & pStgmed->hBitmap ); + break; + + default: + RpcRaiseException(DV_E_TYMED); + break; + } + break; + + case TYMED_HGLOBAL: + Offset = HGLOBAL_UserSize( pFlags, + Offset, + &pStgmed->hGlobal ); + break; + case TYMED_FILE: + { + ulong ulDataSize = lstrlenW(pStgmed->lpszFileName) + 1; + Offset += 3 * sizeof(long); // [string] + Offset += ulDataSize * sizeof(wchar_t); + } + break; + + case TYMED_ISTREAM: + case TYMED_ISTORAGE: + // Note, that we have to set the local flag for backward + // compatibility. + + Offset = WdtpInterfacePointer_UserSize( + (USER_MARSHAL_CB *)pFlags, + *pFlags, + Offset, + pStgmed->pstg, + ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream + : IID_IStorage)); + break; + + default: + break; + + } + } + + // pUnkForRelease, if not null. + + if ( pStgmed->pUnkForRelease ) + Offset = WdtpInterfacePointer_UserSize( (USER_MARSHAL_CB *)pFlags, + *pFlags, + Offset, + pStgmed->pUnkForRelease, + IID_IUnknown ); + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: STGMEDIUM_UserMarshal +// +// Synopsis: Marshals a stgmedium pbject for RPC. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +STGMEDIUM_UserMarshal( + unsigned long * pFlags, + unsigned char * pBufferStart, + STGMEDIUM * pStgmed ) +{ + unsigned char * pBuffer; + unsigned char * pUnionArmMark; + + if ( ! pStgmed ) + return pBufferStart; + + UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserMarshal: %s\n", WdtpGetStgmedName(pStgmed))); + + pBuffer = pBufferStart; + ALIGN( pBuffer, 3 ); + + // userSTGMEDIUM: switch, union arm, pUnk ptr. + + *( PULONG_LV_CAST pBuffer)++ = pStgmed->tymed; + pUnionArmMark = pBuffer; + if ( pStgmed->tymed != TYMED_NULL ) + { + // hGlobal stands for any of these handles. + + *( PULONG_LV_CAST pBuffer)++ = (ulong)pStgmed->hGlobal; + } + + *( PULONG_LV_CAST pBuffer)++ = (ulong)pStgmed->pUnkForRelease; + + // Now the pointee of the union arm. + // We need to marshal only if the handle/pointer field is non null. + // Otherwise it is already in the buffer. + + if ( pStgmed->hGlobal ) + { + switch( pStgmed->tymed ) + { + case TYMED_NULL: + break; + case TYMED_MFPICT: + pBuffer = HMETAFILEPICT_UserMarshal( pFlags, + pBuffer, + &pStgmed->hMetaFilePict ); + break; + case TYMED_ENHMF: + pBuffer = HENHMETAFILE_UserMarshal( pFlags, + pBuffer, + &pStgmed->hEnhMetaFile ); + break; + case TYMED_GDI: + + { + // A GDI object is not necesarrily a BITMAP. Therefore, we handle + // those types we know about based on the object type, and reject + // those which we do not support. + + ulong GdiObjectType = GetObjectType( (HGDIOBJ)pStgmed->hBitmap ); + + // GDI_OBJECT + + *( PULONG_LV_CAST pBuffer)++ = GdiObjectType; + + + + switch( GdiObjectType ) + { + case OBJ_BITMAP: + pBuffer = HBITMAP_UserMarshal( pFlags, + pBuffer, + &pStgmed->hBitmap ); + break; + + case OBJ_PAL: + pBuffer = HPALETTE_UserMarshal( pFlags, + pBuffer, + (HPALETTE *) & pStgmed->hBitmap ); + break; + + default: + RpcRaiseException(DV_E_TYMED); + } + } + break; + + case TYMED_HGLOBAL: + pBuffer = HGLOBAL_UserMarshal( pFlags, + pBuffer, + & pStgmed->hGlobal ); + break; + case TYMED_FILE: + { + // We marshal it as a [string]. + + ulong Count = (pStgmed->lpszFileName) + ? lstrlenW(pStgmed->lpszFileName) + 1 + : 0; + + *( PULONG_LV_CAST pBuffer)++ = Count; + *( PULONG_LV_CAST pBuffer)++ = 0; + *( PULONG_LV_CAST pBuffer)++ = Count; + memcpy( pBuffer, pStgmed->lpszFileName, Count * sizeof(wchar_t) ); + pBuffer += Count * sizeof(wchar_t); + } + break; + + case TYMED_ISTREAM: + case TYMED_ISTORAGE: + // Note, that we have to set the local flag for backward compatibility. + + pBuffer = WdtpInterfacePointer_UserMarshal( + ((USER_MARSHAL_CB *)pFlags), + *pFlags, + pBuffer, + pStgmed->pstg, + ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream + : IID_IStorage)); + break; + + default: + break; + } + } + + // Marker for this pointer is already in the buffer. + + if ( pStgmed->pUnkForRelease ) + pBuffer = WdtpInterfacePointer_UserMarshal( ((USER_MARSHAL_CB *)pFlags), + *pFlags, + pBuffer, + pStgmed->pUnkForRelease, + IID_IUnknown ); + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: STGMEDIUM_UserUnmarshal +// +// Synopsis: Unmarshals a stgmedium object for RPC. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +STGMEDIUM_UserUnmarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + STGMEDIUM * pStgmed ) +{ + unsigned long fUnkForRelease; + unsigned long Handle = 0; + + // switch, union arm, pUnk . + + ALIGN( pBuffer, 3 ); + + pStgmed->tymed = *( PULONG_LV_CAST pBuffer)++; + + UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal: %s\n", WdtpGetStgmedName(pStgmed) )); + + if ( pStgmed->tymed != TYMED_NULL ) + { + // handle or interface pointer (marker) from the buffer + Handle = *( PULONG_LV_CAST pBuffer)++; + } + + // pUnkForRelease pointer marker. + + fUnkForRelease = *( PULONG_LV_CAST pBuffer)++; + + // First pointee + + // Union arm pointee. + // We need to unmarshal only if the handle/pointer field was not NULL. + + if ( Handle ) + { + switch( pStgmed->tymed ) + { + case TYMED_NULL: + break; + case TYMED_MFPICT: + pBuffer = HMETAFILEPICT_UserUnmarshal( pFlags, + pBuffer, + &pStgmed->hMetaFilePict ); + break; + case TYMED_ENHMF: + pBuffer = HENHMETAFILE_UserUnmarshal( pFlags, + pBuffer, + &pStgmed->hEnhMetaFile ); + break; + case TYMED_GDI: + { + // A GDI object is not necesarrily a BITMAP. Therefore, we handle + // those types we know about based on the object type, and reject + // those which we do not support. + + DWORD GdiObjectType = *( PULONG_LV_CAST pBuffer)++; + + switch( GdiObjectType ) + { + case OBJ_BITMAP: + pBuffer = HBITMAP_UserUnmarshal( pFlags, + pBuffer, + &pStgmed->hBitmap ); + break; + + case OBJ_PAL: + pBuffer = HPALETTE_UserUnmarshal( pFlags, + pBuffer, + (HPALETTE *) & pStgmed->hBitmap ); + break; + + default: + RpcRaiseException(DV_E_TYMED); + } + } + break; + + case TYMED_HGLOBAL: + // reallocation is forbidden for [in-out] hglobal in STGMEDIUM. + + pBuffer = WdtpGlobalUnmarshal( pFlags, + pBuffer, + & pStgmed->hGlobal, + FALSE ); // realloc flag + break; + + case TYMED_FILE: + { + // We marshal it as a [string]. + + ulong Count = *( PULONG_LV_CAST pBuffer)++; + pBuffer += 8; + + if ( ! pStgmed->lpszFileName ) + pStgmed->lpszFileName = (LPOLESTR) + WdtpAllocate( pFlags, + Count * sizeof(wchar_t) ); + memcpy( pStgmed->lpszFileName, pBuffer, Count * sizeof(wchar_t) ); + pBuffer += Count * sizeof(wchar_t); + } + break; + + case TYMED_ISTREAM: + case TYMED_ISTORAGE: + // Non null pointer, retrieve the interface pointer + + pBuffer = WdtpInterfacePointer_UserUnmarshal( + (USER_MARSHAL_CB *)pFlags, + pBuffer, + (IUnknown **) &pStgmed->pstm, + ((pStgmed->tymed == TYMED_ISTREAM) + ? IID_IStream + : IID_IStorage)); + break; + + default: + break; + } + } + else + { + // New handle/pointer field is null, so release the previous one + // if it wasn't null. + + if ( pStgmed->hGlobal ) + { + // This should never happen for GetDataHere. + + // Note, that we release the handle field, not the stgmedium itself. + // Accordingly, we don't follow punkForRelease. + + UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal: %s: NULL in, freeing old one\n", WdtpGetStgmedName(pStgmed))); + + STGMEDIUM TmpStg = *pStgmed; + TmpStg.pUnkForRelease = NULL; + + if ( pStgmed->tymed == TYMED_HGLOBAL ) + { + // Cannot reallocate. + RpcRaiseException(DV_E_TYMED); + } + else + { + ReleaseStgMedium( &TmpStg ); + } + } + + pStgmed->hGlobal = 0; + } + + if ( fUnkForRelease ) + { + // There is an interface pointer on the wire. + + pBuffer = WdtpInterfacePointer_UserUnmarshal( (USER_MARSHAL_CB *)pFlags, + pBuffer, + &pStgmed->pUnkForRelease, + IID_IUnknown ); + } + + if ( pStgmed->pUnkForRelease ) + { + // Replace the app's punkForRelease with our custom release + // handler for special situations. + + // The special situation is when a handle is remoted with data + // and so we have to clean up a side effect of having a data copy + // around. UserFree does it properly but we need that for the callee. + // When the callee releases a stgmed, it would invoke + // ReleaseStgMedium and this API doesn't do anything for handles + // when the punkForRelease is not NULL. + + ULONG fHandleWithData = 0; + ULONG fTopLevelOnly = 0; + + switch ( pStgmed->tymed ) + { + case TYMED_HGLOBAL: + fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags ); + break; + + case TYMED_ENHMF: + case TYMED_GDI: + fHandleWithData = GDI_DATA_PASSING( *pFlags ); + break; + + case TYMED_MFPICT: + fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags ); + fTopLevelOnly = fHandleWithData && + ! GDI_DATA_PASSING( *pFlags ); + break; + + default: + break; + } + + if ( fHandleWithData ) + { + IUnknown * + punkTmp = (IUnknown *) new CPunkForRelease( pStgmed, + fTopLevelOnly ); + if (!punkTmp) + { + RpcRaiseException(E_OUTOFMEMORY); + } + + pStgmed->pUnkForRelease = punkTmp; + } + } + + return( pBuffer ); +} + + +//+------------------------------------------------------------------------- +// +// Function: STGMEDIUM_UserFree +// +// Synopsis: Frees a stgmedium object for RPC. +// +// history: May-95 Ryszardk Created. +// +// Note: This routine is called from the freeing walk at server +// or from the SetData *proxy*, when ownership has been passed. +// +//-------------------------------------------------------------------------- + +EXTERN_C +void NukeHandleAndReleasePunk( + STGMEDIUM * pStgmed ) +{ + pStgmed->hGlobal = NULL; + pStgmed->tymed = TYMED_NULL; + + if (pStgmed->pUnkForRelease) + { + pStgmed->pUnkForRelease->Release(); + pStgmed->pUnkForRelease = 0; + } +} + +void __RPC_USER +STGMEDIUM_UserFree( + unsigned long * pFlags, + STGMEDIUM * pStgmed ) +{ + UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserFree: %s\n", WdtpGetStgmedName(pStgmed))); + + if( pStgmed ) + { + switch ( pStgmed->tymed ) + { + case TYMED_FILE: + WdtpFree( pFlags, pStgmed->lpszFileName); + NukeHandleAndReleasePunk( pStgmed ); + break; + + case TYMED_NULL: + case TYMED_ISTREAM: + case TYMED_ISTORAGE: + ReleaseStgMedium( pStgmed ); + break; + + case TYMED_GDI: + case TYMED_ENHMF: + + if ( GDI_HANDLE_PASSING(*pFlags) ) + { + NukeHandleAndReleasePunk( pStgmed ); + } + else + { + // Handle w/data: there is a side effect to clean up. + // For punk !=0, this will go to our CPunk object. + + ReleaseStgMedium( pStgmed ); + } + break; + + case TYMED_HGLOBAL: + + if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) + { + NukeHandleAndReleasePunk( pStgmed ); + } + else + { + // Handle w/data: there is a side effect to clean up. + // For punk ==0, this will just release the data. + // For punk !=0, this will go to our CPunk object, + // release the data, and then call the original punk. + + ReleaseStgMedium( pStgmed ); + } + break; + + case TYMED_MFPICT: + + if ( HGLOBAL_HANDLE_PASSING(*pFlags) ) + { + NukeHandleAndReleasePunk( pStgmed ); + } + else if ( GDI_HANDLE_PASSING(*pFlags) ) + { + if ( pStgmed->pUnkForRelease ) + { + pStgmed->pUnkForRelease->Release(); + } + else + { + if ( pStgmed->hGlobal ) + GlobalFree( pStgmed->hGlobal ); + pStgmed->hGlobal = NULL; + pStgmed->tymed = TYMED_NULL; + } + } + else + { + // Handle w/data: there is a side effect to clean up. + // For punk !=0, this will go to our CPunk object. + + ReleaseStgMedium( pStgmed ); + } + break; + + default: + RpcRaiseException( E_INVALIDARG ); + break; + } + } +} + + +//+------------------------------------------------------------------------- +// +// Function: FLAG_STGMEDIUM_UserSize +// +// Synopsis: Sizes a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +FLAG_STGMEDIUM_UserSize( + unsigned long * pFlags, + unsigned long Offset, + FLAG_STGMEDIUM* pFlagStgmed ) +{ + if ( ! pFlagStgmed ) + return Offset; + + LENGTH_ALIGN( Offset, 3 ); + + Offset += sizeof(long); + Offset = STGMEDIUM_UserSize( pFlags, Offset, & pFlagStgmed->Stgmed ); + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: FLAG_STGMEDIUM_UserMarshal +// +// Synopsis: Marshals a wrapper for stgmedium. Used in SetData. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +FLAG_STGMEDIUM_UserMarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + FLAG_STGMEDIUM* pFlagStgmed ) +{ + if ( ! pFlagStgmed ) + return pBuffer; + + ALIGN( pBuffer, 3 ); + + // Flags: we need them when freeing in the client call_as routine + + pFlagStgmed->ContextFlags = *pFlags; + + *( PULONG_LV_CAST pBuffer)++ = *pFlags; + *( PULONG_LV_CAST pBuffer)++ = pFlagStgmed->fPassOwnership; + + pBuffer = STGMEDIUM_UserMarshal( pFlags, + pBuffer, + & pFlagStgmed->Stgmed ); + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: FLAG_STGMEDIUM_UserUnmarshal +// +// Synopsis: Unmarshals a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +FLAG_STGMEDIUM_UserUnmarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + FLAG_STGMEDIUM* pFlagStgmed ) +{ + ALIGN( pBuffer, 3 ); + + // Flags and buffer marker + + pFlagStgmed->ContextFlags = *( PULONG_LV_CAST pBuffer)++; + + // We need that in the Proxy, when we call the user free routine. + + pFlagStgmed->fPassOwnership = *( PULONG_LV_CAST pBuffer)++; + pFlagStgmed->ContextFlags = *pFlags; + + // We always unmarshal a FLAG_STGMEDIUM object. + // The engine will always free the FLAG_STGMEDIUM object later. + // Adjustments for passing the ownership are done within SetData_Stub. + + pBuffer = STGMEDIUM_UserUnmarshal( pFlags, + pBuffer, + & pFlagStgmed->Stgmed ); + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: FLAG_STGMEDIUM_UserFree +// +// Synopsis: Freess a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +FLAG_STGMEDIUM_UserFree( + unsigned long * pFlags, + FLAG_STGMEDIUM* pFlagsStgmed ) +{ + if ( ! pFlagsStgmed->fPassOwnership ) + STGMEDIUM_UserFree( pFlags, & pFlagsStgmed->Stgmed ); + + // else the callee is supposed to release the stg medium. +} + +//+------------------------------------------------------------------------- +// +// Function: ASYNC_STGMEDIUM_UserSize +// +// Synopsis: Sizes a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +ASYNC_STGMEDIUM_UserSize( + unsigned long * pFlags, + unsigned long Offset, + ASYNC_STGMEDIUM* pAsyncStgmed ) +{ + if ( ! pAsyncStgmed ) + return Offset; + + // we cant do the inproc optimizations (which avoid copies of the data) + // on ASYNC calls, since on return the caller will delete the data + // before the server has run. + + if (!REMOTE_CALL(*pFlags)) + { + *pFlags &= ~0xff; + *pFlags |= MSHCTX_DIFFERENTMACHINE; + } + + Offset = STGMEDIUM_UserSize( pFlags, Offset, pAsyncStgmed ); + + return( Offset ); +} + +//+------------------------------------------------------------------------- +// +// Function: ASYNC_STGMEDIUM_UserMarshal +// +// Synopsis: Marshals a wrapper for stgmedium. Used in SetData. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +ASYNC_STGMEDIUM_UserMarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + ASYNC_STGMEDIUM* pAsyncStgmed ) +{ + if ( ! pAsyncStgmed ) + return pBuffer; + + // we cant do the inproc optimizations (which avoid copies of the data) + // on ASYNC calls, since on return the caller will delete the data + // before the server has run. + + if (!REMOTE_CALL(*pFlags)) + { + *pFlags &= ~0xff; + *pFlags |= MSHCTX_DIFFERENTMACHINE; + } + + pBuffer = STGMEDIUM_UserMarshal( pFlags, + pBuffer, + pAsyncStgmed ); + + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: ASYNC_STGMEDIUM_UserUnmarshal +// +// Synopsis: Unmarshals a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +ASYNC_STGMEDIUM_UserUnmarshal( + unsigned long * pFlags, + unsigned char * pBuffer, + ASYNC_STGMEDIUM* pAsyncStgmed ) +{ + // we cant do the inproc optimizations (which avoid copies of the data) + // on ASYNC calls, since on return the caller will delete the data + // before the server has run. + + if (!REMOTE_CALL(*pFlags)) + { + // note: not strictly necessary to do this for Unmarshal, but it + // provides consistency. + + *pFlags &= ~0xff; + *pFlags |= MSHCTX_DIFFERENTMACHINE; + } + + pBuffer = STGMEDIUM_UserUnmarshal( pFlags, + pBuffer, + pAsyncStgmed ); + return( pBuffer ); +} + +//+------------------------------------------------------------------------- +// +// Function: ASYNC_STGMEDIUM_UserFree +// +// Synopsis: Freess a wrapper for stgmedium. +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +void __RPC_USER +ASYNC_STGMEDIUM_UserFree( + unsigned long * pFlags, + ASYNC_STGMEDIUM* pAsyncStgmed ) +{ + // we cant do the inproc optimizations (which avoid copies of the data) + // on ASYNC calls, since on return the caller will delete the data + // before the server has run. + + if (!REMOTE_CALL(*pFlags)) + { + *pFlags &= ~0xff; + *pFlags |= MSHCTX_DIFFERENTMACHINE; + } + + STGMEDIUM_UserFree( pFlags, pAsyncStgmed ); +} + + +#if (DBG==1) +//+------------------------------------------------------------------------- +// +// Function: WdtpGetStgmedName +// +// Synopsis: Debug support +// +// history: May-95 Ryszardk Created. +// +//-------------------------------------------------------------------------- + +char * +WdtpGetStgmedName( STGMEDIUM * pStgmed) + +{ + char * Name; + if ( pStgmed ) + { + switch (pStgmed->tymed) + { + case TYMED_NULL: + Name = "TYMED_NULL"; + break; + case TYMED_MFPICT: + Name = "TYMED_MFPICT"; + break; + case TYMED_ENHMF: + Name = "TYMED_ENHMF"; + break; + case TYMED_GDI: + Name = "TYMED_GDI"; + break; + case TYMED_HGLOBAL: + Name = "TYMED_HGLOBAL"; + break; + case TYMED_FILE: + Name = "TYMED_FILE"; + break; + case TYMED_ISTREAM: + Name = "TYMED_ISTREAM"; + break; + case TYMED_ISTORAGE: + Name = "TYMED_ISTORAGE"; + break; + default: + Name = "TYMED invalid"; + break; + } + return Name; + } + else + return "STGMED * is null"; +} +#endif + +#ifdef _CAIRO_ +//+------------------------------------------------------------------------- +// +// Function: HEVENT_UserSize +// +// Synopsis: Sizes an HEVENT handle. +// +//-------------------------------------------------------------------------- + +unsigned long __RPC_USER +HEVENT_UserSize ( + unsigned long * pFlags, + unsigned long Offset, + HEVENT * pH ) +{ + return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HEVENT_UserMarshall +// +// Synopsis: Marshalls an HEVENT handle into the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HEVENT_UserMarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HEVENT * pH ) +{ + return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HEVENT_UserUnmarshall +// +// Synopsis: Unmarshalls an HEVENT handle from the RPC buffer. +// +//-------------------------------------------------------------------------- + +unsigned char __RPC_FAR * __RPC_USER +HEVENT_UserUnmarshal ( + unsigned long * pFlags, + unsigned char * pBuffer, + HEVENT * pH ) +{ + return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); +} + +//+------------------------------------------------------------------------- +// +// Function: HEVENT_UserFree +// +// Synopsis: Free an HEVENT +// +//-------------------------------------------------------------------------- + +void __RPC_USER +HEVENT_UserFree( + unsigned long * pFlags, + HEVENT * pH ) +{ +} +#endif + + +//+------------------------------------------------------------------------- +// +// Class: CContinue +// +// Synopsis: Notification object +// +//-------------------------------------------------------------------------- +class CContinue : public IContinue +{ +private: + long _cRef; + BOOL (__stdcall *_pfnContinue)(DWORD); + DWORD _dwContinue; + ~CContinue(void); + +public: + CContinue(BOOL (__stdcall *pfnContinue)(DWORD dwContinue), DWORD dwContinue); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void **); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE FContinue(); +}; + + + + +//+------------------------------------------------------------------------- +// +// Method: CContinue::CContinue, public +// +// Synopsis: Constructor for CContinue +// +//-------------------------------------------------------------------------- +CContinue::CContinue(BOOL (__stdcall *pfnContinue)(DWORD dwContinue), DWORD dwContinue) +: _cRef(1), _pfnContinue(pfnContinue), _dwContinue(dwContinue) +{ +} + +CContinue::~CContinue() +{ +} + +//+------------------------------------------------------------------------- +// +// Method: CContinue::QueryInterface, public +// +// Synopsis: Query for an interface on the notification object. +// +//-------------------------------------------------------------------------- +HRESULT STDMETHODCALLTYPE +CContinue::QueryInterface ( + REFIID iid, + void **ppv ) +{ + HRESULT hr = E_NOINTERFACE; + + if ((IID_IUnknown == iid) || (IID_IContinue == iid)) + { + this->AddRef(); + *ppv = (IContinue *) this; + hr = S_OK; + } + else + { + *ppv = 0; + } + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Method: CContinue::AddRef, public +// +// Synopsis: Increment the reference count. +// +//-------------------------------------------------------------------------- +ULONG STDMETHODCALLTYPE +CContinue::AddRef() +{ + InterlockedIncrement((long *) &_cRef); + return (unsigned long) _cRef; +} + +//+------------------------------------------------------------------------- +// +// Method: CContinue::Release, public +// +// Synopsis: Decrement the reference count. +// +//-------------------------------------------------------------------------- +ULONG STDMETHODCALLTYPE +CContinue::Release() +{ + unsigned long count = _cRef - 1; + + if(0 == InterlockedDecrement((long *)&_cRef)) + { + count = 0; + delete this; + } + + return count; +} + + +//+------------------------------------------------------------------------- +// +// Method: CContinue::FContinue, public +// +// Synopsis: Calls the callback function. +// +//-------------------------------------------------------------------------- +HRESULT STDMETHODCALLTYPE +CContinue::FContinue() +{ + HRESULT hr; + BOOL bResult; + + bResult = (*_pfnContinue) (_dwContinue); + + if(bResult == FALSE) + { + hr = S_FALSE; + } + else + { + hr = S_OK; + } + + return hr; +} + +//+------------------------------------------------------------------------- +// +// Function: CreateCallback +// +// Synopsis: Create a callback notification object . +// +//-------------------------------------------------------------------------- +extern "C" HRESULT CreateCallback( + BOOL (__stdcall *pfnContinue)(DWORD dwContinue), + DWORD dwContinue, + IContinue **ppContinue) +{ + HRESULT hr; + + if(pfnContinue != 0) + { + CContinue *pContinue = new CContinue(pfnContinue, dwContinue); + + *ppContinue = (IContinue *) pContinue; + + if(pContinue != 0) + { + hr = S_OK; + } + else + { + hr = E_OUTOFMEMORY; + } + } + else + { + hr = E_INVALIDARG; + *ppContinue = 0; + } + + return hr; +} |