306 lines
6.4 KiB
C++
306 lines
6.4 KiB
C++
// Stream.cpp -- Implementation for class CStream
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
HRESULT CStream::OpenStream(IUnknown *punkOuter, ILockBytes *pLockBytes, DWORD grfMode,
|
|
IStreamITEx **ppStream
|
|
)
|
|
{
|
|
CStream *pStream= New CStream(punkOuter);
|
|
|
|
if (!pStream)
|
|
{
|
|
pLockBytes->Release();
|
|
|
|
return STG_E_INSUFFICIENTMEMORY;
|
|
}
|
|
|
|
IStreamITEx *pIStream = NULL;
|
|
|
|
HRESULT hr= pStream->m_ImpIStream.InitOpenStream(pLockBytes, grfMode);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
pIStream = (IStreamITEx *) &pStream->m_ImpIStream;
|
|
pStream->AddRef();
|
|
}
|
|
else
|
|
delete pStream;
|
|
|
|
*ppStream= pIStream;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CStream::CImpIStream::InitOpenStream(ILockBytes *pLockBytes, DWORD grfMode)
|
|
{
|
|
m_pLockBytes = pLockBytes;
|
|
m_grfMode = grfMode;
|
|
|
|
// Note: We assume that pLockBytes was AddRef'd before it was given to us.
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// ISequentialStream methods:
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Read
|
|
(void __RPC_FAR *pv,ULONG cb,ULONG __RPC_FAR *pcbRead)
|
|
{
|
|
DWORD grfAccess = m_grfMode & RW_ACCESS_MASK;
|
|
|
|
if (grfAccess != STGM_READ && grfAccess != STGM_READWRITE)
|
|
return STG_E_ACCESSDENIED;
|
|
|
|
CSyncWith sw(m_cs);
|
|
|
|
ULONG cbRead = 0;
|
|
|
|
HRESULT hr = m_pLockBytes->ReadAt(m_ullStreamPosition.Uli(), pv, cb, &cbRead);
|
|
|
|
m_ullStreamPosition += cbRead;
|
|
|
|
if (pcbRead)
|
|
*pcbRead = cbRead;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Write
|
|
(const void __RPC_FAR *pv, ULONG cb,
|
|
ULONG __RPC_FAR *pcbWritten
|
|
)
|
|
{
|
|
DWORD grfAccess = m_grfMode & RW_ACCESS_MASK;
|
|
|
|
if (grfAccess != STGM_WRITE && grfAccess != STGM_READWRITE)
|
|
return STG_E_ACCESSDENIED;
|
|
|
|
CSyncWith sw(m_cs);
|
|
|
|
ULONG cbWritten = 0;
|
|
|
|
HRESULT hr = m_pLockBytes->WriteAt(m_ullStreamPosition.Uli(), pv, cb, &cbWritten);
|
|
|
|
m_ullStreamPosition += cbWritten;
|
|
|
|
if (pcbWritten)
|
|
*pcbWritten = cbWritten;
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IStream methods:
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Seek
|
|
(LARGE_INTEGER dlibMove, DWORD dwOrigin,
|
|
ULARGE_INTEGER __RPC_FAR *plibNewPosition
|
|
)
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
CSyncWith sw(m_cs);
|
|
|
|
STATSTG statstg;
|
|
|
|
hr = m_pLockBytes->Stat(&statstg, STATFLAG_NONAME);
|
|
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
|
|
CULINT ullNewPosition;
|
|
|
|
switch (dwOrigin)
|
|
{
|
|
case STREAM_SEEK_SET:
|
|
|
|
ullNewPosition = *(ULARGE_INTEGER *) &dlibMove;
|
|
|
|
break;
|
|
|
|
case STREAM_SEEK_CUR:
|
|
|
|
ullNewPosition = m_ullStreamPosition + *(ULARGE_INTEGER *) &dlibMove;
|
|
|
|
break;
|
|
|
|
case STREAM_SEEK_END:
|
|
|
|
ullNewPosition = statstg.cbSize;
|
|
ullNewPosition += *(ULARGE_INTEGER *) &dlibMove;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return STG_E_INVALIDFUNCTION;
|
|
}
|
|
|
|
if (ullNewPosition > statstg.cbSize)
|
|
return STG_E_INVALIDPOINTER;
|
|
|
|
m_ullStreamPosition = ullNewPosition;
|
|
|
|
if (plibNewPosition)
|
|
*plibNewPosition = ullNewPosition.Uli();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::SetSize(ULARGE_INTEGER libNewSize)
|
|
{
|
|
DWORD grfAccess = m_grfMode & RW_ACCESS_MASK;
|
|
|
|
if (grfAccess != STGM_WRITE && grfAccess != STGM_READWRITE)
|
|
return STG_E_ACCESSDENIED;
|
|
|
|
return m_pLockBytes->SetSize(libNewSize);
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::CopyTo
|
|
(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb,
|
|
ULARGE_INTEGER __RPC_FAR *pcbRead,
|
|
ULARGE_INTEGER __RPC_FAR *pcbWritten
|
|
)
|
|
{
|
|
BYTE abBuffer[CB_MAX_COPY_SEGMENT];
|
|
|
|
CULINT ullRequested, ullRead(0), ullWritten(0);
|
|
|
|
ullRequested = cb;
|
|
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
CSyncWith sw(m_cs);
|
|
|
|
ULONG ulSegment;
|
|
|
|
for (; ullRequested.NonZero(); ullRequested -= ulSegment)
|
|
{
|
|
ulSegment = CB_MAX_COPY_SEGMENT;
|
|
|
|
if (ulSegment > ullRequested)
|
|
ulSegment = ullRequested.Uli().LowPart;
|
|
|
|
ULONG cbRead = 0;
|
|
|
|
hr = Read(abBuffer, ulSegment, &cbRead);
|
|
|
|
ullRead += cbRead;
|
|
|
|
if (!SUCCEEDED(hr))
|
|
break;
|
|
|
|
ULONG cbWritten = 0;
|
|
|
|
hr = pstm->Write(abBuffer, ulSegment, &cbWritten);
|
|
|
|
ullWritten += cbWritten;
|
|
|
|
if (!SUCCEEDED(hr))
|
|
break;
|
|
}
|
|
|
|
if (pcbRead)
|
|
*pcbRead = ullRead.Uli();
|
|
|
|
if (pcbWritten)
|
|
*pcbWritten = ullWritten.Uli();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Commit(DWORD grfCommitFlags)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Revert(void)
|
|
{
|
|
RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::LockRegion
|
|
(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
|
|
DWORD dwLockType
|
|
)
|
|
{
|
|
return m_pLockBytes->LockRegion(libOffset, cb, dwLockType);
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::UnlockRegion
|
|
(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
|
|
DWORD dwLockType
|
|
)
|
|
{
|
|
return m_pLockBytes->UnlockRegion(libOffset, cb, dwLockType);
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Stat
|
|
(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
HRESULT hr = m_pLockBytes->Stat(pstatstg, grfStatFlag);
|
|
|
|
if (SUCCEEDED(hr))
|
|
pstatstg->type = STGTY_STREAM;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall CStream::CImpIStream::Clone
|
|
(IStream __RPC_FAR *__RPC_FAR *ppstm)
|
|
{
|
|
CImpIStream *pStreamNew = NULL;
|
|
|
|
m_pLockBytes->AddRef();
|
|
|
|
HRESULT hr = CStream::OpenStream(NULL, m_pLockBytes, m_grfMode,
|
|
(IStreamITEx **)&pStreamNew
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pStreamNew->m_ullStreamPosition = m_ullStreamPosition;
|
|
|
|
*ppstm = (IStream *) pStreamNew;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CStream::CImpIStream::SetDataSpaceName
|
|
(const WCHAR *pwcsDataSpaceName)
|
|
{
|
|
RonM_ASSERT(FALSE);
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CStream::CImpIStream::GetDataSpaceName
|
|
(WCHAR **ppwcsDataSpaceName)
|
|
{
|
|
RonM_ASSERT(FALSE);
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CStream::CImpIStream::Flush()
|
|
{
|
|
return m_pLockBytes->Flush();
|
|
}
|
|
|
|
|
|
|
|
|