include: Fix function names in IVBSAXXMLReader interface in msxml2.idl.
[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         if(This->publicId)
1521             SysFreeString(This->publicId);
1522         if(This->systemId)
1523             SysFreeString(This->systemId);
1524         HeapFree(GetProcessHeap(), 0, This->nsStack);
1525
1526         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1527         HeapFree( GetProcessHeap(), 0, This );
1528     }
1529
1530     return ref;
1531 }
1532
1533 /*** ISAXLocator methods ***/
1534 static HRESULT WINAPI isaxlocator_getColumnNumber(
1535         ISAXLocator* iface,
1536         int *pnColumn)
1537 {
1538     saxlocator *This = impl_from_ISAXLocator( iface );
1539
1540     *pnColumn = This->column;
1541     return S_OK;
1542 }
1543
1544 static HRESULT WINAPI isaxlocator_getLineNumber(
1545         ISAXLocator* iface,
1546         int *pnLine)
1547 {
1548     saxlocator *This = impl_from_ISAXLocator( iface );
1549
1550     *pnLine = This->line;
1551     return S_OK;
1552 }
1553
1554 static HRESULT WINAPI isaxlocator_getPublicId(
1555         ISAXLocator* iface,
1556         const WCHAR ** ppwchPublicId)
1557 {
1558     BSTR publicId;
1559     saxlocator *This = impl_from_ISAXLocator( iface );
1560
1561     if(This->publicId) SysFreeString(This->publicId);
1562
1563     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1564     if(SysStringLen(publicId))
1565         This->publicId = (WCHAR*)&publicId;
1566     else
1567     {
1568         SysFreeString(publicId);
1569         This->publicId = NULL;
1570     }
1571
1572     *ppwchPublicId = This->publicId;
1573     return S_OK;
1574 }
1575
1576 static HRESULT WINAPI isaxlocator_getSystemId(
1577         ISAXLocator* iface,
1578         const WCHAR ** ppwchSystemId)
1579 {
1580     BSTR systemId;
1581     saxlocator *This = impl_from_ISAXLocator( iface );
1582
1583     if(This->systemId) SysFreeString(This->systemId);
1584
1585     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1586     if(SysStringLen(systemId))
1587         This->systemId = (WCHAR*)&systemId;
1588     else
1589     {
1590         SysFreeString(systemId);
1591         This->systemId = NULL;
1592     }
1593
1594     *ppwchSystemId = This->systemId;
1595     return S_OK;
1596 }
1597
1598 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1599 {
1600     isaxlocator_QueryInterface,
1601     isaxlocator_AddRef,
1602     isaxlocator_Release,
1603     isaxlocator_getColumnNumber,
1604     isaxlocator_getLineNumber,
1605     isaxlocator_getPublicId,
1606     isaxlocator_getSystemId
1607 };
1608
1609 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1610 {
1611     saxlocator *locator;
1612
1613     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
1614     if( !locator )
1615         return E_OUTOFMEMORY;
1616
1617     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1618     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1619     locator->ref = 1;
1620     locator->vbInterface = vbInterface;
1621
1622     locator->saxreader = reader;
1623     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1624
1625     locator->pParserCtxt = NULL;
1626     locator->publicId = NULL;
1627     locator->systemId = NULL;
1628     locator->lastCur = NULL;
1629     locator->line = 0;
1630     locator->column = 0;
1631     locator->ret = S_OK;
1632     locator->nsStackSize = 8;
1633     locator->nsStackLast = 0;
1634     locator->nsStack = HeapAlloc(GetProcessHeap(), 0, locator->nsStackSize);
1635     if(!locator->nsStack)
1636     {
1637         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1638         HeapFree(GetProcessHeap(), 0, locator);
1639         return E_OUTOFMEMORY;
1640     }
1641
1642     *ppsaxlocator = locator;
1643
1644     TRACE("returning %p\n", *ppsaxlocator);
1645
1646     return S_OK;
1647 }
1648
1649 /*** SAXXMLReader internal functions ***/
1650 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1651 {
1652     saxlocator *locator;
1653     HRESULT hr;
1654
1655     hr = SAXLocator_create(This, &locator, vbInterface);
1656     if(FAILED(hr))
1657         return E_FAIL;
1658
1659     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1660     if(!locator->pParserCtxt)
1661     {
1662         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1663         return E_FAIL;
1664     }
1665
1666     locator->pParserCtxt->sax = &locator->saxreader->sax;
1667     locator->pParserCtxt->userData = locator;
1668
1669     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1670     else hr = locator->ret;
1671
1672     if(locator->pParserCtxt)
1673     {
1674         locator->pParserCtxt->sax = NULL;
1675         xmlFreeParserCtxt(locator->pParserCtxt);
1676         locator->pParserCtxt = NULL;
1677     }
1678
1679     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1680     return S_OK;
1681 }
1682
1683 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1684 {
1685     saxlocator *locator;
1686     HRESULT hr;
1687     ULONG dataRead;
1688     char data[1024];
1689
1690     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1691     if(hr != S_OK)
1692         return hr;
1693
1694     hr = SAXLocator_create(This, &locator, vbInterface);
1695     if(FAILED(hr))
1696         return E_FAIL;
1697
1698     locator->pParserCtxt = xmlCreatePushParserCtxt(
1699             &locator->saxreader->sax, locator,
1700             data, dataRead, NULL);
1701     if(!locator->pParserCtxt)
1702     {
1703         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1704         return E_FAIL;
1705     }
1706
1707     while(1)
1708     {
1709         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1710         if(hr != S_OK)
1711             break;
1712
1713         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1714         else hr = locator->ret;
1715
1716         if(hr != S_OK) break;
1717
1718         if(dataRead != sizeof(data))
1719         {
1720             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1721             else hr = locator->ret;
1722
1723             break;
1724         }
1725     }
1726
1727     locator->pParserCtxt->sax = NULL;
1728     xmlFreeParserCtxt(locator->pParserCtxt);
1729     locator->pParserCtxt = NULL;
1730     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1731     return hr;
1732 }
1733
1734 static HRESULT WINAPI internal_getEntityResolver(
1735         saxreader *This,
1736         void *pEntityResolver,
1737         BOOL vbInterface)
1738 {
1739     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1740     return E_NOTIMPL;
1741 }
1742
1743 static HRESULT WINAPI internal_putEntityResolver(
1744         saxreader *This,
1745         void *pEntityResolver,
1746         BOOL vbInterface)
1747 {
1748     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1749     return E_NOTIMPL;
1750 }
1751
1752 static HRESULT WINAPI internal_getContentHandler(
1753         saxreader* This,
1754         void *pContentHandler,
1755         BOOL vbInterface)
1756 {
1757     TRACE("(%p)->(%p)\n", This, pContentHandler);
1758     if(pContentHandler == NULL)
1759         return E_POINTER;
1760     if((vbInterface && This->vbcontentHandler)
1761             || (!vbInterface && This->contentHandler))
1762     {
1763         if(vbInterface)
1764             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1765         else
1766             ISAXContentHandler_AddRef(This->contentHandler);
1767     }
1768     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1769         This->vbcontentHandler;
1770     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1771
1772     return S_OK;
1773 }
1774
1775 static HRESULT WINAPI internal_putContentHandler(
1776         saxreader* This,
1777         void *contentHandler,
1778         BOOL vbInterface)
1779 {
1780     TRACE("(%p)->(%p)\n", This, contentHandler);
1781     if(contentHandler)
1782     {
1783         if(vbInterface)
1784             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1785         else
1786             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1787     }
1788     if((vbInterface && This->vbcontentHandler)
1789             || (!vbInterface && This->contentHandler))
1790     {
1791         if(vbInterface)
1792             IVBSAXContentHandler_Release(This->vbcontentHandler);
1793         else
1794             ISAXContentHandler_Release(This->contentHandler);
1795     }
1796     if(vbInterface)
1797         This->vbcontentHandler = contentHandler;
1798     else
1799         This->contentHandler = contentHandler;
1800
1801     return S_OK;
1802 }
1803
1804 static HRESULT WINAPI internal_getDTDHandler(
1805         saxreader* This,
1806         void *pDTDHandler,
1807         BOOL vbInterface)
1808 {
1809     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1810     return E_NOTIMPL;
1811 }
1812
1813 static HRESULT WINAPI internal_putDTDHandler(
1814         saxreader* This,
1815         void *pDTDHandler,
1816         BOOL vbInterface)
1817 {
1818     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1819     return E_NOTIMPL;
1820 }
1821
1822 static HRESULT WINAPI internal_getErrorHandler(
1823         saxreader* This,
1824         void *pErrorHandler,
1825         BOOL vbInterface)
1826 {
1827     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1828     if(pErrorHandler == NULL)
1829         return E_POINTER;
1830
1831     if(vbInterface && This->vberrorHandler)
1832         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1833     else if(!vbInterface && This->errorHandler)
1834         ISAXErrorHandler_AddRef(This->errorHandler);
1835
1836     if(vbInterface)
1837         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1838     else
1839         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1840
1841     return S_OK;
1842
1843 }
1844
1845 static HRESULT WINAPI internal_putErrorHandler(
1846         saxreader* This,
1847         void *errorHandler,
1848         BOOL vbInterface)
1849 {
1850     TRACE("(%p)->(%p)\n", This, errorHandler);
1851     if(errorHandler)
1852     {
1853         if(vbInterface)
1854             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1855         else
1856             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1857     }
1858
1859     if(vbInterface && This->vberrorHandler)
1860         IVBSAXErrorHandler_Release(This->vberrorHandler);
1861     else if(!vbInterface && This->errorHandler)
1862         ISAXErrorHandler_Release(This->errorHandler);
1863
1864     if(vbInterface)
1865         This->vberrorHandler = errorHandler;
1866     else
1867         This->errorHandler = errorHandler;
1868
1869     return S_OK;
1870
1871 }
1872
1873 static HRESULT WINAPI internal_parse(
1874         saxreader* This,
1875         VARIANT varInput,
1876         BOOL vbInterface)
1877 {
1878     HRESULT hr;
1879
1880     TRACE("(%p)\n", This);
1881
1882     hr = S_OK;
1883     switch(V_VT(&varInput))
1884     {
1885         case VT_BSTR:
1886             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
1887                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
1888             break;
1889         case VT_ARRAY|VT_UI1: {
1890             void *pSAData;
1891             LONG lBound, uBound;
1892             ULONG dataRead;
1893
1894             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
1895             if(hr != S_OK) break;
1896             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
1897             if(hr != S_OK) break;
1898             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
1899             hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData);
1900             if(hr != S_OK) break;
1901             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
1902             SafeArrayUnaccessData(V_ARRAY(&varInput));
1903             break;
1904         }
1905         case VT_UNKNOWN:
1906         case VT_DISPATCH: {
1907             IPersistStream *persistStream;
1908             IStream *stream = NULL;
1909             IXMLDOMDocument *xmlDoc;
1910
1911             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1912                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
1913             {
1914                 hr = IPersistStream_Save(persistStream, stream, TRUE);
1915                 IPersistStream_Release(persistStream);
1916                 if(hr != S_OK) break;
1917             }
1918             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1919                         &IID_IStream, (void**)&stream) == S_OK)
1920             {
1921                 hr = internal_parseStream(This, stream, vbInterface);
1922                 IStream_Release(stream);
1923                 break;
1924             }
1925             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1926                                        &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
1927             {
1928                 BSTR bstrData;
1929
1930                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
1931                 hr = internal_parseBuffer(This, (const char*)bstrData,
1932                         SysStringByteLen(bstrData), vbInterface);
1933                 IXMLDOMDocument_Release(xmlDoc);
1934                 hr = E_NOTIMPL;
1935                 break;
1936             }
1937         }
1938         default:
1939             WARN("vt %d not implemented\n", V_VT(&varInput));
1940             hr = E_INVALIDARG;
1941     }
1942
1943     return hr;
1944 }
1945
1946 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
1947 {
1948     saxreader *This = obj;
1949
1950     return internal_parseBuffer(This, ptr, len, TRUE);
1951 }
1952
1953 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
1954 {
1955     saxreader *This = obj;
1956
1957     return internal_parseBuffer(This, ptr, len, FALSE);
1958 }
1959
1960 static HRESULT WINAPI internal_parseURL(
1961         saxreader* This,
1962         const WCHAR *url,
1963         BOOL vbInterface)
1964 {
1965     bsc_t *bsc;
1966     HRESULT hr;
1967
1968     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
1969
1970     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
1971     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
1972
1973     if(FAILED(hr))
1974         return hr;
1975
1976     detach_bsc(bsc);
1977
1978     return S_OK;
1979 }
1980
1981 /*** IVBSAXXMLReader interface ***/
1982 /*** IUnknown methods ***/
1983 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
1984 {
1985     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1986
1987     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1988
1989     *ppvObject = NULL;
1990
1991     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1992          IsEqualGUID( riid, &IID_IDispatch ) ||
1993          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
1994     {
1995         *ppvObject = iface;
1996     }
1997     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
1998     {
1999         *ppvObject = (ISAXXMLReader*)&This->lpSAXXMLReaderVtbl;
2000     }
2001     else
2002     {
2003         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2004         return E_NOINTERFACE;
2005     }
2006
2007     IVBSAXXMLReader_AddRef( iface );
2008
2009     return S_OK;
2010 }
2011
2012 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2013 {
2014     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2015     TRACE("%p\n", This );
2016     return InterlockedIncrement( &This->ref );
2017 }
2018
2019 static ULONG WINAPI saxxmlreader_Release(
2020     IVBSAXXMLReader* iface)
2021 {
2022     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2023     LONG ref;
2024
2025     TRACE("%p\n", This );
2026
2027     ref = InterlockedDecrement( &This->ref );
2028     if ( ref == 0 )
2029     {
2030         if(This->contentHandler)
2031             ISAXContentHandler_Release(This->contentHandler);
2032
2033         if(This->vbcontentHandler)
2034             IVBSAXContentHandler_Release(This->vbcontentHandler);
2035
2036         if(This->errorHandler)
2037             ISAXErrorHandler_Release(This->errorHandler);
2038
2039         if(This->vberrorHandler)
2040             IVBSAXErrorHandler_Release(This->vberrorHandler);
2041
2042         HeapFree( GetProcessHeap(), 0, This );
2043     }
2044
2045     return ref;
2046 }
2047 /*** IDispatch ***/
2048 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2049 {
2050     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2051
2052     TRACE("(%p)->(%p)\n", This, pctinfo);
2053
2054     *pctinfo = 1;
2055
2056     return S_OK;
2057 }
2058
2059 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2060     IVBSAXXMLReader *iface,
2061     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2062 {
2063     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2064     HRESULT hr;
2065
2066     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2067
2068     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2069
2070     return hr;
2071 }
2072
2073 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2074     IVBSAXXMLReader *iface,
2075     REFIID riid,
2076     LPOLESTR* rgszNames,
2077     UINT cNames,
2078     LCID lcid,
2079     DISPID* rgDispId)
2080 {
2081     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2082     ITypeInfo *typeinfo;
2083     HRESULT hr;
2084
2085     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2086           lcid, rgDispId);
2087
2088     if(!rgszNames || cNames == 0 || !rgDispId)
2089         return E_INVALIDARG;
2090
2091     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2092     if(SUCCEEDED(hr))
2093     {
2094         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2095         ITypeInfo_Release(typeinfo);
2096     }
2097
2098     return hr;
2099 }
2100
2101 static HRESULT WINAPI saxxmlreader_Invoke(
2102     IVBSAXXMLReader *iface,
2103     DISPID dispIdMember,
2104     REFIID riid,
2105     LCID lcid,
2106     WORD wFlags,
2107     DISPPARAMS* pDispParams,
2108     VARIANT* pVarResult,
2109     EXCEPINFO* pExcepInfo,
2110     UINT* puArgErr)
2111 {
2112     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2113     ITypeInfo *typeinfo;
2114     HRESULT hr;
2115
2116     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2117           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2118
2119     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2120     if(SUCCEEDED(hr))
2121     {
2122         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2123                 pVarResult, pExcepInfo, puArgErr);
2124         ITypeInfo_Release(typeinfo);
2125     }
2126
2127     return hr;
2128 }
2129
2130 /*** IVBSAXXMLReader methods ***/
2131 static HRESULT WINAPI saxxmlreader_getFeature(
2132     IVBSAXXMLReader* iface,
2133     const WCHAR *pFeature,
2134     VARIANT_BOOL *pValue)
2135 {
2136     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2137
2138     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2139     return E_NOTIMPL;
2140 }
2141
2142 static HRESULT WINAPI saxxmlreader_putFeature(
2143     IVBSAXXMLReader* iface,
2144     const WCHAR *pFeature,
2145     VARIANT_BOOL vfValue)
2146 {
2147     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2148
2149     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2150     return E_NOTIMPL;
2151 }
2152
2153 static HRESULT WINAPI saxxmlreader_getProperty(
2154     IVBSAXXMLReader* iface,
2155     const WCHAR *pProp,
2156     VARIANT *pValue)
2157 {
2158     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2159
2160     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2161     return E_NOTIMPL;
2162 }
2163
2164 static HRESULT WINAPI saxxmlreader_putProperty(
2165     IVBSAXXMLReader* iface,
2166     const WCHAR *pProp,
2167     VARIANT value)
2168 {
2169     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2170
2171     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
2172     return E_NOTIMPL;
2173 }
2174
2175 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2176     IVBSAXXMLReader* iface,
2177     IVBSAXEntityResolver **pEntityResolver)
2178 {
2179     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2180     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2181 }
2182
2183 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2184     IVBSAXXMLReader* iface,
2185     IVBSAXEntityResolver *pEntityResolver)
2186 {
2187     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2188     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2189 }
2190
2191 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2192     IVBSAXXMLReader* iface,
2193     IVBSAXContentHandler **ppContentHandler)
2194 {
2195     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2196     return internal_getContentHandler(This, ppContentHandler, TRUE);
2197 }
2198
2199 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2200     IVBSAXXMLReader* iface,
2201     IVBSAXContentHandler *contentHandler)
2202 {
2203     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2204     return internal_putContentHandler(This, contentHandler, TRUE);
2205 }
2206
2207 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2208     IVBSAXXMLReader* iface,
2209     IVBSAXDTDHandler **pDTDHandler)
2210 {
2211     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2212     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2213 }
2214
2215 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2216     IVBSAXXMLReader* iface,
2217     IVBSAXDTDHandler *pDTDHandler)
2218 {
2219     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2220     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2221 }
2222
2223 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2224     IVBSAXXMLReader* iface,
2225     IVBSAXErrorHandler **pErrorHandler)
2226 {
2227     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2228     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2229 }
2230
2231 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2232     IVBSAXXMLReader* iface,
2233     IVBSAXErrorHandler *errorHandler)
2234 {
2235     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2236     return internal_putErrorHandler(This, errorHandler, TRUE);
2237 }
2238
2239 static HRESULT WINAPI saxxmlreader_get_baseURL(
2240     IVBSAXXMLReader* iface,
2241     const WCHAR **pBaseUrl)
2242 {
2243     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2244
2245     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2246     return E_NOTIMPL;
2247 }
2248
2249 static HRESULT WINAPI saxxmlreader_put_baseURL(
2250     IVBSAXXMLReader* iface,
2251     const WCHAR *pBaseUrl)
2252 {
2253     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2254
2255     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2256     return E_NOTIMPL;
2257 }
2258
2259 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2260     IVBSAXXMLReader* iface,
2261     const WCHAR **pSecureBaseUrl)
2262 {
2263     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2264
2265     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2266     return E_NOTIMPL;
2267 }
2268
2269
2270 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2271     IVBSAXXMLReader* iface,
2272     const WCHAR *secureBaseUrl)
2273 {
2274     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2275
2276     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2277     return E_NOTIMPL;
2278 }
2279
2280 static HRESULT WINAPI saxxmlreader_parse(
2281     IVBSAXXMLReader* iface,
2282     VARIANT varInput)
2283 {
2284     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2285     return internal_parse(This, varInput, TRUE);
2286 }
2287
2288 static HRESULT WINAPI saxxmlreader_parseURL(
2289     IVBSAXXMLReader* iface,
2290     const WCHAR *url)
2291 {
2292     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2293     return internal_parseURL(This, url, TRUE);
2294 }
2295
2296 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2297 {
2298     saxxmlreader_QueryInterface,
2299     saxxmlreader_AddRef,
2300     saxxmlreader_Release,
2301     saxxmlreader_GetTypeInfoCount,
2302     saxxmlreader_GetTypeInfo,
2303     saxxmlreader_GetIDsOfNames,
2304     saxxmlreader_Invoke,
2305     saxxmlreader_getFeature,
2306     saxxmlreader_putFeature,
2307     saxxmlreader_getProperty,
2308     saxxmlreader_putProperty,
2309     saxxmlreader_get_entityResolver,
2310     saxxmlreader_put_entityResolver,
2311     saxxmlreader_get_contentHandler,
2312     saxxmlreader_put_contentHandler,
2313     saxxmlreader_get_dtdHandler,
2314     saxxmlreader_put_dtdHandler,
2315     saxxmlreader_get_errorHandler,
2316     saxxmlreader_put_errorHandler,
2317     saxxmlreader_get_baseURL,
2318     saxxmlreader_put_baseURL,
2319     saxxmlreader_get_secureBaseURL,
2320     saxxmlreader_put_secureBaseURL,
2321     saxxmlreader_parse,
2322     saxxmlreader_parseURL
2323 };
2324
2325 /*** ISAXXMLReader interface ***/
2326 /*** IUnknown methods ***/
2327 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2328 {
2329     saxreader *This = impl_from_ISAXXMLReader( iface );
2330     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2331 }
2332
2333 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2334 {
2335     saxreader *This = impl_from_ISAXXMLReader( iface );
2336     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2337 }
2338
2339 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2340 {
2341     saxreader *This = impl_from_ISAXXMLReader( iface );
2342     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2343 }
2344
2345 /*** ISAXXMLReader methods ***/
2346 static HRESULT WINAPI isaxxmlreader_getFeature(
2347         ISAXXMLReader* iface,
2348         const WCHAR *pFeature,
2349         VARIANT_BOOL *pValue)
2350 {
2351     saxreader *This = impl_from_ISAXXMLReader( iface );
2352     return IVBSAXXMLReader_getFeature(
2353             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2354             pFeature, pValue);
2355 }
2356
2357 static HRESULT WINAPI isaxxmlreader_putFeature(
2358         ISAXXMLReader* iface,
2359         const WCHAR *pFeature,
2360         VARIANT_BOOL vfValue)
2361 {
2362     saxreader *This = impl_from_ISAXXMLReader( iface );
2363     return IVBSAXXMLReader_putFeature(
2364             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2365             pFeature, vfValue);
2366 }
2367
2368 static HRESULT WINAPI isaxxmlreader_getProperty(
2369         ISAXXMLReader* iface,
2370         const WCHAR *pProp,
2371         VARIANT *pValue)
2372 {
2373     saxreader *This = impl_from_ISAXXMLReader( iface );
2374     return IVBSAXXMLReader_getProperty(
2375             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2376             pProp, pValue);
2377 }
2378
2379 static HRESULT WINAPI isaxxmlreader_putProperty(
2380         ISAXXMLReader* iface,
2381         const WCHAR *pProp,
2382         VARIANT value)
2383 {
2384     saxreader *This = impl_from_ISAXXMLReader( iface );
2385     return IVBSAXXMLReader_putProperty(
2386             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2387             pProp, value);
2388 }
2389
2390 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2391         ISAXXMLReader* iface,
2392         ISAXEntityResolver **ppEntityResolver)
2393 {
2394     saxreader *This = impl_from_ISAXXMLReader( iface );
2395     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2396 }
2397
2398 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2399         ISAXXMLReader* iface,
2400         ISAXEntityResolver *pEntityResolver)
2401 {
2402     saxreader *This = impl_from_ISAXXMLReader( iface );
2403     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2404 }
2405
2406 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2407         ISAXXMLReader* iface,
2408         ISAXContentHandler **pContentHandler)
2409 {
2410     saxreader *This = impl_from_ISAXXMLReader( iface );
2411     return internal_getContentHandler(This, pContentHandler, FALSE);
2412 }
2413
2414 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2415         ISAXXMLReader* iface,
2416         ISAXContentHandler *contentHandler)
2417 {
2418     saxreader *This = impl_from_ISAXXMLReader( iface );
2419     return internal_putContentHandler(This, contentHandler, FALSE);
2420 }
2421
2422 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2423         ISAXXMLReader* iface,
2424         ISAXDTDHandler **pDTDHandler)
2425 {
2426     saxreader *This = impl_from_ISAXXMLReader( iface );
2427     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2428 }
2429
2430 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2431         ISAXXMLReader* iface,
2432         ISAXDTDHandler *pDTDHandler)
2433 {
2434     saxreader *This = impl_from_ISAXXMLReader( iface );
2435     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2436 }
2437
2438 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2439         ISAXXMLReader* iface,
2440         ISAXErrorHandler **pErrorHandler)
2441 {
2442     saxreader *This = impl_from_ISAXXMLReader( iface );
2443     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2444 }
2445
2446 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2447         ISAXXMLReader* iface,
2448         ISAXErrorHandler *errorHandler)
2449 {
2450     saxreader *This = impl_from_ISAXXMLReader( iface );
2451     return internal_putErrorHandler(This, errorHandler, FALSE);
2452 }
2453
2454 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2455         ISAXXMLReader* iface,
2456         const WCHAR **pBaseUrl)
2457 {
2458     saxreader *This = impl_from_ISAXXMLReader( iface );
2459     return IVBSAXXMLReader_get_baseURL(
2460             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2461             pBaseUrl);
2462 }
2463
2464 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2465         ISAXXMLReader* iface,
2466         const WCHAR *pBaseUrl)
2467 {
2468     saxreader *This = impl_from_ISAXXMLReader( iface );
2469     return IVBSAXXMLReader_put_baseURL(
2470             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2471             pBaseUrl);
2472 }
2473
2474 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2475         ISAXXMLReader* iface,
2476         const WCHAR **pSecureBaseUrl)
2477 {
2478     saxreader *This = impl_from_ISAXXMLReader( iface );
2479     return IVBSAXXMLReader_get_secureBaseURL(
2480             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2481             pSecureBaseUrl);
2482 }
2483
2484 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2485         ISAXXMLReader* iface,
2486         const WCHAR *secureBaseUrl)
2487 {
2488     saxreader *This = impl_from_ISAXXMLReader( iface );
2489     return IVBSAXXMLReader_put_secureBaseURL(
2490             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2491             secureBaseUrl);
2492 }
2493
2494 static HRESULT WINAPI isaxxmlreader_parse(
2495         ISAXXMLReader* iface,
2496         VARIANT varInput)
2497 {
2498     saxreader *This = impl_from_ISAXXMLReader( iface );
2499     return internal_parse(This, varInput, FALSE);
2500 }
2501
2502 static HRESULT WINAPI isaxxmlreader_parseURL(
2503         ISAXXMLReader* iface,
2504         const WCHAR *url)
2505 {
2506     saxreader *This = impl_from_ISAXXMLReader( iface );
2507     return internal_parseURL(This, url, FALSE);
2508 }
2509
2510 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2511 {
2512     isaxxmlreader_QueryInterface,
2513     isaxxmlreader_AddRef,
2514     isaxxmlreader_Release,
2515     isaxxmlreader_getFeature,
2516     isaxxmlreader_putFeature,
2517     isaxxmlreader_getProperty,
2518     isaxxmlreader_putProperty,
2519     isaxxmlreader_getEntityResolver,
2520     isaxxmlreader_putEntityResolver,
2521     isaxxmlreader_getContentHandler,
2522     isaxxmlreader_putContentHandler,
2523     isaxxmlreader_getDTDHandler,
2524     isaxxmlreader_putDTDHandler,
2525     isaxxmlreader_getErrorHandler,
2526     isaxxmlreader_putErrorHandler,
2527     isaxxmlreader_getBaseURL,
2528     isaxxmlreader_putBaseURL,
2529     isaxxmlreader_getSecureBaseURL,
2530     isaxxmlreader_putSecureBaseURL,
2531     isaxxmlreader_parse,
2532     isaxxmlreader_parseURL
2533 };
2534
2535 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2536 {
2537     saxreader *reader;
2538
2539     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2540
2541     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
2542     if( !reader )
2543         return E_OUTOFMEMORY;
2544
2545     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2546     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2547     reader->ref = 1;
2548     reader->contentHandler = NULL;
2549     reader->vbcontentHandler = NULL;
2550     reader->errorHandler = NULL;
2551     reader->vberrorHandler = NULL;
2552
2553     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2554     reader->sax.initialized = XML_SAX2_MAGIC;
2555     reader->sax.startDocument = libxmlStartDocument;
2556     reader->sax.endDocument = libxmlEndDocument;
2557     reader->sax.startElementNs = libxmlStartElementNS;
2558     reader->sax.endElementNs = libxmlEndElementNS;
2559     reader->sax.characters = libxmlCharacters;
2560     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2561     reader->sax.error = libxmlFatalError;
2562     reader->sax.fatalError = libxmlFatalError;
2563
2564     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2565
2566     TRACE("returning iface %p\n", *ppObj);
2567
2568     return S_OK;
2569 }
2570
2571 #else
2572
2573 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2574 {
2575     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2576             "libxml2 support was not present at compile time.\n");
2577     return E_NOTIMPL;
2578 }
2579
2580 #endif