windows-nt/Source/XPSP1/NT/com/ole32/stg/exp/marshl.cxx
2020-09-26 16:20:57 +08:00

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