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