|
|
//+-------------------------------------------------------------------------
//
// 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
|