|
|
#define INC_OLE2
#include <windows.h>
#include <windowsx.h>
#include <cstream.h>
#include <dbgtrace.h>
#define Tracefn(fn)
CImpIStream::CImpIStream(void) { SYSTEMTIME st;
Tracefn("CImpIStream::CImpIStream"); m_cRef = 1;
m_cbSeek = 0; m_statstg.cbSize.LowPart = 0; memset(&m_statstg,0,sizeof(STATSTG));
GetSystemTime(&st); SystemTimeToFileTime(&st,&m_statstg.ctime); }
CImpIStream::~CImpIStream(void) { Tracefn("CImpIStream::~CImpIStream"); }
STDMETHODIMP CImpIStream::QueryInterface( REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) { Tracefn("CImpIStream::QueryInterface");
*ppvObject=NULL;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid,IID_IStream)) *ppvObject=(LPVOID)this;
if( *ppvObject != NULL ) { ((LPUNKNOWN)*ppvObject)->AddRef(); return NOERROR; }
return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CImpIStream::AddRef(void) { Tracefn("CImpIStream::AddRef"); InterlockedIncrement(&m_cRef); return m_cRef; }
STDMETHODIMP_(ULONG) CImpIStream::Release(void) { ULONG cRefT; Tracefn("CImpIStream::Release"); cRefT = InterlockedDecrement(&m_cRef); if( 0 == cRefT ) delete this; return cRefT; }
STDMETHODIMP CImpIStream::Read( void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { Tracefn("CImpIStream::Read"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::Write( const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { Tracefn("CImpIStream::Write"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { Tracefn("CImpIStream::Seek") return E_NOTIMPL; }
STDMETHODIMP CImpIStream::SetSize( ULARGE_INTEGER libNewSize) { Tracefn("CImpIStream::SetSize"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::CopyTo( IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { Tracefn("CImpIStream::CopyTo"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::Commit( DWORD grfCommitFlags) { Tracefn("CImpIStream::Commit"); return S_OK; }
STDMETHODIMP CImpIStream::Revert( void) { Tracefn("CImpIStream::Revert"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { Tracefn("CImpIStream::LockRegion"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { Tracefn("CImpIStream::UnlockRegion"); return E_NOTIMPL; }
STDMETHODIMP CImpIStream::Stat( STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) { STATSTG * pstat = NULL; Tracefn("CImpIStream::Stat");
if( !pstatstg ) return STG_E_INVALIDPOINTER;
memcpy(pstatstg,&m_statstg,sizeof(STATSTG));
return NOERROR; }
STDMETHODIMP CImpIStream::Clone( IStream __RPC_FAR *__RPC_FAR *ppstm) { Tracefn("CImpIStream::Clone"); return E_NOTIMPL; }
/* -------------------------------------------------------------------------
CStreamMem ------------------------------------------------------------------------- */ CStreamMem::CStreamMem(void) { Tracefn("CStreamMem::CStreamMem"); m_pvData = NULL; m_fExternalData = FALSE; }
CStreamMem::CStreamMem(PVOID pvData,ULONG cbSize) { Tracefn("CStreamMem::CStreamMem"); m_pvData = pvData; m_cbSeek = 0; m_statstg.cbSize.LowPart = cbSize; m_fExternalData = TRUE; }
CStreamMem::~CStreamMem(void) { Tracefn("CStreamMem::~CStreamMem"); if( m_pvData && !m_fExternalData ) free(m_pvData); }
STDMETHODIMP CStreamMem::GetPointerFromStream(PVOID *ppv,DWORD *pdwSize) { HRESULT hr = NOERROR;
if( NULL == ppv || NULL == pdwSize ) return STG_E_INVALIDPOINTER;
if( NULL != m_pvData ) { *ppv = m_pvData; *pdwSize = m_statstg.cbSize.LowPart; } else { *ppv = NULL; *pdwSize = 0; } return hr; }
// IStream
STDMETHODIMP CStreamMem::Read( void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { SYSTEMTIME st; ULONG cbRead = 0; Tracefn("CStreamMem::Read");
if( pcbRead != NULL ) *pcbRead = 0;
_ASSERT(m_cbSeek <= m_statstg.cbSize.LowPart);
// anything to do?
if( cb == 0 || m_statstg.cbSize.LowPart == 0 || m_cbSeek == m_statstg.cbSize.LowPart ) return NOERROR;
// determine amount to copy
cbRead = min(cb,m_statstg.cbSize.LowPart - m_cbSeek);
if( cbRead > 0 ) { // copy it
CopyMemory(pv,(PBYTE)m_pvData + m_cbSeek,cbRead);
// adjust seek pointer
m_cbSeek += cbRead; }
// update access time
GetSystemTime(&st); SystemTimeToFileTime(&st,&m_statstg.atime);
if( pcbRead != NULL ) *pcbRead = cbRead;
_ASSERT(m_cbSeek <= m_statstg.cbSize.LowPart);
return NOERROR; }
STDMETHODIMP CStreamMem::Write( const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { ULONG cbNewSize = 0; PVOID pvMem = NULL; SYSTEMTIME st; Tracefn("CStreamMem::Write");
if( pcbWritten != NULL) *pcbWritten = 0;
// external data is readonly
if( m_fExternalData ) return STG_E_MEDIUMFULL;
// anything to do?
if( cb == 0 ) return NOERROR;
// determine new size
cbNewSize = max(m_cbSeek + cb, m_statstg.cbSize.LowPart);
if( m_pvData == NULL ) { // no memory alloc yet
if( NULL == (m_pvData = malloc(cbNewSize)) ) return STG_E_MEDIUMFULL; m_statstg.cbSize.LowPart = cbNewSize; } else if( cbNewSize > m_statstg.cbSize.LowPart ) { // grow existing memory
if( NULL == (pvMem = realloc(m_pvData,cbNewSize)) ) return STG_E_MEDIUMFULL; m_pvData = pvMem; m_statstg.cbSize.LowPart = cbNewSize; }
// copy mem
CopyMemory((PBYTE)m_pvData + m_cbSeek,pv,cb);
// adjust seek pointer
m_cbSeek += cb;
// set the number of bytes actually written
m_statstg.cbSize.LowPart = max(m_statstg.cbSize.LowPart,m_cbSeek);
// return bytes written
if( pcbWritten != NULL) *pcbWritten = cb;
// update modify time
GetSystemTime(&st); SystemTimeToFileTime(&st,&m_statstg.mtime);
return NOERROR; }
STDMETHODIMP CStreamMem::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { Tracefn("CStreamMem::Seek"); // can we handle the seek?
if( dlibMove.HighPart != 0 ) return STG_E_WRITEFAULT;
// handle the seek request
switch( dwOrigin) { case STREAM_SEEK_SET: if( dlibMove.LowPart > m_statstg.cbSize.LowPart ) return STG_E_WRITEFAULT; m_cbSeek = dlibMove.LowPart; break; case STREAM_SEEK_CUR: if( dlibMove.LowPart + m_cbSeek > m_statstg.cbSize.LowPart ) return STG_E_WRITEFAULT; m_cbSeek += (int)dlibMove.LowPart; break; case STREAM_SEEK_END: if ((int)dlibMove.LowPart > 0 || (ULONG)(-(int)dlibMove.LowPart) > m_statstg.cbSize.LowPart) { return STG_E_WRITEFAULT; } m_cbSeek = m_statstg.cbSize.LowPart + (int)dlibMove.LowPart; break; }
// return new seek position
if( plibNewPosition ) { plibNewPosition->HighPart = 0; plibNewPosition->LowPart = m_cbSeek; } return NOERROR; }
STDMETHODIMP CStreamMem::SetSize( ULARGE_INTEGER libNewSize) { PVOID pvMem = NULL; Tracefn("CStreamMem::SetSize");
// external data is readonly
if( m_fExternalData ) return STG_E_MEDIUMFULL;
// can we handle the new size?
if( libNewSize.HighPart != 0 ) return STG_E_MEDIUMFULL;
// alloc mem
if( !m_pvData ) pvMem = malloc(libNewSize.LowPart); else pvMem = realloc(m_pvData,libNewSize.LowPart); if( !pvMem ) return STG_E_MEDIUMFULL;
// save mem info
m_pvData = pvMem; m_statstg.cbSize.LowPart = libNewSize.LowPart;
// adjust the number of bytes actually written
m_statstg.cbSize.LowPart = min(m_statstg.cbSize.LowPart,m_statstg.cbSize.LowPart);
return NOERROR; }
STDMETHODIMP CStreamMem::CopyTo( IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) { Tracefn("CStreamMem::CopyTo"); HRESULT hr = NOERROR; ULONG cbBytes = 0; ULONG cbWritten = 0;
if( pstm == NULL ) return STG_E_INVALIDPOINTER;
cbBytes = min(m_statstg.cbSize.LowPart - m_cbSeek,cb.LowPart);
if( pcbRead ) pcbRead->QuadPart = cbBytes;
if( cbBytes == 0 ) return NOERROR;
hr = pstm->Write((PBYTE)m_pvData + m_cbSeek,cbBytes,&cbWritten); if( pcbWritten ) pcbWritten->QuadPart = cbWritten; return hr; }
/* -------------------------------------------------------------------------
CStreamFile ------------------------------------------------------------------------- */ CStreamFile::CStreamFile(HANDLE hFile,BOOL fCloseHandle, BOOL fReadOnly) { Tracefn("CStreamFile::CStreamFile"); _ASSERT(hFile != INVALID_HANDLE_VALUE);
if( hFile == INVALID_HANDLE_VALUE ) return; m_fCloseHandle = fCloseHandle; m_fReadOnly = fReadOnly; m_hFile = hFile; m_statstg.cbSize.LowPart = GetFileSize(m_hFile,NULL); }
CStreamFile::~CStreamFile(void) { Tracefn("CStreamFile::~CStreamFile"); if( m_fCloseHandle && m_hFile != INVALID_HANDLE_VALUE ) CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; }
// IStream
STDMETHODIMP CStreamFile::Read( void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) { SYSTEMTIME st; Tracefn("CStreamFile::Read");
if( m_hFile == INVALID_HANDLE_VALUE ) return STG_E_INVALIDHANDLE;
if( !pcbRead ) return STG_E_INVALIDPOINTER;
*pcbRead = 0;
// anything to do?
if( cb == 0 || m_statstg.cbSize.LowPart == 0 || m_cbSeek == m_statstg.cbSize.LowPart ) return NOERROR;
if( !ReadFile(m_hFile,pv,cb,pcbRead,NULL) ) return HRESULT_FROM_WIN32(GetLastError());
// adjust seek pointer
m_cbSeek += *pcbRead;
// update access time
GetSystemTime(&st); SystemTimeToFileTime(&st,&m_statstg.atime);
return NOERROR; }
STDMETHODIMP CStreamFile::Write( const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { ULONG cbNewSize = 0; ULONG cbWritten = 0; PVOID pvMem = NULL; SYSTEMTIME st;
Tracefn("CStreamFile::Write");
if( m_hFile == INVALID_HANDLE_VALUE ) return STG_E_INVALIDHANDLE;
if (m_fReadOnly) return STG_E_MEDIUMFULL;
if( pcbWritten != NULL ) *pcbWritten = 0;
// anything to do?
if( cb == 0 ) return NOERROR;
if( !WriteFile(m_hFile,pv,cb,&cbWritten,NULL) ) return HRESULT_FROM_WIN32(GetLastError());
m_cbSeek += cbWritten; if( m_cbSeek > m_statstg.cbSize.LowPart ) { m_statstg.cbSize.LowPart = m_cbSeek; if( !SetEndOfFile(m_hFile) ) return HRESULT_FROM_WIN32(GetLastError()); } if( pcbWritten != NULL ) *pcbWritten = cbWritten;
// update modify time
GetSystemTime(&st); SystemTimeToFileTime(&st,&m_statstg.mtime);
return NOERROR; }
STDMETHODIMP CStreamFile::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) { Tracefn("CStreamFile::Seek");
if( m_hFile == INVALID_HANDLE_VALUE ) return STG_E_INVALIDHANDLE;
// handle the seek request
switch( dwOrigin) { case STREAM_SEEK_SET: m_cbSeek = dlibMove.LowPart; break; case STREAM_SEEK_CUR: m_cbSeek += (int)dlibMove.LowPart; break; case STREAM_SEEK_END: m_cbSeek = m_statstg.cbSize.LowPart + (int)dlibMove.LowPart; break; }
// do seek
if( -1L == SetFilePointer(m_hFile,m_cbSeek,NULL,FILE_BEGIN) ) return HRESULT_FROM_WIN32(GetLastError());
// return new seek position
if( plibNewPosition ) { plibNewPosition->HighPart = 0; plibNewPosition->LowPart = m_cbSeek; }
return NOERROR; }
STDMETHODIMP CStreamFile::SetSize( ULARGE_INTEGER libNewSize) { Tracefn("CStreamFile::SetSize"); HRESULT hr = NOERROR;
if( m_hFile == INVALID_HANDLE_VALUE ) return STG_E_INVALIDHANDLE;
// can we handle the new size?
if( libNewSize.HighPart != 0 ) return STG_E_MEDIUMFULL;
// seek to new end of file
if( -1L == SetFilePointer(m_hFile,libNewSize.LowPart,NULL,FILE_BEGIN) ) return HRESULT_FROM_WIN32(GetLastError());
// set end of file
if( !SetEndOfFile(m_hFile) ) { // get the error
hr = HRESULT_FROM_WIN32(GetLastError()); } else { // save new size.
m_statstg.cbSize.LowPart = libNewSize.LowPart; }
// restore seek pointer
if( -1L == SetFilePointer(m_hFile,m_cbSeek,NULL,FILE_BEGIN) ) hr = HRESULT_FROM_WIN32(GetLastError());
return hr; }
STDMETHODIMP CStreamFile::Commit( DWORD grfCommitFlags) { Tracefn("CStreamFile::Commit"); HRESULT hr = S_OK; if( m_hFile == INVALID_HANDLE_VALUE ) return STG_E_INVALIDHANDLE;
if(!FlushFileBuffers(m_hFile)) hr = HRESULT_FROM_WIN32(GetLastError()); return hr; }
|