include: Added missing Header_* defines.
[wine.git] / dlls / msxml3 / saxreader.c
blob04fab81708c9f45d9d42ebc9907322c8aba362e8
1 /*
2 * SAX Reader implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2008 Piotr Caban
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.
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.
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
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 # include <libxml/SAX2.h>
30 # include <libxml/parserInternals.h>
31 #endif
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "winnls.h"
37 #include "ole2.h"
38 #include "msxml6.h"
39 #include "wininet.h"
40 #include "urlmon.h"
41 #include "winreg.h"
42 #include "shlwapi.h"
44 #include "wine/debug.h"
46 #include "msxml_private.h"
48 #ifdef HAVE_LIBXML2
50 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
52 typedef enum
54 FeatureUnknown = 0,
55 ExhaustiveErrors = 1 << 1,
56 ExternalGeneralEntities = 1 << 2,
57 ExternalParameterEntities = 1 << 3,
58 ForcedResync = 1 << 4,
59 NamespacePrefixes = 1 << 5,
60 Namespaces = 1 << 6,
61 ParameterEntities = 1 << 7,
62 PreserveSystemIndentifiers = 1 << 8,
63 ProhibitDTD = 1 << 9,
64 SchemaValidation = 1 << 10,
65 ServerHttpRequest = 1 << 11,
66 SuppressValidationfatalError = 1 << 12,
67 UseInlineSchema = 1 << 13,
68 UseSchemaLocation = 1 << 14,
69 LexicalHandlerParEntities = 1 << 15
70 } saxreader_feature;
72 /* feature names */
73 static const WCHAR FeatureExternalGeneralEntitiesW[] = {
74 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/',
75 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l',
76 '-','e','n','t','i','t','i','e','s',0
79 static const WCHAR FeatureExternalParameterEntitiesW[] = {
80 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
81 '/','e','x','t','e','r','n','a','l','-','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
84 static const WCHAR FeatureLexicalHandlerParEntitiesW[] = {
85 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
86 '/','l','e','x','i','c','a','l','-','h','a','n','d','l','e','r','/','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
89 static const WCHAR FeatureProhibitDTDW[] = {
90 'p','r','o','h','i','b','i','t','-','d','t','d',0
93 static const WCHAR FeatureNamespacesW[] = {
94 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
95 '/','n','a','m','e','s','p','a','c','e','s',0
98 static const WCHAR FeatureNamespacePrefixesW[] = {
99 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
100 '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
103 static const WCHAR ExhaustiveErrorsW[] = {
104 'e','x','h','a','u','s','t','i','v','e','-','e','r','r','o','r','s',0
107 static const WCHAR SchemaValidationW[] = {
108 's','c','h','e','m','a','-','v','a','l','i','d','a','t','i','o','n',0
111 struct saxreader_feature_pair
113 saxreader_feature feature;
114 const WCHAR *name;
117 static const struct saxreader_feature_pair saxreader_feature_map[] = {
118 { ExhaustiveErrors, ExhaustiveErrorsW },
119 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
120 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
121 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
122 { NamespacePrefixes, FeatureNamespacePrefixesW },
123 { Namespaces, FeatureNamespacesW },
124 { ProhibitDTD, FeatureProhibitDTDW },
125 { SchemaValidation, SchemaValidationW },
128 static saxreader_feature get_saxreader_feature(const WCHAR *name)
130 int min, max, n, c;
132 min = 0;
133 max = ARRAY_SIZE(saxreader_feature_map) - 1;
135 while (min <= max)
137 n = (min+max)/2;
139 c = strcmpW(saxreader_feature_map[n].name, name);
140 if (!c)
141 return saxreader_feature_map[n].feature;
143 if (c > 0)
144 max = n-1;
145 else
146 min = n+1;
149 return FeatureUnknown;
152 struct bstrpool
154 BSTR *pool;
155 unsigned int index;
156 unsigned int len;
159 typedef struct
161 BSTR prefix;
162 BSTR uri;
163 } ns;
165 typedef struct
167 struct list entry;
168 BSTR prefix;
169 BSTR local;
170 BSTR qname;
171 ns *ns; /* namespaces defined in this particular element */
172 int ns_count;
173 } element_entry;
175 enum saxhandler_type
177 SAXContentHandler = 0,
178 SAXDeclHandler,
179 SAXDTDHandler,
180 SAXEntityResolver,
181 SAXErrorHandler,
182 SAXLexicalHandler,
183 SAXHandler_Last
186 struct saxanyhandler_iface
188 IUnknown *handler;
189 IUnknown *vbhandler;
192 struct saxcontenthandler_iface
194 ISAXContentHandler *handler;
195 IVBSAXContentHandler *vbhandler;
198 struct saxerrorhandler_iface
200 ISAXErrorHandler *handler;
201 IVBSAXErrorHandler *vbhandler;
204 struct saxlexicalhandler_iface
206 ISAXLexicalHandler *handler;
207 IVBSAXLexicalHandler *vbhandler;
210 struct saxentityresolver_iface
212 ISAXEntityResolver *handler;
213 IVBSAXEntityResolver *vbhandler;
216 struct saxhandler_iface
218 union {
219 struct saxcontenthandler_iface content;
220 struct saxentityresolver_iface entityresolver;
221 struct saxerrorhandler_iface error;
222 struct saxlexicalhandler_iface lexical;
223 struct saxanyhandler_iface anyhandler;
224 } u;
227 typedef struct
229 DispatchEx dispex;
230 IVBSAXXMLReader IVBSAXXMLReader_iface;
231 ISAXXMLReader ISAXXMLReader_iface;
232 LONG ref;
234 struct saxhandler_iface saxhandlers[SAXHandler_Last];
235 xmlSAXHandler sax;
236 BOOL isParsing;
237 struct bstrpool pool;
238 saxreader_feature features;
239 BSTR xmldecl_version;
240 MSXML_VERSION version;
241 } saxreader;
243 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
245 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
246 IUnknown *unk = (IUnknown*)ptr;
248 if (unk)
249 IUnknown_AddRef(unk);
251 if ((vb && iface->vbhandler) || (!vb && iface->handler))
252 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
254 if (vb)
255 iface->vbhandler = unk;
256 else
257 iface->handler = unk;
259 return S_OK;
262 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
264 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
266 if (!ret) return E_POINTER;
268 if ((vb && iface->vbhandler) || (!vb && iface->handler))
270 if (vb)
271 IUnknown_AddRef(iface->vbhandler);
272 else
273 IUnknown_AddRef(iface->handler);
276 *ret = vb ? iface->vbhandler : iface->handler;
278 return S_OK;
281 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
283 return &reader->saxhandlers[SAXContentHandler].u.content;
286 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
288 return &reader->saxhandlers[SAXErrorHandler].u.error;
291 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
293 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
296 typedef struct
298 IVBSAXLocator IVBSAXLocator_iface;
299 ISAXLocator ISAXLocator_iface;
300 IVBSAXAttributes IVBSAXAttributes_iface;
301 ISAXAttributes ISAXAttributes_iface;
302 LONG ref;
303 saxreader *saxreader;
304 HRESULT ret;
305 xmlParserCtxtPtr pParserCtxt;
306 BSTR publicId;
307 BSTR systemId;
308 int line;
309 int column;
310 BOOL vbInterface;
311 struct list elements;
313 BSTR namespaceUri;
314 int attr_alloc_count;
315 int attr_count;
316 struct _attributes
318 BSTR szLocalname;
319 BSTR szURI;
320 BSTR szValue;
321 BSTR szQName;
322 } *attributes;
323 } saxlocator;
325 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
327 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
330 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
332 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
335 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
337 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
340 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
342 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
345 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
347 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
350 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
352 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
355 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
357 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
358 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
361 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
363 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
364 HRESULT hr;
366 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
368 if (locator->vbInterface)
369 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
370 else
371 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
373 return hr;
376 /* property names */
377 static const WCHAR PropertyCharsetW[] = {
378 'c','h','a','r','s','e','t',0
380 static const WCHAR PropertyXmlDeclVersionW[] = {
381 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
383 static const WCHAR PropertyDeclHandlerW[] = {
384 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
385 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
386 'd','e','c','l','a','r','a','t','i','o','n',
387 '-','h','a','n','d','l','e','r',0
389 static const WCHAR PropertyDomNodeW[] = {
390 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
391 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
392 'd','o','m','-','n','o','d','e',0
394 static const WCHAR PropertyInputSourceW[] = {
395 'i','n','p','u','t','-','s','o','u','r','c','e',0
397 static const WCHAR PropertyLexicalHandlerW[] = {
398 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
399 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
400 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
402 static const WCHAR PropertyMaxElementDepthW[] = {
403 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
405 static const WCHAR PropertyMaxXMLSizeW[] = {
406 'm','a','x','-','x','m','l','-','s','i','z','e',0
408 static const WCHAR PropertySchemaDeclHandlerW[] = {
409 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
410 'h','a','n','d','l','e','r',0
412 static const WCHAR PropertyXMLDeclEncodingW[] = {
413 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
415 static const WCHAR PropertyXMLDeclStandaloneW[] = {
416 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
418 static const WCHAR PropertyXMLDeclVersionW[] = {
419 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
422 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
424 /* handling of non-VARIANT_* values is version dependent */
425 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
426 value = VARIANT_FALSE;
427 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
428 value = VARIANT_TRUE;
430 if (value == VARIANT_TRUE)
431 reader->features |= feature;
432 else
433 reader->features &= ~feature;
435 return S_OK;
438 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
440 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
441 return S_OK;
444 static BOOL is_namespaces_enabled(const saxreader *reader)
446 return (reader->version < MSXML4) || (reader->features & Namespaces);
449 static BSTR build_qname(BSTR prefix, BSTR local)
451 if (prefix && *prefix)
453 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
454 WCHAR *ptr;
456 ptr = qname;
457 strcpyW(ptr, prefix);
458 ptr += SysStringLen(prefix);
459 *ptr++ = ':';
460 strcpyW(ptr, local);
461 return qname;
463 else
464 return SysAllocString(local);
467 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
468 const xmlChar **namespaces)
470 element_entry *ret;
471 int i;
473 ret = heap_alloc(sizeof(*ret));
474 if (!ret) return ret;
476 ret->local = bstr_from_xmlChar(local);
477 ret->prefix = bstr_from_xmlChar(prefix);
478 ret->qname = build_qname(ret->prefix, ret->local);
479 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
480 ret->ns_count = nb_ns;
482 for (i=0; i < nb_ns; i++)
484 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
485 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
488 return ret;
491 static void free_element_entry(element_entry *element)
493 int i;
495 for (i=0; i<element->ns_count;i++)
497 SysFreeString(element->ns[i].prefix);
498 SysFreeString(element->ns[i].uri);
501 SysFreeString(element->prefix);
502 SysFreeString(element->local);
503 SysFreeString(element->qname);
505 heap_free(element->ns);
506 heap_free(element);
509 static void push_element_ns(saxlocator *locator, element_entry *element)
511 list_add_head(&locator->elements, &element->entry);
514 static element_entry * pop_element_ns(saxlocator *locator)
516 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
518 if (element)
519 list_remove(&element->entry);
521 return element;
524 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
526 element_entry *element;
527 BSTR uriW;
528 int i;
530 if (!uri) return NULL;
532 uriW = bstr_from_xmlChar(uri);
534 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
536 for (i=0; i < element->ns_count; i++)
537 if (!strcmpW(uriW, element->ns[i].uri))
539 SysFreeString(uriW);
540 return element->ns[i].uri;
544 SysFreeString(uriW);
545 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
546 return NULL;
549 /* used to localize version dependent error check behaviour */
550 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
552 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
555 /* index value -1 means it tries to loop for a first time */
556 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
558 if (This->saxreader->version >= MSXML4)
560 if (*i == -1) *i = 0; else ++*i;
561 return *i < element->ns_count;
563 else
565 if (*i == -1) *i = element->ns_count-1; else --*i;
566 return *i >= 0;
570 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
572 if (!pool->pool)
574 pool->pool = heap_alloc(16 * sizeof(*pool->pool));
575 if (!pool->pool)
576 return FALSE;
578 pool->index = 0;
579 pool->len = 16;
581 else if (pool->index == pool->len)
583 BSTR *realloc = heap_realloc(pool->pool, pool->len * 2 * sizeof(*realloc));
585 if (!realloc)
586 return FALSE;
588 pool->pool = realloc;
589 pool->len *= 2;
592 pool->pool[pool->index++] = pool_entry;
593 return TRUE;
596 static void free_bstr_pool(struct bstrpool *pool)
598 unsigned int i;
600 for (i = 0; i < pool->index; i++)
601 SysFreeString(pool->pool[i]);
603 heap_free(pool->pool);
605 pool->pool = NULL;
606 pool->index = pool->len = 0;
609 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
611 DWORD dLen;
612 BSTR bstr;
614 if (!buf)
615 return NULL;
617 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
618 if(len != -1) dLen++;
619 bstr = SysAllocStringLen(NULL, dLen-1);
620 if (!bstr)
621 return NULL;
622 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
623 if(len != -1) bstr[dLen-1] = '\0';
625 return bstr;
628 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
630 xmlChar *qname;
631 BSTR bstr;
633 if(!name) return NULL;
635 if(!prefix || !*prefix)
636 return bstr_from_xmlChar(name);
638 qname = xmlBuildQName(name, prefix, NULL, 0);
639 bstr = bstr_from_xmlChar(qname);
640 xmlFree(qname);
642 return bstr;
645 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
647 BSTR pool_entry = bstr_from_xmlChar(buf);
649 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
651 SysFreeString(pool_entry);
652 return NULL;
655 return pool_entry;
658 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
660 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
662 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
664 SysFreeString(pool_entry);
665 return NULL;
668 return pool_entry;
671 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
673 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
674 xmlStopParser(This->pParserCtxt);
675 This->ret = hr;
677 if (saxreader_has_handler(This, SAXErrorHandler))
679 WCHAR msg[1024];
680 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
681 NULL, hr, 0, msg, ARRAY_SIZE(msg), NULL))
683 FIXME("MSXML errors not yet supported.\n");
684 msg[0] = '\0';
687 if(This->vbInterface)
689 BSTR bstrMsg = SysAllocString(msg);
690 IVBSAXErrorHandler_fatalError(handler->vbhandler,
691 &This->IVBSAXLocator_iface, &bstrMsg, hr);
692 SysFreeString(bstrMsg);
694 else
695 ISAXErrorHandler_fatalError(handler->handler,
696 &This->ISAXLocator_iface, msg, hr);
700 static void update_position(saxlocator *This, BOOL fix_column)
702 const xmlChar *p = This->pParserCtxt->input->cur-1;
703 const xmlChar *baseP = This->pParserCtxt->input->base;
705 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
706 if(fix_column)
708 This->column = 1;
709 for(;p>=baseP && *p!='\n' && *p!='\r'; p--)
710 This->column++;
712 else
714 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
718 /*** IVBSAXAttributes interface ***/
719 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
720 IVBSAXAttributes* iface,
721 REFIID riid,
722 void **ppvObject)
724 saxlocator *This = impl_from_IVBSAXAttributes(iface);
725 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
726 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
729 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
731 saxlocator *This = impl_from_IVBSAXAttributes(iface);
732 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
735 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
737 saxlocator *This = impl_from_IVBSAXAttributes(iface);
738 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
741 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
743 saxlocator *This = impl_from_IVBSAXAttributes( iface );
745 TRACE("(%p)->(%p)\n", This, pctinfo);
747 *pctinfo = 1;
749 return S_OK;
752 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
753 IVBSAXAttributes *iface,
754 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
756 saxlocator *This = impl_from_IVBSAXAttributes( iface );
758 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
760 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
763 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
764 IVBSAXAttributes *iface,
765 REFIID riid,
766 LPOLESTR* rgszNames,
767 UINT cNames,
768 LCID lcid,
769 DISPID* rgDispId)
771 saxlocator *This = impl_from_IVBSAXAttributes( iface );
772 ITypeInfo *typeinfo;
773 HRESULT hr;
775 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
776 lcid, rgDispId);
778 if(!rgszNames || cNames == 0 || !rgDispId)
779 return E_INVALIDARG;
781 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
782 if(SUCCEEDED(hr))
784 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
785 ITypeInfo_Release(typeinfo);
788 return hr;
791 static HRESULT WINAPI ivbsaxattributes_Invoke(
792 IVBSAXAttributes *iface,
793 DISPID dispIdMember,
794 REFIID riid,
795 LCID lcid,
796 WORD wFlags,
797 DISPPARAMS* pDispParams,
798 VARIANT* pVarResult,
799 EXCEPINFO* pExcepInfo,
800 UINT* puArgErr)
802 saxlocator *This = impl_from_IVBSAXAttributes( iface );
803 ITypeInfo *typeinfo;
804 HRESULT hr;
806 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
807 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
809 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
810 if(SUCCEEDED(hr))
812 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
813 pDispParams, pVarResult, pExcepInfo, puArgErr);
814 ITypeInfo_Release(typeinfo);
817 return hr;
820 /*** IVBSAXAttributes methods ***/
821 static HRESULT WINAPI ivbsaxattributes_get_length(
822 IVBSAXAttributes* iface,
823 int *nLength)
825 saxlocator *This = impl_from_IVBSAXAttributes( iface );
826 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
829 static HRESULT WINAPI ivbsaxattributes_getURI(
830 IVBSAXAttributes* iface,
831 int nIndex,
832 BSTR *uri)
834 saxlocator *This = impl_from_IVBSAXAttributes( iface );
835 const WCHAR *uriW;
836 HRESULT hr;
837 int len;
839 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
841 if (!uri)
842 return E_POINTER;
844 *uri = NULL;
845 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
846 if (FAILED(hr))
847 return hr;
849 return return_bstrn(uriW, len, uri);
852 static HRESULT WINAPI ivbsaxattributes_getLocalName(
853 IVBSAXAttributes* iface,
854 int nIndex,
855 BSTR *name)
857 saxlocator *This = impl_from_IVBSAXAttributes( iface );
858 const WCHAR *nameW;
859 HRESULT hr;
860 int len;
862 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
864 if (!name)
865 return E_POINTER;
867 *name = NULL;
868 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
869 if (FAILED(hr))
870 return hr;
872 return return_bstrn(nameW, len, name);
875 static HRESULT WINAPI ivbsaxattributes_getQName(
876 IVBSAXAttributes* iface,
877 int nIndex,
878 BSTR *QName)
880 saxlocator *This = impl_from_IVBSAXAttributes( iface );
881 const WCHAR *nameW;
882 HRESULT hr;
883 int len;
885 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
887 if (!QName)
888 return E_POINTER;
890 *QName = NULL;
891 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
892 if (FAILED(hr))
893 return hr;
895 return return_bstrn(nameW, len, QName);
898 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
899 IVBSAXAttributes* iface,
900 BSTR uri,
901 BSTR localName,
902 int *index)
904 saxlocator *This = impl_from_IVBSAXAttributes( iface );
905 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
906 localName, SysStringLen(localName), index);
909 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
910 IVBSAXAttributes* iface,
911 BSTR QName,
912 int *index)
914 saxlocator *This = impl_from_IVBSAXAttributes( iface );
915 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
916 SysStringLen(QName), index);
919 static HRESULT WINAPI ivbsaxattributes_getType(
920 IVBSAXAttributes* iface,
921 int nIndex,
922 BSTR *type)
924 saxlocator *This = impl_from_IVBSAXAttributes( iface );
925 const WCHAR *typeW;
926 HRESULT hr;
927 int len;
929 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
931 if (!type)
932 return E_POINTER;
934 *type = NULL;
935 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
936 if (FAILED(hr))
937 return hr;
939 return return_bstrn(typeW, len, type);
942 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
943 IVBSAXAttributes* iface,
944 BSTR uri,
945 BSTR localName,
946 BSTR *type)
948 saxlocator *This = impl_from_IVBSAXAttributes( iface );
949 const WCHAR *typeW;
950 HRESULT hr;
951 int len;
953 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
955 if (!type)
956 return E_POINTER;
958 *type = NULL;
959 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
960 localName, SysStringLen(localName), &typeW, &len);
961 if (FAILED(hr))
962 return hr;
964 return return_bstrn(typeW, len, type);
967 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
968 IVBSAXAttributes* iface,
969 BSTR QName,
970 BSTR *type)
972 saxlocator *This = impl_from_IVBSAXAttributes( iface );
973 const WCHAR *typeW;
974 HRESULT hr;
975 int len;
977 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
979 if (!type)
980 return E_POINTER;
982 *type = NULL;
983 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
984 &typeW, &len);
985 if (FAILED(hr))
986 return hr;
988 return return_bstrn(typeW, len, type);
991 static HRESULT WINAPI ivbsaxattributes_getValue(
992 IVBSAXAttributes* iface,
993 int nIndex,
994 BSTR *value)
996 saxlocator *This = impl_from_IVBSAXAttributes( iface );
997 const WCHAR *valueW;
998 HRESULT hr;
999 int len;
1001 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
1003 if (!value)
1004 return E_POINTER;
1006 *value = NULL;
1007 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
1008 if (FAILED(hr))
1009 return hr;
1011 return return_bstrn(valueW, len, value);
1014 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1015 IVBSAXAttributes* iface,
1016 BSTR uri,
1017 BSTR localName,
1018 BSTR *value)
1020 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1021 const WCHAR *valueW;
1022 HRESULT hr;
1023 int len;
1025 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1027 if (!value)
1028 return E_POINTER;
1030 *value = NULL;
1031 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1032 localName, SysStringLen(localName), &valueW, &len);
1033 if (FAILED(hr))
1034 return hr;
1036 return return_bstrn(valueW, len, value);
1039 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1040 IVBSAXAttributes* iface,
1041 BSTR QName,
1042 BSTR *value)
1044 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1045 const WCHAR *valueW;
1046 HRESULT hr;
1047 int len;
1049 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1051 if (!value)
1052 return E_POINTER;
1054 *value = NULL;
1055 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1056 SysStringLen(QName), &valueW, &len);
1057 if (FAILED(hr))
1058 return hr;
1060 return return_bstrn(valueW, len, value);
1063 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1065 ivbsaxattributes_QueryInterface,
1066 ivbsaxattributes_AddRef,
1067 ivbsaxattributes_Release,
1068 ivbsaxattributes_GetTypeInfoCount,
1069 ivbsaxattributes_GetTypeInfo,
1070 ivbsaxattributes_GetIDsOfNames,
1071 ivbsaxattributes_Invoke,
1072 ivbsaxattributes_get_length,
1073 ivbsaxattributes_getURI,
1074 ivbsaxattributes_getLocalName,
1075 ivbsaxattributes_getQName,
1076 ivbsaxattributes_getIndexFromName,
1077 ivbsaxattributes_getIndexFromQName,
1078 ivbsaxattributes_getType,
1079 ivbsaxattributes_getTypeFromName,
1080 ivbsaxattributes_getTypeFromQName,
1081 ivbsaxattributes_getValue,
1082 ivbsaxattributes_getValueFromName,
1083 ivbsaxattributes_getValueFromQName
1086 /*** ISAXAttributes interface ***/
1087 /*** IUnknown methods ***/
1088 static HRESULT WINAPI isaxattributes_QueryInterface(
1089 ISAXAttributes* iface,
1090 REFIID riid,
1091 void **ppvObject)
1093 saxlocator *This = impl_from_ISAXAttributes(iface);
1094 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1095 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1098 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1100 saxlocator *This = impl_from_ISAXAttributes(iface);
1101 TRACE("%p\n", This);
1102 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1105 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1107 saxlocator *This = impl_from_ISAXAttributes(iface);
1109 TRACE("%p\n", This);
1110 return ISAXLocator_Release(&This->ISAXLocator_iface);
1113 /*** ISAXAttributes methods ***/
1114 static HRESULT WINAPI isaxattributes_getLength(
1115 ISAXAttributes* iface,
1116 int *length)
1118 saxlocator *This = impl_from_ISAXAttributes( iface );
1120 *length = This->attr_count;
1121 TRACE("Length set to %d\n", *length);
1122 return S_OK;
1125 static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
1127 return index < locator->attr_count && index >= 0;
1130 static HRESULT WINAPI isaxattributes_getURI(
1131 ISAXAttributes* iface,
1132 int index,
1133 const WCHAR **url,
1134 int *size)
1136 saxlocator *This = impl_from_ISAXAttributes( iface );
1137 TRACE("(%p)->(%d)\n", This, index);
1139 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1140 if(!url || !size) return E_POINTER;
1142 *size = SysStringLen(This->attributes[index].szURI);
1143 *url = This->attributes[index].szURI;
1145 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1147 return S_OK;
1150 static HRESULT WINAPI isaxattributes_getLocalName(
1151 ISAXAttributes* iface,
1152 int index,
1153 const WCHAR **pLocalName,
1154 int *pLocalNameLength)
1156 saxlocator *This = impl_from_ISAXAttributes( iface );
1157 TRACE("(%p)->(%d)\n", This, index);
1159 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1160 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1162 *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
1163 *pLocalName = This->attributes[index].szLocalname;
1165 return S_OK;
1168 static HRESULT WINAPI isaxattributes_getQName(
1169 ISAXAttributes* iface,
1170 int index,
1171 const WCHAR **pQName,
1172 int *pQNameLength)
1174 saxlocator *This = impl_from_ISAXAttributes( iface );
1175 TRACE("(%p)->(%d)\n", This, index);
1177 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1178 if(!pQName || !pQNameLength) return E_POINTER;
1180 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1181 *pQName = This->attributes[index].szQName;
1183 return S_OK;
1186 static HRESULT WINAPI isaxattributes_getName(
1187 ISAXAttributes* iface,
1188 int index,
1189 const WCHAR **uri,
1190 int *pUriLength,
1191 const WCHAR **localName,
1192 int *pLocalNameSize,
1193 const WCHAR **QName,
1194 int *pQNameLength)
1196 saxlocator *This = impl_from_ISAXAttributes( iface );
1197 TRACE("(%p)->(%d)\n", This, index);
1199 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1200 if(!uri || !pUriLength || !localName || !pLocalNameSize
1201 || !QName || !pQNameLength) return E_POINTER;
1203 *pUriLength = SysStringLen(This->attributes[index].szURI);
1204 *uri = This->attributes[index].szURI;
1205 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1206 *localName = This->attributes[index].szLocalname;
1207 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1208 *QName = This->attributes[index].szQName;
1210 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1212 return S_OK;
1215 static HRESULT WINAPI isaxattributes_getIndexFromName(
1216 ISAXAttributes* iface,
1217 const WCHAR *pUri,
1218 int cUriLength,
1219 const WCHAR *pLocalName,
1220 int cocalNameLength,
1221 int *index)
1223 saxlocator *This = impl_from_ISAXAttributes( iface );
1224 int i;
1225 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1226 debugstr_w(pLocalName), cocalNameLength);
1228 if(!pUri || !pLocalName || !index) return E_POINTER;
1230 for(i=0; i<This->attr_count; i++)
1232 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1233 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1234 continue;
1235 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1236 sizeof(WCHAR)*cUriLength))
1237 continue;
1238 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1239 sizeof(WCHAR)*cocalNameLength))
1240 continue;
1242 *index = i;
1243 return S_OK;
1246 return E_INVALIDARG;
1249 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1250 ISAXAttributes* iface,
1251 const WCHAR *pQName,
1252 int nQNameLength,
1253 int *index)
1255 saxlocator *This = impl_from_ISAXAttributes( iface );
1256 int i;
1257 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1259 if(!pQName || !index) return E_POINTER;
1260 if(!nQNameLength) return E_INVALIDARG;
1262 for(i=0; i<This->attr_count; i++)
1264 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1265 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1267 *index = i;
1268 return S_OK;
1271 return E_INVALIDARG;
1274 static HRESULT WINAPI isaxattributes_getType(
1275 ISAXAttributes* iface,
1276 int nIndex,
1277 const WCHAR **pType,
1278 int *pTypeLength)
1280 saxlocator *This = impl_from_ISAXAttributes( iface );
1282 FIXME("(%p)->(%d) stub\n", This, nIndex);
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI isaxattributes_getTypeFromName(
1287 ISAXAttributes* iface,
1288 const WCHAR *pUri,
1289 int nUri,
1290 const WCHAR *pLocalName,
1291 int nLocalName,
1292 const WCHAR **pType,
1293 int *nType)
1295 saxlocator *This = impl_from_ISAXAttributes( iface );
1297 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1298 debugstr_w(pLocalName), nLocalName);
1299 return E_NOTIMPL;
1302 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1303 ISAXAttributes* iface,
1304 const WCHAR *pQName,
1305 int nQName,
1306 const WCHAR **pType,
1307 int *nType)
1309 saxlocator *This = impl_from_ISAXAttributes( iface );
1311 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1312 return E_NOTIMPL;
1315 static HRESULT WINAPI isaxattributes_getValue(
1316 ISAXAttributes* iface,
1317 int index,
1318 const WCHAR **value,
1319 int *nValue)
1321 saxlocator *This = impl_from_ISAXAttributes( iface );
1322 TRACE("(%p)->(%d)\n", This, index);
1324 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1325 if(!value || !nValue) return E_POINTER;
1327 *nValue = SysStringLen(This->attributes[index].szValue);
1328 *value = This->attributes[index].szValue;
1330 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1332 return S_OK;
1335 static HRESULT WINAPI isaxattributes_getValueFromName(
1336 ISAXAttributes* iface,
1337 const WCHAR *pUri,
1338 int nUri,
1339 const WCHAR *pLocalName,
1340 int nLocalName,
1341 const WCHAR **pValue,
1342 int *nValue)
1344 HRESULT hr;
1345 int index;
1346 saxlocator *This = impl_from_ISAXAttributes( iface );
1347 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1348 debugstr_w(pLocalName), nLocalName);
1350 hr = ISAXAttributes_getIndexFromName(iface,
1351 pUri, nUri, pLocalName, nLocalName, &index);
1352 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1354 return hr;
1357 static HRESULT WINAPI isaxattributes_getValueFromQName(
1358 ISAXAttributes* iface,
1359 const WCHAR *pQName,
1360 int nQName,
1361 const WCHAR **pValue,
1362 int *nValue)
1364 HRESULT hr;
1365 int index;
1366 saxlocator *This = impl_from_ISAXAttributes( iface );
1367 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1369 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1370 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1372 return hr;
1375 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1377 isaxattributes_QueryInterface,
1378 isaxattributes_AddRef,
1379 isaxattributes_Release,
1380 isaxattributes_getLength,
1381 isaxattributes_getURI,
1382 isaxattributes_getLocalName,
1383 isaxattributes_getQName,
1384 isaxattributes_getName,
1385 isaxattributes_getIndexFromName,
1386 isaxattributes_getIndexFromQName,
1387 isaxattributes_getType,
1388 isaxattributes_getTypeFromName,
1389 isaxattributes_getTypeFromQName,
1390 isaxattributes_getValue,
1391 isaxattributes_getValueFromName,
1392 isaxattributes_getValueFromQName
1395 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1396 so when document has escaped value with '&amp;' it's parsed to '&' and then
1397 escaped to '&#38;'. This function takes care of ampersands only. */
1398 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1400 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1401 WCHAR *dest, *ptrW, *str;
1402 DWORD str_len;
1403 BSTR bstr;
1405 if (!buf)
1406 return NULL;
1408 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1409 if (len != -1) str_len++;
1411 str = heap_alloc(str_len*sizeof(WCHAR));
1412 if (!str) return NULL;
1414 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1415 if (len != -1) str[str_len-1] = 0;
1417 ptrW = str;
1418 while ((dest = strstrW(ptrW, ampescW)))
1420 WCHAR *src;
1422 /* leave first '&' from a reference as a value */
1423 src = dest + ARRAY_SIZE(ampescW) - 1;
1424 dest++;
1426 /* move together with null terminator */
1427 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1429 ptrW++;
1432 bstr = SysAllocString(str);
1433 heap_free(str);
1435 return bstr;
1438 static void free_attribute_values(saxlocator *locator)
1440 int i;
1442 for (i = 0; i < locator->attr_count; i++)
1444 SysFreeString(locator->attributes[i].szLocalname);
1445 locator->attributes[i].szLocalname = NULL;
1447 SysFreeString(locator->attributes[i].szValue);
1448 locator->attributes[i].szValue = NULL;
1450 SysFreeString(locator->attributes[i].szQName);
1451 locator->attributes[i].szQName = NULL;
1455 static HRESULT SAXAttributes_populate(saxlocator *locator,
1456 int nb_namespaces, const xmlChar **xmlNamespaces,
1457 int nb_attributes, const xmlChar **xmlAttributes)
1459 static const xmlChar xmlns[] = "xmlns";
1460 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1462 struct _attributes *attrs;
1463 int i;
1465 /* skip namespace definitions */
1466 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1467 nb_namespaces = 0;
1469 locator->attr_count = nb_namespaces + nb_attributes;
1470 if(locator->attr_count > locator->attr_alloc_count)
1472 int new_size = locator->attr_count * 2;
1473 attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1474 if(!attrs)
1476 free_attribute_values(locator);
1477 locator->attr_count = 0;
1478 return E_OUTOFMEMORY;
1480 locator->attributes = attrs;
1481 locator->attr_alloc_count = new_size;
1483 else
1485 attrs = locator->attributes;
1488 for (i = 0; i < nb_namespaces; i++)
1490 SysFreeString(attrs[nb_attributes+i].szLocalname);
1491 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1493 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1495 SysFreeString(attrs[nb_attributes+i].szValue);
1496 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1498 SysFreeString(attrs[nb_attributes+i].szQName);
1499 if(!xmlNamespaces[2*i])
1500 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1501 else
1502 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1505 for (i = 0; i < nb_attributes; i++)
1507 static const xmlChar xmlA[] = "xml";
1509 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1510 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1511 else
1512 /* that's an important feature to keep same uri pointer for every reported attribute */
1513 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1515 SysFreeString(attrs[i].szLocalname);
1516 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1518 SysFreeString(attrs[i].szValue);
1519 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1521 SysFreeString(attrs[i].szQName);
1522 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1525 return S_OK;
1528 /*** LibXML callbacks ***/
1529 static void libxmlStartDocument(void *ctx)
1531 saxlocator *This = ctx;
1532 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1533 HRESULT hr;
1535 if (This->saxreader->version >= MSXML4)
1537 const xmlChar *p = This->pParserCtxt->input->cur-1;
1538 update_position(This, FALSE);
1539 while(p>This->pParserCtxt->input->base && *p!='>')
1541 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1542 This->line--;
1543 p--;
1545 This->column = 0;
1546 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1547 This->column++;
1550 /* store version value, declaration has to contain version attribute */
1551 if (This->pParserCtxt->standalone != -1)
1553 SysFreeString(This->saxreader->xmldecl_version);
1554 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1557 if (saxreader_has_handler(This, SAXContentHandler))
1559 if(This->vbInterface)
1560 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1561 else
1562 hr = ISAXContentHandler_startDocument(handler->handler);
1564 if (sax_callback_failed(This, hr))
1565 format_error_message_from_id(This, hr);
1569 static void libxmlEndDocument(void *ctx)
1571 saxlocator *This = ctx;
1572 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1573 HRESULT hr;
1575 if (This->saxreader->version >= MSXML4) {
1576 update_position(This, FALSE);
1577 if(This->column > 1)
1578 This->line++;
1579 This->column = 0;
1580 } else {
1581 This->column = 0;
1582 This->line = 0;
1585 if(This->ret != S_OK) return;
1587 if (saxreader_has_handler(This, SAXContentHandler))
1589 if(This->vbInterface)
1590 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1591 else
1592 hr = ISAXContentHandler_endDocument(handler->handler);
1594 if (sax_callback_failed(This, hr))
1595 format_error_message_from_id(This, hr);
1599 static void libxmlStartElementNS(
1600 void *ctx,
1601 const xmlChar *localname,
1602 const xmlChar *prefix,
1603 const xmlChar *URI,
1604 int nb_namespaces,
1605 const xmlChar **namespaces,
1606 int nb_attributes,
1607 int nb_defaulted,
1608 const xmlChar **attributes)
1610 saxlocator *This = ctx;
1611 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1612 element_entry *element;
1613 HRESULT hr = S_OK;
1614 BSTR uri;
1616 update_position(This, TRUE);
1617 if(*(This->pParserCtxt->input->cur) == '/')
1618 This->column++;
1619 if(This->saxreader->version < MSXML4)
1620 This->column++;
1622 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1623 push_element_ns(This, element);
1625 if (is_namespaces_enabled(This->saxreader))
1627 int i;
1629 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1631 if (This->vbInterface)
1632 hr = IVBSAXContentHandler_startPrefixMapping(
1633 handler->vbhandler,
1634 &element->ns[i].prefix,
1635 &element->ns[i].uri);
1636 else
1637 hr = ISAXContentHandler_startPrefixMapping(
1638 handler->handler,
1639 element->ns[i].prefix,
1640 SysStringLen(element->ns[i].prefix),
1641 element->ns[i].uri,
1642 SysStringLen(element->ns[i].uri));
1644 if (sax_callback_failed(This, hr))
1646 format_error_message_from_id(This, hr);
1647 return;
1652 uri = find_element_uri(This, URI);
1653 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1654 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1656 BSTR local;
1658 if (is_namespaces_enabled(This->saxreader))
1659 local = element->local;
1660 else
1661 uri = local = NULL;
1663 if (This->vbInterface)
1664 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1665 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1666 else
1667 hr = ISAXContentHandler_startElement(handler->handler,
1668 uri, SysStringLen(uri),
1669 local, SysStringLen(local),
1670 element->qname, SysStringLen(element->qname),
1671 &This->ISAXAttributes_iface);
1673 if (sax_callback_failed(This, hr))
1674 format_error_message_from_id(This, hr);
1678 static void libxmlEndElementNS(
1679 void *ctx,
1680 const xmlChar *localname,
1681 const xmlChar *prefix,
1682 const xmlChar *URI)
1684 saxlocator *This = ctx;
1685 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1686 element_entry *element;
1687 const xmlChar *p;
1688 BSTR uri, local;
1689 HRESULT hr;
1691 update_position(This, FALSE);
1692 p = This->pParserCtxt->input->cur;
1694 if (This->saxreader->version >= MSXML4)
1696 p--;
1697 while(p>This->pParserCtxt->input->base && *p!='>')
1699 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1700 This->line--;
1701 p--;
1704 else if(*(p-1)!='>' || *(p-2)!='/')
1706 p--;
1707 while(p-2>=This->pParserCtxt->input->base
1708 && *(p-2)!='<' && *(p-1)!='/')
1710 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1711 This->line--;
1712 p--;
1715 This->column = 0;
1716 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1717 This->column++;
1719 uri = find_element_uri(This, URI);
1720 element = pop_element_ns(This);
1722 if (!saxreader_has_handler(This, SAXContentHandler))
1724 free_attribute_values(This);
1725 This->attr_count = 0;
1726 free_element_entry(element);
1727 return;
1730 if (is_namespaces_enabled(This->saxreader))
1731 local = element->local;
1732 else
1733 uri = local = NULL;
1735 if (This->vbInterface)
1736 hr = IVBSAXContentHandler_endElement(
1737 handler->vbhandler,
1738 &uri, &local, &element->qname);
1739 else
1740 hr = ISAXContentHandler_endElement(
1741 handler->handler,
1742 uri, SysStringLen(uri),
1743 local, SysStringLen(local),
1744 element->qname, SysStringLen(element->qname));
1746 free_attribute_values(This);
1747 This->attr_count = 0;
1749 if (sax_callback_failed(This, hr))
1751 format_error_message_from_id(This, hr);
1752 free_element_entry(element);
1753 return;
1756 if (is_namespaces_enabled(This->saxreader))
1758 int i = -1;
1759 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1761 if (This->vbInterface)
1762 hr = IVBSAXContentHandler_endPrefixMapping(
1763 handler->vbhandler, &element->ns[i].prefix);
1764 else
1765 hr = ISAXContentHandler_endPrefixMapping(
1766 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1768 if (sax_callback_failed(This, hr)) break;
1771 if (sax_callback_failed(This, hr))
1772 format_error_message_from_id(This, hr);
1775 free_element_entry(element);
1778 static void libxmlCharacters(
1779 void *ctx,
1780 const xmlChar *ch,
1781 int len)
1783 saxlocator *This = ctx;
1784 BSTR Chars;
1785 HRESULT hr;
1786 xmlChar *cur, *end;
1787 BOOL lastEvent = FALSE;
1789 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1791 update_position(This, FALSE);
1792 cur = (xmlChar*)This->pParserCtxt->input->cur;
1793 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1795 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1796 This->line--;
1797 cur--;
1799 This->column = 1;
1800 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1801 This->column++;
1803 cur = (xmlChar*)ch;
1804 if(*(ch-1)=='\r') cur--;
1805 end = cur;
1807 while(1)
1809 while(end-ch<len && *end!='\r') end++;
1810 if(end-ch==len)
1812 lastEvent = TRUE;
1814 else
1816 *end = '\n';
1817 end++;
1820 if (This->saxreader->version >= MSXML4)
1822 xmlChar *p;
1824 for(p=cur; p!=end; p++)
1826 if(*p=='\n')
1828 This->line++;
1829 This->column = 1;
1831 else
1833 This->column++;
1837 if(!lastEvent)
1838 This->column = 0;
1841 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1842 hr = saxreader_saxcharacters(This, Chars);
1844 if (sax_callback_failed(This, hr))
1846 format_error_message_from_id(This, hr);
1847 return;
1850 if (This->saxreader->version < MSXML4)
1851 This->column += end-cur;
1853 if(lastEvent)
1854 break;
1856 *(end-1) = '\r';
1857 if(*end == '\n')
1859 end++;
1860 This->column++;
1862 cur = end;
1864 if(end-ch == len) break;
1868 static void libxmlSetDocumentLocator(
1869 void *ctx,
1870 xmlSAXLocatorPtr loc)
1872 saxlocator *This = ctx;
1873 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1874 HRESULT hr = S_OK;
1876 if (saxreader_has_handler(This, SAXContentHandler))
1878 if(This->vbInterface)
1879 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1880 &This->IVBSAXLocator_iface);
1881 else
1882 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1885 if(FAILED(hr))
1886 format_error_message_from_id(This, hr);
1889 static void libxmlComment(void *ctx, const xmlChar *value)
1891 saxlocator *This = ctx;
1892 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1893 BSTR bValue;
1894 HRESULT hr;
1895 const xmlChar *p = This->pParserCtxt->input->cur;
1897 update_position(This, FALSE);
1898 while(p-4>=This->pParserCtxt->input->base
1899 && memcmp(p-4, "<!--", sizeof(char[4])))
1901 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1902 This->line--;
1903 p--;
1906 This->column = 0;
1907 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1908 This->column++;
1910 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1912 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1914 if (This->vbInterface)
1915 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1916 else
1917 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1919 if(FAILED(hr))
1920 format_error_message_from_id(This, hr);
1923 static void libxmlFatalError(void *ctx, const char *msg, ...)
1925 saxlocator *This = ctx;
1926 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1927 char message[1024];
1928 WCHAR *error;
1929 DWORD len;
1930 va_list args;
1932 if(This->ret != S_OK) {
1933 xmlStopParser(This->pParserCtxt);
1934 return;
1937 va_start(args, msg);
1938 vsprintf(message, msg, args);
1939 va_end(args);
1941 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1942 error = heap_alloc(sizeof(WCHAR)*len);
1943 if(error)
1945 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1946 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1949 if (!saxreader_has_handler(This, SAXErrorHandler))
1951 xmlStopParser(This->pParserCtxt);
1952 This->ret = E_FAIL;
1953 heap_free(error);
1954 return;
1957 FIXME("Error handling is not compatible.\n");
1959 if(This->vbInterface)
1961 BSTR bstrError = SysAllocString(error);
1962 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1963 &bstrError, E_FAIL);
1964 SysFreeString(bstrError);
1966 else
1967 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1969 heap_free(error);
1971 xmlStopParser(This->pParserCtxt);
1972 This->ret = E_FAIL;
1975 /* The only reason this helper exists is that CDATA section are reported by chunks,
1976 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1978 This helper should be called for substring with trailing newlines.
1980 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1982 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1983 WCHAR *ptr;
1985 len = SysStringLen(bstr);
1986 ptr = bstr + len - 1;
1987 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1988 ptr--;
1990 while (*++ptr)
1992 /* replace returns as:
1994 - "\r<char>" -> "\n<char>"
1995 - "\r\r" -> "\r"
1996 - "\r\n" -> "\n"
1998 if (*ptr == '\r')
2000 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
2002 /* shift tail */
2003 memmove(ptr, ptr+1, len-- - (ptr-bstr));
2005 else
2006 *ptr = '\n';
2010 ret = SysAllocStringLen(bstr, len);
2011 SysFreeString(bstr);
2012 return ret;
2015 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2017 const xmlChar *start, *end;
2018 saxlocator *locator = ctx;
2019 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2020 HRESULT hr = S_OK;
2021 BSTR chars;
2022 int i;
2024 update_position(locator, FALSE);
2025 if (saxreader_has_handler(locator, SAXLexicalHandler))
2027 if (locator->vbInterface)
2028 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2029 else
2030 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2033 if(FAILED(hr))
2035 format_error_message_from_id(locator, hr);
2036 return;
2039 start = value;
2040 end = NULL;
2041 i = 0;
2043 while (i < len)
2045 /* scan for newlines */
2046 if (value[i] == '\r' || value[i] == '\n')
2048 /* skip newlines/linefeeds */
2049 while (i < len)
2051 if (value[i] != '\r' && value[i] != '\n') break;
2052 i++;
2054 end = &value[i];
2056 /* report */
2057 chars = saxreader_get_cdata_chunk(start, end-start);
2058 TRACE("(chunk %s)\n", debugstr_w(chars));
2059 hr = saxreader_saxcharacters(locator, chars);
2060 SysFreeString(chars);
2062 start = &value[i];
2063 end = NULL;
2065 i++;
2066 locator->column++;
2069 /* no newline chars (or last chunk) report as a whole */
2070 if (!end && start == value)
2072 /* report */
2073 chars = bstr_from_xmlCharN(start, len-(start-value));
2074 TRACE("(%s)\n", debugstr_w(chars));
2075 hr = saxreader_saxcharacters(locator, chars);
2076 SysFreeString(chars);
2079 if (saxreader_has_handler(locator, SAXLexicalHandler))
2081 if (locator->vbInterface)
2082 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2083 else
2084 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2087 if(FAILED(hr))
2088 format_error_message_from_id(locator, hr);
2091 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2093 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2094 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2097 /*** IVBSAXLocator interface ***/
2098 /*** IUnknown methods ***/
2099 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2101 saxlocator *This = impl_from_IVBSAXLocator( iface );
2103 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2105 *ppvObject = NULL;
2107 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2108 IsEqualGUID( riid, &IID_IDispatch) ||
2109 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2111 *ppvObject = iface;
2113 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2115 *ppvObject = &This->IVBSAXAttributes_iface;
2117 else
2119 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2120 return E_NOINTERFACE;
2123 IVBSAXLocator_AddRef( iface );
2125 return S_OK;
2128 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2130 saxlocator *This = impl_from_IVBSAXLocator( iface );
2131 TRACE("%p\n", This );
2132 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2135 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2137 saxlocator *This = impl_from_IVBSAXLocator( iface );
2138 return ISAXLocator_Release(&This->ISAXLocator_iface);
2141 /*** IDispatch methods ***/
2142 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2144 saxlocator *This = impl_from_IVBSAXLocator( iface );
2146 TRACE("(%p)->(%p)\n", This, pctinfo);
2148 *pctinfo = 1;
2150 return S_OK;
2153 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2154 IVBSAXLocator *iface,
2155 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2157 saxlocator *This = impl_from_IVBSAXLocator( iface );
2159 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2161 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2164 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2165 IVBSAXLocator *iface,
2166 REFIID riid,
2167 LPOLESTR* rgszNames,
2168 UINT cNames,
2169 LCID lcid,
2170 DISPID* rgDispId)
2172 saxlocator *This = impl_from_IVBSAXLocator( iface );
2173 ITypeInfo *typeinfo;
2174 HRESULT hr;
2176 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2177 lcid, rgDispId);
2179 if(!rgszNames || cNames == 0 || !rgDispId)
2180 return E_INVALIDARG;
2182 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2183 if(SUCCEEDED(hr))
2185 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2186 ITypeInfo_Release(typeinfo);
2189 return hr;
2192 static HRESULT WINAPI ivbsaxlocator_Invoke(
2193 IVBSAXLocator *iface,
2194 DISPID dispIdMember,
2195 REFIID riid,
2196 LCID lcid,
2197 WORD wFlags,
2198 DISPPARAMS* pDispParams,
2199 VARIANT* pVarResult,
2200 EXCEPINFO* pExcepInfo,
2201 UINT* puArgErr)
2203 saxlocator *This = impl_from_IVBSAXLocator( iface );
2204 ITypeInfo *typeinfo;
2205 HRESULT hr;
2207 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2208 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2210 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2211 if(SUCCEEDED(hr))
2213 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2214 pDispParams, pVarResult, pExcepInfo, puArgErr);
2215 ITypeInfo_Release(typeinfo);
2218 return hr;
2221 /*** IVBSAXLocator methods ***/
2222 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2223 IVBSAXLocator* iface,
2224 int *pnColumn)
2226 saxlocator *This = impl_from_IVBSAXLocator( iface );
2227 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2230 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2231 IVBSAXLocator* iface,
2232 int *pnLine)
2234 saxlocator *This = impl_from_IVBSAXLocator( iface );
2235 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2238 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2240 saxlocator *This = impl_from_IVBSAXLocator( iface );
2241 const WCHAR *publicidW;
2242 HRESULT hr;
2244 TRACE("(%p)->(%p)\n", This, ret);
2246 if (!ret)
2247 return E_POINTER;
2249 *ret = NULL;
2250 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2251 if (FAILED(hr))
2252 return hr;
2254 return return_bstr(publicidW, ret);
2257 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2259 saxlocator *This = impl_from_IVBSAXLocator( iface );
2260 const WCHAR *systemidW;
2261 HRESULT hr;
2263 TRACE("(%p)->(%p)\n", This, ret);
2265 if (!ret)
2266 return E_POINTER;
2268 *ret = NULL;
2269 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2270 if (FAILED(hr))
2271 return hr;
2273 return return_bstr(systemidW, ret);
2276 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2278 ivbsaxlocator_QueryInterface,
2279 ivbsaxlocator_AddRef,
2280 ivbsaxlocator_Release,
2281 ivbsaxlocator_GetTypeInfoCount,
2282 ivbsaxlocator_GetTypeInfo,
2283 ivbsaxlocator_GetIDsOfNames,
2284 ivbsaxlocator_Invoke,
2285 ivbsaxlocator_get_columnNumber,
2286 ivbsaxlocator_get_lineNumber,
2287 ivbsaxlocator_get_publicId,
2288 ivbsaxlocator_get_systemId
2291 /*** ISAXLocator interface ***/
2292 /*** IUnknown methods ***/
2293 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2295 saxlocator *This = impl_from_ISAXLocator( iface );
2297 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2299 *ppvObject = NULL;
2301 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2302 IsEqualGUID( riid, &IID_ISAXLocator ))
2304 *ppvObject = iface;
2306 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2308 *ppvObject = &This->ISAXAttributes_iface;
2310 else
2312 WARN("interface %s not implemented\n", debugstr_guid(riid));
2313 return E_NOINTERFACE;
2316 ISAXLocator_AddRef( iface );
2318 return S_OK;
2321 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2323 saxlocator *This = impl_from_ISAXLocator( iface );
2324 ULONG ref = InterlockedIncrement( &This->ref );
2325 TRACE("(%p)->(%d)\n", This, ref);
2326 return ref;
2329 static ULONG WINAPI isaxlocator_Release(
2330 ISAXLocator* iface)
2332 saxlocator *This = impl_from_ISAXLocator( iface );
2333 LONG ref = InterlockedDecrement( &This->ref );
2335 TRACE("(%p)->(%d)\n", This, ref );
2337 if (ref == 0)
2339 element_entry *element, *element2;
2340 int index;
2342 SysFreeString(This->publicId);
2343 SysFreeString(This->systemId);
2344 SysFreeString(This->namespaceUri);
2346 for(index = 0; index < This->attr_alloc_count; index++)
2348 SysFreeString(This->attributes[index].szLocalname);
2349 SysFreeString(This->attributes[index].szValue);
2350 SysFreeString(This->attributes[index].szQName);
2352 heap_free(This->attributes);
2354 /* element stack */
2355 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2357 list_remove(&element->entry);
2358 free_element_entry(element);
2361 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2362 heap_free( This );
2365 return ref;
2368 /*** ISAXLocator methods ***/
2369 static HRESULT WINAPI isaxlocator_getColumnNumber(
2370 ISAXLocator* iface,
2371 int *pnColumn)
2373 saxlocator *This = impl_from_ISAXLocator( iface );
2375 *pnColumn = This->column;
2376 return S_OK;
2379 static HRESULT WINAPI isaxlocator_getLineNumber(
2380 ISAXLocator* iface,
2381 int *pnLine)
2383 saxlocator *This = impl_from_ISAXLocator( iface );
2385 *pnLine = This->line;
2386 return S_OK;
2389 static HRESULT WINAPI isaxlocator_getPublicId(
2390 ISAXLocator* iface,
2391 const WCHAR ** ppwchPublicId)
2393 BSTR publicId;
2394 saxlocator *This = impl_from_ISAXLocator( iface );
2396 SysFreeString(This->publicId);
2398 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2399 if(SysStringLen(publicId))
2400 This->publicId = publicId;
2401 else
2403 SysFreeString(publicId);
2404 This->publicId = NULL;
2407 *ppwchPublicId = This->publicId;
2408 return S_OK;
2411 static HRESULT WINAPI isaxlocator_getSystemId(
2412 ISAXLocator* iface,
2413 const WCHAR ** ppwchSystemId)
2415 BSTR systemId;
2416 saxlocator *This = impl_from_ISAXLocator( iface );
2418 SysFreeString(This->systemId);
2420 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2421 if(SysStringLen(systemId))
2422 This->systemId = systemId;
2423 else
2425 SysFreeString(systemId);
2426 This->systemId = NULL;
2429 *ppwchSystemId = This->systemId;
2430 return S_OK;
2433 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2435 isaxlocator_QueryInterface,
2436 isaxlocator_AddRef,
2437 isaxlocator_Release,
2438 isaxlocator_getColumnNumber,
2439 isaxlocator_getLineNumber,
2440 isaxlocator_getPublicId,
2441 isaxlocator_getSystemId
2444 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2446 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2447 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2449 saxlocator *locator;
2451 locator = heap_alloc( sizeof (*locator) );
2452 if( !locator )
2453 return E_OUTOFMEMORY;
2455 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2456 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2457 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2458 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2459 locator->ref = 1;
2460 locator->vbInterface = vbInterface;
2462 locator->saxreader = reader;
2463 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2465 locator->pParserCtxt = NULL;
2466 locator->publicId = NULL;
2467 locator->systemId = NULL;
2468 locator->line = reader->version < MSXML4 ? 0 : 1;
2469 locator->column = 0;
2470 locator->ret = S_OK;
2471 if (locator->saxreader->version >= MSXML6)
2472 locator->namespaceUri = SysAllocString(w3xmlns);
2473 else
2474 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2475 if(!locator->namespaceUri)
2477 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2478 heap_free(locator);
2479 return E_OUTOFMEMORY;
2482 locator->attr_alloc_count = 8;
2483 locator->attr_count = 0;
2484 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2485 if(!locator->attributes)
2487 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2488 SysFreeString(locator->namespaceUri);
2489 heap_free(locator);
2490 return E_OUTOFMEMORY;
2493 list_init(&locator->elements);
2495 *ppsaxlocator = locator;
2497 TRACE("returning %p\n", *ppsaxlocator);
2499 return S_OK;
2502 /*** SAXXMLReader internal functions ***/
2503 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2505 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2506 xmlChar *enc_name = NULL;
2507 saxlocator *locator;
2508 HRESULT hr;
2510 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2512 hr = SAXLocator_create(This, &locator, vbInterface);
2513 if (FAILED(hr))
2514 return hr;
2516 if (size >= 4)
2518 const unsigned char *buff = (unsigned char*)buffer;
2520 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2521 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2522 TRACE("detected encoding: %s\n", enc_name);
2523 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2524 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2525 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2527 buffer += 3;
2528 size -= 3;
2532 /* if libxml2 detection failed try to guess */
2533 if (encoding == XML_CHAR_ENCODING_NONE)
2535 const WCHAR *ptr = (WCHAR*)buffer;
2536 /* an xml declaration with optional encoding will still be handled by the parser */
2537 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2539 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2540 encoding = XML_CHAR_ENCODING_UTF16LE;
2543 else if (encoding == XML_CHAR_ENCODING_UTF8)
2544 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2545 else
2546 enc_name = NULL;
2548 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2549 if (!locator->pParserCtxt)
2551 ISAXLocator_Release(&locator->ISAXLocator_iface);
2552 return E_FAIL;
2555 if (enc_name)
2557 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2558 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2559 TRACE("switching to %s\n", enc_name);
2560 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2564 xmlFree(locator->pParserCtxt->sax);
2565 locator->pParserCtxt->sax = &locator->saxreader->sax;
2566 locator->pParserCtxt->userData = locator;
2568 This->isParsing = TRUE;
2569 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2570 hr = E_FAIL;
2571 else
2572 hr = locator->ret;
2573 This->isParsing = FALSE;
2575 if(locator->pParserCtxt)
2577 locator->pParserCtxt->sax = NULL;
2578 xmlFreeParserCtxt(locator->pParserCtxt);
2579 locator->pParserCtxt = NULL;
2582 ISAXLocator_Release(&locator->ISAXLocator_iface);
2583 return hr;
2586 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2588 saxlocator *locator;
2589 HRESULT hr;
2590 ULONG dataRead;
2591 char data[2048];
2592 int ret;
2594 dataRead = 0;
2595 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2596 if(FAILED(hr)) return hr;
2598 hr = SAXLocator_create(This, &locator, vbInterface);
2599 if(FAILED(hr)) return hr;
2601 locator->pParserCtxt = xmlCreatePushParserCtxt(
2602 &locator->saxreader->sax, locator,
2603 data, dataRead, NULL);
2604 if(!locator->pParserCtxt)
2606 ISAXLocator_Release(&locator->ISAXLocator_iface);
2607 return E_FAIL;
2610 This->isParsing = TRUE;
2612 do {
2613 dataRead = 0;
2614 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2615 if (FAILED(hr) || !dataRead) break;
2617 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2618 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2619 }while(hr == S_OK);
2621 if(SUCCEEDED(hr))
2623 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2624 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2628 This->isParsing = FALSE;
2630 xmlFreeParserCtxt(locator->pParserCtxt);
2631 locator->pParserCtxt = NULL;
2632 ISAXLocator_Release(&locator->ISAXLocator_iface);
2633 return hr;
2636 static HRESULT internal_parse(
2637 saxreader* This,
2638 VARIANT varInput,
2639 BOOL vbInterface)
2641 HRESULT hr;
2643 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2645 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2646 free_bstr_pool(&This->pool);
2648 switch(V_VT(&varInput))
2650 case VT_BSTR:
2651 case VT_BSTR|VT_BYREF:
2653 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2654 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2655 break;
2657 case VT_ARRAY|VT_UI1: {
2658 void *pSAData;
2659 LONG lBound, uBound;
2660 ULONG dataRead;
2662 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2663 if(hr != S_OK) break;
2664 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2665 if(hr != S_OK) break;
2666 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2667 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2668 if(hr != S_OK) break;
2669 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2670 SafeArrayUnaccessData(V_ARRAY(&varInput));
2671 break;
2673 case VT_UNKNOWN:
2674 case VT_DISPATCH: {
2675 ISequentialStream *stream = NULL;
2676 IXMLDOMDocument *xmlDoc;
2678 if (!V_UNKNOWN(&varInput))
2679 return E_INVALIDARG;
2681 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2682 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2684 BSTR bstrData;
2686 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2687 hr = internal_parseBuffer(This, (const char*)bstrData,
2688 SysStringByteLen(bstrData), vbInterface);
2689 IXMLDOMDocument_Release(xmlDoc);
2690 SysFreeString(bstrData);
2691 break;
2694 /* try base interface first */
2695 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2696 if (!stream)
2697 /* this should never happen if IStream is implemented properly, but just in case */
2698 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2700 if(stream)
2702 hr = internal_parseStream(This, stream, vbInterface);
2703 ISequentialStream_Release(stream);
2705 else
2707 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2708 hr = E_INVALIDARG;
2711 break;
2713 default:
2714 WARN("vt %d not implemented\n", V_VT(&varInput));
2715 hr = E_INVALIDARG;
2718 return hr;
2721 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2723 saxreader *This = obj;
2725 return internal_parseBuffer(This, ptr, len, TRUE);
2728 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2730 saxreader *This = obj;
2732 return internal_parseBuffer(This, ptr, len, FALSE);
2735 static HRESULT internal_parseURL(
2736 saxreader* This,
2737 const WCHAR *url,
2738 BOOL vbInterface)
2740 IMoniker *mon;
2741 bsc_t *bsc;
2742 HRESULT hr;
2744 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2746 hr = create_moniker_from_url(url, &mon);
2747 if(FAILED(hr))
2748 return hr;
2750 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2751 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2752 IMoniker_Release(mon);
2754 if(FAILED(hr))
2755 return hr;
2757 return detach_bsc(bsc);
2760 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2762 const IID *riid;
2764 if (V_VT(v) == VT_EMPTY)
2765 return saxreader_put_handler(This, type, NULL, vb);
2767 switch (type)
2769 case SAXDeclHandler:
2770 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2771 break;
2772 case SAXLexicalHandler:
2773 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2774 break;
2775 default:
2776 ERR("wrong handler type %d\n", type);
2777 return E_FAIL;
2780 switch (V_VT(v))
2782 case VT_DISPATCH:
2783 case VT_UNKNOWN:
2785 IUnknown *handler = NULL;
2787 if (V_UNKNOWN(v))
2789 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2790 if (FAILED(hr)) return hr;
2793 saxreader_put_handler(This, type, handler, vb);
2794 if (handler) IUnknown_Release(handler);
2795 break;
2797 default:
2798 ERR("value type %d not supported\n", V_VT(v));
2799 return E_INVALIDARG;
2802 return S_OK;
2805 static HRESULT internal_putProperty(
2806 saxreader* This,
2807 const WCHAR *prop,
2808 VARIANT value,
2809 BOOL vbInterface)
2811 VARIANT *v;
2813 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2815 if (This->isParsing) return E_FAIL;
2817 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2818 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2819 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2821 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2822 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2824 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2826 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2827 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2828 return E_NOTIMPL;
2831 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2833 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2834 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2835 return E_NOTIMPL;
2838 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2840 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2841 return E_NOTIMPL;
2843 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2844 return E_FAIL;
2846 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2847 return E_NOTIMPL;
2849 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2850 return E_NOTIMPL;
2852 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2853 return E_FAIL;
2855 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2856 return E_FAIL;
2858 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2859 return E_FAIL;
2861 return E_INVALIDARG;
2864 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2866 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2868 if (!value) return E_POINTER;
2870 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2872 V_VT(value) = VT_UNKNOWN;
2873 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2874 return S_OK;
2877 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2879 V_VT(value) = VT_UNKNOWN;
2880 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2881 return S_OK;
2884 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2886 V_VT(value) = VT_BSTR;
2887 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2888 return S_OK;
2891 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2893 return E_NOTIMPL;
2896 /*** IVBSAXXMLReader interface ***/
2897 /*** IUnknown methods ***/
2898 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2900 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2902 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2904 *ppvObject = NULL;
2906 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2907 IsEqualGUID( riid, &IID_IDispatch ) ||
2908 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2910 *ppvObject = iface;
2912 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2914 *ppvObject = &This->ISAXXMLReader_iface;
2916 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2918 return *ppvObject ? S_OK : E_NOINTERFACE;
2920 else
2922 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2923 return E_NOINTERFACE;
2926 IVBSAXXMLReader_AddRef( iface );
2928 return S_OK;
2931 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2933 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2934 TRACE("%p\n", This );
2935 return InterlockedIncrement( &This->ref );
2938 static ULONG WINAPI saxxmlreader_Release(
2939 IVBSAXXMLReader* iface)
2941 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2942 LONG ref;
2944 TRACE("%p\n", This );
2946 ref = InterlockedDecrement( &This->ref );
2947 if ( ref == 0 )
2949 int i;
2951 for (i = 0; i < SAXHandler_Last; i++)
2953 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2955 if (saxiface->handler)
2956 IUnknown_Release(saxiface->handler);
2958 if (saxiface->vbhandler)
2959 IUnknown_Release(saxiface->vbhandler);
2962 SysFreeString(This->xmldecl_version);
2963 free_bstr_pool(&This->pool);
2965 heap_free( This );
2968 return ref;
2970 /*** IDispatch ***/
2971 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2973 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2974 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2977 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2978 IVBSAXXMLReader *iface,
2979 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2981 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2982 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2983 iTInfo, lcid, ppTInfo);
2986 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2987 IVBSAXXMLReader *iface,
2988 REFIID riid,
2989 LPOLESTR* rgszNames,
2990 UINT cNames,
2991 LCID lcid,
2992 DISPID* rgDispId)
2994 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2995 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2996 riid, rgszNames, cNames, lcid, rgDispId);
2999 static HRESULT WINAPI saxxmlreader_Invoke(
3000 IVBSAXXMLReader *iface,
3001 DISPID dispIdMember,
3002 REFIID riid,
3003 LCID lcid,
3004 WORD wFlags,
3005 DISPPARAMS* pDispParams,
3006 VARIANT* pVarResult,
3007 EXCEPINFO* pExcepInfo,
3008 UINT* puArgErr)
3010 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3011 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3012 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3015 /*** IVBSAXXMLReader methods ***/
3016 static HRESULT WINAPI saxxmlreader_getFeature(
3017 IVBSAXXMLReader* iface,
3018 BSTR feature_name,
3019 VARIANT_BOOL *value)
3021 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3022 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3025 static HRESULT WINAPI saxxmlreader_putFeature(
3026 IVBSAXXMLReader* iface,
3027 BSTR feature_name,
3028 VARIANT_BOOL value)
3030 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3031 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3034 static HRESULT WINAPI saxxmlreader_getProperty(
3035 IVBSAXXMLReader* iface,
3036 BSTR prop,
3037 VARIANT *value)
3039 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3040 return internal_getProperty(This, prop, value, TRUE);
3043 static HRESULT WINAPI saxxmlreader_putProperty(
3044 IVBSAXXMLReader* iface,
3045 BSTR pProp,
3046 VARIANT value)
3048 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3049 return internal_putProperty(This, pProp, value, TRUE);
3052 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3053 IVBSAXXMLReader* iface,
3054 IVBSAXEntityResolver **resolver)
3056 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3057 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3060 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3061 IVBSAXXMLReader* iface,
3062 IVBSAXEntityResolver *resolver)
3064 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3065 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3068 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3069 IVBSAXXMLReader* iface,
3070 IVBSAXContentHandler **handler)
3072 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3073 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3076 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3077 IVBSAXXMLReader* iface,
3078 IVBSAXContentHandler *handler)
3080 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3081 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3084 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3085 IVBSAXXMLReader* iface,
3086 IVBSAXDTDHandler **handler)
3088 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3089 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3092 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3093 IVBSAXXMLReader* iface,
3094 IVBSAXDTDHandler *handler)
3096 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3097 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3100 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3101 IVBSAXXMLReader* iface,
3102 IVBSAXErrorHandler **handler)
3104 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3105 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3108 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3109 IVBSAXXMLReader* iface,
3110 IVBSAXErrorHandler *handler)
3112 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3113 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3116 static HRESULT WINAPI saxxmlreader_get_baseURL(
3117 IVBSAXXMLReader* iface,
3118 BSTR *pBaseUrl)
3120 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3122 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3123 return E_NOTIMPL;
3126 static HRESULT WINAPI saxxmlreader_put_baseURL(
3127 IVBSAXXMLReader* iface,
3128 BSTR pBaseUrl)
3130 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3131 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3134 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3135 IVBSAXXMLReader* iface,
3136 BSTR *pSecureBaseUrl)
3138 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3140 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3141 return E_NOTIMPL;
3144 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3145 IVBSAXXMLReader* iface,
3146 BSTR secureBaseUrl)
3148 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3149 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3152 static HRESULT WINAPI saxxmlreader_parse(
3153 IVBSAXXMLReader* iface,
3154 VARIANT varInput)
3156 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3157 return internal_parse(This, varInput, TRUE);
3160 static HRESULT WINAPI saxxmlreader_parseURL(
3161 IVBSAXXMLReader* iface,
3162 BSTR url)
3164 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3165 return internal_parseURL(This, url, TRUE);
3168 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3170 saxxmlreader_QueryInterface,
3171 saxxmlreader_AddRef,
3172 saxxmlreader_Release,
3173 saxxmlreader_GetTypeInfoCount,
3174 saxxmlreader_GetTypeInfo,
3175 saxxmlreader_GetIDsOfNames,
3176 saxxmlreader_Invoke,
3177 saxxmlreader_getFeature,
3178 saxxmlreader_putFeature,
3179 saxxmlreader_getProperty,
3180 saxxmlreader_putProperty,
3181 saxxmlreader_get_entityResolver,
3182 saxxmlreader_put_entityResolver,
3183 saxxmlreader_get_contentHandler,
3184 saxxmlreader_put_contentHandler,
3185 saxxmlreader_get_dtdHandler,
3186 saxxmlreader_put_dtdHandler,
3187 saxxmlreader_get_errorHandler,
3188 saxxmlreader_put_errorHandler,
3189 saxxmlreader_get_baseURL,
3190 saxxmlreader_put_baseURL,
3191 saxxmlreader_get_secureBaseURL,
3192 saxxmlreader_put_secureBaseURL,
3193 saxxmlreader_parse,
3194 saxxmlreader_parseURL
3197 /*** ISAXXMLReader interface ***/
3198 /*** IUnknown methods ***/
3199 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3201 saxreader *This = impl_from_ISAXXMLReader( iface );
3202 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3205 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3207 saxreader *This = impl_from_ISAXXMLReader( iface );
3208 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3211 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3213 saxreader *This = impl_from_ISAXXMLReader( iface );
3214 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3217 /*** ISAXXMLReader methods ***/
3218 static HRESULT WINAPI isaxxmlreader_getFeature(
3219 ISAXXMLReader* iface,
3220 const WCHAR *feature_name,
3221 VARIANT_BOOL *value)
3223 saxreader *This = impl_from_ISAXXMLReader( iface );
3224 saxreader_feature feature;
3226 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3228 feature = get_saxreader_feature(feature_name);
3230 if (This->version < MSXML4 && (feature == ExhaustiveErrors || feature == SchemaValidation))
3231 return E_INVALIDARG;
3233 if (feature == Namespaces ||
3234 feature == NamespacePrefixes ||
3235 feature == ExhaustiveErrors ||
3236 feature == SchemaValidation)
3237 return get_feature_value(This, feature, value);
3239 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3240 return E_NOTIMPL;
3243 static HRESULT WINAPI isaxxmlreader_putFeature(
3244 ISAXXMLReader* iface,
3245 const WCHAR *feature_name,
3246 VARIANT_BOOL value)
3248 saxreader *This = impl_from_ISAXXMLReader( iface );
3249 saxreader_feature feature;
3251 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3253 feature = get_saxreader_feature(feature_name);
3255 /* accepted cases */
3256 if ((feature == ExhaustiveErrors && value == VARIANT_FALSE) ||
3257 (feature == SchemaValidation && value == VARIANT_FALSE) ||
3258 feature == Namespaces ||
3259 feature == NamespacePrefixes)
3261 return set_feature_value(This, feature, value);
3264 if (feature == LexicalHandlerParEntities ||
3265 feature == ProhibitDTD ||
3266 feature == ExternalGeneralEntities ||
3267 feature == ExternalParameterEntities)
3269 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3270 return set_feature_value(This, feature, value);
3273 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3274 return E_NOTIMPL;
3277 static HRESULT WINAPI isaxxmlreader_getProperty(
3278 ISAXXMLReader* iface,
3279 const WCHAR *prop,
3280 VARIANT *value)
3282 saxreader *This = impl_from_ISAXXMLReader( iface );
3283 return internal_getProperty(This, prop, value, FALSE);
3286 static HRESULT WINAPI isaxxmlreader_putProperty(
3287 ISAXXMLReader* iface,
3288 const WCHAR *pProp,
3289 VARIANT value)
3291 saxreader *This = impl_from_ISAXXMLReader( iface );
3292 return internal_putProperty(This, pProp, value, FALSE);
3295 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3296 ISAXXMLReader* iface,
3297 ISAXEntityResolver **resolver)
3299 saxreader *This = impl_from_ISAXXMLReader( iface );
3300 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3303 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3304 ISAXXMLReader* iface,
3305 ISAXEntityResolver *resolver)
3307 saxreader *This = impl_from_ISAXXMLReader( iface );
3308 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3311 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3312 ISAXXMLReader* iface,
3313 ISAXContentHandler **handler)
3315 saxreader *This = impl_from_ISAXXMLReader( iface );
3316 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3319 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3320 ISAXXMLReader* iface,
3321 ISAXContentHandler *handler)
3323 saxreader *This = impl_from_ISAXXMLReader( iface );
3324 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3327 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3328 ISAXXMLReader* iface,
3329 ISAXDTDHandler **handler)
3331 saxreader *This = impl_from_ISAXXMLReader( iface );
3332 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3335 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3336 ISAXXMLReader* iface,
3337 ISAXDTDHandler *handler)
3339 saxreader *This = impl_from_ISAXXMLReader( iface );
3340 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3343 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3344 ISAXXMLReader* iface,
3345 ISAXErrorHandler **handler)
3347 saxreader *This = impl_from_ISAXXMLReader( iface );
3348 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3351 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3353 saxreader *This = impl_from_ISAXXMLReader( iface );
3354 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3357 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3358 ISAXXMLReader* iface,
3359 const WCHAR **base_url)
3361 saxreader *This = impl_from_ISAXXMLReader( iface );
3363 FIXME("(%p)->(%p) stub\n", This, base_url);
3364 return E_NOTIMPL;
3367 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3368 ISAXXMLReader* iface,
3369 const WCHAR *pBaseUrl)
3371 saxreader *This = impl_from_ISAXXMLReader( iface );
3373 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3374 return E_NOTIMPL;
3377 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3378 ISAXXMLReader* iface,
3379 const WCHAR **pSecureBaseUrl)
3381 saxreader *This = impl_from_ISAXXMLReader( iface );
3382 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3383 return E_NOTIMPL;
3386 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3387 ISAXXMLReader* iface,
3388 const WCHAR *secureBaseUrl)
3390 saxreader *This = impl_from_ISAXXMLReader( iface );
3392 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3393 return E_NOTIMPL;
3396 static HRESULT WINAPI isaxxmlreader_parse(
3397 ISAXXMLReader* iface,
3398 VARIANT varInput)
3400 saxreader *This = impl_from_ISAXXMLReader( iface );
3401 return internal_parse(This, varInput, FALSE);
3404 static HRESULT WINAPI isaxxmlreader_parseURL(
3405 ISAXXMLReader* iface,
3406 const WCHAR *url)
3408 saxreader *This = impl_from_ISAXXMLReader( iface );
3409 return internal_parseURL(This, url, FALSE);
3412 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3414 isaxxmlreader_QueryInterface,
3415 isaxxmlreader_AddRef,
3416 isaxxmlreader_Release,
3417 isaxxmlreader_getFeature,
3418 isaxxmlreader_putFeature,
3419 isaxxmlreader_getProperty,
3420 isaxxmlreader_putProperty,
3421 isaxxmlreader_getEntityResolver,
3422 isaxxmlreader_putEntityResolver,
3423 isaxxmlreader_getContentHandler,
3424 isaxxmlreader_putContentHandler,
3425 isaxxmlreader_getDTDHandler,
3426 isaxxmlreader_putDTDHandler,
3427 isaxxmlreader_getErrorHandler,
3428 isaxxmlreader_putErrorHandler,
3429 isaxxmlreader_getBaseURL,
3430 isaxxmlreader_putBaseURL,
3431 isaxxmlreader_getSecureBaseURL,
3432 isaxxmlreader_putSecureBaseURL,
3433 isaxxmlreader_parse,
3434 isaxxmlreader_parseURL
3437 static const tid_t saxreader_iface_tids[] = {
3438 IVBSAXXMLReader_tid,
3441 static dispex_static_data_t saxreader_dispex = {
3442 NULL,
3443 IVBSAXXMLReader_tid,
3444 NULL,
3445 saxreader_iface_tids
3448 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3450 saxreader *reader;
3452 TRACE("(%p)\n", ppObj);
3454 reader = heap_alloc( sizeof (*reader) );
3455 if( !reader )
3456 return E_OUTOFMEMORY;
3458 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3459 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3460 reader->ref = 1;
3461 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3462 reader->isParsing = FALSE;
3463 reader->xmldecl_version = NULL;
3464 reader->pool.pool = NULL;
3465 reader->pool.index = 0;
3466 reader->pool.len = 0;
3467 reader->features = Namespaces | NamespacePrefixes;
3468 reader->version = version;
3470 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3472 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3473 reader->sax.initialized = XML_SAX2_MAGIC;
3474 reader->sax.startDocument = libxmlStartDocument;
3475 reader->sax.endDocument = libxmlEndDocument;
3476 reader->sax.startElementNs = libxmlStartElementNS;
3477 reader->sax.endElementNs = libxmlEndElementNS;
3478 reader->sax.characters = libxmlCharacters;
3479 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3480 reader->sax.comment = libxmlComment;
3481 reader->sax.error = libxmlFatalError;
3482 reader->sax.fatalError = libxmlFatalError;
3483 reader->sax.cdataBlock = libxml_cdatablock;
3484 reader->sax.resolveEntity = libxmlresolveentity;
3486 *ppObj = &reader->IVBSAXXMLReader_iface;
3488 TRACE("returning iface %p\n", *ppObj);
3490 return S_OK;
3493 #else
3495 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3497 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3498 "libxml2 support was not present at compile time.\n");
3499 return E_NOTIMPL;
3502 #endif