msxml3: Use existing helpers for heap allocations.
[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, 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)!='<' && *(end-1)!='/') end--;
1115
1116     update_position(This, end);
1117
1118     nsNr = namespacePop(This);
1119
1120     if(has_content_handler(This))
1121     {
1122         NamespaceUri = bstr_from_xmlChar(URI);
1123         LocalName = bstr_from_xmlChar(localname);
1124         QName = QName_from_xmlChar(prefix, localname);
1125
1126         if(This->vbInterface)
1127             hr = IVBSAXContentHandler_endElement(
1128                     This->saxreader->vbcontentHandler,
1129                     &NamespaceUri, &LocalName, &QName);
1130         else
1131             hr = ISAXContentHandler_endElement(
1132                     This->saxreader->contentHandler,
1133                     NamespaceUri, SysStringLen(NamespaceUri),
1134                     LocalName, SysStringLen(LocalName),
1135                     QName, SysStringLen(QName));
1136
1137         SysFreeString(NamespaceUri);
1138         SysFreeString(LocalName);
1139         SysFreeString(QName);
1140
1141         if(hr != S_OK)
1142         {
1143             format_error_message_from_id(This, hr);
1144             return;
1145         }
1146
1147         for(index=This->pParserCtxt->nsNr-2;
1148                 index>=This->pParserCtxt->nsNr-nsNr*2; index-=2)
1149         {
1150             Prefix = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]);
1151
1152             if(This->vbInterface)
1153                 hr = IVBSAXContentHandler_endPrefixMapping(
1154                         This->saxreader->vbcontentHandler, &Prefix);
1155             else
1156                 hr = ISAXContentHandler_endPrefixMapping(
1157                         This->saxreader->contentHandler,
1158                         Prefix, SysStringLen(Prefix));
1159
1160             SysFreeString(Prefix);
1161
1162             if(hr != S_OK)
1163             {
1164                 format_error_message_from_id(This, hr);
1165                 return;
1166             }
1167
1168         }
1169     }
1170
1171     update_position(This, NULL);
1172 }
1173
1174 static void libxmlCharacters(
1175         void *ctx,
1176         const xmlChar *ch,
1177         int len)
1178 {
1179     saxlocator *This = ctx;
1180     BSTR Chars;
1181     HRESULT hr;
1182     xmlChar *cur;
1183     xmlChar *end;
1184     BOOL lastEvent = FALSE;
1185
1186     if(!(has_content_handler(This))) return;
1187
1188     cur = (xmlChar*)ch;
1189     if(*(ch-1)=='\r') cur--;
1190     end = cur;
1191
1192     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1193         This->column++;
1194
1195     while(1)
1196     {
1197         while(end-ch<len && *end!='\r') end++;
1198         if(end-ch==len)
1199         {
1200             end--;
1201             lastEvent = TRUE;
1202         }
1203
1204         if(!lastEvent) *end = '\n';
1205
1206         Chars = bstr_from_xmlCharN(cur, end-cur+1);
1207         if(This->vbInterface)
1208             hr = IVBSAXContentHandler_characters(
1209                     This->saxreader->vbcontentHandler, &Chars);
1210         else
1211             hr = ISAXContentHandler_characters(
1212                     This->saxreader->contentHandler,
1213                     Chars, SysStringLen(Chars));
1214         SysFreeString(Chars);
1215
1216         if(hr != S_OK)
1217         {
1218             format_error_message_from_id(This, hr);
1219             return;
1220         }
1221
1222         This->column += end-cur+1;
1223
1224         if(lastEvent)
1225             break;
1226
1227         *end = '\r';
1228         end++;
1229         if(*end == '\n')
1230         {
1231             end++;
1232             This->column++;
1233         }
1234         cur = end;
1235
1236         if(end-ch == len) break;
1237     }
1238
1239     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1240         This->column = This->realColumn
1241             +This->pParserCtxt->input->cur-This->lastCur;
1242 }
1243
1244 static void libxmlSetDocumentLocator(
1245         void *ctx,
1246         xmlSAXLocatorPtr loc)
1247 {
1248     saxlocator *This = ctx;
1249     HRESULT hr;
1250
1251     if(This->vbInterface)
1252         hr = IVBSAXContentHandler_putref_documentLocator(
1253                 This->saxreader->vbcontentHandler,
1254                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1255     else
1256         hr = ISAXContentHandler_putDocumentLocator(
1257                 This->saxreader->contentHandler,
1258                 (ISAXLocator*)&This->lpSAXLocatorVtbl);
1259
1260     if(FAILED(hr))
1261         format_error_message_from_id(This, hr);
1262 }
1263
1264 static void libxmlComment(void *ctx, const xmlChar *value)
1265 {
1266     saxlocator *This = ctx;
1267     BSTR bValue;
1268     HRESULT hr;
1269     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur;
1270
1271     while(memcmp(beg-4, "<!--", sizeof(char[4]))) beg--;
1272     update_position(This, beg);
1273
1274     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1275     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1276
1277     bValue = bstr_from_xmlChar(value);
1278
1279     if(This->vbInterface)
1280         hr = IVBSAXLexicalHandler_comment(
1281                 This->saxreader->vblexicalHandler, &bValue);
1282     else
1283         hr = ISAXLexicalHandler_comment(
1284                 This->saxreader->lexicalHandler,
1285                 bValue, SysStringLen(bValue));
1286
1287     SysFreeString(bValue);
1288
1289     if(FAILED(hr))
1290         format_error_message_from_id(This, hr);
1291
1292     update_position(This, NULL);
1293 }
1294
1295 static void libxmlFatalError(void *ctx, const char *msg, ...)
1296 {
1297     saxlocator *This = ctx;
1298     char message[1024];
1299     WCHAR *wszError;
1300     DWORD len;
1301     va_list args;
1302
1303     if((This->vbInterface && !This->saxreader->vberrorHandler)
1304             || (!This->vbInterface && !This->saxreader->errorHandler))
1305     {
1306         xmlStopParser(This->pParserCtxt);
1307         This->ret = E_FAIL;
1308         return;
1309     }
1310
1311     FIXME("Error handling is not compatible.\n");
1312
1313     va_start(args, msg);
1314     vsprintf(message, msg, args);
1315     va_end(args);
1316
1317     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1318     wszError = heap_alloc(sizeof(WCHAR)*len);
1319     if(wszError)
1320         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, wszError, len);
1321
1322     if(This->vbInterface)
1323     {
1324         BSTR bstrError = SysAllocString(wszError);
1325         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1326                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1327     }
1328     else
1329         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1330                 (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
1331
1332     heap_free(wszError);
1333
1334     xmlStopParser(This->pParserCtxt);
1335     This->ret = E_FAIL;
1336 }
1337
1338 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1339 {
1340     saxlocator *This = ctx;
1341     HRESULT hr = S_OK;
1342     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1343     xmlChar *cur, *end;
1344     int realLen;
1345     BSTR Chars;
1346     BOOL lastEvent = FALSE, change;
1347
1348     while(memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) beg--;
1349     update_position(This, beg);
1350
1351     if(This->vbInterface && This->saxreader->vblexicalHandler)
1352         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1353     if(!This->vbInterface && This->saxreader->lexicalHandler)
1354         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1355
1356     if(FAILED(hr))
1357     {
1358         format_error_message_from_id(This, hr);
1359         return;
1360     }
1361
1362     realLen = This->pParserCtxt->input->cur-beg-3;
1363     cur = beg;
1364     end = beg;
1365
1366     while(1)
1367     {
1368         while(end-beg<realLen && *end!='\r') end++;
1369         if(end-beg==realLen)
1370         {
1371             end--;
1372             lastEvent = TRUE;
1373         }
1374         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1375             lastEvent = TRUE;
1376
1377         if(*end == '\r') change = TRUE;
1378         else change = FALSE;
1379
1380         if(change) *end = '\n';
1381
1382         if(has_content_handler(This))
1383         {
1384             Chars = bstr_from_xmlCharN(cur, end-cur+1);
1385             if(This->vbInterface)
1386                 hr = IVBSAXContentHandler_characters(
1387                         This->saxreader->vbcontentHandler, &Chars);
1388             else
1389                 hr = ISAXContentHandler_characters(
1390                         This->saxreader->contentHandler,
1391                         Chars, SysStringLen(Chars));
1392             SysFreeString(Chars);
1393         }
1394
1395         if(change) *end = '\r';
1396
1397         if(lastEvent)
1398             break;
1399
1400         This->column += end-cur+2;
1401         end += 2;
1402         cur = end;
1403     }
1404
1405     if(This->vbInterface && This->saxreader->vblexicalHandler)
1406         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1407     if(!This->vbInterface && This->saxreader->lexicalHandler)
1408         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1409
1410     if(FAILED(hr))
1411         format_error_message_from_id(This, hr);
1412
1413     This->column += 4+end-cur;
1414 }
1415
1416 /*** IVBSAXLocator interface ***/
1417 /*** IUnknown methods ***/
1418 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1419 {
1420     saxlocator *This = impl_from_IVBSAXLocator( iface );
1421
1422     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1423
1424     *ppvObject = NULL;
1425
1426     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1427             IsEqualGUID( riid, &IID_IDispatch) ||
1428             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1429     {
1430         *ppvObject = iface;
1431     }
1432     else
1433     {
1434         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1435         return E_NOINTERFACE;
1436     }
1437
1438     IVBSAXLocator_AddRef( iface );
1439
1440     return S_OK;
1441 }
1442
1443 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1444 {
1445     saxlocator *This = impl_from_IVBSAXLocator( iface );
1446     TRACE("%p\n", This );
1447     return InterlockedIncrement( &This->ref );
1448 }
1449
1450 static ULONG WINAPI ivbsaxlocator_Release(
1451         IVBSAXLocator* iface)
1452 {
1453     saxlocator *This = impl_from_IVBSAXLocator( iface );
1454     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1455 }
1456
1457 /*** IDispatch methods ***/
1458 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1459 {
1460     saxlocator *This = impl_from_IVBSAXLocator( iface );
1461
1462     TRACE("(%p)->(%p)\n", This, pctinfo);
1463
1464     *pctinfo = 1;
1465
1466     return S_OK;
1467 }
1468
1469 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1470     IVBSAXLocator *iface,
1471     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1472 {
1473     saxlocator *This = impl_from_IVBSAXLocator( iface );
1474     HRESULT hr;
1475
1476     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1477
1478     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1479
1480     return hr;
1481 }
1482
1483 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1484     IVBSAXLocator *iface,
1485     REFIID riid,
1486     LPOLESTR* rgszNames,
1487     UINT cNames,
1488     LCID lcid,
1489     DISPID* rgDispId)
1490 {
1491     saxlocator *This = impl_from_IVBSAXLocator( iface );
1492     ITypeInfo *typeinfo;
1493     HRESULT hr;
1494
1495     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1496           lcid, rgDispId);
1497
1498     if(!rgszNames || cNames == 0 || !rgDispId)
1499         return E_INVALIDARG;
1500
1501     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1502     if(SUCCEEDED(hr))
1503     {
1504         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1505         ITypeInfo_Release(typeinfo);
1506     }
1507
1508     return hr;
1509 }
1510
1511 static HRESULT WINAPI ivbsaxlocator_Invoke(
1512     IVBSAXLocator *iface,
1513     DISPID dispIdMember,
1514     REFIID riid,
1515     LCID lcid,
1516     WORD wFlags,
1517     DISPPARAMS* pDispParams,
1518     VARIANT* pVarResult,
1519     EXCEPINFO* pExcepInfo,
1520     UINT* puArgErr)
1521 {
1522     saxlocator *This = impl_from_IVBSAXLocator( iface );
1523     ITypeInfo *typeinfo;
1524     HRESULT hr;
1525
1526     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1527           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1528
1529     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1530     if(SUCCEEDED(hr))
1531     {
1532         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1533                 pVarResult, pExcepInfo, puArgErr);
1534         ITypeInfo_Release(typeinfo);
1535     }
1536
1537     return hr;
1538 }
1539
1540 /*** IVBSAXLocator methods ***/
1541 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1542         IVBSAXLocator* iface,
1543         int *pnColumn)
1544 {
1545     saxlocator *This = impl_from_IVBSAXLocator( iface );
1546     return ISAXLocator_getColumnNumber(
1547             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1548             pnColumn);
1549 }
1550
1551 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1552         IVBSAXLocator* iface,
1553         int *pnLine)
1554 {
1555     saxlocator *This = impl_from_IVBSAXLocator( iface );
1556     return ISAXLocator_getLineNumber(
1557             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1558             pnLine);
1559 }
1560
1561 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1562         IVBSAXLocator* iface,
1563         BSTR* publicId)
1564 {
1565     saxlocator *This = impl_from_IVBSAXLocator( iface );
1566     return ISAXLocator_getPublicId(
1567             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1568             (const WCHAR**)publicId);
1569 }
1570
1571 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1572         IVBSAXLocator* iface,
1573         BSTR* systemId)
1574 {
1575     saxlocator *This = impl_from_IVBSAXLocator( iface );
1576     return ISAXLocator_getSystemId(
1577             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1578             (const WCHAR**)systemId);
1579 }
1580
1581 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1582 {
1583     ivbsaxlocator_QueryInterface,
1584     ivbsaxlocator_AddRef,
1585     ivbsaxlocator_Release,
1586     ivbsaxlocator_GetTypeInfoCount,
1587     ivbsaxlocator_GetTypeInfo,
1588     ivbsaxlocator_GetIDsOfNames,
1589     ivbsaxlocator_Invoke,
1590     ivbsaxlocator_get_columnNumber,
1591     ivbsaxlocator_get_lineNumber,
1592     ivbsaxlocator_get_publicId,
1593     ivbsaxlocator_get_systemId
1594 };
1595
1596 /*** ISAXLocator interface ***/
1597 /*** IUnknown methods ***/
1598 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1599 {
1600     saxlocator *This = impl_from_ISAXLocator( iface );
1601
1602     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1603
1604     *ppvObject = NULL;
1605
1606     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1607             IsEqualGUID( riid, &IID_ISAXLocator ))
1608     {
1609         *ppvObject = iface;
1610     }
1611     else
1612     {
1613         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1614         return E_NOINTERFACE;
1615     }
1616
1617     ISAXLocator_AddRef( iface );
1618
1619     return S_OK;
1620 }
1621
1622 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1623 {
1624     saxlocator *This = impl_from_ISAXLocator( iface );
1625     TRACE("%p\n", This );
1626     return InterlockedIncrement( &This->ref );
1627 }
1628
1629 static ULONG WINAPI isaxlocator_Release(
1630         ISAXLocator* iface)
1631 {
1632     saxlocator *This = impl_from_ISAXLocator( iface );
1633     LONG ref;
1634
1635     TRACE("%p\n", This );
1636
1637     ref = InterlockedDecrement( &This->ref );
1638     if ( ref == 0 )
1639     {
1640         SysFreeString(This->publicId);
1641         SysFreeString(This->systemId);
1642         heap_free(This->nsStack);
1643
1644         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1645         heap_free( This );
1646     }
1647
1648     return ref;
1649 }
1650
1651 /*** ISAXLocator methods ***/
1652 static HRESULT WINAPI isaxlocator_getColumnNumber(
1653         ISAXLocator* iface,
1654         int *pnColumn)
1655 {
1656     saxlocator *This = impl_from_ISAXLocator( iface );
1657
1658     *pnColumn = This->column;
1659     return S_OK;
1660 }
1661
1662 static HRESULT WINAPI isaxlocator_getLineNumber(
1663         ISAXLocator* iface,
1664         int *pnLine)
1665 {
1666     saxlocator *This = impl_from_ISAXLocator( iface );
1667
1668     *pnLine = This->line;
1669     return S_OK;
1670 }
1671
1672 static HRESULT WINAPI isaxlocator_getPublicId(
1673         ISAXLocator* iface,
1674         const WCHAR ** ppwchPublicId)
1675 {
1676     BSTR publicId;
1677     saxlocator *This = impl_from_ISAXLocator( iface );
1678
1679     SysFreeString(This->publicId);
1680
1681     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1682     if(SysStringLen(publicId))
1683         This->publicId = (WCHAR*)&publicId;
1684     else
1685     {
1686         SysFreeString(publicId);
1687         This->publicId = NULL;
1688     }
1689
1690     *ppwchPublicId = This->publicId;
1691     return S_OK;
1692 }
1693
1694 static HRESULT WINAPI isaxlocator_getSystemId(
1695         ISAXLocator* iface,
1696         const WCHAR ** ppwchSystemId)
1697 {
1698     BSTR systemId;
1699     saxlocator *This = impl_from_ISAXLocator( iface );
1700
1701     SysFreeString(This->systemId);
1702
1703     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1704     if(SysStringLen(systemId))
1705         This->systemId = (WCHAR*)&systemId;
1706     else
1707     {
1708         SysFreeString(systemId);
1709         This->systemId = NULL;
1710     }
1711
1712     *ppwchSystemId = This->systemId;
1713     return S_OK;
1714 }
1715
1716 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1717 {
1718     isaxlocator_QueryInterface,
1719     isaxlocator_AddRef,
1720     isaxlocator_Release,
1721     isaxlocator_getColumnNumber,
1722     isaxlocator_getLineNumber,
1723     isaxlocator_getPublicId,
1724     isaxlocator_getSystemId
1725 };
1726
1727 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1728 {
1729     saxlocator *locator;
1730
1731     locator = heap_alloc( sizeof (*locator) );
1732     if( !locator )
1733         return E_OUTOFMEMORY;
1734
1735     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1736     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1737     locator->ref = 1;
1738     locator->vbInterface = vbInterface;
1739
1740     locator->saxreader = reader;
1741     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1742
1743     locator->pParserCtxt = NULL;
1744     locator->publicId = NULL;
1745     locator->systemId = NULL;
1746     locator->lastCur = NULL;
1747     locator->line = 0;
1748     locator->column = 0;
1749     locator->ret = S_OK;
1750     locator->nsStackSize = 8;
1751     locator->nsStackLast = 0;
1752     locator->nsStack = heap_alloc(locator->nsStackSize);
1753     if(!locator->nsStack)
1754     {
1755         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1756         heap_free(locator);
1757         return E_OUTOFMEMORY;
1758     }
1759
1760     *ppsaxlocator = locator;
1761
1762     TRACE("returning %p\n", *ppsaxlocator);
1763
1764     return S_OK;
1765 }
1766
1767 /*** SAXXMLReader internal functions ***/
1768 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1769 {
1770     saxlocator *locator;
1771     HRESULT hr;
1772
1773     hr = SAXLocator_create(This, &locator, vbInterface);
1774     if(FAILED(hr))
1775         return hr;
1776
1777     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1778     if(!locator->pParserCtxt)
1779     {
1780         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1781         return E_FAIL;
1782     }
1783
1784     xmlFree(locator->pParserCtxt->sax);
1785     locator->pParserCtxt->sax = &locator->saxreader->sax;
1786     locator->pParserCtxt->userData = locator;
1787
1788     This->isParsing = TRUE;
1789     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1790     else hr = locator->ret;
1791     This->isParsing = FALSE;
1792
1793     if(locator->pParserCtxt)
1794     {
1795         locator->pParserCtxt->sax = NULL;
1796         xmlFreeParserCtxt(locator->pParserCtxt);
1797         locator->pParserCtxt = NULL;
1798     }
1799
1800     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1801     return hr;
1802 }
1803
1804 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1805 {
1806     saxlocator *locator;
1807     HRESULT hr;
1808     ULONG dataRead;
1809     char data[1024];
1810
1811     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1812     if(hr != S_OK)
1813         return hr;
1814
1815     hr = SAXLocator_create(This, &locator, vbInterface);
1816     if(FAILED(hr))
1817         return hr;
1818
1819     locator->pParserCtxt = xmlCreatePushParserCtxt(
1820             &locator->saxreader->sax, locator,
1821             data, dataRead, NULL);
1822     if(!locator->pParserCtxt)
1823     {
1824         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1825         return E_FAIL;
1826     }
1827
1828     This->isParsing = TRUE;
1829     while(1)
1830     {
1831         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1832         if(hr != S_OK)
1833             break;
1834
1835         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1836         else hr = locator->ret;
1837
1838         if(hr != S_OK) break;
1839
1840         if(dataRead != sizeof(data))
1841         {
1842             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1843             else hr = locator->ret;
1844
1845             break;
1846         }
1847     }
1848     This->isParsing = FALSE;
1849
1850     xmlFreeParserCtxt(locator->pParserCtxt);
1851     locator->pParserCtxt = NULL;
1852     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1853     return hr;
1854 }
1855
1856 static HRESULT internal_getEntityResolver(
1857         saxreader *This,
1858         void *pEntityResolver,
1859         BOOL vbInterface)
1860 {
1861     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1862     return E_NOTIMPL;
1863 }
1864
1865 static HRESULT internal_putEntityResolver(
1866         saxreader *This,
1867         void *pEntityResolver,
1868         BOOL vbInterface)
1869 {
1870     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1871     return E_NOTIMPL;
1872 }
1873
1874 static HRESULT internal_getContentHandler(
1875         saxreader* This,
1876         void *pContentHandler,
1877         BOOL vbInterface)
1878 {
1879     TRACE("(%p)->(%p)\n", This, pContentHandler);
1880     if(pContentHandler == NULL)
1881         return E_POINTER;
1882     if((vbInterface && This->vbcontentHandler)
1883             || (!vbInterface && This->contentHandler))
1884     {
1885         if(vbInterface)
1886             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1887         else
1888             ISAXContentHandler_AddRef(This->contentHandler);
1889     }
1890     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1891         This->vbcontentHandler;
1892     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1893
1894     return S_OK;
1895 }
1896
1897 static HRESULT internal_putContentHandler(
1898         saxreader* This,
1899         void *contentHandler,
1900         BOOL vbInterface)
1901 {
1902     TRACE("(%p)->(%p)\n", This, contentHandler);
1903     if(contentHandler)
1904     {
1905         if(vbInterface)
1906             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1907         else
1908             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1909     }
1910     if((vbInterface && This->vbcontentHandler)
1911             || (!vbInterface && This->contentHandler))
1912     {
1913         if(vbInterface)
1914             IVBSAXContentHandler_Release(This->vbcontentHandler);
1915         else
1916             ISAXContentHandler_Release(This->contentHandler);
1917     }
1918     if(vbInterface)
1919         This->vbcontentHandler = contentHandler;
1920     else
1921         This->contentHandler = contentHandler;
1922
1923     return S_OK;
1924 }
1925
1926 static HRESULT internal_getDTDHandler(
1927         saxreader* This,
1928         void *pDTDHandler,
1929         BOOL vbInterface)
1930 {
1931     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1932     return E_NOTIMPL;
1933 }
1934
1935 static HRESULT internal_putDTDHandler(
1936         saxreader* This,
1937         void *pDTDHandler,
1938         BOOL vbInterface)
1939 {
1940     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1941     return E_NOTIMPL;
1942 }
1943
1944 static HRESULT internal_getErrorHandler(
1945         saxreader* This,
1946         void *pErrorHandler,
1947         BOOL vbInterface)
1948 {
1949     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1950     if(pErrorHandler == NULL)
1951         return E_POINTER;
1952
1953     if(vbInterface && This->vberrorHandler)
1954         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1955     else if(!vbInterface && This->errorHandler)
1956         ISAXErrorHandler_AddRef(This->errorHandler);
1957
1958     if(vbInterface)
1959         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1960     else
1961         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1962
1963     return S_OK;
1964
1965 }
1966
1967 static HRESULT internal_putErrorHandler(
1968         saxreader* This,
1969         void *errorHandler,
1970         BOOL vbInterface)
1971 {
1972     TRACE("(%p)->(%p)\n", This, errorHandler);
1973     if(errorHandler)
1974     {
1975         if(vbInterface)
1976             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1977         else
1978             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1979     }
1980
1981     if(vbInterface && This->vberrorHandler)
1982         IVBSAXErrorHandler_Release(This->vberrorHandler);
1983     else if(!vbInterface && This->errorHandler)
1984         ISAXErrorHandler_Release(This->errorHandler);
1985
1986     if(vbInterface)
1987         This->vberrorHandler = errorHandler;
1988     else
1989         This->errorHandler = errorHandler;
1990
1991     return S_OK;
1992
1993 }
1994
1995 static HRESULT internal_parse(
1996         saxreader* This,
1997         VARIANT varInput,
1998         BOOL vbInterface)
1999 {
2000     HRESULT hr;
2001
2002     TRACE("(%p)\n", This);
2003
2004     hr = S_OK;
2005     switch(V_VT(&varInput))
2006     {
2007         case VT_BSTR:
2008             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2009                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2010             break;
2011         case VT_ARRAY|VT_UI1: {
2012             void *pSAData;
2013             LONG lBound, uBound;
2014             ULONG dataRead;
2015
2016             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2017             if(hr != S_OK) break;
2018             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2019             if(hr != S_OK) break;
2020             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2021             hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2022             if(hr != S_OK) break;
2023             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2024             SafeArrayUnaccessData(V_ARRAY(&varInput));
2025             break;
2026         }
2027         case VT_UNKNOWN:
2028         case VT_DISPATCH: {
2029             IPersistStream *persistStream;
2030             IStream *stream = NULL;
2031             IXMLDOMDocument *xmlDoc;
2032
2033             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2034                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2035             {
2036                 BSTR bstrData;
2037
2038                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2039                 hr = internal_parseBuffer(This, (const char*)bstrData,
2040                         SysStringByteLen(bstrData), vbInterface);
2041                 IXMLDOMDocument_Release(xmlDoc);
2042                 SysFreeString(bstrData);
2043                 break;
2044             }
2045             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2046                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2047             {
2048                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2049                 IPersistStream_Release(persistStream);
2050                 if(hr != S_OK) break;
2051             }
2052             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2053                         &IID_IStream, (void**)&stream) == S_OK)
2054             {
2055                 hr = internal_parseStream(This, stream, vbInterface);
2056                 IStream_Release(stream);
2057                 break;
2058             }
2059         }
2060         default:
2061             WARN("vt %d not implemented\n", V_VT(&varInput));
2062             hr = E_INVALIDARG;
2063     }
2064
2065     return hr;
2066 }
2067
2068 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2069 {
2070     saxreader *This = obj;
2071
2072     return internal_parseBuffer(This, ptr, len, TRUE);
2073 }
2074
2075 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2076 {
2077     saxreader *This = obj;
2078
2079     return internal_parseBuffer(This, ptr, len, FALSE);
2080 }
2081
2082 static HRESULT internal_parseURL(
2083         saxreader* This,
2084         const WCHAR *url,
2085         BOOL vbInterface)
2086 {
2087     bsc_t *bsc;
2088     HRESULT hr;
2089
2090     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2091
2092     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2093     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2094
2095     if(FAILED(hr))
2096         return hr;
2097
2098     detach_bsc(bsc);
2099
2100     return S_OK;
2101 }
2102
2103 static HRESULT internal_putProperty(
2104     saxreader* This,
2105     const WCHAR *pProp,
2106     VARIANT value,
2107     BOOL vbInterface)
2108 {
2109     static const WCHAR wszCharset[] = {
2110         'c','h','a','r','s','e','t',0
2111     };
2112     static const WCHAR wszDeclarationHandler[] = {
2113         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2114         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2115         'd','e','c','l','a','r','a','t','i','o','n',
2116         '-','h','a','n','d','l','e','r',0
2117     };
2118     static const WCHAR wszDomNode[] = {
2119         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2120         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2121         'd','o','m','-','n','o','d','e',0
2122     };
2123     static const WCHAR wszInputSource[] = {
2124         'i','n','p','u','t','-','s','o','u','r','c','e',0
2125     };
2126     static const WCHAR wszLexicalHandler[] = {
2127         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2128         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2129         'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
2130     };
2131     static const WCHAR wszMaxElementDepth[] = {
2132         'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
2133     };
2134     static const WCHAR wszMaxXMLSize[] = {
2135         'm','a','x','-','x','m','l','-','s','i','z','e',0
2136     };
2137     static const WCHAR wszSchemaDeclarationHandler[] = {
2138         's','c','h','e','m','a','-',
2139         'd','e','c','l','a','r','a','t','i','o','n','-',
2140         'h','a','n','d','l','e','r',0
2141     };
2142     static const WCHAR wszXMLDeclEncoding[] = {
2143         'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
2144     };
2145     static const WCHAR wszXMLDeclStandalone[] = {
2146         'x','m','l','d','e','c','l',
2147         '-','s','t','a','n','d','a','l','o','n','e',0
2148     };
2149     static const WCHAR wszXMLDeclVersion[] = {
2150         'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
2151     };
2152
2153     FIXME("(%p)->(%s): semi-stub\n", This, debugstr_w(pProp));
2154
2155     if(!memcmp(pProp, wszCharset, sizeof(wszCharset)))
2156         return E_NOTIMPL;
2157
2158     if(!memcmp(pProp, wszDeclarationHandler, sizeof(wszDeclarationHandler)))
2159     {
2160         if(This->isParsing) return E_FAIL;
2161
2162         if(V_UNKNOWN(&value))
2163         {
2164             if(vbInterface)
2165                 IVBSAXDeclHandler_AddRef((IVBSAXDeclHandler*)V_UNKNOWN(&value));
2166             else
2167                 ISAXDeclHandler_AddRef((ISAXDeclHandler*)V_UNKNOWN(&value));
2168         }
2169         if((vbInterface && This->vbdeclHandler)
2170                 || (!vbInterface && This->declHandler))
2171         {
2172             if(vbInterface)
2173                 IVBSAXDeclHandler_Release(This->vbdeclHandler);
2174             else
2175                 ISAXDeclHandler_Release(This->declHandler);
2176         }
2177         if(vbInterface)
2178             This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2179         else
2180             This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2181         return S_OK;
2182     }
2183
2184     if(!memcmp(pProp, wszDomNode, sizeof(wszDomNode)))
2185         return E_FAIL;
2186
2187     if(!memcmp(pProp, wszInputSource, sizeof(wszInputSource)))
2188         return E_NOTIMPL;
2189
2190     if(!memcmp(pProp, wszLexicalHandler, sizeof(wszLexicalHandler)))
2191     {
2192         if(This->isParsing) return E_FAIL;
2193
2194         if(V_UNKNOWN(&value))
2195         {
2196             if(vbInterface)
2197                 IVBSAXLexicalHandler_AddRef(
2198                         (IVBSAXLexicalHandler*)V_UNKNOWN(&value));
2199             else
2200                 ISAXLexicalHandler_AddRef(
2201                         (ISAXLexicalHandler*)V_UNKNOWN(&value));
2202         }
2203         if((vbInterface && This->vblexicalHandler)
2204                 || (!vbInterface && This->lexicalHandler))
2205         {
2206             if(vbInterface)
2207                 IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2208             else
2209                 ISAXLexicalHandler_Release(This->lexicalHandler);
2210         }
2211         if(vbInterface)
2212             This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2213         else
2214             This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2215         return S_OK;
2216     }
2217
2218     if(!memcmp(pProp, wszMaxElementDepth, sizeof(wszMaxElementDepth)))
2219         return E_NOTIMPL;
2220
2221     if(!memcmp(pProp, wszMaxXMLSize, sizeof(wszMaxXMLSize)))
2222         return E_NOTIMPL;
2223
2224     if(!memcmp(pProp, wszSchemaDeclarationHandler,
2225                 sizeof(wszSchemaDeclarationHandler)))
2226         return E_NOTIMPL;
2227
2228     if(!memcmp(pProp, wszXMLDeclEncoding, sizeof(wszXMLDeclEncoding)))
2229         return E_FAIL;
2230
2231     if(!memcmp(pProp, wszXMLDeclStandalone, sizeof(wszXMLDeclStandalone)))
2232         return E_FAIL;
2233
2234     if(!memcmp(pProp, wszXMLDeclVersion, sizeof(wszXMLDeclVersion)))
2235         return E_FAIL;
2236
2237     return E_INVALIDARG;
2238 }
2239
2240 /*** IVBSAXXMLReader interface ***/
2241 /*** IUnknown methods ***/
2242 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2243 {
2244     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2245
2246     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2247
2248     *ppvObject = NULL;
2249
2250     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2251          IsEqualGUID( riid, &IID_IDispatch ) ||
2252          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2253     {
2254         *ppvObject = iface;
2255     }
2256     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2257     {
2258         *ppvObject = &This->lpSAXXMLReaderVtbl;
2259     }
2260     else
2261     {
2262         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2263         return E_NOINTERFACE;
2264     }
2265
2266     IVBSAXXMLReader_AddRef( iface );
2267
2268     return S_OK;
2269 }
2270
2271 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2272 {
2273     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2274     TRACE("%p\n", This );
2275     return InterlockedIncrement( &This->ref );
2276 }
2277
2278 static ULONG WINAPI saxxmlreader_Release(
2279     IVBSAXXMLReader* iface)
2280 {
2281     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2282     LONG ref;
2283
2284     TRACE("%p\n", This );
2285
2286     ref = InterlockedDecrement( &This->ref );
2287     if ( ref == 0 )
2288     {
2289         if(This->contentHandler)
2290             ISAXContentHandler_Release(This->contentHandler);
2291
2292         if(This->vbcontentHandler)
2293             IVBSAXContentHandler_Release(This->vbcontentHandler);
2294
2295         if(This->errorHandler)
2296             ISAXErrorHandler_Release(This->errorHandler);
2297
2298         if(This->vberrorHandler)
2299             IVBSAXErrorHandler_Release(This->vberrorHandler);
2300
2301         if(This->lexicalHandler)
2302             ISAXLexicalHandler_Release(This->lexicalHandler);
2303
2304         if(This->vblexicalHandler)
2305             IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2306
2307         if(This->declHandler)
2308             ISAXDeclHandler_Release(This->declHandler);
2309
2310         if(This->vbdeclHandler)
2311             IVBSAXDeclHandler_Release(This->vbdeclHandler);
2312
2313         heap_free( This );
2314     }
2315
2316     return ref;
2317 }
2318 /*** IDispatch ***/
2319 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2320 {
2321     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2322
2323     TRACE("(%p)->(%p)\n", This, pctinfo);
2324
2325     *pctinfo = 1;
2326
2327     return S_OK;
2328 }
2329
2330 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2331     IVBSAXXMLReader *iface,
2332     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2333 {
2334     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2335     HRESULT hr;
2336
2337     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2338
2339     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2340
2341     return hr;
2342 }
2343
2344 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2345     IVBSAXXMLReader *iface,
2346     REFIID riid,
2347     LPOLESTR* rgszNames,
2348     UINT cNames,
2349     LCID lcid,
2350     DISPID* rgDispId)
2351 {
2352     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2353     ITypeInfo *typeinfo;
2354     HRESULT hr;
2355
2356     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2357           lcid, rgDispId);
2358
2359     if(!rgszNames || cNames == 0 || !rgDispId)
2360         return E_INVALIDARG;
2361
2362     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2363     if(SUCCEEDED(hr))
2364     {
2365         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2366         ITypeInfo_Release(typeinfo);
2367     }
2368
2369     return hr;
2370 }
2371
2372 static HRESULT WINAPI saxxmlreader_Invoke(
2373     IVBSAXXMLReader *iface,
2374     DISPID dispIdMember,
2375     REFIID riid,
2376     LCID lcid,
2377     WORD wFlags,
2378     DISPPARAMS* pDispParams,
2379     VARIANT* pVarResult,
2380     EXCEPINFO* pExcepInfo,
2381     UINT* puArgErr)
2382 {
2383     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2384     ITypeInfo *typeinfo;
2385     HRESULT hr;
2386
2387     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2388           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2389
2390     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2391     if(SUCCEEDED(hr))
2392     {
2393         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2394                 pVarResult, pExcepInfo, puArgErr);
2395         ITypeInfo_Release(typeinfo);
2396     }
2397
2398     return hr;
2399 }
2400
2401 /*** IVBSAXXMLReader methods ***/
2402 static HRESULT WINAPI saxxmlreader_getFeature(
2403     IVBSAXXMLReader* iface,
2404     const WCHAR *pFeature,
2405     VARIANT_BOOL *pValue)
2406 {
2407     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2408
2409     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2410     return E_NOTIMPL;
2411 }
2412
2413 static HRESULT WINAPI saxxmlreader_putFeature(
2414     IVBSAXXMLReader* iface,
2415     const WCHAR *pFeature,
2416     VARIANT_BOOL vfValue)
2417 {
2418     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2419
2420     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2421     return E_NOTIMPL;
2422 }
2423
2424 static HRESULT WINAPI saxxmlreader_getProperty(
2425     IVBSAXXMLReader* iface,
2426     const WCHAR *pProp,
2427     VARIANT *pValue)
2428 {
2429     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2430
2431     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2432     return E_NOTIMPL;
2433 }
2434
2435 static HRESULT WINAPI saxxmlreader_putProperty(
2436     IVBSAXXMLReader* iface,
2437     const WCHAR *pProp,
2438     VARIANT value)
2439 {
2440     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2441     return internal_putProperty(This, pProp, value, TRUE);
2442 }
2443
2444 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2445     IVBSAXXMLReader* iface,
2446     IVBSAXEntityResolver **pEntityResolver)
2447 {
2448     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2449     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2450 }
2451
2452 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2453     IVBSAXXMLReader* iface,
2454     IVBSAXEntityResolver *pEntityResolver)
2455 {
2456     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2457     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2458 }
2459
2460 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2461     IVBSAXXMLReader* iface,
2462     IVBSAXContentHandler **ppContentHandler)
2463 {
2464     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2465     return internal_getContentHandler(This, ppContentHandler, TRUE);
2466 }
2467
2468 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2469     IVBSAXXMLReader* iface,
2470     IVBSAXContentHandler *contentHandler)
2471 {
2472     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2473     return internal_putContentHandler(This, contentHandler, TRUE);
2474 }
2475
2476 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2477     IVBSAXXMLReader* iface,
2478     IVBSAXDTDHandler **pDTDHandler)
2479 {
2480     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2481     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2482 }
2483
2484 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2485     IVBSAXXMLReader* iface,
2486     IVBSAXDTDHandler *pDTDHandler)
2487 {
2488     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2489     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2490 }
2491
2492 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2493     IVBSAXXMLReader* iface,
2494     IVBSAXErrorHandler **pErrorHandler)
2495 {
2496     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2497     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2498 }
2499
2500 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2501     IVBSAXXMLReader* iface,
2502     IVBSAXErrorHandler *errorHandler)
2503 {
2504     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2505     return internal_putErrorHandler(This, errorHandler, TRUE);
2506 }
2507
2508 static HRESULT WINAPI saxxmlreader_get_baseURL(
2509     IVBSAXXMLReader* iface,
2510     const WCHAR **pBaseUrl)
2511 {
2512     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2513
2514     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2515     return E_NOTIMPL;
2516 }
2517
2518 static HRESULT WINAPI saxxmlreader_put_baseURL(
2519     IVBSAXXMLReader* iface,
2520     const WCHAR *pBaseUrl)
2521 {
2522     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2523
2524     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2525     return E_NOTIMPL;
2526 }
2527
2528 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2529     IVBSAXXMLReader* iface,
2530     const WCHAR **pSecureBaseUrl)
2531 {
2532     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2533
2534     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2535     return E_NOTIMPL;
2536 }
2537
2538
2539 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2540     IVBSAXXMLReader* iface,
2541     const WCHAR *secureBaseUrl)
2542 {
2543     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2544
2545     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2546     return E_NOTIMPL;
2547 }
2548
2549 static HRESULT WINAPI saxxmlreader_parse(
2550     IVBSAXXMLReader* iface,
2551     VARIANT varInput)
2552 {
2553     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2554     return internal_parse(This, varInput, TRUE);
2555 }
2556
2557 static HRESULT WINAPI saxxmlreader_parseURL(
2558     IVBSAXXMLReader* iface,
2559     const WCHAR *url)
2560 {
2561     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2562     return internal_parseURL(This, url, TRUE);
2563 }
2564
2565 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2566 {
2567     saxxmlreader_QueryInterface,
2568     saxxmlreader_AddRef,
2569     saxxmlreader_Release,
2570     saxxmlreader_GetTypeInfoCount,
2571     saxxmlreader_GetTypeInfo,
2572     saxxmlreader_GetIDsOfNames,
2573     saxxmlreader_Invoke,
2574     saxxmlreader_getFeature,
2575     saxxmlreader_putFeature,
2576     saxxmlreader_getProperty,
2577     saxxmlreader_putProperty,
2578     saxxmlreader_get_entityResolver,
2579     saxxmlreader_put_entityResolver,
2580     saxxmlreader_get_contentHandler,
2581     saxxmlreader_put_contentHandler,
2582     saxxmlreader_get_dtdHandler,
2583     saxxmlreader_put_dtdHandler,
2584     saxxmlreader_get_errorHandler,
2585     saxxmlreader_put_errorHandler,
2586     saxxmlreader_get_baseURL,
2587     saxxmlreader_put_baseURL,
2588     saxxmlreader_get_secureBaseURL,
2589     saxxmlreader_put_secureBaseURL,
2590     saxxmlreader_parse,
2591     saxxmlreader_parseURL
2592 };
2593
2594 /*** ISAXXMLReader interface ***/
2595 /*** IUnknown methods ***/
2596 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2597 {
2598     saxreader *This = impl_from_ISAXXMLReader( iface );
2599     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2600 }
2601
2602 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2603 {
2604     saxreader *This = impl_from_ISAXXMLReader( iface );
2605     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2606 }
2607
2608 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2609 {
2610     saxreader *This = impl_from_ISAXXMLReader( iface );
2611     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2612 }
2613
2614 /*** ISAXXMLReader methods ***/
2615 static HRESULT WINAPI isaxxmlreader_getFeature(
2616         ISAXXMLReader* iface,
2617         const WCHAR *pFeature,
2618         VARIANT_BOOL *pValue)
2619 {
2620     saxreader *This = impl_from_ISAXXMLReader( iface );
2621     return IVBSAXXMLReader_getFeature(
2622             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2623             pFeature, pValue);
2624 }
2625
2626 static HRESULT WINAPI isaxxmlreader_putFeature(
2627         ISAXXMLReader* iface,
2628         const WCHAR *pFeature,
2629         VARIANT_BOOL vfValue)
2630 {
2631     saxreader *This = impl_from_ISAXXMLReader( iface );
2632     return IVBSAXXMLReader_putFeature(
2633             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2634             pFeature, vfValue);
2635 }
2636
2637 static HRESULT WINAPI isaxxmlreader_getProperty(
2638         ISAXXMLReader* iface,
2639         const WCHAR *pProp,
2640         VARIANT *pValue)
2641 {
2642     saxreader *This = impl_from_ISAXXMLReader( iface );
2643     return IVBSAXXMLReader_getProperty(
2644             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2645             pProp, pValue);
2646 }
2647
2648 static HRESULT WINAPI isaxxmlreader_putProperty(
2649         ISAXXMLReader* iface,
2650         const WCHAR *pProp,
2651         VARIANT value)
2652 {
2653     saxreader *This = impl_from_ISAXXMLReader( iface );
2654     return internal_putProperty(This, pProp, value, FALSE);
2655 }
2656
2657 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2658         ISAXXMLReader* iface,
2659         ISAXEntityResolver **ppEntityResolver)
2660 {
2661     saxreader *This = impl_from_ISAXXMLReader( iface );
2662     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2663 }
2664
2665 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2666         ISAXXMLReader* iface,
2667         ISAXEntityResolver *pEntityResolver)
2668 {
2669     saxreader *This = impl_from_ISAXXMLReader( iface );
2670     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2671 }
2672
2673 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2674         ISAXXMLReader* iface,
2675         ISAXContentHandler **pContentHandler)
2676 {
2677     saxreader *This = impl_from_ISAXXMLReader( iface );
2678     return internal_getContentHandler(This, pContentHandler, FALSE);
2679 }
2680
2681 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2682         ISAXXMLReader* iface,
2683         ISAXContentHandler *contentHandler)
2684 {
2685     saxreader *This = impl_from_ISAXXMLReader( iface );
2686     return internal_putContentHandler(This, contentHandler, FALSE);
2687 }
2688
2689 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2690         ISAXXMLReader* iface,
2691         ISAXDTDHandler **pDTDHandler)
2692 {
2693     saxreader *This = impl_from_ISAXXMLReader( iface );
2694     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2695 }
2696
2697 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2698         ISAXXMLReader* iface,
2699         ISAXDTDHandler *pDTDHandler)
2700 {
2701     saxreader *This = impl_from_ISAXXMLReader( iface );
2702     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2703 }
2704
2705 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2706         ISAXXMLReader* iface,
2707         ISAXErrorHandler **pErrorHandler)
2708 {
2709     saxreader *This = impl_from_ISAXXMLReader( iface );
2710     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2711 }
2712
2713 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2714         ISAXXMLReader* iface,
2715         ISAXErrorHandler *errorHandler)
2716 {
2717     saxreader *This = impl_from_ISAXXMLReader( iface );
2718     return internal_putErrorHandler(This, errorHandler, FALSE);
2719 }
2720
2721 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2722         ISAXXMLReader* iface,
2723         const WCHAR **pBaseUrl)
2724 {
2725     saxreader *This = impl_from_ISAXXMLReader( iface );
2726     return IVBSAXXMLReader_get_baseURL(
2727             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2728             pBaseUrl);
2729 }
2730
2731 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2732         ISAXXMLReader* iface,
2733         const WCHAR *pBaseUrl)
2734 {
2735     saxreader *This = impl_from_ISAXXMLReader( iface );
2736     return IVBSAXXMLReader_put_baseURL(
2737             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2738             pBaseUrl);
2739 }
2740
2741 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2742         ISAXXMLReader* iface,
2743         const WCHAR **pSecureBaseUrl)
2744 {
2745     saxreader *This = impl_from_ISAXXMLReader( iface );
2746     return IVBSAXXMLReader_get_secureBaseURL(
2747             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2748             pSecureBaseUrl);
2749 }
2750
2751 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2752         ISAXXMLReader* iface,
2753         const WCHAR *secureBaseUrl)
2754 {
2755     saxreader *This = impl_from_ISAXXMLReader( iface );
2756     return IVBSAXXMLReader_put_secureBaseURL(
2757             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2758             secureBaseUrl);
2759 }
2760
2761 static HRESULT WINAPI isaxxmlreader_parse(
2762         ISAXXMLReader* iface,
2763         VARIANT varInput)
2764 {
2765     saxreader *This = impl_from_ISAXXMLReader( iface );
2766     return internal_parse(This, varInput, FALSE);
2767 }
2768
2769 static HRESULT WINAPI isaxxmlreader_parseURL(
2770         ISAXXMLReader* iface,
2771         const WCHAR *url)
2772 {
2773     saxreader *This = impl_from_ISAXXMLReader( iface );
2774     return internal_parseURL(This, url, FALSE);
2775 }
2776
2777 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2778 {
2779     isaxxmlreader_QueryInterface,
2780     isaxxmlreader_AddRef,
2781     isaxxmlreader_Release,
2782     isaxxmlreader_getFeature,
2783     isaxxmlreader_putFeature,
2784     isaxxmlreader_getProperty,
2785     isaxxmlreader_putProperty,
2786     isaxxmlreader_getEntityResolver,
2787     isaxxmlreader_putEntityResolver,
2788     isaxxmlreader_getContentHandler,
2789     isaxxmlreader_putContentHandler,
2790     isaxxmlreader_getDTDHandler,
2791     isaxxmlreader_putDTDHandler,
2792     isaxxmlreader_getErrorHandler,
2793     isaxxmlreader_putErrorHandler,
2794     isaxxmlreader_getBaseURL,
2795     isaxxmlreader_putBaseURL,
2796     isaxxmlreader_getSecureBaseURL,
2797     isaxxmlreader_putSecureBaseURL,
2798     isaxxmlreader_parse,
2799     isaxxmlreader_parseURL
2800 };
2801
2802 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2803 {
2804     saxreader *reader;
2805
2806     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2807
2808     reader = heap_alloc( sizeof (*reader) );
2809     if( !reader )
2810         return E_OUTOFMEMORY;
2811
2812     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2813     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2814     reader->ref = 1;
2815     reader->contentHandler = NULL;
2816     reader->vbcontentHandler = NULL;
2817     reader->errorHandler = NULL;
2818     reader->vberrorHandler = NULL;
2819     reader->lexicalHandler = NULL;
2820     reader->vblexicalHandler = NULL;
2821     reader->declHandler = NULL;
2822     reader->vbdeclHandler = NULL;
2823     reader->isParsing = FALSE;
2824
2825     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2826     reader->sax.initialized = XML_SAX2_MAGIC;
2827     reader->sax.startDocument = libxmlStartDocument;
2828     reader->sax.endDocument = libxmlEndDocument;
2829     reader->sax.startElementNs = libxmlStartElementNS;
2830     reader->sax.endElementNs = libxmlEndElementNS;
2831     reader->sax.characters = libxmlCharacters;
2832     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2833     reader->sax.comment = libxmlComment;
2834     reader->sax.error = libxmlFatalError;
2835     reader->sax.fatalError = libxmlFatalError;
2836     reader->sax.cdataBlock = libxmlCDataBlock;
2837
2838     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2839
2840     TRACE("returning iface %p\n", *ppObj);
2841
2842     return S_OK;
2843 }
2844
2845 #else
2846
2847 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2848 {
2849     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2850             "libxml2 support was not present at compile time.\n");
2851     return E_NOTIMPL;
2852 }
2853
2854 #endif