321 lines
5.7 KiB
C++
321 lines
5.7 KiB
C++
//+-------------------------------------------------------------------
|
||
//
|
||
// 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;
|
||
}
|
||
|