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