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