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