summaryrefslogblamecommitdiffstats
path: root/private/oleutest/balls/common/stream.cxx
blob: d5c4681bfdfa17fc5a05954daf89f8cbc4558559 (plain) (tree)































































































































































































































































































































                                                                                
//+-------------------------------------------------------------------
//
//  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;
}