//Change msxml3.dll to msxml2.dll if Msxml2.dll is used.
#import "msxml3.dll"
#include <stdio.h>
class clsIStreamOnMemory : public IStream
{
private:
DWORD m_dwRef;
char * m_pcBuffer;
unsigned m_uBufferSize;
unsigned m_uFilePos;
public:
clsIStreamOnMemory( void * pvBuffer, unsigned uSize )
: m_dwRef(0)
, m_pcBuffer( reinterpret_cast<char *>(pvBuffer) )
, m_uBufferSize(uSize)
, m_uFilePos(0)
{}
DWORD GetRefCount() const
{ return m_dwRef; }
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
// ISequentialStream
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read(
/* [length_is][size_is][out] */ void __RPC_FAR *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG __RPC_FAR *pcbRead);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Write(
/* [size_is][in] */ const void __RPC_FAR *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG __RPC_FAR *pcbWritten)
{ // Not needed.
return E_NOTIMPL;
}
// IStream
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Seek(
/* [in] */ LARGE_INTEGER dlibMove,
/* [in] */ DWORD dwOrigin,
/* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetSize(
/* [in] */ ULARGE_INTEGER libNewSize)
{ // Not needed.
return E_NOTIMPL;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo(
/* [unique][in] */ IStream __RPC_FAR *pstm,
/* [in] */ ULARGE_INTEGER cb,
/* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
/* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ DWORD grfCommitFlags)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Revert( void)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE LockRegion(
/* [in] */ ULARGE_INTEGER libOffset,
/* [in] */ ULARGE_INTEGER cb,
/* [in] */ DWORD dwLockType)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(
/* [in] */ ULARGE_INTEGER libOffset,
/* [in] */ ULARGE_INTEGER cb,
/* [in] */ DWORD dwLockType)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Stat(
/* [out] */ STATSTG __RPC_FAR *pstatstg,
/* [in] */ DWORD grfStatFlag)
{ // Not needed.
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Clone(
/* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm)
{ // Not needed.
return E_NOTIMPL;
}
};
static void TestFailed();
int main(int argc, char* argv[])
{
CoInitialize(NULL);
TestFailed();
CoUninitialize();
return 0;
}
static void TestFailed()
{
try
{
MSXML2::IXMLDOMDocumentPtr spDoc;
//If MSXML2.dll is used, change FreeThreadedDOMDocument30 to FreeThreadedDOMDocument26.
HRESULT hr = spDoc.CreateInstance( __uuidof(MSXML2::FreeThreadedDOMDocument30) );
if (hr != S_OK)
{
printf( "*** ERROR:failed to instantiate DOM document (hr = 0x%8.8x\n)", hr );
return;
}
/* This is the Unicode XML document that you are to load. */
WCHAR szDocument[] = { L"_<root></root>" };
//add the Unicode byte order mark to the beginning of the document.
szDocument[0] = 0xFEFF;
// Create the corrupted document by truncating the document to 3 bytes.
unsigned uBufferSize = 3;
clsIStreamOnMemory isom( szDocument, uBufferSize );
VARIANT_BOOL bLoaded = spDoc->load( &isom );
if (isom.GetRefCount() != 0)
{
printf( "*** ERROR: document is holding onto IStream when it shouldn't.\n" );
}
if (bLoaded)
{
if (uBufferSize < 4)
{
printf( "*** ERROR: Parser loaded a corrupted document.\n" );
}
else
{
printf( "Document loaded OK\n" );
}
}
else
{
printf( "Document failed to load\n" );
}
}
catch (_com_error e)
{
_bstr_t bsDesc = e.Description();
}
getchar();
}
HRESULT STDMETHODCALLTYPE clsIStreamOnMemory::QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
if ( IsEqualIID( riid, __uuidof(IUnknown))
|| IsEqualIID( riid, __uuidof(IStream))
)
{
*ppvObject = reinterpret_cast<void *>(static_cast<IStream *>(this));
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE clsIStreamOnMemory::AddRef( void)
{
m_dwRef ++;
return m_dwRef;
}
ULONG STDMETHODCALLTYPE clsIStreamOnMemory::Release( void)
{
m_dwRef --;
return m_dwRef;
}
// ISequentialStream
HRESULT STDMETHODCALLTYPE clsIStreamOnMemory::Read(
/* [length_is][size_is][out] */ void __RPC_FAR *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG __RPC_FAR *pcbRead)
{
if (m_uFilePos >= m_uBufferSize)
{
// Past end of file.
if (pcbRead != NULL)
{
*pcbRead = 0;
}
return S_OK;
}
if (cb > m_uBufferSize - m_uFilePos)
{
cb = m_uBufferSize - m_uFilePos;
}
const char * pszCur = &m_pcBuffer[m_uFilePos];
memcpy( pv, &m_pcBuffer[m_uFilePos], cb );
m_uFilePos += cb;
if (pcbRead != NULL)
{
*pcbRead = cb;
}
return S_OK;
}