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