Re: MFC serialization of HICON
Mark here is CStream:
class CStream : public IStream, public CObject
{
DECLARE_SERIAL(CStream)
LPBYTE m_lpData;
DWORD m_cbData;
DWORD m_cbCapacity;
LPBYTE m_lpSeek;
public:
CStream(DWORD cbInitialCapacity=0)
: m_lpData(NULL),
m_cbData(0),
m_cbCapacity(0),
m_lpSeek(NULL)
{
if( cbInitialCapacity == 0 )
return;
m_lpData = new BYTE[cbInitialCapacity];
m_lpSeek = m_lpData;
m_cbCapacity = cbInitialCapacity;
};
~CStream()
{
if( m_lpData != NULL )
delete[] m_lpData;
}
void Serialize(CArchive &ar)
{
if( ar.IsStoring() )
{
ar << m_cbData;
if( m_cbData > 0 )
{
ar.Write(m_lpData,m_cbData);
}
}
else
{
ar >> m_cbData;
m_cbCapacity = m_cbData;
if( m_cbData > 0 )
{
m_lpData = new BYTE[m_cbData];
m_lpSeek = m_lpData;
ar.Read(m_lpData,m_cbData);
}
}
}
//IUnknown
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void
__RPC_FAR *__RPC_FAR *ppvObject)
{
if( riid == __uuidof(IStream) ||
riid == __uuidof(ISequentialStream) )
{
*ppvObject = this;
return S_OK;
}
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
return 1;
}
virtual ULONG STDMETHODCALLTYPE Release(void)
{
return 1;
}
//ISequentialStream
public:
virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead)
{
//Re-adjust for how much data we have.
cb = min(m_cbData-(m_lpSeek-m_lpData),cb);
::memcpy(pv,m_lpSeek,cb);
m_lpSeek += cb;
if( pcbRead != 0 )
*pcbRead = cb;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG
*pcbWritten)
{
//Allocate more space if we need it.
ULONG_PTR ulMaxWrite = m_cbCapacity-(m_lpSeek-m_lpData);
if( cb > ulMaxWrite )
{
ulMaxWrite = (m_lpSeek-m_lpData)+cb;
ULONG_PTR lpDelta = m_lpSeek-m_lpData;
LPBYTE lpData = new BYTE[ulMaxWrite];
::memcpy(lpData,m_lpData,m_cbData);
delete[] m_lpData;
m_lpData = lpData;
m_lpSeek = m_lpData + lpDelta;
}
::memcpy(m_lpSeek,pv,cb);
m_lpSeek += cb;
//What's the biggest location we've written to?
m_cbData = max(m_cbData,(DWORD)(m_lpSeek-m_lpData));
if( pcbWritten != NULL )
*pcbWritten = cb;
return S_OK;
}
//IStream
public:
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD
dwOrigin, ULARGE_INTEGER* /*plibNewPosition*/)
{
//Need seek implemented!
switch(dwOrigin)
{
case STREAM_SEEK_SET:
m_lpSeek = m_lpData + dlibMove.QuadPart;
break;
case STREAM_SEEK_CUR:
m_lpSeek += dlibMove.QuadPart;
break;
case STREAM_SEEK_END:
m_lpSeek = m_lpData + m_cbData - dlibMove.QuadPart;
break;
default:
ASSERT(FALSE);
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER /*libNewSize*/)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE CopyTo( IStream* /*pstm*/,
ULARGE_INTEGER /*cb*/, ULARGE_INTEGER* /*pcbRead*/, ULARGE_INTEGER*
/*pcbWritten*/ )
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD /*grfCommitFlags*/)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Revert(void)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER
/*libOffset*/,ULARGE_INTEGER /*cb*/,DWORD /*dwLockType*/)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER
/*libOffset*/,ULARGE_INTEGER /*cb*/,DWORD /*dwLockType*/)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Stat(
/* [out] */ STATSTG* pstatstg,
/* [in] */ DWORD /*grfStatFlag*/ )
{
pstatstg->type = STGTY_LOCKBYTES;
pstatstg->cbSize.QuadPart = m_cbData;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Clone(
/* [out] */ IStream** /*ppstm*/)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
};
Pawel Kozielski