1069 lines
32 KiB
C++
1069 lines
32 KiB
C++
//+--------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1992.
|
|
//
|
|
// File: marshl.cxx
|
|
//
|
|
// Contents: Marshal/Unmarshal implementation
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
#include <exphead.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <expdf.hxx>
|
|
#include <expst.hxx>
|
|
#include <pbstream.hxx>
|
|
#include <marshl.hxx>
|
|
#include <logfile.hxx>
|
|
|
|
// Standard marshal data is an IID plus a DWORD
|
|
#define CBSTDMARSHALSIZE (sizeof(IID)+sizeof(DWORD))
|
|
|
|
SCODE VerifyIid(REFIID iid, REFIID iidObj)
|
|
{
|
|
if ((IsEqualIID(iid, IID_IUnknown) || (IsEqualIID(iid, iidObj))))
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (IsEqualIID(iidObj, IID_ILockBytes))
|
|
{
|
|
if (IsEqualIID(iid, IID_IFillLockBytes))
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
if (IsEqualIID(iidObj, IID_IStorage))
|
|
{
|
|
if ( IsEqualIID(iid, IID_IPropertySetStorage)
|
|
|| IsEqualIID(iid, IID_IPropertyBagEx) )
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return STG_E_INVALIDPARAMETER;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: DfUnMarshalInterface, public
|
|
//
|
|
// Synopsis: Unmarshals marshaled data
|
|
//
|
|
// Arguments: [pstStm] - Stream to read data from
|
|
// [iid] - Interface to unmarshal
|
|
// [fFirst] - First time unmarshalling
|
|
// [ppvObj] - Interface return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDAPI DfUnMarshalInterface(IStream *pstStm,
|
|
REFIID iid,
|
|
BOOL fFirst,
|
|
void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbRead;
|
|
IID iidSt;
|
|
DWORD mshlflags;
|
|
SafeIUnknown punk;
|
|
|
|
olLog(("--------::In DfUnMarshalInterface(%p, iid, %d, %p). "
|
|
"Context == %lX\n", pstStm, fFirst, ppvObj,
|
|
(ULONG)GetCurrentContextId()));
|
|
olDebugOut((DEB_TRACE, "In DfUnMarshalInterface("
|
|
"%p, ?, %d, %p)\n", pstStm, fFirst, ppvObj));
|
|
|
|
olChk(ValidateOutPtrBuffer(ppvObj));
|
|
*ppvObj = NULL;
|
|
olChk(ValidateInterface(pstStm, IID_IStream));
|
|
olChk(ValidateIid(iid));
|
|
if (!fFirst)
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
olHChk(pstStm->Read(&iidSt, sizeof(iidSt), &cbRead));
|
|
if (cbRead != sizeof(iidSt))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olHChk(pstStm->Read(&mshlflags, sizeof(mshlflags), &cbRead));
|
|
if (cbRead != sizeof(mshlflags))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olChk(VerifyIid(iid, iidSt));
|
|
|
|
#if !defined(MULTIHEAP)
|
|
olChk(DfSyncSharedMemory());
|
|
DfInitSharedMemBase();
|
|
#endif
|
|
if (IsEqualIID(iidSt, IID_ILockBytes))
|
|
sc = CFileStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
|
|
else if (IsEqualIID(iidSt, IID_IStream))
|
|
sc = CExposedStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
|
|
else if (IsEqualIID(iidSt, IID_IStorage))
|
|
sc = CExposedDocFile::Unmarshal(pstStm, (void **)&punk, mshlflags);
|
|
else
|
|
sc = E_NOINTERFACE;
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
if (!IsEqualIID(iid, iidSt))
|
|
{
|
|
sc = punk->QueryInterface(iid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
TRANSFER_INTERFACE(punk, IUnknown, ppvObj);
|
|
#if DBG == 1
|
|
void *pvCheck;
|
|
HRESULT scCheck = ((IUnknown*)*ppvObj)->QueryInterface(iidSt, &pvCheck);
|
|
olAssert (scCheck == S_OK || scCheck == STG_E_REVERTED);
|
|
if (SUCCEEDED(scCheck))
|
|
{
|
|
olAssert( pvCheck == *ppvObj );
|
|
((IUnknown*)pvCheck)->Release();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out DfUnMarshalInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
olLog(("--------::Out DfUnMarshalInterface(). "
|
|
"*ppvObj == %p, ret == %lX\n", *ppvObj, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetCoMarshalSize, private
|
|
//
|
|
// Synopsis: Gets the marshal size for an interface marshalled using
|
|
// CoMarshalInterface
|
|
//
|
|
// Arguments: [riid] - Interface id
|
|
// [punk] - Interface pointer
|
|
// [pv] - Context info
|
|
// [dwDestContext] - Destination context
|
|
// [pvDestContext] - Destination context
|
|
// [mshlflags] - Marshal flags
|
|
// [pcb] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcb]
|
|
//
|
|
// Algorithm: CoMarshalInterface is guaranteed to add no more than
|
|
// MARSHALINTERFACE_MIN bytes of overhead to a marshal
|
|
// Also, the standard marshaller takes no more than that
|
|
// So if the given object supports IMarshal, the return
|
|
// is IMarshal::GetMarshalSizeMax+MARSHALINTERFACE_MIN,
|
|
// otherwise it is just MARSHALINTERFACE_MIN
|
|
//
|
|
// History: 03-Aug-93 DrewB Created
|
|
//
|
|
// Notes: On 32-bit platforms, we can use CoGetMarshalSizeMax
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef WIN32
|
|
static SCODE GetCoMarshalSize(REFIID riid,
|
|
IUnknown *punk,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
void *pvDestContext,
|
|
DWORD mshlflags,
|
|
DWORD *pcb)
|
|
{
|
|
IMarshal *pmsh;
|
|
SCODE sc;
|
|
DWORD cb;
|
|
|
|
olDebugOut((DEB_ITRACE, "In GetCoMarshalSize("
|
|
"riid, %p, %p, %lu, %p, %lu, %p)\n", pv, punk, dwDestContext,
|
|
pvDestContext, mshlflags, pcb));
|
|
|
|
sc = DfGetScode(punk->QueryInterface(IID_IMarshal, (void **)&pmsh));
|
|
if (sc == E_NOINTERFACE)
|
|
{
|
|
*pcb = MARSHALINTERFACE_MIN;
|
|
sc = S_OK;
|
|
}
|
|
else if (SUCCEEDED(sc))
|
|
{
|
|
sc = DfGetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
&cb));
|
|
if (SUCCEEDED(sc))
|
|
*pcb = MARSHALINTERFACE_MIN+cb;
|
|
pmsh->Release();
|
|
}
|
|
|
|
olDebugOut((DEB_ITRACE, "Out GetCoMarshalSize => %lu, 0x%lX\n",
|
|
*pcb, sc));
|
|
return sc;
|
|
}
|
|
#else
|
|
#define GetCoMarshalSize(riid, punk, pv, dwDestContext, pvDestContext,\
|
|
mshlflags, pcb) \
|
|
GetScode(CoGetMarshalSizeMax(pcb, riid, punk, dwDestContext, \
|
|
pvDestContext, mshlflags))
|
|
#endif
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: GetStdMarshalSize, public
|
|
//
|
|
// Synopsis: Returns the size needed for a standard marshal buffer
|
|
//
|
|
// Arguments: [iid] - Requested marshal IID
|
|
// [iidObj] - IID of object being marshalled
|
|
// [dwDestContext] - Destination context
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Marshal flags
|
|
// [pcbSize] - Size return
|
|
// [cbSize] - Object private size
|
|
// [ppc] - Context to marshal or NULL
|
|
// [fMarshalOriginal] - Marshal original in context
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbSize]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE GetStdMarshalSize(REFIID iid,
|
|
REFIID iidObj,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
DWORD *pcbSize,
|
|
DWORD cbSize,
|
|
#ifdef ASYNC
|
|
CAsyncConnection *pcpoint,
|
|
BOOL fMarshalILBs,
|
|
#endif
|
|
CPerContext *ppc,
|
|
BOOL const fMarshalOriginal)
|
|
{
|
|
DWORD cbLBSize;
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_ITRACE, "In GetStdMarshalSize("
|
|
"iid, iidObj, %lu, %p, %lu, %p, %lu, %p, %d)\n",
|
|
dwDestContext, pvDestContext, mshlflags, pcbSize, cbSize, ppc,
|
|
fMarshalOriginal));
|
|
|
|
olChk(ValidateOutBuffer(pcbSize, sizeof(DWORD)));
|
|
*pcbSize = 0;
|
|
olChk(ValidateIid(iid));
|
|
olChk(VerifyIid(iid, iidObj));
|
|
|
|
if (((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
|| pvDestContext != NULL)
|
|
olErr(EH_Err, STG_E_INVALIDFLAG);
|
|
|
|
*pcbSize = CBSTDMARSHALSIZE+cbSize;
|
|
#ifdef MULTIHEAP
|
|
*pcbSize += sizeof(ULONG)+sizeof(ContextId)+sizeof(CPerContext*);
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
*pcbSize += sizeof(CMarshalList*);
|
|
#endif
|
|
#ifdef ASYNC
|
|
if ((ppc) && fMarshalILBs)
|
|
#else
|
|
if (ppc)
|
|
#endif
|
|
{
|
|
*pcbSize += sizeof(CGlobalContext *);
|
|
olChk(GetCoMarshalSize(IID_ILockBytes,
|
|
(ILockBytes *)ppc->GetBase(),
|
|
NULL, dwDestContext, pvDestContext,
|
|
mshlflags, &cbLBSize));
|
|
*pcbSize += cbLBSize;
|
|
olChk(GetCoMarshalSize(IID_ILockBytes,
|
|
(ILockBytes *)ppc->GetDirty(),
|
|
NULL, dwDestContext, pvDestContext,
|
|
mshlflags, &cbLBSize));
|
|
*pcbSize += cbLBSize;
|
|
if (fMarshalOriginal)
|
|
{
|
|
olChk(GetCoMarshalSize(IID_ILockBytes,
|
|
(ILockBytes *)ppc->GetOriginal(),
|
|
NULL, dwDestContext, pvDestContext,
|
|
mshlflags, &cbLBSize));
|
|
*pcbSize += cbLBSize;
|
|
}
|
|
}
|
|
#ifdef ASYNC
|
|
//BOOL determines whether we have a connection to marshal or not
|
|
*pcbSize += sizeof(BOOL);
|
|
if ((pcpoint) && (pcpoint->GetMarshalPoint() != NULL))
|
|
{
|
|
ULONG cbConnectSize;
|
|
//Async flags
|
|
*pcbSize += sizeof(DWORD);
|
|
olChk(GetCoMarshalSize(IID_IDocfileAsyncConnectionPoint,
|
|
pcpoint->GetMarshalPoint(),
|
|
NULL, dwDestContext, pvDestContext,
|
|
mshlflags, &cbConnectSize));
|
|
*pcbSize += cbConnectSize;
|
|
}
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "Out GetStdMarshalSize\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: StartMarshal, public
|
|
//
|
|
// Synopsis: Writes standard marshal header
|
|
//
|
|
// Arguments: [pstStm] - Stream to write marshal data into
|
|
// [iid] - Interface to marshal
|
|
// [iidObj] - Object being marshalled
|
|
// [mshlflags] - Marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE StartMarshal(IStream *pstStm,
|
|
REFIID iid,
|
|
REFIID iidObj,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbWritten;
|
|
|
|
olDebugOut((DEB_ITRACE, "In StartMarshal(%p, iid, iidObj, %lu)\n",
|
|
pstStm, mshlflags));
|
|
|
|
olChk(ValidateInterface(pstStm, IID_IStream));
|
|
olChk(ValidateIid(iid));
|
|
olChk(VerifyIid(iid, iidObj));
|
|
olHChk(pstStm->Write((void *)&iidObj, sizeof(iidObj), &cbWritten));
|
|
if (cbWritten != sizeof(iidObj))
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
#if defined(_WIN64)
|
|
mshlflags |= MSHLFLAGS_STG_WIN64;
|
|
#endif
|
|
olHChk(pstStm->Write((void *)&mshlflags, sizeof(mshlflags), &cbWritten));
|
|
if (cbWritten != sizeof(mshlflags))
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
|
|
olDebugOut((DEB_ITRACE, "Out StartMarshal\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SkipStdMarshal, public
|
|
//
|
|
// Synopsis: Skips over the standard marshal data
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [piid] - IID return
|
|
// [pmshlflags] - Return marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [piid]
|
|
// [pmshlflags]
|
|
//
|
|
// History: 20-Nov-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifdef WIN32
|
|
SCODE SkipStdMarshal(IStream *pstm, IID *piid, DWORD *pmshlflags)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbRead;
|
|
|
|
olDebugOut((DEB_ITRACE, "In SkipStdMarshal(%p, %p, %p)\n", pstm,
|
|
piid, pmshlflags));
|
|
|
|
olHChk(pstm->Read(piid, sizeof(IID), &cbRead));
|
|
if (cbRead != sizeof(IID))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olHChk(pstm->Read(pmshlflags, sizeof(DWORD), &cbRead));
|
|
if (cbRead != sizeof(DWORD))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
|
|
olDebugOut((DEB_ITRACE, "Out SkipStdMarshal => %lX\n", sc));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
#endif
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: MarshalPointer, public
|
|
//
|
|
// Synopsis: Marshals a pointer
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [pv] - Pointer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Aug-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE MarshalPointer(IStream *pstm, void *pv)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbWritten;
|
|
|
|
olDebugOut((DEB_ITRACE, "In MarshalPointer(%p, %p)\n", pstm, pv));
|
|
|
|
#ifdef USEBASED
|
|
ULONG ul = (ULONG)((ULONG_PTR)pv - (ULONG_PTR)DFBASEPTR);
|
|
#endif
|
|
|
|
sc = DfGetScode(pstm->Write(&ul, sizeof(ul), &cbWritten));
|
|
if (SUCCEEDED(sc) && cbWritten != sizeof(ul))
|
|
sc = STG_E_WRITEFAULT;
|
|
|
|
olDebugOut((DEB_ITRACE, "Out MarshalPointer\n"));
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: MarshalContext, public
|
|
//
|
|
// Synopsis: Marshals a context
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [ppc] - Context
|
|
// [dwDestContext] - Destination context
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Marshal flags
|
|
// [fMarshalOriginal] - Marshal original or not
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Aug-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE MarshalContext(IStream *pstm,
|
|
CPerContext *ppc,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
#ifdef ASYNC
|
|
BOOL const fMarshalILBs,
|
|
#endif
|
|
BOOL const fMarshalOriginal)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_ITRACE, "In MarshalContext(%p, %p, %lu, %p, %lu, %d)\n",
|
|
pstm, ppc, dwDestContext, pvDestContext, mshlflags,
|
|
fMarshalOriginal));
|
|
|
|
olChk(MarshalPointer(pstm, ppc->GetGlobal()));
|
|
|
|
#ifdef ASYNC
|
|
if (fMarshalILBs)
|
|
#endif
|
|
{
|
|
olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetBase(),
|
|
dwDestContext, pvDestContext, mshlflags));
|
|
olHChk(CoMarshalInterface(pstm, IID_ILockBytes,
|
|
(ILockBytes *)ppc->GetDirty(),
|
|
dwDestContext, pvDestContext, mshlflags));
|
|
if (fMarshalOriginal)
|
|
olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetOriginal(),
|
|
dwDestContext, pvDestContext, mshlflags));
|
|
}
|
|
|
|
olDebugOut((DEB_ITRACE, "Out MarshalContext\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: UnmarshalPointer, public
|
|
//
|
|
// Synopsis: Unmarshals a pointer
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [ppv] - Pointer return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppv]
|
|
//
|
|
// History: 20-Aug-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE UnmarshalPointer(IStream *pstm,
|
|
void **ppv)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbRead;
|
|
ULONG ul;
|
|
|
|
olDebugOut((DEB_ITRACE, "In UnmarshalPointer(%p, %p)\n", pstm, ppv));
|
|
|
|
sc = DfGetScode(pstm->Read(&ul, sizeof(ul), &cbRead));
|
|
if (SUCCEEDED(sc) && cbRead != sizeof(ul))
|
|
sc = STG_E_READFAULT;
|
|
|
|
#ifdef USEBASED
|
|
*ppv = (void *)(ul + (BYTE*)DFBASEPTR);
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "Out UnmarshalPointer => %p\n", *ppv));
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Function: UnmarshalContext, public
|
|
//
|
|
// Synopsis: Unmarshals a context
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [pppc] - Context return
|
|
// [fUnmarshalOriginal] - Marshalled original exists or not
|
|
// [fIsRoot] - Root unmarshal or not
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pppc]
|
|
//
|
|
// History: 20-Aug-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE UnmarshalContext(IStream *pstm,
|
|
CGlobalContext *pgc,
|
|
CPerContext **pppc,
|
|
DWORD mshlflags,
|
|
#ifdef ASYNC
|
|
BOOL const fUnmarshalILBs,
|
|
#endif
|
|
BOOL const fUnmarshalOriginal,
|
|
#ifdef MULTIHEAP
|
|
ContextId cntxid,
|
|
#endif
|
|
BOOL const fIsRoot)
|
|
{
|
|
BOOL fNewContext;
|
|
ILockBytes *plkbBase = NULL;
|
|
CFileStream *pfstDirty = NULL;
|
|
ILockBytes *plkbOriginal = NULL;
|
|
SCODE sc, sc2;
|
|
CPerContext *ppc;
|
|
ULONG ulOpenLock = 0;
|
|
|
|
olDebugOut((DEB_ITRACE, "In UnmarshalContext(%p, %p, %lu, %d, %d)\n",
|
|
pstm, pppc, mshlflags, fUnmarshalOriginal, fIsRoot));
|
|
|
|
ppc = pgc->Find(GetCurrentContextId());
|
|
|
|
// ignore leaked contexts from processes that died and their ID got reused
|
|
if (ppc != NULL && !ppc->IsHandleValid())
|
|
ppc = NULL;
|
|
|
|
fNewContext = (ppc == NULL);
|
|
|
|
#ifdef MULTIHEAP
|
|
// when marshaling to the same process, use the same heap
|
|
// when marshaling to a different process, check the context list
|
|
// if there is a matching percontext, use that heap
|
|
|
|
if (GetCurrentContextId() != cntxid && ppc != NULL)
|
|
{
|
|
ppc->SetThreadAllocatorState(NULL); // set new base
|
|
|
|
// Whenever we unmarshal into a different process, we create
|
|
// a new mapping (of the same heap),
|
|
// even if a mapping of the same heap may already exist in
|
|
// the same process. For pointer identity, it is essential
|
|
// that we find and use the existing heap.
|
|
// process A ---marshal---> process B ---marshal----> process A
|
|
// The "final" unmarshaled exposed object in process A should
|
|
// match the original pointer used when the exposed object
|
|
// was originally marshaled. To do this, we check the global
|
|
// context list, and if there's a percontext match, we use
|
|
// its allocator and heap mapping (and don't create a new one).
|
|
// However, to actually search the global context list (it
|
|
// lives in shared memory), we need a temporary mapping until
|
|
// a matching percontext can be found and reused.
|
|
// If not, then a new percontext is allocated and the temporary
|
|
// mapping becomes "permanent" for the lifetime of the new percontext.
|
|
}
|
|
#endif
|
|
if (fNewContext)
|
|
{
|
|
olMemTo(EH_Open,
|
|
ppc = new (pgc->GetMalloc()) CPerContext(pgc->GetMalloc()));
|
|
olChkTo(EH_ppc, ppc->InitFromGlobal(pgc));
|
|
}
|
|
|
|
#ifdef MULTIHEAP
|
|
// take the ownership of the heap away from the temporary
|
|
ppc->SetAllocatorState (NULL, &g_smAllocator);
|
|
|
|
//ppc from above may have used incorrect base (base of temporary heap).
|
|
// Since we're returning and storing an unbased pointer, we need to get
|
|
// the real absolute pointer here. At this point, ppc will always be in
|
|
// the context list, so we don't need to worry about a NULL return.
|
|
ppc = pgc->Find(GetCurrentContextId());
|
|
|
|
olAssert(ppc != NULL);
|
|
#endif
|
|
|
|
#ifdef ASYNC
|
|
if (fUnmarshalILBs)
|
|
{
|
|
#endif
|
|
|
|
// attempt to unmarshal all the interfaces first. this makes cleanup
|
|
// easier.
|
|
sc = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&plkbBase);
|
|
sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&pfstDirty);
|
|
|
|
sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
|
|
|
|
if (fUnmarshalOriginal)
|
|
{
|
|
sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes,
|
|
(void **)&plkbOriginal);
|
|
sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
|
|
}
|
|
|
|
// cleanup if any failure so far
|
|
olChkTo(EH_plkbOriginal, sc);
|
|
|
|
if (ppc->GetBase() != NULL)
|
|
{
|
|
// already have context, just release the things we unmarshaled.
|
|
plkbBase->Release();
|
|
plkbBase = NULL;
|
|
}
|
|
|
|
if (ppc->GetDirty() != NULL)
|
|
{
|
|
pfstDirty->Release();
|
|
pfstDirty = NULL;
|
|
}
|
|
|
|
if ((plkbOriginal) && (ppc->GetOriginal() != NULL))
|
|
{
|
|
plkbOriginal->Release();
|
|
plkbOriginal = NULL;
|
|
}
|
|
else if ((NULL == plkbOriginal) && plkbBase)
|
|
{
|
|
plkbBase->AddRef();
|
|
plkbOriginal = plkbBase;
|
|
}
|
|
olAssert (plkbOriginal != NULL || ppc->GetOriginal() != NULL);
|
|
|
|
// Make sure there is a reserved handle if this is a root
|
|
// file-based lockbytes
|
|
if (fIsRoot)
|
|
{
|
|
IFileLockBytes *pflkb;
|
|
|
|
if (SUCCEEDED(DfGetScode((plkbOriginal ? plkbOriginal :
|
|
ppc->GetOriginal())->
|
|
QueryInterface(IID_IFileLockBytes,
|
|
(void **)&pflkb))))
|
|
{
|
|
sc = DfGetScode(pflkb->ReserveHandle());
|
|
pflkb->Release();
|
|
olChkTo(EH_plkbOriginal, sc);
|
|
}
|
|
}
|
|
#ifdef ASYNC
|
|
}
|
|
#endif
|
|
|
|
if (fNewContext)
|
|
{
|
|
olAssert(plkbOriginal != NULL);
|
|
|
|
// Take open locks if necessary
|
|
if (fIsRoot && pgc->TakeLock())
|
|
{
|
|
olChkTo(EH_plkbOriginal,
|
|
GetOpen(plkbOriginal, pgc->GetOpenLockFlags(),
|
|
FALSE, &ulOpenLock));
|
|
}
|
|
|
|
ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
|
|
}
|
|
else
|
|
{
|
|
if (ppc->GetBase() == NULL)
|
|
{
|
|
//Fill in the ILB fields
|
|
ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
|
|
}
|
|
ppc->AddRef();
|
|
|
|
}
|
|
|
|
*pppc = ppc;
|
|
|
|
olDebugOut((DEB_ITRACE, "Out UnmarshalContext => %p\n", *pppc));
|
|
return S_OK;
|
|
|
|
EH_ppc:
|
|
// Preserve plkbOriginal so the lock is released even after the
|
|
// context releases things;
|
|
plkbOriginal->AddRef();
|
|
ppc->Release();
|
|
pfstDirty = NULL;
|
|
plkbBase = NULL;
|
|
EH_Open:
|
|
if (ulOpenLock != 0)
|
|
{
|
|
olAssert(plkbOriginal != NULL);
|
|
ReleaseOpen(plkbOriginal, pgc->GetOpenLockFlags(), ulOpenLock);
|
|
}
|
|
EH_plkbOriginal:
|
|
if (plkbOriginal)
|
|
plkbOriginal->Release();
|
|
|
|
if (pfstDirty)
|
|
pfstDirty->Release();
|
|
if (plkbBase)
|
|
plkbBase->Release();
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseContext, public
|
|
//
|
|
// Synopsis: Releases references for a context's marshal data
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [fHasOriginal] - Original is marshalled
|
|
// [mshlflags] - Marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Nov-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifdef WIN32
|
|
SCODE ReleaseContext(IStream *pstm,
|
|
#ifdef ASYNC
|
|
BOOL const fUnmarshalILBs,
|
|
#endif
|
|
BOOL const fHasOriginal,
|
|
DWORD mshlflags)
|
|
{
|
|
CGlobalContext *pgc;
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_ITRACE, "In ReleaseContext(%p, %d, %lu)\n", pstm,
|
|
fHasOriginal, mshlflags));
|
|
|
|
olChk(UnmarshalPointer(pstm, (void **)&pgc));
|
|
if (fUnmarshalILBs)
|
|
{
|
|
olHChk(CoReleaseMarshalData(pstm));
|
|
olHChk(CoReleaseMarshalData(pstm));
|
|
if (fHasOriginal)
|
|
olHChk(CoReleaseMarshalData(pstm));
|
|
}
|
|
|
|
olDebugOut((DEB_ITRACE, "Out ReleaseContext\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MULTIHEAP
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: MarshalSharedMemory, public
|
|
//
|
|
// Synopsis: marshals the shared memory context
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [ppc] - per context structure
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Dec-95 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE MarshalSharedMemory (IStream *pstStm, CPerContext *ppc)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ULONG cbWritten;
|
|
ULONG ulHeapName;
|
|
ContextId cntxid = GetCurrentContextId();
|
|
ULONGLONG ulppc = (ULONGLONG) ppc;
|
|
|
|
ulHeapName = g_smAllocator.GetHeapName();
|
|
olHChk(pstStm->Write((void*) &ulHeapName, sizeof(ulHeapName), &cbWritten));
|
|
if (cbWritten != sizeof(ulHeapName))
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
olHChk(pstStm->Write((void*) &cntxid, sizeof(cntxid), &cbWritten));
|
|
if (cbWritten != sizeof(cntxid))
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
olHChk(pstStm->Write((void*) &ulppc, sizeof(ulppc), &cbWritten));
|
|
if (cbWritten != sizeof(ulppc))
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SkipSharedMemory, public
|
|
//
|
|
// Synopsis: Cleanup marshaling packet during CoReleaseMarshalData
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Dec-95 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE SkipSharedMemory (IStream *pstStm, DWORD mshlflags)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ULONG cbRead;
|
|
ULONG ulHeapName;
|
|
ContextId cntxid;
|
|
ULONGLONG ulppc;
|
|
|
|
olChk(pstStm->Read(&ulHeapName, sizeof(ulHeapName), &cbRead));
|
|
if (cbRead != sizeof(ulHeapName))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olChk(pstStm->Read(&cntxid, sizeof(cntxid), &cbRead));
|
|
if (cbRead != sizeof(cntxid))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olChk(pstStm->Read(&ulppc, sizeof(ulppc), &cbRead));
|
|
if (cbRead != sizeof(ulppc))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UnMarshalSharedMemory, public
|
|
//
|
|
// Synopsis: Unmarshals the shared memory context
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Dec-95 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE UnmarshalSharedMemory (IStream *pstStm, DWORD mshlflags,
|
|
CPerContext *ppcOwner, ContextId *pcntxid)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ULONG cbRead;
|
|
ULONG ulHeapName;
|
|
ContextId cntxid;
|
|
CPerContext *ppc;
|
|
ULONGLONG ulppc;
|
|
|
|
olHChk(pstStm->Read(&ulHeapName, sizeof(ulHeapName), &cbRead));
|
|
if (cbRead != sizeof(ulHeapName))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olHChk(pstStm->Read(&cntxid, sizeof(cntxid), &cbRead));
|
|
if (cbRead != sizeof(cntxid))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
olHChk(pstStm->Read(&ulppc, sizeof(ulppc), &cbRead));
|
|
if (cbRead != sizeof(ulppc))
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
|
|
ppc = (CPerContext *) ulppc;
|
|
|
|
#if defined(_WIN64)
|
|
if ((mshlflags & MSHLFLAGS_STG_WIN64) == 0)
|
|
olErr (EH_Err, STG_E_INVALIDFUNCTION);
|
|
#else
|
|
if ((mshlflags & MSHLFLAGS_STG_WIN64) != 0)
|
|
olErr (EH_Err, STG_E_INVALIDFUNCTION);
|
|
#endif
|
|
|
|
*pcntxid = cntxid;
|
|
if (GetCurrentContextId() == cntxid)
|
|
{
|
|
// marshaling to the same process, reuse the per context and heap
|
|
// in the case of marshaling to another thread
|
|
// the per context takes ownership of the thread's allocator
|
|
ppc->SetThreadAllocatorState(NULL);
|
|
}
|
|
else
|
|
{
|
|
// marshaling to another process on the same machine
|
|
// if the name of heap is different that current one, open it
|
|
if (g_smAllocator.GetHeapName() != ulHeapName)
|
|
{
|
|
DfInitSharedMemBase();
|
|
olChk(DfSyncSharedMemory(ulHeapName));
|
|
}
|
|
|
|
// Because the unmarshaling code calls IStream::Read,
|
|
// possibly using another shared heap, we need a temporary
|
|
// owner until the real CPerContext is unmarshaled
|
|
ppcOwner->GetThreadAllocatorState();
|
|
ppcOwner->SetThreadAllocatorState(NULL);
|
|
}
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef ASYNC
|
|
SCODE MarshalConnection(IStream *pstm,
|
|
CAsyncConnection *pcpoint,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbWritten;
|
|
IDocfileAsyncConnectionPoint *pdacp = pcpoint->GetMarshalPoint();
|
|
BOOL fIsInitialized = (pdacp != NULL);
|
|
|
|
//Write out the pointer.
|
|
olHChk(pstm->Write(&fIsInitialized,
|
|
sizeof(BOOL),
|
|
&cbWritten));
|
|
if (cbWritten != sizeof(BOOL))
|
|
{
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
|
|
if (fIsInitialized)
|
|
{
|
|
//If the pointer was NULL, we don't need to worry about actually
|
|
//marshalling anything, and we can detect this in the unmarshal
|
|
//path. If it wasn't NULL, we need to store some additional
|
|
//information: The async flags and the actual connection point,
|
|
//which will be standard marshalled.
|
|
DWORD dwAsyncFlags = pcpoint->GetAsyncFlags();
|
|
|
|
olChk(pstm->Write(&dwAsyncFlags, sizeof(DWORD), &cbWritten));
|
|
if (cbWritten != sizeof(DWORD))
|
|
{
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
}
|
|
|
|
//Finally, standard marshal the connection point itself.
|
|
olHChk(CoMarshalInterface(pstm,
|
|
IID_IDocfileAsyncConnectionPoint,
|
|
pdacp,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags));
|
|
}
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
SCODE UnmarshalConnection(IStream *pstm,
|
|
DWORD *pdwAsyncFlags,
|
|
IDocfileAsyncConnectionPoint **ppdacp,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
BOOL fIsInitialized;
|
|
ULONG cbRead;
|
|
|
|
*ppdacp = NULL;
|
|
*pdwAsyncFlags = 0;
|
|
|
|
olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
|
|
if (cbRead != sizeof(BOOL))
|
|
{
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
|
|
if (fIsInitialized)
|
|
{
|
|
olChk(pstm->Read(pdwAsyncFlags, sizeof(DWORD), &cbRead));
|
|
if (cbRead != sizeof(DWORD))
|
|
{
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
sc = CoUnmarshalInterface(pstm,
|
|
IID_IDocfileAsyncConnectionPoint,
|
|
(void **)ppdacp);
|
|
}
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
SCODE ReleaseConnection(IStream *pstm, DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbRead;
|
|
BOOL fIsInitialized;
|
|
DWORD dwAsyncFlags;
|
|
|
|
olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
|
|
if (cbRead != sizeof(BOOL))
|
|
{
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
if (fIsInitialized)
|
|
{
|
|
olChk(pstm->Read(&dwAsyncFlags, sizeof(DWORD), &cbRead));
|
|
if (cbRead != sizeof(DWORD))
|
|
{
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
olHChk(CoReleaseMarshalData(pstm));
|
|
}
|
|
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
#endif
|