You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1023 lines
23 KiB
1023 lines
23 KiB
//+----------------------------------------------------------------------------
|
|
// File: util.cxx
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
// Includes -------------------------------------------------------------------
|
|
#include <core.hxx>
|
|
|
|
|
|
// Globals --------------------------------------------------------------------
|
|
const UCHAR SZ_NEWLINE[] = "\n\r";
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: CopyStream
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CopyStream(
|
|
IStream * pstmDest,
|
|
IStream * pstmSrc,
|
|
ULARGE_INTEGER cbCopy,
|
|
ULARGE_INTEGER * pcbRead,
|
|
ULARGE_INTEGER * pcbWritten)
|
|
{
|
|
DWORD cb = cbCopy.LowPart;
|
|
DWORD cbStep = min(cb, 0xFFFF);
|
|
DWORD cbRead, cbWritten;
|
|
DWORD cbTotalRead = 0;
|
|
DWORD cbTotalWritten = 0;
|
|
void * pv = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (cbCopy.HighPart)
|
|
return E_INVALIDARG;
|
|
|
|
pv = new BYTE[cbStep];
|
|
if (!pv)
|
|
return E_OUTOFMEMORY;
|
|
|
|
while (cb)
|
|
{
|
|
cbRead = min(cbStep, cb);
|
|
|
|
hr = pstmSrc->Read(pv, cbRead, &cbRead);
|
|
if (hr || !cbRead)
|
|
break;
|
|
|
|
cbTotalRead += cbRead;
|
|
|
|
hr = pstmDest->Write(pv, cbRead, &cbWritten);
|
|
if (S_OK != hr)
|
|
break;
|
|
|
|
cbTotalWritten += cbWritten;
|
|
|
|
if (cbWritten != cbRead)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
cb -= cbRead;
|
|
}
|
|
|
|
if (pcbRead)
|
|
{
|
|
pcbRead->HighPart = 0;
|
|
pcbRead->LowPart = cbTotalRead;
|
|
}
|
|
|
|
if (pcbWritten)
|
|
{
|
|
pcbWritten->HighPart = 0;
|
|
pcbWritten->LowPart = cbTotalWritten;
|
|
}
|
|
|
|
delete [] pv;
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Read
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CMemoryStream::Read(
|
|
void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbRead)
|
|
{
|
|
Assert(_pbData);
|
|
Assert(_ibPos <= _cbSize);
|
|
|
|
cb = min(cb, _cbSize - _ibPos);
|
|
|
|
::memcpy(pv, _pbData + _ibPos, cb);
|
|
_ibPos += cb;
|
|
|
|
if (pcbRead)
|
|
{
|
|
*pcbRead = cb;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Write
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CMemoryStream::Write(
|
|
const void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbWritten)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(_pbData);
|
|
Assert(_ibPos <= _cbSize);
|
|
|
|
if ((_ibPos + cb) > _cbSize)
|
|
{
|
|
hr = STG_E_MEDIUMFULL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
::memcpy(_pbData + _ibPos, pv, cb);
|
|
_ibPos += cb;
|
|
|
|
Cleanup:
|
|
if (pcbWritten)
|
|
{
|
|
*pcbWritten = (SUCCEEDED(hr) ? cb : 0);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Seek
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CMemoryStream::Seek(
|
|
LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER * plibNewPosition)
|
|
{
|
|
LONG ibOffset = (LONG)dlibMove.LowPart;
|
|
|
|
Assert(_pbData);
|
|
|
|
// Ensure only 32-bits is in-use
|
|
if (!(dlibMove.HighPart == 0 && ibOffset >= 0) &&
|
|
!(dlibMove.HighPart == -1 && ibOffset < 0))
|
|
return E_INVALIDARG;
|
|
|
|
switch (dwOrigin)
|
|
{
|
|
case STREAM_SEEK_SET:
|
|
break;
|
|
|
|
case STREAM_SEEK_CUR:
|
|
ibOffset = (LONG)_ibPos + ibOffset;
|
|
break;
|
|
|
|
case STREAM_SEEK_END:
|
|
ibOffset = (LONG)_cbSize + ibOffset;
|
|
break;
|
|
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Ensure the new offset is within the correct range
|
|
if ((ULONG)ibOffset > _cbSize)
|
|
return E_INVALIDARG;
|
|
|
|
// Store the new offset and return it
|
|
_ibPos = (ULONG)ibOffset;
|
|
|
|
if (plibNewPosition)
|
|
{
|
|
plibNewPosition->HighPart = 0;
|
|
plibNewPosition->LowPart = _ibPos;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: SetSize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CMemoryStream::SetSize(
|
|
ULARGE_INTEGER libNewSize)
|
|
{
|
|
if (libNewSize.HighPart)
|
|
return STG_E_MEDIUMFULL;
|
|
|
|
if (libNewSize.LowPart <= _cbSize)
|
|
{
|
|
_cbSize = libNewSize.LowPart;
|
|
}
|
|
else
|
|
{
|
|
BYTE * pbData = new BYTE[libNewSize.LowPart];
|
|
|
|
if (!pbData)
|
|
return STG_E_MEDIUMFULL;
|
|
|
|
if (_pbData && _cbSize)
|
|
{
|
|
::memcpy(pbData, _pbData, _cbSize);
|
|
}
|
|
|
|
delete [] _pbData;
|
|
_cbSize = libNewSize.LowPart;
|
|
_pbData = pbData;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: CopyTo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CMemoryStream::CopyTo(
|
|
IStream * pstm,
|
|
ULARGE_INTEGER cb,
|
|
ULARGE_INTEGER * pcbRead,
|
|
ULARGE_INTEGER * pcbWritten)
|
|
{
|
|
if (!pstm)
|
|
return STG_E_INVALIDPOINTER;
|
|
|
|
if (cb.HighPart || ((_ibPos + cb.LowPart) > _cbSize))
|
|
return E_INVALIDARG;
|
|
|
|
Assert(_pbData);
|
|
return ::CopyStream(pstm, this, cb, pcbRead, pcbWritten);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: CBufferedStream
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CBufferedStream::CBufferedStream(
|
|
IStream * pstm,
|
|
ULONG cbNewLine,
|
|
BOOL fRead)
|
|
{
|
|
Assert(_pstm);
|
|
|
|
_fRead = fRead;
|
|
_pb = NULL;
|
|
_cb = 0;
|
|
_ib = 0;
|
|
_cbLine = 0;
|
|
_cbNewLine = cbNewLine;
|
|
_cbTotal = 0;
|
|
_pstm = ::SAddRef(pstm);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: ~CBufferedStream
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CBufferedStream::~CBufferedStream()
|
|
{
|
|
Verify(SUCCEEDED(Flush()));
|
|
::SRelease(_pstm);
|
|
delete [] _pb;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Flush
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CBufferedStream::Flush(
|
|
ULONG * pcbWritten)
|
|
{
|
|
ULONG cbWritten;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(_pstm);
|
|
Implies(_cbNewLine, _ib <= (_cb + CB_NEWLINE));
|
|
Implies(!_cbNewLine, _ib <= _cb);
|
|
|
|
if (!pcbWritten)
|
|
{
|
|
pcbWritten = &cbWritten;
|
|
}
|
|
*pcbWritten = 0;
|
|
|
|
// For read-only streams, "read" the rest of the buffer by setting the buffer index
|
|
// (This will force a re-load during the next read)
|
|
if (_fRead)
|
|
{
|
|
_ib = _cb;
|
|
}
|
|
|
|
// For write-only streams, write the buffer to the stream
|
|
else if (_ib)
|
|
{
|
|
Assert(!_fRead);
|
|
hr = _pstm->Write(_pb, _ib, pcbWritten);
|
|
_cbTotal += *pcbWritten;
|
|
if (S_OK == hr)
|
|
{
|
|
Assert(*pcbWritten == _ib);
|
|
_ib = 0;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Load
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CBufferedStream::Load()
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(_fRead);
|
|
|
|
hr = _pstm->Read(_pb, _cb, &_cbTotal);
|
|
if (S_OK != hr)
|
|
goto Cleanup;
|
|
_ib = 0;
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: SetBufferSize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CBufferedStream::SetBufferSize(
|
|
ULONG cb)
|
|
{
|
|
// The buffer size cannot be changed once it has been set
|
|
// Also, it is illegal to use a zero-sized buffer
|
|
if (_pb || !cb)
|
|
return E_FAIL;
|
|
|
|
// Allocate a new buffer of the requested size
|
|
// (If the caller requested automatic interjection of NEWLINEs, slightly increase
|
|
// allocated buffer; the remembered size will continue to be that which they
|
|
// requested)
|
|
_pb = new BYTE[cb + (_cbNewLine ? CB_NEWLINE : 0)];
|
|
if (!_pb)
|
|
return E_OUTOFMEMORY;
|
|
_cb = cb;
|
|
_ib = (_fRead ? _cb : 0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Read
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBufferedStream::Read(
|
|
void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbRead)
|
|
{
|
|
ULONG cbTotalRead;
|
|
ULONG cbRead;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(_pb);
|
|
Assert(_cb);
|
|
Assert(_ib <= _cb);
|
|
|
|
if (!pv)
|
|
return E_INVALIDARG;
|
|
|
|
if (!pcbRead)
|
|
{
|
|
pcbRead = &cbTotalRead;
|
|
}
|
|
*pcbRead = 0;
|
|
|
|
// If bytes remain in the buffer, "read" those first
|
|
if (_ib < _cbTotal)
|
|
{
|
|
cbRead = min(cb, _cbTotal-_ib);
|
|
::memcpy(pv, _pb+_ib, cbRead);
|
|
_ib += cbRead;
|
|
cb -= cbRead;
|
|
pv = (void *)(((const BYTE *)pv) + cbRead);
|
|
*pcbRead += cbRead;
|
|
}
|
|
|
|
// If bytes remain to be read, fetch them now
|
|
if (cb)
|
|
{
|
|
Assert(_ib >= _cbTotal);
|
|
Assert(_cbTotal <= _cb);
|
|
|
|
// If the request fits within half of the buffer, then load a buffer full
|
|
if (cb < (_cb/2))
|
|
{
|
|
hr = Load();
|
|
if (S_OK != hr)
|
|
goto Cleanup;
|
|
|
|
cbRead = min(cb, _cbTotal);
|
|
::memcpy(pv, _pb, cbRead);
|
|
|
|
_ib = cbRead;
|
|
*pcbRead += cbRead;
|
|
}
|
|
|
|
// Otherwise, read directly into the callers buffer
|
|
else
|
|
{
|
|
hr = _pstm->Read(pv, cb, pcbRead);
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Write
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBufferedStream::Write(
|
|
const void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbWritten)
|
|
{
|
|
const BYTE * pbSrc = (const BYTE *)pv;
|
|
ULONG ibSrc = 0;
|
|
ULONG cbWritten;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(_pb);
|
|
Assert(_cb);
|
|
Assert(_ib <= _cb);
|
|
|
|
if (!pv)
|
|
return E_INVALIDARG;
|
|
|
|
if (pcbWritten)
|
|
{
|
|
*pcbWritten = 0;
|
|
}
|
|
|
|
// Treat calls to write on a read-only stream as if the stream is full
|
|
if (_fRead)
|
|
{
|
|
hr = STG_E_MEDIUMFULL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Write the bytes to the stream
|
|
while (cb)
|
|
{
|
|
// Determine the number of bytes to write this time through
|
|
cbWritten = min(cb, _cb-_ib);
|
|
if (_cbNewLine)
|
|
{
|
|
cbWritten = min(cbWritten, _cbNewLine-_cbLine);
|
|
}
|
|
|
|
// Write the bytes to the local buffer
|
|
::memcpy(_pb + _ib, pbSrc + ibSrc, cbWritten);
|
|
|
|
// Update the counters reflecting what has been written
|
|
// (Adding a newline if necessary)
|
|
cb -= cbWritten;
|
|
ibSrc += cbWritten;
|
|
_ib += cbWritten;
|
|
if (_cbNewLine)
|
|
{
|
|
_cbLine += cbWritten;
|
|
if (_cbLine >= _cbNewLine)
|
|
{
|
|
::memcpy(_pb + _ib, SZ_NEWLINE, CB_NEWLINE);
|
|
_cbLine = 0;
|
|
_ib += CB_NEWLINE;
|
|
}
|
|
}
|
|
|
|
// If the buffer is full, write it to the stream
|
|
if (_ib >= _cb)
|
|
{
|
|
hr = Flush(&cbWritten);
|
|
if (pcbWritten)
|
|
{
|
|
*pcbWritten += cbWritten;
|
|
}
|
|
if (S_OK != hr)
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: CFileStream
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CFileStream::CFileStream()
|
|
{
|
|
_hFile = NULL;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: ~CFileStream
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CFileStream::~CFileStream()
|
|
{
|
|
if (_hFile)
|
|
{
|
|
::CloseHandle(_hFile);
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Init
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CFileStream::Init(
|
|
LPCWSTR wszFileName,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwShareMode,
|
|
LPSECURITY_ATTRIBUTES pSecurityAttributes,
|
|
DWORD dwCreationDistribution,
|
|
DWORD dwFlagsAndAttributes,
|
|
HANDLE hTemplateFile)
|
|
{
|
|
int len = WideCharToMultiByte(CP_ACP, 0, wszFileName, -1, 0, 0, NULL, NULL);
|
|
LPSTR psz = new CHAR[len];
|
|
|
|
if (psz)
|
|
{
|
|
if (::WideCharToMultiByte(CP_ACP, 0, wszFileName, -1, (LPSTR)psz, len, NULL, NULL))
|
|
{
|
|
_hFile = ::CreateFileA(psz, dwDesiredAccess, dwShareMode, pSecurityAttributes,
|
|
dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile);
|
|
}
|
|
delete [] psz;
|
|
}
|
|
else
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// CreateFile succeeded if we didn't get back INVALID_HANDLE_VALUE
|
|
return ((_hFile != INVALID_HANDLE_VALUE)
|
|
? S_OK
|
|
: GetWin32Hresult());
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: GetFileSize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CFileStream::GetFileSize(
|
|
ULONG * pcbSize)
|
|
{
|
|
Assert(_hFile);
|
|
Assert(pcbSize);
|
|
*pcbSize = ::GetFileSize(_hFile, NULL);
|
|
return (*pcbSize == 0xFFFFFFFF
|
|
? GetWin32Hresult()
|
|
: S_OK);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Read
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CFileStream::Read(
|
|
void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbRead)
|
|
{
|
|
ULONG cbRead;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!pv)
|
|
return E_INVALIDARG;
|
|
|
|
if (!pcbRead)
|
|
{
|
|
pcbRead = &cbRead;
|
|
}
|
|
|
|
hr = (::ReadFile(_hFile, pv, cb, pcbRead, NULL)
|
|
? S_OK
|
|
: S_FALSE);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Write
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CFileStream::Write(
|
|
const void * pv,
|
|
ULONG cb,
|
|
ULONG * pcbWritten)
|
|
{
|
|
ULONG cbWritten;
|
|
HRESULT hr;
|
|
|
|
if (!pv)
|
|
return E_INVALIDARG;
|
|
|
|
if (!pcbWritten)
|
|
{
|
|
pcbWritten = &cbWritten;
|
|
}
|
|
|
|
hr = (::WriteFile(_hFile, pv, cb, pcbWritten, NULL)
|
|
? S_OK
|
|
: STG_E_MEDIUMFULL);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Member: Seek
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CFileStream::Seek(
|
|
LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER * plibNewPosition)
|
|
{
|
|
DWORD dwMoveMethod;
|
|
ULARGE_INTEGER libNewPosition;
|
|
HRESULT hr;
|
|
|
|
if (plibNewPosition)
|
|
{
|
|
plibNewPosition->HighPart = 0;
|
|
plibNewPosition->LowPart = 0;
|
|
}
|
|
|
|
switch(dwOrigin)
|
|
{
|
|
case STREAM_SEEK_SET: dwMoveMethod = FILE_BEGIN; break;
|
|
case STREAM_SEEK_CUR: dwMoveMethod = FILE_CURRENT; break;
|
|
case STREAM_SEEK_END: dwMoveMethod = FILE_END; break;
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
libNewPosition.LowPart = ::SetFilePointer(_hFile, dlibMove.LowPart, &dlibMove.HighPart, dwMoveMethod);
|
|
libNewPosition.HighPart = dlibMove.HighPart;
|
|
|
|
if (libNewPosition.LowPart == 0xFFFFFFFF &&
|
|
::GetLastError() != NO_ERROR)
|
|
{
|
|
hr = STG_E_INVALIDPOINTER;
|
|
}
|
|
else
|
|
{
|
|
if (plibNewPosition)
|
|
{
|
|
*plibNewPosition = libNewPosition;
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: SetSize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CFileStream::SetSize(
|
|
ULARGE_INTEGER libNewSize)
|
|
{
|
|
LONG curLow, curHigh;
|
|
BOOL fEOFSet;
|
|
|
|
curHigh = 0;
|
|
curLow = ::SetFilePointer(_hFile, 0, &curHigh, FILE_CURRENT);
|
|
if (0xFFFFFFFF == ::SetFilePointer(_hFile, libNewSize.LowPart,
|
|
(LONG *)&libNewSize.HighPart, FILE_BEGIN))
|
|
{
|
|
return STG_E_INVALIDFUNCTION;
|
|
}
|
|
|
|
fEOFSet = ::SetEndOfFile(_hFile);
|
|
#ifdef _DEBUG
|
|
Verify(0xFFFFFFFF != ::SetFilePointer(_hFile, curLow, &curHigh, FILE_BEGIN));
|
|
#else
|
|
::SetFilePointer(_hFile, curLow, &curHigh, FILE_BEGIN);
|
|
#endif
|
|
|
|
return (fEOFSet
|
|
? S_OK
|
|
: STG_E_MEDIUMFULL);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: CopyTo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CFileStream::CopyTo(
|
|
IStream * pstm,
|
|
ULARGE_INTEGER cb,
|
|
ULARGE_INTEGER * pcbRead,
|
|
ULARGE_INTEGER * pcbWritten)
|
|
{
|
|
if (!pstm)
|
|
return STG_E_INVALIDPOINTER;
|
|
|
|
return ::CopyStream(pstm, this, cb, pcbRead, pcbWritten);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Member: PrivateQueryInterface
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CFileStream::PrivateQueryInterface(
|
|
REFIID riid,
|
|
void ** ppvObj)
|
|
{
|
|
if (riid == IID_IStream)
|
|
*ppvObj = (IStream *)this;
|
|
|
|
if (*ppvObj)
|
|
return S_OK;
|
|
else
|
|
return parent::PrivateQueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: CoAlloc
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void *
|
|
CoAlloc(
|
|
ULONG cb)
|
|
{
|
|
Assert(TLS(dll.pmalloc));
|
|
return TLS(dll.pmalloc)->Alloc(cb);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: CoFree
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
CoFree(
|
|
void * pv)
|
|
{
|
|
if (!pv)
|
|
return;
|
|
|
|
Assert(TLS(dll.pmalloc));
|
|
Assert(CoDidAlloc(pv));
|
|
TLS(dll.pmalloc)->Free(pv);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: CoGetSize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
ULONG
|
|
CoGetSize(
|
|
void * pv)
|
|
{
|
|
Assert(TLS(dll.pmalloc));
|
|
Assert(CoDidAlloc(pv));
|
|
return (ULONG)(TLS(dll.pmalloc)->GetSize(pv));
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: CoDidAlloc
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
CoDidAlloc(
|
|
void * pv)
|
|
{
|
|
Assert(TLS(dll.pmalloc));
|
|
return (!pv || TLS(dll.pmalloc)->DidAlloc(pv) == 1
|
|
? TRUE
|
|
: FALSE);
|
|
}
|
|
|
|
|
|
#ifdef _NOCRT
|
|
//+----------------------------------------------------------------------------
|
|
// Function: purecall
|
|
//
|
|
// Synopsis: _SHIP build replacement for CRT vtable routine
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
int __cdecl
|
|
_purecall()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: _tcslen
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
extern "C" size_t __cdecl
|
|
_tcslen(
|
|
const TCHAR * psz)
|
|
{
|
|
for (size_t i=0; *psz; psz++, i++);
|
|
return i;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: memcmp
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
extern "C" int __cdecl
|
|
memcmp(
|
|
const void * pv1,
|
|
const void * pv2,
|
|
size_t cb)
|
|
{
|
|
size_t i;
|
|
int d;
|
|
for (i=0, d=0; i < cb && !d; i++)
|
|
d = (*(const BYTE *)pv1) - (*(const BYTE *)pv2);
|
|
return d;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: memcpy
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
extern "C" void * __cdecl
|
|
memcpy(
|
|
void * pvDest,
|
|
const void * pvSrc,
|
|
size_t cb)
|
|
{
|
|
for (size_t i=0; i < cb; i++)
|
|
((BYTE *)pvDest)[i] = ((const BYTE *)pvSrc)[i];
|
|
return pvDest;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: memset
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
extern "C" void * __cdecl
|
|
memset(
|
|
void * pv,
|
|
int c,
|
|
size_t cb)
|
|
{
|
|
for (size_t i=0; i < cb; i++)
|
|
((BYTE *)pv)[i] = (BYTE)c;
|
|
return pv;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
// Function: memmove
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
extern "C" void * __cdecl
|
|
memmove(
|
|
void * pvDest,
|
|
const void * pvSrc,
|
|
size_t cb)
|
|
{
|
|
BYTE * pb1;
|
|
BYTE * pb2;
|
|
|
|
if (pvSrc < pvDest)
|
|
{
|
|
pb1 = (BYTE *)pvDest + cb;
|
|
pb2 = (BYTE *)pvSrc + cb;
|
|
for (; cb; cb--)
|
|
{
|
|
*pb1-- = *pb2--;
|
|
}
|
|
}
|
|
else if (pvSrc > pvDest)
|
|
{
|
|
pb1 = (BYTE *)pvDest;
|
|
pb2 = (BYTE *)pvSrc;
|
|
for (; cb; cb--)
|
|
{
|
|
*pb1++ = *pb2++;
|
|
}
|
|
}
|
|
return pvDest;
|
|
}
|
|
#endif // _NOCRT
|