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