xref: /minix3/external/mit/expat/dist/xmlwf/xmlwin32url.cxx (revision 1230fdc108a70388f87f1b3abdb6731e789a6d94)
1*1230fdc1SLionel Sambuc #include "expat.h"
2*1230fdc1SLionel Sambuc #ifdef XML_UNICODE
3*1230fdc1SLionel Sambuc #define UNICODE
4*1230fdc1SLionel Sambuc #endif
5*1230fdc1SLionel Sambuc #include <windows.h>
6*1230fdc1SLionel Sambuc #include <urlmon.h>
7*1230fdc1SLionel Sambuc #include <wininet.h>
8*1230fdc1SLionel Sambuc #include <stdio.h>
9*1230fdc1SLionel Sambuc #include <tchar.h>
10*1230fdc1SLionel Sambuc #include "xmlurl.h"
11*1230fdc1SLionel Sambuc #include "xmlmime.h"
12*1230fdc1SLionel Sambuc 
13*1230fdc1SLionel Sambuc static int
14*1230fdc1SLionel Sambuc processURL(XML_Parser parser, IMoniker *baseMoniker, const XML_Char *url);
15*1230fdc1SLionel Sambuc 
16*1230fdc1SLionel Sambuc typedef void (*StopHandler)(void *, HRESULT);
17*1230fdc1SLionel Sambuc 
18*1230fdc1SLionel Sambuc class Callback : public IBindStatusCallback {
19*1230fdc1SLionel Sambuc public:
20*1230fdc1SLionel Sambuc   // IUnknown methods
21*1230fdc1SLionel Sambuc   STDMETHODIMP QueryInterface(REFIID,void **);
22*1230fdc1SLionel Sambuc   STDMETHODIMP_(ULONG) AddRef();
23*1230fdc1SLionel Sambuc   STDMETHODIMP_(ULONG) Release();
24*1230fdc1SLionel Sambuc   // IBindStatusCallback methods
25*1230fdc1SLionel Sambuc   STDMETHODIMP OnStartBinding(DWORD, IBinding *);
26*1230fdc1SLionel Sambuc   STDMETHODIMP GetPriority(LONG *);
27*1230fdc1SLionel Sambuc   STDMETHODIMP OnLowResource(DWORD);
28*1230fdc1SLionel Sambuc   STDMETHODIMP OnProgress(ULONG, ULONG, ULONG, LPCWSTR);
29*1230fdc1SLionel Sambuc   STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR);
30*1230fdc1SLionel Sambuc   STDMETHODIMP GetBindInfo(DWORD *, BINDINFO *);
31*1230fdc1SLionel Sambuc   STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *);
32*1230fdc1SLionel Sambuc   STDMETHODIMP OnObjectAvailable(REFIID, IUnknown *);
33*1230fdc1SLionel Sambuc   Callback(XML_Parser, IMoniker *, StopHandler, void *);
34*1230fdc1SLionel Sambuc   ~Callback();
35*1230fdc1SLionel Sambuc   int externalEntityRef(const XML_Char *context,
36*1230fdc1SLionel Sambuc                         const XML_Char *systemId, const XML_Char *publicId);
37*1230fdc1SLionel Sambuc private:
38*1230fdc1SLionel Sambuc   XML_Parser parser_;
39*1230fdc1SLionel Sambuc   IMoniker *baseMoniker_;
40*1230fdc1SLionel Sambuc   DWORD totalRead_;
41*1230fdc1SLionel Sambuc   ULONG ref_;
42*1230fdc1SLionel Sambuc   IBinding *pBinding_;
43*1230fdc1SLionel Sambuc   StopHandler stopHandler_;
44*1230fdc1SLionel Sambuc   void *stopArg_;
45*1230fdc1SLionel Sambuc };
46*1230fdc1SLionel Sambuc 
STDMETHODIMP_(ULONG)47*1230fdc1SLionel Sambuc STDMETHODIMP_(ULONG)
48*1230fdc1SLionel Sambuc Callback::AddRef()
49*1230fdc1SLionel Sambuc {
50*1230fdc1SLionel Sambuc   return ref_++;
51*1230fdc1SLionel Sambuc }
52*1230fdc1SLionel Sambuc 
STDMETHODIMP_(ULONG)53*1230fdc1SLionel Sambuc STDMETHODIMP_(ULONG)
54*1230fdc1SLionel Sambuc Callback::Release()
55*1230fdc1SLionel Sambuc {
56*1230fdc1SLionel Sambuc   if (--ref_ == 0) {
57*1230fdc1SLionel Sambuc     delete this;
58*1230fdc1SLionel Sambuc     return 0;
59*1230fdc1SLionel Sambuc   }
60*1230fdc1SLionel Sambuc   return ref_;
61*1230fdc1SLionel Sambuc }
62*1230fdc1SLionel Sambuc 
63*1230fdc1SLionel Sambuc STDMETHODIMP
QueryInterface(REFIID riid,void ** ppv)64*1230fdc1SLionel Sambuc Callback::QueryInterface(REFIID riid, void** ppv)
65*1230fdc1SLionel Sambuc {
66*1230fdc1SLionel Sambuc   if (IsEqualGUID(riid, IID_IUnknown))
67*1230fdc1SLionel Sambuc     *ppv = (IUnknown *)this;
68*1230fdc1SLionel Sambuc   else if (IsEqualGUID(riid, IID_IBindStatusCallback))
69*1230fdc1SLionel Sambuc     *ppv = (IBindStatusCallback *)this;
70*1230fdc1SLionel Sambuc   else
71*1230fdc1SLionel Sambuc     return E_NOINTERFACE;
72*1230fdc1SLionel Sambuc   ((LPUNKNOWN)*ppv)->AddRef();
73*1230fdc1SLionel Sambuc   return S_OK;
74*1230fdc1SLionel Sambuc }
75*1230fdc1SLionel Sambuc 
76*1230fdc1SLionel Sambuc STDMETHODIMP
OnStartBinding(DWORD,IBinding * pBinding)77*1230fdc1SLionel Sambuc Callback::OnStartBinding(DWORD, IBinding* pBinding)
78*1230fdc1SLionel Sambuc {
79*1230fdc1SLionel Sambuc   pBinding_ = pBinding;
80*1230fdc1SLionel Sambuc   pBinding->AddRef();
81*1230fdc1SLionel Sambuc   return S_OK;
82*1230fdc1SLionel Sambuc }
83*1230fdc1SLionel Sambuc 
84*1230fdc1SLionel Sambuc STDMETHODIMP
GetPriority(LONG *)85*1230fdc1SLionel Sambuc Callback::GetPriority(LONG *)
86*1230fdc1SLionel Sambuc {
87*1230fdc1SLionel Sambuc   return E_NOTIMPL;
88*1230fdc1SLionel Sambuc }
89*1230fdc1SLionel Sambuc 
90*1230fdc1SLionel Sambuc STDMETHODIMP
OnLowResource(DWORD)91*1230fdc1SLionel Sambuc Callback::OnLowResource(DWORD)
92*1230fdc1SLionel Sambuc {
93*1230fdc1SLionel Sambuc   return E_NOTIMPL;
94*1230fdc1SLionel Sambuc }
95*1230fdc1SLionel Sambuc 
96*1230fdc1SLionel Sambuc STDMETHODIMP
OnProgress(ULONG,ULONG,ULONG,LPCWSTR)97*1230fdc1SLionel Sambuc Callback::OnProgress(ULONG, ULONG, ULONG, LPCWSTR)
98*1230fdc1SLionel Sambuc {
99*1230fdc1SLionel Sambuc   return S_OK;
100*1230fdc1SLionel Sambuc }
101*1230fdc1SLionel Sambuc 
102*1230fdc1SLionel Sambuc STDMETHODIMP
OnStopBinding(HRESULT hr,LPCWSTR szError)103*1230fdc1SLionel Sambuc Callback::OnStopBinding(HRESULT hr, LPCWSTR szError)
104*1230fdc1SLionel Sambuc {
105*1230fdc1SLionel Sambuc   if (pBinding_) {
106*1230fdc1SLionel Sambuc     pBinding_->Release();
107*1230fdc1SLionel Sambuc     pBinding_ = 0;
108*1230fdc1SLionel Sambuc   }
109*1230fdc1SLionel Sambuc   if (baseMoniker_) {
110*1230fdc1SLionel Sambuc     baseMoniker_->Release();
111*1230fdc1SLionel Sambuc     baseMoniker_ = 0;
112*1230fdc1SLionel Sambuc   }
113*1230fdc1SLionel Sambuc   stopHandler_(stopArg_, hr);
114*1230fdc1SLionel Sambuc   return S_OK;
115*1230fdc1SLionel Sambuc }
116*1230fdc1SLionel Sambuc 
117*1230fdc1SLionel Sambuc STDMETHODIMP
GetBindInfo(DWORD * pgrfBINDF,BINDINFO * pbindinfo)118*1230fdc1SLionel Sambuc Callback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo)
119*1230fdc1SLionel Sambuc {
120*1230fdc1SLionel Sambuc   *pgrfBINDF = BINDF_ASYNCHRONOUS;
121*1230fdc1SLionel Sambuc   return S_OK;
122*1230fdc1SLionel Sambuc }
123*1230fdc1SLionel Sambuc 
124*1230fdc1SLionel Sambuc static void
reportError(XML_Parser parser)125*1230fdc1SLionel Sambuc reportError(XML_Parser parser)
126*1230fdc1SLionel Sambuc {
127*1230fdc1SLionel Sambuc   int code = XML_GetErrorCode(parser);
128*1230fdc1SLionel Sambuc   const XML_Char *message = XML_ErrorString(code);
129*1230fdc1SLionel Sambuc   if (message)
130*1230fdc1SLionel Sambuc     _ftprintf(stderr, _T("%s:%d:%ld: %s\n"),
131*1230fdc1SLionel Sambuc 	     XML_GetBase(parser),
132*1230fdc1SLionel Sambuc 	     XML_GetErrorLineNumber(parser),
133*1230fdc1SLionel Sambuc 	     XML_GetErrorColumnNumber(parser),
134*1230fdc1SLionel Sambuc 	     message);
135*1230fdc1SLionel Sambuc   else
136*1230fdc1SLionel Sambuc     _ftprintf(stderr, _T("%s: (unknown message %d)\n"),
137*1230fdc1SLionel Sambuc               XML_GetBase(parser), code);
138*1230fdc1SLionel Sambuc }
139*1230fdc1SLionel Sambuc 
140*1230fdc1SLionel Sambuc STDMETHODIMP
OnDataAvailable(DWORD grfBSCF,DWORD dwSize,FORMATETC * pfmtetc,STGMEDIUM * pstgmed)141*1230fdc1SLionel Sambuc Callback::OnDataAvailable(DWORD grfBSCF,
142*1230fdc1SLionel Sambuc                           DWORD dwSize,
143*1230fdc1SLionel Sambuc                           FORMATETC *pfmtetc,
144*1230fdc1SLionel Sambuc                           STGMEDIUM* pstgmed)
145*1230fdc1SLionel Sambuc {
146*1230fdc1SLionel Sambuc   if (grfBSCF & BSCF_FIRSTDATANOTIFICATION) {
147*1230fdc1SLionel Sambuc     IWinInetHttpInfo *hp;
148*1230fdc1SLionel Sambuc     HRESULT hr = pBinding_->QueryInterface(IID_IWinInetHttpInfo,
149*1230fdc1SLionel Sambuc                                            (void **)&hp);
150*1230fdc1SLionel Sambuc     if (SUCCEEDED(hr)) {
151*1230fdc1SLionel Sambuc       char contentType[1024];
152*1230fdc1SLionel Sambuc       DWORD bufSize = sizeof(contentType);
153*1230fdc1SLionel Sambuc       DWORD flags = 0;
154*1230fdc1SLionel Sambuc       contentType[0] = 0;
155*1230fdc1SLionel Sambuc       hr = hp->QueryInfo(HTTP_QUERY_CONTENT_TYPE, contentType,
156*1230fdc1SLionel Sambuc                          &bufSize, 0, NULL);
157*1230fdc1SLionel Sambuc       if (SUCCEEDED(hr)) {
158*1230fdc1SLionel Sambuc 	char charset[CHARSET_MAX];
159*1230fdc1SLionel Sambuc 	getXMLCharset(contentType, charset);
160*1230fdc1SLionel Sambuc 	if (charset[0]) {
161*1230fdc1SLionel Sambuc #ifdef XML_UNICODE
162*1230fdc1SLionel Sambuc 	  XML_Char wcharset[CHARSET_MAX];
163*1230fdc1SLionel Sambuc 	  XML_Char *p1 = wcharset;
164*1230fdc1SLionel Sambuc 	  const char *p2 = charset;
165*1230fdc1SLionel Sambuc 	  while ((*p1++ = (unsigned char)*p2++) != 0)
166*1230fdc1SLionel Sambuc 	    ;
167*1230fdc1SLionel Sambuc 	  XML_SetEncoding(parser_, wcharset);
168*1230fdc1SLionel Sambuc #else
169*1230fdc1SLionel Sambuc 	  XML_SetEncoding(parser_, charset);
170*1230fdc1SLionel Sambuc #endif
171*1230fdc1SLionel Sambuc 	}
172*1230fdc1SLionel Sambuc       }
173*1230fdc1SLionel Sambuc       hp->Release();
174*1230fdc1SLionel Sambuc     }
175*1230fdc1SLionel Sambuc   }
176*1230fdc1SLionel Sambuc   if (!parser_)
177*1230fdc1SLionel Sambuc     return E_ABORT;
178*1230fdc1SLionel Sambuc   if (pstgmed->tymed == TYMED_ISTREAM) {
179*1230fdc1SLionel Sambuc     while (totalRead_ < dwSize) {
180*1230fdc1SLionel Sambuc #define READ_MAX (64*1024)
181*1230fdc1SLionel Sambuc       DWORD nToRead = dwSize - totalRead_;
182*1230fdc1SLionel Sambuc       if (nToRead > READ_MAX)
183*1230fdc1SLionel Sambuc 	nToRead = READ_MAX;
184*1230fdc1SLionel Sambuc       void *buf = XML_GetBuffer(parser_, nToRead);
185*1230fdc1SLionel Sambuc       if (!buf) {
186*1230fdc1SLionel Sambuc 	_ftprintf(stderr, _T("out of memory\n"));
187*1230fdc1SLionel Sambuc 	return E_ABORT;
188*1230fdc1SLionel Sambuc       }
189*1230fdc1SLionel Sambuc       DWORD nRead;
190*1230fdc1SLionel Sambuc       HRESULT hr = pstgmed->pstm->Read(buf, nToRead, &nRead);
191*1230fdc1SLionel Sambuc       if (SUCCEEDED(hr)) {
192*1230fdc1SLionel Sambuc 	totalRead_ += nRead;
193*1230fdc1SLionel Sambuc 	if (!XML_ParseBuffer(parser_,
194*1230fdc1SLionel Sambuc 			     nRead,
195*1230fdc1SLionel Sambuc 			     (grfBSCF & BSCF_LASTDATANOTIFICATION) != 0
196*1230fdc1SLionel Sambuc 			     && totalRead_ == dwSize)) {
197*1230fdc1SLionel Sambuc 	  reportError(parser_);
198*1230fdc1SLionel Sambuc 	  return E_ABORT;
199*1230fdc1SLionel Sambuc 	}
200*1230fdc1SLionel Sambuc       }
201*1230fdc1SLionel Sambuc     }
202*1230fdc1SLionel Sambuc   }
203*1230fdc1SLionel Sambuc   return S_OK;
204*1230fdc1SLionel Sambuc }
205*1230fdc1SLionel Sambuc 
206*1230fdc1SLionel Sambuc STDMETHODIMP
OnObjectAvailable(REFIID,IUnknown *)207*1230fdc1SLionel Sambuc Callback::OnObjectAvailable(REFIID, IUnknown *)
208*1230fdc1SLionel Sambuc {
209*1230fdc1SLionel Sambuc   return S_OK;
210*1230fdc1SLionel Sambuc }
211*1230fdc1SLionel Sambuc 
212*1230fdc1SLionel Sambuc int
externalEntityRef(const XML_Char * context,const XML_Char * systemId,const XML_Char * publicId)213*1230fdc1SLionel Sambuc Callback::externalEntityRef(const XML_Char *context,
214*1230fdc1SLionel Sambuc                             const XML_Char *systemId,
215*1230fdc1SLionel Sambuc                             const XML_Char *publicId)
216*1230fdc1SLionel Sambuc {
217*1230fdc1SLionel Sambuc   XML_Parser entParser = XML_ExternalEntityParserCreate(parser_, context, 0);
218*1230fdc1SLionel Sambuc   XML_SetBase(entParser, systemId);
219*1230fdc1SLionel Sambuc   int ret = processURL(entParser, baseMoniker_, systemId);
220*1230fdc1SLionel Sambuc   XML_ParserFree(entParser);
221*1230fdc1SLionel Sambuc   return ret;
222*1230fdc1SLionel Sambuc }
223*1230fdc1SLionel Sambuc 
Callback(XML_Parser parser,IMoniker * baseMoniker,StopHandler stopHandler,void * stopArg)224*1230fdc1SLionel Sambuc Callback::Callback(XML_Parser parser, IMoniker *baseMoniker,
225*1230fdc1SLionel Sambuc                    StopHandler stopHandler, void *stopArg)
226*1230fdc1SLionel Sambuc : parser_(parser),
227*1230fdc1SLionel Sambuc   baseMoniker_(baseMoniker),
228*1230fdc1SLionel Sambuc   ref_(0),
229*1230fdc1SLionel Sambuc   pBinding_(0),
230*1230fdc1SLionel Sambuc   totalRead_(0),
231*1230fdc1SLionel Sambuc   stopHandler_(stopHandler),
232*1230fdc1SLionel Sambuc   stopArg_(stopArg)
233*1230fdc1SLionel Sambuc {
234*1230fdc1SLionel Sambuc   if (baseMoniker_)
235*1230fdc1SLionel Sambuc     baseMoniker_->AddRef();
236*1230fdc1SLionel Sambuc }
237*1230fdc1SLionel Sambuc 
~Callback()238*1230fdc1SLionel Sambuc Callback::~Callback()
239*1230fdc1SLionel Sambuc {
240*1230fdc1SLionel Sambuc   if (pBinding_)
241*1230fdc1SLionel Sambuc     pBinding_->Release();
242*1230fdc1SLionel Sambuc   if (baseMoniker_)
243*1230fdc1SLionel Sambuc     baseMoniker_->Release();
244*1230fdc1SLionel Sambuc }
245*1230fdc1SLionel Sambuc 
246*1230fdc1SLionel Sambuc static int
externalEntityRef(void * arg,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)247*1230fdc1SLionel Sambuc externalEntityRef(void *arg,
248*1230fdc1SLionel Sambuc                   const XML_Char *context,
249*1230fdc1SLionel Sambuc                   const XML_Char *base,
250*1230fdc1SLionel Sambuc                   const XML_Char *systemId,
251*1230fdc1SLionel Sambuc                   const XML_Char *publicId)
252*1230fdc1SLionel Sambuc {
253*1230fdc1SLionel Sambuc   return ((Callback *)arg)->externalEntityRef(context, systemId, publicId);
254*1230fdc1SLionel Sambuc }
255*1230fdc1SLionel Sambuc 
256*1230fdc1SLionel Sambuc 
257*1230fdc1SLionel Sambuc static HRESULT
openStream(XML_Parser parser,IMoniker * baseMoniker,const XML_Char * uri,StopHandler stopHandler,void * stopArg)258*1230fdc1SLionel Sambuc openStream(XML_Parser parser,
259*1230fdc1SLionel Sambuc            IMoniker *baseMoniker,
260*1230fdc1SLionel Sambuc            const XML_Char *uri,
261*1230fdc1SLionel Sambuc            StopHandler stopHandler, void *stopArg)
262*1230fdc1SLionel Sambuc {
263*1230fdc1SLionel Sambuc   if (!XML_SetBase(parser, uri))
264*1230fdc1SLionel Sambuc     return E_OUTOFMEMORY;
265*1230fdc1SLionel Sambuc   HRESULT hr;
266*1230fdc1SLionel Sambuc   IMoniker *m;
267*1230fdc1SLionel Sambuc #ifdef XML_UNICODE
268*1230fdc1SLionel Sambuc   hr = CreateURLMoniker(0, uri, &m);
269*1230fdc1SLionel Sambuc #else
270*1230fdc1SLionel Sambuc   LPWSTR uriw = new wchar_t[strlen(uri) + 1];
271*1230fdc1SLionel Sambuc   for (int i = 0;; i++) {
272*1230fdc1SLionel Sambuc     uriw[i] = uri[i];
273*1230fdc1SLionel Sambuc     if (uriw[i] == 0)
274*1230fdc1SLionel Sambuc       break;
275*1230fdc1SLionel Sambuc   }
276*1230fdc1SLionel Sambuc   hr = CreateURLMoniker(baseMoniker, uriw, &m);
277*1230fdc1SLionel Sambuc   delete [] uriw;
278*1230fdc1SLionel Sambuc #endif
279*1230fdc1SLionel Sambuc   if (FAILED(hr))
280*1230fdc1SLionel Sambuc     return hr;
281*1230fdc1SLionel Sambuc   IBindStatusCallback *cb = new Callback(parser, m, stopHandler, stopArg);
282*1230fdc1SLionel Sambuc   XML_SetExternalEntityRefHandler(parser, externalEntityRef);
283*1230fdc1SLionel Sambuc   XML_SetExternalEntityRefHandlerArg(parser, cb);
284*1230fdc1SLionel Sambuc   cb->AddRef();
285*1230fdc1SLionel Sambuc   IBindCtx *b;
286*1230fdc1SLionel Sambuc   if (FAILED(hr = CreateAsyncBindCtx(0, cb, 0, &b))) {
287*1230fdc1SLionel Sambuc     cb->Release();
288*1230fdc1SLionel Sambuc     m->Release();
289*1230fdc1SLionel Sambuc     return hr;
290*1230fdc1SLionel Sambuc   }
291*1230fdc1SLionel Sambuc   cb->Release();
292*1230fdc1SLionel Sambuc   IStream *pStream;
293*1230fdc1SLionel Sambuc   hr = m->BindToStorage(b, 0, IID_IStream, (void **)&pStream);
294*1230fdc1SLionel Sambuc   if (SUCCEEDED(hr)) {
295*1230fdc1SLionel Sambuc     if (pStream)
296*1230fdc1SLionel Sambuc       pStream->Release();
297*1230fdc1SLionel Sambuc   }
298*1230fdc1SLionel Sambuc   if (hr == MK_S_ASYNCHRONOUS)
299*1230fdc1SLionel Sambuc     hr = S_OK;
300*1230fdc1SLionel Sambuc   m->Release();
301*1230fdc1SLionel Sambuc   b->Release();
302*1230fdc1SLionel Sambuc   return hr;
303*1230fdc1SLionel Sambuc }
304*1230fdc1SLionel Sambuc 
305*1230fdc1SLionel Sambuc struct QuitInfo {
306*1230fdc1SLionel Sambuc   const XML_Char *url;
307*1230fdc1SLionel Sambuc   HRESULT hr;
308*1230fdc1SLionel Sambuc   int stop;
309*1230fdc1SLionel Sambuc };
310*1230fdc1SLionel Sambuc 
311*1230fdc1SLionel Sambuc static void
winPerror(const XML_Char * url,HRESULT hr)312*1230fdc1SLionel Sambuc winPerror(const XML_Char *url, HRESULT hr)
313*1230fdc1SLionel Sambuc {
314*1230fdc1SLionel Sambuc   LPVOID buf;
315*1230fdc1SLionel Sambuc   if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
316*1230fdc1SLionel Sambuc 		    | FORMAT_MESSAGE_FROM_HMODULE,
317*1230fdc1SLionel Sambuc 		    GetModuleHandleA("urlmon.dll"),
318*1230fdc1SLionel Sambuc 		    hr,
319*1230fdc1SLionel Sambuc 		    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
320*1230fdc1SLionel Sambuc 		    (LPTSTR) &buf,
321*1230fdc1SLionel Sambuc 		    0,
322*1230fdc1SLionel Sambuc 		    NULL)
323*1230fdc1SLionel Sambuc       || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
324*1230fdc1SLionel Sambuc 		      | FORMAT_MESSAGE_FROM_SYSTEM,
325*1230fdc1SLionel Sambuc 		      0,
326*1230fdc1SLionel Sambuc 		      hr,
327*1230fdc1SLionel Sambuc 		      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
328*1230fdc1SLionel Sambuc 		      (LPTSTR) &buf,
329*1230fdc1SLionel Sambuc 		      0,
330*1230fdc1SLionel Sambuc 		      NULL)) {
331*1230fdc1SLionel Sambuc     /* The system error messages seem to end with a newline. */
332*1230fdc1SLionel Sambuc     _ftprintf(stderr, _T("%s: %s"), url, buf);
333*1230fdc1SLionel Sambuc     fflush(stderr);
334*1230fdc1SLionel Sambuc     LocalFree(buf);
335*1230fdc1SLionel Sambuc   }
336*1230fdc1SLionel Sambuc   else
337*1230fdc1SLionel Sambuc     _ftprintf(stderr, _T("%s: error %x\n"), url, hr);
338*1230fdc1SLionel Sambuc }
339*1230fdc1SLionel Sambuc 
340*1230fdc1SLionel Sambuc static void
threadQuit(void * p,HRESULT hr)341*1230fdc1SLionel Sambuc threadQuit(void *p, HRESULT hr)
342*1230fdc1SLionel Sambuc {
343*1230fdc1SLionel Sambuc   QuitInfo *qi = (QuitInfo *)p;
344*1230fdc1SLionel Sambuc   qi->hr = hr;
345*1230fdc1SLionel Sambuc   qi->stop = 1;
346*1230fdc1SLionel Sambuc }
347*1230fdc1SLionel Sambuc 
348*1230fdc1SLionel Sambuc extern "C"
349*1230fdc1SLionel Sambuc int
XML_URLInit(void)350*1230fdc1SLionel Sambuc XML_URLInit(void)
351*1230fdc1SLionel Sambuc {
352*1230fdc1SLionel Sambuc   return SUCCEEDED(CoInitialize(0));
353*1230fdc1SLionel Sambuc }
354*1230fdc1SLionel Sambuc 
355*1230fdc1SLionel Sambuc extern "C"
356*1230fdc1SLionel Sambuc void
XML_URLUninit(void)357*1230fdc1SLionel Sambuc XML_URLUninit(void)
358*1230fdc1SLionel Sambuc {
359*1230fdc1SLionel Sambuc   CoUninitialize();
360*1230fdc1SLionel Sambuc }
361*1230fdc1SLionel Sambuc 
362*1230fdc1SLionel Sambuc static int
processURL(XML_Parser parser,IMoniker * baseMoniker,const XML_Char * url)363*1230fdc1SLionel Sambuc processURL(XML_Parser parser, IMoniker *baseMoniker,
364*1230fdc1SLionel Sambuc            const XML_Char *url)
365*1230fdc1SLionel Sambuc {
366*1230fdc1SLionel Sambuc   QuitInfo qi;
367*1230fdc1SLionel Sambuc   qi.stop = 0;
368*1230fdc1SLionel Sambuc   qi.url = url;
369*1230fdc1SLionel Sambuc 
370*1230fdc1SLionel Sambuc   XML_SetBase(parser, url);
371*1230fdc1SLionel Sambuc   HRESULT hr = openStream(parser, baseMoniker, url, threadQuit, &qi);
372*1230fdc1SLionel Sambuc   if (FAILED(hr)) {
373*1230fdc1SLionel Sambuc     winPerror(url, hr);
374*1230fdc1SLionel Sambuc     return 0;
375*1230fdc1SLionel Sambuc   }
376*1230fdc1SLionel Sambuc   else if (FAILED(qi.hr)) {
377*1230fdc1SLionel Sambuc     winPerror(url, qi.hr);
378*1230fdc1SLionel Sambuc     return 0;
379*1230fdc1SLionel Sambuc   }
380*1230fdc1SLionel Sambuc   MSG msg;
381*1230fdc1SLionel Sambuc   while (!qi.stop && GetMessage (&msg, NULL, 0, 0)) {
382*1230fdc1SLionel Sambuc     TranslateMessage (&msg);
383*1230fdc1SLionel Sambuc     DispatchMessage (&msg);
384*1230fdc1SLionel Sambuc   }
385*1230fdc1SLionel Sambuc   return 1;
386*1230fdc1SLionel Sambuc }
387*1230fdc1SLionel Sambuc 
388*1230fdc1SLionel Sambuc extern "C"
389*1230fdc1SLionel Sambuc int
XML_ProcessURL(XML_Parser parser,const XML_Char * url,unsigned flags)390*1230fdc1SLionel Sambuc XML_ProcessURL(XML_Parser parser,
391*1230fdc1SLionel Sambuc                const XML_Char *url,
392*1230fdc1SLionel Sambuc                unsigned flags)
393*1230fdc1SLionel Sambuc {
394*1230fdc1SLionel Sambuc   return processURL(parser, 0, url);
395*1230fdc1SLionel Sambuc }
396