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
);