|
|
//+-------------------------------------------------------------------------
//
// 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
//
// 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
//
//--------------------------------------------------------------------------
#include "stdrpc.hxx"
#pragma hdrstop
#include <oleauto.h>
#include <objbase.h>
#include "transmit.h"
#include <rpcwdt.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: 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 += wcslen(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 += wcslen(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 = (wcslen(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 = wcslen(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 ); }
//+-------------------------------------------------------------------------
//
// 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: WdtpVoidStaer_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 ) { }
//+-------------------------------------------------------------------------
//
// Function: HWND_UserSize
//
// Synopsis: Sizes an HWND handle.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER HWND_UserSize ( unsigned long * pFlags, unsigned long Offset, HWND * pH ) { return WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_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 WdtpVoidStar_UserUnmarshal( pFlags, pBuffer, (ulong*)pH ); }
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_UserFree
//
// Synopsis: Free an HBRUSH.
//
//--------------------------------------------------------------------------
void __RPC_USER HBRUSH_UserFree( unsigned long * pFlags, HBRUSH * pH ) { }
// #########################################################################
//
// HGLOBAL.
// See transmit.h for explanation of strict 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 strict vs. lax 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 + handle
Offset += 3 * sizeof(long) + sizeof(void*);
// The lower part is a metafile handle.
if ( HGLOBAL_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)++ = (ulong) pMFP->hMF;
// See if the HMETAFILE needs to be sent as data, too.
if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) ) { 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; }
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 ) { 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)++; pMFP->hMF = (HMETAFILE) *( PULONG_LV_CAST pBuffer)++;
if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) ) { // 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 lax 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 ); } } }
// #########################################################################
//
// HBITMAP
// See transmit.h for explanation of lax 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 lax 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.
if ( (IId == IID_IStorage || IId == IID_IStream ) && *ppIf ) { // This may happen only on the client side.
// Throw away a new one when coming back to the client !!
// This is a pecularity of DocFile custom marshalling:
// pointer identity is broken.
if ( punkTemp ) punkTemp->Release();
// keep the old one
} else { // 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(void*) + sizeof(long); // pointer, switch only
else Offset += sizeof(void*) + sizeof(long) + sizeof(void*); // same + handle
// 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 = wcslen(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, MSHCTX_LOCAL, 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: if pointer, switch, union arm, .
*( PULONG_LV_CAST pBuffer)++ = (ulong)pStgmed->pUnkForRelease; *( 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; }
// 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) ? wcslen(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), MSHCTX_LOCAL, 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;
// if pointer, switch, union arm.
ALIGN( pBuffer, 3 );
// pUnkForRelease pointer marker.
fUnkForRelease = *( PULONG_LV_CAST pBuffer)++; 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)++; }
// 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->hGlobal ) GlobalFree( pStgmed->hGlobal ); 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;
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.
}
#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
|