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