msxml3: Correctly allocate namespaces stack in saxreader.
[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 "msxml2.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     LPWSTR str;
162     BSTR bstr;
163
164     if (!buf)
165         return NULL;
166
167     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
168     if(len != -1) dLen++;
169     str = heap_alloc(dLen * sizeof (WCHAR));
170     if (!str)
171         return NULL;
172     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, dLen);
173     if(len != -1) str[dLen-1] = '\0';
174     bstr = SysAllocString(str);
175     heap_free(str);
176
177     return bstr;
178 }
179
180 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
181 {
182     DWORD dLen, dLast;
183     LPWSTR str;
184     BSTR bstr;
185
186     if(!name) return NULL;
187
188     if(!prefix || *prefix=='\0')
189         return bstr_from_xmlChar(name);
190
191     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, NULL, 0)
192         + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, NULL, 0);
193     str = heap_alloc(dLen * sizeof(WCHAR));
194     if(!str)
195         return NULL;
196
197     dLast = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, str, dLen);
198     str[dLast-1] = ':';
199     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, &str[dLast], dLen-dLast);
200     bstr = SysAllocString(str);
201
202     heap_free(str);
203
204     return bstr;
205 }
206
207 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
208 {
209     xmlStopParser(This->pParserCtxt);
210     This->ret = hr;
211
212     if((This->vbInterface && This->saxreader->vberrorHandler)
213             || (!This->vbInterface && This->saxreader->errorHandler))
214     {
215         WCHAR msg[1024];
216         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
217                     NULL, hr, 0, msg, sizeof(msg), NULL))
218         {
219             FIXME("MSXML errors not yet supported.\n");
220             msg[0] = '\0';
221         }
222
223         if(This->vbInterface)
224         {
225             BSTR bstrMsg = SysAllocString(msg);
226             IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
227                     (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrMsg, hr);
228         }
229         else
230             ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
231                     (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr);
232     }
233 }
234
235 static void update_position(saxlocator *This, xmlChar *end)
236 {
237     if(This->lastCur == NULL)
238     {
239         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
240         This->realLine = 1;
241         This->realColumn = 1;
242     }
243     else if(This->lastCur < This->pParserCtxt->input->base)
244     {
245         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
246         This->realLine = 1;
247         This->realColumn = 1;
248     }
249
250     if(This->pParserCtxt->input->cur<This->lastCur)
251     {
252         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
253         This->realLine -= 1;
254         This->realColumn = 1;
255     }
256
257     if(!end) end = (xmlChar*)This->pParserCtxt->input->cur;
258
259     while(This->lastCur < end)
260     {
261         if(*(This->lastCur) == '\n')
262         {
263             This->realLine++;
264             This->realColumn = 1;
265         }
266         else if(*(This->lastCur) == '\r' &&
267                 (This->lastCur==This->pParserCtxt->input->end ||
268                  *(This->lastCur+1)!='\n'))
269         {
270             This->realLine++;
271             This->realColumn = 1;
272         }
273         else This->realColumn++;
274
275         This->lastCur++;
276
277         /* Count multibyte UTF8 encoded characters once */
278         while((*(This->lastCur)&0xC0) == 0x80) This->lastCur++;
279     }
280
281     This->line = This->realLine;
282     This->column = This->realColumn;
283 }
284
285 /*** IVBSAXAttributes interface ***/
286 /*** IUnknown methods ***/
287 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
288         IVBSAXAttributes* iface,
289         REFIID riid,
290         void **ppvObject)
291 {
292     saxattributes *This = impl_from_IVBSAXAttributes(iface);
293
294     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
295
296     *ppvObject = NULL;
297
298     if (IsEqualGUID(riid, &IID_IUnknown) ||
299             IsEqualGUID(riid, &IID_IDispatch) ||
300             IsEqualGUID(riid, &IID_IVBSAXAttributes))
301     {
302         *ppvObject = iface;
303     }
304     else
305     {
306         FIXME("interface %s not implemented\n", debugstr_guid(riid));
307         return E_NOINTERFACE;
308     }
309
310     IVBSAXAttributes_AddRef(iface);
311
312     return S_OK;
313 }
314
315 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
316 {
317     saxattributes *This = impl_from_IVBSAXAttributes(iface);
318     return ISAXAttributes_AddRef((ISAXAttributes*)&This->lpSAXAttributesVtbl);
319 }
320
321 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
322 {
323     saxattributes *This = impl_from_IVBSAXAttributes(iface);
324     return ISAXAttributes_Release((ISAXAttributes*)&This->lpSAXAttributesVtbl);
325 }
326
327 /*** IDispatch methods ***/
328 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
329 {
330     saxattributes *This = impl_from_IVBSAXAttributes( iface );
331
332     TRACE("(%p)->(%p)\n", This, pctinfo);
333
334     *pctinfo = 1;
335
336     return S_OK;
337 }
338
339 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
340     IVBSAXAttributes *iface,
341     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
342 {
343     saxattributes *This = impl_from_IVBSAXAttributes( iface );
344     HRESULT hr;
345
346     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
347
348     hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
349
350     return hr;
351 }
352
353 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
354     IVBSAXAttributes *iface,
355     REFIID riid,
356     LPOLESTR* rgszNames,
357     UINT cNames,
358     LCID lcid,
359     DISPID* rgDispId)
360 {
361     saxattributes *This = impl_from_IVBSAXAttributes( iface );
362     ITypeInfo *typeinfo;
363     HRESULT hr;
364
365     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
366           lcid, rgDispId);
367
368     if(!rgszNames || cNames == 0 || !rgDispId)
369         return E_INVALIDARG;
370
371     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
372     if(SUCCEEDED(hr))
373     {
374         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
375         ITypeInfo_Release(typeinfo);
376     }
377
378     return hr;
379 }
380
381 static HRESULT WINAPI ivbsaxattributes_Invoke(
382     IVBSAXAttributes *iface,
383     DISPID dispIdMember,
384     REFIID riid,
385     LCID lcid,
386     WORD wFlags,
387     DISPPARAMS* pDispParams,
388     VARIANT* pVarResult,
389     EXCEPINFO* pExcepInfo,
390     UINT* puArgErr)
391 {
392     saxattributes *This = impl_from_IVBSAXAttributes( iface );
393     ITypeInfo *typeinfo;
394     HRESULT hr;
395
396     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
397           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
398
399     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
400     if(SUCCEEDED(hr))
401     {
402         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXAttributesVtbl), dispIdMember, wFlags, pDispParams,
403                 pVarResult, pExcepInfo, puArgErr);
404         ITypeInfo_Release(typeinfo);
405     }
406
407     return hr;
408 }
409
410 /*** IVBSAXAttributes methods ***/
411 static HRESULT WINAPI ivbsaxattributes_get_length(
412         IVBSAXAttributes* iface,
413         int *nLength)
414 {
415     saxattributes *This = impl_from_IVBSAXAttributes( iface );
416     return ISAXAttributes_getLength(
417             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
418             nLength);
419 }
420
421 static HRESULT WINAPI ivbsaxattributes_getURI(
422         IVBSAXAttributes* iface,
423         int nIndex,
424         BSTR *uri)
425 {
426     int len;
427     saxattributes *This = impl_from_IVBSAXAttributes( iface );
428     return ISAXAttributes_getURI(
429             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
430             nIndex, (const WCHAR**)uri, &len);
431 }
432
433 static HRESULT WINAPI ivbsaxattributes_getLocalName(
434         IVBSAXAttributes* iface,
435         int nIndex,
436         BSTR *localName)
437 {
438     int len;
439     saxattributes *This = impl_from_IVBSAXAttributes( iface );
440     return ISAXAttributes_getLocalName(
441             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
442             nIndex, (const WCHAR**)localName, &len);
443 }
444
445 static HRESULT WINAPI ivbsaxattributes_getQName(
446         IVBSAXAttributes* iface,
447         int nIndex,
448         BSTR *QName)
449 {
450     int len;
451     saxattributes *This = impl_from_IVBSAXAttributes( iface );
452     return ISAXAttributes_getQName(
453             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
454             nIndex, (const WCHAR**)QName, &len);
455 }
456
457 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
458         IVBSAXAttributes* iface,
459         BSTR uri,
460         BSTR localName,
461         int *index)
462 {
463     saxattributes *This = impl_from_IVBSAXAttributes( iface );
464     return ISAXAttributes_getIndexFromName(
465             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
466             localName, SysStringLen(localName), index);
467 }
468
469 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
470         IVBSAXAttributes* iface,
471         BSTR QName,
472         int *index)
473 {
474     saxattributes *This = impl_from_IVBSAXAttributes( iface );
475     return ISAXAttributes_getIndexFromQName(
476             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
477             SysStringLen(QName), index);
478 }
479
480 static HRESULT WINAPI ivbsaxattributes_getType(
481         IVBSAXAttributes* iface,
482         int nIndex,
483         BSTR *type)
484 {
485     int len;
486     saxattributes *This = impl_from_IVBSAXAttributes( iface );
487     return ISAXAttributes_getType(
488             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
489             nIndex, (const WCHAR**)type, &len);
490 }
491
492 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
493         IVBSAXAttributes* iface,
494         BSTR uri,
495         BSTR localName,
496         BSTR *type)
497 {
498     int len;
499     saxattributes *This = impl_from_IVBSAXAttributes( iface );
500     return ISAXAttributes_getTypeFromName(
501             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
502             localName, SysStringLen(localName), (const WCHAR**)type, &len);
503 }
504
505 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
506         IVBSAXAttributes* iface,
507         BSTR QName,
508         BSTR *type)
509 {
510     int len;
511     saxattributes *This = impl_from_IVBSAXAttributes( iface );
512     return ISAXAttributes_getTypeFromQName(
513             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
514             SysStringLen(QName), (const WCHAR**)type, &len);
515 }
516
517 static HRESULT WINAPI ivbsaxattributes_getValue(
518         IVBSAXAttributes* iface,
519         int nIndex,
520         BSTR *value)
521 {
522     int len;
523     saxattributes *This = impl_from_IVBSAXAttributes( iface );
524     return ISAXAttributes_getValue(
525             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
526             nIndex, (const WCHAR**)value, &len);
527 }
528
529 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
530         IVBSAXAttributes* iface,
531         BSTR uri,
532         BSTR localName,
533         BSTR *value)
534 {
535     int len;
536     saxattributes *This = impl_from_IVBSAXAttributes( iface );
537     return ISAXAttributes_getValueFromName(
538             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
539             localName, SysStringLen(localName), (const WCHAR**)value, &len);
540 }
541
542 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
543         IVBSAXAttributes* iface,
544         BSTR QName,
545         BSTR *value)
546 {
547     int len;
548     saxattributes *This = impl_from_IVBSAXAttributes( iface );
549     return ISAXAttributes_getValueFromQName(
550             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
551             SysStringLen(QName), (const WCHAR**)value, &len);
552 }
553
554 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
555 {
556     ivbsaxattributes_QueryInterface,
557     ivbsaxattributes_AddRef,
558     ivbsaxattributes_Release,
559     ivbsaxattributes_GetTypeInfoCount,
560     ivbsaxattributes_GetTypeInfo,
561     ivbsaxattributes_GetIDsOfNames,
562     ivbsaxattributes_Invoke,
563     ivbsaxattributes_get_length,
564     ivbsaxattributes_getURI,
565     ivbsaxattributes_getLocalName,
566     ivbsaxattributes_getQName,
567     ivbsaxattributes_getIndexFromName,
568     ivbsaxattributes_getIndexFromQName,
569     ivbsaxattributes_getType,
570     ivbsaxattributes_getTypeFromName,
571     ivbsaxattributes_getTypeFromQName,
572     ivbsaxattributes_getValue,
573     ivbsaxattributes_getValueFromName,
574     ivbsaxattributes_getValueFromQName
575 };
576
577 /*** ISAXAttributes interface ***/
578 /*** IUnknown methods ***/
579 static HRESULT WINAPI isaxattributes_QueryInterface(
580         ISAXAttributes* iface,
581         REFIID riid,
582         void **ppvObject)
583 {
584     saxattributes *This = impl_from_ISAXAttributes(iface);
585
586     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
587
588     *ppvObject = NULL;
589
590     if (IsEqualGUID(riid, &IID_IUnknown) ||
591             IsEqualGUID(riid, &IID_ISAXAttributes))
592     {
593         *ppvObject = iface;
594     }
595     else
596     {
597         FIXME("interface %s not implemented\n", debugstr_guid(riid));
598         return E_NOINTERFACE;
599     }
600
601     ISAXAttributes_AddRef(iface);
602
603     return S_OK;
604 }
605
606 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
607 {
608     saxattributes *This = impl_from_ISAXAttributes(iface);
609     TRACE("%p\n", This);
610     return InterlockedIncrement(&This->ref);
611 }
612
613 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
614 {
615     saxattributes *This = impl_from_ISAXAttributes(iface);
616     LONG ref;
617
618     TRACE("%p\n", This);
619
620     ref = InterlockedDecrement(&This->ref);
621     if (ref==0)
622     {
623         int index;
624         for(index=0; index<This->nb_attributes; index++)
625         {
626             SysFreeString(This->szLocalname[index]);
627             SysFreeString(This->szURI[index]);
628             SysFreeString(This->szValue[index]);
629             SysFreeString(This->szQName[index]);
630         }
631
632         heap_free(This->szLocalname);
633         heap_free(This->szURI);
634         heap_free(This->szValue);
635         heap_free(This->szQName);
636
637         heap_free(This);
638     }
639
640     return ref;
641 }
642
643 /*** ISAXAttributes methods ***/
644 static HRESULT WINAPI isaxattributes_getLength(
645         ISAXAttributes* iface,
646         int *length)
647 {
648     saxattributes *This = impl_from_ISAXAttributes( iface );
649
650     *length = This->nb_attributes;
651     TRACE("Length set to %d\n", *length);
652     return S_OK;
653 }
654
655 static HRESULT WINAPI isaxattributes_getURI(
656         ISAXAttributes* iface,
657         int nIndex,
658         const WCHAR **pUrl,
659         int *pUriSize)
660 {
661     saxattributes *This = impl_from_ISAXAttributes( iface );
662     TRACE("(%p)->(%d)\n", This, nIndex);
663
664     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
665     if(!pUrl || !pUriSize) return E_POINTER;
666
667     *pUriSize = SysStringLen(This->szURI[nIndex]);
668     *pUrl = This->szURI[nIndex];
669
670     return S_OK;
671 }
672
673 static HRESULT WINAPI isaxattributes_getLocalName(
674         ISAXAttributes* iface,
675         int nIndex,
676         const WCHAR **pLocalName,
677         int *pLocalNameLength)
678 {
679     saxattributes *This = impl_from_ISAXAttributes( iface );
680     TRACE("(%p)->(%d)\n", This, nIndex);
681
682     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
683     if(!pLocalName || !pLocalNameLength) return E_POINTER;
684
685     *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]);
686     *pLocalName = This->szLocalname[nIndex];
687
688     return S_OK;
689 }
690
691 static HRESULT WINAPI isaxattributes_getQName(
692         ISAXAttributes* iface,
693         int nIndex,
694         const WCHAR **pQName,
695         int *pQNameLength)
696 {
697     saxattributes *This = impl_from_ISAXAttributes( iface );
698     TRACE("(%p)->(%d)\n", This, nIndex);
699
700     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
701     if(!pQName || !pQNameLength) return E_POINTER;
702
703     *pQNameLength = SysStringLen(This->szQName[nIndex]);
704     *pQName = This->szQName[nIndex];
705
706     return S_OK;
707 }
708
709 static HRESULT WINAPI isaxattributes_getName(
710         ISAXAttributes* iface,
711         int nIndex,
712         const WCHAR **pUri,
713         int *pUriLength,
714         const WCHAR **pLocalName,
715         int *pLocalNameSize,
716         const WCHAR **pQName,
717         int *pQNameLength)
718 {
719     saxattributes *This = impl_from_ISAXAttributes( iface );
720     TRACE("(%p)->(%d)\n", This, nIndex);
721
722     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
723     if(!pUri || !pUriLength || !pLocalName || !pLocalNameSize
724             || !pQName || !pQNameLength) return E_POINTER;
725
726     *pUriLength = SysStringLen(This->szURI[nIndex]);
727     *pUri = This->szURI[nIndex];
728     *pLocalNameSize = SysStringLen(This->szLocalname[nIndex]);
729     *pLocalName = This->szLocalname[nIndex];
730     *pQNameLength = SysStringLen(This->szQName[nIndex]);
731     *pQName = This->szQName[nIndex];
732
733     return S_OK;
734 }
735
736 static HRESULT WINAPI isaxattributes_getIndexFromName(
737         ISAXAttributes* iface,
738         const WCHAR *pUri,
739         int cUriLength,
740         const WCHAR *pLocalName,
741         int cocalNameLength,
742         int *index)
743 {
744     saxattributes *This = impl_from_ISAXAttributes( iface );
745     int i;
746     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
747             debugstr_w(pLocalName), cocalNameLength);
748
749     if(!pUri || !pLocalName || !index) return E_POINTER;
750
751     for(i=0; i<This->nb_attributes; i++)
752     {
753         if(cUriLength!=SysStringLen(This->szURI[i])
754                 || cocalNameLength!=SysStringLen(This->szLocalname[i]))
755             continue;
756         if(cUriLength && memcmp(pUri, This->szURI[i],
757                     sizeof(WCHAR)*cUriLength))
758             continue;
759         if(cocalNameLength && memcmp(pLocalName, This->szLocalname[i],
760                     sizeof(WCHAR)*cocalNameLength))
761             continue;
762
763         *index = i;
764         return S_OK;
765     }
766
767     return E_INVALIDARG;
768 }
769
770 static HRESULT WINAPI isaxattributes_getIndexFromQName(
771         ISAXAttributes* iface,
772         const WCHAR *pQName,
773         int nQNameLength,
774         int *index)
775 {
776     saxattributes *This = impl_from_ISAXAttributes( iface );
777     int i;
778     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
779
780     if(!pQName || !index) return E_POINTER;
781     if(!nQNameLength) return E_INVALIDARG;
782
783     for(i=0; i<This->nb_attributes; i++)
784     {
785         if(nQNameLength!=SysStringLen(This->szQName[i])) continue;
786         if(memcmp(pQName, This->szQName, sizeof(WCHAR)*nQNameLength)) continue;
787
788         *index = i;
789         return S_OK;
790     }
791
792     return E_INVALIDARG;
793 }
794
795 static HRESULT WINAPI isaxattributes_getType(
796         ISAXAttributes* iface,
797         int nIndex,
798         const WCHAR **pType,
799         int *pTypeLength)
800 {
801     saxattributes *This = impl_from_ISAXAttributes( iface );
802
803     FIXME("(%p)->(%d) stub\n", This, nIndex);
804     return E_NOTIMPL;
805 }
806
807 static HRESULT WINAPI isaxattributes_getTypeFromName(
808         ISAXAttributes* iface,
809         const WCHAR *pUri,
810         int nUri,
811         const WCHAR *pLocalName,
812         int nLocalName,
813         const WCHAR **pType,
814         int *nType)
815 {
816     saxattributes *This = impl_from_ISAXAttributes( iface );
817
818     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
819             debugstr_w(pLocalName), nLocalName);
820     return E_NOTIMPL;
821 }
822
823 static HRESULT WINAPI isaxattributes_getTypeFromQName(
824         ISAXAttributes* iface,
825         const WCHAR *pQName,
826         int nQName,
827         const WCHAR **pType,
828         int *nType)
829 {
830     saxattributes *This = impl_from_ISAXAttributes( iface );
831
832     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
833     return E_NOTIMPL;
834 }
835
836 static HRESULT WINAPI isaxattributes_getValue(
837         ISAXAttributes* iface,
838         int nIndex,
839         const WCHAR **pValue,
840         int *nValue)
841 {
842     saxattributes *This = impl_from_ISAXAttributes( iface );
843     TRACE("(%p)->(%d)\n", This, nIndex);
844
845     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
846     if(!pValue || !nValue) return E_POINTER;
847
848     *nValue = SysStringLen(This->szValue[nIndex]);
849     *pValue = This->szValue[nIndex];
850
851     return S_OK;
852 }
853
854 static HRESULT WINAPI isaxattributes_getValueFromName(
855         ISAXAttributes* iface,
856         const WCHAR *pUri,
857         int nUri,
858         const WCHAR *pLocalName,
859         int nLocalName,
860         const WCHAR **pValue,
861         int *nValue)
862 {
863     HRESULT hr;
864     int index;
865     saxattributes *This = impl_from_ISAXAttributes( iface );
866     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
867             debugstr_w(pLocalName), nLocalName);
868
869     hr = ISAXAttributes_getIndexFromName(iface,
870             pUri, nUri, pLocalName, nLocalName, &index);
871     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
872
873     return hr;
874 }
875
876 static HRESULT WINAPI isaxattributes_getValueFromQName(
877         ISAXAttributes* iface,
878         const WCHAR *pQName,
879         int nQName,
880         const WCHAR **pValue,
881         int *nValue)
882 {
883     HRESULT hr;
884     int index;
885     saxattributes *This = impl_from_ISAXAttributes( iface );
886     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
887
888     hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
889     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
890
891     return hr;
892 }
893
894 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
895 {
896     isaxattributes_QueryInterface,
897     isaxattributes_AddRef,
898     isaxattributes_Release,
899     isaxattributes_getLength,
900     isaxattributes_getURI,
901     isaxattributes_getLocalName,
902     isaxattributes_getQName,
903     isaxattributes_getName,
904     isaxattributes_getIndexFromName,
905     isaxattributes_getIndexFromQName,
906     isaxattributes_getType,
907     isaxattributes_getTypeFromName,
908     isaxattributes_getTypeFromQName,
909     isaxattributes_getValue,
910     isaxattributes_getValueFromName,
911     isaxattributes_getValueFromQName
912 };
913
914 static HRESULT SAXAttributes_create(saxattributes **attr,
915         int nb_namespaces, const xmlChar **xmlNamespaces,
916         int nb_attributes, const xmlChar **xmlAttributes)
917 {
918     saxattributes *attributes;
919     int index;
920     static const xmlChar xmlns[] = "xmlns";
921
922     attributes = heap_alloc(sizeof(*attributes));
923     if(!attributes)
924         return E_OUTOFMEMORY;
925
926     attributes->lpVBSAXAttributesVtbl = &ivbsaxattributes_vtbl;
927     attributes->lpSAXAttributesVtbl = &isaxattributes_vtbl;
928     attributes->ref = 1;
929
930     attributes->nb_attributes = nb_namespaces+nb_attributes;
931
932     attributes->szLocalname = heap_alloc(sizeof(BSTR)*attributes->nb_attributes);
933     attributes->szURI = heap_alloc(sizeof(BSTR)*attributes->nb_attributes);
934     attributes->szValue = heap_alloc(sizeof(BSTR)*attributes->nb_attributes);
935     attributes->szQName = heap_alloc(sizeof(BSTR)*attributes->nb_attributes);
936
937     if(!attributes->szLocalname || !attributes->szURI
938             || !attributes->szValue || !attributes->szQName)
939     {
940         heap_free(attributes->szLocalname);
941         heap_free(attributes->szURI);
942         heap_free(attributes->szValue);
943         heap_free(attributes->szQName);
944         heap_free(attributes);
945         return E_FAIL;
946     }
947
948     for(index=0; index<nb_namespaces; index++)
949     {
950         attributes->szLocalname[index] = SysAllocStringLen(NULL, 0);
951         attributes->szURI[index] = SysAllocStringLen(NULL, 0);
952         attributes->szValue[index] = bstr_from_xmlChar(xmlNamespaces[2*index+1]);
953         attributes->szQName[index] = QName_from_xmlChar(xmlns, xmlNamespaces[2*index]);
954     }
955
956     for(index=0; index<nb_attributes; index++)
957     {
958         attributes->szLocalname[nb_namespaces+index] =
959             bstr_from_xmlChar(xmlAttributes[index*5]);
960         attributes->szURI[nb_namespaces+index] =
961             bstr_from_xmlChar(xmlAttributes[index*5+2]);
962         attributes->szValue[nb_namespaces+index] =
963             bstr_from_xmlCharN(xmlAttributes[index*5+3],
964                     xmlAttributes[index*5+4]-xmlAttributes[index*5+3]);
965         attributes->szQName[nb_namespaces+index] =
966             QName_from_xmlChar(xmlAttributes[index*5+1], xmlAttributes[index*5]);
967     }
968
969     *attr = attributes;
970
971     TRACE("returning %p\n", *attr);
972
973     return S_OK;
974 }
975
976 /*** LibXML callbacks ***/
977 static void libxmlStartDocument(void *ctx)
978 {
979     saxlocator *This = ctx;
980     HRESULT hr;
981
982     if(has_content_handler(This))
983     {
984         if(This->vbInterface)
985             hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler);
986         else
987             hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
988
989         if(hr != S_OK)
990             format_error_message_from_id(This, hr);
991     }
992
993     update_position(This, NULL);
994 }
995
996 static void libxmlEndDocument(void *ctx)
997 {
998     saxlocator *This = ctx;
999     HRESULT hr;
1000
1001     This->column = 0;
1002     This->line = 0;
1003
1004     if(This->ret != S_OK) return;
1005
1006     if(has_content_handler(This))
1007     {
1008         if(This->vbInterface)
1009             hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler);
1010         else
1011             hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
1012
1013         if(hr != S_OK)
1014             format_error_message_from_id(This, hr);
1015     }
1016 }
1017
1018 static void libxmlStartElementNS(
1019         void *ctx,
1020         const xmlChar *localname,
1021         const xmlChar *prefix,
1022         const xmlChar *URI,
1023         int nb_namespaces,
1024         const xmlChar **namespaces,
1025         int nb_attributes,
1026         int nb_defaulted,
1027         const xmlChar **attributes)
1028 {
1029     BSTR NamespaceUri, LocalName, QName, Prefix, Uri;
1030     saxlocator *This = ctx;
1031     HRESULT hr;
1032     saxattributes *attr;
1033     int index;
1034
1035     if(*(This->pParserCtxt->input->cur) == '/')
1036         update_position(This, (xmlChar*)This->pParserCtxt->input->cur+2);
1037     else
1038         update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1);
1039
1040     hr = namespacePush(This, nb_namespaces);
1041     if(hr==S_OK && has_content_handler(This))
1042     {
1043         for(index=0; index<nb_namespaces; index++)
1044         {
1045             Prefix = bstr_from_xmlChar(namespaces[2*index]);
1046             Uri = bstr_from_xmlChar(namespaces[2*index+1]);
1047
1048             if(This->vbInterface)
1049                 hr = IVBSAXContentHandler_startPrefixMapping(
1050                         This->saxreader->vbcontentHandler,
1051                         &Prefix, &Uri);
1052             else
1053                 hr = ISAXContentHandler_startPrefixMapping(
1054                         This->saxreader->contentHandler,
1055                         Prefix, SysStringLen(Prefix),
1056                         Uri, SysStringLen(Uri));
1057
1058             SysFreeString(Prefix);
1059             SysFreeString(Uri);
1060
1061             if(hr != S_OK)
1062             {
1063                 format_error_message_from_id(This, hr);
1064                 return;
1065             }
1066         }
1067
1068         NamespaceUri = bstr_from_xmlChar(URI);
1069         LocalName = bstr_from_xmlChar(localname);
1070         QName = QName_from_xmlChar(prefix, localname);
1071
1072         hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes);
1073         if(hr == S_OK)
1074         {
1075             if(This->vbInterface)
1076                 hr = IVBSAXContentHandler_startElement(
1077                         This->saxreader->vbcontentHandler,
1078                         &NamespaceUri, &LocalName, &QName,
1079                         (IVBSAXAttributes*)&attr->lpVBSAXAttributesVtbl);
1080             else
1081                 hr = ISAXContentHandler_startElement(
1082                         This->saxreader->contentHandler,
1083                         NamespaceUri, SysStringLen(NamespaceUri),
1084                         LocalName, SysStringLen(LocalName),
1085                         QName, SysStringLen(QName),
1086                         (ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1087
1088             ISAXAttributes_Release((ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1089         }
1090
1091         SysFreeString(NamespaceUri);
1092         SysFreeString(LocalName);
1093         SysFreeString(QName);
1094     }
1095
1096     if(hr != S_OK)
1097         format_error_message_from_id(This, hr);
1098 }
1099
1100 static void libxmlEndElementNS(
1101         void *ctx,
1102         const xmlChar *localname,
1103         const xmlChar *prefix,
1104         const xmlChar *URI)
1105 {
1106     BSTR NamespaceUri, LocalName, QName, Prefix;
1107     saxlocator *This = ctx;
1108     HRESULT hr;
1109     xmlChar *end;
1110     int nsNr, index;
1111
1112     end = (xmlChar*)This->pParserCtxt->input->cur;
1113     if(*(end-1) != '>' || *(end-2) != '/')
1114         while(end-2>=This->pParserCtxt->input->base
1115                 && *(end-2)!='<' && *(end-1)!='/') end--;
1116
1117     update_position(This, end);
1118
1119     nsNr = namespacePop(This);
1120
1121     if(has_content_handler(This))
1122     {
1123         NamespaceUri = bstr_from_xmlChar(URI);
1124         LocalName = bstr_from_xmlChar(localname);
1125         QName = QName_from_xmlChar(prefix, localname);
1126
1127         if(This->vbInterface)
1128             hr = IVBSAXContentHandler_endElement(
1129                     This->saxreader->vbcontentHandler,
1130                     &NamespaceUri, &LocalName, &QName);
1131         else
1132             hr = ISAXContentHandler_endElement(
1133                     This->saxreader->contentHandler,
1134                     NamespaceUri, SysStringLen(NamespaceUri),
1135                     LocalName, SysStringLen(LocalName),
1136                     QName, SysStringLen(QName));
1137
1138         SysFreeString(NamespaceUri);
1139         SysFreeString(LocalName);
1140         SysFreeString(QName);
1141
1142         if(hr != S_OK)
1143         {
1144             format_error_message_from_id(This, hr);
1145             return;
1146         }
1147
1148         for(index=This->pParserCtxt->nsNr-2;
1149                 index>=This->pParserCtxt->nsNr-nsNr*2; index-=2)
1150         {
1151             Prefix = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]);
1152
1153             if(This->vbInterface)
1154                 hr = IVBSAXContentHandler_endPrefixMapping(
1155                         This->saxreader->vbcontentHandler, &Prefix);
1156             else
1157                 hr = ISAXContentHandler_endPrefixMapping(
1158                         This->saxreader->contentHandler,
1159                         Prefix, SysStringLen(Prefix));
1160
1161             SysFreeString(Prefix);
1162
1163             if(hr != S_OK)
1164             {
1165                 format_error_message_from_id(This, hr);
1166                 return;
1167             }
1168
1169         }
1170     }
1171
1172     update_position(This, NULL);
1173 }
1174
1175 static void libxmlCharacters(
1176         void *ctx,
1177         const xmlChar *ch,
1178         int len)
1179 {
1180     saxlocator *This = ctx;
1181     BSTR Chars;
1182     HRESULT hr;
1183     xmlChar *cur;
1184     xmlChar *end;
1185     BOOL lastEvent = FALSE;
1186
1187     if(!(has_content_handler(This))) return;
1188
1189     cur = (xmlChar*)ch;
1190     if(*(ch-1)=='\r') cur--;
1191     end = cur;
1192
1193     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1194         This->column++;
1195
1196     while(1)
1197     {
1198         while(end-ch<len && *end!='\r') end++;
1199         if(end-ch==len)
1200         {
1201             end--;
1202             lastEvent = TRUE;
1203         }
1204
1205         if(!lastEvent) *end = '\n';
1206
1207         Chars = bstr_from_xmlCharN(cur, end-cur+1);
1208         if(This->vbInterface)
1209             hr = IVBSAXContentHandler_characters(
1210                     This->saxreader->vbcontentHandler, &Chars);
1211         else
1212             hr = ISAXContentHandler_characters(
1213                     This->saxreader->contentHandler,
1214                     Chars, SysStringLen(Chars));
1215         SysFreeString(Chars);
1216
1217         if(hr != S_OK)
1218         {
1219             format_error_message_from_id(This, hr);
1220             return;
1221         }
1222
1223         This->column += end-cur+1;
1224
1225         if(lastEvent)
1226             break;
1227
1228         *end = '\r';
1229         end++;
1230         if(*end == '\n')
1231         {
1232             end++;
1233             This->column++;
1234         }
1235         cur = end;
1236
1237         if(end-ch == len) break;
1238     }
1239
1240     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1241         This->column = This->realColumn
1242             +This->pParserCtxt->input->cur-This->lastCur;
1243 }
1244
1245 static void libxmlSetDocumentLocator(
1246         void *ctx,
1247         xmlSAXLocatorPtr loc)
1248 {
1249     saxlocator *This = ctx;
1250     HRESULT hr;
1251
1252     if(This->vbInterface)
1253         hr = IVBSAXContentHandler_putref_documentLocator(
1254                 This->saxreader->vbcontentHandler,
1255                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1256     else
1257         hr = ISAXContentHandler_putDocumentLocator(
1258                 This->saxreader->contentHandler,
1259                 (ISAXLocator*)&This->lpSAXLocatorVtbl);
1260
1261     if(FAILED(hr))
1262         format_error_message_from_id(This, hr);
1263 }
1264
1265 static void libxmlComment(void *ctx, const xmlChar *value)
1266 {
1267     saxlocator *This = ctx;
1268     BSTR bValue;
1269     HRESULT hr;
1270     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur;
1271
1272     while(beg-4>=This->pParserCtxt->input->base
1273             && memcmp(beg-4, "<!--", sizeof(char[4]))) beg--;
1274     update_position(This, beg);
1275
1276     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1277     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1278
1279     bValue = bstr_from_xmlChar(value);
1280
1281     if(This->vbInterface)
1282         hr = IVBSAXLexicalHandler_comment(
1283                 This->saxreader->vblexicalHandler, &bValue);
1284     else
1285         hr = ISAXLexicalHandler_comment(
1286                 This->saxreader->lexicalHandler,
1287                 bValue, SysStringLen(bValue));
1288
1289     SysFreeString(bValue);
1290
1291     if(FAILED(hr))
1292         format_error_message_from_id(This, hr);
1293
1294     update_position(This, NULL);
1295 }
1296
1297 static void libxmlFatalError(void *ctx, const char *msg, ...)
1298 {
1299     saxlocator *This = ctx;
1300     char message[1024];
1301     WCHAR *wszError;
1302     DWORD len;
1303     va_list args;
1304
1305     if((This->vbInterface && !This->saxreader->vberrorHandler)
1306             || (!This->vbInterface && !This->saxreader->errorHandler))
1307     {
1308         xmlStopParser(This->pParserCtxt);
1309         This->ret = E_FAIL;
1310         return;
1311     }
1312
1313     FIXME("Error handling is not compatible.\n");
1314
1315     va_start(args, msg);
1316     vsprintf(message, msg, args);
1317     va_end(args);
1318
1319     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1320     wszError = heap_alloc(sizeof(WCHAR)*len);
1321     if(wszError)
1322         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, wszError, len);
1323
1324     if(This->vbInterface)
1325     {
1326         BSTR bstrError = SysAllocString(wszError);
1327         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1328                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1329     }
1330     else
1331         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1332                 (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
1333
1334     heap_free(wszError);
1335
1336     xmlStopParser(This->pParserCtxt);
1337     This->ret = E_FAIL;
1338 }
1339
1340 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1341 {
1342     saxlocator *This = ctx;
1343     HRESULT hr = S_OK;
1344     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1345     xmlChar *cur, *end;
1346     int realLen;
1347     BSTR Chars;
1348     BOOL lastEvent = FALSE, change;
1349
1350     while(beg-9>=This->pParserCtxt->input->base
1351             && memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) beg--;
1352     update_position(This, beg);
1353
1354     if(This->vbInterface && This->saxreader->vblexicalHandler)
1355         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1356     if(!This->vbInterface && This->saxreader->lexicalHandler)
1357         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1358
1359     if(FAILED(hr))
1360     {
1361         format_error_message_from_id(This, hr);
1362         return;
1363     }
1364
1365     realLen = This->pParserCtxt->input->cur-beg-3;
1366     cur = beg;
1367     end = beg;
1368
1369     while(1)
1370     {
1371         while(end-beg<realLen && *end!='\r') end++;
1372         if(end-beg==realLen)
1373         {
1374             end--;
1375             lastEvent = TRUE;
1376         }
1377         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1378             lastEvent = TRUE;
1379
1380         if(*end == '\r') change = TRUE;
1381         else change = FALSE;
1382
1383         if(change) *end = '\n';
1384
1385         if(has_content_handler(This))
1386         {
1387             Chars = bstr_from_xmlCharN(cur, end-cur+1);
1388             if(This->vbInterface)
1389                 hr = IVBSAXContentHandler_characters(
1390                         This->saxreader->vbcontentHandler, &Chars);
1391             else
1392                 hr = ISAXContentHandler_characters(
1393                         This->saxreader->contentHandler,
1394                         Chars, SysStringLen(Chars));
1395             SysFreeString(Chars);
1396         }
1397
1398         if(change) *end = '\r';
1399
1400         if(lastEvent)
1401             break;
1402
1403         This->column += end-cur+2;
1404         end += 2;
1405         cur = end;
1406     }
1407
1408     if(This->vbInterface && This->saxreader->vblexicalHandler)
1409         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1410     if(!This->vbInterface && This->saxreader->lexicalHandler)
1411         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1412
1413     if(FAILED(hr))
1414         format_error_message_from_id(This, hr);
1415
1416     This->column += 4+end-cur;
1417 }
1418
1419 /*** IVBSAXLocator interface ***/
1420 /*** IUnknown methods ***/
1421 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1422 {
1423     saxlocator *This = impl_from_IVBSAXLocator( iface );
1424
1425     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1426
1427     *ppvObject = NULL;
1428
1429     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1430             IsEqualGUID( riid, &IID_IDispatch) ||
1431             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1432     {
1433         *ppvObject = iface;
1434     }
1435     else
1436     {
1437         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1438         return E_NOINTERFACE;
1439     }
1440
1441     IVBSAXLocator_AddRef( iface );
1442
1443     return S_OK;
1444 }
1445
1446 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1447 {
1448     saxlocator *This = impl_from_IVBSAXLocator( iface );
1449     TRACE("%p\n", This );
1450     return InterlockedIncrement( &This->ref );
1451 }
1452
1453 static ULONG WINAPI ivbsaxlocator_Release(
1454         IVBSAXLocator* iface)
1455 {
1456     saxlocator *This = impl_from_IVBSAXLocator( iface );
1457     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1458 }
1459
1460 /*** IDispatch methods ***/
1461 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1462 {
1463     saxlocator *This = impl_from_IVBSAXLocator( iface );
1464
1465     TRACE("(%p)->(%p)\n", This, pctinfo);
1466
1467     *pctinfo = 1;
1468
1469     return S_OK;
1470 }
1471
1472 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1473     IVBSAXLocator *iface,
1474     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1475 {
1476     saxlocator *This = impl_from_IVBSAXLocator( iface );
1477     HRESULT hr;
1478
1479     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1480
1481     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1482
1483     return hr;
1484 }
1485
1486 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1487     IVBSAXLocator *iface,
1488     REFIID riid,
1489     LPOLESTR* rgszNames,
1490     UINT cNames,
1491     LCID lcid,
1492     DISPID* rgDispId)
1493 {
1494     saxlocator *This = impl_from_IVBSAXLocator( iface );
1495     ITypeInfo *typeinfo;
1496     HRESULT hr;
1497
1498     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1499           lcid, rgDispId);
1500
1501     if(!rgszNames || cNames == 0 || !rgDispId)
1502         return E_INVALIDARG;
1503
1504     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1505     if(SUCCEEDED(hr))
1506     {
1507         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1508         ITypeInfo_Release(typeinfo);
1509     }
1510
1511     return hr;
1512 }
1513
1514 static HRESULT WINAPI ivbsaxlocator_Invoke(
1515     IVBSAXLocator *iface,
1516     DISPID dispIdMember,
1517     REFIID riid,
1518     LCID lcid,
1519     WORD wFlags,
1520     DISPPARAMS* pDispParams,
1521     VARIANT* pVarResult,
1522     EXCEPINFO* pExcepInfo,
1523     UINT* puArgErr)
1524 {
1525     saxlocator *This = impl_from_IVBSAXLocator( iface );
1526     ITypeInfo *typeinfo;
1527     HRESULT hr;
1528
1529     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1530           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1531
1532     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1533     if(SUCCEEDED(hr))
1534     {
1535         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1536                 pVarResult, pExcepInfo, puArgErr);
1537         ITypeInfo_Release(typeinfo);
1538     }
1539
1540     return hr;
1541 }
1542
1543 /*** IVBSAXLocator methods ***/
1544 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1545         IVBSAXLocator* iface,
1546         int *pnColumn)
1547 {
1548     saxlocator *This = impl_from_IVBSAXLocator( iface );
1549     return ISAXLocator_getColumnNumber(
1550             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1551             pnColumn);
1552 }
1553
1554 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1555         IVBSAXLocator* iface,
1556         int *pnLine)
1557 {
1558     saxlocator *This = impl_from_IVBSAXLocator( iface );
1559     return ISAXLocator_getLineNumber(
1560             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1561             pnLine);
1562 }
1563
1564 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1565         IVBSAXLocator* iface,
1566         BSTR* publicId)
1567 {
1568     saxlocator *This = impl_from_IVBSAXLocator( iface );
1569     return ISAXLocator_getPublicId(
1570             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1571             (const WCHAR**)publicId);
1572 }
1573
1574 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1575         IVBSAXLocator* iface,
1576         BSTR* systemId)
1577 {
1578     saxlocator *This = impl_from_IVBSAXLocator( iface );
1579     return ISAXLocator_getSystemId(
1580             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1581             (const WCHAR**)systemId);
1582 }
1583
1584 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1585 {
1586     ivbsaxlocator_QueryInterface,
1587     ivbsaxlocator_AddRef,
1588     ivbsaxlocator_Release,
1589     ivbsaxlocator_GetTypeInfoCount,
1590     ivbsaxlocator_GetTypeInfo,
1591     ivbsaxlocator_GetIDsOfNames,
1592     ivbsaxlocator_Invoke,
1593     ivbsaxlocator_get_columnNumber,
1594     ivbsaxlocator_get_lineNumber,
1595     ivbsaxlocator_get_publicId,
1596     ivbsaxlocator_get_systemId
1597 };
1598
1599 /*** ISAXLocator interface ***/
1600 /*** IUnknown methods ***/
1601 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1602 {
1603     saxlocator *This = impl_from_ISAXLocator( iface );
1604
1605     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1606
1607     *ppvObject = NULL;
1608
1609     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1610             IsEqualGUID( riid, &IID_ISAXLocator ))
1611     {
1612         *ppvObject = iface;
1613     }
1614     else
1615     {
1616         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1617         return E_NOINTERFACE;
1618     }
1619
1620     ISAXLocator_AddRef( iface );
1621
1622     return S_OK;
1623 }
1624
1625 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1626 {
1627     saxlocator *This = impl_from_ISAXLocator( iface );
1628     TRACE("%p\n", This );
1629     return InterlockedIncrement( &This->ref );
1630 }
1631
1632 static ULONG WINAPI isaxlocator_Release(
1633         ISAXLocator* iface)
1634 {
1635     saxlocator *This = impl_from_ISAXLocator( iface );
1636     LONG ref;
1637
1638     TRACE("%p\n", This );
1639
1640     ref = InterlockedDecrement( &This->ref );
1641     if ( ref == 0 )
1642     {
1643         SysFreeString(This->publicId);
1644         SysFreeString(This->systemId);
1645         heap_free(This->nsStack);
1646
1647         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1648         heap_free( This );
1649     }
1650
1651     return ref;
1652 }
1653
1654 /*** ISAXLocator methods ***/
1655 static HRESULT WINAPI isaxlocator_getColumnNumber(
1656         ISAXLocator* iface,
1657         int *pnColumn)
1658 {
1659     saxlocator *This = impl_from_ISAXLocator( iface );
1660
1661     *pnColumn = This->column;
1662     return S_OK;
1663 }
1664
1665 static HRESULT WINAPI isaxlocator_getLineNumber(
1666         ISAXLocator* iface,
1667         int *pnLine)
1668 {
1669     saxlocator *This = impl_from_ISAXLocator( iface );
1670
1671     *pnLine = This->line;
1672     return S_OK;
1673 }
1674
1675 static HRESULT WINAPI isaxlocator_getPublicId(
1676         ISAXLocator* iface,
1677         const WCHAR ** ppwchPublicId)
1678 {
1679     BSTR publicId;
1680     saxlocator *This = impl_from_ISAXLocator( iface );
1681
1682     SysFreeString(This->publicId);
1683
1684     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1685     if(SysStringLen(publicId))
1686         This->publicId = (WCHAR*)&publicId;
1687     else
1688     {
1689         SysFreeString(publicId);
1690         This->publicId = NULL;
1691     }
1692
1693     *ppwchPublicId = This->publicId;
1694     return S_OK;
1695 }
1696
1697 static HRESULT WINAPI isaxlocator_getSystemId(
1698         ISAXLocator* iface,
1699         const WCHAR ** ppwchSystemId)
1700 {
1701     BSTR systemId;
1702     saxlocator *This = impl_from_ISAXLocator( iface );
1703
1704     SysFreeString(This->systemId);
1705
1706     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1707     if(SysStringLen(systemId))
1708         This->systemId = (WCHAR*)&systemId;
1709     else
1710     {
1711         SysFreeString(systemId);
1712         This->systemId = NULL;
1713     }
1714
1715     *ppwchSystemId = This->systemId;
1716     return S_OK;
1717 }
1718
1719 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1720 {
1721     isaxlocator_QueryInterface,
1722     isaxlocator_AddRef,
1723     isaxlocator_Release,
1724     isaxlocator_getColumnNumber,
1725     isaxlocator_getLineNumber,
1726     isaxlocator_getPublicId,
1727     isaxlocator_getSystemId
1728 };
1729
1730 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1731 {
1732     saxlocator *locator;
1733
1734     locator = heap_alloc( sizeof (*locator) );
1735     if( !locator )
1736         return E_OUTOFMEMORY;
1737
1738     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1739     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1740     locator->ref = 1;
1741     locator->vbInterface = vbInterface;
1742
1743     locator->saxreader = reader;
1744     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1745
1746     locator->pParserCtxt = NULL;
1747     locator->publicId = NULL;
1748     locator->systemId = NULL;
1749     locator->lastCur = NULL;
1750     locator->line = 0;
1751     locator->column = 0;
1752     locator->ret = S_OK;
1753     locator->nsStackSize = 8;
1754     locator->nsStackLast = 0;
1755     locator->nsStack = heap_alloc(sizeof(int)*locator->nsStackSize);
1756     if(!locator->nsStack)
1757     {
1758         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1759         heap_free(locator);
1760         return E_OUTOFMEMORY;
1761     }
1762
1763     *ppsaxlocator = locator;
1764
1765     TRACE("returning %p\n", *ppsaxlocator);
1766
1767     return S_OK;
1768 }
1769
1770 /*** SAXXMLReader internal functions ***/
1771 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1772 {
1773     saxlocator *locator;
1774     HRESULT hr;
1775
1776     hr = SAXLocator_create(This, &locator, vbInterface);
1777     if(FAILED(hr))
1778         return hr;
1779
1780     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1781     if(!locator->pParserCtxt)
1782     {
1783         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1784         return E_FAIL;
1785     }
1786
1787     xmlFree(locator->pParserCtxt->sax);
1788     locator->pParserCtxt->sax = &locator->saxreader->sax;
1789     locator->pParserCtxt->userData = locator;
1790
1791     This->isParsing = TRUE;
1792     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1793     else hr = locator->ret;
1794     This->isParsing = FALSE;
1795
1796     if(locator->pParserCtxt)
1797     {
1798         locator->pParserCtxt->sax = NULL;
1799         xmlFreeParserCtxt(locator->pParserCtxt);
1800         locator->pParserCtxt = NULL;
1801     }
1802
1803     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1804     return hr;
1805 }
1806
1807 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1808 {
1809     saxlocator *locator;
1810     HRESULT hr;
1811     ULONG dataRead;
1812     char data[1024];
1813
1814     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1815     if(hr != S_OK)
1816         return hr;
1817
1818     hr = SAXLocator_create(This, &locator, vbInterface);
1819     if(FAILED(hr))
1820         return hr;
1821
1822     locator->pParserCtxt = xmlCreatePushParserCtxt(
1823             &locator->saxreader->sax, locator,
1824             data, dataRead, NULL);
1825     if(!locator->pParserCtxt)
1826     {
1827         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1828         return E_FAIL;
1829     }
1830
1831     This->isParsing = TRUE;
1832     while(1)
1833     {
1834         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1835         if(hr != S_OK)
1836             break;
1837
1838         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1839         else hr = locator->ret;
1840
1841         if(hr != S_OK) break;
1842
1843         if(dataRead != sizeof(data))
1844         {
1845             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1846             else hr = locator->ret;
1847
1848             break;
1849         }
1850     }
1851     This->isParsing = FALSE;
1852
1853     xmlFreeParserCtxt(locator->pParserCtxt);
1854     locator->pParserCtxt = NULL;
1855     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1856     return hr;
1857 }
1858
1859 static HRESULT internal_getEntityResolver(
1860         saxreader *This,
1861         void *pEntityResolver,
1862         BOOL vbInterface)
1863 {
1864     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1865     return E_NOTIMPL;
1866 }
1867
1868 static HRESULT internal_putEntityResolver(
1869         saxreader *This,
1870         void *pEntityResolver,
1871         BOOL vbInterface)
1872 {
1873     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1874     return E_NOTIMPL;
1875 }
1876
1877 static HRESULT internal_getContentHandler(
1878         saxreader* This,
1879         void *pContentHandler,
1880         BOOL vbInterface)
1881 {
1882     TRACE("(%p)->(%p)\n", This, pContentHandler);
1883     if(pContentHandler == NULL)
1884         return E_POINTER;
1885     if((vbInterface && This->vbcontentHandler)
1886             || (!vbInterface && This->contentHandler))
1887     {
1888         if(vbInterface)
1889             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1890         else
1891             ISAXContentHandler_AddRef(This->contentHandler);
1892     }
1893     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1894         This->vbcontentHandler;
1895     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1896
1897     return S_OK;
1898 }
1899
1900 static HRESULT internal_putContentHandler(
1901         saxreader* This,
1902         void *contentHandler,
1903         BOOL vbInterface)
1904 {
1905     TRACE("(%p)->(%p)\n", This, contentHandler);
1906     if(contentHandler)
1907     {
1908         if(vbInterface)
1909             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1910         else
1911             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1912     }
1913     if((vbInterface && This->vbcontentHandler)
1914             || (!vbInterface && This->contentHandler))
1915     {
1916         if(vbInterface)
1917             IVBSAXContentHandler_Release(This->vbcontentHandler);
1918         else
1919             ISAXContentHandler_Release(This->contentHandler);
1920     }
1921     if(vbInterface)
1922         This->vbcontentHandler = contentHandler;
1923     else
1924         This->contentHandler = contentHandler;
1925
1926     return S_OK;
1927 }
1928
1929 static HRESULT internal_getDTDHandler(
1930         saxreader* This,
1931         void *pDTDHandler,
1932         BOOL vbInterface)
1933 {
1934     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1935     return E_NOTIMPL;
1936 }
1937
1938 static HRESULT internal_putDTDHandler(
1939         saxreader* This,
1940         void *pDTDHandler,
1941         BOOL vbInterface)
1942 {
1943     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1944     return E_NOTIMPL;
1945 }
1946
1947 static HRESULT internal_getErrorHandler(
1948         saxreader* This,
1949         void *pErrorHandler,
1950         BOOL vbInterface)
1951 {
1952     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1953     if(pErrorHandler == NULL)
1954         return E_POINTER;
1955
1956     if(vbInterface && This->vberrorHandler)
1957         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1958     else if(!vbInterface && This->errorHandler)
1959         ISAXErrorHandler_AddRef(This->errorHandler);
1960
1961     if(vbInterface)
1962         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1963     else
1964         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1965
1966     return S_OK;
1967
1968 }
1969
1970 static HRESULT internal_putErrorHandler(
1971         saxreader* This,
1972         void *errorHandler,
1973         BOOL vbInterface)
1974 {
1975     TRACE("(%p)->(%p)\n", This, errorHandler);
1976     if(errorHandler)
1977     {
1978         if(vbInterface)
1979             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1980         else
1981             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1982     }
1983
1984     if(vbInterface && This->vberrorHandler)
1985         IVBSAXErrorHandler_Release(This->vberrorHandler);
1986     else if(!vbInterface && This->errorHandler)
1987         ISAXErrorHandler_Release(This->errorHandler);
1988
1989     if(vbInterface)
1990         This->vberrorHandler = errorHandler;
1991     else
1992         This->errorHandler = errorHandler;
1993
1994     return S_OK;
1995
1996 }
1997
1998 static HRESULT internal_parse(
1999         saxreader* This,
2000         VARIANT varInput,
2001         BOOL vbInterface)
2002 {
2003     HRESULT hr;
2004
2005     TRACE("(%p)\n", This);
2006
2007     hr = S_OK;
2008     switch(V_VT(&varInput))
2009     {
2010         case VT_BSTR:
2011             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2012                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2013             break;
2014         case VT_ARRAY|VT_UI1: {
2015             void *pSAData;
2016             LONG lBound, uBound;
2017             ULONG dataRead;
2018
2019             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2020             if(hr != S_OK) break;
2021             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2022             if(hr != S_OK) break;
2023             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2024             hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2025             if(hr != S_OK) break;
2026             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2027             SafeArrayUnaccessData(V_ARRAY(&varInput));
2028             break;
2029         }
2030         case VT_UNKNOWN:
2031         case VT_DISPATCH: {
2032             IPersistStream *persistStream;
2033             IStream *stream = NULL;
2034             IXMLDOMDocument *xmlDoc;
2035
2036             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2037                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2038             {
2039                 BSTR bstrData;
2040
2041                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2042                 hr = internal_parseBuffer(This, (const char*)bstrData,
2043                         SysStringByteLen(bstrData), vbInterface);
2044                 IXMLDOMDocument_Release(xmlDoc);
2045                 SysFreeString(bstrData);
2046                 break;
2047             }
2048             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2049                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2050             {
2051                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2052                 IPersistStream_Release(persistStream);
2053                 if(hr != S_OK) break;
2054             }
2055             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2056                         &IID_IStream, (void**)&stream) == S_OK)
2057             {
2058                 hr = internal_parseStream(This, stream, vbInterface);
2059                 IStream_Release(stream);
2060                 break;
2061             }
2062         }
2063         default:
2064             WARN("vt %d not implemented\n", V_VT(&varInput));
2065             hr = E_INVALIDARG;
2066     }
2067
2068     return hr;
2069 }
2070
2071 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2072 {
2073     saxreader *This = obj;
2074
2075     return internal_parseBuffer(This, ptr, len, TRUE);
2076 }
2077
2078 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2079 {
2080     saxreader *This = obj;
2081
2082     return internal_parseBuffer(This, ptr, len, FALSE);
2083 }
2084
2085 static HRESULT internal_parseURL(
2086         saxreader* This,
2087         const WCHAR *url,
2088         BOOL vbInterface)
2089 {
2090     bsc_t *bsc;
2091     HRESULT hr;
2092
2093     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2094
2095     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2096     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2097
2098     if(FAILED(hr))
2099         return hr;
2100
2101     detach_bsc(bsc);
2102
2103     return S_OK;
2104 }
2105
2106 static HRESULT internal_putProperty(
2107     saxreader* This,
2108     const WCHAR *pProp,
2109     VARIANT value,
2110     BOOL vbInterface)
2111 {
2112     static const WCHAR wszCharset[] = {
2113         'c','h','a','r','s','e','t',0
2114     };
2115     static const WCHAR wszDeclarationHandler[] = {
2116         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2117         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2118         'd','e','c','l','a','r','a','t','i','o','n',
2119         '-','h','a','n','d','l','e','r',0
2120     };
2121     static const WCHAR wszDomNode[] = {
2122         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2123         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2124         'd','o','m','-','n','o','d','e',0
2125     };
2126     static const WCHAR wszInputSource[] = {
2127         'i','n','p','u','t','-','s','o','u','r','c','e',0
2128     };
2129     static const WCHAR wszLexicalHandler[] = {
2130         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2131         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2132         'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
2133     };
2134     static const WCHAR wszMaxElementDepth[] = {
2135         'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
2136     };
2137     static const WCHAR wszMaxXMLSize[] = {
2138         'm','a','x','-','x','m','l','-','s','i','z','e',0
2139     };
2140     static const WCHAR wszSchemaDeclarationHandler[] = {
2141         's','c','h','e','m','a','-',
2142         'd','e','c','l','a','r','a','t','i','o','n','-',
2143         'h','a','n','d','l','e','r',0
2144     };
2145     static const WCHAR wszXMLDeclEncoding[] = {
2146         'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
2147     };
2148     static const WCHAR wszXMLDeclStandalone[] = {
2149         'x','m','l','d','e','c','l',
2150         '-','s','t','a','n','d','a','l','o','n','e',0
2151     };
2152     static const WCHAR wszXMLDeclVersion[] = {
2153         'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
2154     };
2155
2156     FIXME("(%p)->(%s): semi-stub\n", This, debugstr_w(pProp));
2157
2158     if(!memcmp(pProp, wszCharset, sizeof(wszCharset)))
2159         return E_NOTIMPL;
2160
2161     if(!memcmp(pProp, wszDeclarationHandler, sizeof(wszDeclarationHandler)))
2162     {
2163         if(This->isParsing) return E_FAIL;
2164
2165         if(V_UNKNOWN(&value))
2166         {
2167             if(vbInterface)
2168                 IVBSAXDeclHandler_AddRef((IVBSAXDeclHandler*)V_UNKNOWN(&value));
2169             else
2170                 ISAXDeclHandler_AddRef((ISAXDeclHandler*)V_UNKNOWN(&value));
2171         }
2172         if((vbInterface && This->vbdeclHandler)
2173                 || (!vbInterface && This->declHandler))
2174         {
2175             if(vbInterface)
2176                 IVBSAXDeclHandler_Release(This->vbdeclHandler);
2177             else
2178                 ISAXDeclHandler_Release(This->declHandler);
2179         }
2180         if(vbInterface)
2181             This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2182         else
2183             This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2184         return S_OK;
2185     }
2186
2187     if(!memcmp(pProp, wszDomNode, sizeof(wszDomNode)))
2188         return E_FAIL;
2189
2190     if(!memcmp(pProp, wszInputSource, sizeof(wszInputSource)))
2191         return E_NOTIMPL;
2192
2193     if(!memcmp(pProp, wszLexicalHandler, sizeof(wszLexicalHandler)))
2194     {
2195         if(This->isParsing) return E_FAIL;
2196
2197         if(V_UNKNOWN(&value))
2198         {
2199             if(vbInterface)
2200                 IVBSAXLexicalHandler_AddRef(
2201                         (IVBSAXLexicalHandler*)V_UNKNOWN(&value));
2202             else
2203                 ISAXLexicalHandler_AddRef(
2204                         (ISAXLexicalHandler*)V_UNKNOWN(&value));
2205         }
2206         if((vbInterface && This->vblexicalHandler)
2207                 || (!vbInterface && This->lexicalHandler))
2208         {
2209             if(vbInterface)
2210                 IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2211             else
2212                 ISAXLexicalHandler_Release(This->lexicalHandler);
2213         }
2214         if(vbInterface)
2215             This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2216         else
2217             This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2218         return S_OK;
2219     }
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