You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3296 lines
94 KiB
3296 lines
94 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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
|
|
|
|
|