BUG: MSXML Component Fails When Loading Local Files (301935)
The information in this article applies to:
- Microsoft Windows CE Platform SDK for Pocket PC
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 "0x00000001".
RESOLUTION
To work around this problem, implement an IStream interface to access local files.
STATUSMicrosoft 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.
#pragma once
#include <wininet.h>
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<IUnknown*>(this);
else if (riid == IID_IStream)
*ppi = static_cast<IStream*>(this);
else
return E_NOINTERFACE;
reinterpret_cast<IUnknown*>(*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(""), 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(""), 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("GET"), 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("FILE://"), 7 ) )
lpszNoProtocol += 7;
else if ( !_tcsnicmp( lpszName, TEXT("FILE:"), 5 ) )
lpszNoProtocol += 5;
return 0 != ( m_file = _tfopen( lpszNoProtocol, fRead ? TEXT("rb") : TEXT("wb") ) );
}
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("HTTP:"), 5 ) )
pNewStream = new CMyHttpStream;
else if ( !_tcsnicmp( lpszName, TEXT("FTP:"), 4 ) )
pNewStream = new CMyFtpStream;
else if ( !_tcsnicmp( lpszName, TEXT("FILE:"), 5 ) )
pNewStream = new CMyFileStream;
else
pNewStream = new CMyFileStream;
if ( !pNewStream )
return 0;
if ( pNewStream->Open( lpszName, fRead ) )
return static_cast<IStream*>(pNewStream);
delete pNewStream;
return 0;
}
Here is an example of how the stream class might be used:
if ( IStream* pStream = CMyStream::Create( L"file://\\wehavenobananas.xml" ) )
{
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 );
}
REFERENCES
For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:
301939
How to add MSXML support to a C++ application
Modification Type: | Major | Last Reviewed: | 9/10/2004 |
---|
Keywords: | kbbug kbpending KB301935 |
---|
|