//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: marshl.cxx // // Contents: Marshal/Unmarshal implementation // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include #include // 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