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