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