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