14 processURL(XML_Parser parser
, IMoniker 
*baseMoniker
, const XML_Char 
*url
); 
  16 typedef void (*StopHandler
)(void *, HRESULT
); 
  18 class Callback 
: public IBindStatusCallback 
{ 
  21   STDMETHODIMP 
QueryInterface(REFIID
,void **); 
  22   STDMETHODIMP_(ULONG
) AddRef(); 
  23   STDMETHODIMP_(ULONG
) Release(); 
  24   // IBindStatusCallback methods 
  25   STDMETHODIMP 
OnStartBinding(DWORD
, IBinding 
*); 
  26   STDMETHODIMP 
GetPriority(LONG 
*); 
  27   STDMETHODIMP 
OnLowResource(DWORD
); 
  28   STDMETHODIMP 
OnProgress(ULONG
, ULONG
, ULONG
, LPCWSTR
); 
  29   STDMETHODIMP 
OnStopBinding(HRESULT
, LPCWSTR
); 
  30   STDMETHODIMP 
GetBindInfo(DWORD 
*, BINDINFO 
*); 
  31   STDMETHODIMP 
OnDataAvailable(DWORD
, DWORD
, FORMATETC 
*, STGMEDIUM 
*); 
  32   STDMETHODIMP 
OnObjectAvailable(REFIID
, IUnknown 
*); 
  33   Callback(XML_Parser
, IMoniker 
*, StopHandler
, void *); 
  35   int externalEntityRef(const XML_Char 
*context
, 
  36                         const XML_Char 
*systemId
, const XML_Char 
*publicId
); 
  39   IMoniker 
*baseMoniker_
; 
  43   StopHandler stopHandler_
; 
  64 Callback::QueryInterface(REFIID riid
, void** ppv
) 
  66   if (IsEqualGUID(riid
, IID_IUnknown
)) 
  67     *ppv 
= (IUnknown 
*)this; 
  68   else if (IsEqualGUID(riid
, IID_IBindStatusCallback
)) 
  69     *ppv 
= (IBindStatusCallback 
*)this; 
  72   ((LPUNKNOWN
)*ppv
)->AddRef(); 
  77 Callback::OnStartBinding(DWORD
, IBinding
* pBinding
) 
  85 Callback::GetPriority(LONG 
*) 
  91 Callback::OnLowResource(DWORD
) 
  97 Callback::OnProgress(ULONG
, ULONG
, ULONG
, LPCWSTR
) 
 103 Callback::OnStopBinding(HRESULT hr
, LPCWSTR szError
) 
 106     pBinding_
->Release(); 
 110     baseMoniker_
->Release(); 
 113   stopHandler_(stopArg_
, hr
); 
 118 Callback::GetBindInfo(DWORD
* pgrfBINDF
, BINDINFO
* pbindinfo
) 
 120   *pgrfBINDF 
= BINDF_ASYNCHRONOUS
; 
 125 reportError(XML_Parser parser
) 
 127   int code 
= XML_GetErrorCode(parser
); 
 128   const XML_Char 
*message 
= XML_ErrorString(code
); 
 130     _ftprintf(stderr
, _T("%s:%d:%ld: %s\n"), 
 132              XML_GetErrorLineNumber(parser
), 
 133              XML_GetErrorColumnNumber(parser
), 
 136     _ftprintf(stderr
, _T("%s: (unknown message %d)\n"), 
 137               XML_GetBase(parser
), code
); 
 141 Callback::OnDataAvailable(DWORD grfBSCF
, 
 146   if (grfBSCF 
& BSCF_FIRSTDATANOTIFICATION
) { 
 147     IWinInetHttpInfo 
*hp
; 
 148     HRESULT hr 
= pBinding_
->QueryInterface(IID_IWinInetHttpInfo
, 
 151       char contentType
[1024]; 
 152       DWORD bufSize 
= sizeof(contentType
); 
 155       hr 
= hp
->QueryInfo(HTTP_QUERY_CONTENT_TYPE
, contentType
, 
 158         char charset
[CHARSET_MAX
]; 
 159         getXMLCharset(contentType
, charset
); 
 162           XML_Char wcharset
[CHARSET_MAX
]; 
 163           XML_Char 
*p1 
= wcharset
; 
 164           const char *p2 
= charset
; 
 165           while ((*p1
++ = (unsigned char)*p2
++) != 0) 
 167           XML_SetEncoding(parser_
, wcharset
); 
 169           XML_SetEncoding(parser_
, charset
); 
 178   if (pstgmed
->tymed 
== TYMED_ISTREAM
) { 
 179     while (totalRead_ 
< dwSize
) { 
 180 #define READ_MAX (64*1024) 
 181       DWORD nToRead 
= dwSize 
- totalRead_
; 
 182       if (nToRead 
> READ_MAX
) 
 184       void *buf 
= XML_GetBuffer(parser_
, nToRead
); 
 186         _ftprintf(stderr
, _T("out of memory\n")); 
 190       HRESULT hr 
= pstgmed
->pstm
->Read(buf
, nToRead
, &nRead
); 
 193         if (!XML_ParseBuffer(parser_
, 
 195                              (grfBSCF 
& BSCF_LASTDATANOTIFICATION
) != 0 
 196                              && totalRead_ 
== dwSize
)) { 
 197           reportError(parser_
); 
 207 Callback::OnObjectAvailable(REFIID
, IUnknown 
*) 
 213 Callback::externalEntityRef(const XML_Char 
*context
, 
 214                             const XML_Char 
*systemId
, 
 215                             const XML_Char 
*publicId
) 
 217   XML_Parser entParser 
= XML_ExternalEntityParserCreate(parser_
, context
, 0); 
 218   XML_SetBase(entParser
, systemId
); 
 219   int ret 
= processURL(entParser
, baseMoniker_
, systemId
); 
 220   XML_ParserFree(entParser
); 
 224 Callback::Callback(XML_Parser parser
, IMoniker 
*baseMoniker
, 
 225                    StopHandler stopHandler
, void *stopArg
) 
 227   baseMoniker_(baseMoniker
), 
 231   stopHandler_(stopHandler
), 
 235     baseMoniker_
->AddRef(); 
 238 Callback::~Callback() 
 241     pBinding_
->Release(); 
 243     baseMoniker_
->Release(); 
 247 externalEntityRef(void *arg
, 
 248                   const XML_Char 
*context
, 
 249                   const XML_Char 
*base
, 
 250                   const XML_Char 
*systemId
, 
 251                   const XML_Char 
*publicId
) 
 253   return ((Callback 
*)arg
)->externalEntityRef(context
, systemId
, publicId
); 
 258 openStream(XML_Parser parser
, 
 259            IMoniker 
*baseMoniker
, 
 261            StopHandler stopHandler
, void *stopArg
) 
 263   if (!XML_SetBase(parser
, uri
)) 
 264     return E_OUTOFMEMORY
; 
 268   hr 
= CreateURLMoniker(0, uri
, &m
); 
 270   LPWSTR uriw 
= new wchar_t[strlen(uri
) + 1]; 
 271   for (int i 
= 0;; i
++) { 
 276   hr 
= CreateURLMoniker(baseMoniker
, uriw
, &m
); 
 281   IBindStatusCallback 
*cb 
= new Callback(parser
, m
, stopHandler
, stopArg
); 
 282   XML_SetExternalEntityRefHandler(parser
, externalEntityRef
); 
 283   XML_SetExternalEntityRefHandlerArg(parser
, cb
); 
 286   if (FAILED(hr 
= CreateAsyncBindCtx(0, cb
, 0, &b
))) { 
 293   hr 
= m
->BindToStorage(b
, 0, IID_IStream
, (void **)&pStream
); 
 298   if (hr 
== MK_S_ASYNCHRONOUS
) 
 312 winPerror(const XML_Char 
*url
, HRESULT hr
) 
 315   if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
 
 316                     | FORMAT_MESSAGE_FROM_HMODULE
, 
 317                     GetModuleHandleA("urlmon.dll"), 
 319                     MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), 
 323       || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
 
 324                       | FORMAT_MESSAGE_FROM_SYSTEM
, 
 327                       MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), 
 331     /* The system error messages seem to end with a newline. */ 
 332     _ftprintf(stderr
, _T("%s: %s"), url
, buf
); 
 337     _ftprintf(stderr
, _T("%s: error %x\n"), url
, hr
); 
 341 threadQuit(void *p
, HRESULT hr
) 
 343   QuitInfo 
*qi 
= (QuitInfo 
*)p
; 
 352   return SUCCEEDED(CoInitialize(0)); 
 363 processURL(XML_Parser parser
, IMoniker 
*baseMoniker
, 
 370   XML_SetBase(parser
, url
); 
 371   HRESULT hr 
= openStream(parser
, baseMoniker
, url
, threadQuit
, &qi
); 
 376   else if (FAILED(qi
.hr
)) { 
 377     winPerror(url
, qi
.hr
); 
 381   while (!qi
.stop 
&& GetMessage (&msg
, NULL
, 0, 0)) { 
 382     TranslateMessage (&msg
); 
 383     DispatchMessage (&msg
); 
 390 XML_ProcessURL(XML_Parser parser
, 
 394   return processURL(parser
, 0, url
);