winealsa: Map ALSA errors to AUDCLNT_E_*.
[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         attrs[index].szLocalname = bstr_from_xmlChar(xmlAttributes[index*5]);
1139         attrs[index].szURI = find_element_uri(locator, xmlAttributes[index*5+2]);
1140         attrs[index].szValue = bstr_from_xmlCharN(xmlAttributes[index*5+3],
1141                 xmlAttributes[index*5+4]-xmlAttributes[index*5+3]);
1142         attrs[index].szQName = QName_from_xmlChar(xmlAttributes[index*5+1],
1143                 xmlAttributes[index*5]);
1144     }
1145
1146     return S_OK;
1147 }
1148
1149 /*** LibXML callbacks ***/
1150 static void libxmlStartDocument(void *ctx)
1151 {
1152     saxlocator *This = ctx;
1153     HRESULT hr;
1154
1155     if(This->saxreader->version >= MSXML6)
1156     {
1157         const xmlChar *p = This->pParserCtxt->input->cur-1;
1158         update_position(This, FALSE);
1159         while(p>This->pParserCtxt->input->base && *p!='>')
1160         {
1161             if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1162                 This->line--;
1163             p--;
1164         }
1165         This->column = 0;
1166         for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1167             This->column++;
1168     }
1169
1170     if(has_content_handler(This))
1171     {
1172         if(This->vbInterface)
1173             hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler);
1174         else
1175             hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
1176
1177         if (sax_callback_failed(This, hr))
1178             format_error_message_from_id(This, hr);
1179     }
1180 }
1181
1182 static void libxmlEndDocument(void *ctx)
1183 {
1184     saxlocator *This = ctx;
1185     HRESULT hr;
1186
1187     if(This->saxreader->version >= MSXML6) {
1188         update_position(This, FALSE);
1189         if(This->column > 1)
1190             This->line++;
1191         This->column = 0;
1192     } else {
1193         This->column = 0;
1194         This->line = 0;
1195     }
1196
1197     if(This->ret != S_OK) return;
1198
1199     if(has_content_handler(This))
1200     {
1201         if(This->vbInterface)
1202             hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler);
1203         else
1204             hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
1205
1206         if (sax_callback_failed(This, hr))
1207             format_error_message_from_id(This, hr);
1208     }
1209 }
1210
1211 static void libxmlStartElementNS(
1212         void *ctx,
1213         const xmlChar *localname,
1214         const xmlChar *prefix,
1215         const xmlChar *URI,
1216         int nb_namespaces,
1217         const xmlChar **namespaces,
1218         int nb_attributes,
1219         int nb_defaulted,
1220         const xmlChar **attributes)
1221 {
1222     saxlocator *This = ctx;
1223     element_entry *element;
1224     HRESULT hr = S_OK;
1225
1226     update_position(This, TRUE);
1227     if(*(This->pParserCtxt->input->cur) == '/')
1228         This->column++;
1229     if(This->saxreader->version < MSXML6)
1230         This->column++;
1231
1232     element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1233     push_element_ns(This, element);
1234
1235     if (has_content_handler(This))
1236     {
1237         BSTR uri;
1238         int i;
1239
1240         for (i = 0; i < nb_namespaces; i++)
1241         {
1242             if(This->vbInterface)
1243                 hr = IVBSAXContentHandler_startPrefixMapping(
1244                         This->saxreader->vbcontentHandler,
1245                         &element->ns[i].prefix,
1246                         &element->ns[i].uri);
1247             else
1248                 hr = ISAXContentHandler_startPrefixMapping(
1249                         This->saxreader->contentHandler,
1250                         element->ns[i].prefix,
1251                         SysStringLen(element->ns[i].prefix),
1252                         element->ns[i].uri,
1253                         SysStringLen(element->ns[i].uri));
1254
1255             if (sax_callback_failed(This, hr))
1256             {
1257                 format_error_message_from_id(This, hr);
1258                 return;
1259             }
1260         }
1261
1262         uri = find_element_uri(This, URI);
1263
1264         hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1265         if(hr == S_OK)
1266         {
1267             if(This->vbInterface)
1268                 hr = IVBSAXContentHandler_startElement(This->saxreader->vbcontentHandler,
1269                         &uri, &element->local, &element->qname, &This->IVBSAXAttributes_iface);
1270             else
1271                 hr = ISAXContentHandler_startElement(This->saxreader->contentHandler,
1272                         uri, SysStringLen(uri),
1273                         element->local, SysStringLen(element->local),
1274                         element->qname, SysStringLen(element->qname),
1275                         &This->ISAXAttributes_iface);
1276         }
1277     }
1278
1279     if (sax_callback_failed(This, hr))
1280         format_error_message_from_id(This, hr);
1281 }
1282
1283 static void libxmlEndElementNS(
1284         void *ctx,
1285         const xmlChar *localname,
1286         const xmlChar *prefix,
1287         const xmlChar *URI)
1288 {
1289     saxlocator *This = ctx;
1290     element_entry *element;
1291     const xmlChar *p;
1292     HRESULT hr;
1293     BSTR uri;
1294     int i;
1295
1296     update_position(This, FALSE);
1297     p = This->pParserCtxt->input->cur;
1298     if(This->saxreader->version >= MSXML6)
1299     {
1300         p--;
1301         while(p>This->pParserCtxt->input->base && *p!='>')
1302         {
1303             if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1304                 This->line--;
1305             p--;
1306         }
1307     }
1308     else if(*(p-1)!='>' || *(p-2)!='/')
1309     {
1310         p--;
1311         while(p-2>=This->pParserCtxt->input->base
1312                 && *(p-2)!='<' && *(p-1)!='/')
1313         {
1314             if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1315                 This->line--;
1316             p--;
1317         }
1318     }
1319     This->column = 0;
1320     for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1321         This->column++;
1322
1323     uri = find_element_uri(This, URI);
1324     element = pop_element_ns(This);
1325
1326     if (!has_content_handler(This))
1327     {
1328         This->nb_attributes = 0;
1329         free_element_entry(element);
1330         return;
1331     }
1332
1333     if(This->vbInterface)
1334         hr = IVBSAXContentHandler_endElement(
1335                 This->saxreader->vbcontentHandler,
1336                 &uri, &element->local, &element->qname);
1337     else
1338         hr = ISAXContentHandler_endElement(
1339                 This->saxreader->contentHandler,
1340                 uri, SysStringLen(uri),
1341                 element->local, SysStringLen(element->local),
1342                 element->qname, SysStringLen(element->qname));
1343
1344     This->nb_attributes = 0;
1345
1346     if (sax_callback_failed(This, hr))
1347     {
1348         format_error_message_from_id(This, hr);
1349         return;
1350     }
1351
1352     i = -1;
1353     while (iterate_endprefix_index(This, element, &i))
1354     {
1355         if(This->vbInterface)
1356             hr = IVBSAXContentHandler_endPrefixMapping(
1357                     This->saxreader->vbcontentHandler, &element->ns[i].prefix);
1358         else
1359             hr = ISAXContentHandler_endPrefixMapping(
1360                     This->saxreader->contentHandler,
1361                     element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1362
1363         if (sax_callback_failed(This, hr)) break;
1364     }
1365
1366     if (sax_callback_failed(This, hr))
1367         format_error_message_from_id(This, hr);
1368
1369     free_element_entry(element);
1370 }
1371
1372 static void libxmlCharacters(
1373         void *ctx,
1374         const xmlChar *ch,
1375         int len)
1376 {
1377     saxlocator *This = ctx;
1378     BSTR Chars;
1379     HRESULT hr;
1380     xmlChar *cur, *end;
1381     BOOL lastEvent = FALSE;
1382
1383     if(!(has_content_handler(This))) return;
1384
1385     update_position(This, FALSE);
1386     cur = (xmlChar*)This->pParserCtxt->input->cur;
1387     while(cur>=This->pParserCtxt->input->base && *cur!='>')
1388     {
1389         if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1390             This->line--;
1391         cur--;
1392     }
1393     This->column = 1;
1394     for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1395         This->column++;
1396
1397     cur = (xmlChar*)ch;
1398     if(*(ch-1)=='\r') cur--;
1399     end = cur;
1400
1401     while(1)
1402     {
1403         while(end-ch<len && *end!='\r') end++;
1404         if(end-ch==len)
1405         {
1406             lastEvent = TRUE;
1407         }
1408         else
1409         {
1410             *end = '\n';
1411             end++;
1412         }
1413
1414         if(This->saxreader->version >= MSXML6)
1415         {
1416             xmlChar *p;
1417
1418             for(p=cur; p!=end; p++)
1419             {
1420                 if(*p=='\n')
1421                 {
1422                     This->line++;
1423                     This->column = 1;
1424                 }
1425                 else
1426                 {
1427                     This->column++;
1428                 }
1429             }
1430
1431             if(!lastEvent)
1432                 This->column = 0;
1433         }
1434
1435         Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1436         if(This->vbInterface)
1437             hr = IVBSAXContentHandler_characters(
1438                     This->saxreader->vbcontentHandler, &Chars);
1439         else
1440             hr = ISAXContentHandler_characters(
1441                     This->saxreader->contentHandler,
1442                     Chars, SysStringLen(Chars));
1443
1444         if (sax_callback_failed(This, hr))
1445         {
1446             format_error_message_from_id(This, hr);
1447             return;
1448         }
1449
1450         if(This->saxreader->version < MSXML6)
1451             This->column += end-cur;
1452
1453         if(lastEvent)
1454             break;
1455
1456         *(end-1) = '\r';
1457         if(*end == '\n')
1458         {
1459             end++;
1460             This->column++;
1461         }
1462         cur = end;
1463
1464         if(end-ch == len) break;
1465     }
1466 }
1467
1468 static void libxmlSetDocumentLocator(
1469         void *ctx,
1470         xmlSAXLocatorPtr loc)
1471 {
1472     saxlocator *This = ctx;
1473     HRESULT hr = S_OK;
1474
1475     if(has_content_handler(This))
1476     {
1477         if(This->vbInterface)
1478             hr = IVBSAXContentHandler_putref_documentLocator(This->saxreader->vbcontentHandler,
1479                     &This->IVBSAXLocator_iface);
1480         else
1481             hr = ISAXContentHandler_putDocumentLocator(This->saxreader->contentHandler,
1482                     &This->ISAXLocator_iface);
1483     }
1484
1485     if(FAILED(hr))
1486         format_error_message_from_id(This, hr);
1487 }
1488
1489 static void libxmlComment(void *ctx, const xmlChar *value)
1490 {
1491     saxlocator *This = ctx;
1492     BSTR bValue;
1493     HRESULT hr;
1494     const xmlChar *p = This->pParserCtxt->input->cur;
1495
1496     update_position(This, FALSE);
1497     while(p-4>=This->pParserCtxt->input->base
1498             && memcmp(p-4, "<!--", sizeof(char[4])))
1499     {
1500         if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1501             This->line--;
1502         p--;
1503     }
1504     This->column = 0;
1505     for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1506         This->column++;
1507
1508     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1509     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1510
1511     bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1512
1513     if(This->vbInterface)
1514         hr = IVBSAXLexicalHandler_comment(
1515                 This->saxreader->vblexicalHandler, &bValue);
1516     else
1517         hr = ISAXLexicalHandler_comment(
1518                 This->saxreader->lexicalHandler,
1519                 bValue, SysStringLen(bValue));
1520
1521     if(FAILED(hr))
1522         format_error_message_from_id(This, hr);
1523 }
1524
1525 static void libxmlFatalError(void *ctx, const char *msg, ...)
1526 {
1527     saxlocator *This = ctx;
1528     char message[1024];
1529     WCHAR *error;
1530     DWORD len;
1531     va_list args;
1532
1533     if(This->ret != S_OK) {
1534         xmlStopParser(This->pParserCtxt);
1535         return;
1536     }
1537
1538     va_start(args, msg);
1539     vsprintf(message, msg, args);
1540     va_end(args);
1541
1542     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1543     error = heap_alloc(sizeof(WCHAR)*len);
1544     if(error)
1545     {
1546         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1547         TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1548     }
1549
1550     if(!has_error_handler(This))
1551     {
1552         xmlStopParser(This->pParserCtxt);
1553         This->ret = E_FAIL;
1554         heap_free(error);
1555         return;
1556     }
1557
1558     FIXME("Error handling is not compatible.\n");
1559
1560     if(This->vbInterface)
1561     {
1562         BSTR bstrError = SysAllocString(error);
1563         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler, &This->IVBSAXLocator_iface,
1564                 &bstrError, E_FAIL);
1565         SysFreeString(bstrError);
1566     }
1567     else
1568         ISAXErrorHandler_fatalError(This->saxreader->errorHandler, &This->ISAXLocator_iface,
1569                 error, E_FAIL);
1570
1571     heap_free(error);
1572
1573     xmlStopParser(This->pParserCtxt);
1574     This->ret = E_FAIL;
1575 }
1576
1577 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1578 {
1579     saxlocator *This = ctx;
1580     HRESULT hr = S_OK;
1581     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1582     xmlChar *cur, *end;
1583     int realLen;
1584     BSTR Chars;
1585     BOOL lastEvent = FALSE, change;
1586
1587     update_position(This, FALSE);
1588     while(beg-9>=This->pParserCtxt->input->base
1589             && memcmp(beg-9, "<![CDATA[", sizeof(char[9])))
1590     {
1591         if(*beg=='\n' || (*beg=='\r' && *(beg+1)!='\n'))
1592             This->line--;
1593         beg--;
1594     }
1595     This->column = 0;
1596     for(; beg>=This->pParserCtxt->input->base && *beg!='\n' && *beg!='\r'; beg--)
1597         This->column++;
1598
1599     if(This->vbInterface && This->saxreader->vblexicalHandler)
1600         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1601     if(!This->vbInterface && This->saxreader->lexicalHandler)
1602         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1603
1604     if(FAILED(hr))
1605     {
1606         format_error_message_from_id(This, hr);
1607         return;
1608     }
1609
1610     realLen = This->pParserCtxt->input->cur-beg-3;
1611     cur = beg;
1612     end = beg;
1613
1614     while(1)
1615     {
1616         while(end-beg<realLen && *end!='\r') end++;
1617         if(end-beg==realLen)
1618         {
1619             end--;
1620             lastEvent = TRUE;
1621         }
1622         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1623             lastEvent = TRUE;
1624
1625         if(*end == '\r') change = TRUE;
1626         else change = FALSE;
1627
1628         if(change) *end = '\n';
1629
1630         if(has_content_handler(This))
1631         {
1632             Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1);
1633             if(This->vbInterface)
1634                 hr = IVBSAXContentHandler_characters(
1635                         This->saxreader->vbcontentHandler, &Chars);
1636             else
1637                 hr = ISAXContentHandler_characters(
1638                         This->saxreader->contentHandler,
1639                         Chars, SysStringLen(Chars));
1640         }
1641
1642         if(change) *end = '\r';
1643
1644         if(lastEvent)
1645             break;
1646
1647         This->column += end-cur+2;
1648         end += 2;
1649         cur = end;
1650     }
1651
1652     if(This->vbInterface && This->saxreader->vblexicalHandler)
1653         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1654     if(!This->vbInterface && This->saxreader->lexicalHandler)
1655         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1656
1657     if(FAILED(hr))
1658         format_error_message_from_id(This, hr);
1659
1660     This->column += 4+end-cur;
1661 }
1662
1663 /*** IVBSAXLocator interface ***/
1664 /*** IUnknown methods ***/
1665 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1666 {
1667     saxlocator *This = impl_from_IVBSAXLocator( iface );
1668
1669     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1670
1671     *ppvObject = NULL;
1672
1673     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1674             IsEqualGUID( riid, &IID_IDispatch) ||
1675             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1676     {
1677         *ppvObject = iface;
1678     }
1679     else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
1680     {
1681         *ppvObject = &This->IVBSAXAttributes_iface;
1682     }
1683     else
1684     {
1685         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1686         return E_NOINTERFACE;
1687     }
1688
1689     IVBSAXLocator_AddRef( iface );
1690
1691     return S_OK;
1692 }
1693
1694 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1695 {
1696     saxlocator *This = impl_from_IVBSAXLocator( iface );
1697     TRACE("%p\n", This );
1698     return InterlockedIncrement( &This->ref );
1699 }
1700
1701 static ULONG WINAPI ivbsaxlocator_Release(
1702         IVBSAXLocator* iface)
1703 {
1704     saxlocator *This = impl_from_IVBSAXLocator( iface );
1705     return ISAXLocator_Release((ISAXLocator*)&This->IVBSAXLocator_iface);
1706 }
1707
1708 /*** IDispatch methods ***/
1709 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1710 {
1711     saxlocator *This = impl_from_IVBSAXLocator( iface );
1712
1713     TRACE("(%p)->(%p)\n", This, pctinfo);
1714
1715     *pctinfo = 1;
1716
1717     return S_OK;
1718 }
1719
1720 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1721     IVBSAXLocator *iface,
1722     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1723 {
1724     saxlocator *This = impl_from_IVBSAXLocator( iface );
1725     HRESULT hr;
1726
1727     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1728
1729     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1730
1731     return hr;
1732 }
1733
1734 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1735     IVBSAXLocator *iface,
1736     REFIID riid,
1737     LPOLESTR* rgszNames,
1738     UINT cNames,
1739     LCID lcid,
1740     DISPID* rgDispId)
1741 {
1742     saxlocator *This = impl_from_IVBSAXLocator( iface );
1743     ITypeInfo *typeinfo;
1744     HRESULT hr;
1745
1746     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1747           lcid, rgDispId);
1748
1749     if(!rgszNames || cNames == 0 || !rgDispId)
1750         return E_INVALIDARG;
1751
1752     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1753     if(SUCCEEDED(hr))
1754     {
1755         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1756         ITypeInfo_Release(typeinfo);
1757     }
1758
1759     return hr;
1760 }
1761
1762 static HRESULT WINAPI ivbsaxlocator_Invoke(
1763     IVBSAXLocator *iface,
1764     DISPID dispIdMember,
1765     REFIID riid,
1766     LCID lcid,
1767     WORD wFlags,
1768     DISPPARAMS* pDispParams,
1769     VARIANT* pVarResult,
1770     EXCEPINFO* pExcepInfo,
1771     UINT* puArgErr)
1772 {
1773     saxlocator *This = impl_from_IVBSAXLocator( iface );
1774     ITypeInfo *typeinfo;
1775     HRESULT hr;
1776
1777     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1778           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1779
1780     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1781     if(SUCCEEDED(hr))
1782     {
1783         hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
1784                 pDispParams, pVarResult, pExcepInfo, puArgErr);
1785         ITypeInfo_Release(typeinfo);
1786     }
1787
1788     return hr;
1789 }
1790
1791 /*** IVBSAXLocator methods ***/
1792 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1793         IVBSAXLocator* iface,
1794         int *pnColumn)
1795 {
1796     saxlocator *This = impl_from_IVBSAXLocator( iface );
1797     return ISAXLocator_getColumnNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnColumn);
1798 }
1799
1800 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1801         IVBSAXLocator* iface,
1802         int *pnLine)
1803 {
1804     saxlocator *This = impl_from_IVBSAXLocator( iface );
1805     return ISAXLocator_getLineNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnLine);
1806 }
1807
1808 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1809         IVBSAXLocator* iface,
1810         BSTR* publicId)
1811 {
1812     saxlocator *This = impl_from_IVBSAXLocator( iface );
1813     return ISAXLocator_getPublicId((ISAXLocator*)&This->IVBSAXLocator_iface,
1814             (const WCHAR**)publicId);
1815 }
1816
1817 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1818         IVBSAXLocator* iface,
1819         BSTR* systemId)
1820 {
1821     saxlocator *This = impl_from_IVBSAXLocator( iface );
1822     return ISAXLocator_getSystemId((ISAXLocator*)&This->IVBSAXLocator_iface,
1823             (const WCHAR**)systemId);
1824 }
1825
1826 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
1827 {
1828     ivbsaxlocator_QueryInterface,
1829     ivbsaxlocator_AddRef,
1830     ivbsaxlocator_Release,
1831     ivbsaxlocator_GetTypeInfoCount,
1832     ivbsaxlocator_GetTypeInfo,
1833     ivbsaxlocator_GetIDsOfNames,
1834     ivbsaxlocator_Invoke,
1835     ivbsaxlocator_get_columnNumber,
1836     ivbsaxlocator_get_lineNumber,
1837     ivbsaxlocator_get_publicId,
1838     ivbsaxlocator_get_systemId
1839 };
1840
1841 /*** ISAXLocator interface ***/
1842 /*** IUnknown methods ***/
1843 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1844 {
1845     saxlocator *This = impl_from_ISAXLocator( iface );
1846
1847     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1848
1849     *ppvObject = NULL;
1850
1851     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1852             IsEqualGUID( riid, &IID_ISAXLocator ))
1853     {
1854         *ppvObject = iface;
1855     }
1856     else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
1857     {
1858         *ppvObject = &This->ISAXAttributes_iface;
1859     }
1860     else
1861     {
1862         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1863         return E_NOINTERFACE;
1864     }
1865
1866     ISAXLocator_AddRef( iface );
1867
1868     return S_OK;
1869 }
1870
1871 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1872 {
1873     saxlocator *This = impl_from_ISAXLocator( iface );
1874     ULONG ref = InterlockedIncrement( &This->ref );
1875     TRACE("(%p)->(%d)\n", This, ref);
1876     return ref;
1877 }
1878
1879 static ULONG WINAPI isaxlocator_Release(
1880         ISAXLocator* iface)
1881 {
1882     saxlocator *This = impl_from_ISAXLocator( iface );
1883     LONG ref = InterlockedDecrement( &This->ref );
1884
1885     TRACE("(%p)->(%d)\n", This, ref );
1886
1887     if (ref == 0)
1888     {
1889         element_entry *element, *element2;
1890         int index;
1891
1892         SysFreeString(This->publicId);
1893         SysFreeString(This->systemId);
1894         SysFreeString(This->namespaceUri);
1895
1896         for(index=0; index<This->nb_attributes; index++)
1897         {
1898             SysFreeString(This->attributes[index].szLocalname);
1899             SysFreeString(This->attributes[index].szValue);
1900             SysFreeString(This->attributes[index].szQName);
1901         }
1902         heap_free(This->attributes);
1903
1904         /* element stack */
1905         LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
1906         {
1907             list_remove(&element->entry);
1908             free_element_entry(element);
1909         }
1910
1911         ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
1912         heap_free( This );
1913     }
1914
1915     return ref;
1916 }
1917
1918 /*** ISAXLocator methods ***/
1919 static HRESULT WINAPI isaxlocator_getColumnNumber(
1920         ISAXLocator* iface,
1921         int *pnColumn)
1922 {
1923     saxlocator *This = impl_from_ISAXLocator( iface );
1924
1925     *pnColumn = This->column;
1926     return S_OK;
1927 }
1928
1929 static HRESULT WINAPI isaxlocator_getLineNumber(
1930         ISAXLocator* iface,
1931         int *pnLine)
1932 {
1933     saxlocator *This = impl_from_ISAXLocator( iface );
1934
1935     *pnLine = This->line;
1936     return S_OK;
1937 }
1938
1939 static HRESULT WINAPI isaxlocator_getPublicId(
1940         ISAXLocator* iface,
1941         const WCHAR ** ppwchPublicId)
1942 {
1943     BSTR publicId;
1944     saxlocator *This = impl_from_ISAXLocator( iface );
1945
1946     SysFreeString(This->publicId);
1947
1948     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1949     if(SysStringLen(publicId))
1950         This->publicId = (WCHAR*)&publicId;
1951     else
1952     {
1953         SysFreeString(publicId);
1954         This->publicId = NULL;
1955     }
1956
1957     *ppwchPublicId = This->publicId;
1958     return S_OK;
1959 }
1960
1961 static HRESULT WINAPI isaxlocator_getSystemId(
1962         ISAXLocator* iface,
1963         const WCHAR ** ppwchSystemId)
1964 {
1965     BSTR systemId;
1966     saxlocator *This = impl_from_ISAXLocator( iface );
1967
1968     SysFreeString(This->systemId);
1969
1970     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1971     if(SysStringLen(systemId))
1972         This->systemId = (WCHAR*)&systemId;
1973     else
1974     {
1975         SysFreeString(systemId);
1976         This->systemId = NULL;
1977     }
1978
1979     *ppwchSystemId = This->systemId;
1980     return S_OK;
1981 }
1982
1983 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
1984 {
1985     isaxlocator_QueryInterface,
1986     isaxlocator_AddRef,
1987     isaxlocator_Release,
1988     isaxlocator_getColumnNumber,
1989     isaxlocator_getLineNumber,
1990     isaxlocator_getPublicId,
1991     isaxlocator_getSystemId
1992 };
1993
1994 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1995 {
1996     static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
1997         'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
1998
1999     saxlocator *locator;
2000
2001     locator = heap_alloc( sizeof (*locator) );
2002     if( !locator )
2003         return E_OUTOFMEMORY;
2004
2005     locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2006     locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2007     locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2008     locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2009     locator->ref = 1;
2010     locator->vbInterface = vbInterface;
2011
2012     locator->saxreader = reader;
2013     ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2014
2015     locator->pParserCtxt = NULL;
2016     locator->publicId = NULL;
2017     locator->systemId = NULL;
2018     locator->line = (reader->version>=MSXML6 ? 1 : 0);
2019     locator->column = 0;
2020     locator->ret = S_OK;
2021     if(locator->saxreader->version >= MSXML6)
2022         locator->namespaceUri = SysAllocString(w3xmlns);
2023     else
2024         locator->namespaceUri = SysAllocStringLen(NULL, 0);
2025     if(!locator->namespaceUri)
2026     {
2027         ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2028         heap_free(locator);
2029         return E_OUTOFMEMORY;
2030     }
2031
2032     locator->attributesSize = 8;
2033     locator->nb_attributes = 0;
2034     locator->attributes = heap_alloc(sizeof(struct _attributes)*locator->attributesSize);
2035     if(!locator->attributes)
2036     {
2037         ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2038         SysFreeString(locator->namespaceUri);
2039         heap_free(locator);
2040         return E_OUTOFMEMORY;
2041     }
2042
2043     list_init(&locator->elements);
2044
2045     *ppsaxlocator = locator;
2046
2047     TRACE("returning %p\n", *ppsaxlocator);
2048
2049     return S_OK;
2050 }
2051
2052 /*** SAXXMLReader internal functions ***/
2053 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2054 {
2055     xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2056     xmlChar *enc_name = NULL;
2057     saxlocator *locator;
2058     HRESULT hr;
2059
2060     hr = SAXLocator_create(This, &locator, vbInterface);
2061     if(FAILED(hr))
2062         return hr;
2063
2064     if (size >= 4)
2065     {
2066         const unsigned char *buff = (unsigned char*)buffer;
2067
2068         encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2069         enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2070         TRACE("detected encoding: %s\n", enc_name);
2071         /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2072         if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2073             buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2074         {
2075             buffer += 3;
2076             size -= 3;
2077         }
2078     }
2079
2080     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2081     if(!locator->pParserCtxt)
2082     {
2083         ISAXLocator_Release(&locator->ISAXLocator_iface);
2084         return E_FAIL;
2085     }
2086
2087     if (encoding == XML_CHAR_ENCODING_UTF8)
2088         locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2089
2090     xmlFree(locator->pParserCtxt->sax);
2091     locator->pParserCtxt->sax = &locator->saxreader->sax;
2092     locator->pParserCtxt->userData = locator;
2093
2094     This->isParsing = TRUE;
2095     if(xmlParseDocument(locator->pParserCtxt)==-1 && locator->ret==S_OK)
2096         hr = E_FAIL;
2097     else
2098         hr = locator->ret;
2099     This->isParsing = FALSE;
2100
2101     if(locator->pParserCtxt)
2102     {
2103         locator->pParserCtxt->sax = NULL;
2104         xmlFreeParserCtxt(locator->pParserCtxt);
2105         locator->pParserCtxt = NULL;
2106     }
2107
2108     ISAXLocator_Release(&locator->ISAXLocator_iface);
2109     return hr;
2110 }
2111
2112 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
2113 {
2114     saxlocator *locator;
2115     HRESULT hr;
2116     ULONG dataRead;
2117     char data[1024];
2118     int ret;
2119
2120     dataRead = 0;
2121     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
2122     if(FAILED(hr)) return hr;
2123
2124     hr = SAXLocator_create(This, &locator, vbInterface);
2125     if(FAILED(hr)) return hr;
2126
2127     locator->pParserCtxt = xmlCreatePushParserCtxt(
2128             &locator->saxreader->sax, locator,
2129             data, dataRead, NULL);
2130     if(!locator->pParserCtxt)
2131     {
2132         ISAXLocator_Release(&locator->ISAXLocator_iface);
2133         return E_FAIL;
2134     }
2135
2136     This->isParsing = TRUE;
2137
2138     if(dataRead != sizeof(data))
2139     {
2140         ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2141         hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2142     }
2143     else
2144     {
2145         while(1)
2146         {
2147             dataRead = 0;
2148             hr = IStream_Read(stream, data, sizeof(data), &dataRead);
2149             if (FAILED(hr)) break;
2150
2151             ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2152             hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2153
2154             if (hr != S_OK) break;
2155
2156             if (dataRead != sizeof(data))
2157             {
2158                 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2159                 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2160                 break;
2161             }
2162         }
2163     }
2164
2165     This->isParsing = FALSE;
2166
2167     xmlFreeParserCtxt(locator->pParserCtxt);
2168     locator->pParserCtxt = NULL;
2169     ISAXLocator_Release(&locator->ISAXLocator_iface);
2170     return hr;
2171 }
2172
2173 static HRESULT internal_getEntityResolver(
2174         saxreader *This,
2175         void *pEntityResolver,
2176         BOOL vbInterface)
2177 {
2178     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
2179     return E_NOTIMPL;
2180 }
2181
2182 static HRESULT internal_putEntityResolver(
2183         saxreader *This,
2184         void *pEntityResolver,
2185         BOOL vbInterface)
2186 {
2187     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
2188     return E_NOTIMPL;
2189 }
2190
2191 static HRESULT internal_getContentHandler(
2192         saxreader* This,
2193         void *pContentHandler,
2194         BOOL vbInterface)
2195 {
2196     TRACE("(%p)->(%p)\n", This, pContentHandler);
2197     if(pContentHandler == NULL)
2198         return E_POINTER;
2199     if((vbInterface && This->vbcontentHandler)
2200             || (!vbInterface && This->contentHandler))
2201     {
2202         if(vbInterface)
2203             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
2204         else
2205             ISAXContentHandler_AddRef(This->contentHandler);
2206     }
2207     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
2208         This->vbcontentHandler;
2209     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
2210
2211     return S_OK;
2212 }
2213
2214 static HRESULT internal_putContentHandler(
2215         saxreader* This,
2216         void *contentHandler,
2217         BOOL vbInterface)
2218 {
2219     TRACE("(%p)->(%p)\n", This, contentHandler);
2220     if(contentHandler)
2221     {
2222         if(vbInterface)
2223             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
2224         else
2225             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
2226     }
2227     if((vbInterface && This->vbcontentHandler)
2228             || (!vbInterface && This->contentHandler))
2229     {
2230         if(vbInterface)
2231             IVBSAXContentHandler_Release(This->vbcontentHandler);
2232         else
2233             ISAXContentHandler_Release(This->contentHandler);
2234     }
2235     if(vbInterface)
2236         This->vbcontentHandler = contentHandler;
2237     else
2238         This->contentHandler = contentHandler;
2239
2240     return S_OK;
2241 }
2242
2243 static HRESULT internal_getDTDHandler(
2244         saxreader* This,
2245         void *pDTDHandler,
2246         BOOL vbInterface)
2247 {
2248     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
2249     return E_NOTIMPL;
2250 }
2251
2252 static HRESULT internal_putDTDHandler(
2253         saxreader* This,
2254         void *pDTDHandler,
2255         BOOL vbInterface)
2256 {
2257     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
2258     return E_NOTIMPL;
2259 }
2260
2261 static HRESULT internal_getErrorHandler(
2262         saxreader* This,
2263         void *pErrorHandler,
2264         BOOL vbInterface)
2265 {
2266     TRACE("(%p)->(%p)\n", This, pErrorHandler);
2267     if(pErrorHandler == NULL)
2268         return E_POINTER;
2269
2270     if(vbInterface && This->vberrorHandler)
2271         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
2272     else if(!vbInterface && This->errorHandler)
2273         ISAXErrorHandler_AddRef(This->errorHandler);
2274
2275     if(vbInterface)
2276         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
2277     else
2278         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
2279
2280     return S_OK;
2281
2282 }
2283
2284 static HRESULT internal_putErrorHandler(
2285         saxreader* This,
2286         void *errorHandler,
2287         BOOL vbInterface)
2288 {
2289     TRACE("(%p)->(%p)\n", This, errorHandler);
2290     if(errorHandler)
2291     {
2292         if(vbInterface)
2293             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
2294         else
2295             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
2296     }
2297
2298     if(vbInterface && This->vberrorHandler)
2299         IVBSAXErrorHandler_Release(This->vberrorHandler);
2300     else if(!vbInterface && This->errorHandler)
2301         ISAXErrorHandler_Release(This->errorHandler);
2302
2303     if(vbInterface)
2304         This->vberrorHandler = errorHandler;
2305     else
2306         This->errorHandler = errorHandler;
2307
2308     return S_OK;
2309
2310 }
2311
2312 static HRESULT internal_parse(
2313         saxreader* This,
2314         VARIANT varInput,
2315         BOOL vbInterface)
2316 {
2317     HRESULT hr;
2318
2319     TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2320
2321     /* Dispose of the BSTRs in the pool from a prior run, if any. */
2322     free_bstr_pool(&This->pool);
2323
2324     switch(V_VT(&varInput))
2325     {
2326         case VT_BSTR:
2327             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2328                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2329             break;
2330         case VT_ARRAY|VT_UI1: {
2331             void *pSAData;
2332             LONG lBound, uBound;
2333             ULONG dataRead;
2334
2335             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2336             if(hr != S_OK) break;
2337             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2338             if(hr != S_OK) break;
2339             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2340             hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2341             if(hr != S_OK) break;
2342             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2343             SafeArrayUnaccessData(V_ARRAY(&varInput));
2344             break;
2345         }
2346         case VT_UNKNOWN:
2347         case VT_DISPATCH: {
2348             IPersistStream *persistStream;
2349             IStream *stream = NULL;
2350             IXMLDOMDocument *xmlDoc;
2351
2352             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2353                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2354             {
2355                 BSTR bstrData;
2356
2357                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2358                 hr = internal_parseBuffer(This, (const char*)bstrData,
2359                         SysStringByteLen(bstrData), vbInterface);
2360                 IXMLDOMDocument_Release(xmlDoc);
2361                 SysFreeString(bstrData);
2362                 break;
2363             }
2364
2365             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2366                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2367             {
2368                 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2369                 if(hr != S_OK)
2370                 {
2371                     IPersistStream_Release(persistStream);
2372                     return hr;
2373                 }
2374
2375                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2376                 IPersistStream_Release(persistStream);
2377                 if(hr != S_OK)
2378                 {
2379                     IStream_Release(stream);
2380                     stream = NULL;
2381                 }
2382             }
2383
2384             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2385                         &IID_IStream, (void**)&stream) == S_OK)
2386             {
2387                 hr = internal_parseStream(This, stream, vbInterface);
2388                 IStream_Release(stream);
2389                 break;
2390             }
2391         }
2392         default:
2393             WARN("vt %d not implemented\n", V_VT(&varInput));
2394             hr = E_INVALIDARG;
2395     }
2396
2397     return hr;
2398 }
2399
2400 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2401 {
2402     saxreader *This = obj;
2403
2404     return internal_parseBuffer(This, ptr, len, TRUE);
2405 }
2406
2407 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2408 {
2409     saxreader *This = obj;
2410
2411     return internal_parseBuffer(This, ptr, len, FALSE);
2412 }
2413
2414 static HRESULT internal_parseURL(
2415         saxreader* This,
2416         const WCHAR *url,
2417         BOOL vbInterface)
2418 {
2419     bsc_t *bsc;
2420     HRESULT hr;
2421
2422     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2423
2424     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2425     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2426
2427     if(FAILED(hr))
2428         return hr;
2429
2430     return detach_bsc(bsc);
2431 }
2432
2433 static HRESULT internal_putProperty(
2434     saxreader* This,
2435     const WCHAR *prop,
2436     VARIANT value,
2437     BOOL vbInterface)
2438 {
2439     TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2440
2441     if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2442     {
2443         if(This->isParsing) return E_FAIL;
2444
2445         switch (V_VT(&value))
2446         {
2447         case VT_EMPTY:
2448             if (vbInterface)
2449             {
2450                 if (This->vbdeclHandler)
2451                 {
2452                     IVBSAXDeclHandler_Release(This->vbdeclHandler);
2453                     This->vbdeclHandler = NULL;
2454                 }
2455             }
2456             else
2457                 if (This->declHandler)
2458                 {
2459                     ISAXDeclHandler_Release(This->declHandler);
2460                     This->declHandler = NULL;
2461                 }
2462             break;
2463         case VT_UNKNOWN:
2464             if (V_UNKNOWN(&value)) IUnknown_AddRef(V_UNKNOWN(&value));
2465
2466             if ((vbInterface && This->vbdeclHandler) ||
2467                (!vbInterface && This->declHandler))
2468             {
2469                 if (vbInterface)
2470                     IVBSAXDeclHandler_Release(This->vbdeclHandler);
2471                 else
2472                     ISAXDeclHandler_Release(This->declHandler);
2473             }
2474
2475             if (vbInterface)
2476                 This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2477             else
2478                 This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2479             break;
2480         default:
2481             return E_INVALIDARG;
2482         }
2483
2484         return S_OK;
2485     }
2486
2487     if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2488     {
2489         if(This->isParsing) return E_FAIL;
2490
2491         switch (V_VT(&value))
2492         {
2493         case VT_EMPTY:
2494             if (vbInterface)
2495             {
2496                 if (This->vblexicalHandler)
2497                 {
2498                     IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2499                     This->vblexicalHandler = NULL;
2500                 }
2501             }
2502             else
2503                 if (This->lexicalHandler)
2504                 {
2505                     ISAXLexicalHandler_Release(This->lexicalHandler);
2506                     This->lexicalHandler = NULL;
2507                 }
2508             break;
2509         case VT_UNKNOWN:
2510             if (V_UNKNOWN(&value)) IUnknown_AddRef(V_UNKNOWN(&value));
2511
2512             if ((vbInterface && This->vblexicalHandler) ||
2513                (!vbInterface && This->lexicalHandler))
2514             {
2515                 if (vbInterface)
2516                     IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2517                 else
2518                     ISAXLexicalHandler_Release(This->lexicalHandler);
2519             }
2520
2521             if (vbInterface)
2522                 This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2523             else
2524                 This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2525             break;
2526         default:
2527             return E_INVALIDARG;
2528         }
2529
2530         return S_OK;
2531     }
2532
2533     if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2534     {
2535         if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
2536         FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(&value));
2537         return E_NOTIMPL;
2538     }
2539
2540     if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2541     {
2542         if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
2543         FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(&value));
2544         return E_NOTIMPL;
2545     }
2546
2547     FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(&value));
2548
2549     if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2550         return E_NOTIMPL;
2551
2552     if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2553         return E_FAIL;
2554
2555     if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2556         return E_NOTIMPL;
2557
2558     if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2559         return E_NOTIMPL;
2560
2561     if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2562         return E_FAIL;
2563
2564     if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2565         return E_FAIL;
2566
2567     if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2568         return E_FAIL;
2569
2570     return E_INVALIDARG;
2571 }
2572
2573 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2574 {
2575     TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2576
2577     if (!value) return E_POINTER;
2578
2579     if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2580     {
2581         V_VT(value) = VT_UNKNOWN;
2582         V_UNKNOWN(value) = vb ? (IUnknown*)This->vblexicalHandler : (IUnknown*)This->lexicalHandler;
2583         if (V_UNKNOWN(value)) IUnknown_AddRef(V_UNKNOWN(value));
2584         return S_OK;
2585     }
2586
2587     if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2588     {
2589         V_VT(value) = VT_UNKNOWN;
2590         V_UNKNOWN(value) = vb ? (IUnknown*)This->vbdeclHandler : (IUnknown*)This->declHandler;
2591         if (V_UNKNOWN(value)) IUnknown_AddRef(V_UNKNOWN(value));
2592         return S_OK;
2593     }
2594
2595     FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2596
2597     return E_NOTIMPL;
2598 }
2599
2600 /*** IVBSAXXMLReader interface ***/
2601 /*** IUnknown methods ***/
2602 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2603 {
2604     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2605
2606     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2607
2608     *ppvObject = NULL;
2609
2610     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2611          IsEqualGUID( riid, &IID_IDispatch ) ||
2612          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2613     {
2614         *ppvObject = iface;
2615     }
2616     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2617     {
2618         *ppvObject = &This->ISAXXMLReader_iface;
2619     }
2620     else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2621     {
2622         return *ppvObject ? S_OK : E_NOINTERFACE;
2623     }
2624     else
2625     {
2626         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2627         return E_NOINTERFACE;
2628     }
2629
2630     IVBSAXXMLReader_AddRef( iface );
2631
2632     return S_OK;
2633 }
2634
2635 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2636 {
2637     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2638     TRACE("%p\n", This );
2639     return InterlockedIncrement( &This->ref );
2640 }
2641
2642 static ULONG WINAPI saxxmlreader_Release(
2643     IVBSAXXMLReader* iface)
2644 {
2645     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2646     LONG ref;
2647
2648     TRACE("%p\n", This );
2649
2650     ref = InterlockedDecrement( &This->ref );
2651     if ( ref == 0 )
2652     {
2653         if(This->contentHandler)
2654             ISAXContentHandler_Release(This->contentHandler);
2655
2656         if(This->vbcontentHandler)
2657             IVBSAXContentHandler_Release(This->vbcontentHandler);
2658
2659         if(This->errorHandler)
2660             ISAXErrorHandler_Release(This->errorHandler);
2661
2662         if(This->vberrorHandler)
2663             IVBSAXErrorHandler_Release(This->vberrorHandler);
2664
2665         if(This->lexicalHandler)
2666             ISAXLexicalHandler_Release(This->lexicalHandler);
2667
2668         if(This->vblexicalHandler)
2669             IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2670
2671         if(This->declHandler)
2672             ISAXDeclHandler_Release(This->declHandler);
2673
2674         if(This->vbdeclHandler)
2675             IVBSAXDeclHandler_Release(This->vbdeclHandler);
2676
2677         free_bstr_pool(&This->pool);
2678
2679         release_dispex(&This->dispex);
2680         heap_free( This );
2681     }
2682
2683     return ref;
2684 }
2685 /*** IDispatch ***/
2686 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2687 {
2688     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2689     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2690 }
2691
2692 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2693     IVBSAXXMLReader *iface,
2694     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2695 {
2696     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2697     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2698         iTInfo, lcid, ppTInfo);
2699 }
2700
2701 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2702     IVBSAXXMLReader *iface,
2703     REFIID riid,
2704     LPOLESTR* rgszNames,
2705     UINT cNames,
2706     LCID lcid,
2707     DISPID* rgDispId)
2708 {
2709     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2710     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2711         riid, rgszNames, cNames, lcid, rgDispId);
2712 }
2713
2714 static HRESULT WINAPI saxxmlreader_Invoke(
2715     IVBSAXXMLReader *iface,
2716     DISPID dispIdMember,
2717     REFIID riid,
2718     LCID lcid,
2719     WORD wFlags,
2720     DISPPARAMS* pDispParams,
2721     VARIANT* pVarResult,
2722     EXCEPINFO* pExcepInfo,
2723     UINT* puArgErr)
2724 {
2725     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2726     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2727         dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2728 }
2729
2730 /*** IVBSAXXMLReader methods ***/
2731 static HRESULT WINAPI saxxmlreader_getFeature(
2732     IVBSAXXMLReader* iface,
2733     const WCHAR *feature,
2734     VARIANT_BOOL *value)
2735 {
2736     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2737
2738     if (!strcmpW(FeatureNamespacesW, feature))
2739         return get_feature_value(This, Namespaces, value);
2740
2741     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature), value);
2742     return E_NOTIMPL;
2743 }
2744
2745 static HRESULT WINAPI saxxmlreader_putFeature(
2746     IVBSAXXMLReader* iface,
2747     const WCHAR *feature,
2748     VARIANT_BOOL value)
2749 {
2750     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2751
2752     TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature), value);
2753
2754     if (!strcmpW(FeatureExternalGeneralEntitiesW, feature) && value == VARIANT_FALSE)
2755         return set_feature_value(This, ExternalGeneralEntities, value);
2756
2757     if (!strcmpW(FeatureExternalParameterEntitiesW, feature) && value == VARIANT_FALSE)
2758         return set_feature_value(This, ExternalParameterEntities, value);
2759
2760     if (!strcmpW(FeatureLexicalHandlerParEntitiesW, feature))
2761     {
2762         FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature), value);
2763         return set_feature_value(This, LexicalHandlerParEntities, value);
2764     }
2765
2766     if (!strcmpW(FeatureProhibitDTDW, feature))
2767     {
2768         FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature), value);
2769         return set_feature_value(This, ProhibitDTD, value);
2770     }
2771
2772     if (!strcmpW(FeatureNamespacesW, feature) && value == VARIANT_TRUE)
2773         return set_feature_value(This, Namespaces, value);
2774
2775     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature), value);
2776     return E_NOTIMPL;
2777 }
2778
2779 static HRESULT WINAPI saxxmlreader_getProperty(
2780     IVBSAXXMLReader* iface,
2781     const WCHAR *prop,
2782     VARIANT *value)
2783 {
2784     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2785     return internal_getProperty(This, prop, value, TRUE);
2786 }
2787
2788 static HRESULT WINAPI saxxmlreader_putProperty(
2789     IVBSAXXMLReader* iface,
2790     const WCHAR *pProp,
2791     VARIANT value)
2792 {
2793     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2794     return internal_putProperty(This, pProp, value, TRUE);
2795 }
2796
2797 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2798     IVBSAXXMLReader* iface,
2799     IVBSAXEntityResolver **pEntityResolver)
2800 {
2801     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2802     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2803 }
2804
2805 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2806     IVBSAXXMLReader* iface,
2807     IVBSAXEntityResolver *pEntityResolver)
2808 {
2809     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2810     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2811 }
2812
2813 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2814     IVBSAXXMLReader* iface,
2815     IVBSAXContentHandler **ppContentHandler)
2816 {
2817     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2818     return internal_getContentHandler(This, ppContentHandler, TRUE);
2819 }
2820
2821 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2822     IVBSAXXMLReader* iface,
2823     IVBSAXContentHandler *contentHandler)
2824 {
2825     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2826     return internal_putContentHandler(This, contentHandler, TRUE);
2827 }
2828
2829 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2830     IVBSAXXMLReader* iface,
2831     IVBSAXDTDHandler **pDTDHandler)
2832 {
2833     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2834     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2835 }
2836
2837 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2838     IVBSAXXMLReader* iface,
2839     IVBSAXDTDHandler *pDTDHandler)
2840 {
2841     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2842     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2843 }
2844
2845 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2846     IVBSAXXMLReader* iface,
2847     IVBSAXErrorHandler **pErrorHandler)
2848 {
2849     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2850     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2851 }
2852
2853 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2854     IVBSAXXMLReader* iface,
2855     IVBSAXErrorHandler *errorHandler)
2856 {
2857     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2858     return internal_putErrorHandler(This, errorHandler, TRUE);
2859 }
2860
2861 static HRESULT WINAPI saxxmlreader_get_baseURL(
2862     IVBSAXXMLReader* iface,
2863     const WCHAR **pBaseUrl)
2864 {
2865     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2866
2867     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2868     return E_NOTIMPL;
2869 }
2870
2871 static HRESULT WINAPI saxxmlreader_put_baseURL(
2872     IVBSAXXMLReader* iface,
2873     const WCHAR *pBaseUrl)
2874 {
2875     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2876
2877     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2878     return E_NOTIMPL;
2879 }
2880
2881 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2882     IVBSAXXMLReader* iface,
2883     const WCHAR **pSecureBaseUrl)
2884 {
2885     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2886
2887     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2888     return E_NOTIMPL;
2889 }
2890
2891
2892 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2893     IVBSAXXMLReader* iface,
2894     const WCHAR *secureBaseUrl)
2895 {
2896     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2897
2898     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2899     return E_NOTIMPL;
2900 }
2901
2902 static HRESULT WINAPI saxxmlreader_parse(
2903     IVBSAXXMLReader* iface,
2904     VARIANT varInput)
2905 {
2906     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2907     return internal_parse(This, varInput, TRUE);
2908 }
2909
2910 static HRESULT WINAPI saxxmlreader_parseURL(
2911     IVBSAXXMLReader* iface,
2912     const WCHAR *url)
2913 {
2914     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2915     return internal_parseURL(This, url, TRUE);
2916 }
2917
2918 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
2919 {
2920     saxxmlreader_QueryInterface,
2921     saxxmlreader_AddRef,
2922     saxxmlreader_Release,
2923     saxxmlreader_GetTypeInfoCount,
2924     saxxmlreader_GetTypeInfo,
2925     saxxmlreader_GetIDsOfNames,
2926     saxxmlreader_Invoke,
2927     saxxmlreader_getFeature,
2928     saxxmlreader_putFeature,
2929     saxxmlreader_getProperty,
2930     saxxmlreader_putProperty,
2931     saxxmlreader_get_entityResolver,
2932     saxxmlreader_put_entityResolver,
2933     saxxmlreader_get_contentHandler,
2934     saxxmlreader_put_contentHandler,
2935     saxxmlreader_get_dtdHandler,
2936     saxxmlreader_put_dtdHandler,
2937     saxxmlreader_get_errorHandler,
2938     saxxmlreader_put_errorHandler,
2939     saxxmlreader_get_baseURL,
2940     saxxmlreader_put_baseURL,
2941     saxxmlreader_get_secureBaseURL,
2942     saxxmlreader_put_secureBaseURL,
2943     saxxmlreader_parse,
2944     saxxmlreader_parseURL
2945 };
2946
2947 /*** ISAXXMLReader interface ***/
2948 /*** IUnknown methods ***/
2949 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2950 {
2951     saxreader *This = impl_from_ISAXXMLReader( iface );
2952     return saxxmlreader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
2953 }
2954
2955 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2956 {
2957     saxreader *This = impl_from_ISAXXMLReader( iface );
2958     return saxxmlreader_AddRef(&This->IVBSAXXMLReader_iface);
2959 }
2960
2961 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2962 {
2963     saxreader *This = impl_from_ISAXXMLReader( iface );
2964     return saxxmlreader_Release(&This->IVBSAXXMLReader_iface);
2965 }
2966
2967 /*** ISAXXMLReader methods ***/
2968 static HRESULT WINAPI isaxxmlreader_getFeature(
2969         ISAXXMLReader* iface,
2970         const WCHAR *pFeature,
2971         VARIANT_BOOL *pValue)
2972 {
2973     saxreader *This = impl_from_ISAXXMLReader( iface );
2974     return IVBSAXXMLReader_getFeature(&This->IVBSAXXMLReader_iface, pFeature, pValue);
2975 }
2976
2977 static HRESULT WINAPI isaxxmlreader_putFeature(
2978         ISAXXMLReader* iface,
2979         const WCHAR *pFeature,
2980         VARIANT_BOOL vfValue)
2981 {
2982     saxreader *This = impl_from_ISAXXMLReader( iface );
2983     return IVBSAXXMLReader_putFeature(&This->IVBSAXXMLReader_iface, pFeature, vfValue);
2984 }
2985
2986 static HRESULT WINAPI isaxxmlreader_getProperty(
2987         ISAXXMLReader* iface,
2988         const WCHAR *prop,
2989         VARIANT *value)
2990 {
2991     saxreader *This = impl_from_ISAXXMLReader( iface );
2992     return internal_getProperty(This, prop, value, FALSE);
2993 }
2994
2995 static HRESULT WINAPI isaxxmlreader_putProperty(
2996         ISAXXMLReader* iface,
2997         const WCHAR *pProp,
2998         VARIANT value)
2999 {
3000     saxreader *This = impl_from_ISAXXMLReader( iface );
3001     return internal_putProperty(This, pProp, value, FALSE);
3002 }
3003
3004 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3005         ISAXXMLReader* iface,
3006         ISAXEntityResolver **ppEntityResolver)
3007 {
3008     saxreader *This = impl_from_ISAXXMLReader( iface );
3009     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
3010 }
3011
3012 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3013         ISAXXMLReader* iface,
3014         ISAXEntityResolver *pEntityResolver)
3015 {
3016     saxreader *This = impl_from_ISAXXMLReader( iface );
3017     return internal_putEntityResolver(This, pEntityResolver, FALSE);
3018 }
3019
3020 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3021         ISAXXMLReader* iface,
3022         ISAXContentHandler **pContentHandler)
3023 {
3024     saxreader *This = impl_from_ISAXXMLReader( iface );
3025     return internal_getContentHandler(This, pContentHandler, FALSE);
3026 }
3027
3028 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3029         ISAXXMLReader* iface,
3030         ISAXContentHandler *contentHandler)
3031 {
3032     saxreader *This = impl_from_ISAXXMLReader( iface );
3033     return internal_putContentHandler(This, contentHandler, FALSE);
3034 }
3035
3036 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3037         ISAXXMLReader* iface,
3038         ISAXDTDHandler **pDTDHandler)
3039 {
3040     saxreader *This = impl_from_ISAXXMLReader( iface );
3041     return internal_getDTDHandler(This, pDTDHandler, FALSE);
3042 }
3043
3044 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3045         ISAXXMLReader* iface,
3046         ISAXDTDHandler *pDTDHandler)
3047 {
3048     saxreader *This = impl_from_ISAXXMLReader( iface );
3049     return internal_putDTDHandler(This, pDTDHandler, FALSE);
3050 }
3051
3052 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3053         ISAXXMLReader* iface,
3054         ISAXErrorHandler **pErrorHandler)
3055 {
3056     saxreader *This = impl_from_ISAXXMLReader( iface );
3057     return internal_getErrorHandler(This, pErrorHandler, FALSE);
3058 }
3059
3060 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
3061         ISAXXMLReader* iface,
3062         ISAXErrorHandler *errorHandler)
3063 {
3064     saxreader *This = impl_from_ISAXXMLReader( iface );
3065     return internal_putErrorHandler(This, errorHandler, FALSE);
3066 }
3067
3068 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3069         ISAXXMLReader* iface,
3070         const WCHAR **pBaseUrl)
3071 {
3072     saxreader *This = impl_from_ISAXXMLReader( iface );
3073     return IVBSAXXMLReader_get_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
3074 }
3075
3076 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3077         ISAXXMLReader* iface,
3078         const WCHAR *pBaseUrl)
3079 {
3080     saxreader *This = impl_from_ISAXXMLReader( iface );
3081     return IVBSAXXMLReader_put_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
3082 }
3083
3084 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3085         ISAXXMLReader* iface,
3086         const WCHAR **pSecureBaseUrl)
3087 {
3088     saxreader *This = impl_from_ISAXXMLReader( iface );
3089     return IVBSAXXMLReader_get_secureBaseURL(&This->IVBSAXXMLReader_iface, pSecureBaseUrl);
3090 }
3091
3092 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3093         ISAXXMLReader* iface,
3094         const WCHAR *secureBaseUrl)
3095 {
3096     saxreader *This = impl_from_ISAXXMLReader( iface );
3097     return IVBSAXXMLReader_put_secureBaseURL(&This->IVBSAXXMLReader_iface, secureBaseUrl);
3098 }
3099
3100 static HRESULT WINAPI isaxxmlreader_parse(
3101         ISAXXMLReader* iface,
3102         VARIANT varInput)
3103 {
3104     saxreader *This = impl_from_ISAXXMLReader( iface );
3105     return internal_parse(This, varInput, FALSE);
3106 }
3107
3108 static HRESULT WINAPI isaxxmlreader_parseURL(
3109         ISAXXMLReader* iface,
3110         const WCHAR *url)
3111 {
3112     saxreader *This = impl_from_ISAXXMLReader( iface );
3113     return internal_parseURL(This, url, FALSE);
3114 }
3115
3116 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3117 {
3118     isaxxmlreader_QueryInterface,
3119     isaxxmlreader_AddRef,
3120     isaxxmlreader_Release,
3121     isaxxmlreader_getFeature,
3122     isaxxmlreader_putFeature,
3123     isaxxmlreader_getProperty,
3124     isaxxmlreader_putProperty,
3125     isaxxmlreader_getEntityResolver,
3126     isaxxmlreader_putEntityResolver,
3127     isaxxmlreader_getContentHandler,
3128     isaxxmlreader_putContentHandler,
3129     isaxxmlreader_getDTDHandler,
3130     isaxxmlreader_putDTDHandler,
3131     isaxxmlreader_getErrorHandler,
3132     isaxxmlreader_putErrorHandler,
3133     isaxxmlreader_getBaseURL,
3134     isaxxmlreader_putBaseURL,
3135     isaxxmlreader_getSecureBaseURL,
3136     isaxxmlreader_putSecureBaseURL,
3137     isaxxmlreader_parse,
3138     isaxxmlreader_parseURL
3139 };
3140
3141 static const tid_t saxreader_iface_tids[] = {
3142     IVBSAXXMLReader_tid,
3143     0
3144 };
3145 static dispex_static_data_t saxreader_dispex = {
3146     NULL,
3147     IVBSAXXMLReader_tid,
3148     NULL,
3149     saxreader_iface_tids
3150 };
3151
3152 HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppObj)
3153 {
3154     saxreader *reader;
3155
3156     TRACE("(%p, %p)\n", outer, ppObj);
3157
3158     reader = heap_alloc( sizeof (*reader) );
3159     if( !reader )
3160         return E_OUTOFMEMORY;
3161
3162     reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3163     reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3164     reader->ref = 1;
3165     reader->contentHandler = NULL;
3166     reader->vbcontentHandler = NULL;
3167     reader->errorHandler = NULL;
3168     reader->vberrorHandler = NULL;
3169     reader->lexicalHandler = NULL;
3170     reader->vblexicalHandler = NULL;
3171     reader->declHandler = NULL;
3172     reader->vbdeclHandler = NULL;
3173     reader->isParsing = FALSE;
3174     reader->pool.pool = NULL;
3175     reader->pool.index = 0;
3176     reader->pool.len = 0;
3177     reader->features = Namespaces;
3178     reader->version = version;
3179
3180     init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3181
3182     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3183     reader->sax.initialized = XML_SAX2_MAGIC;
3184     reader->sax.startDocument = libxmlStartDocument;
3185     reader->sax.endDocument = libxmlEndDocument;
3186     reader->sax.startElementNs = libxmlStartElementNS;
3187     reader->sax.endElementNs = libxmlEndElementNS;
3188     reader->sax.characters = libxmlCharacters;
3189     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3190     reader->sax.comment = libxmlComment;
3191     reader->sax.error = libxmlFatalError;
3192     reader->sax.fatalError = libxmlFatalError;
3193     reader->sax.cdataBlock = libxmlCDataBlock;
3194
3195     *ppObj = &reader->IVBSAXXMLReader_iface;
3196
3197     TRACE("returning iface %p\n", *ppObj);
3198
3199     return S_OK;
3200 }
3201
3202 #else
3203
3204 HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *pUnkOuter, LPVOID *ppObj)
3205 {
3206     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3207             "libxml2 support was not present at compile time.\n");
3208     return E_NOTIMPL;
3209 }
3210
3211 #endif