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