Microsoft KB Archive/301935

= BUG: MSXML Component Fails When Loading Local Files =

Article ID: 301935

Article Last Modified on 9/10/2004

-

APPLIES TO


 * Microsoft Windows CE Platform Software Development Kit for Handheld PC 2000

-



This article was previously published under Q301935



SYMPTOMS
When you are specifying a path to a local file in a call to IXMLDOMDocument::load, the call returns a success value of FALSE, and the dispatch invoke method returns &quot;0x00000001&quot;.



RESOLUTION
To work around this problem, implement an IStream interface to access local files.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



MORE INFORMATION
The following is a simple example of how to implement an IStream interface to support ftp, http, and local file protocols. Use the static function CMyStream::Create to create the stream.
 * 1) pragma once


 * 1) include 

struct CMyFileStream; struct CMyFtpStream; struct CMyHttpStream;

class CMyStream : public IStream {

LONG   m_lRefCount;

public:

CMyStream {       m_lRefCount = 1; }

~CMyStream {       Close; }

HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void ** ppi ) {       if (riid == IID_IUnknown) *ppi = static_cast(this);

else if (riid == IID_IStream) *ppi = static_cast(this);

else return E_NOINTERFACE;

reinterpret_cast(*ppi)->AddRef;

return S_OK; }

ULONG STDMETHODCALLTYPE AddRef( void ) {       return InterlockedIncrement( &m_lRefCount ); }

ULONG STDMETHODCALLTYPE Release( void ) {       if ( InterlockedDecrement( &m_lRefCount ) == 0 ) {           delete this; return 0; }       return (ULONG)m_lRefCount; }

HRESULT STDMETHODCALLTYPE Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE SetSize( ULARGE_INTEGER libNewSize) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CopyTo( IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE Commit( DWORD grfCommitFlags) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE Revert( void) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE Stat( STATSTG* pstatstg, DWORD grfStatFlag) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE Clone( IStream** ppstm) { return E_NOTIMPL; }

virtual BOOL Open( LPCTSTR lpszName, BOOL fRead = TRUE ) = 0; virtual BOOL Close = 0 { return FALSE; }

static IStream* Create( LPCTSTR lpszName, BOOL fRead = TRUE ); };

struct CMyFtpStream : public CMyStream {   CMyFtpStream {       m_hConnect = 0; m_hSession = 0; m_hFile = 0; }

HRESULT STDMETHODCALLTYPE Read( void* pv, DWORD cb, DWORD* pcbRead ) {          if ( !m_hFile ) return E_FAIL;

DWORD dwActual;

if( !InternetReadFile( m_hFile, pv, cb, pcbRead ? pcbRead : &dwActual ) ) return FALSE;

return S_OK; }   HRESULT STDMETHODCALLTYPE Write( const void* pv, DWORD cb, DWORD* pcbWritten ) {       return E_NOTIMPL; }

BOOL Open( LPCTSTR lpszName, BOOL fRead = TRUE ) {       if ( !fRead ) return E_NOTIMPL;

URL_COMPONENTS uc; TCHAR          achHostName[256]; TCHAR          achUrlPath[256];

m_hSession = InternetOpen( TEXT(&quot;&quot;), INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 ); if ( !m_hSession ) return FALSE;

memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); uc.lpszHostName = achHostName; uc.dwHostNameLength = 256; uc.lpszUrlPath = achUrlPath; uc.dwUrlPathLength = 256;

InternetCrackUrl( lpszName, 0, ICU_ESCAPE, &uc );

m_hConnect = InternetConnect( m_hSession, achHostName, INTERNET_DEFAULT_FTP_PORT, 0, 0, INTERNET_SERVICE_FTP, 0, 0 ); if ( !m_hConnect ) return FALSE;

FtpOpenFile( m_hConnect, achUrlPath, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY|INTERNET_FLAG_NO_CACHE_WRITE, 0 ); if ( !m_hFile ) return FALSE;

return TRUE; }

BOOL Close {       if ( m_hConnect ) InternetCloseHandle( m_hConnect ); if ( m_hSession ) InternetCloseHandle( m_hSession );

return TRUE; }

private:

HINTERNET  m_hFile; HINTERNET  m_hSession; HINTERNET  m_hConnect; };

struct CMyHttpStream : public CMyStream {   CMyHttpStream {       m_hRequest = 0; m_hConnect = 0; m_hSession = 0; }

HRESULT STDMETHODCALLTYPE Read( void* pv, DWORD cb, DWORD* pcbRead ) {          if ( !m_hRequest ) return E_FAIL;

DWORD dwActual;

if( !InternetReadFile( m_hRequest, pv, cb, pcbRead ? pcbRead : &dwActual ) ) return FALSE;

return S_OK; }   HRESULT STDMETHODCALLTYPE Write( const void* pv, DWORD cb, DWORD* pcbWritten ) {       return E_NOTIMPL; }

BOOL Open( LPCTSTR lpszName, BOOL fRead = TRUE ) {       if ( !fRead ) return E_NOTIMPL;

URL_COMPONENTS uc; TCHAR          achHostName[256]; TCHAR          achUrlPath[256];

m_hSession = InternetOpen( TEXT(&quot;&quot;), INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 ); if ( !m_hSession ) return FALSE;

memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); uc.lpszHostName = achHostName; uc.dwHostNameLength = 256; uc.lpszUrlPath = achUrlPath; uc.dwUrlPathLength = 256;

InternetCrackUrl( lpszName, 0, ICU_ESCAPE, &uc );

m_hConnect = InternetConnect( m_hSession, achHostName, INTERNET_DEFAULT_HTTP_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, 0 ); if ( !m_hConnect ) return FALSE;

m_hRequest = HttpOpenRequest( m_hConnect, TEXT(&quot;GET&quot;), achUrlPath, 0, 0, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0 ); if ( !m_hRequest ) return FALSE;

if ( !HttpSendRequest( m_hRequest, 0, 0, 0, 0 ) ) return FALSE;

return TRUE; }

BOOL Close {       if ( m_hRequest ) InternetCloseHandle( m_hRequest ); if ( m_hConnect ) InternetCloseHandle( m_hConnect ); if ( m_hSession ) InternetCloseHandle( m_hSession );

return TRUE; }

private:

HINTERNET  m_hSession; HINTERNET  m_hConnect; HINTERNET  m_hRequest; };

struct CMyFileStream : public CMyStream {

CMyFileStream {       m_file = 0; }

HRESULT STDMETHODCALLTYPE Read( void* pv, DWORD cb, DWORD* pcbRead ) {          if ( !m_fRead || !m_file ) return S_FALSE;

if ( !cb ) return S_OK;

size_t actual = (ULONG)fread( pv, 1, cb, m_file );

if ( pcbRead ) *pcbRead = (DWORD)actual;

return ( actual ? S_OK : S_FALSE ); }   HRESULT STDMETHODCALLTYPE Write( const void* pv, DWORD cb, DWORD* pcbWritten ) {       if ( m_fRead || !m_file ) return S_FALSE;

if ( !cb ) return S_OK;

size_t actual = fwrite( pv, 1, cb, m_file );

if ( pcbWritten ) *pcbWritten = (DWORD)actual;

return ( actual ? S_OK : S_FALSE ); }

BOOL Open( LPCTSTR lpszName, BOOL fRead = TRUE ) {       LPCTSTR lpszNoProtocol = lpszName;

m_fRead = fRead;

if ( !_tcsnicmp( lpszName, TEXT(&quot;FILE://&quot;), 7 ) ) lpszNoProtocol += 7; else if ( !_tcsnicmp( lpszName, TEXT(&quot;FILE:&quot;), 5 ) ) lpszNoProtocol += 5;

return 0 != ( m_file = _tfopen( lpszNoProtocol, fRead ? TEXT(&quot;rb&quot;) : TEXT(&quot;wb&quot;) ) ); }

BOOL Close {       if ( m_file ) return ( 0 == fclose( m_file ) ); else return FALSE; }

private:

FILE*      m_file; BOOL       m_fRead;

};

IStream* CMyStream::Create( LPCTSTR lpszName, BOOL fRead ) {   CMyStream*  pNewStream;

if ( !_tcsnicmp( lpszName, TEXT(&quot;HTTP:&quot;), 5 ) ) pNewStream = new CMyHttpStream; else if ( !_tcsnicmp( lpszName, TEXT(&quot;FTP:&quot;), 4 ) ) pNewStream = new CMyFtpStream; else if ( !_tcsnicmp( lpszName, TEXT(&quot;FILE:&quot;), 5 ) ) pNewStream = new CMyFileStream; else pNewStream = new CMyFileStream;

if ( !pNewStream ) return 0;

if ( pNewStream->Open( lpszName, fRead ) ) return static_cast(pNewStream);

delete pNewStream; return 0; } Here is an example of how the stream class might be used:

if ( IStream* pStream = CMyStream::Create( L&quot;file://\\wehavenobananas.xml&quot; ) ) {       VARIANT_BOOL    vSuccess = VARIANT_FALSE; VARIANT        vSource;

VariantInit( &vSource ); vSource.punkVal = pStream; vSource.vt = VT_UNKNOWN;

pDocument->load( vSource, &vSuccess );

pStream->Release;

fLoaded = ( VARIANT_TRUE == vSuccess ); }

