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