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