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