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