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