wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[wine] / dlls / msxml3 / saxreader.c
1 /*
2  *    SAX Reader implementation
3  *
4  * Copyright 2008 Alistair Leslie-Hughes
5  * Copyright 2008 Piotr Caban
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml2.h"
33 #include "wininet.h"
34 #include "urlmon.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
37
38 #include "wine/debug.h"
39
40 #include "msxml_private.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43
44 #ifdef HAVE_LIBXML2
45
46 #include <libxml/SAX2.h>
47 #include <libxml/parserInternals.h>
48
49 typedef struct _saxreader
50 {
51     const struct IVBSAXXMLReaderVtbl *lpVBSAXXMLReaderVtbl;
52     const struct ISAXXMLReaderVtbl *lpSAXXMLReaderVtbl;
53     LONG ref;
54     struct ISAXContentHandler *contentHandler;
55     struct IVBSAXContentHandler *vbcontentHandler;
56     struct ISAXErrorHandler *errorHandler;
57     struct IVBSAXErrorHandler *vberrorHandler;
58     xmlSAXHandler sax;
59 } saxreader;
60
61 typedef struct _saxlocator
62 {
63     const struct IVBSAXLocatorVtbl *lpVBSAXLocatorVtbl;
64     const struct ISAXLocatorVtbl *lpSAXLocatorVtbl;
65     LONG ref;
66     saxreader *saxreader;
67     HRESULT ret;
68     xmlParserCtxtPtr pParserCtxt;
69     WCHAR *publicId;
70     WCHAR *systemId;
71     xmlChar *lastCur;
72     int line;
73     int column;
74     BOOL vbInterface;
75     int nsStackSize;
76     int nsStackLast;
77     int *nsStack;
78 } saxlocator;
79
80 typedef struct _saxattributes
81 {
82     const struct IVBSAXAttributesVtbl *lpVBSAXAttributesVtbl;
83     const struct ISAXAttributesVtbl *lpSAXAttributesVtbl;
84     LONG ref;
85     int nb_attributes;
86     BSTR *szLocalname;
87     BSTR *szURI;
88     BSTR *szValue;
89     BSTR *szQName;
90 } saxattributes;
91
92 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
93 {
94     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVBSAXXMLReaderVtbl));
95 }
96
97 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
98 {
99     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpSAXXMLReaderVtbl));
100 }
101
102 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
103 {
104     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpVBSAXLocatorVtbl));
105 }
106
107 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
108 {
109     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpSAXLocatorVtbl));
110 }
111
112 static inline saxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
113 {
114     return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpVBSAXAttributesVtbl));
115 }
116
117 static inline saxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
118 {
119     return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpSAXAttributesVtbl));
120 }
121
122
123 static HRESULT namespacePush(saxlocator *locator, int ns)
124 {
125     if(locator->nsStackLast>=locator->nsStackSize)
126     {
127         int *new_stack;
128
129         new_stack = HeapReAlloc(GetProcessHeap(), 0,
130                 locator->nsStack, locator->nsStackSize*2);
131         if(!new_stack) return E_OUTOFMEMORY;
132         locator->nsStack = new_stack;
133         locator->nsStackSize *= 2;
134     }
135     locator->nsStack[locator->nsStackLast++] = ns;
136
137     return S_OK;
138 }
139
140 static int namespacePop(saxlocator *locator)
141 {
142     if(locator->nsStackLast == 0) return 0;
143     return locator->nsStack[--locator->nsStackLast];
144 }
145
146 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
147 {
148     DWORD dLen;
149     LPWSTR str;
150     BSTR bstr;
151
152     if (!buf)
153         return NULL;
154
155     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
156     if(len != -1) dLen++;
157     str = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dLen * sizeof (WCHAR));
158     if (!str)
159         return NULL;
160     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, dLen);
161     if(len != -1) str[dLen-1] = '\0';
162     bstr = SysAllocString(str);
163     HeapFree(GetProcessHeap(), 0, str);
164
165     return bstr;
166 }
167
168 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
169 {
170     DWORD dLen, dLast;
171     LPWSTR str;
172     BSTR bstr;
173
174     if(!name) return NULL;
175
176     if(!prefix || *prefix=='\0')
177         return bstr_from_xmlChar(name);
178
179     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, NULL, 0)
180         + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, NULL, 0);
181     str = HeapAlloc(GetProcessHeap(), 0, dLen * sizeof(WCHAR));
182     if(!str)
183         return NULL;
184
185     dLast = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, str, dLen);
186     str[dLast-1] = ':';
187     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, &str[dLast], dLen-dLast);
188     bstr = SysAllocString(str);
189
190     HeapFree(GetProcessHeap(), 0, str);
191
192     return bstr;
193 }
194
195 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
196 {
197     xmlStopParser(This->pParserCtxt);
198     This->ret = hr;
199
200     if((This->vbInterface && This->saxreader->vberrorHandler)
201             || (!This->vbInterface && This->saxreader->errorHandler))
202     {
203         WCHAR msg[1024];
204         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
205                     NULL, hr, 0, msg, sizeof(msg), NULL))
206         {
207             FIXME("MSXML errors not yet supported.\n");
208             msg[0] = '\0';
209         }
210
211         if(This->vbInterface)
212         {
213             BSTR bstrMsg = SysAllocString(msg);
214             IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
215                     (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrMsg, hr);
216         }
217         else
218             ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
219                     (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr);
220     }
221 }
222
223 static void update_position(saxlocator *This, xmlChar *end)
224 {
225     if(This->lastCur == NULL)
226     {
227         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
228         This->line = 1;
229         This->column = 1;
230     }
231     else if(This->lastCur < This->pParserCtxt->input->base)
232     {
233         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
234         This->line = 1;
235         This->column = 1;
236     }
237
238     if(!end) end = (xmlChar*)This->pParserCtxt->input->cur;
239
240     while(This->lastCur < end)
241     {
242         if(*(This->lastCur) == '\n')
243         {
244             This->line++;
245             This->column = 1;
246         }
247         else if(*(This->lastCur) == '\r' && (This->lastCur==This->pParserCtxt->input->end || *(This->lastCur+1)!='\n'))
248         {
249             This->line++;
250             This->column = 1;
251         }
252         else This->column++;
253
254         This->lastCur++;
255     }
256 }
257
258 /*** IVBSAXAttributes interface ***/
259 /*** IUnknown methods ***/
260 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
261         IVBSAXAttributes* iface,
262         REFIID riid,
263         void **ppvObject)
264 {
265     saxattributes *This = impl_from_IVBSAXAttributes(iface);
266
267     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
268
269     *ppvObject = NULL;
270
271     if (IsEqualGUID(riid, &IID_IUnknown) ||
272             IsEqualGUID(riid, &IID_IDispatch) ||
273             IsEqualGUID(riid, &IID_IVBSAXAttributes))
274     {
275         *ppvObject = iface;
276     }
277     else
278     {
279         FIXME("interface %s not implemented\n", debugstr_guid(riid));
280         return E_NOINTERFACE;
281     }
282
283     IVBSAXAttributes_AddRef(iface);
284
285     return S_OK;
286 }
287
288 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
289 {
290     saxattributes *This = impl_from_IVBSAXAttributes(iface);
291     return ISAXAttributes_AddRef((ISAXAttributes*)&This->lpSAXAttributesVtbl);
292 }
293
294 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
295 {
296     saxattributes *This = impl_from_IVBSAXAttributes(iface);
297     return ISAXAttributes_Release((ISAXAttributes*)&This->lpSAXAttributesVtbl);
298 }
299
300 /*** IDispatch methods ***/
301 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
302 {
303     saxattributes *This = impl_from_IVBSAXAttributes( iface );
304
305     TRACE("(%p)->(%p)\n", This, pctinfo);
306
307     *pctinfo = 1;
308
309     return S_OK;
310 }
311
312 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
313     IVBSAXAttributes *iface,
314     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
315 {
316     saxattributes *This = impl_from_IVBSAXAttributes( iface );
317     HRESULT hr;
318
319     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
320
321     hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
322
323     return hr;
324 }
325
326 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
327     IVBSAXAttributes *iface,
328     REFIID riid,
329     LPOLESTR* rgszNames,
330     UINT cNames,
331     LCID lcid,
332     DISPID* rgDispId)
333 {
334     saxattributes *This = impl_from_IVBSAXAttributes( iface );
335     ITypeInfo *typeinfo;
336     HRESULT hr;
337
338     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
339           lcid, rgDispId);
340
341     if(!rgszNames || cNames == 0 || !rgDispId)
342         return E_INVALIDARG;
343
344     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
345     if(SUCCEEDED(hr))
346     {
347         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
348         ITypeInfo_Release(typeinfo);
349     }
350
351     return hr;
352 }
353
354 static HRESULT WINAPI ivbsaxattributes_Invoke(
355     IVBSAXAttributes *iface,
356     DISPID dispIdMember,
357     REFIID riid,
358     LCID lcid,
359     WORD wFlags,
360     DISPPARAMS* pDispParams,
361     VARIANT* pVarResult,
362     EXCEPINFO* pExcepInfo,
363     UINT* puArgErr)
364 {
365     saxattributes *This = impl_from_IVBSAXAttributes( iface );
366     ITypeInfo *typeinfo;
367     HRESULT hr;
368
369     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
370           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
371
372     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
373     if(SUCCEEDED(hr))
374     {
375         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXAttributesVtbl), dispIdMember, wFlags, pDispParams,
376                 pVarResult, pExcepInfo, puArgErr);
377         ITypeInfo_Release(typeinfo);
378     }
379
380     return hr;
381 }
382
383 /*** IVBSAXAttributes methods ***/
384 static HRESULT WINAPI ivbsaxattributes_get_length(
385         IVBSAXAttributes* iface,
386         int *nLength)
387 {
388     saxattributes *This = impl_from_IVBSAXAttributes( iface );
389     return ISAXAttributes_getLength(
390             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
391             nLength);
392 }
393
394 static HRESULT WINAPI ivbsaxattributes_getURI(
395         IVBSAXAttributes* iface,
396         int nIndex,
397         BSTR *uri)
398 {
399     int len;
400     saxattributes *This = impl_from_IVBSAXAttributes( iface );
401     return ISAXAttributes_getURI(
402             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
403             nIndex, (const WCHAR**)uri, &len);
404 }
405
406 static HRESULT WINAPI ivbsaxattributes_getLocalName(
407         IVBSAXAttributes* iface,
408         int nIndex,
409         BSTR *localName)
410 {
411     int len;
412     saxattributes *This = impl_from_IVBSAXAttributes( iface );
413     return ISAXAttributes_getLocalName(
414             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
415             nIndex, (const WCHAR**)localName, &len);
416 }
417
418 static HRESULT WINAPI ivbsaxattributes_getQName(
419         IVBSAXAttributes* iface,
420         int nIndex,
421         BSTR *QName)
422 {
423     int len;
424     saxattributes *This = impl_from_IVBSAXAttributes( iface );
425     return ISAXAttributes_getQName(
426             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
427             nIndex, (const WCHAR**)QName, &len);
428 }
429
430 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
431         IVBSAXAttributes* iface,
432         BSTR uri,
433         BSTR localName,
434         int *index)
435 {
436     saxattributes *This = impl_from_IVBSAXAttributes( iface );
437     return ISAXAttributes_getIndexFromName(
438             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
439             (const WCHAR*)uri, SysStringLen(uri),
440             (const WCHAR*)localName, SysStringLen(localName), index);
441 }
442
443 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
444         IVBSAXAttributes* iface,
445         BSTR QName,
446         int *index)
447 {
448     saxattributes *This = impl_from_IVBSAXAttributes( iface );
449     return ISAXAttributes_getIndexFromQName(
450             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
451             (const WCHAR*)QName, SysStringLen(QName), index);
452 }
453
454 static HRESULT WINAPI ivbsaxattributes_getType(
455         IVBSAXAttributes* iface,
456         int nIndex,
457         BSTR *type)
458 {
459     int len;
460     saxattributes *This = impl_from_IVBSAXAttributes( iface );
461     return ISAXAttributes_getType(
462             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
463             nIndex, (const WCHAR**)type, &len);
464 }
465
466 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
467         IVBSAXAttributes* iface,
468         BSTR uri,
469         BSTR localName,
470         BSTR *type)
471 {
472     int len;
473     saxattributes *This = impl_from_IVBSAXAttributes( iface );
474     return ISAXAttributes_getTypeFromName(
475             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
476             (const WCHAR*)uri, SysStringLen(uri),
477             (const WCHAR*)localName, SysStringLen(localName),
478             (const WCHAR**)type, &len);
479 }
480
481 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
482         IVBSAXAttributes* iface,
483         BSTR QName,
484         BSTR *type)
485 {
486     int len;
487     saxattributes *This = impl_from_IVBSAXAttributes( iface );
488     return ISAXAttributes_getTypeFromQName(
489             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
490             (const WCHAR*)QName, SysStringLen(QName),
491             (const WCHAR**)type, &len);
492 }
493
494 static HRESULT WINAPI ivbsaxattributes_getValue(
495         IVBSAXAttributes* iface,
496         int nIndex,
497         BSTR *value)
498 {
499     int len;
500     saxattributes *This = impl_from_IVBSAXAttributes( iface );
501     return ISAXAttributes_getValue(
502             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
503             nIndex, (const WCHAR**)value, &len);
504 }
505
506 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
507         IVBSAXAttributes* iface,
508         BSTR uri,
509         BSTR localName,
510         BSTR *value)
511 {
512     int len;
513     saxattributes *This = impl_from_IVBSAXAttributes( iface );
514     return ISAXAttributes_getValueFromName(
515             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
516             (const WCHAR*)uri, SysStringLen(uri),
517             (const WCHAR*)localName, SysStringLen(localName),
518             (const WCHAR**)value, &len);
519 }
520
521 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
522         IVBSAXAttributes* iface,
523         BSTR QName,
524         BSTR *value)
525 {
526     int len;
527     saxattributes *This = impl_from_IVBSAXAttributes( iface );
528     return ISAXAttributes_getValueFromQName(
529             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
530             (const WCHAR*)QName, SysStringLen(QName),
531             (const WCHAR**)value, &len);
532 }
533
534 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
535 {
536     ivbsaxattributes_QueryInterface,
537     ivbsaxattributes_AddRef,
538     ivbsaxattributes_Release,
539     ivbsaxattributes_GetTypeInfoCount,
540     ivbsaxattributes_GetTypeInfo,
541     ivbsaxattributes_GetIDsOfNames,
542     ivbsaxattributes_Invoke,
543     ivbsaxattributes_get_length,
544     ivbsaxattributes_getURI,
545     ivbsaxattributes_getLocalName,
546     ivbsaxattributes_getQName,
547     ivbsaxattributes_getIndexFromName,
548     ivbsaxattributes_getIndexFromQName,
549     ivbsaxattributes_getType,
550     ivbsaxattributes_getTypeFromName,
551     ivbsaxattributes_getTypeFromQName,
552     ivbsaxattributes_getValue,
553     ivbsaxattributes_getValueFromName,
554     ivbsaxattributes_getValueFromQName
555 };
556
557 /*** ISAXAttributes interface ***/
558 /*** IUnknown methods ***/
559 static HRESULT WINAPI isaxattributes_QueryInterface(
560         ISAXAttributes* iface,
561         REFIID riid,
562         void **ppvObject)
563 {
564     saxattributes *This = impl_from_ISAXAttributes(iface);
565
566     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
567
568     *ppvObject = NULL;
569
570     if (IsEqualGUID(riid, &IID_IUnknown) ||
571             IsEqualGUID(riid, &IID_ISAXAttributes))
572     {
573         *ppvObject = iface;
574     }
575     else
576     {
577         FIXME("interface %s not implemented\n", debugstr_guid(riid));
578         return E_NOINTERFACE;
579     }
580
581     ISAXAttributes_AddRef(iface);
582
583     return S_OK;
584 }
585
586 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
587 {
588     saxattributes *This = impl_from_ISAXAttributes(iface);
589     TRACE("%p\n", This);
590     return InterlockedIncrement(&This->ref);
591 }
592
593 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
594 {
595     saxattributes *This = impl_from_ISAXAttributes(iface);
596     LONG ref;
597
598     TRACE("%p\n", This);
599
600     ref = InterlockedDecrement(&This->ref);
601     if (ref==0)
602     {
603         int index;
604         for(index=0; index<This->nb_attributes; index++)
605         {
606             SysFreeString(This->szLocalname[index]);
607             SysFreeString(This->szURI[index]);
608             SysFreeString(This->szValue[index]);
609             SysFreeString(This->szQName[index]);
610         }
611
612         HeapFree(GetProcessHeap(), 0, This->szLocalname);
613         HeapFree(GetProcessHeap(), 0, This->szURI);
614         HeapFree(GetProcessHeap(), 0, This->szValue);
615         HeapFree(GetProcessHeap(), 0, This->szQName);
616
617         HeapFree(GetProcessHeap(), 0, This);
618     }
619
620     return ref;
621 }
622
623 /*** ISAXAttributes methods ***/
624 static HRESULT WINAPI isaxattributes_getLength(
625         ISAXAttributes* iface,
626         int *length)
627 {
628     saxattributes *This = impl_from_ISAXAttributes( iface );
629
630     *length = This->nb_attributes;
631     TRACE("Length set to %d\n", *length);
632     return S_OK;
633 }
634
635 static HRESULT WINAPI isaxattributes_getURI(
636         ISAXAttributes* iface,
637         int nIndex,
638         const WCHAR **pUrl,
639         int *pUriSize)
640 {
641     saxattributes *This = impl_from_ISAXAttributes( iface );
642     TRACE("(%p)->(%d)\n", This, nIndex);
643
644     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
645     if(!pUrl || !pUriSize) return E_POINTER;
646
647     *pUriSize = SysStringLen(This->szURI[nIndex]);
648     *pUrl = This->szURI[nIndex];
649
650     return S_OK;
651 }
652
653 static HRESULT WINAPI isaxattributes_getLocalName(
654         ISAXAttributes* iface,
655         int nIndex,
656         const WCHAR **pLocalName,
657         int *pLocalNameLength)
658 {
659     saxattributes *This = impl_from_ISAXAttributes( iface );
660     TRACE("(%p)->(%d)\n", This, nIndex);
661
662     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
663     if(!pLocalName || !pLocalNameLength) return E_POINTER;
664
665     *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]);
666     *pLocalName = This->szLocalname[nIndex];
667
668     return S_OK;
669 }
670
671 static HRESULT WINAPI isaxattributes_getQName(
672         ISAXAttributes* iface,
673         int nIndex,
674         const WCHAR **pQName,
675         int *pQNameLength)
676 {
677     saxattributes *This = impl_from_ISAXAttributes( iface );
678     TRACE("(%p)->(%d)\n", This, nIndex);
679
680     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
681     if(!pQName || !pQNameLength) return E_POINTER;
682
683     *pQNameLength = SysStringLen(This->szQName[nIndex]);
684     *pQName = This->szQName[nIndex];
685
686     return S_OK;
687 }
688
689 static HRESULT WINAPI isaxattributes_getName(
690         ISAXAttributes* iface,
691         int nIndex,
692         const WCHAR **pUri,
693         int *pUriLength,
694         const WCHAR **pLocalName,
695         int *pLocalNameSize,
696         const WCHAR **pQName,
697         int *pQNameLength)
698 {
699     saxattributes *This = impl_from_ISAXAttributes( iface );
700     TRACE("(%p)->(%d)\n", This, nIndex);
701
702     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
703     if(!pUri || !pUriLength || !pLocalName || !pLocalNameSize
704             || !pQName || !pQNameLength) return E_POINTER;
705
706     *pUriLength = SysStringLen(This->szURI[nIndex]);
707     *pUri = This->szURI[nIndex];
708     *pLocalNameSize = SysStringLen(This->szLocalname[nIndex]);
709     *pLocalName = This->szLocalname[nIndex];
710     *pQNameLength = SysStringLen(This->szQName[nIndex]);
711     *pQName = This->szQName[nIndex];
712
713     return S_OK;
714 }
715
716 static HRESULT WINAPI isaxattributes_getIndexFromName(
717         ISAXAttributes* iface,
718         const WCHAR *pUri,
719         int cUriLength,
720         const WCHAR *pLocalName,
721         int cocalNameLength,
722         int *index)
723 {
724     saxattributes *This = impl_from_ISAXAttributes( iface );
725     int i;
726     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
727             debugstr_w(pLocalName), cocalNameLength);
728
729     if(!pUri || !pLocalName || !index) return E_POINTER;
730
731     for(i=0; i<This->nb_attributes; i++)
732     {
733         if(cUriLength!=SysStringLen(This->szURI[i])
734                 || cocalNameLength!=SysStringLen(This->szLocalname[i]))
735             continue;
736         if(cUriLength && memcmp(pUri, This->szURI[i],
737                     sizeof(WCHAR)*cUriLength))
738             continue;
739         if(cocalNameLength && memcmp(pLocalName, This->szLocalname[i],
740                     sizeof(WCHAR)*cocalNameLength))
741             continue;
742
743         *index = i;
744         return S_OK;
745     }
746
747     return E_INVALIDARG;
748 }
749
750 static HRESULT WINAPI isaxattributes_getIndexFromQName(
751         ISAXAttributes* iface,
752         const WCHAR *pQName,
753         int nQNameLength,
754         int *index)
755 {
756     saxattributes *This = impl_from_ISAXAttributes( iface );
757     int i;
758     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
759
760     if(!pQName || !index) return E_POINTER;
761     if(!nQNameLength) return E_INVALIDARG;
762
763     for(i=0; i<This->nb_attributes; i++)
764     {
765         if(nQNameLength!=SysStringLen(This->szQName[i])) continue;
766         if(memcmp(pQName, This->szQName, sizeof(WCHAR)*nQNameLength)) continue;
767
768         *index = i;
769         return S_OK;
770     }
771
772     return E_INVALIDARG;
773 }
774
775 static HRESULT WINAPI isaxattributes_getType(
776         ISAXAttributes* iface,
777         int nIndex,
778         const WCHAR **pType,
779         int *pTypeLength)
780 {
781     saxattributes *This = impl_from_ISAXAttributes( iface );
782
783     FIXME("(%p)->(%d) stub\n", This, nIndex);
784     return E_NOTIMPL;
785 }
786
787 static HRESULT WINAPI isaxattributes_getTypeFromName(
788         ISAXAttributes* iface,
789         const WCHAR *pUri,
790         int nUri,
791         const WCHAR *pLocalName,
792         int nLocalName,
793         const WCHAR **pType,
794         int *nType)
795 {
796     saxattributes *This = impl_from_ISAXAttributes( iface );
797
798     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
799             debugstr_w(pLocalName), nLocalName);
800     return E_NOTIMPL;
801 }
802
803 static HRESULT WINAPI isaxattributes_getTypeFromQName(
804         ISAXAttributes* iface,
805         const WCHAR *pQName,
806         int nQName,
807         const WCHAR **pType,
808         int *nType)
809 {
810     saxattributes *This = impl_from_ISAXAttributes( iface );
811
812     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
813     return E_NOTIMPL;
814 }
815
816 static HRESULT WINAPI isaxattributes_getValue(
817         ISAXAttributes* iface,
818         int nIndex,
819         const WCHAR **pValue,
820         int *nValue)
821 {
822     saxattributes *This = impl_from_ISAXAttributes( iface );
823     TRACE("(%p)->(%d)\n", This, nIndex);
824
825     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
826     if(!pValue || !nValue) return E_POINTER;
827
828     *nValue = SysStringLen(This->szValue[nIndex]);
829     *pValue = This->szValue[nIndex];
830
831     return S_OK;
832 }
833
834 static HRESULT WINAPI isaxattributes_getValueFromName(
835         ISAXAttributes* iface,
836         const WCHAR *pUri,
837         int nUri,
838         const WCHAR *pLocalName,
839         int nLocalName,
840         const WCHAR **pValue,
841         int *nValue)
842 {
843     HRESULT hr;
844     int index;
845     saxattributes *This = impl_from_ISAXAttributes( iface );
846     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
847             debugstr_w(pLocalName), nLocalName);
848
849     hr = ISAXAttributes_getIndexFromName(iface,
850             pUri, nUri, pLocalName, nLocalName, &index);
851     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
852
853     return hr;
854 }
855
856 static HRESULT WINAPI isaxattributes_getValueFromQName(
857         ISAXAttributes* iface,
858         const WCHAR *pQName,
859         int nQName,
860         const WCHAR **pValue,
861         int *nValue)
862 {
863     HRESULT hr;
864     int index;
865     saxattributes *This = impl_from_ISAXAttributes( iface );
866     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
867
868     hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
869     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
870
871     return hr;
872 }
873
874 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
875 {
876     isaxattributes_QueryInterface,
877     isaxattributes_AddRef,
878     isaxattributes_Release,
879     isaxattributes_getLength,
880     isaxattributes_getURI,
881     isaxattributes_getLocalName,
882     isaxattributes_getQName,
883     isaxattributes_getName,
884     isaxattributes_getIndexFromName,
885     isaxattributes_getIndexFromQName,
886     isaxattributes_getType,
887     isaxattributes_getTypeFromName,
888     isaxattributes_getTypeFromQName,
889     isaxattributes_getValue,
890     isaxattributes_getValueFromName,
891     isaxattributes_getValueFromQName
892 };
893
894 static HRESULT SAXAttributes_create(saxattributes **attr,
895         int nb_namespaces, const xmlChar **xmlNamespaces,
896         int nb_attributes, const xmlChar **xmlAttributes)
897 {
898     saxattributes *attributes;
899     int index;
900     static const xmlChar xmlns[] = "xmlns";
901
902     attributes = HeapAlloc(GetProcessHeap(), 0, sizeof(*attributes));
903     if(!attributes)
904         return E_OUTOFMEMORY;
905
906     attributes->lpVBSAXAttributesVtbl = &ivbsaxattributes_vtbl;
907     attributes->lpSAXAttributesVtbl = &isaxattributes_vtbl;
908     attributes->ref = 1;
909
910     attributes->nb_attributes = nb_namespaces+nb_attributes;
911
912     attributes->szLocalname =
913         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
914     attributes->szURI =
915         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
916     attributes->szValue =
917         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
918     attributes->szQName =
919         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
920
921     if(!attributes->szLocalname || !attributes->szURI
922             || !attributes->szValue || !attributes->szQName)
923     {
924         HeapFree(GetProcessHeap(), 0, attributes->szLocalname);
925         HeapFree(GetProcessHeap(), 0, attributes->szURI);
926         HeapFree(GetProcessHeap(), 0, attributes->szValue);
927         HeapFree(GetProcessHeap(), 0, attributes->szQName);
928         HeapFree(GetProcessHeap(), 0, attributes);
929         return E_FAIL;
930     }
931
932     for(index=0; index<nb_namespaces; index++)
933     {
934         attributes->szLocalname[index] = SysAllocStringLen(NULL, 0);
935         attributes->szURI[index] = SysAllocStringLen(NULL, 0);
936         attributes->szValue[index] = bstr_from_xmlChar(xmlNamespaces[2*index+1]);
937         attributes->szQName[index] = QName_from_xmlChar(xmlns, xmlNamespaces[2*index]);
938     }
939
940     for(index=0; index<nb_attributes; index++)
941     {
942         attributes->szLocalname[nb_namespaces+index] =
943             bstr_from_xmlChar(xmlAttributes[index*5]);
944         attributes->szURI[nb_namespaces+index] =
945             bstr_from_xmlChar(xmlAttributes[index*5+2]);
946         attributes->szValue[nb_namespaces+index] =
947             bstr_from_xmlCharN(xmlAttributes[index*5+3],
948                     xmlAttributes[index*5+4]-xmlAttributes[index*5+3]);
949         attributes->szQName[nb_namespaces+index] =
950             QName_from_xmlChar(xmlAttributes[index*5+1], xmlAttributes[index*5]);
951     }
952
953     *attr = attributes;
954
955     TRACE("returning %p\n", *attr);
956
957     return S_OK;
958 }
959
960 /*** LibXML callbacks ***/
961 static void libxmlStartDocument(void *ctx)
962 {
963     saxlocator *This = ctx;
964     HRESULT hr;
965
966     if((This->vbInterface && This->saxreader->vbcontentHandler)
967             || (!This->vbInterface && This->saxreader->contentHandler))
968     {
969         if(This->vbInterface)
970             hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler);
971         else
972             hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
973
974         if(hr != S_OK)
975             format_error_message_from_id(This, hr);
976     }
977
978     update_position(This, NULL);
979 }
980
981 static void libxmlEndDocument(void *ctx)
982 {
983     saxlocator *This = ctx;
984     HRESULT hr;
985
986     This->column = 0;
987     This->line = 0;
988
989     if(This->ret != S_OK) return;
990
991     if((This->vbInterface && This->saxreader->vbcontentHandler)
992             || (!This->vbInterface && This->saxreader->contentHandler))
993     {
994         if(This->vbInterface)
995             hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler);
996         else
997             hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
998
999         if(hr != S_OK)
1000             format_error_message_from_id(This, hr);
1001     }
1002 }
1003
1004 static void libxmlStartElementNS(
1005         void *ctx,
1006         const xmlChar *localname,
1007         const xmlChar *prefix,
1008         const xmlChar *URI,
1009         int nb_namespaces,
1010         const xmlChar **namespaces,
1011         int nb_attributes,
1012         int nb_defaulted,
1013         const xmlChar **attributes)
1014 {
1015     BSTR NamespaceUri, LocalName, QName, Prefix, Uri;
1016     saxlocator *This = ctx;
1017     HRESULT hr;
1018     saxattributes *attr;
1019     int index;
1020
1021     update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1);
1022
1023     hr = namespacePush(This, nb_namespaces);
1024     if(hr==S_OK && ((This->vbInterface && This->saxreader->vbcontentHandler)
1025                 || (!This->vbInterface && This->saxreader->contentHandler)))
1026     {
1027         for(index=0; index<nb_namespaces; index++)
1028         {
1029             Prefix = bstr_from_xmlChar(namespaces[2*index]);
1030             Uri = bstr_from_xmlChar(namespaces[2*index+1]);
1031
1032             if(This->vbInterface)
1033                 hr = IVBSAXContentHandler_startPrefixMapping(
1034                         This->saxreader->vbcontentHandler,
1035                         &Prefix, &Uri);
1036             else
1037                 hr = ISAXContentHandler_startPrefixMapping(
1038                         This->saxreader->contentHandler,
1039                         Prefix, SysStringLen(Prefix),
1040                         Uri, SysStringLen(Uri));
1041
1042             SysFreeString(Prefix);
1043             SysFreeString(Uri);
1044
1045             if(hr != S_OK)
1046             {
1047                 format_error_message_from_id(This, hr);
1048                 return;
1049             }
1050         }
1051
1052         NamespaceUri = bstr_from_xmlChar(URI);
1053         LocalName = bstr_from_xmlChar(localname);
1054         QName = QName_from_xmlChar(prefix, localname);
1055
1056         hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes);
1057         if(hr == S_OK)
1058         {
1059             if(This->vbInterface)
1060                 hr = IVBSAXContentHandler_startElement(
1061                         This->saxreader->vbcontentHandler,
1062                         &NamespaceUri, &LocalName, &QName,
1063                         (IVBSAXAttributes*)&attr->lpVBSAXAttributesVtbl);
1064             else
1065                 hr = ISAXContentHandler_startElement(
1066                         This->saxreader->contentHandler,
1067                         NamespaceUri, SysStringLen(NamespaceUri),
1068                         LocalName, SysStringLen(LocalName),
1069                         QName, SysStringLen(QName),
1070                         (ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1071
1072             ISAXAttributes_Release((ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1073         }
1074
1075         SysFreeString(NamespaceUri);
1076         SysFreeString(LocalName);
1077         SysFreeString(QName);
1078     }
1079
1080     if(hr != S_OK)
1081         format_error_message_from_id(This, hr);
1082 }
1083
1084 static void libxmlEndElementNS(
1085         void *ctx,
1086         const xmlChar *localname,
1087         const xmlChar *prefix,
1088         const xmlChar *URI)
1089 {
1090     BSTR NamespaceUri, LocalName, QName, Prefix;
1091     saxlocator *This = ctx;
1092     HRESULT hr;
1093     xmlChar *end;
1094     int nsNr, index;
1095
1096     end = This->lastCur;
1097     while(*end != '<' && *(end+1) != '/') end++;
1098     update_position(This, end+2);
1099
1100     nsNr = namespacePop(This);
1101
1102     if((This->vbInterface && This->saxreader->vbcontentHandler)
1103             || (!This->vbInterface && This->saxreader->contentHandler))
1104     {
1105         NamespaceUri = bstr_from_xmlChar(URI);
1106         LocalName = bstr_from_xmlChar(localname);
1107         QName = QName_from_xmlChar(prefix, localname);
1108
1109         if(This->vbInterface)
1110             hr = IVBSAXContentHandler_endElement(
1111                     This->saxreader->vbcontentHandler,
1112                     &NamespaceUri, &LocalName, &QName);
1113         else
1114             hr = ISAXContentHandler_endElement(
1115                     This->saxreader->contentHandler,
1116                     NamespaceUri, SysStringLen(NamespaceUri),
1117                     LocalName, SysStringLen(LocalName),
1118                     QName, SysStringLen(QName));
1119
1120         SysFreeString(NamespaceUri);
1121         SysFreeString(LocalName);
1122         SysFreeString(QName);
1123
1124         if(hr != S_OK)
1125         {
1126             format_error_message_from_id(This, hr);
1127             return;
1128         }
1129
1130         for(index=This->pParserCtxt->nsNr-2;
1131                 index>=This->pParserCtxt->nsNr-nsNr*2; index-=2)
1132         {
1133             Prefix = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]);
1134
1135             if(This->vbInterface)
1136                 hr = IVBSAXContentHandler_endPrefixMapping(
1137                         This->saxreader->vbcontentHandler, &Prefix);
1138             else
1139                 hr = ISAXContentHandler_endPrefixMapping(
1140                         This->saxreader->contentHandler,
1141                         Prefix, SysStringLen(Prefix));
1142
1143             SysFreeString(Prefix);
1144         }
1145     }
1146 }
1147
1148 static void libxmlCharacters(
1149         void *ctx,
1150         const xmlChar *ch,
1151         int len)
1152 {
1153     BSTR Chars;
1154     saxlocator *This = ctx;
1155     HRESULT hr;
1156     xmlChar *end;
1157     xmlChar *lastCurCopy;
1158     xmlChar *chEnd;
1159     int columnCopy;
1160     int lineCopy;
1161
1162     if(*(This->lastCur-1) != '>' && *(This->lastCur-1) != '/') return;
1163
1164     if(*(This->lastCur-1) != '>')
1165     {
1166         end = (xmlChar*)This->pParserCtxt->input->cur-len;
1167         while(*(end-1) != '>') end--;
1168         update_position(This, end);
1169     }
1170
1171     chEnd = This->lastCur+len;
1172     while(*chEnd != '<') chEnd++;
1173
1174     Chars = bstr_from_xmlChar(ch);
1175
1176     lastCurCopy = This->lastCur;
1177     columnCopy = This->column;
1178     lineCopy = This->line;
1179     end = This->lastCur;
1180
1181     if((This->vbInterface && This->saxreader->vbcontentHandler)
1182             || (!This->vbInterface && This->saxreader->contentHandler))
1183     {
1184         while(This->lastCur < chEnd)
1185         {
1186             end = This->lastCur;
1187             while(end < chEnd-1)
1188             {
1189                 if(*end == '\r') break;
1190                 end++;
1191             }
1192
1193             Chars = bstr_from_xmlChar(This->lastCur);
1194
1195             if(*end == '\r' && *(end+1) == '\n')
1196             {
1197                 memmove((WCHAR*)Chars+(end-This->lastCur),
1198                         (WCHAR*)Chars+(end-This->lastCur)+1,
1199                         (SysStringLen(Chars)-(end-This->lastCur))*sizeof(WCHAR));
1200                 SysReAllocStringLen(&Chars, Chars, SysStringLen(Chars)-1);
1201             }
1202             else if(*end == '\r') Chars[end-This->lastCur] = '\n';
1203
1204             if(This->vbInterface)
1205                 hr = IVBSAXContentHandler_characters(
1206                         This->saxreader->vbcontentHandler, &Chars);
1207             else
1208                 hr = ISAXContentHandler_characters(
1209                         This->saxreader->contentHandler,
1210                         Chars, end-This->lastCur+1);
1211
1212             SysFreeString(Chars);
1213             if(hr != S_OK)
1214             {
1215                 format_error_message_from_id(This, hr);
1216                 return;
1217             }
1218
1219             if(*(end+1) == '\n') end++;
1220             if(end < chEnd) end++;
1221
1222             This->column += end-This->lastCur;
1223             This->lastCur = end;
1224         }
1225
1226         This->lastCur = lastCurCopy;
1227         This->column = columnCopy;
1228         This->line = lineCopy;
1229         update_position(This, chEnd);
1230     }
1231 }
1232
1233 static void libxmlSetDocumentLocator(
1234         void *ctx,
1235         xmlSAXLocatorPtr loc)
1236 {
1237     saxlocator *This = ctx;
1238     HRESULT hr;
1239
1240     if(This->vbInterface)
1241         hr = IVBSAXContentHandler_putref_documentLocator(
1242                 This->saxreader->vbcontentHandler,
1243                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1244     else
1245         hr = ISAXContentHandler_putDocumentLocator(
1246                 This->saxreader->contentHandler,
1247                 (ISAXLocator*)&This->lpSAXLocatorVtbl);
1248
1249     if(FAILED(hr))
1250         format_error_message_from_id(This, hr);
1251 }
1252
1253 void libxmlFatalError(void *ctx, const char *msg, ...)
1254 {
1255     saxlocator *This = ctx;
1256     char message[1024];
1257     WCHAR *wszError;
1258     DWORD len;
1259     va_list args;
1260
1261     if((This->vbInterface && !This->saxreader->vberrorHandler)
1262             || (!This->vbInterface && !This->saxreader->errorHandler))
1263     {
1264         xmlStopParser(This->pParserCtxt);
1265         This->ret = E_FAIL;
1266         return;
1267     }
1268
1269     FIXME("Error handling is not compatible.\n");
1270
1271     va_start(args, msg);
1272     vsprintf(message, msg, args);
1273     va_end(args);
1274
1275     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1276     wszError = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
1277     if(wszError)
1278         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, (LPWSTR)wszError, len);
1279
1280     if(This->vbInterface)
1281     {
1282         BSTR bstrError = SysAllocString(wszError);
1283         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1284                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1285     }
1286     else
1287         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1288                 (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
1289
1290     HeapFree(GetProcessHeap(), 0, wszError);
1291
1292     xmlStopParser(This->pParserCtxt);
1293     This->ret = E_FAIL;
1294 }
1295
1296 /*** IVBSAXLocator interface ***/
1297 /*** IUnknown methods ***/
1298 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1299 {
1300     saxlocator *This = impl_from_IVBSAXLocator( iface );
1301
1302     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1303
1304     *ppvObject = NULL;
1305
1306     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1307             IsEqualGUID( riid, &IID_IDispatch) ||
1308             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1309     {
1310         *ppvObject = iface;
1311     }
1312     else
1313     {
1314         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1315         return E_NOINTERFACE;
1316     }
1317
1318     IVBSAXLocator_AddRef( iface );
1319
1320     return S_OK;
1321 }
1322
1323 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1324 {
1325     saxlocator *This = impl_from_IVBSAXLocator( iface );
1326     TRACE("%p\n", This );
1327     return InterlockedIncrement( &This->ref );
1328 }
1329
1330 static ULONG WINAPI ivbsaxlocator_Release(
1331         IVBSAXLocator* iface)
1332 {
1333     saxlocator *This = impl_from_IVBSAXLocator( iface );
1334     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1335 }
1336
1337 /*** IDispatch methods ***/
1338 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1339 {
1340     saxlocator *This = impl_from_IVBSAXLocator( iface );
1341
1342     TRACE("(%p)->(%p)\n", This, pctinfo);
1343
1344     *pctinfo = 1;
1345
1346     return S_OK;
1347 }
1348
1349 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1350     IVBSAXLocator *iface,
1351     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1352 {
1353     saxlocator *This = impl_from_IVBSAXLocator( iface );
1354     HRESULT hr;
1355
1356     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1357
1358     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1359
1360     return hr;
1361 }
1362
1363 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1364     IVBSAXLocator *iface,
1365     REFIID riid,
1366     LPOLESTR* rgszNames,
1367     UINT cNames,
1368     LCID lcid,
1369     DISPID* rgDispId)
1370 {
1371     saxlocator *This = impl_from_IVBSAXLocator( iface );
1372     ITypeInfo *typeinfo;
1373     HRESULT hr;
1374
1375     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1376           lcid, rgDispId);
1377
1378     if(!rgszNames || cNames == 0 || !rgDispId)
1379         return E_INVALIDARG;
1380
1381     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1382     if(SUCCEEDED(hr))
1383     {
1384         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1385         ITypeInfo_Release(typeinfo);
1386     }
1387
1388     return hr;
1389 }
1390
1391 static HRESULT WINAPI ivbsaxlocator_Invoke(
1392     IVBSAXLocator *iface,
1393     DISPID dispIdMember,
1394     REFIID riid,
1395     LCID lcid,
1396     WORD wFlags,
1397     DISPPARAMS* pDispParams,
1398     VARIANT* pVarResult,
1399     EXCEPINFO* pExcepInfo,
1400     UINT* puArgErr)
1401 {
1402     saxlocator *This = impl_from_IVBSAXLocator( iface );
1403     ITypeInfo *typeinfo;
1404     HRESULT hr;
1405
1406     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1407           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1408
1409     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1410     if(SUCCEEDED(hr))
1411     {
1412         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1413                 pVarResult, pExcepInfo, puArgErr);
1414         ITypeInfo_Release(typeinfo);
1415     }
1416
1417     return hr;
1418 }
1419
1420 /*** IVBSAXLocator methods ***/
1421 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1422         IVBSAXLocator* iface,
1423         int *pnColumn)
1424 {
1425     saxlocator *This = impl_from_IVBSAXLocator( iface );
1426     return ISAXLocator_getColumnNumber(
1427             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1428             pnColumn);
1429 }
1430
1431 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1432         IVBSAXLocator* iface,
1433         int *pnLine)
1434 {
1435     saxlocator *This = impl_from_IVBSAXLocator( iface );
1436     return ISAXLocator_getLineNumber(
1437             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1438             pnLine);
1439 }
1440
1441 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1442         IVBSAXLocator* iface,
1443         BSTR* publicId)
1444 {
1445     saxlocator *This = impl_from_IVBSAXLocator( iface );
1446     return ISAXLocator_getPublicId(
1447             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1448             (const WCHAR**)publicId);
1449 }
1450
1451 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1452         IVBSAXLocator* iface,
1453         BSTR* systemId)
1454 {
1455     saxlocator *This = impl_from_IVBSAXLocator( iface );
1456     return ISAXLocator_getSystemId(
1457             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1458             (const WCHAR**)systemId);
1459 }
1460
1461 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1462 {
1463     ivbsaxlocator_QueryInterface,
1464     ivbsaxlocator_AddRef,
1465     ivbsaxlocator_Release,
1466     ivbsaxlocator_GetTypeInfoCount,
1467     ivbsaxlocator_GetTypeInfo,
1468     ivbsaxlocator_GetIDsOfNames,
1469     ivbsaxlocator_Invoke,
1470     ivbsaxlocator_get_columnNumber,
1471     ivbsaxlocator_get_lineNumber,
1472     ivbsaxlocator_get_publicId,
1473     ivbsaxlocator_get_systemId
1474 };
1475
1476 /*** ISAXLocator interface ***/
1477 /*** IUnknown methods ***/
1478 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1479 {
1480     saxlocator *This = impl_from_ISAXLocator( iface );
1481
1482     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1483
1484     *ppvObject = NULL;
1485
1486     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1487             IsEqualGUID( riid, &IID_ISAXLocator ))
1488     {
1489         *ppvObject = iface;
1490     }
1491     else
1492     {
1493         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1494         return E_NOINTERFACE;
1495     }
1496
1497     ISAXLocator_AddRef( iface );
1498
1499     return S_OK;
1500 }
1501
1502 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1503 {
1504     saxlocator *This = impl_from_ISAXLocator( iface );
1505     TRACE("%p\n", This );
1506     return InterlockedIncrement( &This->ref );
1507 }
1508
1509 static ULONG WINAPI isaxlocator_Release(
1510         ISAXLocator* iface)
1511 {
1512     saxlocator *This = impl_from_ISAXLocator( iface );
1513     LONG ref;
1514
1515     TRACE("%p\n", This );
1516
1517     ref = InterlockedDecrement( &This->ref );
1518     if ( ref == 0 )
1519     {
1520         SysFreeString(This->publicId);
1521         SysFreeString(This->systemId);
1522         HeapFree(GetProcessHeap(), 0, This->nsStack);
1523
1524         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1525         HeapFree( GetProcessHeap(), 0, This );
1526     }
1527
1528     return ref;
1529 }
1530
1531 /*** ISAXLocator methods ***/
1532 static HRESULT WINAPI isaxlocator_getColumnNumber(
1533         ISAXLocator* iface,
1534         int *pnColumn)
1535 {
1536     saxlocator *This = impl_from_ISAXLocator( iface );
1537
1538     *pnColumn = This->column;
1539     return S_OK;
1540 }
1541
1542 static HRESULT WINAPI isaxlocator_getLineNumber(
1543         ISAXLocator* iface,
1544         int *pnLine)
1545 {
1546     saxlocator *This = impl_from_ISAXLocator( iface );
1547
1548     *pnLine = This->line;
1549     return S_OK;
1550 }
1551
1552 static HRESULT WINAPI isaxlocator_getPublicId(
1553         ISAXLocator* iface,
1554         const WCHAR ** ppwchPublicId)
1555 {
1556     BSTR publicId;
1557     saxlocator *This = impl_from_ISAXLocator( iface );
1558
1559     SysFreeString(This->publicId);
1560
1561     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1562     if(SysStringLen(publicId))
1563         This->publicId = (WCHAR*)&publicId;
1564     else
1565     {
1566         SysFreeString(publicId);
1567         This->publicId = NULL;
1568     }
1569
1570     *ppwchPublicId = This->publicId;
1571     return S_OK;
1572 }
1573
1574 static HRESULT WINAPI isaxlocator_getSystemId(
1575         ISAXLocator* iface,
1576         const WCHAR ** ppwchSystemId)
1577 {
1578     BSTR systemId;
1579     saxlocator *This = impl_from_ISAXLocator( iface );
1580
1581     SysFreeString(This->systemId);
1582
1583     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1584     if(SysStringLen(systemId))
1585         This->systemId = (WCHAR*)&systemId;
1586     else
1587     {
1588         SysFreeString(systemId);
1589         This->systemId = NULL;
1590     }
1591
1592     *ppwchSystemId = This->systemId;
1593     return S_OK;
1594 }
1595
1596 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1597 {
1598     isaxlocator_QueryInterface,
1599     isaxlocator_AddRef,
1600     isaxlocator_Release,
1601     isaxlocator_getColumnNumber,
1602     isaxlocator_getLineNumber,
1603     isaxlocator_getPublicId,
1604     isaxlocator_getSystemId
1605 };
1606
1607 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1608 {
1609     saxlocator *locator;
1610
1611     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
1612     if( !locator )
1613         return E_OUTOFMEMORY;
1614
1615     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1616     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1617     locator->ref = 1;
1618     locator->vbInterface = vbInterface;
1619
1620     locator->saxreader = reader;
1621     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1622
1623     locator->pParserCtxt = NULL;
1624     locator->publicId = NULL;
1625     locator->systemId = NULL;
1626     locator->lastCur = NULL;
1627     locator->line = 0;
1628     locator->column = 0;
1629     locator->ret = S_OK;
1630     locator->nsStackSize = 8;
1631     locator->nsStackLast = 0;
1632     locator->nsStack = HeapAlloc(GetProcessHeap(), 0, locator->nsStackSize);
1633     if(!locator->nsStack)
1634     {
1635         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1636         HeapFree(GetProcessHeap(), 0, locator);
1637         return E_OUTOFMEMORY;
1638     }
1639
1640     *ppsaxlocator = locator;
1641
1642     TRACE("returning %p\n", *ppsaxlocator);
1643
1644     return S_OK;
1645 }
1646
1647 /*** SAXXMLReader internal functions ***/
1648 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1649 {
1650     saxlocator *locator;
1651     HRESULT hr;
1652
1653     hr = SAXLocator_create(This, &locator, vbInterface);
1654     if(FAILED(hr))
1655         return E_FAIL;
1656
1657     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1658     if(!locator->pParserCtxt)
1659     {
1660         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1661         return E_FAIL;
1662     }
1663
1664     locator->pParserCtxt->sax = &locator->saxreader->sax;
1665     locator->pParserCtxt->userData = locator;
1666
1667     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1668     else hr = locator->ret;
1669
1670     if(locator->pParserCtxt)
1671     {
1672         locator->pParserCtxt->sax = NULL;
1673         xmlFreeParserCtxt(locator->pParserCtxt);
1674         locator->pParserCtxt = NULL;
1675     }
1676
1677     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1678     return S_OK;
1679 }
1680
1681 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1682 {
1683     saxlocator *locator;
1684     HRESULT hr;
1685     ULONG dataRead;
1686     char data[1024];
1687
1688     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1689     if(hr != S_OK)
1690         return hr;
1691
1692     hr = SAXLocator_create(This, &locator, vbInterface);
1693     if(FAILED(hr))
1694         return E_FAIL;
1695
1696     locator->pParserCtxt = xmlCreatePushParserCtxt(
1697             &locator->saxreader->sax, locator,
1698             data, dataRead, NULL);
1699     if(!locator->pParserCtxt)
1700     {
1701         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1702         return E_FAIL;
1703     }
1704
1705     while(1)
1706     {
1707         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1708         if(hr != S_OK)
1709             break;
1710
1711         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1712         else hr = locator->ret;
1713
1714         if(hr != S_OK) break;
1715
1716         if(dataRead != sizeof(data))
1717         {
1718             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1719             else hr = locator->ret;
1720
1721             break;
1722         }
1723     }
1724
1725     locator->pParserCtxt->sax = NULL;
1726     xmlFreeParserCtxt(locator->pParserCtxt);
1727     locator->pParserCtxt = NULL;
1728     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1729     return hr;
1730 }
1731
1732 static HRESULT WINAPI internal_getEntityResolver(
1733         saxreader *This,
1734         void *pEntityResolver,
1735         BOOL vbInterface)
1736 {
1737     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1738     return E_NOTIMPL;
1739 }
1740
1741 static HRESULT WINAPI internal_putEntityResolver(
1742         saxreader *This,
1743         void *pEntityResolver,
1744         BOOL vbInterface)
1745 {
1746     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1747     return E_NOTIMPL;
1748 }
1749
1750 static HRESULT WINAPI internal_getContentHandler(
1751         saxreader* This,
1752         void *pContentHandler,
1753         BOOL vbInterface)
1754 {
1755     TRACE("(%p)->(%p)\n", This, pContentHandler);
1756     if(pContentHandler == NULL)
1757         return E_POINTER;
1758     if((vbInterface && This->vbcontentHandler)
1759             || (!vbInterface && This->contentHandler))
1760     {
1761         if(vbInterface)
1762             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1763         else
1764             ISAXContentHandler_AddRef(This->contentHandler);
1765     }
1766     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1767         This->vbcontentHandler;
1768     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1769
1770     return S_OK;
1771 }
1772
1773 static HRESULT WINAPI internal_putContentHandler(
1774         saxreader* This,
1775         void *contentHandler,
1776         BOOL vbInterface)
1777 {
1778     TRACE("(%p)->(%p)\n", This, contentHandler);
1779     if(contentHandler)
1780     {
1781         if(vbInterface)
1782             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1783         else
1784             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1785     }
1786     if((vbInterface && This->vbcontentHandler)
1787             || (!vbInterface && This->contentHandler))
1788     {
1789         if(vbInterface)
1790             IVBSAXContentHandler_Release(This->vbcontentHandler);
1791         else
1792             ISAXContentHandler_Release(This->contentHandler);
1793     }
1794     if(vbInterface)
1795         This->vbcontentHandler = contentHandler;
1796     else
1797         This->contentHandler = contentHandler;
1798
1799     return S_OK;
1800 }
1801
1802 static HRESULT WINAPI internal_getDTDHandler(
1803         saxreader* This,
1804         void *pDTDHandler,
1805         BOOL vbInterface)
1806 {
1807     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1808     return E_NOTIMPL;
1809 }
1810
1811 static HRESULT WINAPI internal_putDTDHandler(
1812         saxreader* This,
1813         void *pDTDHandler,
1814         BOOL vbInterface)
1815 {
1816     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1817     return E_NOTIMPL;
1818 }
1819
1820 static HRESULT WINAPI internal_getErrorHandler(
1821         saxreader* This,
1822         void *pErrorHandler,
1823         BOOL vbInterface)
1824 {
1825     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1826     if(pErrorHandler == NULL)
1827         return E_POINTER;
1828
1829     if(vbInterface && This->vberrorHandler)
1830         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1831     else if(!vbInterface && This->errorHandler)
1832         ISAXErrorHandler_AddRef(This->errorHandler);
1833
1834     if(vbInterface)
1835         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1836     else
1837         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1838
1839     return S_OK;
1840
1841 }
1842
1843 static HRESULT WINAPI internal_putErrorHandler(
1844         saxreader* This,
1845         void *errorHandler,
1846         BOOL vbInterface)
1847 {
1848     TRACE("(%p)->(%p)\n", This, errorHandler);
1849     if(errorHandler)
1850     {
1851         if(vbInterface)
1852             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1853         else
1854             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1855     }
1856
1857     if(vbInterface && This->vberrorHandler)
1858         IVBSAXErrorHandler_Release(This->vberrorHandler);
1859     else if(!vbInterface && This->errorHandler)
1860         ISAXErrorHandler_Release(This->errorHandler);
1861
1862     if(vbInterface)
1863         This->vberrorHandler = errorHandler;
1864     else
1865         This->errorHandler = errorHandler;
1866
1867     return S_OK;
1868
1869 }
1870
1871 static HRESULT WINAPI internal_parse(
1872         saxreader* This,
1873         VARIANT varInput,
1874         BOOL vbInterface)
1875 {
1876     HRESULT hr;
1877
1878     TRACE("(%p)\n", This);
1879
1880     hr = S_OK;
1881     switch(V_VT(&varInput))
1882     {
1883         case VT_BSTR:
1884             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
1885                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
1886             break;
1887         case VT_ARRAY|VT_UI1: {
1888             void *pSAData;
1889             LONG lBound, uBound;
1890             ULONG dataRead;
1891
1892             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
1893             if(hr != S_OK) break;
1894             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
1895             if(hr != S_OK) break;
1896             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
1897             hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData);
1898             if(hr != S_OK) break;
1899             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
1900             SafeArrayUnaccessData(V_ARRAY(&varInput));
1901             break;
1902         }
1903         case VT_UNKNOWN:
1904         case VT_DISPATCH: {
1905             IPersistStream *persistStream;
1906             IStream *stream = NULL;
1907             IXMLDOMDocument *xmlDoc;
1908
1909             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1910                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
1911             {
1912                 BSTR bstrData;
1913
1914                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
1915                 hr = internal_parseBuffer(This, (const char*)bstrData,
1916                         SysStringByteLen(bstrData), vbInterface);
1917                 IXMLDOMDocument_Release(xmlDoc);
1918                 break;
1919             }
1920             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1921                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
1922             {
1923                 hr = IPersistStream_Save(persistStream, stream, TRUE);
1924                 IPersistStream_Release(persistStream);
1925                 if(hr != S_OK) break;
1926             }
1927             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1928                         &IID_IStream, (void**)&stream) == S_OK)
1929             {
1930                 hr = internal_parseStream(This, stream, vbInterface);
1931                 IStream_Release(stream);
1932                 break;
1933             }
1934         }
1935         default:
1936             WARN("vt %d not implemented\n", V_VT(&varInput));
1937             hr = E_INVALIDARG;
1938     }
1939
1940     return hr;
1941 }
1942
1943 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
1944 {
1945     saxreader *This = obj;
1946
1947     return internal_parseBuffer(This, ptr, len, TRUE);
1948 }
1949
1950 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
1951 {
1952     saxreader *This = obj;
1953
1954     return internal_parseBuffer(This, ptr, len, FALSE);
1955 }
1956
1957 static HRESULT WINAPI internal_parseURL(
1958         saxreader* This,
1959         const WCHAR *url,
1960         BOOL vbInterface)
1961 {
1962     bsc_t *bsc;
1963     HRESULT hr;
1964
1965     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
1966
1967     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
1968     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
1969
1970     if(FAILED(hr))
1971         return hr;
1972
1973     detach_bsc(bsc);
1974
1975     return S_OK;
1976 }
1977
1978 /*** IVBSAXXMLReader interface ***/
1979 /*** IUnknown methods ***/
1980 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
1981 {
1982     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1983
1984     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1985
1986     *ppvObject = NULL;
1987
1988     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1989          IsEqualGUID( riid, &IID_IDispatch ) ||
1990          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
1991     {
1992         *ppvObject = iface;
1993     }
1994     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
1995     {
1996         *ppvObject = (ISAXXMLReader*)&This->lpSAXXMLReaderVtbl;
1997     }
1998     else
1999     {
2000         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2001         return E_NOINTERFACE;
2002     }
2003
2004     IVBSAXXMLReader_AddRef( iface );
2005
2006     return S_OK;
2007 }
2008
2009 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2010 {
2011     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2012     TRACE("%p\n", This );
2013     return InterlockedIncrement( &This->ref );
2014 }
2015
2016 static ULONG WINAPI saxxmlreader_Release(
2017     IVBSAXXMLReader* iface)
2018 {
2019     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2020     LONG ref;
2021
2022     TRACE("%p\n", This );
2023
2024     ref = InterlockedDecrement( &This->ref );
2025     if ( ref == 0 )
2026     {
2027         if(This->contentHandler)
2028             ISAXContentHandler_Release(This->contentHandler);
2029
2030         if(This->vbcontentHandler)
2031             IVBSAXContentHandler_Release(This->vbcontentHandler);
2032
2033         if(This->errorHandler)
2034             ISAXErrorHandler_Release(This->errorHandler);
2035
2036         if(This->vberrorHandler)
2037             IVBSAXErrorHandler_Release(This->vberrorHandler);
2038
2039         HeapFree( GetProcessHeap(), 0, This );
2040     }
2041
2042     return ref;
2043 }
2044 /*** IDispatch ***/
2045 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2046 {
2047     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2048
2049     TRACE("(%p)->(%p)\n", This, pctinfo);
2050
2051     *pctinfo = 1;
2052
2053     return S_OK;
2054 }
2055
2056 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2057     IVBSAXXMLReader *iface,
2058     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2059 {
2060     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2061     HRESULT hr;
2062
2063     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2064
2065     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2066
2067     return hr;
2068 }
2069
2070 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2071     IVBSAXXMLReader *iface,
2072     REFIID riid,
2073     LPOLESTR* rgszNames,
2074     UINT cNames,
2075     LCID lcid,
2076     DISPID* rgDispId)
2077 {
2078     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2079     ITypeInfo *typeinfo;
2080     HRESULT hr;
2081
2082     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2083           lcid, rgDispId);
2084
2085     if(!rgszNames || cNames == 0 || !rgDispId)
2086         return E_INVALIDARG;
2087
2088     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2089     if(SUCCEEDED(hr))
2090     {
2091         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2092         ITypeInfo_Release(typeinfo);
2093     }
2094
2095     return hr;
2096 }
2097
2098 static HRESULT WINAPI saxxmlreader_Invoke(
2099     IVBSAXXMLReader *iface,
2100     DISPID dispIdMember,
2101     REFIID riid,
2102     LCID lcid,
2103     WORD wFlags,
2104     DISPPARAMS* pDispParams,
2105     VARIANT* pVarResult,
2106     EXCEPINFO* pExcepInfo,
2107     UINT* puArgErr)
2108 {
2109     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2110     ITypeInfo *typeinfo;
2111     HRESULT hr;
2112
2113     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2114           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2115
2116     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2117     if(SUCCEEDED(hr))
2118     {
2119         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2120                 pVarResult, pExcepInfo, puArgErr);
2121         ITypeInfo_Release(typeinfo);
2122     }
2123
2124     return hr;
2125 }
2126
2127 /*** IVBSAXXMLReader methods ***/
2128 static HRESULT WINAPI saxxmlreader_getFeature(
2129     IVBSAXXMLReader* iface,
2130     const WCHAR *pFeature,
2131     VARIANT_BOOL *pValue)
2132 {
2133     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2134
2135     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2136     return E_NOTIMPL;
2137 }
2138
2139 static HRESULT WINAPI saxxmlreader_putFeature(
2140     IVBSAXXMLReader* iface,
2141     const WCHAR *pFeature,
2142     VARIANT_BOOL vfValue)
2143 {
2144     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2145
2146     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2147     return E_NOTIMPL;
2148 }
2149
2150 static HRESULT WINAPI saxxmlreader_getProperty(
2151     IVBSAXXMLReader* iface,
2152     const WCHAR *pProp,
2153     VARIANT *pValue)
2154 {
2155     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2156
2157     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2158     return E_NOTIMPL;
2159 }
2160
2161 static HRESULT WINAPI saxxmlreader_putProperty(
2162     IVBSAXXMLReader* iface,
2163     const WCHAR *pProp,
2164     VARIANT value)
2165 {
2166     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2167
2168     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
2169     return E_NOTIMPL;
2170 }
2171
2172 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2173     IVBSAXXMLReader* iface,
2174     IVBSAXEntityResolver **pEntityResolver)
2175 {
2176     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2177     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2178 }
2179
2180 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2181     IVBSAXXMLReader* iface,
2182     IVBSAXEntityResolver *pEntityResolver)
2183 {
2184     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2185     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2186 }
2187
2188 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2189     IVBSAXXMLReader* iface,
2190     IVBSAXContentHandler **ppContentHandler)
2191 {
2192     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2193     return internal_getContentHandler(This, ppContentHandler, TRUE);
2194 }
2195
2196 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2197     IVBSAXXMLReader* iface,
2198     IVBSAXContentHandler *contentHandler)
2199 {
2200     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2201     return internal_putContentHandler(This, contentHandler, TRUE);
2202 }
2203
2204 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2205     IVBSAXXMLReader* iface,
2206     IVBSAXDTDHandler **pDTDHandler)
2207 {
2208     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2209     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2210 }
2211
2212 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2213     IVBSAXXMLReader* iface,
2214     IVBSAXDTDHandler *pDTDHandler)
2215 {
2216     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2217     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2218 }
2219
2220 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2221     IVBSAXXMLReader* iface,
2222     IVBSAXErrorHandler **pErrorHandler)
2223 {
2224     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2225     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2226 }
2227
2228 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2229     IVBSAXXMLReader* iface,
2230     IVBSAXErrorHandler *errorHandler)
2231 {
2232     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2233     return internal_putErrorHandler(This, errorHandler, TRUE);
2234 }
2235
2236 static HRESULT WINAPI saxxmlreader_get_baseURL(
2237     IVBSAXXMLReader* iface,
2238     const WCHAR **pBaseUrl)
2239 {
2240     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2241
2242     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2243     return E_NOTIMPL;
2244 }
2245
2246 static HRESULT WINAPI saxxmlreader_put_baseURL(
2247     IVBSAXXMLReader* iface,
2248     const WCHAR *pBaseUrl)
2249 {
2250     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2251
2252     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2253     return E_NOTIMPL;
2254 }
2255
2256 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2257     IVBSAXXMLReader* iface,
2258     const WCHAR **pSecureBaseUrl)
2259 {
2260     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2261
2262     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2263     return E_NOTIMPL;
2264 }
2265
2266
2267 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2268     IVBSAXXMLReader* iface,
2269     const WCHAR *secureBaseUrl)
2270 {
2271     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2272
2273     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2274     return E_NOTIMPL;
2275 }
2276
2277 static HRESULT WINAPI saxxmlreader_parse(
2278     IVBSAXXMLReader* iface,
2279     VARIANT varInput)
2280 {
2281     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2282     return internal_parse(This, varInput, TRUE);
2283 }
2284
2285 static HRESULT WINAPI saxxmlreader_parseURL(
2286     IVBSAXXMLReader* iface,
2287     const WCHAR *url)
2288 {
2289     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2290     return internal_parseURL(This, url, TRUE);
2291 }
2292
2293 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2294 {
2295     saxxmlreader_QueryInterface,
2296     saxxmlreader_AddRef,
2297     saxxmlreader_Release,
2298     saxxmlreader_GetTypeInfoCount,
2299     saxxmlreader_GetTypeInfo,
2300     saxxmlreader_GetIDsOfNames,
2301     saxxmlreader_Invoke,
2302     saxxmlreader_getFeature,
2303     saxxmlreader_putFeature,
2304     saxxmlreader_getProperty,
2305     saxxmlreader_putProperty,
2306     saxxmlreader_get_entityResolver,
2307     saxxmlreader_put_entityResolver,
2308     saxxmlreader_get_contentHandler,
2309     saxxmlreader_put_contentHandler,
2310     saxxmlreader_get_dtdHandler,
2311     saxxmlreader_put_dtdHandler,
2312     saxxmlreader_get_errorHandler,
2313     saxxmlreader_put_errorHandler,
2314     saxxmlreader_get_baseURL,
2315     saxxmlreader_put_baseURL,
2316     saxxmlreader_get_secureBaseURL,
2317     saxxmlreader_put_secureBaseURL,
2318     saxxmlreader_parse,
2319     saxxmlreader_parseURL
2320 };
2321
2322 /*** ISAXXMLReader interface ***/
2323 /*** IUnknown methods ***/
2324 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2325 {
2326     saxreader *This = impl_from_ISAXXMLReader( iface );
2327     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2328 }
2329
2330 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2331 {
2332     saxreader *This = impl_from_ISAXXMLReader( iface );
2333     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2334 }
2335
2336 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2337 {
2338     saxreader *This = impl_from_ISAXXMLReader( iface );
2339     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2340 }
2341
2342 /*** ISAXXMLReader methods ***/
2343 static HRESULT WINAPI isaxxmlreader_getFeature(
2344         ISAXXMLReader* iface,
2345         const WCHAR *pFeature,
2346         VARIANT_BOOL *pValue)
2347 {
2348     saxreader *This = impl_from_ISAXXMLReader( iface );
2349     return IVBSAXXMLReader_getFeature(
2350             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2351             pFeature, pValue);
2352 }
2353
2354 static HRESULT WINAPI isaxxmlreader_putFeature(
2355         ISAXXMLReader* iface,
2356         const WCHAR *pFeature,
2357         VARIANT_BOOL vfValue)
2358 {
2359     saxreader *This = impl_from_ISAXXMLReader( iface );
2360     return IVBSAXXMLReader_putFeature(
2361             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2362             pFeature, vfValue);
2363 }
2364
2365 static HRESULT WINAPI isaxxmlreader_getProperty(
2366         ISAXXMLReader* iface,
2367         const WCHAR *pProp,
2368         VARIANT *pValue)
2369 {
2370     saxreader *This = impl_from_ISAXXMLReader( iface );
2371     return IVBSAXXMLReader_getProperty(
2372             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2373             pProp, pValue);
2374 }
2375
2376 static HRESULT WINAPI isaxxmlreader_putProperty(
2377         ISAXXMLReader* iface,
2378         const WCHAR *pProp,
2379         VARIANT value)
2380 {
2381     saxreader *This = impl_from_ISAXXMLReader( iface );
2382     return IVBSAXXMLReader_putProperty(
2383             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2384             pProp, value);
2385 }
2386
2387 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2388         ISAXXMLReader* iface,
2389         ISAXEntityResolver **ppEntityResolver)
2390 {
2391     saxreader *This = impl_from_ISAXXMLReader( iface );
2392     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2393 }
2394
2395 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2396         ISAXXMLReader* iface,
2397         ISAXEntityResolver *pEntityResolver)
2398 {
2399     saxreader *This = impl_from_ISAXXMLReader( iface );
2400     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2401 }
2402
2403 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2404         ISAXXMLReader* iface,
2405         ISAXContentHandler **pContentHandler)
2406 {
2407     saxreader *This = impl_from_ISAXXMLReader( iface );
2408     return internal_getContentHandler(This, pContentHandler, FALSE);
2409 }
2410
2411 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2412         ISAXXMLReader* iface,
2413         ISAXContentHandler *contentHandler)
2414 {
2415     saxreader *This = impl_from_ISAXXMLReader( iface );
2416     return internal_putContentHandler(This, contentHandler, FALSE);
2417 }
2418
2419 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2420         ISAXXMLReader* iface,
2421         ISAXDTDHandler **pDTDHandler)
2422 {
2423     saxreader *This = impl_from_ISAXXMLReader( iface );
2424     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2425 }
2426
2427 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2428         ISAXXMLReader* iface,
2429         ISAXDTDHandler *pDTDHandler)
2430 {
2431     saxreader *This = impl_from_ISAXXMLReader( iface );
2432     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2433 }
2434
2435 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2436         ISAXXMLReader* iface,
2437         ISAXErrorHandler **pErrorHandler)
2438 {
2439     saxreader *This = impl_from_ISAXXMLReader( iface );
2440     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2441 }
2442
2443 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2444         ISAXXMLReader* iface,
2445         ISAXErrorHandler *errorHandler)
2446 {
2447     saxreader *This = impl_from_ISAXXMLReader( iface );
2448     return internal_putErrorHandler(This, errorHandler, FALSE);
2449 }
2450
2451 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2452         ISAXXMLReader* iface,
2453         const WCHAR **pBaseUrl)
2454 {
2455     saxreader *This = impl_from_ISAXXMLReader( iface );
2456     return IVBSAXXMLReader_get_baseURL(
2457             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2458             pBaseUrl);
2459 }
2460
2461 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2462         ISAXXMLReader* iface,
2463         const WCHAR *pBaseUrl)
2464 {
2465     saxreader *This = impl_from_ISAXXMLReader( iface );
2466     return IVBSAXXMLReader_put_baseURL(
2467             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2468             pBaseUrl);
2469 }
2470
2471 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2472         ISAXXMLReader* iface,
2473         const WCHAR **pSecureBaseUrl)
2474 {
2475     saxreader *This = impl_from_ISAXXMLReader( iface );
2476     return IVBSAXXMLReader_get_secureBaseURL(
2477             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2478             pSecureBaseUrl);
2479 }
2480
2481 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2482         ISAXXMLReader* iface,
2483         const WCHAR *secureBaseUrl)
2484 {
2485     saxreader *This = impl_from_ISAXXMLReader( iface );
2486     return IVBSAXXMLReader_put_secureBaseURL(
2487             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2488             secureBaseUrl);
2489 }
2490
2491 static HRESULT WINAPI isaxxmlreader_parse(
2492         ISAXXMLReader* iface,
2493         VARIANT varInput)
2494 {
2495     saxreader *This = impl_from_ISAXXMLReader( iface );
2496     return internal_parse(This, varInput, FALSE);
2497 }
2498
2499 static HRESULT WINAPI isaxxmlreader_parseURL(
2500         ISAXXMLReader* iface,
2501         const WCHAR *url)
2502 {
2503     saxreader *This = impl_from_ISAXXMLReader( iface );
2504     return internal_parseURL(This, url, FALSE);
2505 }
2506
2507 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2508 {
2509     isaxxmlreader_QueryInterface,
2510     isaxxmlreader_AddRef,
2511     isaxxmlreader_Release,
2512     isaxxmlreader_getFeature,
2513     isaxxmlreader_putFeature,
2514     isaxxmlreader_getProperty,
2515     isaxxmlreader_putProperty,
2516     isaxxmlreader_getEntityResolver,
2517     isaxxmlreader_putEntityResolver,
2518     isaxxmlreader_getContentHandler,
2519     isaxxmlreader_putContentHandler,
2520     isaxxmlreader_getDTDHandler,
2521     isaxxmlreader_putDTDHandler,
2522     isaxxmlreader_getErrorHandler,
2523     isaxxmlreader_putErrorHandler,
2524     isaxxmlreader_getBaseURL,
2525     isaxxmlreader_putBaseURL,
2526     isaxxmlreader_getSecureBaseURL,
2527     isaxxmlreader_putSecureBaseURL,
2528     isaxxmlreader_parse,
2529     isaxxmlreader_parseURL
2530 };
2531
2532 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2533 {
2534     saxreader *reader;
2535
2536     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2537
2538     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
2539     if( !reader )
2540         return E_OUTOFMEMORY;
2541
2542     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2543     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2544     reader->ref = 1;
2545     reader->contentHandler = NULL;
2546     reader->vbcontentHandler = NULL;
2547     reader->errorHandler = NULL;
2548     reader->vberrorHandler = NULL;
2549
2550     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2551     reader->sax.initialized = XML_SAX2_MAGIC;
2552     reader->sax.startDocument = libxmlStartDocument;
2553     reader->sax.endDocument = libxmlEndDocument;
2554     reader->sax.startElementNs = libxmlStartElementNS;
2555     reader->sax.endElementNs = libxmlEndElementNS;
2556     reader->sax.characters = libxmlCharacters;
2557     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2558     reader->sax.error = libxmlFatalError;
2559     reader->sax.fatalError = libxmlFatalError;
2560
2561     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2562
2563     TRACE("returning iface %p\n", *ppObj);
2564
2565     return S_OK;
2566 }
2567
2568 #else
2569
2570 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2571 {
2572     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2573             "libxml2 support was not present at compile time.\n");
2574     return E_NOTIMPL;
2575 }
2576
2577 #endif