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