msxml3: Build qualified name using libxml2 helper.
[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 inline BOOL has_error_handler(const saxlocator *locator)
136 {
137     return (locator->vbInterface && locator->saxreader->vberrorHandler) ||
138           (!locator->vbInterface && locator->saxreader->errorHandler);
139 }
140
141 static HRESULT namespacePush(saxlocator *locator, int ns)
142 {
143     if(locator->nsStackLast>=locator->nsStackSize)
144     {
145         int *new_stack;
146
147         new_stack = HeapReAlloc(GetProcessHeap(), 0,
148                 locator->nsStack, sizeof(int)*locator->nsStackSize*2);
149         if(!new_stack) return E_OUTOFMEMORY;
150         locator->nsStack = new_stack;
151         locator->nsStackSize *= 2;
152     }
153     locator->nsStack[locator->nsStackLast++] = ns;
154
155     return S_OK;
156 }
157
158 static int namespacePop(saxlocator *locator)
159 {
160     if(locator->nsStackLast == 0) return 0;
161     return locator->nsStack[--locator->nsStackLast];
162 }
163
164 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
165 {
166     DWORD dLen;
167     BSTR bstr;
168
169     if (!buf)
170         return NULL;
171
172     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
173     if(len != -1) dLen++;
174     bstr = SysAllocStringLen(NULL, dLen-1);
175     if (!bstr)
176         return NULL;
177     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
178     if(len != -1) bstr[dLen-1] = '\0';
179
180     return bstr;
181 }
182
183 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
184 {
185     xmlChar *qname;
186     BSTR bstr;
187
188     if(!name) return NULL;
189
190     if(!prefix || !*prefix)
191         return bstr_from_xmlChar(name);
192
193     qname = xmlBuildQName(name, prefix, NULL, 0);
194     bstr = bstr_from_xmlChar(qname);
195     xmlFree(qname);
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(has_error_handler(This))
206     {
207         WCHAR msg[1024];
208         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
209                     NULL, hr, 0, msg, sizeof(msg), NULL))
210         {
211             FIXME("MSXML errors not yet supported.\n");
212             msg[0] = '\0';
213         }
214
215         if(This->vbInterface)
216         {
217             BSTR bstrMsg = SysAllocString(msg);
218             IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
219                     (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrMsg, hr);
220             SysFreeString(bstrMsg);
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 = S_OK;
1244
1245     if(has_content_handler(This))
1246     {
1247         if(This->vbInterface)
1248             hr = IVBSAXContentHandler_putref_documentLocator(
1249                     This->saxreader->vbcontentHandler,
1250                     (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1251         else
1252             hr = ISAXContentHandler_putDocumentLocator(
1253                     This->saxreader->contentHandler,
1254                     (ISAXLocator*)&This->lpSAXLocatorVtbl);
1255     }
1256
1257     if(FAILED(hr))
1258         format_error_message_from_id(This, hr);
1259 }
1260
1261 static void libxmlComment(void *ctx, const xmlChar *value)
1262 {
1263     saxlocator *This = ctx;
1264     BSTR bValue;
1265     HRESULT hr;
1266     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur;
1267
1268     while(beg-4>=This->pParserCtxt->input->base
1269             && memcmp(beg-4, "<!--", sizeof(char[4]))) beg--;
1270     update_position(This, beg);
1271
1272     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1273     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1274
1275     bValue = bstr_from_xmlChar(value);
1276
1277     if(This->vbInterface)
1278         hr = IVBSAXLexicalHandler_comment(
1279                 This->saxreader->vblexicalHandler, &bValue);
1280     else
1281         hr = ISAXLexicalHandler_comment(
1282                 This->saxreader->lexicalHandler,
1283                 bValue, SysStringLen(bValue));
1284
1285     SysFreeString(bValue);
1286
1287     if(FAILED(hr))
1288         format_error_message_from_id(This, hr);
1289
1290     update_position(This, NULL);
1291 }
1292
1293 static void libxmlFatalError(void *ctx, const char *msg, ...)
1294 {
1295     saxlocator *This = ctx;
1296     char message[1024];
1297     WCHAR *error;
1298     DWORD len;
1299     va_list args;
1300
1301     if(!has_error_handler(This))
1302     {
1303         xmlStopParser(This->pParserCtxt);
1304         This->ret = E_FAIL;
1305         return;
1306     }
1307
1308     FIXME("Error handling is not compatible.\n");
1309
1310     va_start(args, msg);
1311     vsprintf(message, msg, args);
1312     va_end(args);
1313
1314     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1315     error = heap_alloc(sizeof(WCHAR)*len);
1316     if(error)
1317     {
1318         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1319         TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1320     }
1321
1322     if(This->vbInterface)
1323     {
1324         BSTR bstrError = SysAllocString(error);
1325         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1326                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1327         SysFreeString(bstrError);
1328     }
1329     else
1330         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1331                 (ISAXLocator*)&This->lpSAXLocatorVtbl, error, E_FAIL);
1332
1333     heap_free(error);
1334
1335     xmlStopParser(This->pParserCtxt);
1336     This->ret = E_FAIL;
1337 }
1338
1339 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1340 {
1341     saxlocator *This = ctx;
1342     HRESULT hr = S_OK;
1343     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1344     xmlChar *cur, *end;
1345     int realLen;
1346     BSTR Chars;
1347     BOOL lastEvent = FALSE, change;
1348
1349     while(beg-9>=This->pParserCtxt->input->base
1350             && memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) beg--;
1351     update_position(This, beg);
1352
1353     if(This->vbInterface && This->saxreader->vblexicalHandler)
1354         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1355     if(!This->vbInterface && This->saxreader->lexicalHandler)
1356         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1357
1358     if(FAILED(hr))
1359     {
1360         format_error_message_from_id(This, hr);
1361         return;
1362     }
1363
1364     realLen = This->pParserCtxt->input->cur-beg-3;
1365     cur = beg;
1366     end = beg;
1367
1368     while(1)
1369     {
1370         while(end-beg<realLen && *end!='\r') end++;
1371         if(end-beg==realLen)
1372         {
1373             end--;
1374             lastEvent = TRUE;
1375         }
1376         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1377             lastEvent = TRUE;
1378
1379         if(*end == '\r') change = TRUE;
1380         else change = FALSE;
1381
1382         if(change) *end = '\n';
1383
1384         if(has_content_handler(This))
1385         {
1386             Chars = bstr_from_xmlCharN(cur, end-cur+1);
1387             if(This->vbInterface)
1388                 hr = IVBSAXContentHandler_characters(
1389                         This->saxreader->vbcontentHandler, &Chars);
1390             else
1391                 hr = ISAXContentHandler_characters(
1392                         This->saxreader->contentHandler,
1393                         Chars, SysStringLen(Chars));
1394             SysFreeString(Chars);
1395         }
1396
1397         if(change) *end = '\r';
1398
1399         if(lastEvent)
1400             break;
1401
1402         This->column += end-cur+2;
1403         end += 2;
1404         cur = end;
1405     }
1406
1407     if(This->vbInterface && This->saxreader->vblexicalHandler)
1408         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1409     if(!This->vbInterface && This->saxreader->lexicalHandler)
1410         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1411
1412     if(FAILED(hr))
1413         format_error_message_from_id(This, hr);
1414
1415     This->column += 4+end-cur;
1416 }
1417
1418 /*** IVBSAXLocator interface ***/
1419 /*** IUnknown methods ***/
1420 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1421 {
1422     saxlocator *This = impl_from_IVBSAXLocator( iface );
1423
1424     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1425
1426     *ppvObject = NULL;
1427
1428     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1429             IsEqualGUID( riid, &IID_IDispatch) ||
1430             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1431     {
1432         *ppvObject = iface;
1433     }
1434     else
1435     {
1436         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1437         return E_NOINTERFACE;
1438     }
1439
1440     IVBSAXLocator_AddRef( iface );
1441
1442     return S_OK;
1443 }
1444
1445 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1446 {
1447     saxlocator *This = impl_from_IVBSAXLocator( iface );
1448     TRACE("%p\n", This );
1449     return InterlockedIncrement( &This->ref );
1450 }
1451
1452 static ULONG WINAPI ivbsaxlocator_Release(
1453         IVBSAXLocator* iface)
1454 {
1455     saxlocator *This = impl_from_IVBSAXLocator( iface );
1456     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1457 }
1458
1459 /*** IDispatch methods ***/
1460 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1461 {
1462     saxlocator *This = impl_from_IVBSAXLocator( iface );
1463
1464     TRACE("(%p)->(%p)\n", This, pctinfo);
1465
1466     *pctinfo = 1;
1467
1468     return S_OK;
1469 }
1470
1471 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1472     IVBSAXLocator *iface,
1473     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1474 {
1475     saxlocator *This = impl_from_IVBSAXLocator( iface );
1476     HRESULT hr;
1477
1478     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1479
1480     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1481
1482     return hr;
1483 }
1484
1485 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1486     IVBSAXLocator *iface,
1487     REFIID riid,
1488     LPOLESTR* rgszNames,
1489     UINT cNames,
1490     LCID lcid,
1491     DISPID* rgDispId)
1492 {
1493     saxlocator *This = impl_from_IVBSAXLocator( iface );
1494     ITypeInfo *typeinfo;
1495     HRESULT hr;
1496
1497     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1498           lcid, rgDispId);
1499
1500     if(!rgszNames || cNames == 0 || !rgDispId)
1501         return E_INVALIDARG;
1502
1503     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1504     if(SUCCEEDED(hr))
1505     {
1506         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1507         ITypeInfo_Release(typeinfo);
1508     }
1509
1510     return hr;
1511 }
1512
1513 static HRESULT WINAPI ivbsaxlocator_Invoke(
1514     IVBSAXLocator *iface,
1515     DISPID dispIdMember,
1516     REFIID riid,
1517     LCID lcid,
1518     WORD wFlags,
1519     DISPPARAMS* pDispParams,
1520     VARIANT* pVarResult,
1521     EXCEPINFO* pExcepInfo,
1522     UINT* puArgErr)
1523 {
1524     saxlocator *This = impl_from_IVBSAXLocator( iface );
1525     ITypeInfo *typeinfo;
1526     HRESULT hr;
1527
1528     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1529           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1530
1531     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1532     if(SUCCEEDED(hr))
1533     {
1534         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1535                 pVarResult, pExcepInfo, puArgErr);
1536         ITypeInfo_Release(typeinfo);
1537     }
1538
1539     return hr;
1540 }
1541
1542 /*** IVBSAXLocator methods ***/
1543 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1544         IVBSAXLocator* iface,
1545         int *pnColumn)
1546 {
1547     saxlocator *This = impl_from_IVBSAXLocator( iface );
1548     return ISAXLocator_getColumnNumber(
1549             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1550             pnColumn);
1551 }
1552
1553 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1554         IVBSAXLocator* iface,
1555         int *pnLine)
1556 {
1557     saxlocator *This = impl_from_IVBSAXLocator( iface );
1558     return ISAXLocator_getLineNumber(
1559             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1560             pnLine);
1561 }
1562
1563 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1564         IVBSAXLocator* iface,
1565         BSTR* publicId)
1566 {
1567     saxlocator *This = impl_from_IVBSAXLocator( iface );
1568     return ISAXLocator_getPublicId(
1569             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1570             (const WCHAR**)publicId);
1571 }
1572
1573 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1574         IVBSAXLocator* iface,
1575         BSTR* systemId)
1576 {
1577     saxlocator *This = impl_from_IVBSAXLocator( iface );
1578     return ISAXLocator_getSystemId(
1579             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1580             (const WCHAR**)systemId);
1581 }
1582
1583 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1584 {
1585     ivbsaxlocator_QueryInterface,
1586     ivbsaxlocator_AddRef,
1587     ivbsaxlocator_Release,
1588     ivbsaxlocator_GetTypeInfoCount,
1589     ivbsaxlocator_GetTypeInfo,
1590     ivbsaxlocator_GetIDsOfNames,
1591     ivbsaxlocator_Invoke,
1592     ivbsaxlocator_get_columnNumber,
1593     ivbsaxlocator_get_lineNumber,
1594     ivbsaxlocator_get_publicId,
1595     ivbsaxlocator_get_systemId
1596 };
1597
1598 /*** ISAXLocator interface ***/
1599 /*** IUnknown methods ***/
1600 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1601 {
1602     saxlocator *This = impl_from_ISAXLocator( iface );
1603
1604     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1605
1606     *ppvObject = NULL;
1607
1608     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1609             IsEqualGUID( riid, &IID_ISAXLocator ))
1610     {
1611         *ppvObject = iface;
1612     }
1613     else
1614     {
1615         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1616         return E_NOINTERFACE;
1617     }
1618
1619     ISAXLocator_AddRef( iface );
1620
1621     return S_OK;
1622 }
1623
1624 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1625 {
1626     saxlocator *This = impl_from_ISAXLocator( iface );
1627     TRACE("%p\n", This );
1628     return InterlockedIncrement( &This->ref );
1629 }
1630
1631 static ULONG WINAPI isaxlocator_Release(
1632         ISAXLocator* iface)
1633 {
1634     saxlocator *This = impl_from_ISAXLocator( iface );
1635     LONG ref;
1636
1637     TRACE("%p\n", This );
1638
1639     ref = InterlockedDecrement( &This->ref );
1640     if ( ref == 0 )
1641     {
1642         SysFreeString(This->publicId);
1643         SysFreeString(This->systemId);
1644         heap_free(This->nsStack);
1645
1646         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1647         heap_free( This );
1648     }
1649
1650     return ref;
1651 }
1652
1653 /*** ISAXLocator methods ***/
1654 static HRESULT WINAPI isaxlocator_getColumnNumber(
1655         ISAXLocator* iface,
1656         int *pnColumn)
1657 {
1658     saxlocator *This = impl_from_ISAXLocator( iface );
1659
1660     *pnColumn = This->column;
1661     return S_OK;
1662 }
1663
1664 static HRESULT WINAPI isaxlocator_getLineNumber(
1665         ISAXLocator* iface,
1666         int *pnLine)
1667 {
1668     saxlocator *This = impl_from_ISAXLocator( iface );
1669
1670     *pnLine = This->line;
1671     return S_OK;
1672 }
1673
1674 static HRESULT WINAPI isaxlocator_getPublicId(
1675         ISAXLocator* iface,
1676         const WCHAR ** ppwchPublicId)
1677 {
1678     BSTR publicId;
1679     saxlocator *This = impl_from_ISAXLocator( iface );
1680
1681     SysFreeString(This->publicId);
1682
1683     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1684     if(SysStringLen(publicId))
1685         This->publicId = (WCHAR*)&publicId;
1686     else
1687     {
1688         SysFreeString(publicId);
1689         This->publicId = NULL;
1690     }
1691
1692     *ppwchPublicId = This->publicId;
1693     return S_OK;
1694 }
1695
1696 static HRESULT WINAPI isaxlocator_getSystemId(
1697         ISAXLocator* iface,
1698         const WCHAR ** ppwchSystemId)
1699 {
1700     BSTR systemId;
1701     saxlocator *This = impl_from_ISAXLocator( iface );
1702
1703     SysFreeString(This->systemId);
1704
1705     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1706     if(SysStringLen(systemId))
1707         This->systemId = (WCHAR*)&systemId;
1708     else
1709     {
1710         SysFreeString(systemId);
1711         This->systemId = NULL;
1712     }
1713
1714     *ppwchSystemId = This->systemId;
1715     return S_OK;
1716 }
1717
1718 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1719 {
1720     isaxlocator_QueryInterface,
1721     isaxlocator_AddRef,
1722     isaxlocator_Release,
1723     isaxlocator_getColumnNumber,
1724     isaxlocator_getLineNumber,
1725     isaxlocator_getPublicId,
1726     isaxlocator_getSystemId
1727 };
1728
1729 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1730 {
1731     saxlocator *locator;
1732
1733     locator = heap_alloc( sizeof (*locator) );
1734     if( !locator )
1735         return E_OUTOFMEMORY;
1736
1737     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1738     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1739     locator->ref = 1;
1740     locator->vbInterface = vbInterface;
1741
1742     locator->saxreader = reader;
1743     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1744
1745     locator->pParserCtxt = NULL;
1746     locator->publicId = NULL;
1747     locator->systemId = NULL;
1748     locator->lastCur = NULL;
1749     locator->line = 0;
1750     locator->column = 0;
1751     locator->ret = S_OK;
1752     locator->nsStackSize = 8;
1753     locator->nsStackLast = 0;
1754     locator->nsStack = heap_alloc(sizeof(int)*locator->nsStackSize);
1755     if(!locator->nsStack)
1756     {
1757         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1758         heap_free(locator);
1759         return E_OUTOFMEMORY;
1760     }
1761
1762     *ppsaxlocator = locator;
1763
1764     TRACE("returning %p\n", *ppsaxlocator);
1765
1766     return S_OK;
1767 }
1768
1769 /*** SAXXMLReader internal functions ***/
1770 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1771 {
1772     saxlocator *locator;
1773     HRESULT hr;
1774
1775     hr = SAXLocator_create(This, &locator, vbInterface);
1776     if(FAILED(hr))
1777         return hr;
1778
1779     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1780     if(!locator->pParserCtxt)
1781     {
1782         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1783         return E_FAIL;
1784     }
1785
1786     xmlFree(locator->pParserCtxt->sax);
1787     locator->pParserCtxt->sax = &locator->saxreader->sax;
1788     locator->pParserCtxt->userData = locator;
1789
1790     This->isParsing = TRUE;
1791     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1792     else hr = locator->ret;
1793     This->isParsing = FALSE;
1794
1795     if(locator->pParserCtxt)
1796     {
1797         locator->pParserCtxt->sax = NULL;
1798         xmlFreeParserCtxt(locator->pParserCtxt);
1799         locator->pParserCtxt = NULL;
1800     }
1801
1802     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1803     return hr;
1804 }
1805
1806 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1807 {
1808     saxlocator *locator;
1809     HRESULT hr;
1810     ULONG dataRead;
1811     char data[1024];
1812
1813     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1814     if(hr != S_OK)
1815         return hr;
1816
1817     hr = SAXLocator_create(This, &locator, vbInterface);
1818     if(FAILED(hr))
1819         return hr;
1820
1821     locator->pParserCtxt = xmlCreatePushParserCtxt(
1822             &locator->saxreader->sax, locator,
1823             data, dataRead, NULL);
1824     if(!locator->pParserCtxt)
1825     {
1826         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1827         return E_FAIL;
1828     }
1829
1830     This->isParsing = TRUE;
1831     while(1)
1832     {
1833         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1834         if(hr != S_OK)
1835             break;
1836
1837         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1838         else hr = locator->ret;
1839
1840         if(hr != S_OK) break;
1841
1842         if(dataRead != sizeof(data))
1843         {
1844             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1845             else hr = locator->ret;
1846
1847             break;
1848         }
1849     }
1850     This->isParsing = FALSE;
1851
1852     xmlFreeParserCtxt(locator->pParserCtxt);
1853     locator->pParserCtxt = NULL;
1854     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1855     return hr;
1856 }
1857
1858 static HRESULT internal_getEntityResolver(
1859         saxreader *This,
1860         void *pEntityResolver,
1861         BOOL vbInterface)
1862 {
1863     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1864     return E_NOTIMPL;
1865 }
1866
1867 static HRESULT internal_putEntityResolver(
1868         saxreader *This,
1869         void *pEntityResolver,
1870         BOOL vbInterface)
1871 {
1872     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1873     return E_NOTIMPL;
1874 }
1875
1876 static HRESULT internal_getContentHandler(
1877         saxreader* This,
1878         void *pContentHandler,
1879         BOOL vbInterface)
1880 {
1881     TRACE("(%p)->(%p)\n", This, pContentHandler);
1882     if(pContentHandler == NULL)
1883         return E_POINTER;
1884     if((vbInterface && This->vbcontentHandler)
1885             || (!vbInterface && This->contentHandler))
1886     {
1887         if(vbInterface)
1888             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1889         else
1890             ISAXContentHandler_AddRef(This->contentHandler);
1891     }
1892     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1893         This->vbcontentHandler;
1894     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1895
1896     return S_OK;
1897 }
1898
1899 static HRESULT internal_putContentHandler(
1900         saxreader* This,
1901         void *contentHandler,
1902         BOOL vbInterface)
1903 {
1904     TRACE("(%p)->(%p)\n", This, contentHandler);
1905     if(contentHandler)
1906     {
1907         if(vbInterface)
1908             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1909         else
1910             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1911     }
1912     if((vbInterface && This->vbcontentHandler)
1913             || (!vbInterface && This->contentHandler))
1914     {
1915         if(vbInterface)
1916             IVBSAXContentHandler_Release(This->vbcontentHandler);
1917         else
1918             ISAXContentHandler_Release(This->contentHandler);
1919     }
1920     if(vbInterface)
1921         This->vbcontentHandler = contentHandler;
1922     else
1923         This->contentHandler = contentHandler;
1924
1925     return S_OK;
1926 }
1927
1928 static HRESULT internal_getDTDHandler(
1929         saxreader* This,
1930         void *pDTDHandler,
1931         BOOL vbInterface)
1932 {
1933     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1934     return E_NOTIMPL;
1935 }
1936
1937 static HRESULT internal_putDTDHandler(
1938         saxreader* This,
1939         void *pDTDHandler,
1940         BOOL vbInterface)
1941 {
1942     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1943     return E_NOTIMPL;
1944 }
1945
1946 static HRESULT internal_getErrorHandler(
1947         saxreader* This,
1948         void *pErrorHandler,
1949         BOOL vbInterface)
1950 {
1951     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1952     if(pErrorHandler == NULL)
1953         return E_POINTER;
1954
1955     if(vbInterface && This->vberrorHandler)
1956         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1957     else if(!vbInterface && This->errorHandler)
1958         ISAXErrorHandler_AddRef(This->errorHandler);
1959
1960     if(vbInterface)
1961         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1962     else
1963         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1964
1965     return S_OK;
1966
1967 }
1968
1969 static HRESULT internal_putErrorHandler(
1970         saxreader* This,
1971         void *errorHandler,
1972         BOOL vbInterface)
1973 {
1974     TRACE("(%p)->(%p)\n", This, errorHandler);
1975     if(errorHandler)
1976     {
1977         if(vbInterface)
1978             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1979         else
1980             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1981     }
1982
1983     if(vbInterface && This->vberrorHandler)
1984         IVBSAXErrorHandler_Release(This->vberrorHandler);
1985     else if(!vbInterface && This->errorHandler)
1986         ISAXErrorHandler_Release(This->errorHandler);
1987
1988     if(vbInterface)
1989         This->vberrorHandler = errorHandler;
1990     else
1991         This->errorHandler = errorHandler;
1992
1993     return S_OK;
1994
1995 }
1996
1997 static HRESULT internal_parse(
1998         saxreader* This,
1999         VARIANT varInput,
2000         BOOL vbInterface)
2001 {
2002     HRESULT hr;
2003
2004     TRACE("(%p)\n", This);
2005
2006     hr = S_OK;
2007     switch(V_VT(&varInput))
2008     {
2009         case VT_BSTR:
2010             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2011                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2012             break;
2013         case VT_ARRAY|VT_UI1: {
2014             void *pSAData;
2015             LONG lBound, uBound;
2016             ULONG dataRead;
2017
2018             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2019             if(hr != S_OK) break;
2020             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2021             if(hr != S_OK) break;
2022             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2023             hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2024             if(hr != S_OK) break;
2025             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2026             SafeArrayUnaccessData(V_ARRAY(&varInput));
2027             break;
2028         }
2029         case VT_UNKNOWN:
2030         case VT_DISPATCH: {
2031             IPersistStream *persistStream;
2032             IStream *stream = NULL;
2033             IXMLDOMDocument *xmlDoc;
2034
2035             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2036                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2037             {
2038                 BSTR bstrData;
2039
2040                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2041                 hr = internal_parseBuffer(This, (const char*)bstrData,
2042                         SysStringByteLen(bstrData), vbInterface);
2043                 IXMLDOMDocument_Release(xmlDoc);
2044                 SysFreeString(bstrData);
2045                 break;
2046             }
2047
2048             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2049                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2050             {
2051                 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2052                 if(hr != S_OK)
2053                 {
2054                     IPersistStream_Release(persistStream);
2055                     return hr;
2056                 }
2057
2058                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2059                 IPersistStream_Release(persistStream);
2060                 if(hr != S_OK)
2061                 {
2062                     IStream_Release(stream);
2063                     break;
2064                 }
2065             }
2066             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2067                         &IID_IStream, (void**)&stream) == S_OK)
2068             {
2069                 hr = internal_parseStream(This, stream, vbInterface);
2070                 IStream_Release(stream);
2071                 break;
2072             }
2073         }
2074         default:
2075             WARN("vt %d not implemented\n", V_VT(&varInput));
2076             hr = E_INVALIDARG;
2077     }
2078
2079     return hr;
2080 }
2081
2082 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2083 {
2084     saxreader *This = obj;
2085
2086     return internal_parseBuffer(This, ptr, len, TRUE);
2087 }
2088
2089 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2090 {
2091     saxreader *This = obj;
2092
2093     return internal_parseBuffer(This, ptr, len, FALSE);
2094 }
2095
2096 static HRESULT internal_parseURL(
2097         saxreader* This,
2098         const WCHAR *url,
2099         BOOL vbInterface)
2100 {
2101     bsc_t *bsc;
2102     HRESULT hr;
2103
2104     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2105
2106     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2107     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2108
2109     if(FAILED(hr))
2110         return hr;
2111
2112     detach_bsc(bsc);
2113
2114     return S_OK;
2115 }
2116
2117 static HRESULT internal_putProperty(
2118     saxreader* This,
2119     const WCHAR *pProp,
2120     VARIANT value,
2121     BOOL vbInterface)
2122 {
2123     static const WCHAR wszCharset[] = {
2124         'c','h','a','r','s','e','t',0
2125     };
2126     static const WCHAR wszDeclarationHandler[] = {
2127         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2128         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2129         'd','e','c','l','a','r','a','t','i','o','n',
2130         '-','h','a','n','d','l','e','r',0
2131     };
2132     static const WCHAR wszDomNode[] = {
2133         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2134         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2135         'd','o','m','-','n','o','d','e',0
2136     };
2137     static const WCHAR wszInputSource[] = {
2138         'i','n','p','u','t','-','s','o','u','r','c','e',0
2139     };
2140     static const WCHAR wszLexicalHandler[] = {
2141         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2142         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2143         'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
2144     };
2145     static const WCHAR wszMaxElementDepth[] = {
2146         'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
2147     };
2148     static const WCHAR wszMaxXMLSize[] = {
2149         'm','a','x','-','x','m','l','-','s','i','z','e',0
2150     };
2151     static const WCHAR wszSchemaDeclarationHandler[] = {
2152         's','c','h','e','m','a','-',
2153         'd','e','c','l','a','r','a','t','i','o','n','-',
2154         'h','a','n','d','l','e','r',0
2155     };
2156     static const WCHAR wszXMLDeclEncoding[] = {
2157         'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
2158     };
2159     static const WCHAR wszXMLDeclStandalone[] = {
2160         'x','m','l','d','e','c','l',
2161         '-','s','t','a','n','d','a','l','o','n','e',0
2162     };
2163     static const WCHAR wszXMLDeclVersion[] = {
2164         'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
2165     };
2166
2167     TRACE("(%p)->(%s)\n", This, debugstr_w(pProp));
2168
2169     if(!memcmp(pProp, wszDeclarationHandler, sizeof(wszDeclarationHandler)))
2170     {
2171         if(This->isParsing) return E_FAIL;
2172
2173         if(V_UNKNOWN(&value))
2174         {
2175             if(vbInterface)
2176                 IVBSAXDeclHandler_AddRef((IVBSAXDeclHandler*)V_UNKNOWN(&value));
2177             else
2178                 ISAXDeclHandler_AddRef((ISAXDeclHandler*)V_UNKNOWN(&value));
2179         }
2180         if((vbInterface && This->vbdeclHandler)
2181                 || (!vbInterface && This->declHandler))
2182         {
2183             if(vbInterface)
2184                 IVBSAXDeclHandler_Release(This->vbdeclHandler);
2185             else
2186                 ISAXDeclHandler_Release(This->declHandler);
2187         }
2188         if(vbInterface)
2189             This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2190         else
2191             This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2192         return S_OK;
2193     }
2194
2195     if(!memcmp(pProp, wszLexicalHandler, sizeof(wszLexicalHandler)))
2196     {
2197         if(This->isParsing) return E_FAIL;
2198
2199         if(V_UNKNOWN(&value))
2200         {
2201             if(vbInterface)
2202                 IVBSAXLexicalHandler_AddRef(
2203                         (IVBSAXLexicalHandler*)V_UNKNOWN(&value));
2204             else
2205                 ISAXLexicalHandler_AddRef(
2206                         (ISAXLexicalHandler*)V_UNKNOWN(&value));
2207         }
2208         if((vbInterface && This->vblexicalHandler)
2209                 || (!vbInterface && This->lexicalHandler))
2210         {
2211             if(vbInterface)
2212                 IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2213             else
2214                 ISAXLexicalHandler_Release(This->lexicalHandler);
2215         }
2216         if(vbInterface)
2217             This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2218         else
2219             This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2220         return S_OK;
2221     }
2222
2223     FIXME("(%p)->(%s): unsupported property\n", This, debugstr_w(pProp));
2224
2225     if(!memcmp(pProp, wszCharset, sizeof(wszCharset)))
2226         return E_NOTIMPL;
2227
2228     if(!memcmp(pProp, wszDomNode, sizeof(wszDomNode)))
2229         return E_FAIL;
2230
2231     if(!memcmp(pProp, wszInputSource, sizeof(wszInputSource)))
2232         return E_NOTIMPL;
2233
2234     if(!memcmp(pProp, wszMaxElementDepth, sizeof(wszMaxElementDepth)))
2235         return E_NOTIMPL;
2236
2237     if(!memcmp(pProp, wszMaxXMLSize, sizeof(wszMaxXMLSize)))
2238         return E_NOTIMPL;
2239
2240     if(!memcmp(pProp, wszSchemaDeclarationHandler,
2241                 sizeof(wszSchemaDeclarationHandler)))
2242         return E_NOTIMPL;
2243
2244     if(!memcmp(pProp, wszXMLDeclEncoding, sizeof(wszXMLDeclEncoding)))
2245         return E_FAIL;
2246
2247     if(!memcmp(pProp, wszXMLDeclStandalone, sizeof(wszXMLDeclStandalone)))
2248         return E_FAIL;
2249
2250     if(!memcmp(pProp, wszXMLDeclVersion, sizeof(wszXMLDeclVersion)))
2251         return E_FAIL;
2252
2253     return E_INVALIDARG;
2254 }
2255
2256 /*** IVBSAXXMLReader interface ***/
2257 /*** IUnknown methods ***/
2258 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2259 {
2260     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2261
2262     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2263
2264     *ppvObject = NULL;
2265
2266     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2267          IsEqualGUID( riid, &IID_IDispatch ) ||
2268          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2269     {
2270         *ppvObject = iface;
2271     }
2272     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2273     {
2274         *ppvObject = &This->lpSAXXMLReaderVtbl;
2275     }
2276     else
2277     {
2278         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2279         return E_NOINTERFACE;
2280     }
2281
2282     IVBSAXXMLReader_AddRef( iface );
2283
2284     return S_OK;
2285 }
2286
2287 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2288 {
2289     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2290     TRACE("%p\n", This );
2291     return InterlockedIncrement( &This->ref );
2292 }
2293
2294 static ULONG WINAPI saxxmlreader_Release(
2295     IVBSAXXMLReader* iface)
2296 {
2297     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2298     LONG ref;
2299
2300     TRACE("%p\n", This );
2301
2302     ref = InterlockedDecrement( &This->ref );
2303     if ( ref == 0 )
2304     {
2305         if(This->contentHandler)
2306             ISAXContentHandler_Release(This->contentHandler);
2307
2308         if(This->vbcontentHandler)
2309             IVBSAXContentHandler_Release(This->vbcontentHandler);
2310
2311         if(This->errorHandler)
2312             ISAXErrorHandler_Release(This->errorHandler);
2313
2314         if(This->vberrorHandler)
2315             IVBSAXErrorHandler_Release(This->vberrorHandler);
2316
2317         if(This->lexicalHandler)
2318             ISAXLexicalHandler_Release(This->lexicalHandler);
2319
2320         if(This->vblexicalHandler)
2321             IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2322
2323         if(This->declHandler)
2324             ISAXDeclHandler_Release(This->declHandler);
2325
2326         if(This->vbdeclHandler)
2327             IVBSAXDeclHandler_Release(This->vbdeclHandler);
2328
2329         heap_free( This );
2330     }
2331
2332     return ref;
2333 }
2334 /*** IDispatch ***/
2335 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2336 {
2337     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2338
2339     TRACE("(%p)->(%p)\n", This, pctinfo);
2340
2341     *pctinfo = 1;
2342
2343     return S_OK;
2344 }
2345
2346 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2347     IVBSAXXMLReader *iface,
2348     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2349 {
2350     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2351     HRESULT hr;
2352
2353     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2354
2355     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2356
2357     return hr;
2358 }
2359
2360 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2361     IVBSAXXMLReader *iface,
2362     REFIID riid,
2363     LPOLESTR* rgszNames,
2364     UINT cNames,
2365     LCID lcid,
2366     DISPID* rgDispId)
2367 {
2368     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2369     ITypeInfo *typeinfo;
2370     HRESULT hr;
2371
2372     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2373           lcid, rgDispId);
2374
2375     if(!rgszNames || cNames == 0 || !rgDispId)
2376         return E_INVALIDARG;
2377
2378     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2379     if(SUCCEEDED(hr))
2380     {
2381         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2382         ITypeInfo_Release(typeinfo);
2383     }
2384
2385     return hr;
2386 }
2387
2388 static HRESULT WINAPI saxxmlreader_Invoke(
2389     IVBSAXXMLReader *iface,
2390     DISPID dispIdMember,
2391     REFIID riid,
2392     LCID lcid,
2393     WORD wFlags,
2394     DISPPARAMS* pDispParams,
2395     VARIANT* pVarResult,
2396     EXCEPINFO* pExcepInfo,
2397     UINT* puArgErr)
2398 {
2399     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2400     ITypeInfo *typeinfo;
2401     HRESULT hr;
2402
2403     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2404           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2405
2406     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2407     if(SUCCEEDED(hr))
2408     {
2409         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2410                 pVarResult, pExcepInfo, puArgErr);
2411         ITypeInfo_Release(typeinfo);
2412     }
2413
2414     return hr;
2415 }
2416
2417 /*** IVBSAXXMLReader methods ***/
2418 static HRESULT WINAPI saxxmlreader_getFeature(
2419     IVBSAXXMLReader* iface,
2420     const WCHAR *pFeature,
2421     VARIANT_BOOL *pValue)
2422 {
2423     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2424
2425     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2426     return E_NOTIMPL;
2427 }
2428
2429 static HRESULT WINAPI saxxmlreader_putFeature(
2430     IVBSAXXMLReader* iface,
2431     const WCHAR *pFeature,
2432     VARIANT_BOOL vfValue)
2433 {
2434     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2435
2436     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2437     return E_NOTIMPL;
2438 }
2439
2440 static HRESULT WINAPI saxxmlreader_getProperty(
2441     IVBSAXXMLReader* iface,
2442     const WCHAR *pProp,
2443     VARIANT *pValue)
2444 {
2445     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2446
2447     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2448     return E_NOTIMPL;
2449 }
2450
2451 static HRESULT WINAPI saxxmlreader_putProperty(
2452     IVBSAXXMLReader* iface,
2453     const WCHAR *pProp,
2454     VARIANT value)
2455 {
2456     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2457     return internal_putProperty(This, pProp, value, TRUE);
2458 }
2459
2460 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2461     IVBSAXXMLReader* iface,
2462     IVBSAXEntityResolver **pEntityResolver)
2463 {
2464     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2465     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2466 }
2467
2468 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2469     IVBSAXXMLReader* iface,
2470     IVBSAXEntityResolver *pEntityResolver)
2471 {
2472     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2473     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2474 }
2475
2476 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2477     IVBSAXXMLReader* iface,
2478     IVBSAXContentHandler **ppContentHandler)
2479 {
2480     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2481     return internal_getContentHandler(This, ppContentHandler, TRUE);
2482 }
2483
2484 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2485     IVBSAXXMLReader* iface,
2486     IVBSAXContentHandler *contentHandler)
2487 {
2488     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2489     return internal_putContentHandler(This, contentHandler, TRUE);
2490 }
2491
2492 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2493     IVBSAXXMLReader* iface,
2494     IVBSAXDTDHandler **pDTDHandler)
2495 {
2496     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2497     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2498 }
2499
2500 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2501     IVBSAXXMLReader* iface,
2502     IVBSAXDTDHandler *pDTDHandler)
2503 {
2504     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2505     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2506 }
2507
2508 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2509     IVBSAXXMLReader* iface,
2510     IVBSAXErrorHandler **pErrorHandler)
2511 {
2512     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2513     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2514 }
2515
2516 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2517     IVBSAXXMLReader* iface,
2518     IVBSAXErrorHandler *errorHandler)
2519 {
2520     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2521     return internal_putErrorHandler(This, errorHandler, TRUE);
2522 }
2523
2524 static HRESULT WINAPI saxxmlreader_get_baseURL(
2525     IVBSAXXMLReader* iface,
2526     const WCHAR **pBaseUrl)
2527 {
2528     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2529
2530     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2531     return E_NOTIMPL;
2532 }
2533
2534 static HRESULT WINAPI saxxmlreader_put_baseURL(
2535     IVBSAXXMLReader* iface,
2536     const WCHAR *pBaseUrl)
2537 {
2538     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2539
2540     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2541     return E_NOTIMPL;
2542 }
2543
2544 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2545     IVBSAXXMLReader* iface,
2546     const WCHAR **pSecureBaseUrl)
2547 {
2548     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2549
2550     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2551     return E_NOTIMPL;
2552 }
2553
2554
2555 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2556     IVBSAXXMLReader* iface,
2557     const WCHAR *secureBaseUrl)
2558 {
2559     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2560
2561     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2562     return E_NOTIMPL;
2563 }
2564
2565 static HRESULT WINAPI saxxmlreader_parse(
2566     IVBSAXXMLReader* iface,
2567     VARIANT varInput)
2568 {
2569     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2570     return internal_parse(This, varInput, TRUE);
2571 }
2572
2573 static HRESULT WINAPI saxxmlreader_parseURL(
2574     IVBSAXXMLReader* iface,
2575     const WCHAR *url)
2576 {
2577     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2578     return internal_parseURL(This, url, TRUE);
2579 }
2580
2581 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2582 {
2583     saxxmlreader_QueryInterface,
2584     saxxmlreader_AddRef,
2585     saxxmlreader_Release,
2586     saxxmlreader_GetTypeInfoCount,
2587     saxxmlreader_GetTypeInfo,
2588     saxxmlreader_GetIDsOfNames,
2589     saxxmlreader_Invoke,
2590     saxxmlreader_getFeature,
2591     saxxmlreader_putFeature,
2592     saxxmlreader_getProperty,
2593     saxxmlreader_putProperty,
2594     saxxmlreader_get_entityResolver,
2595     saxxmlreader_put_entityResolver,
2596     saxxmlreader_get_contentHandler,
2597     saxxmlreader_put_contentHandler,
2598     saxxmlreader_get_dtdHandler,
2599     saxxmlreader_put_dtdHandler,
2600     saxxmlreader_get_errorHandler,
2601     saxxmlreader_put_errorHandler,
2602     saxxmlreader_get_baseURL,
2603     saxxmlreader_put_baseURL,
2604     saxxmlreader_get_secureBaseURL,
2605     saxxmlreader_put_secureBaseURL,
2606     saxxmlreader_parse,
2607     saxxmlreader_parseURL
2608 };
2609
2610 /*** ISAXXMLReader interface ***/
2611 /*** IUnknown methods ***/
2612 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2613 {
2614     saxreader *This = impl_from_ISAXXMLReader( iface );
2615     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2616 }
2617
2618 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2619 {
2620     saxreader *This = impl_from_ISAXXMLReader( iface );
2621     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2622 }
2623
2624 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2625 {
2626     saxreader *This = impl_from_ISAXXMLReader( iface );
2627     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2628 }
2629
2630 /*** ISAXXMLReader methods ***/
2631 static HRESULT WINAPI isaxxmlreader_getFeature(
2632         ISAXXMLReader* iface,
2633         const WCHAR *pFeature,
2634         VARIANT_BOOL *pValue)
2635 {
2636     saxreader *This = impl_from_ISAXXMLReader( iface );
2637     return IVBSAXXMLReader_getFeature(
2638             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2639             pFeature, pValue);
2640 }
2641
2642 static HRESULT WINAPI isaxxmlreader_putFeature(
2643         ISAXXMLReader* iface,
2644         const WCHAR *pFeature,
2645         VARIANT_BOOL vfValue)
2646 {
2647     saxreader *This = impl_from_ISAXXMLReader( iface );
2648     return IVBSAXXMLReader_putFeature(
2649             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2650             pFeature, vfValue);
2651 }
2652
2653 static HRESULT WINAPI isaxxmlreader_getProperty(
2654         ISAXXMLReader* iface,
2655         const WCHAR *pProp,
2656         VARIANT *pValue)
2657 {
2658     saxreader *This = impl_from_ISAXXMLReader( iface );
2659     return IVBSAXXMLReader_getProperty(
2660             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2661             pProp, pValue);
2662 }
2663
2664 static HRESULT WINAPI isaxxmlreader_putProperty(
2665         ISAXXMLReader* iface,
2666         const WCHAR *pProp,
2667         VARIANT value)
2668 {
2669     saxreader *This = impl_from_ISAXXMLReader( iface );
2670     return internal_putProperty(This, pProp, value, FALSE);
2671 }
2672
2673 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2674         ISAXXMLReader* iface,
2675         ISAXEntityResolver **ppEntityResolver)
2676 {
2677     saxreader *This = impl_from_ISAXXMLReader( iface );
2678     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2679 }
2680
2681 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2682         ISAXXMLReader* iface,
2683         ISAXEntityResolver *pEntityResolver)
2684 {
2685     saxreader *This = impl_from_ISAXXMLReader( iface );
2686     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2687 }
2688
2689 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2690         ISAXXMLReader* iface,
2691         ISAXContentHandler **pContentHandler)
2692 {
2693     saxreader *This = impl_from_ISAXXMLReader( iface );
2694     return internal_getContentHandler(This, pContentHandler, FALSE);
2695 }
2696
2697 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2698         ISAXXMLReader* iface,
2699         ISAXContentHandler *contentHandler)
2700 {
2701     saxreader *This = impl_from_ISAXXMLReader( iface );
2702     return internal_putContentHandler(This, contentHandler, FALSE);
2703 }
2704
2705 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2706         ISAXXMLReader* iface,
2707         ISAXDTDHandler **pDTDHandler)
2708 {
2709     saxreader *This = impl_from_ISAXXMLReader( iface );
2710     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2711 }
2712
2713 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2714         ISAXXMLReader* iface,
2715         ISAXDTDHandler *pDTDHandler)
2716 {
2717     saxreader *This = impl_from_ISAXXMLReader( iface );
2718     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2719 }
2720
2721 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2722         ISAXXMLReader* iface,
2723         ISAXErrorHandler **pErrorHandler)
2724 {
2725     saxreader *This = impl_from_ISAXXMLReader( iface );
2726     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2727 }
2728
2729 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2730         ISAXXMLReader* iface,
2731         ISAXErrorHandler *errorHandler)
2732 {
2733     saxreader *This = impl_from_ISAXXMLReader( iface );
2734     return internal_putErrorHandler(This, errorHandler, FALSE);
2735 }
2736
2737 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2738         ISAXXMLReader* iface,
2739         const WCHAR **pBaseUrl)
2740 {
2741     saxreader *This = impl_from_ISAXXMLReader( iface );
2742     return IVBSAXXMLReader_get_baseURL(
2743             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2744             pBaseUrl);
2745 }
2746
2747 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2748         ISAXXMLReader* iface,
2749         const WCHAR *pBaseUrl)
2750 {
2751     saxreader *This = impl_from_ISAXXMLReader( iface );
2752     return IVBSAXXMLReader_put_baseURL(
2753             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2754             pBaseUrl);
2755 }
2756
2757 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2758         ISAXXMLReader* iface,
2759         const WCHAR **pSecureBaseUrl)
2760 {
2761     saxreader *This = impl_from_ISAXXMLReader( iface );
2762     return IVBSAXXMLReader_get_secureBaseURL(
2763             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2764             pSecureBaseUrl);
2765 }
2766
2767 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2768         ISAXXMLReader* iface,
2769         const WCHAR *secureBaseUrl)
2770 {
2771     saxreader *This = impl_from_ISAXXMLReader( iface );
2772     return IVBSAXXMLReader_put_secureBaseURL(
2773             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2774             secureBaseUrl);
2775 }
2776
2777 static HRESULT WINAPI isaxxmlreader_parse(
2778         ISAXXMLReader* iface,
2779         VARIANT varInput)
2780 {
2781     saxreader *This = impl_from_ISAXXMLReader( iface );
2782     return internal_parse(This, varInput, FALSE);
2783 }
2784
2785 static HRESULT WINAPI isaxxmlreader_parseURL(
2786         ISAXXMLReader* iface,
2787         const WCHAR *url)
2788 {
2789     saxreader *This = impl_from_ISAXXMLReader( iface );
2790     return internal_parseURL(This, url, FALSE);
2791 }
2792
2793 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2794 {
2795     isaxxmlreader_QueryInterface,
2796     isaxxmlreader_AddRef,
2797     isaxxmlreader_Release,
2798     isaxxmlreader_getFeature,
2799     isaxxmlreader_putFeature,
2800     isaxxmlreader_getProperty,
2801     isaxxmlreader_putProperty,
2802     isaxxmlreader_getEntityResolver,
2803     isaxxmlreader_putEntityResolver,
2804     isaxxmlreader_getContentHandler,
2805     isaxxmlreader_putContentHandler,
2806     isaxxmlreader_getDTDHandler,
2807     isaxxmlreader_putDTDHandler,
2808     isaxxmlreader_getErrorHandler,
2809     isaxxmlreader_putErrorHandler,
2810     isaxxmlreader_getBaseURL,
2811     isaxxmlreader_putBaseURL,
2812     isaxxmlreader_getSecureBaseURL,
2813     isaxxmlreader_putSecureBaseURL,
2814     isaxxmlreader_parse,
2815     isaxxmlreader_parseURL
2816 };
2817
2818 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2819 {
2820     saxreader *reader;
2821
2822     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2823
2824     reader = heap_alloc( sizeof (*reader) );
2825     if( !reader )
2826         return E_OUTOFMEMORY;
2827
2828     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2829     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2830     reader->ref = 1;
2831     reader->contentHandler = NULL;
2832     reader->vbcontentHandler = NULL;
2833     reader->errorHandler = NULL;
2834     reader->vberrorHandler = NULL;
2835     reader->lexicalHandler = NULL;
2836     reader->vblexicalHandler = NULL;
2837     reader->declHandler = NULL;
2838     reader->vbdeclHandler = NULL;
2839     reader->isParsing = FALSE;
2840
2841     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2842     reader->sax.initialized = XML_SAX2_MAGIC;
2843     reader->sax.startDocument = libxmlStartDocument;
2844     reader->sax.endDocument = libxmlEndDocument;
2845     reader->sax.startElementNs = libxmlStartElementNS;
2846     reader->sax.endElementNs = libxmlEndElementNS;
2847     reader->sax.characters = libxmlCharacters;
2848     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2849     reader->sax.comment = libxmlComment;
2850     reader->sax.error = libxmlFatalError;
2851     reader->sax.fatalError = libxmlFatalError;
2852     reader->sax.cdataBlock = libxmlCDataBlock;
2853
2854     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2855
2856     TRACE("returning iface %p\n", *ppObj);
2857
2858     return S_OK;
2859 }
2860
2861 #else
2862
2863 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2864 {
2865     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2866             "libxml2 support was not present at compile time.\n");
2867     return E_NOTIMPL;
2868 }
2869
2870 #endif