838 lines
19 KiB
C++
838 lines
19 KiB
C++
|
/******************************************************************************
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
pchstm.h
|
||
|
|
||
|
Abstract:
|
||
|
This file contains the implementations of various stream objects
|
||
|
|
||
|
Revision History:
|
||
|
created derekm 01/19/00
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "pfstm.h"
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamFile- construct / destruct
|
||
|
|
||
|
// **************************************************************************
|
||
|
CPFStreamFile::CPFStreamFile(void)
|
||
|
{
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
m_dwAccess = 0;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
CPFStreamFile::~CPFStreamFile(void)
|
||
|
{
|
||
|
this->Close();
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamFile- non interface
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamFile::Open(LPCWSTR szFile, DWORD dwAccess,
|
||
|
DWORD dwDisposition, DWORD dwSharing)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Open(szFile)");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
VALIDATEPARM(hr, (szFile == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
hFile = ::CreateFileW(szFile, dwAccess, dwSharing, NULL, dwDisposition,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
TESTBOOL(hr, (hFile != INVALID_HANDLE_VALUE))
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
this->Close();
|
||
|
|
||
|
m_hFile = hFile;
|
||
|
m_dwAccess = dwAccess;
|
||
|
hFile = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
done:
|
||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||
|
CloseHandle(hFile);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamFile::Open(HANDLE hFile, DWORD dwAccess)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Open(hFile)");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
HANDLE hFileNew = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
VALIDATEPARM(hr, (hFile == INVALID_HANDLE_VALUE || hFile == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
TESTBOOL(hr, DuplicateHandle(GetCurrentProcess(), hFile,
|
||
|
GetCurrentProcess(), &hFileNew, dwAccess,
|
||
|
FALSE, 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
this->Close();
|
||
|
|
||
|
m_hFile = hFileNew;
|
||
|
m_dwAccess = dwAccess;
|
||
|
hFileNew = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
done:
|
||
|
if (hFileNew != INVALID_HANDLE_VALUE)
|
||
|
CloseHandle(hFileNew);
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamFile::Close(void)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Close");
|
||
|
|
||
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
CloseHandle(m_hFile);
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamFile- ISequentialStream
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamFile::Read(void *pv, ULONG cb, ULONG *pcbRead)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Read");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD cbRead;
|
||
|
|
||
|
if (pv == NULL || m_hFile == INVALID_HANDLE_VALUE || m_hFile == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbRead != NULL)
|
||
|
*pcbRead = 0;
|
||
|
|
||
|
if (ReadFile(m_hFile, pv, cb, &cbRead, NULL) == FALSE)
|
||
|
{
|
||
|
if (GetLastError() == ERROR_ACCESS_DENIED)
|
||
|
hr = STG_E_ACCESSDENIED;
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (cbRead == 0 && cb != 0)
|
||
|
{
|
||
|
hr = S_FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbRead != NULL)
|
||
|
*pcbRead = cbRead;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamFile::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Write");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD cbWritten;
|
||
|
|
||
|
if (pv == NULL || m_hFile == INVALID_HANDLE_VALUE || m_hFile == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if ((m_dwAccess & GENERIC_WRITE) == 0)
|
||
|
{
|
||
|
hr = STG_E_WRITEFAULT;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbWritten != NULL)
|
||
|
*pcbWritten = 0;
|
||
|
|
||
|
if (WriteFile(m_hFile, pv, cb, &cbWritten, NULL) == FALSE)
|
||
|
{
|
||
|
switch(GetLastError())
|
||
|
{
|
||
|
case ERROR_DISK_FULL:
|
||
|
hr = STG_E_MEDIUMFULL;
|
||
|
break;
|
||
|
|
||
|
case ERROR_ACCESS_DENIED:
|
||
|
hr = STG_E_ACCESSDENIED;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = STG_E_CANTSAVE;
|
||
|
}
|
||
|
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbWritten != NULL)
|
||
|
*pcbWritten = cbWritten;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamFile- IStream
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamFile::Seek(LARGE_INTEGER libMove, DWORD dwOrigin,
|
||
|
ULARGE_INTEGER *plibNewPosition)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Seek");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LONG dwHigh, dwLow;
|
||
|
|
||
|
if (m_hFile == INVALID_HANDLE_VALUE || m_hFile == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (plibNewPosition != NULL)
|
||
|
{
|
||
|
plibNewPosition->HighPart = 0;
|
||
|
plibNewPosition->LowPart = 0;
|
||
|
}
|
||
|
|
||
|
switch(dwOrigin)
|
||
|
{
|
||
|
default:
|
||
|
case STREAM_SEEK_CUR:
|
||
|
dwOrigin = FILE_CURRENT;
|
||
|
break;
|
||
|
|
||
|
case STREAM_SEEK_SET:
|
||
|
dwOrigin = FILE_BEGIN;
|
||
|
break;
|
||
|
|
||
|
case STREAM_SEEK_END:
|
||
|
dwOrigin = FILE_END;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TESTBOOL(hr, SetFilePointerEx(m_hFile, libMove,
|
||
|
(LARGE_INTEGER *)plibNewPosition, dwOrigin));
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
hr = STG_E_INVALIDFUNCTION;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamFile::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Seek");
|
||
|
|
||
|
BY_HANDLE_FILE_INFORMATION fi;
|
||
|
HRESULT hr = NOERROR;
|
||
|
|
||
|
if (pstatstg == NULL || m_hFile == INVALID_HANDLE_VALUE ||
|
||
|
m_hFile == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (GetFileInformationByHandle(m_hFile, &fi) == FALSE)
|
||
|
{
|
||
|
hr = STG_E_ACCESSDENIED;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
pstatstg->pwcsName = NULL;
|
||
|
pstatstg->type = STGTY_STREAM;
|
||
|
pstatstg->cbSize.HighPart = fi.nFileSizeHigh;
|
||
|
pstatstg->cbSize.LowPart = fi.nFileSizeLow;
|
||
|
pstatstg->mtime = fi.ftCreationTime;
|
||
|
pstatstg->ctime = fi.ftLastAccessTime;
|
||
|
pstatstg->atime = fi.ftLastWriteTime;
|
||
|
pstatstg->clsid = CLSID_NULL;
|
||
|
pstatstg->grfMode = 0;
|
||
|
pstatstg->grfLocksSupported = 0;
|
||
|
pstatstg->grfStateBits = 0;
|
||
|
pstatstg->reserved = 0;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamFile::Clone(IStream **ppstm)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamFile::Clone");
|
||
|
|
||
|
CPFStreamFile *pstm = NULL;
|
||
|
HRESULT hr = NOERROR;
|
||
|
|
||
|
if (ppstm == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// Create a new stream object.
|
||
|
pstm = CPFStreamFile::CreateInstance();
|
||
|
if (pstm == NULL)
|
||
|
{
|
||
|
hr = STG_E_INSUFFICIENTMEMORY;
|
||
|
goto done;
|
||
|
}
|
||
|
pstm->AddRef();
|
||
|
|
||
|
// intialize it
|
||
|
hr = pstm->Open(m_hFile, m_dwAccess);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// need to hand back the IStream interface, so...
|
||
|
hr = pstm->QueryInterface(IID_IStream, (LPVOID *)ppstm);
|
||
|
_ASSERT(SUCCEEDED(hr));
|
||
|
|
||
|
pstm = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pstm != NULL)
|
||
|
pstm->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamMem- construct / destruct
|
||
|
|
||
|
// **************************************************************************
|
||
|
CPFStreamMem::CPFStreamMem(void)
|
||
|
{
|
||
|
m_pvData = NULL;
|
||
|
m_pvPtr = NULL;
|
||
|
m_cb = 0;
|
||
|
m_cbRead = 0;
|
||
|
m_cbGrow = 0;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
CPFStreamMem::~CPFStreamMem(void)
|
||
|
{
|
||
|
this->Clean();
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamMem- non interface
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamMem::Init(DWORD cbStart, DWORD cbGrowBy)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Init");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LPVOID pvNew = NULL;
|
||
|
|
||
|
// if the user passes us -1 for either of these, he means 'use default',
|
||
|
// which is the system page size...
|
||
|
if (cbStart == (DWORD)-1 || cbGrowBy == (DWORD)-1)
|
||
|
{
|
||
|
SYSTEM_INFO si;
|
||
|
|
||
|
ZeroMemory(&si, sizeof(si));
|
||
|
GetSystemInfo(&si);
|
||
|
if (cbStart == (DWORD)-1)
|
||
|
cbStart = si.dwPageSize;
|
||
|
if (cbGrowBy == (DWORD)-1)
|
||
|
cbGrowBy = si.dwPageSize;
|
||
|
}
|
||
|
|
||
|
if (cbStart > 0)
|
||
|
{
|
||
|
pvNew = MyAlloc(cbStart);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
this->Clean();
|
||
|
|
||
|
m_pvData = pvNew;
|
||
|
m_pvPtr = pvNew;
|
||
|
m_cb = cbStart;
|
||
|
m_cbWrite = 0;
|
||
|
m_cbGrow = cbGrowBy;
|
||
|
|
||
|
pvNew = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pvNew != NULL)
|
||
|
MyFree(pvNew);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamMem::InitBinBlob(LPVOID pv, DWORD cb, DWORD cbGrow)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::InitBinBlob");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LPVOID pvNew = NULL;
|
||
|
|
||
|
VALIDATEPARM(hr, (pv == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
if (cb == 0)
|
||
|
goto done;
|
||
|
|
||
|
pvNew = MyAlloc(cb);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
CopyMemory(pvNew, pv, cb);
|
||
|
|
||
|
this->Clean();
|
||
|
|
||
|
m_pvData = pvNew;
|
||
|
m_pvPtr = pvNew;
|
||
|
m_cb = cb;
|
||
|
m_cbWrite = cb;
|
||
|
m_cbGrow = cbGrow;
|
||
|
|
||
|
pvNew = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pvNew != NULL)
|
||
|
MyFree(pvNew);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamMem::InitTextBlob(LPCWSTR wsz, DWORD cch, BOOL fConvertToANSI)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::InitTextBlob(LPCWSTR)");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LPVOID pvNew = NULL;
|
||
|
DWORD cb;
|
||
|
|
||
|
VALIDATEPARM(hr, (wsz == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
if (cch == 0)
|
||
|
goto done;
|
||
|
|
||
|
if (fConvertToANSI)
|
||
|
{
|
||
|
cb = WideCharToMultiByte(CP_ACP, 0, wsz, -1, NULL, 0, NULL, NULL);
|
||
|
TESTBOOL(hr, (cb != 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
pvNew = MyAlloc(cb);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
if (WideCharToMultiByte(CP_ACP, 0, wsz, -1, (LPSTR)pvNew, cb, NULL,
|
||
|
NULL) == 0)
|
||
|
TESTBOOL(hr, (cb != 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// assume cch does NOT include the NULL terminator, so gotta add 1
|
||
|
cb = (cch + 1) * sizeof(WCHAR);
|
||
|
pvNew = MyAlloc(cb);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
CopyMemory(pvNew, wsz, cb);
|
||
|
}
|
||
|
|
||
|
this->Clean();
|
||
|
|
||
|
m_pvData = pvNew;
|
||
|
m_pvPtr = pvNew;
|
||
|
m_cb = cb;
|
||
|
m_cbWrite = cb;
|
||
|
m_cbGrow = 0;
|
||
|
|
||
|
pvNew = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pvNew != NULL)
|
||
|
MyFree(pvNew);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamMem::InitTextBlob(LPCSTR sz, DWORD cch, BOOL fConvertToWCHAR)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::InitTextBlob(LPCSTR)");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LPVOID pvNew = NULL;
|
||
|
DWORD cb;
|
||
|
|
||
|
VALIDATEPARM(hr, (sz == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
if (cch == 0)
|
||
|
goto done;
|
||
|
|
||
|
if (fConvertToWCHAR)
|
||
|
{
|
||
|
cb = MultiByteToWideChar(CP_ACP, 0, sz, -1, NULL, 0);
|
||
|
TESTBOOL(hr, (cb != 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
pvNew = MyAlloc(cb);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
cb = MultiByteToWideChar(CP_ACP, 0, sz, -1, (LPWSTR)pvNew, cb);
|
||
|
TESTBOOL(hr, (cb != 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// assume cch does NOT include the NULL terminator, so gotta add 1
|
||
|
cb = cch + 1;
|
||
|
pvNew = MyAlloc(cb);
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), E_OUTOFMEMORY);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
CopyMemory(pvNew, sz, cb);
|
||
|
}
|
||
|
|
||
|
this->Clean();
|
||
|
|
||
|
m_pvData = pvNew;
|
||
|
m_pvPtr = pvNew;
|
||
|
m_cb = cb;
|
||
|
m_cbWrite = cb;
|
||
|
m_cbGrow = 0;
|
||
|
|
||
|
pvNew = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pvNew != NULL)
|
||
|
MyFree(pvNew);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
HRESULT CPFStreamMem::Clean(void)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Clean");
|
||
|
|
||
|
if (m_pvData != NULL)
|
||
|
{
|
||
|
MyFree(m_pvData);
|
||
|
m_pvData = NULL;
|
||
|
m_pvPtr = NULL;
|
||
|
m_cb = 0;
|
||
|
m_cbRead = 0;
|
||
|
m_cbWrite = 0;
|
||
|
m_cbGrow = 0;
|
||
|
}
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamMem- ISequentialStream
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamMem::Read(void *pv, ULONG cb, ULONG *pcbRead)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Read");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD cbRead;
|
||
|
|
||
|
if (pv == NULL || m_pvPtr == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbRead != NULL)
|
||
|
*pcbRead = 0;
|
||
|
|
||
|
if (m_cbRead >= m_cbWrite)
|
||
|
{
|
||
|
hr = S_FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (m_cbRead + cb > m_cbWrite)
|
||
|
cbRead = m_cbWrite - m_cbRead;
|
||
|
else
|
||
|
cbRead = cb;
|
||
|
|
||
|
CopyMemory(pv, m_pvPtr, cbRead);
|
||
|
|
||
|
m_pvPtr = (LPVOID)((BYTE *)m_pvPtr + cbRead);
|
||
|
m_cbRead += cbRead;
|
||
|
|
||
|
if (pcbRead != NULL)
|
||
|
*pcbRead = cbRead;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamMem::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Write");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
|
||
|
if (pv == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (pcbWritten != NULL)
|
||
|
*pcbWritten = 0;
|
||
|
|
||
|
if (m_cbRead + cb > m_cb)
|
||
|
{
|
||
|
if (m_cbGrow > 0)
|
||
|
{
|
||
|
LPVOID pvNew = NULL, pvPtr;
|
||
|
DWORD cbNew;
|
||
|
|
||
|
cbNew = MyMax(m_cb + m_cbGrow, m_cbRead + cb);
|
||
|
if (m_pvData == NULL)
|
||
|
{
|
||
|
pvNew = MyAlloc(cbNew);
|
||
|
pvPtr = pvNew;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pvNew = MyReAlloc(m_pvData, cbNew);
|
||
|
pvPtr = (LPVOID)((BYTE *)m_pvPtr + m_cbRead);
|
||
|
}
|
||
|
VALIDATEEXPR(hr, (pvNew == NULL), STG_E_MEDIUMFULL);
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
m_pvData = pvNew;
|
||
|
m_pvPtr = pvPtr;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
hr = STG_E_MEDIUMFULL;
|
||
|
goto done;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CopyMemory(m_pvPtr, pv, cb);
|
||
|
|
||
|
m_pvPtr = (LPVOID)((BYTE *)m_pvPtr + cb);
|
||
|
m_cbRead += cb;
|
||
|
if (m_cbRead > m_cbWrite)
|
||
|
m_cbWrite = m_cbRead;
|
||
|
|
||
|
if (pcbWritten != NULL)
|
||
|
*pcbWritten = cb;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPFStreamFile- IStream
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamMem::Seek(LARGE_INTEGER libMove, DWORD dwOrigin,
|
||
|
ULARGE_INTEGER *plibNewPosition)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Seek");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
LPVOID pvNew;
|
||
|
DWORD cbNew;
|
||
|
|
||
|
if (m_pvPtr == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (plibNewPosition != NULL)
|
||
|
{
|
||
|
plibNewPosition->HighPart = 0;
|
||
|
plibNewPosition->LowPart = 0;
|
||
|
}
|
||
|
|
||
|
if (libMove.HighPart != 0 && libMove.HighPart != (DWORD)-1)
|
||
|
{
|
||
|
hr = STG_E_INVALIDFUNCTION;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
switch(dwOrigin)
|
||
|
{
|
||
|
default:
|
||
|
case STREAM_SEEK_CUR:
|
||
|
pvNew = (LPVOID)((BYTE *)m_pvPtr + libMove.LowPart);
|
||
|
cbNew = m_cbRead + libMove.LowPart;
|
||
|
break;
|
||
|
|
||
|
case STREAM_SEEK_SET:
|
||
|
pvNew = (LPVOID)((BYTE *)m_pvData + libMove.LowPart);
|
||
|
cbNew = libMove.LowPart;
|
||
|
break;
|
||
|
|
||
|
case STREAM_SEEK_END:
|
||
|
pvNew = (LPVOID)(((BYTE *)m_pvData + m_cbWrite) - libMove.LowPart);
|
||
|
cbNew = m_cbWrite - libMove.LowPart;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pvNew < m_pvData || cbNew > m_cbWrite)
|
||
|
{
|
||
|
hr = STG_E_INVALIDFUNCTION;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
m_pvPtr = pvNew;
|
||
|
m_cbRead = cbNew;
|
||
|
|
||
|
if (plibNewPosition != NULL)
|
||
|
plibNewPosition->LowPart = cbNew;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamMem::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Stat");
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
|
||
|
if (pstatstg == NULL || m_pvData == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
ZeroMemory(pstatstg, sizeof(STATSTG));
|
||
|
pstatstg->type = STGTY_STREAM;
|
||
|
pstatstg->cbSize.LowPart = m_cbWrite;
|
||
|
|
||
|
done:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// **************************************************************************
|
||
|
STDMETHODIMP CPFStreamMem::Clone(IStream **ppstm)
|
||
|
{
|
||
|
USE_TRACING("CPFStreamMem::Clone");
|
||
|
|
||
|
CPFStreamMem *pstm = NULL;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (ppstm == NULL)
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// Create a new stream object.
|
||
|
pstm = CPFStreamMem::CreateInstance();
|
||
|
if (pstm == NULL)
|
||
|
{
|
||
|
hr = STG_E_INSUFFICIENTMEMORY;
|
||
|
goto done;
|
||
|
}
|
||
|
pstm->AddRef();
|
||
|
|
||
|
// intialize it
|
||
|
hr = pstm->InitBinBlob(m_pvData, m_cbWrite);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
hr = STG_E_INVALIDPOINTER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// need to hand back the IStream interface, so...
|
||
|
hr = pstm->QueryInterface(IID_IStream, (LPVOID *)ppstm);
|
||
|
_ASSERT(SUCCEEDED(hr));
|
||
|
|
||
|
pstm = NULL;
|
||
|
|
||
|
done:
|
||
|
if (pstm != NULL)
|
||
|
pstm->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|