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