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