|
|
//+-------------------------------------------------------------------
//
// File: stream.cxx
//
// Contents: Stream interface on flat File.
//
// Classes: CStreamOnFile
//
// Macros: DEFINE_INTERFACE_XMIT_ROUTINES
//
// History: 08-08-95 Rickhi Created
//
//--------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <stream.hxx>
CStreamOnFile::CStreamOnFile(const TCHAR *pwszFileName, SCODE &sc, BOOL fRead) : _clRefs(1), _hFile(NULL), _lOffset(0), _cSize(0), _cbData(0), _fRead(fRead) { _pbData = new BYTE[2048]; // should be big enough
if (!_pbData) { sc = E_OUTOFMEMORY; return; }
_cbData = 2048;
// open the file.
DWORD fdwCreate; if (_fRead) fdwCreate = OPEN_EXISTING; // open existing, fail if not found.
else fdwCreate = CREATE_ALWAYS; // overwrite existing if present
_hFile = CreateFile(pwszFileName, GENERIC_READ | GENERIC_WRITE, // fdwAccess
FILE_SHARE_READ | FILE_SHARE_WRITE, // fdwShareMode
NULL, // lpsaSecurity
fdwCreate, // creation options
FILE_ATTRIBUTE_NORMAL, // attributes & flags
NULL // hTemplateFile
);
if (_hFile == INVALID_HANDLE_VALUE) { sc = HRESULT_FROM_WIN32(GetLastError()); return; }
// read the file into the memory block
DWORD cbRead = 0; if (_fRead && ! ReadFile(_hFile, _pbData, _cbData, &cbRead, NULL)) { sc = HRESULT_FROM_WIN32(GetLastError()); return; }
if (_fRead) { _cSize = _cbData; }
sc = S_OK; }
CStreamOnFile::~CStreamOnFile(void) { if (_hFile) { if (!_fRead) { // write the data to the file
DWORD cbWritten = 0; if (!WriteFile(_hFile, _pbData, _cbData, &cbWritten, NULL)) { SCODE sc = HRESULT_FROM_WIN32(GetLastError()); } }
CloseHandle(_hFile); } }
STDMETHODIMP CStreamOnFile::QueryInterface( REFIID iidInterface, void FAR* FAR* ppvObj) { HRESULT hresult = S_OK;
// We only support IUnknown and IStream
if (IsEqualIID(iidInterface, IID_IUnknown) || IsEqualIID(iidInterface, IID_IStream)) { *ppvObj = this; AddRef(); } else { *ppvObj = NULL; hresult = E_NOINTERFACE; }
return hresult; }
STDMETHODIMP_(ULONG) CStreamOnFile::AddRef(void) { InterlockedIncrement(&_clRefs); return _clRefs; }
STDMETHODIMP_(ULONG) CStreamOnFile::Release(void) { if (InterlockedDecrement(&_clRefs) == 0) { delete this; return 0; }
return _clRefs; }
STDMETHODIMP CStreamOnFile::Read( VOID HUGEP* pv, ULONG cb, ULONG FAR* pcbRead) { HRESULT hresult = S_OK;
if (pcbRead) { *pcbRead = 0L; }
if (cb + _lOffset > _cSize) { cb = _cSize - _lOffset; hresult = STG_E_READFAULT; }
memcpy(pv, _pbData + _lOffset, (size_t) cb); _lOffset += cb;
if (pcbRead != NULL) { *pcbRead = cb; }
return hresult; }
STDMETHODIMP CStreamOnFile::Write( VOID const HUGEP* pv, ULONG cbToWrite, ULONG FAR* pcbWritten) { HRESULT hresult = S_OK;
if (pcbWritten) { *pcbWritten = 0L; }
if (cbToWrite + _lOffset > _cbData) { return E_OUTOFMEMORY; }
// copy in the new data
memcpy(_pbData + _lOffset, pv, (size_t) cbToWrite); _lOffset += cbToWrite;
if (pcbWritten != NULL) { *pcbWritten = cbToWrite; }
// We assume maxium size of buffer is the size to send on the network.
if (_cSize < _lOffset) { _cSize = _lOffset; }
return hresult; }
STDMETHODIMP CStreamOnFile::Seek( LARGE_INTEGER dlibMoveIN, DWORD dwOrigin, ULARGE_INTEGER FAR* plibNewPosition) { HRESULT hresult = S_OK;
LONG dlibMove = dlibMoveIN.LowPart; ULONG cbNewPos = dlibMove;
switch(dwOrigin) { case STREAM_SEEK_SET:
if (dlibMove >= 0) { _lOffset = dlibMove; } else { hresult = STG_E_SEEKERROR; } break;
case STREAM_SEEK_CUR:
if (!(dlibMove < 0 && ((ULONG) -dlibMove > _lOffset))) { _lOffset += (ULONG) dlibMove; } else { hresult = STG_E_SEEKERROR; } break;
case STREAM_SEEK_END:
if (!(dlibMove < 0 && ((ULONG) -dlibMove) > _cbData)) { _lOffset = _cbData + dlibMove; } else { hresult = STG_E_SEEKERROR; } break;
default:
hresult = STG_E_SEEKERROR; }
if (plibNewPosition != NULL) { ULISet32(*plibNewPosition, _lOffset); }
return hresult; }
STDMETHODIMP CStreamOnFile::SetSize(ULARGE_INTEGER cb) { return E_NOTIMPL; }
STDMETHODIMP CStreamOnFile::CopyTo( IStream FAR* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER FAR* pcbRead, ULARGE_INTEGER FAR* pcbWritten) { return E_NOTIMPL; }
STDMETHODIMP CStreamOnFile::Commit(DWORD grfCommitFlags) { return NOERROR; }
STDMETHODIMP CStreamOnFile::Revert(void) { return NOERROR; }
STDMETHODIMP CStreamOnFile::LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return STG_E_INVALIDFUNCTION; }
STDMETHODIMP CStreamOnFile::UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return STG_E_INVALIDFUNCTION; }
STDMETHODIMP CStreamOnFile::Stat( STATSTG FAR* pstatstg, DWORD statflag) { memset(pstatstg, 0, sizeof(STATSTG)); return E_NOTIMPL; }
STDMETHODIMP CStreamOnFile::Clone(IStream FAR * FAR *ppstm) { return E_NOTIMPL; }
|