Windows2003-3790/inetcore/urlmon/proxy/transmit.cxx
2020-09-30 16:53:55 +02:00

3151 lines
87 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: transmit.cxx
//
// Contents: Transmit_as routines for oleprx32.dll.
//
// Functions: operator new
// operator delete
// EXCEPINFO_to_xmit
// EXCEPINFO_from_xmit
// EXCEPINFO_free_inst
// EXCEPINFO_free_xmit
// HGLOBAL_to_xmit
// HGLOBAL_from_xmit
// HGLOBAL_free_inst
// HGLOBAL_free_xmit
// HMETAFILEPICT_to_xmit
// HMETAFILEPICT_from_xmit
// HMETAFILEPICT_free_inst
// HMETAFILEPICT_free_xmit
// HENHMETAFILE_to_xmit
// HENHMETAFILE_from_xmit
// HENHMETAFILE_free_inst
// HENHMETAFILE_free_xmit
// HBITMAP_to_xmit
// HBITMAP_from_xmit
// HBITMAP_free_inst
// HBITMAP_free_xmit
// HBRUSH_to_xmit
// HBRUSH_from_xmit
// HBRUSH_free_inst
// HBRUSH_free_xmit
// STGMEDIUM_to_xmit
// STGMEDIUM_from_xmit
// STGMEDIUM_free_inst
// STGMEDIUM_free_xmit
// HACCEL_to_xmit
// HACCEL_from_xmit
// HACCEL_free_inst
// HACCEL_free_xmit
// UINT_to_xmit
// UINT_from_xmit
// UINT_free_inst
// UINT_free_xmit
// WPARAM_to_xmit
// WPARAM_from_xmit
// WPARAM_free_inst
// WPARAM_free_xmit
//
// 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
// 25-May-96 JohannP Moved to urlmon; minor modifications
//
//--------------------------------------------------------------------------
#include "stdrpc.hxx"
#pragma hdrstop
#include "objbase.h"
#include "transmit.h"
#include "crtsubst.h"
#ifndef _CHICAGO_
HBRUSH OleGdiConvertBrush(HBRUSH hbrush);
HBRUSH OleGdiCreateLocalBrush(HBRUSH hbrushRemote);
#endif // _CHICAGO_
void __RPC_USER HENHMETAFILE_to_xmit (HENHMETAFILE __RPC_FAR *pHEnhMetafile,
RemHENHMETAFILE __RPC_FAR * __RPC_FAR *ppxmit);
void __RPC_USER HENHMETAFILE_from_xmit( RemHENHMETAFILE __RPC_FAR *pxmit,
HENHMETAFILE __RPC_FAR *pHEnhMetafile );
void __RPC_USER HENHMETAFILE_free_xmit( RemHENHMETAFILE __RPC_FAR *pxmit);
void __RPC_USER HPALETTE_to_xmit (HPALETTE __RPC_FAR *pHPALETTE,
RemHPALETTE __RPC_FAR * __RPC_FAR *ppxmit);
void __RPC_USER HPALETTE_from_xmit( RemHPALETTE __RPC_FAR *pxmit,
HPALETTE __RPC_FAR *pHPALETTE );
void __RPC_USER HPALETTE_free_xmit( RemHPALETTE __RPC_FAR *pxmit);
void __RPC_USER HPALETTE_free_inst( HPALETTE __RPC_FAR *pHPALETTE);
WINOLEAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pStgMed);
// BUGBUG: setting NTDEBUG=retail does not build this retail, so i cant
// use DBG to conditionally generate this code, hence i must
// disable it for now.
//
// #if DBG==1
// #define Assert(a) ((a) ? NOERROR : FnAssert(#a, NULL, __FILE__, __LINE__))
// #else
#define Assert(a) ((void)0)
// #endif
#pragma code_seg(".orpc")
// we dont need these when we are in with ole32.dll
#if 0
//+-------------------------------------------------------------------------
//
// Function: operator new
7//
// Synopsis: Override operator new so we don't need C runtime library.
//
//--------------------------------------------------------------------------
void *
_CRTAPI1
operator new (size_t size)
{
return CoTaskMemAlloc(size);
}
//+-------------------------------------------------------------------------
//
// Function: operator delete
//
// Synopsis: Override operator delete so we don't need C runtime library.
//
//--------------------------------------------------------------------------
void
_CRTAPI1
operator delete (void * pObj)
{
CoTaskMemFree(pObj);
}
#endif
//+-------------------------------------------------------------------------
//
// 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.
//
// 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_from_xmit, 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);
// IUnknown Methods
STDMETHOD(QueryInterface)(REFIID riid, void **ppunk);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
private:
~CPunkForRelease(void);
ULONG _cRefs; // reference count
STGMEDIUM _stgmed; // storage medium
IUnknown * _pUnkForRelease; // real pUnkForRelease
};
inline CPunkForRelease::CPunkForRelease(STGMEDIUM *pStgMed) :
_cRefs(1),
_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.
Assert(pStgMed);
Assert(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, just
// pretend like the callee is responsible for the release, and
// recurse into ReleaseStgMedium to do the cleanup.
_stgmed.pUnkForRelease = NULL;
ReleaseStgMedium(&_stgmed);
// release the callers punk
_pUnkForRelease->Release();
}
STDMETHODIMP_(ULONG) CPunkForRelease::AddRef(void)
{
InterlockedIncrement((LONG *)&_cRefs);
return _cRefs;
}
STDMETHODIMP_(ULONG) CPunkForRelease::Release(void)
{
if (InterlockedDecrement((LONG *)&_cRefs) == 0)
{
delete this;
return 0;
}
else
return _cRefs;
}
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;
}
}
#ifdef UNUSED
//+-------------------------------------------------------------------------
//
// Function: EXCEPINFO_to_xmit
//
// Synopsis: Convert an EXCEPINFO to a RemEXCEPINFO structure so it can be sent
// over the network.
//
//--------------------------------------------------------------------------
void __RPC_USER EXCEPINFO_to_xmit (EXCEPINFO *pinst, RemEXCEPINFO **ppxmit)
{
unsigned int cSource = 0;
unsigned int cDescription = 0;
unsigned int cHelpFile = 0;
unsigned int *pCount;
wchar_t *pTemp;
if(pinst->pfnDeferredFillIn)
{
//Fill in the EXCEPINFO structure.
(pinst->pfnDeferredFillIn) (pinst);
}
//Calculate the total size of the strings.
if(pinst->bstrSource)
{
pCount = (unsigned int *) pinst->bstrSource;
pCount--;
cSource = *pCount;
}
if(pinst->bstrDescription)
{
pCount = (unsigned int *) pinst->bstrDescription;
pCount--;
cDescription = *pCount;
}
if(pinst->bstrHelpFile)
{
pCount = (unsigned int *) pinst->bstrHelpFile;
pCount--;
cHelpFile = *pCount;
}
*ppxmit = (RemEXCEPINFO *) NdrOleAllocate(sizeof(RemEXCEPINFO) +
((cSource + cDescription + cHelpFile) * sizeof(wchar_t)));
(*ppxmit)->wCode = pinst->wCode;
(*ppxmit)->wReserved = pinst->wReserved;
(*ppxmit)->dwHelpContext = pinst->dwHelpContext;
(*ppxmit)->scode = pinst->scode;
(*ppxmit)->cSource = cSource;
(*ppxmit)->cDescription = cDescription;
(*ppxmit)->cHelpFile = cHelpFile;
pTemp = (*ppxmit)->strings;
if(pinst->bstrSource)
{
memcpy(pTemp, pinst->bstrSource, (*ppxmit)->cSource * sizeof(wchar_t));
pTemp += cSource;
}
if(pinst->bstrDescription)
{
memcpy(pTemp, pinst->bstrDescription, (*ppxmit)->cDescription * sizeof(wchar_t));
pTemp += cDescription;
}
if(pinst->bstrHelpFile)
{
memcpy(pTemp, pinst->bstrHelpFile, (*ppxmit)->cHelpFile * sizeof(wchar_t));
}
}
//+-------------------------------------------------------------------------
//
// Function: EXCEPINFO_from_xmit
//
// Synopsis: Convert a RemEXCEPINFO structure to an EXCEPINFO.
//
//--------------------------------------------------------------------------
void __RPC_USER EXCEPINFO_from_xmit (RemEXCEPINFO *pxmit, EXCEPINFO *pinst)
{
wchar_t *pTemp;
unsigned int *pCount;
pinst->wCode = pxmit->wCode;
pinst->wReserved = pxmit->wReserved;
pinst->bstrSource = 0;
pinst->bstrDescription = 0;
pinst->bstrHelpFile = 0;
pinst->dwHelpContext = pxmit->dwHelpContext;
pinst->pvReserved = 0;
pinst->pfnDeferredFillIn = 0;
pinst->scode = pxmit->scode;
//unmarshal BSTRs
pTemp = pxmit->strings;
if(pxmit->cSource)
{
pCount = (unsigned int *) NdrOleAllocate(sizeof(int) + pxmit->cSource * sizeof(wchar_t) + sizeof(wchar_t));
//set the BSTR count.
*pCount = pxmit->cSource;
pCount++;
pinst->bstrSource = (BSTR) pCount;
//copy the BSTR characters
memcpy(pinst->bstrSource, pTemp, pxmit->cSource * sizeof(wchar_t));
//zero-terminate the BSTR.
pinst->bstrSource[pxmit->cSource] = 0;
//advance the data pointer.
pTemp += pxmit->cSource;
}
if(pxmit->cDescription)
{
pCount = (unsigned int *) NdrOleAllocate(sizeof(int) + pxmit->cDescription * sizeof(wchar_t) + sizeof(wchar_t));
//set the character count.
*pCount = pxmit->cDescription;
pCount++;
pinst->bstrDescription = (BSTR) pCount;
//copy the characters
memcpy(pinst->bstrDescription, pTemp, pxmit->cDescription *sizeof(wchar_t));
//zero-terminate the BSTR.
pinst->bstrDescription[pxmit->cDescription] = 0;
//advance the data pointer.
pTemp += pxmit->cDescription;
}
if(pxmit->cHelpFile)
{
pCount = (unsigned int *) NdrOleAllocate(sizeof(int) + pxmit->cHelpFile * sizeof(wchar_t) + sizeof(wchar_t));
//set the BSTR count.
*pCount = pxmit->cHelpFile;
pCount++;
pinst->bstrHelpFile = (BSTR) pCount;
//copy the BSTR characters
memcpy(pinst->bstrHelpFile, pTemp, pxmit->cHelpFile * sizeof(wchar_t));
//zero-terminate the BSTR.
pinst->bstrHelpFile[pxmit->cHelpFile] = 0;
//advance the data pointer.
pTemp += pxmit->cHelpFile;
}
}
//+-------------------------------------------------------------------------
//
// Function: EXCEPINFO_free_inst
//
// Synopsis: Free the contents of an EXCEPINFO structure.
//
//--------------------------------------------------------------------------
void __RPC_USER EXCEPINFO_free_inst (EXCEPINFO *pinst)
{
unsigned int *pInt;
if(pinst)
{
if(pinst->bstrSource)
{
pInt = (unsigned int *) pinst->bstrSource;
pInt--;
NdrOleFree(pInt);
}
if(pinst->bstrDescription)
{
pInt = (unsigned int *) pinst->bstrDescription;
pInt--;
NdrOleFree(pInt);
}
if(pinst->bstrHelpFile)
{
pInt = (unsigned int *) pinst->bstrHelpFile;
pInt--;
NdrOleFree(pInt);
}
}
}
//+-------------------------------------------------------------------------
//
// Function: EXCEPINFO_free_xmit
//
// Synopsis: Free a RemEXCEPINFO previously obtained via EXCEPINFO_to_xmit.
//
//--------------------------------------------------------------------------
void __RPC_USER EXCEPINFO_free_xmit (RemEXCEPINFO *pxmit)
{
if(pxmit)
{
NdrOleFree(pxmit);
}
}
#endif //UNUSED
//+-------------------------------------------------------------------------
//
// Function: HGLOBAL_to_xmit
//
// Synopsis: Convert an HGLOBAL to a RemHGLOBAL structure so it can be sent
// over the network.
//
// Derivation: We get the size of the global memory block,
// allocate a RemHGLOBAL structure, then copy the contents
// of the global memory block into the RemHGLOBAL structure.
//
//--------------------------------------------------------------------------
void __RPC_USER HGLOBAL_to_xmit (HGLOBAL *pinst, RemHGLOBAL **ppxmit)
{
HGLOBAL hGlobal = *pinst;
//calculate size - we give a null hGlobal a size of zero
DWORD cbData = (DWORD) ((hGlobal)?GlobalSize(hGlobal):0);
//allocate memory
*ppxmit = (RemHGLOBAL *) NdrOleAllocate(sizeof(RemHGLOBAL) + cbData);
// save size of variable length data
(*ppxmit)->cbData = cbData;
if (hGlobal != NULL)
{
// There is an hglobal to transmit
(*ppxmit)->fNullHGlobal = FALSE;
// Remember that an HGLOBAL can be alloc'd to zero size. So we
// check whether there is anything to copy.
if (cbData != 0)
{
// Copy the data
void *pData = GlobalLock(hGlobal);
memcpy((*ppxmit)->data, pData, cbData);
GlobalUnlock(hGlobal);
}
}
else
{
(*ppxmit)->fNullHGlobal = TRUE;
}
}
//+-------------------------------------------------------------------------
//
// Function: HGLOBAL_from_xmit
//
// Synopsis: Convert a RemHGLOBAL structure to an HGLOBAL.
//
// Derivation: We get the data size, allocate a global memory block,
// then copy the data from the RemHGLOBAL structure to
// the global memory block.
//
//--------------------------------------------------------------------------
void __RPC_USER HGLOBAL_from_xmit (RemHGLOBAL __RPC_FAR *pxmit, HGLOBAL __RPC_FAR *pinst)
{
// Default to NULL hglobal
HGLOBAL hGlobal = NULL;
void *pData;
//allocate memory
if (!pxmit->fNullHGlobal)
{
hGlobal = GlobalAlloc(GMEM_MOVEABLE, pxmit->cbData);
if(hGlobal)
{
//copy the data
pData = GlobalLock(hGlobal);
if(pData)
{
memcpy(pData, pxmit->data, pxmit->cbData);
GlobalUnlock(hGlobal);
}
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
}
*pinst = hGlobal;
}
//+-------------------------------------------------------------------------
//
// Function: HGLOBAL_free_inst
//
// Synopsis: Free an HGLOBAL.
//
//--------------------------------------------------------------------------
void __RPC_USER HGLOBAL_free_inst(HGLOBAL *pinst)
{
if(pinst)
{
if(*pinst)
{
GlobalFree(*pinst);
}
}
}
//+-------------------------------------------------------------------------
//
// Function: HGLOBAL_free_xmit
//
// Synopsis: Free a RemHGLOBAL previously obtained via HGLOBAL_to_xmit.
//
//--------------------------------------------------------------------------
void __RPC_USER HGLOBAL_free_xmit(RemHGLOBAL *pxmit)
{
if(pxmit != 0)
NdrOleFree(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: HMETAFILEPICT_to_xmit
//
// Synopsis: Converts a metafilepict handle into a global handle
// that can be remoted
//
// Arguments: [pHMetafilePict]-- pointer to the original metafile handle
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// Algorithm: calls a private gdi api to convert the handle
//
// History: 16-Nov-93 alexgo created
// 07-Jan-94 rickhi copy the metafile
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HMETAFILEPICT_to_xmit (HMETAFILEPICT __RPC_FAR *pHMetafilePict,
RemHMETAFILEPICT __RPC_FAR * __RPC_FAR *ppxmit)
{
#ifdef NEW_GDI_MARSHALLING
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
//calculate size
DWORD cbData = sizeof(long);
//allocate memory
*ppxmit = (RemHMETAFILEPICT *) NdrOleAllocate(sizeof(RemHMETAFILEPICT) + cbData);
if (*ppxmit)
{
//copy data
(*ppxmit)->cbData = cbData;
// BUGBUG: enable this code!
//long lData = (long)OleGdiConvertMetaFilePict(*(HANDLE *)pHMetafilePict);
memcpy((*ppxmit)->data, &lData, cbData);
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
#else
// lock the data
METAFILEPICT *pmfp = (METAFILEPICT *)GlobalLock(*(HANDLE *)pHMetafilePict);
if (pmfp)
{
// calculate the size needed to hold the windows metafile
DWORD cbData = GetMetaFileBitsEx(pmfp->hMF, 0, NULL);
// allocate memory
*ppxmit = (RemHMETAFILEPICT *) NdrOleAllocate(sizeof(RemHMETAFILEPICT) + cbData);
// copy data
(*ppxmit)->cbData = cbData;
(*ppxmit)->mm = pmfp->mm;
(*ppxmit)->xExt = pmfp->xExt;
(*ppxmit)->yExt = pmfp->yExt;
GetMetaFileBitsEx(pmfp->hMF, cbData, &((*ppxmit)->data[0]));
GlobalUnlock(*(HANDLE *)pHMetafilePict);
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HMETAFILEPICT_from_xmit
//
// Synopsis: Converts a global metafilepict handle into a metafile
// handle that a process can use
//
// Arguments: [pxmit] -- the transmitted global handle
// [pHMetafilePict]-- where to put the local metafilepict handle
//
// Returns: void
//
// Algorithm: calls a private gdi api to convert the global handle
//
// History: 16-Nov-93 alexgo created
// 07-Jan-94 rickhi copy the metafile
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HMETAFILEPICT_from_xmit( RemHMETAFILEPICT __RPC_FAR *pxmit,
HMETAFILEPICT __RPC_FAR *pHMetafilePict )
{
#ifdef NEW_GDI_MARSHALLLING
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
long lh;
memcpy(&lh, pxmit->data, pxmit->cbData);
*pHMetafilePict = (HMETAFILE)GdiCreateLocalMetaFilePict(
(HANDLE)lh);
#else
// allocate memory
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
*pHMetafilePict = hGlobal;
if(hGlobal)
{
//copy the data
METAFILEPICT *pmfp = (METAFILEPICT *)GlobalLock(hGlobal);
if(pmfp)
{
pmfp->mm = pxmit->mm;
pmfp->xExt = pxmit->xExt;
pmfp->yExt = pxmit->yExt;
// create a windows metatfile from the data
pmfp->hMF = SetMetaFileBitsEx(pxmit->cbData, pxmit->data);
GlobalUnlock(hGlobal);
}
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HMETAFILEPICT_free_xmit
//
// Synopsis: Free's the global metafilepict handle that gets remoted
//
// Arguments: [pxmit] -- the transmitted metafilepict handle
//
// Returns: void
//
// History: 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HMETAFILEPICT_free_xmit( RemHMETAFILEPICT __RPC_FAR *pxmit)
{
if(pxmit != 0)
NdrOleFree(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: HMETAFILEPICT_free_inst
//
// Synopsis: does nothing, as no memory is allocated
//
// Arguments: [pHMetafilePict] -- pointer to the metafilepict
//
// Returns: void
//
// Algorithm:
//
// History: 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HMETAFILEPICT_free_inst( HMETAFILEPICT __RPC_FAR *pHMetafilePict)
{
METAFILEPICT *pmf;
if(*pHMetafilePict)
{
pmf = (METAFILEPICT *) GlobalLock(*pHMetafilePict);
if(pmf)
{
DeleteMetaFile(pmf->hMF);
GlobalUnlock(*pHMetafilePict);
}
GlobalFree(*pHMetafilePict);
}
}
#ifndef NEW_GDI_MARSHALLLING
//+-------------------------------------------------------------------------
//
// Function: GetColorTableSize
//
// Synopsis: computes the size of the color table using the info in
// the supplied BITMAPINFO
//
// Arguments: [pbmi] -- pointer to the BITMAPINFO for the bitmap
//
// Returns: size of the color table
//
//+-------------------------------------------------------------------------
ULONG GetColorTableSize(BITMAPINFO *pbmi)
{
// compute size of memory needed. it must account for the header
// info, color table, and bitmap, as well as the RemHBITMAP.
ULONG ulColorTableSize;
if (pbmi->bmiHeader.biClrUsed)
{
// biClrUsed contains number of RGBQUADs used
ulColorTableSize = pbmi->bmiHeader.biClrUsed;
}
else if (pbmi->bmiHeader.biCompression == BI_BITFIELDS)
{
// size is 3 DWORD color masks. sizeof(DWORD) == sizeof(RGBQUAD)
ulColorTableSize = 3;
}
else
{
// compute number of RGBQUADs from biBitCount
ulColorTableSize = (pbmi->bmiHeader.biBitCount == 24) ? 0 :
(1<<pbmi->bmiHeader.biBitCount);
}
return (ulColorTableSize * sizeof(RGBQUAD));
}
#endif
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_to_xmit
//
// Synopsis: Converts a bitmap handle into a global handle
// that can be remoted
//
// Arguments: [pBitmap] -- pointer to the original bitmap handle
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// Algorithm: calls a private gdi api to convert the handle
//
// History: 16-Nov-93 alexgo created
// 07-Jan-94 rickhi copy the bitmap
// 12-Aug-94 davepl Rewrote OLD_GDI_MARSHALLING section
//
// Notes: CODEWORK: this code specifically does not account for OS2
// style DIBs. Verify this is OK. Unless the Windows APIs
// deal with OS2 bitmaps on their own...
//
//--------------------------------------------------------------------------
void __RPC_USER HBITMAP_to_xmit (HBITMAP __RPC_FAR *pBitmap,
RemHBITMAP __RPC_FAR * __RPC_FAR *ppxmit)
{
#ifdef NEW_GDI_MARSHALLLING
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
//calculate size
DWORD cbData = sizeof(long);
//allocate memory
*ppxmit = (RemHBITMAP *) NdrOleAllocate(sizeof(RemHBITMAP) + cbData);
if (*ppxmit)
{
//copy data
(*ppxmit)->cbData = cbData;
long lData = (long)GdiConvertBitmap(*pBitmap);
memcpy((*ppxmit)->data, &lData, cbData);
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
#else
BITMAP bm;
HBITMAP hBitmap = (HBITMAP) * pBitmap;
// 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()));
}
// Allocate space for the raw bitmap bits and the bm structure, plus
// the RemHBITMAP structure all at once.
DWORD dwCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
*ppxmit = (RemHBITMAP *) (BYTE *) NdrOleAllocate(sizeof(RemHBITMAP)
+ dwCount + sizeof(bm));
if (NULL == *ppxmit)
{
RpcRaiseException(E_OUTOFMEMORY);
}
// lpBits points to the portion of the RemHBITMAP structure where
// we will store the BITMAP structure and raw bits
BYTE * lpBits = (BYTE *) &(*ppxmit)->data[0];
// Get the raw bits. Offset sizeof(BITMAP) into the buffer so
// that we can stick the BITMAP struct at the front before
// transmission
if (0 == GetBitmapBits(hBitmap, dwCount, lpBits + sizeof(bm)))
{
NdrOleFree(*ppxmit);
*ppxmit = NULL;
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
// Stuff the bm structure in before the bits
memcpy(lpBits, (void *) &bm, sizeof(bm));
(*ppxmit)->cbData = dwCount + sizeof(bm);
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_from_xmit
//
// Synopsis: Converts a global bitmap handle into a bitmap
// handle that a process can use
//
// Arguments: [pxmit] -- the transmitted global handle
// [pBitmap] -- where to put the local bitmap handle
//
// Returns: void
//
// Algorithm: Creates a local bitmap and then associates the remote
// bitmap with the local one.
//
// History: 16-Nov-93 alexgo created
// 07-Jan-94 rickhi copy the bitmap
// 12-Aug-94 davepl rewrote the OLD_GDI_MARSHALLING section
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBITMAP_from_xmit( RemHBITMAP __RPC_FAR *pxmit,
HBITMAP __RPC_FAR *pBitmap )
{
#ifdef NEW_GDI_MARSHALLLING
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
ULONG hLocal = (ULONG)GdiCreateLocalBitmap();
ULONG lh;
memcpy(&lh, pxmit->data, pxmit->cbData);
GdiAssociateObject(hLocal, lh);
*pBitmap = (HBITMAP)hLocal;
#else
BITMAP * pbm = (BITMAP *) &(pxmit->data[0]);
BYTE * lpBits = ((BYTE *) pbm) + sizeof(BITMAP);
// Create a bitmap based on the BITMAP structure and the raw bits in
// the transmission buffer
*pBitmap = CreateBitmap(pbm->bmWidth,
pbm->bmHeight,
pbm->bmPlanes,
pbm->bmBitsPixel,
(void *) lpBits);
// If no bitmap came back, raise an exception rather than just returning
if (NULL == *pBitmap)
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_free_xmit
//
// Synopsis: Free's the buffer used to serialize the bitmap
//
// Effects:
//
// Arguments: [pxmit] -- the transmitted bitmap serialized buffer
//
// Returns: void
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBITMAP_free_xmit( RemHBITMAP __RPC_FAR *pxmit)
{
if(pxmit != 0)
NdrOleFree(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: HBITMAP_free_inst
//
// Synopsis: Destroys the bitmap object
//
// Arguments: [pBitmap] -- pointer to the bitmap handle
//
// Returns: void
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBITMAP_free_inst( HBITMAP __RPC_FAR *pBitmap)
{
DeleteObject(*pBitmap);
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_to_xmit
//
// Synopsis: Converts a brush handle into a global handle
// that can be remoted
//
// Arguments: [pBrush] -- pointer to the original brush handle
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// Algorithm: calls a private gdi api to convert the handle
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBRUSH_to_xmit (HBRUSH __RPC_FAR *pBrush,
RemHBRUSH __RPC_FAR * __RPC_FAR *ppxmit)
{
#ifndef _CHICAGO_
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
//calculate size
DWORD cbData = sizeof(long);
//allocate memory
*ppxmit = (RemHBRUSH *) NdrOleAllocate(sizeof(RemHBRUSH) + cbData);
if (*ppxmit)
{
//copy data
(*ppxmit)->cbData = cbData;
// BUGBUG: enable this code!
//long lData = (long)OleGdiConvertBrush(*pBrush);
//memcpy((*ppxmit)->data, &lData, cbData);
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_from_xmit
//
// Synopsis: Converts a global brush handle into a brush
// handle that a process can use
//
// Arguments: [pxmit] -- the transmitted global handle
// [pBrush] -- where to put the local brush handle
//
// Returns: void
//
// Algorithm: calls a private gdi api to convert the global handle
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBRUSH_from_xmit( RemHBRUSH __RPC_FAR *pxmit,
HBRUSH __RPC_FAR *phBrush )
{
#ifndef _CHICAGO_
// CODEWORK: we can use this in the Daytona and Local Cairo case,
// but not in Chicago or remote Cairo
// BUGBUG: enable this code!
//*phBrush = OleGdiCreateLocalBrush((HBRUSH)(pxmit->data));
*phBrush = NULL;
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_free_xmit
//
// Synopsis: Free's the global brush handle that gets remoted
//
// Arguments: [pxmit] -- the transmitted brush handle
//
// Returns: void
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBRUSH_free_xmit( RemHBRUSH __RPC_FAR *pxmit)
{
#ifndef _CHICAGO_
if(pxmit != 0)
NdrOleFree(pxmit);
#endif
}
//+-------------------------------------------------------------------------
//
// Function: HBRUSH_free_inst
//
// Synopsis: Delete an HBRUSH.
//
// Arguments: [pBrush] -- pointer to the metafile
//
// Returns: void
//
// History: dd-mmm-yy Author Comment
// 16-Nov-93 alexgo created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER HBRUSH_free_inst( HBRUSH __RPC_FAR *pBrush)
{
#ifndef _CHICAGO_
DeleteObject(*pBrush);
#endif
}
/***************************************************************************/
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 = (ULONG) (*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: STGMEDIUM_to_xmit
//
// Synopsis: Convert an STGMEDIUM to a RemSTGMEDIUM structure so it can be sent
// over the network.
//
// The marshalled STGMEDIUM looks like this:
// RemSTGMEDIUM | data from union | data from pUnkForRelease
//--------------------------------------------------------------------------
void __RPC_USER STGMEDIUM_to_xmit (STGMEDIUM *pinst, RemSTGMEDIUM **ppxmit)
{
unsigned char *pData;
RemHGLOBAL *pRemHGLOBAL;
RemHBITMAP *pRemHBITMAP;
RemHPALETTE *pRemHPALETTE;
RemHMETAFILEPICT *pRemHMETAFILEPICT;
RemHENHMETAFILE *pRemHENHMETAFILE;
long size;
unsigned long count;
unsigned long cbInterface;
HRESULT hr = S_OK;
DWORD *pcbData;
DWORD *pcbSize;
DWORD cbData;
unsigned char *pStart;
// If the TYMED for the STGMEDIUM is TYMED_GDI, we need a bit more information
// (ie: what _kind_ of GDI object it is). The field is unused for anything
// except TYMED_GDI
DWORD dwHandleType = 0;
//calculate size of marshalled STGMEDIUM.
size = sizeof(RemSTGMEDIUM);
//add the size of data[].
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
HMETAFILEPICT_to_xmit(&pinst->hMetaFilePict, &pRemHMETAFILEPICT);
size += sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData;
break;
case TYMED_ENHMF:
HENHMETAFILE_to_xmit(&pinst->hEnhMetaFile, &pRemHENHMETAFILE);
size += sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData;
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(GetObjectType( (HGDIOBJ) pinst->hGlobal ))
{
case OBJ_BITMAP:
HBITMAP_to_xmit(&pinst->hBitmap, &pRemHBITMAP);
size += sizeof(RemHBITMAP) + pRemHBITMAP->cbData;
dwHandleType = OBJ_BITMAP;
break;
case OBJ_PAL:
HPALETTE_to_xmit((HPALETTE *) &pinst->hBitmap, &pRemHPALETTE);
size += sizeof(RemHPALETTE) + pRemHPALETTE->cbData;
dwHandleType = OBJ_PAL;
break;
default:
RpcRaiseException(DV_E_TYMED);
}
break;
case TYMED_HGLOBAL:
HGLOBAL_to_xmit(&pinst->hGlobal, &pRemHGLOBAL);
size += sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData;
break;
case TYMED_FILE:
count = wcslen(pinst->lpszFileName) + 1;
size += 4; //allocate room for character count.
size += count * sizeof(wchar_t);
break;
case TYMED_ISTREAM:
size += 4;
if(pinst->pstm)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IStream, pinst->pstm, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
size += cbInterface;
}
break;
case TYMED_ISTORAGE:
size += 4;
if(pinst->pstg)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IStorage, pinst->pstg, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
size += cbInterface;
}
break;
default:
break;
}
//Allocate space for pUnkForRelease.
if(pinst->pUnkForRelease)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IUnknown, pinst->pUnkForRelease, MSHCTX_NOSHAREDMEM, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
{
size += cbInterface;
}
}
//allocate memory
*ppxmit = (RemSTGMEDIUM *) NdrOleAllocate(size);
//Marshal STGMEDIUM
(*ppxmit)->tymed = pinst->tymed;
//SUNDOWN: typecast problem
(*ppxmit)->pData = PtrToUlong(pinst->hGlobal);
(*ppxmit)->pUnkForRelease = PtrToUlong(pinst->pUnkForRelease);
(*ppxmit)->cbData = size - sizeof(RemSTGMEDIUM);
(*ppxmit)->dwHandleType = dwHandleType;
pData = (*ppxmit)->data;
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
//Note that we called HMETAFILEPICT_to_xmit earlier so we could
//get the size.
memcpy(pData, pRemHMETAFILEPICT, sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData);
pData += sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData;
HMETAFILEPICT_free_xmit(pRemHMETAFILEPICT);
break;
case TYMED_ENHMF:
memcpy(pData, pRemHENHMETAFILE, sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData);
pData += sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData;
HENHMETAFILE_free_xmit(pRemHENHMETAFILE);
break;
case TYMED_HGLOBAL:
//Note that we called HGLOBAL_to_xmit earlier so we could
//get the size.
memcpy(pData, pRemHGLOBAL, sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData);
pData += sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData;
HGLOBAL_free_xmit(pRemHGLOBAL);
break;
case TYMED_GDI:
switch(dwHandleType)
{
case OBJ_BITMAP:
memcpy(pData, pRemHBITMAP, sizeof(RemHBITMAP) + pRemHBITMAP->cbData);
pData += sizeof(RemHBITMAP) + pRemHBITMAP->cbData;
HBITMAP_free_xmit(pRemHBITMAP);
break;
case OBJ_PAL:
memcpy(pData, pRemHPALETTE, sizeof(RemHPALETTE) + pRemHPALETTE->cbData);
pData += sizeof(RemHPALETTE) + pRemHPALETTE->cbData;
HPALETTE_free_xmit(pRemHPALETTE);
}
break;
case TYMED_FILE:
//copy the length.
memcpy(pData, &count, sizeof(count));
pData += sizeof(count);
//copy the string.
memcpy(pData, pinst->lpszFileName, count * sizeof(wchar_t));
pData += count * sizeof(wchar_t);
break;
case TYMED_ISTREAM:
if(pinst->pstm)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IStream, pinst->pstm, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
break;
case TYMED_ISTORAGE:
if(pinst->pstg)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IStorage, pinst->pstg, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
break;
default:
break;
}
if(pinst->pUnkForRelease)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IUnknown, pinst->pUnkForRelease, MSHCTX_NOSHAREDMEM, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
}
//+-------------------------------------------------------------------------
//
// Function: STGMEDIUM_from_xmit
//
// Synopsis: Convert a RemSTGMEDIUM structure to an STGMEDIUM.
//
//--------------------------------------------------------------------------
void __RPC_USER STGMEDIUM_from_xmit (RemSTGMEDIUM __RPC_FAR *pxmit, STGMEDIUM __RPC_FAR *pinst)
{
HRESULT hr = S_OK;
unsigned char *pData;
pinst->tymed = pxmit->tymed;
pData = pxmit->data;
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
HMETAFILEPICT_from_xmit((RemHMETAFILEPICT *)pData, &pinst->hMetaFilePict);
pData += sizeof(RemHMETAFILEPICT) + ((RemHMETAFILEPICT *)pData)->cbData;
break;
case TYMED_ENHMF:
HENHMETAFILE_from_xmit((RemHENHMETAFILE *)pData, &pinst->hEnhMetaFile);
pData += sizeof(RemHENHMETAFILE) + ((RemHENHMETAFILE *)pData)->cbData;
break;
case TYMED_HGLOBAL:
HGLOBAL_from_xmit((RemHGLOBAL *)pData, &pinst->hGlobal);
pData += sizeof(RemHGLOBAL) + ((RemHGLOBAL *)pData)->cbData;
break;
// When unmarshalling a STGMEDIUM with TYMED_GDI, we need to know
// what kind of GDI object is packaged, so we inspect the dwHandleType
// field which was set during the marshalling of the STGMEDIUM
case TYMED_GDI:
switch(pxmit->dwHandleType)
{
case OBJ_BITMAP:
HBITMAP_from_xmit((RemHBITMAP *)pData, &pinst->hBitmap);
pData += sizeof(RemHBITMAP) + ((RemHBITMAP *)pData)->cbData;
break;
case OBJ_PAL:
HPALETTE_from_xmit((RemHPALETTE *)pData, (HPALETTE *) &pinst->hBitmap);
pData += sizeof(RemHPALETTE) + ((RemHPALETTE *)pData)->cbData;
break;
default:
RpcRaiseException(DV_E_TYMED);
}
break;
case TYMED_FILE:
{
unsigned long count;
//unmarshal the count.
memcpy(&count, pData, sizeof(count));
pData += sizeof(count);
//allocate memory.
pinst->lpszFileName = (wchar_t *)NdrOleAllocate(count * sizeof(wchar_t));
//copy the string.
memcpy(pinst->lpszFileName, pData, count * sizeof(wchar_t));
pData += count * sizeof(wchar_t);
}
break;
case TYMED_ISTREAM:
if (pxmit->pData)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IStream,
(void **) &pinst->pstm);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
}
else
{
pinst->pstm = NULL;
}
break;
case TYMED_ISTORAGE:
if (pxmit->pData)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IStorage,
(void **) &pinst->pstg);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
}
else
{
pinst->pstg = NULL;
}
break;
default:
break;
}
pinst->pUnkForRelease = NULL;
if(pxmit->pUnkForRelease)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IUnknown, (void **) &pinst->pUnkForRelease);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
// replace the punkForRelease with our custom release
// handler for special situations.
if (pinst->tymed == TYMED_HGLOBAL ||
pinst->tymed == TYMED_MFPICT ||
pinst->tymed == TYMED_ENHMF ||
pinst->tymed == TYMED_GDI)
{
IUnknown *punkTmp = (IUnknown *) new CPunkForRelease(pinst);
if (!punkTmp)
{
RpcRaiseException(E_OUTOFMEMORY);
}
pinst->pUnkForRelease = punkTmp;
}
}
}
//+-------------------------------------------------------------------------
//
// Function: STGMEDIUM_free_inst
//
// Synopsis: Free the contents of an STGMEDIUM structure.
//
//--------------------------------------------------------------------------
void __RPC_USER STGMEDIUM_free_inst(STGMEDIUM *pinst)
{
if(pinst)
{
if (pinst->tymed == TYMED_FILE)
{
NdrOleFree(pinst->lpszFileName);
pinst->lpszFileName = NULL;
if (pinst->pUnkForRelease)
{
pinst->pUnkForRelease->Release();
pinst->pUnkForRelease = 0;
}
}
else
{
ReleaseStgMedium(pinst);
}
}
}
//+-------------------------------------------------------------------------
//
// Function: STGMEDIUM_free_xmit
//
// Synopsis: Free a RemSTGMEDIUM previously obtained from STGMEDIUM_to_xmit.
//
//--------------------------------------------------------------------------
void __RPC_USER STGMEDIUM_free_xmit(RemSTGMEDIUM *pxmit)
{
if(pxmit)
{
NdrOleFree(pxmit);
}
}
//+-------------------------------------------------------------------------
//
// Function: SNB_to_xmit
//
// Synopsis: Converts an SNB structure to a remotable structure
//
// Arguments: [pSNB] -- pointer to the original SNB
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// Algorithm:
//
// History: 10-01-94 rickhi Created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER SNB_to_xmit (SNB __RPC_FAR *pSNB,
RemSNB __RPC_FAR * __RPC_FAR *ppxmit)
{
// calculate the size of the structure needed. add 1 for the NULL
// terminator
ULONG ulCntStr = 0;
ULONG ulCntChar = 0;
if (pSNB && *pSNB)
{
// compute the number of strings and the total number of
// characters in all the strings.
SNB snb = *pSNB;
WCHAR *psz = *snb;
while (psz)
{
ulCntChar += wcslen(psz) + 1;
ulCntStr++;
snb++;
psz = *snb;
}
}
// allocate memory
RemSNB *pRemSNB = (RemSNB *) NdrOleAllocate(sizeof(RemSNB) +
ulCntChar * sizeof(WCHAR));
if (pRemSNB)
{
// copy the data
pRemSNB->ulCntStr = ulCntStr;
pRemSNB->ulCntChar = ulCntChar;
if (pSNB && *pSNB)
{
// copy the string ptrs into the new structure
SNB snb = *pSNB;
WCHAR *pszSrc;
WCHAR *pszTgt = pRemSNB->rgString;
while (pszSrc = *snb++)
{
ULONG ulLen = wcslen(pszSrc) + 1;
memcpy(pszTgt, pszSrc, ulLen * sizeof(WCHAR));
pszTgt += ulLen;
}
}
*ppxmit = pRemSNB;
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
}
//+-------------------------------------------------------------------------
//
// Function: SNB_from_xmit
//
// Synopsis: converts a RemSNB to an SNB
//
// Arguments: [pxmit] -- the transmitted RemSNB
// [pSNB] -- where to put the local SNB
//
// Returns: void
//
// History: 10-Jan-94 rickhi created
//
// Notes:
//
//--------------------------------------------------------------------------
void __RPC_USER SNB_from_xmit( RemSNB __RPC_FAR *pxmit,
SNB __RPC_FAR *pSNB )
{
if (pxmit)
{
if (pxmit->ulCntStr == 0)
{
*pSNB = NULL;
return;
}
SNB snb = (SNB) NdrOleAllocate((pxmit->ulCntStr+1) * sizeof(WCHAR *) +
pxmit->ulCntChar * sizeof(WCHAR));
// set the out parameter
*pSNB = snb;
if (snb)
{
// create the pointer array
WCHAR *pszSrc = pxmit->rgString;
WCHAR *pszTgt = (WCHAR *)(snb + pxmit->ulCntStr + 1);
for (ULONG i = pxmit->ulCntStr; i>0; i--)
{
*snb++ = pszTgt;
ULONG ulLen = wcslen(pszSrc) + 1;
pszSrc += ulLen;
pszTgt += ulLen;
}
*snb++ = NULL;
// copy the actual strings
memcpy(snb, pxmit->rgString, pxmit->ulCntChar * sizeof(WCHAR));
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
}
}
//+-------------------------------------------------------------------------
//
// Function: SNB_free_xmit
//
// Synopsis: Free's the memory for the RemSNB structure
//
// Arguments: [pxmit] -- the transmitted SNB to free
//
// Returns: void
//
// History: 10-Jan-94 rickhi created
//
//--------------------------------------------------------------------------
void __RPC_USER SNB_free_xmit( RemSNB __RPC_FAR *pxmit)
{
if(pxmit != 0)
NdrOleFree(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: SNB_free_inst
//
// Synopsis: Deletes an SNB.
//
// Arguments: [pSNB] -- pointer to the SNB to free
//
// Returns: void
//
// History: 10-Jan-94 created created
//
//--------------------------------------------------------------------------
void __RPC_USER SNB_free_inst( SNB __RPC_FAR *pSNB)
{
if (pSNB)
{
NdrOleFree(*pSNB);
}
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_to_xmit
//
// Synopsis: Convert an HMENU to a long.
//
// Notes: Both the source process and the destination process must
// reside on the same machine. This code assumes that the
// destination process can use the HMENU received from
// the source process.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HMENU_to_xmit(HMENU *pHandle, LONG_PTR **ppLong)
{
*(ppLong) = (LONG_PTR*) NdrOleAllocate(sizeof(LONG_PTR));
**ppLong = (LONG_PTR) *(pHandle);
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_from_xmit
//
// Synopsis: Convert a long to an HMENU.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HMENU_from_xmit(LONG_PTR *pLong, HMENU *pHandle)
{
*(pHandle) = (HMENU) *(pLong);
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_free_inst
//
// Synopsis: Does nothing.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HMENU_free_inst(HMENU *pHandle)
{
}
//+-------------------------------------------------------------------------
//
// Function: HMENU_free_xmit
//
// Synopsis: Free a pointer to a long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HMENU_free_xmit(long *pLong)
{
if(pLong != 0)
NdrOleFree(pLong);
}
EXTERN_C void __RPC_USER HOLEMENU_to_xmit (HOLEMENU *pinst, RemHGLOBAL **ppxmit)
{
HGLOBAL_to_xmit((HGLOBAL *)pinst, ppxmit);
}
EXTERN_C void __RPC_USER HOLEMENU_from_xmit (RemHGLOBAL __RPC_FAR *pxmit, HOLEMENU __RPC_FAR *pinst)
{
HGLOBAL_from_xmit (pxmit, (HGLOBAL __RPC_FAR *)pinst);
}
EXTERN_C void __RPC_USER HOLEMENU_free_inst(HOLEMENU *pinst)
{
HGLOBAL_free_inst((HGLOBAL *)pinst);
}
EXTERN_C void __RPC_USER HOLEMENU_free_xmit(RemHGLOBAL *pxmit)
{
HGLOBAL_free_xmit(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: HWND_to_xmit
//
// Synopsis: Convert an HWND to a long.
//
// Notes: Both the source process and the destination process must
// reside on the same machine. This code assumes that the
// destination process can use the HWND received from
// the source process.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HWND_to_xmit(HWND *pHandle, LONG_PTR **ppLong)
{
*(ppLong) = (LONG_PTR*) NdrOleAllocate(sizeof(LONG_PTR));
**ppLong = (LONG_PTR) *(pHandle);
}
//+-------------------------------------------------------------------------
//
// Function: HWND_from_xmit
//
// Synopsis: Convert a long to an HWND.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HWND_from_xmit(LONG_PTR *pLong, HWND *pHandle)
{
*(pHandle) = (HWND) *(pLong);
}
//+-------------------------------------------------------------------------
//
// Function: HWND_free_inst
//
// Synopsis: Does nothing.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HWND_free_inst(HWND *pHandle)
{
}
//+-------------------------------------------------------------------------
//
// Function: HWND_free_xmit
//
// Synopsis: Free a pointer to a long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HWND_free_xmit(long *pLong)
{
if(pLong != 0)
NdrOleFree(pLong);
}
//+-------------------------------------------------------------------------
//
// Function: HENHMETAFILE_to_xmit
//
// Synopsis: Converts an enhanced metafile handle into a serial buffer
// that can be remoted
//
// Arguments: [pHEnhMetafile] -- pointer to the original emf handle
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// History: 14-Nov-94 DavePl Created
//
//
//--------------------------------------------------------------------------
void __RPC_USER HENHMETAFILE_to_xmit (HENHMETAFILE __RPC_FAR *pHEnhMetafile,
RemHENHMETAFILE __RPC_FAR * __RPC_FAR *ppxmit)
{
// A few inefficient temp vars here to avoid ugly casts later
HENHMETAFILE hemf = *pHEnhMetafile;
// Calculate the number of bytes we need in order to serialize the
// metafile to memory
DWORD cbData = GetEnhMetaFileBits(hemf, 0, NULL);
if (cbData == 0)
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
// Allocate the appropriate number of bytes
*ppxmit = (RemHENHMETAFILE *)
NdrOleAllocate(sizeof(RemHENHMETAFILE) + cbData);
// If the allocation was successful, get the bits into our buffer.
// Otherwise, throw an exception
if (*ppxmit)
{
if (0==GetEnhMetaFileBits(hemf, cbData, &((*ppxmit)->data[0])))
{
NdrOleFree(*ppxmit);
*ppxmit = NULL;
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
(*ppxmit)->cbData = cbData;
}
else
{
RpcRaiseException(E_OUTOFMEMORY);
}
}
//+-------------------------------------------------------------------------
//
// Function: HENHMETAFILE_from_xmit
//
// Synopsis: Converts a serialized enhanced metafile into an emf handle
// that is usable by applications
//
// Arguments: [pxmit] -- the transmitted global handle
// [pHEnhMetafile] -- where to put the local metafilepict handle
//
// Returns: void
//
// History: 14-May-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HENHMETAFILE_from_xmit( RemHENHMETAFILE __RPC_FAR *pxmit,
HENHMETAFILE __RPC_FAR *pHEnhMetafile )
{
// Generate a handle to the enhanced metafile by doing a
// Setbits on the raw data
*pHEnhMetafile = SetEnhMetaFileBits(pxmit->cbData, pxmit->data);
if (NULL == *pHEnhMetafile)
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
}
//+-------------------------------------------------------------------------
//
// Function: HENHMETAFILE_free_xmit
//
// Synopsis: Free's the remote data
//
// Arguments: [pxmit] -- the transmitted data
//
// Returns: void
//
// History: 14-May-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HENHMETAFILE_free_xmit( RemHENHMETAFILE __RPC_FAR *pxmit)
{
if(pxmit != 0)
NdrOleFree(pxmit);
}
//+-------------------------------------------------------------------------
//
// Function: HMETAFILEPICT_free_inst
//
// Synopsis: destroys the metafile
//
// Arguments: [pHEnhMetafile] -- handle to the enhanced metafile
//
// Returns: void
//
// Algorithm:
//
// History: 14-May-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HENHMETAFILE_free_inst( HENHMETAFILE __RPC_FAR *pHEnhMetafile)
{
DeleteEnhMetaFile (*pHEnhMetafile);
}
//+-------------------------------------------------------------------------
//
// Function: HPALETTE_to_xmit
//
// Synopsis: Converts a palette into a serialized buffer
// that can be remoted
//
// Arguments: [pHPALETTE] -- pointer to the original palette handle
// [ppxmit] -- set to point to the transmitted value
//
// Returns: void
//
// History: 11-Aug-94 DavePl Created
//
//
//--------------------------------------------------------------------------
void __RPC_USER HPALETTE_to_xmit (HPALETTE __RPC_FAR *pHPALETTE,
RemHPALETTE __RPC_FAR * __RPC_FAR *ppxmit)
{
// Determine the number of color entries in the palette
DWORD cEntries = GetPaletteEntries(*pHPALETTE, 0, 0, NULL);
// Calculate the resultant data size
DWORD cbData = cEntries * sizeof(PALETTEENTRY);
// Allocate space for the struct and the entries
*ppxmit = (RemHPALETTE *) NdrOleAllocate(sizeof(RemHPALETTE) + cbData);
if (NULL == *ppxmit)
{
RpcRaiseException(E_OUTOFMEMORY);
}
if (cbData)
{
if (0 == GetPaletteEntries(*pHPALETTE,
0,
cEntries,
(PALETTEENTRY *) &((*ppxmit)->data[0])))
{
NdrOleFree(*ppxmit);
*ppxmit = NULL;
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
}
(*ppxmit)->cbData = cbData;
}
//+-------------------------------------------------------------------------
//
// Function: HPALETTE_from_xmit
//
// Synopsis: Converts a serialized palette into an palette handle
// that is usable by applications
//
// Arguments: [pxmit] -- the transmitted buffer
// [pHPALETTE] -- where to put the local palette handle
//
// Returns: void
//
// History: 11-Aug-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HPALETTE_from_xmit( RemHPALETTE __RPC_FAR *pxmit,
HPALETTE __RPC_FAR *pHPALETTE )
{
DWORD cEntries = pxmit->cbData / sizeof(PALETTEENTRY);
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 *) NdrOleAllocate(sizeof(LOGPALETTE));
}
else
{
pLogPal = (LOGPALETTE *) NdrOleAllocate(sizeof(LOGPALETTE) +
(cEntries - 1) * sizeof(PALETTEENTRY));
// If there are entries, and if we have a buffer, move the
// entries into out LOGPALETTE structure
if (pLogPal)
{
memcpy(&(pLogPal->palPalEntry[0]), pxmit->data, pxmit->cbData);
}
}
// If we didn't get a buffer at all...
if (NULL == pLogPal)
{
RpcRaiseException(E_OUTOFMEMORY);
}
// Fill in the rest of the structure
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = (unsigned short) cEntries;
// Attempt to create the palette
*pHPALETTE = CreatePalette(pLogPal);
// Success or failure, we're done with the LOGPALETTE structure
NdrOleFree(pLogPal);
// If the creation failed, raise an exception
if (NULL == *pHPALETTE)
{
RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
}
//+-------------------------------------------------------------------------
//
// Function: HPALETTE_free_xmit
//
// Synopsis: Frees the remote data
//
// Arguments: [pxmit] -- the transmitted data
//
// Returns: void
//
// History: 11-Aug-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HPALETTE_free_xmit( RemHPALETTE __RPC_FAR *pxmit)
{
if(NULL != pxmit)
{
NdrOleFree(pxmit);
}
}
//+-------------------------------------------------------------------------
//
// Function: HPALETTE_free_inst
//
// Synopsis: destroys the palette
//
// Arguments: [pHPALETTE] -- handle to the palette
//
// Returns: void
//
// Algorithm:
//
// History: 11-Aug-94 DavePl Created
//
//--------------------------------------------------------------------------
void __RPC_USER HPALETTE_free_inst( HPALETTE __RPC_FAR *pHPALETTE)
{
DeleteObject( (HGDIOBJ) *pHPALETTE);
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_to_xmit
//
// Synopsis: Convert an HACCEL to a long.
//
// Notes: Both the source process and the destination process must
// reside on the same machine. This code assumes that the
// destination process can use the HACCEL received from
// the source process.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HACCEL_to_xmit(HACCEL *phAccel, LONG_PTR **ppLong)
{
*ppLong = (LONG_PTR*) NdrOleAllocate(sizeof(LONG_PTR));
**ppLong = (LONG_PTR) *phAccel;
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_from_xmit
//
// Synopsis: Convert a long to an HACCEL.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HACCEL_from_xmit(LONG_PTR *pLong, HACCEL *pHandle)
{
*pHandle = (HACCEL) *pLong;
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_free_inst
//
// Synopsis: Does nothing.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HACCEL_free_inst(HACCEL *pHandle)
{
}
//+-------------------------------------------------------------------------
//
// Function: HACCEL_free_xmit
//
// Synopsis: Free a pointer to a long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER HACCEL_free_xmit(long *pLong)
{
if(pLong != 0)
NdrOleFree(pLong);
}
//+-------------------------------------------------------------------------
//
// Function: UINT_to_xmit
//
// Synopsis: Convert a UINT to a 32 bit long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER UINT_to_xmit(UINT *pUint, unsigned long **ppLong)
{
*ppLong = (unsigned long *) NdrOleAllocate(sizeof(long));
**ppLong = (unsigned long) *pUint;
}
//+-------------------------------------------------------------------------
//
// Function: UINT_from_xmit
//
// Synopsis: Convert a 32 bit long to a UINT.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER UINT_from_xmit(
unsigned long __RPC_FAR *pLong,
UINT __RPC_FAR *pUint
)
{
*pUint = (UINT) *pLong;
}
//+-------------------------------------------------------------------------
//
// Function: UINT_free_inst
//
// Synopsis: Does nothing.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER UINT_free_inst(UINT *pHandle)
{
}
//+-------------------------------------------------------------------------
//
// Function: UINT_free_xmit
//
// Synopsis: Free a pointer to a long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER UINT_free_xmit(unsigned long *pLong)
{
if(pLong != 0)
NdrOleFree(pLong);
}
//+-------------------------------------------------------------------------
//
// Function: WPARAM_to_xmit
//
// Synopsis: Convert a WPARAM to a 32 bit long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER WPARAM_to_xmit(WPARAM *pHandle, unsigned long **ppLong)
{
*ppLong = (unsigned long *) NdrOleAllocate(sizeof(unsigned long));
**ppLong = (unsigned long) *pHandle;
}
//+-------------------------------------------------------------------------
//
// Function: WPARAM_from_xmit
//
// Synopsis: Convert a 32 bit long to a WPARAM.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER WPARAM_from_xmit(unsigned long *pLong, WPARAM *pHandle)
{
*pHandle = (WPARAM) *pLong;
}
//+-------------------------------------------------------------------------
//
// Function: WPARAM_free_inst
//
// Synopsis: Does nothing.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER WPARAM_free_inst(WPARAM *pHandle)
{
}
//+-------------------------------------------------------------------------
//
// Function: WPARAM_free_xmit
//
// Synopsis: Free a pointer to a long.
//
//--------------------------------------------------------------------------
EXTERN_C void __RPC_USER WPARAM_free_xmit(unsigned long *pLong)
{
if(pLong != 0)
NdrOleFree(pLong);
}
#ifdef UNUSED
//+-------------------------------------------------------------------------
// new code
//+-------------------------------------------------------------------------
//+-------------------------------------------------------------------------
//
// Function: STGMEDIUM_to_xmit
//
// Synopsis: Convert an STGMEDIUM to a RemBINDINFO structure so it can be sent
// over the network.
//
// The marshalled BINDINFO looks like this:
// RemBINDINFO | data from union | data from pUnkForRelease
//--------------------------------------------------------------------------
void __RPC_USER BINDINFO_to_xmit (BINDINFO *pinst, RemBINDINFO **ppxmit)
{
unsigned char *pData;
RemHGLOBAL *pRemHGLOBAL;
RemHBITMAP *pRemHBITMAP;
RemHPALETTE *pRemHPALETTE;
RemHMETAFILEPICT *pRemHMETAFILEPICT;
RemHENHMETAFILE *pRemHENHMETAFILE;
long size;
unsigned long count;
unsigned long cbInterface;
HRESULT hr = S_OK;
DWORD *pcbData;
DWORD *pcbSize;
DWORD cbData;
unsigned char *pStart;
// If the TYMED for the BINDINFO is TYMED_GDI, we need a bit more information
// (ie: what _kind_ of GDI object it is). The field is unused for anything
// except TYMED_GDI
DWORD dwHandleType = 0;
//calculate size of marshalled BINDINFO.
size = sizeof(RemBINDINFO);
//add the size of data[].
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
HMETAFILEPICT_to_xmit(&pinst->hMetaFilePict, &pRemHMETAFILEPICT);
size += sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData;
break;
case TYMED_ENHMF:
HENHMETAFILE_to_xmit(&pinst->hEnhMetaFile, &pRemHENHMETAFILE);
size += sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData;
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(GetObjectType( (HGDIOBJ) pinst->hGlobal ))
{
case OBJ_BITMAP:
HBITMAP_to_xmit(&pinst->hBitmap, &pRemHBITMAP);
size += sizeof(RemHBITMAP) + pRemHBITMAP->cbData;
dwHandleType = OBJ_BITMAP;
break;
case OBJ_PAL:
HPALETTE_to_xmit((HPALETTE *) &pinst->hBitmap, &pRemHPALETTE);
size += sizeof(RemHPALETTE) + pRemHPALETTE->cbData;
dwHandleType = OBJ_PAL;
break;
default:
RpcRaiseException(DV_E_TYMED);
}
break;
case TYMED_HGLOBAL:
HGLOBAL_to_xmit(&pinst->hGlobal, &pRemHGLOBAL);
size += sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData;
break;
case TYMED_FILE:
count = wcslen(pinst->lpszFileName) + 1;
size += 4; //allocate room for character count.
size += count * sizeof(wchar_t);
break;
case TYMED_ISTREAM:
size += 4;
if(pinst->pstm)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IStream, pinst->pstm, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
size += cbInterface;
}
break;
case TYMED_ISTORAGE:
size += 4;
if(pinst->pstg)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IStorage, pinst->pstg, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
size += cbInterface;
}
break;
default:
break;
}
//Allocate space for pUnkForRelease.
if(pinst->pUnkForRelease)
{
//Align the buffer on an 4 byte boundary.
size += 3;
size &= (unsigned int)0xfffffffc;
//Allocate space for the length and array bounds.
size += 8;
hr = CoGetMarshalSizeMax(&cbInterface, IID_IUnknown, pinst->pUnkForRelease, MSHCTX_NOSHAREDMEM, 0, MSHLFLAGS_NORMAL);
if(hr == S_OK)
{
size += cbInterface;
}
}
//allocate memory
*ppxmit = (RemBINDINFO *) NdrOleAllocate(size);
//Marshal BINDINFO
(*ppxmit)->tymed = pinst->tymed;
(*ppxmit)->pData = (unsigned long) pinst->hGlobal;
(*ppxmit)->pUnkForRelease = (unsigned long) pinst->pUnkForRelease;
(*ppxmit)->cbData = size - sizeof(RemBINDINFO);
(*ppxmit)->dwHandleType = dwHandleType;
pData = (*ppxmit)->data;
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
//Note that we called HMETAFILEPICT_to_xmit earlier so we could
//get the size.
memcpy(pData, pRemHMETAFILEPICT, sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData);
pData += sizeof(RemHMETAFILEPICT) + pRemHMETAFILEPICT->cbData;
HMETAFILEPICT_free_xmit(pRemHMETAFILEPICT);
break;
case TYMED_ENHMF:
memcpy(pData, pRemHENHMETAFILE, sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData);
pData += sizeof(RemHENHMETAFILE) + pRemHENHMETAFILE->cbData;
HENHMETAFILE_free_xmit(pRemHENHMETAFILE);
break;
case TYMED_HGLOBAL:
//Note that we called HGLOBAL_to_xmit earlier so we could
//get the size.
memcpy(pData, pRemHGLOBAL, sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData);
pData += sizeof(RemHGLOBAL) + pRemHGLOBAL->cbData;
HGLOBAL_free_xmit(pRemHGLOBAL);
break;
case TYMED_GDI:
switch(dwHandleType)
{
case OBJ_BITMAP:
memcpy(pData, pRemHBITMAP, sizeof(RemHBITMAP) + pRemHBITMAP->cbData);
pData += sizeof(RemHBITMAP) + pRemHBITMAP->cbData;
HBITMAP_free_xmit(pRemHBITMAP);
break;
case OBJ_PAL:
memcpy(pData, pRemHPALETTE, sizeof(RemHPALETTE) + pRemHPALETTE->cbData);
pData += sizeof(RemHPALETTE) + pRemHPALETTE->cbData;
HPALETTE_free_xmit(pRemHPALETTE);
}
break;
case TYMED_FILE:
//copy the length.
memcpy(pData, &count, sizeof(count));
pData += sizeof(count);
//copy the string.
memcpy(pData, pinst->lpszFileName, count * sizeof(wchar_t));
pData += count * sizeof(wchar_t);
break;
case TYMED_ISTREAM:
if(pinst->pstm)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IStream, pinst->pstm, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
break;
case TYMED_ISTORAGE:
if(pinst->pstg)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IStorage, pinst->pstg, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
break;
default:
break;
}
if(pinst->pUnkForRelease)
{
CStreamOnMessage stream((unsigned char **) &pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Leave space for cbData.
pcbData = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
//Leave space for size.
pcbSize = (DWORD *) pData;
*(unsigned long FAR *)&pData += 4;
pStart = (unsigned char *) pData;
hr = CoMarshalInterface(&stream, IID_IUnknown, pinst->pUnkForRelease, MSHCTX_NOSHAREDMEM, 0, MSHLFLAGS_NORMAL);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
cbData = (DWORD) (pData - pStart);
*pcbData = cbData;
*pcbSize = cbData;
}
}
//+-------------------------------------------------------------------------
//
// Function: BINDINFO_from_xmit
//
// Synopsis: Convert a RemBINDINFO structure to an BINDINFO.
//
//--------------------------------------------------------------------------
void __RPC_USER BINDINFO_from_xmit (RemBINDINFO __RPC_FAR *pxmit, BINDINFO __RPC_FAR *pinst)
{
HRESULT hr = S_OK;
unsigned char *pData;
pinst->tymed = pxmit->tymed;
pData = pxmit->data;
switch(pinst->tymed)
{
case TYMED_NULL:
break;
case TYMED_MFPICT:
HMETAFILEPICT_from_xmit((RemHMETAFILEPICT *)pData, &pinst->hMetaFilePict);
pData += sizeof(RemHMETAFILEPICT) + ((RemHMETAFILEPICT *)pData)->cbData;
break;
case TYMED_ENHMF:
HENHMETAFILE_from_xmit((RemHENHMETAFILE *)pData, &pinst->hEnhMetaFile);
pData += sizeof(RemHENHMETAFILE) + ((RemHENHMETAFILE *)pData)->cbData;
break;
case TYMED_HGLOBAL:
HGLOBAL_from_xmit((RemHGLOBAL *)pData, &pinst->hGlobal);
pData += sizeof(RemHGLOBAL) + ((RemHGLOBAL *)pData)->cbData;
break;
// When unmarshalling a BINDINFO with TYMED_GDI, we need to know
// what kind of GDI object is packaged, so we inspect the dwHandleType
// field which was set during the marshalling of the BINDINFO
case TYMED_GDI:
switch(pxmit->dwHandleType)
{
case OBJ_BITMAP:
HBITMAP_from_xmit((RemHBITMAP *)pData, &pinst->hBitmap);
pData += sizeof(RemHBITMAP) + ((RemHBITMAP *)pData)->cbData;
break;
case OBJ_PAL:
HPALETTE_from_xmit((RemHPALETTE *)pData, (HPALETTE *) &pinst->hBitmap);
pData += sizeof(RemHPALETTE) + ((RemHPALETTE *)pData)->cbData;
break;
default:
RpcRaiseException(DV_E_TYMED);
}
break;
case TYMED_FILE:
{
unsigned long count;
//unmarshal the count.
memcpy(&count, pData, sizeof(count));
pData += sizeof(count);
//allocate memory.
pinst->lpszFileName = (wchar_t *)NdrOleAllocate(count * sizeof(wchar_t));
//copy the string.
memcpy(pinst->lpszFileName, pData, count * sizeof(wchar_t));
pData += count * sizeof(wchar_t);
}
break;
case TYMED_ISTREAM:
if (pxmit->pData)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IStream,
(void **) &pinst->pstm);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
}
else
{
pinst->pstm = NULL;
}
break;
case TYMED_ISTORAGE:
if (pxmit->pData)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IStorage,
(void **) &pinst->pstg);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
}
else
{
pinst->pstg = NULL;
}
break;
default:
break;
}
pinst->pUnkForRelease = NULL;
if(pxmit->pUnkForRelease)
{
CStreamOnMessage stream(&pData);
//Align the buffer on an 4 byte boundary
*(unsigned long FAR *)&pData += 3;
*(unsigned long FAR *)&pData &= 0xfffffffc;
//Skip over cbData.
*(unsigned long FAR *)&pData += 4;
//Skip over cbSize.
*(unsigned long FAR *)&pData += 4;
hr = CoUnmarshalInterface(&stream, IID_IUnknown, (void **) &pinst->pUnkForRelease);
if(hr != S_OK)
{
RpcRaiseException(hr);
}
// replace the punkForRelease with our custom release
// handler for special situations.
if (pinst->tymed == TYMED_HGLOBAL ||
pinst->tymed == TYMED_MFPICT ||
pinst->tymed == TYMED_ENHMF ||
pinst->tymed == TYMED_GDI)
{
IUnknown *punkTmp = (IUnknown *) new CPunkForRelease(pinst);
if (!punkTmp)
{
RpcRaiseException(E_OUTOFMEMORY);
}
pinst->pUnkForRelease = punkTmp;
}
}
}
//+-------------------------------------------------------------------------
//
// Function: BINDINFO_free_inst
//
// Synopsis: Free the contents of an BINDINFO structure.
//
//--------------------------------------------------------------------------
void __RPC_USER BINDINFO_free_inst(BINDINFO *pinst)
{
if(pinst)
{
NdrOleFree(pinst);
}
}
//+-------------------------------------------------------------------------
//
// Function: BINDINFO_free_xmit
//
// Synopsis: Free a RemBINDINFO previously obtained from BINDINFO_to_xmit.
//
//--------------------------------------------------------------------------
void __RPC_USER BINDINFO_free_xmit(RemBINDINFO *pxmit)
{
if(pxmit)
{
NdrOleFree(pxmit);
}
}
#endif //UNUSED