2416 lines
68 KiB
C++
2416 lines
68 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) 1992, Microsoft Corporation.
|
|
//
|
|
// File: expst.cxx
|
|
//
|
|
// Contents: CExposedStream code
|
|
//
|
|
// History: 28-Feb-92 PhilipLa Created.
|
|
// 20-Jun-96 MikeHill Fixed the PropSet version of
|
|
// Lock to check the result of TakeSem.
|
|
// 1-Jul-96 MikeHill - Removed Win32 SEH from PropSet code.
|
|
// - Receive NTPROP in propset Open method.
|
|
// 11-Feb-97 Danl - Changed CMappedStream to IMappedStream
|
|
// - Added QI support for IMappedStream.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <exphead.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <pbstream.hxx>
|
|
#include <expst.hxx>
|
|
#include <lock.hxx>
|
|
#include <seekptr.hxx>
|
|
#include <marshl.hxx>
|
|
#include <logfile.hxx>
|
|
#include <privguid.h> // IID_IMappedStream
|
|
#include <expparam.hxx>
|
|
|
|
#ifndef LARGE_STREAMS
|
|
// Maximum stream size supported by exposed streams
|
|
// This is MAX_ULONG with one subtracted so that
|
|
// the seek pointer has a spot to sit even at the
|
|
// end of the stream
|
|
#define CBMAXSTREAM 0xfffffffeUL
|
|
// Maximum seek pointer value
|
|
#define CBMAXSEEK (CBMAXSTREAM+1)
|
|
#endif
|
|
|
|
#if DBG
|
|
DWORD MyGetLastError()
|
|
{
|
|
return GetLastError();
|
|
}
|
|
#endif
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::CExposedStream, public
|
|
//
|
|
// Synopsis: Empty object constructor
|
|
//
|
|
// History: 30-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
|
|
CExposedStream::CExposedStream(void)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::CExposedStream()\n"));
|
|
_pdfb = NULL;
|
|
_ppc = NULL;
|
|
_cReferences = 0;
|
|
_psp = NULL;
|
|
_pst = NULL;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Init, public
|
|
//
|
|
// Synopsis: Base constructor
|
|
//
|
|
// Arguments: [pst] - Public stream
|
|
// [pdfb] - DocFile basis
|
|
// [ppc] - Context
|
|
// [psp] - Seek pointer or NULL for new seek pointer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Feb-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedStream::Init(CPubStream *pst,
|
|
CDFBasis *pdfb,
|
|
CPerContext *ppc,
|
|
CSeekPointer *psp)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Init("
|
|
"%p, %p, %p, %p)\n",
|
|
pst, pdfb, ppc, psp));
|
|
|
|
if (psp == NULL)
|
|
{
|
|
CSeekPointer *pspTemp;
|
|
olMem(pspTemp = new (pdfb->GetMalloc()) CSeekPointer(0));
|
|
_psp = P_TO_BP(CBasedSeekPointerPtr, pspTemp);
|
|
}
|
|
else
|
|
_psp = P_TO_BP(CBasedSeekPointerPtr, psp);
|
|
_ppc = ppc;
|
|
_pst = P_TO_BP(CBasedPubStreamPtr, pst);
|
|
_pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
|
|
_pdfb->vAddRef();
|
|
_cReferences = 1;
|
|
_sig = CEXPOSEDSTREAM_SIG;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Init\n"));
|
|
return S_OK;
|
|
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
SCODE CExposedStream::InitMarshal(CPubStream *pst,
|
|
CDFBasis *pdfb,
|
|
CPerContext *ppc,
|
|
DWORD dwAsyncFlags,
|
|
IDocfileAsyncConnectionPoint *pdacp,
|
|
CSeekPointer *psp)
|
|
{
|
|
SCODE sc;
|
|
sc = CExposedStream::Init(pst,
|
|
pdfb,
|
|
ppc,
|
|
psp);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
sc = _cpoint.InitMarshal(this, dwAsyncFlags, pdacp);
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::~CExposedStream, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedStream::~CExposedStream(void)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::~CExposedStream\n"));
|
|
olAssert(_cReferences == 0);
|
|
_sig = CEXPOSEDSTREAM_SIGDEL;
|
|
|
|
//In order to call into the tree, we need to take the mutex.
|
|
//The mutex may get deleted in _ppc->Release(), so we can't
|
|
//release it here. The mutex actually gets released in
|
|
//CPerContext::Release() or in the CPerContext destructor.
|
|
SCODE sc;
|
|
|
|
#if !defined(MULTIHEAP)
|
|
// TakeSem and ReleaseSem are moved to the Release Method
|
|
// so that the deallocation for this object is protected
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
#endif //MULTIHEAP
|
|
|
|
|
|
if (_pst)
|
|
_pst->CPubStream::vRelease();
|
|
if (_psp)
|
|
_psp->CSeekPointer::vRelease();
|
|
if (_pdfb)
|
|
_pdfb->CDFBasis::vRelease();
|
|
#if !defined(MULTIHEAP)
|
|
if (_ppc)
|
|
{
|
|
if (_ppc->Release() > 0)
|
|
ReleaseSem(sc);
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release();
|
|
#endif
|
|
#endif // MULTIHEAP
|
|
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::~CExposedStream\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Read, public
|
|
//
|
|
// Synopsis: Read from a stream
|
|
//
|
|
// Arguments: [pb] - Buffer
|
|
// [cb] - Count of bytes to read
|
|
// [pcbRead] - Return number of bytes read
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbRead]
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
ULONG cbRead = 0;
|
|
|
|
olLog(("%p::In CExposedStream::Read(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbRead));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Read %p(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbRead));
|
|
|
|
OL_VALIDATE(Read(pb, cb, pcbRead));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeReadAccess();
|
|
sc = _pst->ReadAt(_psp->GetPos(), pb, cb, (ULONG STACKBASED *)&cbRead);
|
|
#ifndef LARGE_STREAMS
|
|
olAssert(CBMAXSEEK-_psp->GetPos() >= cbRead);
|
|
#endif
|
|
_psp->SetPos(_psp->GetPos()+cbRead);
|
|
pb = (BYTE *)pb + cbRead;
|
|
cb -= cbRead;
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Read => %lu\n", cbRead));
|
|
|
|
EH_Err:
|
|
if (pcbRead)
|
|
{
|
|
// May fault and leave stream seek pointer changed
|
|
// This is acceptable
|
|
*pcbRead = cbRead;
|
|
olLog(("%p::Out CExposedStream::Read(). *pcbRead == %lu, ret = %lx\n",
|
|
this, *pcbRead, sc));
|
|
}
|
|
else
|
|
{
|
|
olLog(("%p::Out CExposedStream::Read(). ret == %lx\n", this, sc));
|
|
}
|
|
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Write, public
|
|
//
|
|
// Synopsis: Write to a stream
|
|
//
|
|
// Arguments: [pb] - Buffer
|
|
// [cb] - Count of bytes to write
|
|
// [pcbWritten] - Return of bytes written
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbWritten]
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Write(
|
|
VOID const HUGEP *pb,
|
|
ULONG cb,
|
|
ULONG *pcbWritten)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
ULONG cbWritten = 0;
|
|
|
|
olLog(("%p::In CExposedStream::Write(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbWritten));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Write %p(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbWritten));
|
|
|
|
OL_VALIDATE(Write(pb, cb, pcbWritten));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
sc = _pst->WriteAt(_psp->GetPos(), pb, cb,
|
|
(ULONG STACKBASED *)&cbWritten);
|
|
#ifndef LARGE_STREAMS
|
|
olAssert(CBMAXSEEK-_psp->GetPos() >= cbWritten);
|
|
#endif
|
|
_psp->SetPos(_psp->GetPos()+cbWritten);
|
|
pb = (BYTE *)pb + cbWritten;
|
|
cb -= cbWritten;
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Write => %lu\n",
|
|
cbWritten));
|
|
EH_Err:
|
|
if (pcbWritten)
|
|
{
|
|
// May fault but that's acceptable
|
|
*pcbWritten = cbWritten;
|
|
olLog(("%p::Out CExposedStream::Write(). "
|
|
"*pcbWritten == %lu, ret = %lx\n",
|
|
this, *pcbWritten, sc));
|
|
}
|
|
else
|
|
{
|
|
olLog(("%p::Out CExposedStream::Write(). ret == %lx\n", this, sc));
|
|
}
|
|
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Seek, public
|
|
//
|
|
// Synopsis: Seek to a point in a stream
|
|
//
|
|
// Arguments: [dlibMove] - Offset to move by
|
|
// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
|
|
// [plibNewPosition] - Return of new offset
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [plibNewPosition]
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER *plibNewPosition)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
#ifdef LARGE_STREAMS
|
|
LONGLONG lMove;
|
|
#else
|
|
LONG lMove;
|
|
#endif
|
|
ULARGE_INTEGER ulPos;
|
|
|
|
olLog(("%p::In CExposedStream::Seek(%ld, %lu, %p)\n",
|
|
this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Seek %p(%ld, %lu, %p)\n",
|
|
this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
|
|
|
|
OL_VALIDATE(Seek(dlibMove, dwOrigin, plibNewPosition));
|
|
|
|
if (dwOrigin == STREAM_SEEK_SET)
|
|
{
|
|
#ifdef LARGE_STREAMS
|
|
if (dlibMove.QuadPart < 0)
|
|
olErr (EH_Err, STG_E_INVALIDFUNCTION);
|
|
#else
|
|
// Truncate dlibMove to 32 bits
|
|
// Make sure we don't seek too far
|
|
if (LIGetHigh(dlibMove) != 0)
|
|
LISet32(dlibMove, 0xffffffff);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifndef LARGE_STREAMS
|
|
// High dword must be zero for positive values or -1 for
|
|
// negative values
|
|
// Additionally, for negative values, the low dword can't
|
|
// exceed -0x80000000 because the 32nd bit is the sign
|
|
// bit
|
|
if (LIGetHigh(dlibMove) > 0 ||
|
|
(LIGetHigh(dlibMove) == 0 &&
|
|
LIGetLow(dlibMove) >= 0x80000000))
|
|
LISet32(dlibMove, 0x7fffffff);
|
|
else if (LIGetHigh(dlibMove) < -1 ||
|
|
(LIGetHigh(dlibMove) == -1 &&
|
|
LIGetLow(dlibMove) <= 0x7fffffff))
|
|
LISet32(dlibMove, 0x80000000);
|
|
#endif
|
|
}
|
|
|
|
#ifdef LARGE_STREAMS
|
|
lMove = dlibMove.QuadPart;
|
|
#else
|
|
lMove = (LONG)LIGetLow(dlibMove);
|
|
#endif
|
|
olChk(Validate());
|
|
|
|
//ASYNC Note: We probably don't need this pending loop in Seek
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
olChk(_pst->CheckReverted());
|
|
SafeReadAccess();
|
|
|
|
#ifdef LARGE_STREAMS
|
|
ulPos.QuadPart = _psp->GetPos();
|
|
#else
|
|
ULISet32(ulPos, _psp->GetPos());
|
|
#endif
|
|
switch(dwOrigin)
|
|
{
|
|
case STREAM_SEEK_SET:
|
|
#ifdef LARGE_STREAMS
|
|
ulPos.QuadPart = lMove;
|
|
#else
|
|
ULISetLow(ulPos, (ULONG)lMove);
|
|
#endif
|
|
break;
|
|
|
|
case STREAM_SEEK_END:
|
|
#ifdef LARGE_STREAMS
|
|
ULONGLONG cbSize;
|
|
#else
|
|
ULONG cbSize;
|
|
#endif
|
|
olChk(_pst->GetSize(&cbSize));
|
|
if (lMove < 0)
|
|
{
|
|
#ifdef LARGE_STREAMS
|
|
if ((ULONGLONG)(-lMove) > cbSize)
|
|
#else
|
|
if ((ULONG)(-lMove) > cbSize)
|
|
#endif
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
}
|
|
#ifdef LARGE_STREAMS
|
|
ulPos.QuadPart = cbSize+lMove;
|
|
#else
|
|
else if ((ULONG)lMove > CBMAXSEEK-cbSize)
|
|
lMove = (LONG)(CBMAXSEEK-cbSize);
|
|
ULISetLow(ulPos, cbSize+lMove);
|
|
#endif
|
|
break;
|
|
|
|
case STREAM_SEEK_CUR:
|
|
if (lMove < 0)
|
|
{
|
|
#ifdef LARGE_STREAMS
|
|
if ((ULONGLONG)(-lMove) > _psp->GetPos())
|
|
#else
|
|
if ((ULONG)(-lMove) > _psp->GetPos())
|
|
#endif
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
}
|
|
#ifdef LARGE_STREAMS
|
|
ulPos.QuadPart = _psp->GetPos()+lMove;
|
|
#else
|
|
else if ((ULONG)lMove > CBMAXSEEK-_psp->GetPos())
|
|
lMove = (LONG)(CBMAXSEEK-_psp->GetPos());
|
|
ULISetLow(ulPos, _psp->GetPos()+lMove);
|
|
#endif
|
|
break;
|
|
}
|
|
#ifdef LARGE_STREAMS
|
|
_psp->SetPos(ulPos.QuadPart);
|
|
#else
|
|
_psp->SetPos(ULIGetLow(ulPos));
|
|
#endif
|
|
|
|
if (plibNewPosition)
|
|
// May fault but that's acceptable
|
|
*plibNewPosition = ulPos;
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Seek => %lu\n",
|
|
ULIGetLow(ulPos)));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Seek(). ulPos == %lu, ret == %lx\n",
|
|
this, ULIGetLow(ulPos), sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetSize, public
|
|
//
|
|
// Synopsis: Sets the size of a stream
|
|
//
|
|
// Arguments: [ulNewSize] - New size
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedStream::SetSize(%lu)\n",
|
|
this, ULIGetLow(ulNewSize)));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::SetSize %p(%lu)\n",
|
|
this, ULIGetLow(ulNewSize)));
|
|
|
|
OL_VALIDATE(SetSize(ulNewSize));
|
|
|
|
#ifndef LARGE_STREAMS
|
|
if (ULIGetHigh(ulNewSize) != 0)
|
|
olErr(EH_Err, STG_E_DOCFILETOOLARGE);
|
|
#endif
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
#ifdef LARGE_STREAMS
|
|
sc = _pst->SetSize(ulNewSize.QuadPart);
|
|
#else
|
|
sc = _pst->SetSize(ULIGetLow(ulNewSize));
|
|
#endif
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::SetSize\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::SetSize(). ret == %lx\n", this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::CopyTo, public
|
|
//
|
|
// Synopsis: Copies information from one stream to another
|
|
//
|
|
// Arguments: [pstm] - Destination
|
|
// [cb] - Number of bytes to copy
|
|
// [pcbRead] - Return number of bytes read
|
|
// [pcbWritten] - Return number of bytes written
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbRead]
|
|
// [pcbWritten]
|
|
//
|
|
// History: 25-Mar-92 DrewB Created
|
|
// 12-Jan-93 AlexT Rewritten without recursion
|
|
//
|
|
// Notes: We do our best to handle overlap correctly. This allows
|
|
// CopyTo to be used to insert and remove space within a
|
|
// stream.
|
|
//
|
|
// In the error case, we make no gurantees as to the
|
|
// validity of pcbRead, pcbWritten, or either stream's
|
|
// seek position.
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedStream::CopyTo(IStream *pstm,
|
|
ULARGE_INTEGER cb,
|
|
ULARGE_INTEGER *pcbRead,
|
|
ULARGE_INTEGER *pcbWritten)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
|
|
olLog(("%p::In CExposedStream::CopyTo(%p, %lu, %p, %p)\n",
|
|
this, pstm, ULIGetLow(cb), pcbRead, pcbWritten));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::CopyTo("
|
|
"%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
|
|
pcbRead, pcbWritten));
|
|
|
|
OL_VALIDATE(CopyTo(pstm, cb, pcbRead, pcbWritten));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
|
|
sc = CopyToWorker(pstm, cb, pcbRead, pcbWritten, &_ss);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
|
|
pcbRead ? ULIGetLow(*pcbRead) : 0,
|
|
pcbWritten ? ULIGetLow(*pcbWritten) : 0));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
SCODE CExposedStream::CopyToWorker(IStream *pstm,
|
|
ULARGE_INTEGER cb,
|
|
ULARGE_INTEGER *pcbRead,
|
|
ULARGE_INTEGER *pcbWritten,
|
|
CSafeSem *pss)
|
|
{
|
|
SCODE sc;
|
|
#ifdef LARGE_STREAMS
|
|
ULONGLONG ulCopySize;
|
|
ULONGLONG ulSrcSize, ulSrcOrig;
|
|
#else
|
|
ULONG ulCopySize;
|
|
ULONG ulSrcSize;
|
|
ULONG ulSrcOrig;
|
|
#endif
|
|
ULARGE_INTEGER uliDestOrig;
|
|
LARGE_INTEGER liDestPos;
|
|
BYTE *pb = NULL;
|
|
BOOL fOverlap;
|
|
#ifdef LARGE_STREAMS
|
|
ULONGLONG ulBytesCopied = 0;
|
|
#else
|
|
ULONG ulBytesCopied = 0;
|
|
#endif
|
|
ULONG ulBufferSize;
|
|
|
|
#ifdef LARGE_STREAMS
|
|
ulCopySize = cb.QuadPart;
|
|
#else
|
|
// Bound the size of the copy
|
|
// 1. The maximum we can copy is 0xffffffff
|
|
if (ULIGetHigh(cb) == 0)
|
|
ulCopySize = ULIGetLow(cb);
|
|
else
|
|
ulCopySize = 0xffffffff;
|
|
#endif
|
|
|
|
// 2. We can only copy what's available in the source stream
|
|
SetReadAccess();
|
|
sc = _pst->GetSize(&ulSrcSize);
|
|
ClearReadAccess();
|
|
olChk(sc);
|
|
|
|
ulSrcOrig = _psp->GetPos();
|
|
if (ulSrcSize < ulSrcOrig)
|
|
{
|
|
// Nothing in source to copy
|
|
ulCopySize = 0;
|
|
}
|
|
else if ((ulSrcSize - ulSrcOrig) < ulCopySize)
|
|
{
|
|
// Shrink ulCopySize to fit bytes in source
|
|
ulCopySize = ulSrcSize - ulSrcOrig;
|
|
}
|
|
|
|
// 3. We can only copy what will fit in the destination
|
|
LISet32(liDestPos, 0);
|
|
olHChk(pstm->Seek(liDestPos, STREAM_SEEK_CUR, &uliDestOrig));
|
|
#ifndef LARGE_STREAMS
|
|
olAssert(ULIGetHigh(uliDestOrig) == 0);
|
|
|
|
if (ulCopySize > CBMAXSEEK - ULIGetLow(uliDestOrig))
|
|
ulCopySize = CBMAXSEEK - ULIGetLow(uliDestOrig);
|
|
#endif
|
|
|
|
ulBufferSize = (_pdfb->GetOpenFlags() & DF_LARGE) ?
|
|
LARGESTREAMBUFFERSIZE : STREAMBUFFERSIZE;
|
|
// We are allowed to fail here with out-of-memory
|
|
olChk(GetBuffer(STREAMBUFFERSIZE, ulBufferSize, &pb, &ulBufferSize));
|
|
|
|
// Since we have no reliable way to determine if the source and
|
|
// destination represent the same stream, we assume they
|
|
// do and always handle overlap.
|
|
|
|
#ifdef LARGE_STREAMS
|
|
fOverlap = (uliDestOrig.QuadPart > ulSrcOrig &&
|
|
uliDestOrig.QuadPart < ulSrcOrig + ulCopySize);
|
|
#else
|
|
fOverlap = (ULIGetLow(uliDestOrig) > ulSrcOrig &&
|
|
ULIGetLow(uliDestOrig) < ulSrcOrig + ulCopySize);
|
|
#endif
|
|
|
|
#ifdef LARGE_STREAMS
|
|
ULONGLONG ulSrcCopyOffset;
|
|
ULONGLONG ulDstCopyOffset;
|
|
#else
|
|
ULONG ulSrcCopyOffset;
|
|
ULONG ulDstCopyOffset;
|
|
#endif
|
|
if (fOverlap)
|
|
{
|
|
// We're going to copy back to front, so determine the
|
|
// stream end positions
|
|
ulSrcCopyOffset = ulSrcOrig + ulCopySize;
|
|
|
|
// uliDestOrig is the destination starting offset
|
|
#ifdef LARGE_STREAMS
|
|
ulDstCopyOffset = uliDestOrig.QuadPart + ulCopySize;
|
|
#else
|
|
ulDstCopyOffset = ULIGetLow(uliDestOrig) + ulCopySize;
|
|
#endif
|
|
}
|
|
|
|
while (ulCopySize > 0)
|
|
{
|
|
// We can only copy up to ulBufferSize bytes at a time
|
|
ULONG cbPart = (ULONG) min(ulCopySize, ulBufferSize);
|
|
|
|
if (fOverlap)
|
|
{
|
|
// We're copying back to front so we need to seek to
|
|
// set up the streams correctly
|
|
|
|
ulSrcCopyOffset -= cbPart;
|
|
ulDstCopyOffset -= cbPart;
|
|
|
|
// Set source stream position
|
|
_psp->SetPos(ulSrcCopyOffset);
|
|
|
|
// Set destination stream position
|
|
liDestPos.QuadPart = ulDstCopyOffset;
|
|
olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
|
|
}
|
|
|
|
ULONG ulRead = 0;
|
|
SetReadAccess();
|
|
sc = _pst->ReadAt(_psp->GetPos(), pb, cbPart, &ulRead);
|
|
ClearReadAccess();
|
|
#ifndef LARGE_STREAMS
|
|
olAssert(CBMAXSEEK-_psp->GetPos() >= ulRead);
|
|
#endif
|
|
_psp->SetPos(_psp->GetPos()+ulRead);
|
|
olChk(sc);
|
|
|
|
if (cbPart != ulRead)
|
|
{
|
|
// There was no error, but we were unable to read cbPart
|
|
// bytes. Something's wrong (the underlying ILockBytes?)
|
|
// but we can't control it; just return an error.
|
|
olErr(EH_Err, STG_E_READFAULT);
|
|
}
|
|
|
|
// We release the tree mutex before calling out to Write
|
|
// to avoid a deadlock in the async FillAppend method
|
|
ULONG ulWritten;
|
|
SCODE sc2;
|
|
pss->Release();
|
|
sc2 = pstm->Write(pb, cbPart, &ulWritten);
|
|
olChk(pss->Take());
|
|
olChk (sc2);
|
|
if (cbPart != ulWritten)
|
|
{
|
|
// There was no error, but we were unable to write
|
|
// ulWritten bytes. We can't trust the pstm
|
|
// implementation, so all we can do here is return
|
|
// an error.
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
}
|
|
|
|
olAssert(ulCopySize >= cbPart);
|
|
ulCopySize -= cbPart;
|
|
ulBytesCopied += cbPart;
|
|
}
|
|
|
|
if (fOverlap)
|
|
{
|
|
// Set the seek pointers to the correct location
|
|
_psp->SetPos(ulSrcOrig + ulBytesCopied);
|
|
|
|
liDestPos.QuadPart = uliDestOrig.QuadPart + ulBytesCopied;
|
|
olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
|
|
}
|
|
|
|
// Fall through
|
|
|
|
EH_Err:
|
|
DfMemFree(pb);
|
|
|
|
if (pcbRead)
|
|
pcbRead->QuadPart = ulBytesCopied;
|
|
if (pcbWritten)
|
|
pcbWritten->QuadPart = ulBytesCopied;
|
|
|
|
olLog(("%p::Out CExposedStream::CopyTo(). "
|
|
"cbRead == %lu, cbWritten == %lu, ret == %lx\n",
|
|
this, pcbRead ? ULIGetLow(*pcbRead) : 0,
|
|
pcbWritten ? ULIGetLow(*pcbWritten) : 0, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Release, public
|
|
//
|
|
// Synopsis: Releases a stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Feb-92 DrewB Created from pbstream source
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedStream::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
olLog(("%p::In CExposedStream::Release()\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Release()\n"));
|
|
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
olAssert(_cReferences > 0);
|
|
lRet = InterlockedDecrement(&_cReferences);
|
|
if (lRet == 0)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
CPerContext *ppc = _ppc;
|
|
SCODE sc = S_OK;
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
#endif //MULTIHEAP
|
|
delete this;
|
|
#ifdef MULTIHEAP
|
|
if (ppc)
|
|
{
|
|
if (ppc->Release() == 0)
|
|
g_smAllocator.Uninit();
|
|
else
|
|
if (SUCCEEDED(sc)) ppc->UntakeSem();
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release();
|
|
#endif
|
|
#endif
|
|
}
|
|
else if (lRet < 0)
|
|
lRet = 0;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Release %p()=> %lu\n",
|
|
this, lRet));
|
|
olLog(("%p::Out CExposedStream::Release(). ret == %lu\n", this, lRet));
|
|
FreeLogFile();
|
|
return lRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Stat, public
|
|
//
|
|
// Synopsis: Fills in a buffer of information about this object
|
|
//
|
|
// Arguments: [pstatstg] - Buffer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pstatstg]
|
|
//
|
|
// History: 24-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
STATSTGW stat;
|
|
|
|
olLog(("%p::In CExposedStream::Stat(%p)\n", this, pstatstg));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Stat(%p)\n",
|
|
pstatstg));
|
|
|
|
OL_VALIDATE(Stat(pstatstg, grfStatFlag));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeReadAccess();
|
|
|
|
sc = _pst->Stat(&stat, grfStatFlag);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
TRY
|
|
{
|
|
*pstatstg = stat;
|
|
pstatstg->type = STGTY_STREAM;
|
|
pstatstg->grfLocksSupported = 0;
|
|
pstatstg->STATSTG_dwStgFmt = 0;
|
|
pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
|
|
pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
|
|
pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
UNREFERENCED_PARM(e);
|
|
if (stat.pwcsName)
|
|
TaskMemFree(stat.pwcsName);
|
|
sc = STG_E_INVALIDPOINTER;
|
|
}
|
|
END_CATCH
|
|
}
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Stat\n"));
|
|
// Fall through
|
|
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Stat(). ret == %lx\n",
|
|
this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Clone, public
|
|
//
|
|
// Synopsis: Clones a stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Feb-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
|
|
{
|
|
SafeCExposedStream pst;
|
|
CSeekPointer *psp;
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedStream::Clone(%p)\n", this, ppstm));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Clone(%p)\n", ppstm));
|
|
|
|
OL_VALIDATE(Clone(ppstm));
|
|
|
|
olChk(Validate());
|
|
olChk(TakeSafeSem());
|
|
olChk(_pst->CheckReverted());
|
|
SafeReadAccess();
|
|
olMem(psp = new (_pdfb->GetMalloc()) CSeekPointer(_psp->GetPos()));
|
|
pst.Attach(new (_pdfb->GetMalloc()) CExposedStream);
|
|
olMemTo(EH_psp, (CExposedStream *)pst);
|
|
olChkTo(EH_pst, pst->Init(BP_TO_P(CPubStream *, _pst),
|
|
BP_TO_P(CDFBasis *, _pdfb),
|
|
_ppc, psp));
|
|
|
|
_ppc->AddRef();
|
|
_pst->vAddRef();
|
|
#ifdef ASYNC
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_pstInit, pst->InitClone(&_cpoint));
|
|
}
|
|
#endif
|
|
TRANSFER_INTERFACE(pst, IStream, ppstm);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
|
|
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
|
|
this, *ppstm, sc));
|
|
return ResultFromScode(sc);
|
|
EH_pstInit:
|
|
pst->Release();
|
|
goto EH_Err;
|
|
EH_pst:
|
|
delete pst;
|
|
EH_psp:
|
|
psp->vRelease();
|
|
goto EH_Err;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::AddRef, public
|
|
//
|
|
// Synopsis: Increments the ref count
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
|
|
{
|
|
ULONG ulRet;
|
|
|
|
olLog(("%p::In CExposedStream::AddRef()\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::AddRef()\n"));
|
|
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
InterlockedIncrement(&_cReferences);
|
|
ulRet = _cReferences;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::AddRef %p() => %lu\n",
|
|
this, _cReferences));
|
|
olLog(("%p::Out CExposedStream::AddRef(). ret == %lu\n", this, ulRet));
|
|
return ulRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::LockRegion, public
|
|
//
|
|
// Synopsis: Nonfunctional
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
|
|
ULARGE_INTEGER cb,
|
|
DWORD dwLockType)
|
|
{
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::LockRegion("
|
|
"%lu, %lu\n", ULIGetLow(cb), dwLockType));
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::LockRegion\n"));
|
|
olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::UnlockRegion, public
|
|
//
|
|
// Synopsis: Nonfunctional
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
|
|
ULARGE_INTEGER cb,
|
|
DWORD dwLockType)
|
|
{
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::UnlockRegion(%lu, %lu)\n",
|
|
ULIGetLow(cb), dwLockType));
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::UnlockRegion\n"));
|
|
olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Commit, public
|
|
//
|
|
// Synopsis: No-op in current implementation
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Commit(%lu)\n",
|
|
grfCommitFlags));
|
|
olLog(("%p::In CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
|
|
|
|
OL_VALIDATE(Commit(grfCommitFlags));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
sc = _pst->Commit(grfCommitFlags);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Commit\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Commit(). ret == %lx\n", this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Revert, public
|
|
//
|
|
// Synopsis: No-op in current implementation
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Revert(void)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::Revert()\n"));
|
|
|
|
OL_VALIDATE(Revert());
|
|
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
//ASYNC Note: Don't need pending loop here.
|
|
sc = _pst->CheckReverted();
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::Revert\n"));
|
|
olLog(("%p::In CExposedStream::Revert()\n", this));
|
|
olLog(("%p::Out CExposedStream::Revert(). ret == %lx", this, sc));
|
|
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 26-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedStream::QueryInterface(?, %p)\n",
|
|
this, ppvObj));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::QueryInterface(?, %p)\n",
|
|
ppvObj));
|
|
|
|
|
|
OL_VALIDATE(QueryInterface(iid, ppvObj));
|
|
|
|
olChk(Validate());
|
|
olChk(_pst->CheckReverted());
|
|
|
|
sc = S_OK;
|
|
if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IStream *)this;
|
|
AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IMarshal))
|
|
{
|
|
//If the ILockBytes we'd need to marshal doesn't support IMarshal
|
|
// then we want to do standard marshalling on the stream, mostly
|
|
// to prevent deadlock problems but also because you'll get better
|
|
// performance. So check, then do the right thing.
|
|
|
|
IMarshal *pim;
|
|
ILockBytes *plkb;
|
|
plkb = _ppc->GetOriginal();
|
|
if (plkb == NULL)
|
|
{
|
|
plkb = _ppc->GetBase();
|
|
}
|
|
|
|
sc = plkb->QueryInterface(IID_IMarshal, (void **)&pim);
|
|
if (FAILED(sc))
|
|
{
|
|
olErr(EH_Err, E_NOINTERFACE);
|
|
}
|
|
pim->Release();
|
|
|
|
#ifdef MULTIHEAP
|
|
if (_ppc->GetHeapBase() == NULL)
|
|
olErr (EH_Err, E_NOINTERFACE);
|
|
#endif
|
|
|
|
*ppvObj = (IMarshal *)this;
|
|
AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IMappedStream))
|
|
{
|
|
*ppvObj = (IMappedStream *)this;
|
|
AddRef();
|
|
}
|
|
#ifdef ASYNC
|
|
else if (IsEqualIID(iid, IID_IConnectionPointContainer) &&
|
|
_cpoint.IsInitialized())
|
|
{
|
|
*ppvObj = (IConnectionPointContainer *)this;
|
|
CExposedStream::AddRef();
|
|
}
|
|
#endif
|
|
|
|
else
|
|
sc = E_NOINTERFACE;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::QueryInterface(). "
|
|
"*ppvObj == %p, ret == %lx\n", this, *ppvObj, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Unmarshal, public
|
|
//
|
|
// Synopsis: Creates a duplicate stream from parts
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [ppv] - Object return
|
|
// [mshlflags] - Marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppv]
|
|
//
|
|
// History: 26-Feb-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedStream::Unmarshal(IStream *pstm,
|
|
void **ppv,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
CDfMutex mtx;
|
|
CPerContext *ppc;
|
|
CPubStream *pst;
|
|
CDFBasis *pdfb;
|
|
CGlobalContext *pgc;
|
|
CExposedStream *pest;
|
|
CSeekPointer *psp;
|
|
IStream *pstmStd = NULL;
|
|
#ifdef ASYNC
|
|
DWORD dwAsyncFlags;
|
|
IDocfileAsyncConnectionPoint *pdacp;
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
CMarshalList *pml;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Unmarshal(%p, %p, %lu)\n",
|
|
pstm, ppv, mshlflags));
|
|
|
|
#ifdef MULTIHEAP
|
|
void *pvBaseOld;
|
|
void *pvBaseNew;
|
|
ContextId cntxid;
|
|
CPerContext pcSharedMemory (NULL); // bootstrap object
|
|
#endif
|
|
|
|
//First unmarshal the standard marshalled version
|
|
sc = CoUnmarshalInterface(pstm, IID_IStream, (void **)&pstmStd);
|
|
if (FAILED(sc))
|
|
{
|
|
// assume that entire standard marshaling stream has been read
|
|
olAssert (pstmStd == NULL);
|
|
sc = S_OK;
|
|
}
|
|
|
|
#ifdef MULTIHEAP
|
|
sc = UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid);
|
|
if (!SUCCEEDED(sc))
|
|
{
|
|
#ifdef POINTER_IDENTITY
|
|
UnmarshalPointer(pstm, (void **) &pest);
|
|
#endif
|
|
UnmarshalPointer(pstm, (void **)&pst);
|
|
UnmarshalPointer(pstm, (void **)&pdfb);
|
|
UnmarshalPointer(pstm, (void **)&psp);
|
|
#ifdef ASYNC
|
|
ReleaseContext(pstm, TRUE, FALSE, mshlflags);
|
|
ReleaseConnection(pstm, mshlflags);
|
|
#else
|
|
ReleaseContext(pstStm, FALSE, mshlflags);
|
|
#endif
|
|
olChkTo(EH_std, sc);
|
|
}
|
|
pvBaseOld = DFBASEPTR;
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pest));
|
|
#endif
|
|
olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pst));
|
|
olChkTo(EH_mem, ValidateBuffer(pst, sizeof(CPubStream)));
|
|
olChkTo(EH_pst, UnmarshalPointer(pstm, (void **)&pdfb));
|
|
olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **)&psp));
|
|
olChkTo(EH_psp, UnmarshalPointer(pstm, (void **)&pgc));
|
|
olChkTo(EH_pgc, ValidateBuffer(pgc, sizeof(CGlobalContext)));
|
|
|
|
//So far, nothing has called into the tree so we don't really need
|
|
// to be holding the tree mutex. The UnmarshalContext call does
|
|
// call into the tree, though, so we need to make sure this is
|
|
// threadsafe. We'll do this my getting the mutex name from the
|
|
// CGlobalContext, then creating a new CDfMutex object. While
|
|
// this is obviously not optimal, since it's possible we could
|
|
// reuse an existing CDfMutex, the reuse strategy isn't threadsafe
|
|
// since we can't do a lookup without the possibility of the thing
|
|
// we're looking for being released by another thread.
|
|
TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
|
|
pgc->GetMutexName(atcMutexName);
|
|
olChkTo(EH_pgc, mtx.Init(atcMutexName));
|
|
olChkTo(EH_pgc, mtx.Take(INFINITE));
|
|
|
|
//At this point we're holding the mutex.
|
|
#ifdef MULTIHEAP
|
|
#ifdef ASYNC
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
TRUE,
|
|
FALSE,
|
|
cntxid,
|
|
FALSE));
|
|
#else
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
FALSE,
|
|
cntxid,
|
|
FALSE));
|
|
#endif
|
|
if ((pvBaseNew = DFBASEPTR) != pvBaseOld)
|
|
{
|
|
pst = (CPubStream*) ((ULONG_PTR)pst - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
pest = (CExposedStream*) ((ULONG_PTR)pest - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
pdfb = (CDFBasis*) ((ULONG_PTR)pdfb - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
psp = (CSeekPointer*) ((ULONG_PTR)psp - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
}
|
|
#else
|
|
#ifdef ASYNC
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE));
|
|
#else
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
FALSE,
|
|
FALSE));
|
|
#endif //ASYNC
|
|
#endif
|
|
#ifdef ASYNC
|
|
olChkTo(EH_ppc, UnmarshalConnection(pstm,
|
|
&dwAsyncFlags,
|
|
&pdacp,
|
|
mshlflags));
|
|
#endif
|
|
|
|
// if we use up 1Gig of address space, use standard unmarshaling
|
|
if (gs_iSharedHeaps > (DOCFILE_SM_LIMIT / DOCFILE_SM_SIZE))
|
|
olErr (EH_ppc, STG_E_INSUFFICIENTMEMORY);
|
|
|
|
#ifdef POINTER_IDENTITY
|
|
olAssert (pest != NULL);
|
|
pml = (CMarshalList *) pest;
|
|
|
|
// Warning: these checks must remain valid across processes
|
|
if (SUCCEEDED(pest->Validate()) && pest->GetPub() == pst)
|
|
{
|
|
pest = (CExposedStream *) pml->FindMarshal(GetCurrentContextId());
|
|
}
|
|
else
|
|
{
|
|
pml = NULL;
|
|
pest = NULL;
|
|
}
|
|
|
|
if (pest == NULL)
|
|
{
|
|
#endif
|
|
olMemTo(EH_ppc, pest = new (pdfb->GetMalloc()) CExposedStream);
|
|
#ifdef ASYNC
|
|
olChkTo(EH_pest, pest->InitMarshal(pst,
|
|
pdfb,
|
|
ppc,
|
|
dwAsyncFlags,
|
|
pdacp,
|
|
psp));
|
|
//InitMarshal adds a reference on pdacp.
|
|
if (pdacp)
|
|
pdacp->Release();
|
|
#else
|
|
olChkTo(EH_pest, pest->Init(pst, pdfb, ppc, psp));
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
if (pml) pml->AddMarshal(pest);
|
|
pst->vAddRef(); // CExposedStream::Init does not AddRef
|
|
psp->vAddRef();
|
|
}
|
|
else
|
|
{
|
|
pdfb->SetAccess(ppc);
|
|
pest->AddRef(); // reuse this object
|
|
ppc->Release(); // reuse percontext
|
|
}
|
|
#else
|
|
pst->vAddRef();
|
|
psp->vAddRef();
|
|
#endif
|
|
|
|
*ppv = pest;
|
|
#ifdef MULTIHEAP
|
|
if (pvBaseOld != pvBaseNew)
|
|
{
|
|
pcSharedMemory.SetThreadAllocatorState(NULL);
|
|
g_smAllocator.Uninit(); // delete the extra mapping
|
|
}
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
|
|
mtx.Release();
|
|
|
|
//We're returning the custom marshalled version, so release the
|
|
//standard marshalled one.
|
|
if (pstmStd != NULL)
|
|
pstmStd->Release();
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Unmarshal => %p\n", *ppv));
|
|
return S_OK;
|
|
|
|
EH_pest:
|
|
delete pest;
|
|
EH_ppc:
|
|
ppc->Release();
|
|
EH_mtx:
|
|
mtx.Release();
|
|
goto EH_Err;
|
|
EH_pgc:
|
|
CoReleaseMarshalData(pstm); // release the ILockBytes
|
|
CoReleaseMarshalData(pstm); // release the ILockBytes
|
|
#ifdef ASYNC
|
|
ReleaseConnection(pstm, mshlflags);
|
|
#endif
|
|
EH_psp:
|
|
EH_pdfb:
|
|
EH_pst:
|
|
EH_mem:
|
|
EH_Err:
|
|
#ifdef MULTIHEAP
|
|
pcSharedMemory.SetThreadAllocatorState(NULL);
|
|
g_smAllocator.Uninit(); // delete the file mapping in error case
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
|
|
EH_std:
|
|
if (pstmStd != NULL)
|
|
{
|
|
//We can return the standard marshalled version instead of an error.
|
|
*ppv = pstmStd;
|
|
return S_OK;
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::GetUnmarshalClass, public
|
|
//
|
|
// Synopsis: Returns the class ID
|
|
//
|
|
// Arguments: [riid] - IID of object
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Unreferenced
|
|
// [pcid] - CLSID return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcid]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::GetUnmarshalClass(REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
LPCLSID pcid)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedStream::GetUnmarshalClass("
|
|
"riid, %p, %lu, %p, %lu, %p)\n",
|
|
this, pv, dwDestContext, pvDestContext, mshlflags, pcid));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::GetUnmarshalClass:%p("
|
|
"riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
|
|
pvDestContext, mshlflags, pcid));
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
UNREFERENCED_PARM(mshlflags);
|
|
|
|
olChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
|
|
memset(pcid, 0, sizeof(CLSID));
|
|
olChk(ValidateIid(riid));
|
|
olChk(Validate());
|
|
olChk(_pst->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
pcid));
|
|
pmsh->Release();
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
olChk(VerifyIid(riid, IID_IStream));
|
|
*pcid = CLSID_DfMarshal;
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::GetUnmarshalClass\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::GetUnmarshalClass(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::GetMarshalSizeMax, public
|
|
//
|
|
// Synopsis: Returns the size needed for the marshal buffer
|
|
//
|
|
// Arguments: [riid] - IID of object being marshaled
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Marshal flags
|
|
// [pcbSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbSize]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::GetMarshalSizeMax(REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
LPDWORD pcbSize)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
olLog(("%p::In CExposedStream::GetMarshalSizeMax("
|
|
"riid, %p, %lu, %p, %lu, %p)\n",
|
|
this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::GetMarshalSizeMax:%p("
|
|
"riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
|
|
pvDestContext, mshlflags, pcbSize));
|
|
|
|
olChk(Validate());
|
|
olChk(_pst->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
pcbSize));
|
|
pmsh->Release();
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
sc = GetStdMarshalSize(riid, IID_IStream, dwDestContext, pvDestContext,
|
|
mshlflags, pcbSize,
|
|
sizeof(CPubStream *)+sizeof(CDFBasis *)+
|
|
sizeof(CSeekPointer *),
|
|
#ifdef ASYNC
|
|
&_cpoint,
|
|
TRUE,
|
|
#endif
|
|
_ppc, FALSE);
|
|
DWORD cbSize = 0;
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
&cbSize));
|
|
pmsh->Release();
|
|
*pcbSize += cbSize;
|
|
}
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::GetMarshalSizeMax\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::GetMarshalSizeMax(). *pcbSize == %lu, "
|
|
"ret == %lx\n", this, *pcbSize, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::MarshalInterface, public
|
|
//
|
|
// Synopsis: Marshals a given object
|
|
//
|
|
// Arguments: [pstStm] - Stream to write marshal data into
|
|
// [riid] - Interface to marshal
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::MarshalInterface(IStream *pstStm,
|
|
REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedStream::MarshalInterface("
|
|
"%p, riid, %p, %lu, %p, %lu). Context == %lX\n",
|
|
this, pstStm, pv, dwDestContext, pvDestContext,
|
|
mshlflags, (ULONG)GetCurrentContextId()));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::MarshalInterface:%p("
|
|
"%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
|
|
dwDestContext, pvDestContext, mshlflags));
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
|
|
olChk(Validate());
|
|
olChk(_pst->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags));
|
|
pmsh->Release();
|
|
olChk(sc);
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
olChk(StartMarshal(pstStm, riid, IID_IStream, mshlflags));
|
|
|
|
//Always standard marshal, in case we get an error during
|
|
//unmarshalling of the custom stuff.
|
|
{
|
|
IMarshal *pmsh;
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = pmsh->MarshalInterface(pstStm, riid, pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags);
|
|
pmsh->Release();
|
|
}
|
|
olChk(sc);
|
|
}
|
|
|
|
#ifdef MULTIHEAP
|
|
olChk(MarshalSharedMemory(pstStm, _ppc));
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChk(MarshalPointer(pstStm, (CExposedStream*) GetNextMarshal()));
|
|
#endif
|
|
olChk(MarshalPointer(pstStm, BP_TO_P(CPubStream *, _pst)));
|
|
olChk(MarshalPointer(pstStm, BP_TO_P(CDFBasis *, _pdfb)));
|
|
olChk(MarshalPointer(pstStm, BP_TO_P(CSeekPointer *, _psp)));
|
|
#ifdef ASYNC
|
|
olChk(MarshalContext(pstStm,
|
|
_ppc,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags,
|
|
TRUE,
|
|
FALSE));
|
|
#else
|
|
olChk(MarshalContext(pstStm,
|
|
_ppc,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags,
|
|
FALSE));
|
|
#endif
|
|
|
|
#ifdef ASYNC
|
|
olChk(MarshalConnection(pstStm,
|
|
&_cpoint,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags));
|
|
#endif
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::MarshalInterface\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::MarshalInterface(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::UnmarshalInterface, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [pstStm] -
|
|
// [riid] -
|
|
// [ppvObj] -
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::UnmarshalInterface(IStream *pstStm,
|
|
REFIID riid,
|
|
void **ppvObj)
|
|
{
|
|
olLog(("%p::INVALID CALL TO CExposedStream::UnmarshalInterface()\n"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::StaticReleaseMarshalData, public static
|
|
//
|
|
// Synopsis: Releases any references held in marshal data
|
|
//
|
|
// Arguments: [pstStm] - Marshal data stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Feb-94 DrewB Created
|
|
//
|
|
// Notes: Assumes standard marshal header has already been read
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedStream::StaticReleaseMarshalData(IStream *pstStm,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
CPubStream *pst;
|
|
CDFBasis *pdfb;
|
|
CSeekPointer *psp;
|
|
#ifdef POINTER_IDENTITY
|
|
CExposedStream *pest;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::StaticReleaseMarshalData:("
|
|
"%p, %lX)\n", pstStm, mshlflags));
|
|
|
|
//First release the standard marshalled stuff
|
|
olChk(CoReleaseMarshalData(pstStm));
|
|
// The final release of the exposed object may have shut down the
|
|
// shared memory heap, so do not access shared memory after this point
|
|
|
|
//Then do the rest of it
|
|
#ifdef MULTIHEAP
|
|
olChk(SkipSharedMemory(pstStm, mshlflags));
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChk(UnmarshalPointer(pstStm, (void **) &pest));
|
|
#endif
|
|
olChk(UnmarshalPointer(pstStm, (void **)&pst));
|
|
olChk(UnmarshalPointer(pstStm, (void **)&pdfb));
|
|
olChk(UnmarshalPointer(pstStm, (void **)&psp));
|
|
#ifdef ASYNC
|
|
olChk(ReleaseContext(pstStm, TRUE, FALSE, mshlflags));
|
|
olChk(ReleaseConnection(pstStm, mshlflags));
|
|
#else
|
|
olChk(ReleaseContext(pstStm, FALSE, mshlflags));
|
|
#endif
|
|
|
|
#ifdef MULTIHEAP
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
olDebugOut((DEB_ITRACE,
|
|
"Out CExposedStream::StaticReleaseMarshalData\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::ReleaseMarshalData, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [pstStm] - Stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 18-Sep-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::ReleaseMarshalData(IStream *pstStm)
|
|
{
|
|
SCODE sc;
|
|
DWORD mshlflags;
|
|
IID iid;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedStream::ReleaseMarshalData(%p)\n", this, pstStm));
|
|
olDebugOut((DEB_TRACE, "In CExposedStream::ReleaseMarshalData:%p(%p)\n",
|
|
this, pstStm));
|
|
|
|
olChk(Validate());
|
|
olChk(_pst->CheckReverted());
|
|
olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
|
|
olAssert(IsEqualIID(iid, IID_IStream));
|
|
sc = StaticReleaseMarshalData(pstStm, mshlflags);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedStream::ReleaseMarshalData\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::ReleaseMarshalData(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::DisconnectObject, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [dwRevserved] -
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 18-Sep-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::DisconnectObject(DWORD dwReserved)
|
|
{
|
|
olLog(("%p::INVALID CALL TO CExposedStream::DisconnectObject()\n"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
#ifdef NEWPROPS
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Open
|
|
//
|
|
// Synopsis: Opens mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Gets the size of the underlying stream and reads it
|
|
// into memory so that it can be "mapped."
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Open(IN VOID *powner, LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Open(powner, phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Close
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Does nothing because the object may be mapped in
|
|
// another process.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Close(OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Close(phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::ReOpen
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Combined open and map.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().ReOpen(ppv,phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Quiesce
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Meaningless for docfile mapped stream.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Quiesce(VOID)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Quiesce();
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Map
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Return the address of the "mapping" buffer.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Map(BOOLEAN fCreate, VOID **ppv)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Map(fCreate, ppv);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Unmap
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes: Unmapping is merely zeroing the pointer. We don't
|
|
// flush because that's done explicitly by the
|
|
// CPropertyStorage class.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Unmap(BOOLEAN fFlush, VOID **pv)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Unmap(fFlush, pv);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Flush
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
// Flush the memory property set to disk and commit it.
|
|
//
|
|
// Signals: HRESULT from IStream methods.
|
|
//
|
|
// Notes: Calls the shared memory buffer to do the actual flush
|
|
// because that code path is shared with the "FlushBufferedData"
|
|
// call for IStorage::Commit.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Flush(OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().Flush(phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::GetSize
|
|
//
|
|
// Synopsis: Returns size of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//--------------------------------------------------------------------
|
|
|
|
ULONG CExposedStream::GetSize(OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
return GetMappedStream().GetSize(phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetSize
|
|
//
|
|
// Synopsis: Sets size of "map." Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Arguments: [cb] -- requested size.
|
|
// [fPersistent] -- FALSE if expanding in-memory read-only image
|
|
// [ppv] -- new mapped address.
|
|
//
|
|
// Signals: Not enough disk space.
|
|
//
|
|
// Notes: In a low memory situation we may not be able to
|
|
// get the requested amount of memory. In this
|
|
// case we must fall back on disk storage as the
|
|
// actual map.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::SetSize(ULONG cb, BOOLEAN fPersistent, VOID **ppv, OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().SetSize(cb, fPersistent, ppv, phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Lock
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
NTSTATUS CExposedStream::Lock(BOOLEAN fExclusive)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
if( SUCCEEDED( sc = TakeSem() ))
|
|
{
|
|
SetDifferentBasisAccess(_pdfb, _ppc);
|
|
return GetMappedStream().Lock(fExclusive);
|
|
}
|
|
else
|
|
{
|
|
olDebugOut((DEB_IERROR, "Couldn't take CExposedStream::Lock(%lx)\n", sc));
|
|
return (STATUS_LOCK_NOT_GRANTED);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Unlock
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
NTSTATUS CExposedStream::Unlock(VOID)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
NTSTATUS Status = GetMappedStream().Unlock();
|
|
ClearBasisAccess(_pdfb);
|
|
ReleaseSem(S_OK);
|
|
return Status;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QueryTimeStamps
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().QueryTimeStamps(pspss, fNonSimple);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QueryModifyTime
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::QueryModifyTime(OUT LONGLONG *pll) const
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
return(GetMappedStream().QueryModifyTime(pll));
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QuerySecurity
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::QuerySecurity(OUT ULONG *pul) const
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
return(GetMappedStream().QuerySecurity(pul));
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::IsWriteable
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::IsWriteable() const
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
return GetConstMappedStream().IsWriteable();
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetChangePending
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#if DBGPROP
|
|
BOOLEAN CExposedStream::SetChangePending(BOOLEAN f)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
return GetMappedStream().SetChangePending(f);
|
|
}
|
|
#endif
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::IsNtMappedStream
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#if DBGPROP
|
|
BOOLEAN CExposedStream::IsNtMappedStream(VOID) const
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::GetParentHandle
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
HANDLE CExposedStream::GetHandle(VOID) const
|
|
{
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetModified
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::SetModified(OUT LONG *phr)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
GetMappedStream().SetModified(phr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::IsModified
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::IsModified(VOID) const
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
//return ((class CExposedStream*const)this)->GetMappedStream().IsModified();
|
|
return GetConstMappedStream().IsModified();
|
|
}
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::ValidateWriteAccess, public
|
|
//
|
|
// Synopsis: returns whether writer currently has write access
|
|
//
|
|
// Notes: tree mutex must be taken
|
|
//
|
|
// History: 30-Apr-96 HenryLee Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
HRESULT CExposedStream::ValidateWriteAccess()
|
|
{
|
|
if (_pst->GetTransactedDepth() >= 1)
|
|
return S_OK;
|
|
|
|
return (!_pdfb->DirectWriterMode() || (*_ppc->GetRecursionCount())) ?
|
|
S_OK : STG_E_ACCESSDENIED;
|
|
};
|
|
|
|
#endif // DIRECTWRITERLOCK
|
|
|
|
#endif
|
|
|