1584 lines
44 KiB
C++
1584 lines
44 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) 1992, Microsoft Corporation.
|
|
//
|
|
// File: expst.cxx
|
|
//
|
|
// Contents: CExposedStream code
|
|
//
|
|
// Notes: See the header file expst.hxx for details
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "exphead.cxx"
|
|
|
|
#include "expst.hxx"
|
|
#include "logfile.hxx"
|
|
|
|
// 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)
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::CExposedStream, public
|
|
//
|
|
// Synopsis: Empty object constructor
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedStream::CExposedStream()
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::CExposedStream()\n"));
|
|
_cReferences = 0;
|
|
_ulAccessLockBase = 0;
|
|
_ulPos = 0;
|
|
_pst = NULL;
|
|
_pdfParent = NULL;
|
|
_fDirty = FALSE;
|
|
#ifdef NEWPROPS
|
|
_pb = NULL;
|
|
_cbUsed = 0;
|
|
_cbOriginalStreamSize = 0;
|
|
_fChangePending = FALSE;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Init, public
|
|
//
|
|
// Synopsis: Base constructor
|
|
//
|
|
// Arguments: [pst] - Direct stream
|
|
// [pdfParent] - the storage parent
|
|
// [df] - Permission flags
|
|
// [pdfn] - name of stream
|
|
// [ulPos] - offset
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Note: We add "this" as a child to the parent to
|
|
// 1) Check for multiple instantiation of a child
|
|
// 2) Uses the RevertFromAbove() function to check
|
|
// for reverted state.
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE CExposedStream::Init(CDirectStream *pst,
|
|
CExposedDocFile* pdfParent,
|
|
const DFLAGS df,
|
|
const CDfName *pdfn,
|
|
const ULONG ulPos)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Init("
|
|
"%p, %lu)\n", pst, ulPos));
|
|
_ulPos = ulPos;
|
|
_pst = pst;
|
|
_pdfParent = pdfParent;
|
|
_df = df;
|
|
_dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
|
|
olAssert(pdfParent);
|
|
_pdfParent->AddChild(this);
|
|
_cReferences = 1;
|
|
_sig = CEXPOSEDSTREAM_SIG;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Init\n"));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// 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]
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbRead = 0;
|
|
|
|
olLog(("%p::In CExposedStream::Read(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbRead));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Read(%p,%lu,%p)\n",
|
|
pb, cb, pcbRead));
|
|
TRY
|
|
{
|
|
if (pcbRead)
|
|
olChkTo(EH_BadPtr, ValidateOutBuffer(pcbRead, sizeof(ULONG)));
|
|
olChk(ValidateHugeOutBuffer(pb, cb));
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
|
|
if (!P_READ(_df))
|
|
sc = STG_E_ACCESSDENIED;
|
|
else
|
|
sc = _pst->ReadAt(_ulPos, pb, cb,
|
|
(ULONG STACKBASED *)&cbRead);
|
|
olAssert( CBMAXSEEK - _ulPos >= cbRead);
|
|
_ulPos+=cbRead;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Read => %lu\n", cbRead));
|
|
|
|
EH_Err:
|
|
if (pcbRead)
|
|
{
|
|
*pcbRead = cbRead;
|
|
olLog(("%p::Out CExposedStream::Read() *pcbRead==%lu, ret=%lx\n",
|
|
this, SAFE_DREF(pcbRead), sc));
|
|
}
|
|
else
|
|
{
|
|
olLog(("%p::Out CExposedStream::Read(). ret == %lx\n", this, sc));
|
|
}
|
|
|
|
EH_BadPtr:
|
|
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]
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Write(
|
|
VOID const HUGEP *pb,
|
|
ULONG cb,
|
|
ULONG *pcbWritten)
|
|
{
|
|
SCODE sc;
|
|
ULONG cbWritten = 0;
|
|
|
|
olLog(("%p::In CExposedStream::Write(%p, %lu, %p)\n",
|
|
this, pb, cb, pcbWritten));
|
|
olDebugOut((DEB_ITRACE,
|
|
"In CExposedStream::Write(%p, %lu, %p)\n",
|
|
pb, cb, pcbWritten));
|
|
TRY
|
|
{
|
|
if (pcbWritten)
|
|
{
|
|
olChkTo(EH_BadPtr,
|
|
ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
|
|
}
|
|
olChk(ValidateHugeBuffer(pb, cb));
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
if (!P_WRITE(_df))
|
|
sc = STG_E_ACCESSDENIED;
|
|
else
|
|
{
|
|
sc = _pst->WriteAt(_ulPos, pb, cb,
|
|
(ULONG STACKBASED *)&cbWritten);
|
|
if (SUCCEEDED(sc))
|
|
SetDirty();
|
|
}
|
|
olAssert( CBMAXSEEK - _ulPos >= cbWritten);
|
|
_ulPos += cbWritten;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Write => %lu\n",
|
|
cbWritten));
|
|
EH_Err:
|
|
if (pcbWritten)
|
|
{
|
|
*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));
|
|
}
|
|
|
|
EH_BadPtr:
|
|
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]
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER *plibNewPosition)
|
|
{
|
|
SCODE sc;
|
|
LONG lMove;
|
|
ULARGE_INTEGER ulPos;
|
|
|
|
olLog(("%p::In CExposedStream::Seek(%ld, %lu, %p)\n",
|
|
this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Seek(%ld, %lu, %p)\n",
|
|
LIGetLow(dlibMove), dwOrigin, plibNewPosition));
|
|
TRY
|
|
{
|
|
if (plibNewPosition)
|
|
{
|
|
olChk(ValidateOutBuffer(plibNewPosition, sizeof(ULARGE_INTEGER)));
|
|
ULISet32(*plibNewPosition, 0);
|
|
}
|
|
if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
|
|
dwOrigin != STREAM_SEEK_END)
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
|
|
// Truncate dlibMove to 32 bits
|
|
if (dwOrigin == STREAM_SEEK_SET)
|
|
{
|
|
// Make sure we don't seek too far
|
|
if (LIGetHigh(dlibMove) != 0)
|
|
LISet32(dlibMove, /*(LONG)*/0xffffffff);
|
|
}
|
|
else
|
|
{
|
|
// 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, /*(LONG)*/0x80000000);
|
|
}
|
|
|
|
lMove = (LONG)LIGetLow(dlibMove);
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
ULISet32(ulPos, _ulPos);
|
|
switch(dwOrigin)
|
|
{
|
|
case STREAM_SEEK_SET:
|
|
ULISetLow(ulPos, (ULONG)lMove);
|
|
break;
|
|
case STREAM_SEEK_END:
|
|
ULONG cbSize;
|
|
olChk(GetSize(&cbSize));
|
|
if (lMove < 0)
|
|
{
|
|
if ((ULONG)(-lMove) > cbSize)
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
}
|
|
else if ((ULONG)lMove > CBMAXSEEK-cbSize)
|
|
lMove = (LONG)(CBMAXSEEK-cbSize);
|
|
ULISetLow(ulPos, cbSize+lMove);
|
|
break;
|
|
case STREAM_SEEK_CUR:
|
|
if (lMove < 0)
|
|
{
|
|
if ((ULONG)(-lMove) > _ulPos)
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
}
|
|
else if ((ULONG)lMove > CBMAXSEEK - _ulPos)
|
|
lMove = (LONG)(CBMAXSEEK- _ulPos);
|
|
ULISetLow(ulPos, _ulPos+lMove);
|
|
break;
|
|
}
|
|
_ulPos = ULIGetLow(ulPos);
|
|
if (plibNewPosition)
|
|
*plibNewPosition = ulPos;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "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
|
|
//
|
|
//---------------------------------------------------------------
|
|
SCODE CExposedStream::SetSize(ULONG cb)
|
|
{
|
|
olDebugOut((DEB_ITRACE,
|
|
"In CExposedStream::SetSize(ULONG %lu)\n", cb));
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
if (!P_WRITE(_df))
|
|
sc = STG_E_ACCESSDENIED;
|
|
else
|
|
{
|
|
olChk(_pst->SetSize(cb));
|
|
SetDirty();
|
|
}
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
|
|
EH_Err:
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::SetSize()\n"));
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetSize, public
|
|
//
|
|
// Synopsis: Sets the size of a stream
|
|
//
|
|
// Arguments: [ulNewSize] - New size
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
|
|
{
|
|
SCODE sc;
|
|
|
|
olLog(("%p::In CExposedStream::SetSize(%lu)\n",
|
|
this, ULIGetLow(ulNewSize)));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::SetSize(%lu)\n",
|
|
ULIGetLow(ulNewSize)));
|
|
TRY
|
|
{
|
|
if (ULIGetHigh(ulNewSize) != 0)
|
|
olErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
olChk(SetSize(ULIGetLow(ulNewSize)));
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "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]
|
|
//
|
|
// 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;
|
|
ULONG ulCopySize;
|
|
ULONG ulSrcSize;
|
|
ULONG ulSrcOrig;
|
|
ULARGE_INTEGER uliDestOrig;
|
|
LARGE_INTEGER liDestPos;
|
|
BYTE *pb = NULL;
|
|
BOOL fOverlap;
|
|
ULONG ulBytesCopied = 0;
|
|
|
|
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));
|
|
|
|
TRY
|
|
{
|
|
if (pcbRead) // okay to set to NULL => not interested
|
|
{
|
|
olChk(ValidateOutBuffer(pcbRead, sizeof(ULARGE_INTEGER)));
|
|
ULISet32(*pcbRead, 0);
|
|
}
|
|
if (pcbWritten) // okay to set to NULL => not interested
|
|
{
|
|
olChk(ValidateOutBuffer(pcbWritten, sizeof(ULARGE_INTEGER)));
|
|
ULISet32(*pcbWritten, 0);
|
|
}
|
|
|
|
olChk(ValidateInterface(pstm, IID_IStream));
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
|
|
// Bound the size of the copy
|
|
// 1. The maximum we can copy is 0xffffffff
|
|
|
|
if (ULIGetHigh(cb) == 0)
|
|
ulCopySize = ULIGetLow(cb);
|
|
else
|
|
ulCopySize = 0xffffffff;
|
|
|
|
// 2. We can only copy what's available in the source stream
|
|
|
|
olChk(GetSize(&ulSrcSize));
|
|
|
|
ulSrcOrig = _ulPos;
|
|
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));
|
|
olAssert(ULIGetHigh(uliDestOrig) == 0);
|
|
|
|
if (ulCopySize > CBMAXSEEK - ULIGetLow(uliDestOrig))
|
|
ulCopySize = CBMAXSEEK - ULIGetLow(uliDestOrig);
|
|
|
|
// We are allowed to fail here with out-of-memory
|
|
olMem(pb = new BYTE[STREAMBUFFERSIZE]);
|
|
|
|
// 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.
|
|
|
|
fOverlap = (ULIGetLow(uliDestOrig) > ulSrcOrig &&
|
|
ULIGetLow(uliDestOrig) < ulSrcOrig + ulCopySize);
|
|
|
|
ULONG ulSrcCopyOffset;
|
|
ULONG ulDstCopyOffset;
|
|
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
|
|
ulDstCopyOffset = ULIGetLow(uliDestOrig) + ulCopySize;
|
|
}
|
|
|
|
while (ulCopySize > 0)
|
|
{
|
|
// We can only copy up to STREAMBUFFERSIZE bytes at a time
|
|
ULONG cbPart = min(ulCopySize, STREAMBUFFERSIZE);
|
|
|
|
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
|
|
_ulPos = ulSrcCopyOffset;
|
|
|
|
// Set destination stream position
|
|
LISet32(liDestPos, ulDstCopyOffset);
|
|
olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
|
|
}
|
|
|
|
{
|
|
ULONG ulRead;
|
|
olHChk(Read(pb, cbPart, &ulRead));
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
ULONG ulWritten;
|
|
olHChk(pstm->Write(pb, cbPart, &ulWritten));
|
|
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
|
|
_ulPos = ulSrcOrig + ulBytesCopied;
|
|
|
|
LISet32(liDestPos, ULIGetLow(uliDestOrig) + ulBytesCopied);
|
|
olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
|
|
}
|
|
|
|
if (pcbRead)
|
|
ULISet32(*pcbRead, ulBytesCopied);
|
|
if (pcbWritten)
|
|
ULISet32(*pcbWritten, ulBytesCopied);
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
|
|
pcbRead ? ULIGetLow(*pcbRead) : 0,
|
|
pcbWritten ? ULIGetLow(*pcbWritten) : 0));
|
|
// Fall through
|
|
EH_Err:
|
|
delete [] pb;
|
|
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
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedStream::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
olLog(("%p::In CExposedStream::Release()\n", this));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Release()\n"));
|
|
TRY
|
|
{
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
olAssert(_cReferences > 0);
|
|
lRet = AtomicDec(&_cReferences);
|
|
if (lRet == 0)
|
|
{
|
|
Commit(0); // flush data
|
|
delete this;
|
|
}
|
|
else if (lRet < 0)
|
|
lRet = 0;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
UNREFERENCED_PARM(e);
|
|
lRet = 0;
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Release\n"));
|
|
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]
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(SCODE) CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SCODE sc, scSem = STG_E_INUSE;
|
|
|
|
olLog(("%p::In CExposedStream::Stat(%p)\n", this, pstatstg));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Stat(%p)\n",
|
|
pstatstg));
|
|
TRY
|
|
{
|
|
olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
|
|
olChk(VerifyStatFlag(grfStatFlag));
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
pstatstg->grfMode = DFlagsToMode(_df);
|
|
|
|
pstatstg->clsid = CLSID_NULL; // irrelevant for streams
|
|
pstatstg->grfStateBits = 0; // irrelevant for streams
|
|
pstatstg->type = STGTY_STREAM;
|
|
pstatstg->grfLocksSupported = 0;
|
|
pstatstg->reserved = 0;
|
|
|
|
// we null these values 'cos they are not interesting for
|
|
// direct streams ...
|
|
pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
|
|
pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
|
|
pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
|
|
pstatstg->pwcsName = NULL;
|
|
if ((grfStatFlag & STATFLAG_NONAME) == 0)
|
|
{ // fill in name
|
|
olChk(DfAllocWCS((WCHAR *)_dfn.GetBuffer(),
|
|
&pstatstg->pwcsName));
|
|
wcscpy(pstatstg->pwcsName, (WCHAR *)_dfn.GetBuffer());
|
|
}
|
|
ULONG cbSize;
|
|
GetSize(&cbSize);
|
|
ULISet32(pstatstg->cbSize, cbSize);
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Stat\n"));
|
|
EH_Err:
|
|
if (FAILED(sc))
|
|
memset(pstatstg, 0, sizeof(STATSTGW));
|
|
EH_RetSc:
|
|
olLog(("%p::Out CExposedStream::Stat(). ret == %lx\n",
|
|
this, sc));
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Clone, public
|
|
//
|
|
// Synopsis: Clones a stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
|
|
{
|
|
CExposedStream *pst;
|
|
SCODE sc;
|
|
|
|
olLog(("%p::In CExposedStream::Clone(%p)\n", this, ppstm));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Clone(%p)\n", ppstm));
|
|
TRY
|
|
{
|
|
olChk(ValidateOutPtrBuffer(ppstm));
|
|
*ppstm = NULL;
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
olMemTo(EH_pst, pst = new CExposedStream);
|
|
olChkTo(EH_pst, pst->Init(_pst, _pdfParent, _df, &_dfn, _ulPos));
|
|
_pst->AddRef();
|
|
*ppstm = pst;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
|
|
return ResultFromScode(sc);
|
|
|
|
EH_pst:
|
|
delete pst;
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
|
|
this, SAFE_DREFppstm, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::AddRef, public
|
|
//
|
|
// Synopsis: Increments the ref count
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
|
|
{
|
|
ULONG ulRet;
|
|
|
|
olLog(("%p::In CExposedStream::AddRef()\n", this));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::AddRef()\n"));
|
|
TRY
|
|
{
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
AtomicInc(&_cReferences);
|
|
ulRet = _cReferences;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
UNREFERENCED_PARM(e);
|
|
ulRet = 0;
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::AddRef\n"));
|
|
olLog(("%p::Out CExposedStream::AddRef(). ret == %lu\n", this, ulRet));
|
|
return ulRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::LockRegion, public
|
|
//
|
|
// Synopsis: Nonfunctional
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
|
|
ULARGE_INTEGER cb,
|
|
DWORD dwLockType)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::LockRegion("
|
|
"%lu, %lu\n", ULIGetLow(cb), dwLockType));
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::LockRegion\n"));
|
|
olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
|
|
UNREFERENCED_PARM(libOffset);
|
|
UNREFERENCED_PARM(cb);
|
|
UNREFERENCED_PARM(dwLockType);
|
|
olAssert(FALSE && aMsg("function not implemented!"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::UnlockRegion, public
|
|
//
|
|
// Synopsis: Nonfunctional
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
|
|
ULARGE_INTEGER cb,
|
|
DWORD dwLockType)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::UnlockRegion(%lu, %lu)\n",
|
|
ULIGetLow(cb), dwLockType));
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::UnlockRegion\n"));
|
|
olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
|
|
UNREFERENCED_PARM(libOffset);
|
|
UNREFERENCED_PARM(cb);
|
|
UNREFERENCED_PARM(dwLockType);
|
|
olAssert(FALSE && aMsg("function not implemented!"));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Commit, public
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
|
|
{
|
|
SCODE sc, scSem = STG_E_INUSE;
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Commit(%lu)\n",
|
|
grfCommitFlags));
|
|
olLog(("%p::In CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
|
|
|
|
TRY
|
|
{
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
|
|
if (_fDirty)
|
|
{ // We're a stream so we must have a parent
|
|
// We dirty all parents up to the next
|
|
// transacted storage
|
|
_pdfParent->SetDirty();
|
|
sc = _pdfParent->GetBaseMS()
|
|
->Flush(FLUSH_CACHE(grfCommitFlags));
|
|
}
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Commit\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedStream::Commit(). ret == %lx", this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Revert, public
|
|
//
|
|
// Synopsis: No-op in current implementation
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::Revert(void)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::Revert()\n"));
|
|
olDebugOut((DEB_ITRACE, "Out CExposedStream::Revert\n"));
|
|
|
|
olLog(("%p::In CExposedStream::Revert()\n", this));
|
|
olLog(("%p::Out CExposedStream::Revert(). ret == %lx", this, S_OK));
|
|
|
|
return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// 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]
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
olLog(("%p::In CExposedStream::QueryInterface(?, %p)\n",
|
|
this, ppvObj));
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::QueryInterface(?, %p)\n",
|
|
ppvObj));
|
|
TRY
|
|
{
|
|
olChk(ValidateOutPtrBuffer(ppvObj));
|
|
*ppvObj = NULL;
|
|
olChk(ValidateIid(iid));
|
|
olChk(Validate());
|
|
olChk(CheckReverted());
|
|
if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
olChk(AddRef());
|
|
*ppvObj = this;
|
|
}
|
|
else
|
|
olErr(EH_Err, E_NOINTERFACE);
|
|
sc = S_OK;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
olDebugOut((DEB_ITRACE, "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::RevertFromAbove, public (virtual)
|
|
//
|
|
// Synopsis: Parent has asked for reversion
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
void CExposedStream::RevertFromAbove(void)
|
|
{
|
|
msfDebugOut((DEB_ITRACE,
|
|
"In CExposedStream::RevertFromAbove:%p()\n", this));
|
|
_df |= DF_REVERTED;
|
|
_pst->Release();
|
|
#if DBG == 1
|
|
_pst = NULL;
|
|
#endif
|
|
msfDebugOut((DEB_ITRACE, "Out CExposedStream::RevertFromAbove\n"));
|
|
}
|
|
|
|
#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, OUT LONG *phr)
|
|
{
|
|
LONG& sc = *phr;
|
|
sc = S_OK;
|
|
|
|
// If given a pointer to the owner of this mapped stream,
|
|
// save it. This could be NULL. (i.e. when called from ReOpen)
|
|
if( NULL != powner )
|
|
_powner = (BYTE*) powner;
|
|
|
|
if (_pb == NULL)
|
|
{
|
|
VOID *pv;
|
|
_cbUsed = 0;
|
|
olChk(CheckReverted());
|
|
_pst->GetSize(&_cbOriginalStreamSize);
|
|
|
|
if (_cbOriginalStreamSize > CBMAXPROPSETSTREAM)
|
|
olErr(EH_Err, STG_E_INVALIDHEADER);
|
|
|
|
_cbUsed = _cbOriginalStreamSize;
|
|
olMemTo(EH_Err, pv = new BYTE[_cbOriginalStreamSize]);
|
|
_pb = (BYTE*) pv;
|
|
olChkTo(EH_Read,
|
|
_pst->ReadAt(0, pv, _cbOriginalStreamSize, &_cbUsed));
|
|
olAssert(_cbOriginalStreamSize == _cbUsed &&
|
|
"CExposedStream did not read in all the info!");
|
|
|
|
// Notify our owner that we have new data
|
|
if (*phr == S_OK && _powner != NULL && 0 != _cbUsed)
|
|
{
|
|
*phr = RtlOnMappedStreamEvent((VOID*)_powner, pv, _cbUsed );
|
|
}
|
|
|
|
}
|
|
olDebugOut((DEB_PROP_MAP, "CExposedStream(%X):Open returns normally\n", this));
|
|
return;
|
|
|
|
// Error handling
|
|
EH_Read:
|
|
delete[] _pb;
|
|
_pb = NULL;
|
|
_cbUsed = 0;
|
|
|
|
EH_Err:
|
|
olDebugOut((DEB_PROP_MAP,
|
|
"CExposedStream(%X):Open exception returns %08X\n",
|
|
this, *phr));
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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)
|
|
{
|
|
// Write the changes. We don't need to Commit them,
|
|
// they will be implicitely committed when the
|
|
// Stream is Released.
|
|
|
|
*phr = Write();
|
|
|
|
if( FAILED(*phr) )
|
|
{
|
|
olDebugOut( (DEB_PROP_MAP,
|
|
"CPubStream(%08X)::Close exception returns %08X\n",
|
|
this, *phr));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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)
|
|
{
|
|
*ppv = NULL;
|
|
Open( (void*)NULL, // unspecified owner
|
|
phr);
|
|
if ( SUCCEEDED(*phr) )
|
|
*ppv = _pb;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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)
|
|
{
|
|
olAssert(_pb != NULL);
|
|
DfpdbgCheckUnusedMemory();
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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)
|
|
{
|
|
UNREFERENCED_PARM(fCreate);
|
|
olAssert(_pb != NULL);
|
|
DfpdbgCheckUnusedMemory();
|
|
*ppv = _pb;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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)
|
|
{
|
|
UNREFERENCED_PARM(fFlush);
|
|
DfpdbgCheckUnusedMemory();
|
|
*pv = NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::Flush(OUT LONG *phr)
|
|
{
|
|
*phr = S_OK;
|
|
// write out any data we have cached to the stream
|
|
if (S_OK == (*phr = Write()))
|
|
{
|
|
// commit the stream
|
|
(*phr) = Commit(STGC_DEFAULT);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::GetSize
|
|
//
|
|
// Synopsis: Returns size of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//--------------------------------------------------------------------
|
|
|
|
ULONG CExposedStream::GetSize(OUT LONG *phr)
|
|
{
|
|
*phr = S_OK;
|
|
if (_pb == NULL)
|
|
Open((void*)NULL, // unspecified owner
|
|
phr);
|
|
|
|
if( SUCCEEDED(*phr) )
|
|
{
|
|
olAssert(_pb != NULL);
|
|
DfpdbgCheckUnusedMemory();
|
|
}
|
|
|
|
return _cbUsed;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::SetSize(ULONG cb, IN BOOLEAN fPersistent,
|
|
VOID **ppv, OUT LONG *phr)
|
|
{
|
|
*phr = S_OK;
|
|
LONG& sc=*phr;
|
|
BYTE *pbNew;
|
|
|
|
olAssert(cb != 0);
|
|
DfpdbgCheckUnusedMemory();
|
|
olChk(CheckReverted());
|
|
|
|
//
|
|
// if we are growing the data, we should grow the stream
|
|
//
|
|
if (fPersistent && cb > _cbUsed)
|
|
{
|
|
olChk(_pst->SetSize(cb));
|
|
}
|
|
|
|
olMem(pbNew = new BYTE[cb]);
|
|
|
|
memcpy(pbNew, _pb, (cb < _cbUsed) ? cb : _cbUsed); // smaller of the 2
|
|
delete[] _pb;
|
|
|
|
_pb = pbNew;
|
|
_cbUsed = cb;
|
|
*ppv = _pb;
|
|
|
|
DfpdbgFillUnusedMemory();
|
|
|
|
EH_Err:
|
|
olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):SetSize %s returns hr=%08X\n",
|
|
this, *phr != S_OK ? "exception" : "", *phr));
|
|
return;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// 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
|
|
{
|
|
UNREFERENCED_PARM(fNonSimple);
|
|
UNREFERENCED_PARM(pspss);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QueryModifyTime
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::QueryModifyTime(OUT LONGLONG *pll) const
|
|
{
|
|
UNREFERENCED_PARM(pll);
|
|
return (FALSE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::QuerySecurity
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::QuerySecurity(OUT ULONG *pul) const
|
|
{
|
|
UNREFERENCED_PARM(pul);
|
|
return FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::IsWriteable
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::IsWriteable() const
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::SetChangePending
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#if DBGPROP
|
|
BOOLEAN CExposedStream::SetChangePending(BOOLEAN f)
|
|
{
|
|
BOOL fOld = _fChangePending;
|
|
_fChangePending = f;
|
|
return(_fChangePending);
|
|
}
|
|
#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::GetHandle
|
|
//
|
|
// 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(VOID)
|
|
{
|
|
_fDirty = TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::IsModified
|
|
//
|
|
// Synopsis: Operates on mapped view of exposed stream. Called by
|
|
// NtCreatePropertySet et al.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
BOOLEAN CExposedStream::IsModified(VOID) const
|
|
{
|
|
return _fDirty;
|
|
}
|
|
|
|
#if DBG
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::DfpdbgFillUnusedMemory
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::DfpdbgFillUnusedMemory(VOID)
|
|
{
|
|
if (_pb == NULL)
|
|
return;
|
|
|
|
BYTE * pbEndPlusOne = _pb + BytesCommitted();
|
|
|
|
for (BYTE *pbUnused = _pb + _cbUsed;
|
|
pbUnused < pbEndPlusOne;
|
|
pbUnused++)
|
|
{
|
|
*pbUnused = (BYTE)(DWORD)pbUnused;
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::DfpdbgCheckUnusedMemory
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
VOID CExposedStream::DfpdbgCheckUnusedMemory(VOID)
|
|
{
|
|
|
|
if (_pb == NULL)
|
|
return;
|
|
|
|
if (_cbUsed == 0)
|
|
return;
|
|
|
|
BYTE * pbEndPlusOne = _pb + BytesCommitted();
|
|
|
|
for (BYTE *pbUnused = _pb + _cbUsed;
|
|
pbUnused < pbEndPlusOne;
|
|
pbUnused ++)
|
|
{
|
|
olAssert(*pbUnused == (BYTE)(DWORD)pbUnused);
|
|
}
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::Write, private
|
|
//
|
|
// Synopsis: Writes a mapped view of an exposed Stream to the
|
|
// underlying Stream. Used by RtlCreatePropertySet et al.
|
|
//
|
|
// Notes: The Stream is not commited. To commit the Stream, in
|
|
// addition to writing it, the Flush method should be used.
|
|
// The Commit is omitted so that it can be skipped in
|
|
// the Property Set Close path, thus eliminating a
|
|
// performance penalty.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
HRESULT CExposedStream::Write(VOID)
|
|
{
|
|
HRESULT hr;
|
|
ULONG cbWritten;
|
|
|
|
if (!_fDirty ||!_pb)
|
|
{
|
|
olDebugOut((DEB_PROP_MAP,
|
|
"CExposedStream(%08X):Flush returns with not-dirty\n", this));
|
|
|
|
// flushing a stream which isn't a property stream
|
|
// this could be optimized by propagating a 'no property streams'
|
|
// flag up the storage hierachy such that FlushBufferedData is
|
|
// not even called for non-property streams.
|
|
return S_OK;
|
|
}
|
|
|
|
hr=CheckReverted();
|
|
if (S_OK!=hr) goto Exit;
|
|
olAssert( _pst != NULL );
|
|
olAssert( _pb != NULL );
|
|
olAssert( _powner != NULL );
|
|
|
|
// notify our owner that we are about to perform a write
|
|
hr = RtlOnMappedStreamEvent( (void*)_powner, (void*) _pb, _cbUsed );
|
|
if ( S_OK != hr ) goto Exit;
|
|
|
|
hr = _pst->WriteAt(0, _pb, _cbUsed, &cbWritten);
|
|
|
|
if( S_OK != hr ) goto Exit;
|
|
// notify our owner that we are done with the write
|
|
hr = RtlOnMappedStreamEvent( (VOID*)_powner, (VOID *) _pb, _cbUsed );
|
|
if( S_OK != hr ) goto Exit;
|
|
|
|
if (_cbUsed < _cbOriginalStreamSize)
|
|
{
|
|
// if the stream is shrinking, this is a good time to do it.
|
|
hr = _pst->SetSize(_cbUsed);
|
|
if (S_OK!=hr) goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (hr == S_OK || hr == STG_E_REVERTED)
|
|
{
|
|
_fDirty = FALSE;
|
|
}
|
|
|
|
olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):Flush %s returns hr=%08X\n",
|
|
this, hr != S_OK ? "exception" : "", hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedStream::FlushBufferedData, public
|
|
//
|
|
// Synopsis: Flush out the property buffers.
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
SCODE CExposedStream::FlushBufferedData()
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedStream::FlushBufferedData:%p()\n",
|
|
this));
|
|
|
|
Flush(&sc);
|
|
|
|
olDebugOut((DEB_PROP_MAP,
|
|
"CExposedStream(%08X):FlushBufferedData returns %08X\n",
|
|
this, sc));
|
|
|
|
return sc;
|
|
}
|
|
|
|
#endif // ifdef NEWPROPS
|
|
|
|
|
|
|
|
|
|
|