windows-nt/Source/XPSP1/NT/com/oleutest/balls/oleprx32/proxy/transmit.cxx

3296 lines
90 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// 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