5c8923caac7f8ce162838154fb7c08a405369c31
[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 len = SysStringLen(bstr);
1954 ptr = bstr + len - 1;
1955 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1956 ptr--;
1957
1958 while (*++ptr)
1959 {
1960 /* replace returns as:
1961
1962 - "\r<char>" -> "\n<char>"
1963 - "\r\r" -> "\r"
1964 - "\r\n" -> "\n"
1965 */
1966 if (*ptr == '\r')
1967 {
1968 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1969 {
1970 /* shift tail */
1971 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1972 }
1973 else
1974 *ptr = '\n';
1975 }
1976 }
1977
1978 ret = SysAllocStringLen(bstr, len);
1979 SysFreeString(bstr);
1980 return ret;
1981 }
1982
1983 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
1984 {
1985 const xmlChar *start, *end;
1986 saxlocator *locator = ctx;
1987 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
1988 HRESULT hr = S_OK;
1989 BSTR chars;
1990 int i;
1991
1992 update_position(locator, FALSE);
1993 if (saxreader_has_handler(locator, SAXLexicalHandler))
1994 {
1995 if (locator->vbInterface)
1996 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
1997 else
1998 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
1999 }
2000
2001 if(FAILED(hr))
2002 {
2003 format_error_message_from_id(locator, hr);
2004 return;
2005 }
2006
2007 start = value;
2008 end = NULL;
2009 i = 0;
2010
2011 while (i < len)
2012 {
2013 /* scan for newlines */
2014 if (value[i] == '\r' || value[i] == '\n')
2015 {
2016 /* skip newlines/linefeeds */
2017 while (i < len)
2018 {
2019 if (value[i] != '\r' && value[i] != '\n') break;
2020 i++;
2021 }
2022 end = &value[i];
2023
2024 /* report */
2025 chars = saxreader_get_cdata_chunk(start, end-start);
2026 TRACE("(chunk %s)\n", debugstr_w(chars));
2027 hr = saxreader_saxcharacters(locator, chars);
2028 SysFreeString(chars);
2029
2030 start = &value[i];
2031 end = NULL;
2032 }
2033 i++;
2034 locator->column++;
2035 }
2036
2037 /* no newline chars (or last chunk) report as a whole */
2038 if (!end && start == value)
2039 {
2040 /* report */
2041 chars = bstr_from_xmlCharN(start, len-(start-value));
2042 TRACE("(%s)\n", debugstr_w(chars));
2043 hr = saxreader_saxcharacters(locator, chars);
2044 SysFreeString(chars);
2045 }
2046
2047 if (saxreader_has_handler(locator, SAXLexicalHandler))
2048 {
2049 if (locator->vbInterface)
2050 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2051 else
2052 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2053 }
2054
2055 if(FAILED(hr))
2056 format_error_message_from_id(locator, hr);
2057 }
2058
2059 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2060 {
2061 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2062 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2063 }
2064
2065 /*** IVBSAXLocator interface ***/
2066 /*** IUnknown methods ***/
2067 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2068 {
2069 saxlocator *This = impl_from_IVBSAXLocator( iface );
2070
2071 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2072
2073 *ppvObject = NULL;
2074
2075 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2076 IsEqualGUID( riid, &IID_IDispatch) ||
2077 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2078 {
2079 *ppvObject = iface;
2080 }
2081 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2082 {
2083 *ppvObject = &This->IVBSAXAttributes_iface;
2084 }
2085 else
2086 {
2087 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2088 return E_NOINTERFACE;
2089 }
2090
2091 IVBSAXLocator_AddRef( iface );
2092
2093 return S_OK;
2094 }
2095
2096 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2097 {
2098 saxlocator *This = impl_from_IVBSAXLocator( iface );
2099 TRACE("%p\n", This );
2100 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2101 }
2102
2103 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2104 {
2105 saxlocator *This = impl_from_IVBSAXLocator( iface );
2106 return ISAXLocator_Release(&This->ISAXLocator_iface);
2107 }
2108
2109 /*** IDispatch methods ***/
2110 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2111 {
2112 saxlocator *This = impl_from_IVBSAXLocator( iface );
2113
2114 TRACE("(%p)->(%p)\n", This, pctinfo);
2115
2116 *pctinfo = 1;
2117
2118 return S_OK;
2119 }
2120
2121 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2122 IVBSAXLocator *iface,
2123 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2124 {
2125 saxlocator *This = impl_from_IVBSAXLocator( iface );
2126
2127 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2128
2129 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2130 }
2131
2132 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2133 IVBSAXLocator *iface,
2134 REFIID riid,
2135 LPOLESTR* rgszNames,
2136 UINT cNames,
2137 LCID lcid,
2138 DISPID* rgDispId)
2139 {
2140 saxlocator *This = impl_from_IVBSAXLocator( iface );
2141 ITypeInfo *typeinfo;
2142 HRESULT hr;
2143
2144 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2145 lcid, rgDispId);
2146
2147 if(!rgszNames || cNames == 0 || !rgDispId)
2148 return E_INVALIDARG;
2149
2150 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2151 if(SUCCEEDED(hr))
2152 {
2153 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2154 ITypeInfo_Release(typeinfo);
2155 }
2156
2157 return hr;
2158 }
2159
2160 static HRESULT WINAPI ivbsaxlocator_Invoke(
2161 IVBSAXLocator *iface,
2162 DISPID dispIdMember,
2163 REFIID riid,
2164 LCID lcid,
2165 WORD wFlags,
2166 DISPPARAMS* pDispParams,
2167 VARIANT* pVarResult,
2168 EXCEPINFO* pExcepInfo,
2169 UINT* puArgErr)
2170 {
2171 saxlocator *This = impl_from_IVBSAXLocator( iface );
2172 ITypeInfo *typeinfo;
2173 HRESULT hr;
2174
2175 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2176 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2177
2178 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2179 if(SUCCEEDED(hr))
2180 {
2181 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2182 pDispParams, pVarResult, pExcepInfo, puArgErr);
2183 ITypeInfo_Release(typeinfo);
2184 }
2185
2186 return hr;
2187 }
2188
2189 /*** IVBSAXLocator methods ***/
2190 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2191 IVBSAXLocator* iface,
2192 int *pnColumn)
2193 {
2194 saxlocator *This = impl_from_IVBSAXLocator( iface );
2195 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2196 }
2197
2198 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2199 IVBSAXLocator* iface,
2200 int *pnLine)
2201 {
2202 saxlocator *This = impl_from_IVBSAXLocator( iface );
2203 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2204 }
2205
2206 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2207 {
2208 saxlocator *This = impl_from_IVBSAXLocator( iface );
2209 const WCHAR *publicidW;
2210 HRESULT hr;
2211
2212 TRACE("(%p)->(%p)\n", This, ret);
2213
2214 if (!ret)
2215 return E_POINTER;
2216
2217 *ret = NULL;
2218 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2219 if (FAILED(hr))
2220 return hr;
2221
2222 return return_bstr(publicidW, ret);
2223 }
2224
2225 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2226 {
2227 saxlocator *This = impl_from_IVBSAXLocator( iface );
2228 const WCHAR *systemidW;
2229 HRESULT hr;
2230
2231 TRACE("(%p)->(%p)\n", This, ret);
2232
2233 if (!ret)
2234 return E_POINTER;
2235
2236 *ret = NULL;
2237 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2238 if (FAILED(hr))
2239 return hr;
2240
2241 return return_bstr(systemidW, ret);
2242 }
2243
2244 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2245 {
2246 ivbsaxlocator_QueryInterface,
2247 ivbsaxlocator_AddRef,
2248 ivbsaxlocator_Release,
2249 ivbsaxlocator_GetTypeInfoCount,
2250 ivbsaxlocator_GetTypeInfo,
2251 ivbsaxlocator_GetIDsOfNames,
2252 ivbsaxlocator_Invoke,
2253 ivbsaxlocator_get_columnNumber,
2254 ivbsaxlocator_get_lineNumber,
2255 ivbsaxlocator_get_publicId,
2256 ivbsaxlocator_get_systemId
2257 };
2258
2259 /*** ISAXLocator interface ***/
2260 /*** IUnknown methods ***/
2261 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2262 {
2263 saxlocator *This = impl_from_ISAXLocator( iface );
2264
2265 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2266
2267 *ppvObject = NULL;
2268
2269 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2270 IsEqualGUID( riid, &IID_ISAXLocator ))
2271 {
2272 *ppvObject = iface;
2273 }
2274 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2275 {
2276 *ppvObject = &This->ISAXAttributes_iface;
2277 }
2278 else
2279 {
2280 WARN("interface %s not implemented\n", debugstr_guid(riid));
2281 return E_NOINTERFACE;
2282 }
2283
2284 ISAXLocator_AddRef( iface );
2285
2286 return S_OK;
2287 }
2288
2289 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2290 {
2291 saxlocator *This = impl_from_ISAXLocator( iface );
2292 ULONG ref = InterlockedIncrement( &This->ref );
2293 TRACE("(%p)->(%d)\n", This, ref);
2294 return ref;
2295 }
2296
2297 static ULONG WINAPI isaxlocator_Release(
2298 ISAXLocator* iface)
2299 {
2300 saxlocator *This = impl_from_ISAXLocator( iface );
2301 LONG ref = InterlockedDecrement( &This->ref );
2302
2303 TRACE("(%p)->(%d)\n", This, ref );
2304
2305 if (ref == 0)
2306 {
2307 element_entry *element, *element2;
2308 int index;
2309
2310 SysFreeString(This->publicId);
2311 SysFreeString(This->systemId);
2312 SysFreeString(This->namespaceUri);
2313
2314 for(index = 0; index < This->attr_alloc_count; index++)
2315 {
2316 SysFreeString(This->attributes[index].szLocalname);
2317 SysFreeString(This->attributes[index].szValue);
2318 SysFreeString(This->attributes[index].szQName);
2319 }
2320 heap_free(This->attributes);
2321
2322 /* element stack */
2323 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2324 {
2325 list_remove(&element->entry);
2326 free_element_entry(element);
2327 }
2328
2329 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2330 heap_free( This );
2331 }
2332
2333 return ref;
2334 }
2335
2336 /*** ISAXLocator methods ***/
2337 static HRESULT WINAPI isaxlocator_getColumnNumber(
2338 ISAXLocator* iface,
2339 int *pnColumn)
2340 {
2341 saxlocator *This = impl_from_ISAXLocator( iface );
2342
2343 *pnColumn = This->column;
2344 return S_OK;
2345 }
2346
2347 static HRESULT WINAPI isaxlocator_getLineNumber(
2348 ISAXLocator* iface,
2349 int *pnLine)
2350 {
2351 saxlocator *This = impl_from_ISAXLocator( iface );
2352
2353 *pnLine = This->line;
2354 return S_OK;
2355 }
2356
2357 static HRESULT WINAPI isaxlocator_getPublicId(
2358 ISAXLocator* iface,
2359 const WCHAR ** ppwchPublicId)
2360 {
2361 BSTR publicId;
2362 saxlocator *This = impl_from_ISAXLocator( iface );
2363
2364 SysFreeString(This->publicId);
2365
2366 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2367 if(SysStringLen(publicId))
2368 This->publicId = publicId;
2369 else
2370 {
2371 SysFreeString(publicId);
2372 This->publicId = NULL;
2373 }
2374
2375 *ppwchPublicId = This->publicId;
2376 return S_OK;
2377 }
2378
2379 static HRESULT WINAPI isaxlocator_getSystemId(
2380 ISAXLocator* iface,
2381 const WCHAR ** ppwchSystemId)
2382 {
2383 BSTR systemId;
2384 saxlocator *This = impl_from_ISAXLocator( iface );
2385
2386 SysFreeString(This->systemId);
2387
2388 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2389 if(SysStringLen(systemId))
2390 This->systemId = systemId;
2391 else
2392 {
2393 SysFreeString(systemId);
2394 This->systemId = NULL;
2395 }
2396
2397 *ppwchSystemId = This->systemId;
2398 return S_OK;
2399 }
2400
2401 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2402 {
2403 isaxlocator_QueryInterface,
2404 isaxlocator_AddRef,
2405 isaxlocator_Release,
2406 isaxlocator_getColumnNumber,
2407 isaxlocator_getLineNumber,
2408 isaxlocator_getPublicId,
2409 isaxlocator_getSystemId
2410 };
2411
2412 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2413 {
2414 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2415 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2416
2417 saxlocator *locator;
2418
2419 locator = heap_alloc( sizeof (*locator) );
2420 if( !locator )
2421 return E_OUTOFMEMORY;
2422
2423 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2424 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2425 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2426 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2427 locator->ref = 1;
2428 locator->vbInterface = vbInterface;
2429
2430 locator->saxreader = reader;
2431 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2432
2433 locator->pParserCtxt = NULL;
2434 locator->publicId = NULL;
2435 locator->systemId = NULL;
2436 locator->line = reader->version < MSXML4 ? 0 : 1;
2437 locator->column = 0;
2438 locator->ret = S_OK;
2439 if (locator->saxreader->version >= MSXML6)
2440 locator->namespaceUri = SysAllocString(w3xmlns);
2441 else
2442 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2443 if(!locator->namespaceUri)
2444 {
2445 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2446 heap_free(locator);
2447 return E_OUTOFMEMORY;
2448 }
2449
2450 locator->attr_alloc_count = 8;
2451 locator->attr_count = 0;
2452 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2453 if(!locator->attributes)
2454 {
2455 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2456 SysFreeString(locator->namespaceUri);
2457 heap_free(locator);
2458 return E_OUTOFMEMORY;
2459 }
2460
2461 list_init(&locator->elements);
2462
2463 *ppsaxlocator = locator;
2464
2465 TRACE("returning %p\n", *ppsaxlocator);
2466
2467 return S_OK;
2468 }
2469
2470 /*** SAXXMLReader internal functions ***/
2471 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2472 {
2473 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2474 xmlChar *enc_name = NULL;
2475 saxlocator *locator;
2476 HRESULT hr;
2477
2478 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2479
2480 hr = SAXLocator_create(This, &locator, vbInterface);
2481 if (FAILED(hr))
2482 return hr;
2483
2484 if (size >= 4)
2485 {
2486 const unsigned char *buff = (unsigned char*)buffer;
2487
2488 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2489 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2490 TRACE("detected encoding: %s\n", enc_name);
2491 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2492 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2493 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2494 {
2495 buffer += 3;
2496 size -= 3;
2497 }
2498 }
2499
2500 /* if libxml2 detection failed try to guess */
2501 if (encoding == XML_CHAR_ENCODING_NONE)
2502 {
2503 const WCHAR *ptr = (WCHAR*)buffer;
2504 /* an xml declaration with optional encoding will still be handled by the parser */
2505 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2506 {
2507 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2508 encoding = XML_CHAR_ENCODING_UTF16LE;
2509 }
2510 }
2511 else if (encoding == XML_CHAR_ENCODING_UTF8)
2512 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2513 else
2514 enc_name = NULL;
2515
2516 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2517 if (!locator->pParserCtxt)
2518 {
2519 ISAXLocator_Release(&locator->ISAXLocator_iface);
2520 return E_FAIL;
2521 }
2522
2523 if (enc_name)
2524 {
2525 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2526 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2527 TRACE("switching to %s\n", enc_name);
2528 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2529 }
2530 }
2531
2532 xmlFree(locator->pParserCtxt->sax);
2533 locator->pParserCtxt->sax = &locator->saxreader->sax;
2534 locator->pParserCtxt->userData = locator;
2535
2536 This->isParsing = TRUE;
2537 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2538 hr = E_FAIL;
2539 else
2540 hr = locator->ret;
2541 This->isParsing = FALSE;
2542
2543 if(locator->pParserCtxt)
2544 {
2545 locator->pParserCtxt->sax = NULL;
2546 xmlFreeParserCtxt(locator->pParserCtxt);
2547 locator->pParserCtxt = NULL;
2548 }
2549
2550 ISAXLocator_Release(&locator->ISAXLocator_iface);
2551 return hr;
2552 }
2553
2554 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2555 {
2556 saxlocator *locator;
2557 HRESULT hr;
2558 ULONG dataRead;
2559 char data[2048];
2560 int ret;
2561
2562 dataRead = 0;
2563 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2564 if(FAILED(hr)) return hr;
2565
2566 hr = SAXLocator_create(This, &locator, vbInterface);
2567 if(FAILED(hr)) return hr;
2568
2569 locator->pParserCtxt = xmlCreatePushParserCtxt(
2570 &locator->saxreader->sax, locator,
2571 data, dataRead, NULL);
2572 if(!locator->pParserCtxt)
2573 {
2574 ISAXLocator_Release(&locator->ISAXLocator_iface);
2575 return E_FAIL;
2576 }
2577
2578 This->isParsing = TRUE;
2579
2580 do {
2581 dataRead = 0;
2582 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2583 if (FAILED(hr) || !dataRead) break;
2584
2585 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2586 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2587 }while(hr == S_OK);
2588
2589 if(SUCCEEDED(hr))
2590 {
2591 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2592 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2593 }
2594
2595
2596 This->isParsing = FALSE;
2597
2598 xmlFreeParserCtxt(locator->pParserCtxt);
2599 locator->pParserCtxt = NULL;
2600 ISAXLocator_Release(&locator->ISAXLocator_iface);
2601 return hr;
2602 }
2603
2604 static HRESULT internal_parse(
2605 saxreader* This,
2606 VARIANT varInput,
2607 BOOL vbInterface)
2608 {
2609 HRESULT hr;
2610
2611 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2612
2613 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2614 free_bstr_pool(&This->pool);
2615
2616 switch(V_VT(&varInput))
2617 {
2618 case VT_BSTR:
2619 case VT_BSTR|VT_BYREF:
2620 {
2621 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2622 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2623 break;
2624 }
2625 case VT_ARRAY|VT_UI1: {
2626 void *pSAData;
2627 LONG lBound, uBound;
2628 ULONG dataRead;
2629
2630 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2631 if(hr != S_OK) break;
2632 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2633 if(hr != S_OK) break;
2634 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2635 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2636 if(hr != S_OK) break;
2637 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2638 SafeArrayUnaccessData(V_ARRAY(&varInput));
2639 break;
2640 }
2641 case VT_UNKNOWN:
2642 case VT_DISPATCH: {
2643 ISequentialStream *stream = NULL;
2644 IXMLDOMDocument *xmlDoc;
2645
2646 if (!V_UNKNOWN(&varInput))
2647 return E_INVALIDARG;
2648
2649 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2650 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2651 {
2652 BSTR bstrData;
2653
2654 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2655 hr = internal_parseBuffer(This, (const char*)bstrData,
2656 SysStringByteLen(bstrData), vbInterface);
2657 IXMLDOMDocument_Release(xmlDoc);
2658 SysFreeString(bstrData);
2659 break;
2660 }
2661
2662 /* try base interface first */
2663 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2664 if (!stream)
2665 /* this should never happen if IStream is implemented properly, but just in case */
2666 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2667
2668 if(stream)
2669 {
2670 hr = internal_parseStream(This, stream, vbInterface);
2671 ISequentialStream_Release(stream);
2672 }
2673 else
2674 {
2675 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2676 hr = E_INVALIDARG;
2677 }
2678
2679 break;
2680 }
2681 default:
2682 WARN("vt %d not implemented\n", V_VT(&varInput));
2683 hr = E_INVALIDARG;
2684 }
2685
2686 return hr;
2687 }
2688
2689 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2690 {
2691 saxreader *This = obj;
2692
2693 return internal_parseBuffer(This, ptr, len, TRUE);
2694 }
2695
2696 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2697 {
2698 saxreader *This = obj;
2699
2700 return internal_parseBuffer(This, ptr, len, FALSE);
2701 }
2702
2703 static HRESULT internal_parseURL(
2704 saxreader* This,
2705 const WCHAR *url,
2706 BOOL vbInterface)
2707 {
2708 IMoniker *mon;
2709 bsc_t *bsc;
2710 HRESULT hr;
2711
2712 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2713
2714 hr = create_moniker_from_url(url, &mon);
2715 if(FAILED(hr))
2716 return hr;
2717
2718 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2719 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2720 IMoniker_Release(mon);
2721
2722 if(FAILED(hr))
2723 return hr;
2724
2725 return detach_bsc(bsc);
2726 }
2727
2728 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2729 {
2730 const IID *riid;
2731
2732 if (V_VT(v) == VT_EMPTY)
2733 return saxreader_put_handler(This, type, NULL, vb);
2734
2735 switch (type)
2736 {
2737 case SAXDeclHandler:
2738 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2739 break;
2740 case SAXLexicalHandler:
2741 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2742 break;
2743 default:
2744 ERR("wrong handler type %d\n", type);
2745 return E_FAIL;
2746 }
2747
2748 switch (V_VT(v))
2749 {
2750 case VT_DISPATCH:
2751 case VT_UNKNOWN:
2752 {
2753 IUnknown *handler = NULL;
2754
2755 if (V_UNKNOWN(v))
2756 {
2757 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2758 if (FAILED(hr)) return hr;
2759 }
2760
2761 saxreader_put_handler(This, type, handler, vb);
2762 if (handler) IUnknown_Release(handler);
2763 break;
2764 }
2765 default:
2766 ERR("value type %d not supported\n", V_VT(v));
2767 return E_INVALIDARG;
2768 }
2769
2770 return S_OK;
2771 }
2772
2773 static HRESULT internal_putProperty(
2774 saxreader* This,
2775 const WCHAR *prop,
2776 VARIANT value,
2777 BOOL vbInterface)
2778 {
2779 VARIANT *v;
2780
2781 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2782
2783 if (This->isParsing) return E_FAIL;
2784
2785 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2786 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2787 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2788
2789 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2790 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2791
2792 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2793 {
2794 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2795 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2796 return E_NOTIMPL;
2797 }
2798
2799 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2800 {
2801 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2802 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2803 return E_NOTIMPL;
2804 }
2805
2806 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2807
2808 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2809 return E_NOTIMPL;
2810
2811 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2812 return E_FAIL;
2813
2814 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2815 return E_NOTIMPL;
2816
2817 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2818 return E_NOTIMPL;
2819
2820 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2821 return E_FAIL;
2822
2823 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2824 return E_FAIL;
2825
2826 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2827 return E_FAIL;
2828
2829 return E_INVALIDARG;
2830 }
2831
2832 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2833 {
2834 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2835
2836 if (!value) return E_POINTER;
2837
2838 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2839 {
2840 V_VT(value) = VT_UNKNOWN;
2841 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2842 return S_OK;
2843 }
2844
2845 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2846 {
2847 V_VT(value) = VT_UNKNOWN;
2848 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2849 return S_OK;
2850 }
2851
2852 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2853 {
2854 V_VT(value) = VT_BSTR;
2855 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2856 return S_OK;
2857 }
2858
2859 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2860
2861 return E_NOTIMPL;
2862 }
2863
2864 /*** IVBSAXXMLReader interface ***/
2865 /*** IUnknown methods ***/
2866 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2867 {
2868 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2869
2870 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2871
2872 *ppvObject = NULL;
2873
2874 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2875 IsEqualGUID( riid, &IID_IDispatch ) ||
2876 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2877 {
2878 *ppvObject = iface;
2879 }
2880 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2881 {
2882 *ppvObject = &This->ISAXXMLReader_iface;
2883 }
2884 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2885 {
2886 return *ppvObject ? S_OK : E_NOINTERFACE;
2887 }
2888 else
2889 {
2890 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2891 return E_NOINTERFACE;
2892 }
2893
2894 IVBSAXXMLReader_AddRef( iface );
2895
2896 return S_OK;
2897 }
2898
2899 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2900 {
2901 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2902 TRACE("%p\n", This );
2903 return InterlockedIncrement( &This->ref );
2904 }
2905
2906 static ULONG WINAPI saxxmlreader_Release(
2907 IVBSAXXMLReader* iface)
2908 {
2909 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2910 LONG ref;
2911
2912 TRACE("%p\n", This );
2913
2914 ref = InterlockedDecrement( &This->ref );
2915 if ( ref == 0 )
2916 {
2917 int i;
2918
2919 for (i = 0; i < SAXHandler_Last; i++)
2920 {
2921 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2922
2923 if (saxiface->handler)
2924 IUnknown_Release(saxiface->handler);
2925
2926 if (saxiface->vbhandler)
2927 IUnknown_Release(saxiface->vbhandler);
2928 }
2929
2930 SysFreeString(This->xmldecl_version);
2931 free_bstr_pool(&This->pool);
2932
2933 heap_free( This );
2934 }
2935
2936 return ref;
2937 }
2938 /*** IDispatch ***/
2939 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2940 {
2941 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2942 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2943 }
2944
2945 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2946 IVBSAXXMLReader *iface,
2947 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2948 {
2949 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2950 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2951 iTInfo, lcid, ppTInfo);
2952 }
2953
2954 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2955 IVBSAXXMLReader *iface,
2956 REFIID riid,
2957 LPOLESTR* rgszNames,
2958 UINT cNames,
2959 LCID lcid,
2960 DISPID* rgDispId)
2961 {
2962 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2963 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2964 riid, rgszNames, cNames, lcid, rgDispId);
2965 }
2966
2967 static HRESULT WINAPI saxxmlreader_Invoke(
2968 IVBSAXXMLReader *iface,
2969 DISPID dispIdMember,
2970 REFIID riid,
2971 LCID lcid,
2972 WORD wFlags,
2973 DISPPARAMS* pDispParams,
2974 VARIANT* pVarResult,
2975 EXCEPINFO* pExcepInfo,
2976 UINT* puArgErr)
2977 {
2978 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2979 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2980 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2981 }
2982
2983 /*** IVBSAXXMLReader methods ***/
2984 static HRESULT WINAPI saxxmlreader_getFeature(
2985 IVBSAXXMLReader* iface,
2986 BSTR feature_name,
2987 VARIANT_BOOL *value)
2988 {
2989 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2990 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
2991 }
2992
2993 static HRESULT WINAPI saxxmlreader_putFeature(
2994 IVBSAXXMLReader* iface,
2995 BSTR feature_name,
2996 VARIANT_BOOL value)
2997 {
2998 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2999 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3000 }
3001
3002 static HRESULT WINAPI saxxmlreader_getProperty(
3003 IVBSAXXMLReader* iface,
3004 BSTR prop,
3005 VARIANT *value)
3006 {
3007 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3008 return internal_getProperty(This, prop, value, TRUE);
3009 }
3010
3011 static HRESULT WINAPI saxxmlreader_putProperty(
3012 IVBSAXXMLReader* iface,
3013 BSTR pProp,
3014 VARIANT value)
3015 {
3016 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3017 return internal_putProperty(This, pProp, value, TRUE);
3018 }
3019
3020 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3021 IVBSAXXMLReader* iface,
3022 IVBSAXEntityResolver **resolver)
3023 {
3024 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3025 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3026 }
3027
3028 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3029 IVBSAXXMLReader* iface,
3030 IVBSAXEntityResolver *resolver)
3031 {
3032 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3033 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3034 }
3035
3036 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3037 IVBSAXXMLReader* iface,
3038 IVBSAXContentHandler **handler)
3039 {
3040 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3041 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3042 }
3043
3044 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3045 IVBSAXXMLReader* iface,
3046 IVBSAXContentHandler *handler)
3047 {
3048 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3049 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3050 }
3051
3052 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3053 IVBSAXXMLReader* iface,
3054 IVBSAXDTDHandler **handler)
3055 {
3056 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3057 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3058 }
3059
3060 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3061 IVBSAXXMLReader* iface,
3062 IVBSAXDTDHandler *handler)
3063 {
3064 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3065 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3066 }
3067
3068 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3069 IVBSAXXMLReader* iface,
3070 IVBSAXErrorHandler **handler)
3071 {
3072 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3073 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3074 }
3075
3076 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3077 IVBSAXXMLReader* iface,
3078 IVBSAXErrorHandler *handler)
3079 {
3080 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3081 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3082 }
3083
3084 static HRESULT WINAPI saxxmlreader_get_baseURL(
3085 IVBSAXXMLReader* iface,
3086 BSTR *pBaseUrl)
3087 {
3088 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3089
3090 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3091 return E_NOTIMPL;
3092 }
3093
3094 static HRESULT WINAPI saxxmlreader_put_baseURL(
3095 IVBSAXXMLReader* iface,
3096 BSTR pBaseUrl)
3097 {
3098 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3099 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3100 }
3101
3102 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3103 IVBSAXXMLReader* iface,
3104 BSTR *pSecureBaseUrl)
3105 {
3106 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3107
3108 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3109 return E_NOTIMPL;
3110 }
3111
3112 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3113 IVBSAXXMLReader* iface,
3114 BSTR secureBaseUrl)
3115 {
3116 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3117 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3118 }
3119
3120 static HRESULT WINAPI saxxmlreader_parse(
3121 IVBSAXXMLReader* iface,
3122 VARIANT varInput)
3123 {
3124 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3125 return internal_parse(This, varInput, TRUE);
3126 }
3127
3128 static HRESULT WINAPI saxxmlreader_parseURL(
3129 IVBSAXXMLReader* iface,
3130 BSTR url)
3131 {
3132 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3133 return internal_parseURL(This, url, TRUE);
3134 }
3135
3136 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3137 {
3138 saxxmlreader_QueryInterface,
3139 saxxmlreader_AddRef,
3140 saxxmlreader_Release,
3141 saxxmlreader_GetTypeInfoCount,
3142 saxxmlreader_GetTypeInfo,
3143 saxxmlreader_GetIDsOfNames,
3144 saxxmlreader_Invoke,
3145 saxxmlreader_getFeature,
3146 saxxmlreader_putFeature,
3147 saxxmlreader_getProperty,
3148 saxxmlreader_putProperty,
3149 saxxmlreader_get_entityResolver,
3150 saxxmlreader_put_entityResolver,
3151 saxxmlreader_get_contentHandler,
3152 saxxmlreader_put_contentHandler,
3153 saxxmlreader_get_dtdHandler,
3154 saxxmlreader_put_dtdHandler,
3155 saxxmlreader_get_errorHandler,
3156 saxxmlreader_put_errorHandler,
3157 saxxmlreader_get_baseURL,
3158 saxxmlreader_put_baseURL,
3159 saxxmlreader_get_secureBaseURL,
3160 saxxmlreader_put_secureBaseURL,
3161 saxxmlreader_parse,
3162 saxxmlreader_parseURL
3163 };
3164
3165 /*** ISAXXMLReader interface ***/
3166 /*** IUnknown methods ***/
3167 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3168 {
3169 saxreader *This = impl_from_ISAXXMLReader( iface );
3170 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3171 }
3172
3173 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3174 {
3175 saxreader *This = impl_from_ISAXXMLReader( iface );
3176 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3177 }
3178
3179 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3180 {
3181 saxreader *This = impl_from_ISAXXMLReader( iface );
3182 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3183 }
3184
3185 /*** ISAXXMLReader methods ***/
3186 static HRESULT WINAPI isaxxmlreader_getFeature(
3187 ISAXXMLReader* iface,
3188 const WCHAR *feature_name,
3189 VARIANT_BOOL *value)
3190 {
3191 saxreader *This = impl_from_ISAXXMLReader( iface );
3192 saxreader_feature feature;
3193
3194 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3195
3196 feature = get_saxreader_feature(feature_name);
3197 if (feature == Namespaces || feature == NamespacePrefixes)
3198 return get_feature_value(This, feature, value);
3199
3200 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3201 return E_NOTIMPL;
3202 }
3203
3204 static HRESULT WINAPI isaxxmlreader_putFeature(
3205 ISAXXMLReader* iface,
3206 const WCHAR *feature_name,
3207 VARIANT_BOOL value)
3208 {
3209 saxreader *This = impl_from_ISAXXMLReader( iface );
3210 saxreader_feature feature;
3211
3212 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3213
3214 feature = get_saxreader_feature(feature_name);
3215
3216 /* accepted cases */
3217 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
3218 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
3219 feature == Namespaces ||
3220 feature == NamespacePrefixes)
3221 {
3222 return set_feature_value(This, feature, value);
3223 }
3224
3225 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
3226 {
3227 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3228 return set_feature_value(This, feature, value);
3229 }
3230
3231 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3232 return E_NOTIMPL;
3233 }
3234
3235 static HRESULT WINAPI isaxxmlreader_getProperty(
3236 ISAXXMLReader* iface,
3237 const WCHAR *prop,
3238 VARIANT *value)
3239 {
3240 saxreader *This = impl_from_ISAXXMLReader( iface );
3241 return internal_getProperty(This, prop, value, FALSE);
3242 }
3243
3244 static HRESULT WINAPI isaxxmlreader_putProperty(
3245 ISAXXMLReader* iface,
3246 const WCHAR *pProp,
3247 VARIANT value)
3248 {
3249 saxreader *This = impl_from_ISAXXMLReader( iface );
3250 return internal_putProperty(This, pProp, value, FALSE);
3251 }
3252
3253 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3254 ISAXXMLReader* iface,
3255 ISAXEntityResolver **resolver)
3256 {
3257 saxreader *This = impl_from_ISAXXMLReader( iface );
3258 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3259 }
3260
3261 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3262 ISAXXMLReader* iface,
3263 ISAXEntityResolver *resolver)
3264 {
3265 saxreader *This = impl_from_ISAXXMLReader( iface );
3266 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3267 }
3268
3269 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3270 ISAXXMLReader* iface,
3271 ISAXContentHandler **handler)
3272 {
3273 saxreader *This = impl_from_ISAXXMLReader( iface );
3274 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3275 }
3276
3277 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3278 ISAXXMLReader* iface,
3279 ISAXContentHandler *handler)
3280 {
3281 saxreader *This = impl_from_ISAXXMLReader( iface );
3282 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3283 }
3284
3285 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3286 ISAXXMLReader* iface,
3287 ISAXDTDHandler **handler)
3288 {
3289 saxreader *This = impl_from_ISAXXMLReader( iface );
3290 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3291 }
3292
3293 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3294 ISAXXMLReader* iface,
3295 ISAXDTDHandler *handler)
3296 {
3297 saxreader *This = impl_from_ISAXXMLReader( iface );
3298 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3299 }
3300
3301 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3302 ISAXXMLReader* iface,
3303 ISAXErrorHandler **handler)
3304 {
3305 saxreader *This = impl_from_ISAXXMLReader( iface );
3306 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3307 }
3308
3309 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3310 {
3311 saxreader *This = impl_from_ISAXXMLReader( iface );
3312 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3313 }
3314
3315 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3316 ISAXXMLReader* iface,
3317 const WCHAR **base_url)
3318 {
3319 saxreader *This = impl_from_ISAXXMLReader( iface );
3320
3321 FIXME("(%p)->(%p) stub\n", This, base_url);
3322 return E_NOTIMPL;
3323 }
3324
3325 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3326 ISAXXMLReader* iface,
3327 const WCHAR *pBaseUrl)
3328 {
3329 saxreader *This = impl_from_ISAXXMLReader( iface );
3330
3331 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3332 return E_NOTIMPL;
3333 }
3334
3335 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3336 ISAXXMLReader* iface,
3337 const WCHAR **pSecureBaseUrl)
3338 {
3339 saxreader *This = impl_from_ISAXXMLReader( iface );
3340 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3341 return E_NOTIMPL;
3342 }
3343
3344 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3345 ISAXXMLReader* iface,
3346 const WCHAR *secureBaseUrl)
3347 {
3348 saxreader *This = impl_from_ISAXXMLReader( iface );
3349
3350 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3351 return E_NOTIMPL;
3352 }
3353
3354 static HRESULT WINAPI isaxxmlreader_parse(
3355 ISAXXMLReader* iface,
3356 VARIANT varInput)
3357 {
3358 saxreader *This = impl_from_ISAXXMLReader( iface );
3359 return internal_parse(This, varInput, FALSE);
3360 }
3361
3362 static HRESULT WINAPI isaxxmlreader_parseURL(
3363 ISAXXMLReader* iface,
3364 const WCHAR *url)
3365 {
3366 saxreader *This = impl_from_ISAXXMLReader( iface );
3367 return internal_parseURL(This, url, FALSE);
3368 }
3369
3370 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3371 {
3372 isaxxmlreader_QueryInterface,
3373 isaxxmlreader_AddRef,
3374 isaxxmlreader_Release,
3375 isaxxmlreader_getFeature,
3376 isaxxmlreader_putFeature,
3377 isaxxmlreader_getProperty,
3378 isaxxmlreader_putProperty,
3379 isaxxmlreader_getEntityResolver,
3380 isaxxmlreader_putEntityResolver,
3381 isaxxmlreader_getContentHandler,
3382 isaxxmlreader_putContentHandler,
3383 isaxxmlreader_getDTDHandler,
3384 isaxxmlreader_putDTDHandler,
3385 isaxxmlreader_getErrorHandler,
3386 isaxxmlreader_putErrorHandler,
3387 isaxxmlreader_getBaseURL,
3388 isaxxmlreader_putBaseURL,
3389 isaxxmlreader_getSecureBaseURL,
3390 isaxxmlreader_putSecureBaseURL,
3391 isaxxmlreader_parse,
3392 isaxxmlreader_parseURL
3393 };
3394
3395 static const tid_t saxreader_iface_tids[] = {
3396 IVBSAXXMLReader_tid,
3397 0
3398 };
3399 static dispex_static_data_t saxreader_dispex = {
3400 NULL,
3401 IVBSAXXMLReader_tid,
3402 NULL,
3403 saxreader_iface_tids
3404 };
3405
3406 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3407 {
3408 saxreader *reader;
3409
3410 TRACE("(%p)\n", ppObj);
3411
3412 reader = heap_alloc( sizeof (*reader) );
3413 if( !reader )
3414 return E_OUTOFMEMORY;
3415
3416 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3417 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3418 reader->ref = 1;
3419 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3420 reader->isParsing = FALSE;
3421 reader->xmldecl_version = NULL;
3422 reader->pool.pool = NULL;
3423 reader->pool.index = 0;
3424 reader->pool.len = 0;
3425 reader->features = Namespaces | NamespacePrefixes;
3426 reader->version = version;
3427
3428 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3429
3430 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3431 reader->sax.initialized = XML_SAX2_MAGIC;
3432 reader->sax.startDocument = libxmlStartDocument;
3433 reader->sax.endDocument = libxmlEndDocument;
3434 reader->sax.startElementNs = libxmlStartElementNS;
3435 reader->sax.endElementNs = libxmlEndElementNS;
3436 reader->sax.characters = libxmlCharacters;
3437 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3438 reader->sax.comment = libxmlComment;
3439 reader->sax.error = libxmlFatalError;
3440 reader->sax.fatalError = libxmlFatalError;
3441 reader->sax.cdataBlock = libxml_cdatablock;
3442 reader->sax.resolveEntity = libxmlresolveentity;
3443
3444 *ppObj = &reader->IVBSAXXMLReader_iface;
3445
3446 TRACE("returning iface %p\n", *ppObj);
3447
3448 return S_OK;
3449 }
3450
3451 #else
3452
3453 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3454 {
3455 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3456 "libxml2 support was not present at compile time.\n");
3457 return E_NOTIMPL;
3458 }
3459
3460 #endif