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