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