msxml3/saxreader: Accept external-general-entities and external-parameter-entities.
[wine.git] / dlls / msxml3 / saxreader.c
blob2a30475e08a2d2ac124978051c9941505ac3ebd2
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 struct saxreader_feature_pair
109 saxreader_feature feature;
110 const WCHAR *name;
113 static const struct saxreader_feature_pair saxreader_feature_map[] = {
114 { ExhaustiveErrors, ExhaustiveErrorsW },
115 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
116 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
117 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
118 { NamespacePrefixes, FeatureNamespacePrefixesW },
119 { Namespaces, FeatureNamespacesW },
120 { ProhibitDTD, FeatureProhibitDTDW }
123 static saxreader_feature get_saxreader_feature(const WCHAR *name)
125 int min, max, n, c;
127 min = 0;
128 max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
130 while (min <= max)
132 n = (min+max)/2;
134 c = strcmpW(saxreader_feature_map[n].name, name);
135 if (!c)
136 return saxreader_feature_map[n].feature;
138 if (c > 0)
139 max = n-1;
140 else
141 min = n+1;
144 return FeatureUnknown;
147 struct bstrpool
149 BSTR *pool;
150 unsigned int index;
151 unsigned int len;
154 typedef struct
156 BSTR prefix;
157 BSTR uri;
158 } ns;
160 typedef struct
162 struct list entry;
163 BSTR prefix;
164 BSTR local;
165 BSTR qname;
166 ns *ns; /* namespaces defined in this particular element */
167 int ns_count;
168 } element_entry;
170 enum saxhandler_type
172 SAXContentHandler = 0,
173 SAXDeclHandler,
174 SAXDTDHandler,
175 SAXEntityResolver,
176 SAXErrorHandler,
177 SAXLexicalHandler,
178 SAXHandler_Last
181 struct saxanyhandler_iface
183 IUnknown *handler;
184 IUnknown *vbhandler;
187 struct saxcontenthandler_iface
189 ISAXContentHandler *handler;
190 IVBSAXContentHandler *vbhandler;
193 struct saxerrorhandler_iface
195 ISAXErrorHandler *handler;
196 IVBSAXErrorHandler *vbhandler;
199 struct saxlexicalhandler_iface
201 ISAXLexicalHandler *handler;
202 IVBSAXLexicalHandler *vbhandler;
205 struct saxentityresolver_iface
207 ISAXEntityResolver *handler;
208 IVBSAXEntityResolver *vbhandler;
211 struct saxhandler_iface
213 union {
214 struct saxcontenthandler_iface content;
215 struct saxentityresolver_iface entityresolver;
216 struct saxerrorhandler_iface error;
217 struct saxlexicalhandler_iface lexical;
218 struct saxanyhandler_iface anyhandler;
219 } u;
222 typedef struct
224 DispatchEx dispex;
225 IVBSAXXMLReader IVBSAXXMLReader_iface;
226 ISAXXMLReader ISAXXMLReader_iface;
227 LONG ref;
229 struct saxhandler_iface saxhandlers[SAXHandler_Last];
230 xmlSAXHandler sax;
231 BOOL isParsing;
232 struct bstrpool pool;
233 saxreader_feature features;
234 BSTR xmldecl_version;
235 MSXML_VERSION version;
236 } saxreader;
238 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
240 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
241 IUnknown *unk = (IUnknown*)ptr;
243 if (unk)
244 IUnknown_AddRef(unk);
246 if ((vb && iface->vbhandler) || (!vb && iface->handler))
247 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
249 if (vb)
250 iface->vbhandler = unk;
251 else
252 iface->handler = unk;
254 return S_OK;
257 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
259 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
261 if (!ret) return E_POINTER;
263 if ((vb && iface->vbhandler) || (!vb && iface->handler))
265 if (vb)
266 IUnknown_AddRef(iface->vbhandler);
267 else
268 IUnknown_AddRef(iface->handler);
271 *ret = vb ? iface->vbhandler : iface->handler;
273 return S_OK;
276 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
278 return &reader->saxhandlers[SAXContentHandler].u.content;
281 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
283 return &reader->saxhandlers[SAXErrorHandler].u.error;
286 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
288 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
291 typedef struct
293 IVBSAXLocator IVBSAXLocator_iface;
294 ISAXLocator ISAXLocator_iface;
295 IVBSAXAttributes IVBSAXAttributes_iface;
296 ISAXAttributes ISAXAttributes_iface;
297 LONG ref;
298 saxreader *saxreader;
299 HRESULT ret;
300 xmlParserCtxtPtr pParserCtxt;
301 BSTR publicId;
302 BSTR systemId;
303 int line;
304 int column;
305 BOOL vbInterface;
306 struct list elements;
308 BSTR namespaceUri;
309 int attr_alloc_count;
310 int attr_count;
311 struct _attributes
313 BSTR szLocalname;
314 BSTR szURI;
315 BSTR szValue;
316 BSTR szQName;
317 } *attributes;
318 } saxlocator;
320 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
322 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
325 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
327 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
330 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
332 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
335 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
337 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
340 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
342 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
345 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
347 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
350 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
352 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
353 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
356 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
358 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
359 HRESULT hr;
361 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
363 if (locator->vbInterface)
364 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
365 else
366 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
368 return hr;
371 /* property names */
372 static const WCHAR PropertyCharsetW[] = {
373 'c','h','a','r','s','e','t',0
375 static const WCHAR PropertyXmlDeclVersionW[] = {
376 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
378 static const WCHAR PropertyDeclHandlerW[] = {
379 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
380 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
381 'd','e','c','l','a','r','a','t','i','o','n',
382 '-','h','a','n','d','l','e','r',0
384 static const WCHAR PropertyDomNodeW[] = {
385 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
386 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
387 'd','o','m','-','n','o','d','e',0
389 static const WCHAR PropertyInputSourceW[] = {
390 'i','n','p','u','t','-','s','o','u','r','c','e',0
392 static const WCHAR PropertyLexicalHandlerW[] = {
393 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
394 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
395 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
397 static const WCHAR PropertyMaxElementDepthW[] = {
398 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
400 static const WCHAR PropertyMaxXMLSizeW[] = {
401 'm','a','x','-','x','m','l','-','s','i','z','e',0
403 static const WCHAR PropertySchemaDeclHandlerW[] = {
404 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
405 'h','a','n','d','l','e','r',0
407 static const WCHAR PropertyXMLDeclEncodingW[] = {
408 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
410 static const WCHAR PropertyXMLDeclStandaloneW[] = {
411 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
413 static const WCHAR PropertyXMLDeclVersionW[] = {
414 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
417 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
419 /* handling of non-VARIANT_* values is version dependent */
420 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
421 value = VARIANT_FALSE;
422 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
423 value = VARIANT_TRUE;
425 if (value == VARIANT_TRUE)
426 reader->features |= feature;
427 else
428 reader->features &= ~feature;
430 return S_OK;
433 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
435 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
436 return S_OK;
439 static BOOL is_namespaces_enabled(const saxreader *reader)
441 return (reader->version < MSXML4) || (reader->features & Namespaces);
444 static BSTR build_qname(BSTR prefix, BSTR local)
446 if (prefix && *prefix)
448 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
449 WCHAR *ptr;
451 ptr = qname;
452 strcpyW(ptr, prefix);
453 ptr += SysStringLen(prefix);
454 *ptr++ = ':';
455 strcpyW(ptr, local);
456 return qname;
458 else
459 return SysAllocString(local);
462 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
463 const xmlChar **namespaces)
465 element_entry *ret;
466 int i;
468 ret = heap_alloc(sizeof(*ret));
469 if (!ret) return ret;
471 ret->local = bstr_from_xmlChar(local);
472 ret->prefix = bstr_from_xmlChar(prefix);
473 ret->qname = build_qname(ret->prefix, ret->local);
474 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
475 ret->ns_count = nb_ns;
477 for (i=0; i < nb_ns; i++)
479 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
480 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
483 return ret;
486 static void free_element_entry(element_entry *element)
488 int i;
490 for (i=0; i<element->ns_count;i++)
492 SysFreeString(element->ns[i].prefix);
493 SysFreeString(element->ns[i].uri);
496 SysFreeString(element->prefix);
497 SysFreeString(element->local);
498 SysFreeString(element->qname);
500 heap_free(element->ns);
501 heap_free(element);
504 static void push_element_ns(saxlocator *locator, element_entry *element)
506 list_add_head(&locator->elements, &element->entry);
509 static element_entry * pop_element_ns(saxlocator *locator)
511 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
513 if (element)
514 list_remove(&element->entry);
516 return element;
519 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
521 element_entry *element;
522 BSTR uriW;
523 int i;
525 if (!uri) return NULL;
527 uriW = bstr_from_xmlChar(uri);
529 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
531 for (i=0; i < element->ns_count; i++)
532 if (!strcmpW(uriW, element->ns[i].uri))
534 SysFreeString(uriW);
535 return element->ns[i].uri;
539 SysFreeString(uriW);
540 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
541 return NULL;
544 /* used to localize version dependent error check behaviour */
545 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
547 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
550 /* index value -1 means it tries to loop for a first time */
551 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
553 if (This->saxreader->version >= MSXML4)
555 if (*i == -1) *i = 0; else ++*i;
556 return *i < element->ns_count;
558 else
560 if (*i == -1) *i = element->ns_count-1; else --*i;
561 return *i >= 0;
565 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
567 if (!pool->pool)
569 pool->pool = heap_alloc(16 * sizeof(*pool->pool));
570 if (!pool->pool)
571 return FALSE;
573 pool->index = 0;
574 pool->len = 16;
576 else if (pool->index == pool->len)
578 BSTR *realloc = heap_realloc(pool->pool, pool->len * 2 * sizeof(*realloc));
580 if (!realloc)
581 return FALSE;
583 pool->pool = realloc;
584 pool->len *= 2;
587 pool->pool[pool->index++] = pool_entry;
588 return TRUE;
591 static void free_bstr_pool(struct bstrpool *pool)
593 unsigned int i;
595 for (i = 0; i < pool->index; i++)
596 SysFreeString(pool->pool[i]);
598 heap_free(pool->pool);
600 pool->pool = NULL;
601 pool->index = pool->len = 0;
604 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
606 DWORD dLen;
607 BSTR bstr;
609 if (!buf)
610 return NULL;
612 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
613 if(len != -1) dLen++;
614 bstr = SysAllocStringLen(NULL, dLen-1);
615 if (!bstr)
616 return NULL;
617 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
618 if(len != -1) bstr[dLen-1] = '\0';
620 return bstr;
623 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
625 xmlChar *qname;
626 BSTR bstr;
628 if(!name) return NULL;
630 if(!prefix || !*prefix)
631 return bstr_from_xmlChar(name);
633 qname = xmlBuildQName(name, prefix, NULL, 0);
634 bstr = bstr_from_xmlChar(qname);
635 xmlFree(qname);
637 return bstr;
640 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
642 BSTR pool_entry = bstr_from_xmlChar(buf);
644 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
646 SysFreeString(pool_entry);
647 return NULL;
650 return pool_entry;
653 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
655 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
657 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
659 SysFreeString(pool_entry);
660 return NULL;
663 return pool_entry;
666 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
668 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
669 xmlStopParser(This->pParserCtxt);
670 This->ret = hr;
672 if (saxreader_has_handler(This, SAXErrorHandler))
674 WCHAR msg[1024];
675 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
676 NULL, hr, 0, msg, sizeof(msg)/sizeof(msg[0]), NULL))
678 FIXME("MSXML errors not yet supported.\n");
679 msg[0] = '\0';
682 if(This->vbInterface)
684 BSTR bstrMsg = SysAllocString(msg);
685 IVBSAXErrorHandler_fatalError(handler->vbhandler,
686 &This->IVBSAXLocator_iface, &bstrMsg, hr);
687 SysFreeString(bstrMsg);
689 else
690 ISAXErrorHandler_fatalError(handler->handler,
691 &This->ISAXLocator_iface, msg, hr);
695 static void update_position(saxlocator *This, BOOL fix_column)
697 const xmlChar *p = This->pParserCtxt->input->cur-1;
698 const xmlChar *baseP = This->pParserCtxt->input->base;
700 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
701 if(fix_column)
703 This->column = 1;
704 for(;p>=baseP && *p!='\n' && *p!='\r'; p--)
705 This->column++;
707 else
709 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
713 /*** IVBSAXAttributes interface ***/
714 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
715 IVBSAXAttributes* iface,
716 REFIID riid,
717 void **ppvObject)
719 saxlocator *This = impl_from_IVBSAXAttributes(iface);
720 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
721 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
724 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
726 saxlocator *This = impl_from_IVBSAXAttributes(iface);
727 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
730 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
732 saxlocator *This = impl_from_IVBSAXAttributes(iface);
733 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
736 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
738 saxlocator *This = impl_from_IVBSAXAttributes( iface );
740 TRACE("(%p)->(%p)\n", This, pctinfo);
742 *pctinfo = 1;
744 return S_OK;
747 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
748 IVBSAXAttributes *iface,
749 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
751 saxlocator *This = impl_from_IVBSAXAttributes( iface );
753 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
755 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
758 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
759 IVBSAXAttributes *iface,
760 REFIID riid,
761 LPOLESTR* rgszNames,
762 UINT cNames,
763 LCID lcid,
764 DISPID* rgDispId)
766 saxlocator *This = impl_from_IVBSAXAttributes( iface );
767 ITypeInfo *typeinfo;
768 HRESULT hr;
770 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
771 lcid, rgDispId);
773 if(!rgszNames || cNames == 0 || !rgDispId)
774 return E_INVALIDARG;
776 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
777 if(SUCCEEDED(hr))
779 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
780 ITypeInfo_Release(typeinfo);
783 return hr;
786 static HRESULT WINAPI ivbsaxattributes_Invoke(
787 IVBSAXAttributes *iface,
788 DISPID dispIdMember,
789 REFIID riid,
790 LCID lcid,
791 WORD wFlags,
792 DISPPARAMS* pDispParams,
793 VARIANT* pVarResult,
794 EXCEPINFO* pExcepInfo,
795 UINT* puArgErr)
797 saxlocator *This = impl_from_IVBSAXAttributes( iface );
798 ITypeInfo *typeinfo;
799 HRESULT hr;
801 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
802 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
804 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
805 if(SUCCEEDED(hr))
807 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
808 pDispParams, pVarResult, pExcepInfo, puArgErr);
809 ITypeInfo_Release(typeinfo);
812 return hr;
815 /*** IVBSAXAttributes methods ***/
816 static HRESULT WINAPI ivbsaxattributes_get_length(
817 IVBSAXAttributes* iface,
818 int *nLength)
820 saxlocator *This = impl_from_IVBSAXAttributes( iface );
821 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
824 static HRESULT WINAPI ivbsaxattributes_getURI(
825 IVBSAXAttributes* iface,
826 int nIndex,
827 BSTR *uri)
829 saxlocator *This = impl_from_IVBSAXAttributes( iface );
830 const WCHAR *uriW;
831 HRESULT hr;
832 int len;
834 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
836 if (!uri)
837 return E_POINTER;
839 *uri = NULL;
840 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
841 if (FAILED(hr))
842 return hr;
844 return return_bstrn(uriW, len, uri);
847 static HRESULT WINAPI ivbsaxattributes_getLocalName(
848 IVBSAXAttributes* iface,
849 int nIndex,
850 BSTR *name)
852 saxlocator *This = impl_from_IVBSAXAttributes( iface );
853 const WCHAR *nameW;
854 HRESULT hr;
855 int len;
857 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
859 if (!name)
860 return E_POINTER;
862 *name = NULL;
863 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
864 if (FAILED(hr))
865 return hr;
867 return return_bstrn(nameW, len, name);
870 static HRESULT WINAPI ivbsaxattributes_getQName(
871 IVBSAXAttributes* iface,
872 int nIndex,
873 BSTR *QName)
875 saxlocator *This = impl_from_IVBSAXAttributes( iface );
876 const WCHAR *nameW;
877 HRESULT hr;
878 int len;
880 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
882 if (!QName)
883 return E_POINTER;
885 *QName = NULL;
886 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
887 if (FAILED(hr))
888 return hr;
890 return return_bstrn(nameW, len, QName);
893 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
894 IVBSAXAttributes* iface,
895 BSTR uri,
896 BSTR localName,
897 int *index)
899 saxlocator *This = impl_from_IVBSAXAttributes( iface );
900 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
901 localName, SysStringLen(localName), index);
904 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
905 IVBSAXAttributes* iface,
906 BSTR QName,
907 int *index)
909 saxlocator *This = impl_from_IVBSAXAttributes( iface );
910 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
911 SysStringLen(QName), index);
914 static HRESULT WINAPI ivbsaxattributes_getType(
915 IVBSAXAttributes* iface,
916 int nIndex,
917 BSTR *type)
919 saxlocator *This = impl_from_IVBSAXAttributes( iface );
920 const WCHAR *typeW;
921 HRESULT hr;
922 int len;
924 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
926 if (!type)
927 return E_POINTER;
929 *type = NULL;
930 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
931 if (FAILED(hr))
932 return hr;
934 return return_bstrn(typeW, len, type);
937 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
938 IVBSAXAttributes* iface,
939 BSTR uri,
940 BSTR localName,
941 BSTR *type)
943 saxlocator *This = impl_from_IVBSAXAttributes( iface );
944 const WCHAR *typeW;
945 HRESULT hr;
946 int len;
948 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
950 if (!type)
951 return E_POINTER;
953 *type = NULL;
954 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
955 localName, SysStringLen(localName), &typeW, &len);
956 if (FAILED(hr))
957 return hr;
959 return return_bstrn(typeW, len, type);
962 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
963 IVBSAXAttributes* iface,
964 BSTR QName,
965 BSTR *type)
967 saxlocator *This = impl_from_IVBSAXAttributes( iface );
968 const WCHAR *typeW;
969 HRESULT hr;
970 int len;
972 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
974 if (!type)
975 return E_POINTER;
977 *type = NULL;
978 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
979 &typeW, &len);
980 if (FAILED(hr))
981 return hr;
983 return return_bstrn(typeW, len, type);
986 static HRESULT WINAPI ivbsaxattributes_getValue(
987 IVBSAXAttributes* iface,
988 int nIndex,
989 BSTR *value)
991 saxlocator *This = impl_from_IVBSAXAttributes( iface );
992 const WCHAR *valueW;
993 HRESULT hr;
994 int len;
996 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
998 if (!value)
999 return E_POINTER;
1001 *value = NULL;
1002 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
1003 if (FAILED(hr))
1004 return hr;
1006 return return_bstrn(valueW, len, value);
1009 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1010 IVBSAXAttributes* iface,
1011 BSTR uri,
1012 BSTR localName,
1013 BSTR *value)
1015 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1016 const WCHAR *valueW;
1017 HRESULT hr;
1018 int len;
1020 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1022 if (!value)
1023 return E_POINTER;
1025 *value = NULL;
1026 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1027 localName, SysStringLen(localName), &valueW, &len);
1028 if (FAILED(hr))
1029 return hr;
1031 return return_bstrn(valueW, len, value);
1034 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1035 IVBSAXAttributes* iface,
1036 BSTR QName,
1037 BSTR *value)
1039 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1040 const WCHAR *valueW;
1041 HRESULT hr;
1042 int len;
1044 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1046 if (!value)
1047 return E_POINTER;
1049 *value = NULL;
1050 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1051 SysStringLen(QName), &valueW, &len);
1052 if (FAILED(hr))
1053 return hr;
1055 return return_bstrn(valueW, len, value);
1058 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1060 ivbsaxattributes_QueryInterface,
1061 ivbsaxattributes_AddRef,
1062 ivbsaxattributes_Release,
1063 ivbsaxattributes_GetTypeInfoCount,
1064 ivbsaxattributes_GetTypeInfo,
1065 ivbsaxattributes_GetIDsOfNames,
1066 ivbsaxattributes_Invoke,
1067 ivbsaxattributes_get_length,
1068 ivbsaxattributes_getURI,
1069 ivbsaxattributes_getLocalName,
1070 ivbsaxattributes_getQName,
1071 ivbsaxattributes_getIndexFromName,
1072 ivbsaxattributes_getIndexFromQName,
1073 ivbsaxattributes_getType,
1074 ivbsaxattributes_getTypeFromName,
1075 ivbsaxattributes_getTypeFromQName,
1076 ivbsaxattributes_getValue,
1077 ivbsaxattributes_getValueFromName,
1078 ivbsaxattributes_getValueFromQName
1081 /*** ISAXAttributes interface ***/
1082 /*** IUnknown methods ***/
1083 static HRESULT WINAPI isaxattributes_QueryInterface(
1084 ISAXAttributes* iface,
1085 REFIID riid,
1086 void **ppvObject)
1088 saxlocator *This = impl_from_ISAXAttributes(iface);
1089 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1090 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1093 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1095 saxlocator *This = impl_from_ISAXAttributes(iface);
1096 TRACE("%p\n", This);
1097 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1100 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1102 saxlocator *This = impl_from_ISAXAttributes(iface);
1104 TRACE("%p\n", This);
1105 return ISAXLocator_Release(&This->ISAXLocator_iface);
1108 /*** ISAXAttributes methods ***/
1109 static HRESULT WINAPI isaxattributes_getLength(
1110 ISAXAttributes* iface,
1111 int *length)
1113 saxlocator *This = impl_from_ISAXAttributes( iface );
1115 *length = This->attr_count;
1116 TRACE("Length set to %d\n", *length);
1117 return S_OK;
1120 static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
1122 return index < locator->attr_count && index >= 0;
1125 static HRESULT WINAPI isaxattributes_getURI(
1126 ISAXAttributes* iface,
1127 int index,
1128 const WCHAR **url,
1129 int *size)
1131 saxlocator *This = impl_from_ISAXAttributes( iface );
1132 TRACE("(%p)->(%d)\n", This, index);
1134 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1135 if(!url || !size) return E_POINTER;
1137 *size = SysStringLen(This->attributes[index].szURI);
1138 *url = This->attributes[index].szURI;
1140 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1142 return S_OK;
1145 static HRESULT WINAPI isaxattributes_getLocalName(
1146 ISAXAttributes* iface,
1147 int index,
1148 const WCHAR **pLocalName,
1149 int *pLocalNameLength)
1151 saxlocator *This = impl_from_ISAXAttributes( iface );
1152 TRACE("(%p)->(%d)\n", This, index);
1154 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1155 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1157 *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
1158 *pLocalName = This->attributes[index].szLocalname;
1160 return S_OK;
1163 static HRESULT WINAPI isaxattributes_getQName(
1164 ISAXAttributes* iface,
1165 int index,
1166 const WCHAR **pQName,
1167 int *pQNameLength)
1169 saxlocator *This = impl_from_ISAXAttributes( iface );
1170 TRACE("(%p)->(%d)\n", This, index);
1172 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1173 if(!pQName || !pQNameLength) return E_POINTER;
1175 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1176 *pQName = This->attributes[index].szQName;
1178 return S_OK;
1181 static HRESULT WINAPI isaxattributes_getName(
1182 ISAXAttributes* iface,
1183 int index,
1184 const WCHAR **uri,
1185 int *pUriLength,
1186 const WCHAR **localName,
1187 int *pLocalNameSize,
1188 const WCHAR **QName,
1189 int *pQNameLength)
1191 saxlocator *This = impl_from_ISAXAttributes( iface );
1192 TRACE("(%p)->(%d)\n", This, index);
1194 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1195 if(!uri || !pUriLength || !localName || !pLocalNameSize
1196 || !QName || !pQNameLength) return E_POINTER;
1198 *pUriLength = SysStringLen(This->attributes[index].szURI);
1199 *uri = This->attributes[index].szURI;
1200 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1201 *localName = This->attributes[index].szLocalname;
1202 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1203 *QName = This->attributes[index].szQName;
1205 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1207 return S_OK;
1210 static HRESULT WINAPI isaxattributes_getIndexFromName(
1211 ISAXAttributes* iface,
1212 const WCHAR *pUri,
1213 int cUriLength,
1214 const WCHAR *pLocalName,
1215 int cocalNameLength,
1216 int *index)
1218 saxlocator *This = impl_from_ISAXAttributes( iface );
1219 int i;
1220 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1221 debugstr_w(pLocalName), cocalNameLength);
1223 if(!pUri || !pLocalName || !index) return E_POINTER;
1225 for(i=0; i<This->attr_count; i++)
1227 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1228 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1229 continue;
1230 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1231 sizeof(WCHAR)*cUriLength))
1232 continue;
1233 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1234 sizeof(WCHAR)*cocalNameLength))
1235 continue;
1237 *index = i;
1238 return S_OK;
1241 return E_INVALIDARG;
1244 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1245 ISAXAttributes* iface,
1246 const WCHAR *pQName,
1247 int nQNameLength,
1248 int *index)
1250 saxlocator *This = impl_from_ISAXAttributes( iface );
1251 int i;
1252 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1254 if(!pQName || !index) return E_POINTER;
1255 if(!nQNameLength) return E_INVALIDARG;
1257 for(i=0; i<This->attr_count; i++)
1259 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1260 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1262 *index = i;
1263 return S_OK;
1266 return E_INVALIDARG;
1269 static HRESULT WINAPI isaxattributes_getType(
1270 ISAXAttributes* iface,
1271 int nIndex,
1272 const WCHAR **pType,
1273 int *pTypeLength)
1275 saxlocator *This = impl_from_ISAXAttributes( iface );
1277 FIXME("(%p)->(%d) stub\n", This, nIndex);
1278 return E_NOTIMPL;
1281 static HRESULT WINAPI isaxattributes_getTypeFromName(
1282 ISAXAttributes* iface,
1283 const WCHAR *pUri,
1284 int nUri,
1285 const WCHAR *pLocalName,
1286 int nLocalName,
1287 const WCHAR **pType,
1288 int *nType)
1290 saxlocator *This = impl_from_ISAXAttributes( iface );
1292 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1293 debugstr_w(pLocalName), nLocalName);
1294 return E_NOTIMPL;
1297 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1298 ISAXAttributes* iface,
1299 const WCHAR *pQName,
1300 int nQName,
1301 const WCHAR **pType,
1302 int *nType)
1304 saxlocator *This = impl_from_ISAXAttributes( iface );
1306 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1307 return E_NOTIMPL;
1310 static HRESULT WINAPI isaxattributes_getValue(
1311 ISAXAttributes* iface,
1312 int index,
1313 const WCHAR **value,
1314 int *nValue)
1316 saxlocator *This = impl_from_ISAXAttributes( iface );
1317 TRACE("(%p)->(%d)\n", This, index);
1319 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1320 if(!value || !nValue) return E_POINTER;
1322 *nValue = SysStringLen(This->attributes[index].szValue);
1323 *value = This->attributes[index].szValue;
1325 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1327 return S_OK;
1330 static HRESULT WINAPI isaxattributes_getValueFromName(
1331 ISAXAttributes* iface,
1332 const WCHAR *pUri,
1333 int nUri,
1334 const WCHAR *pLocalName,
1335 int nLocalName,
1336 const WCHAR **pValue,
1337 int *nValue)
1339 HRESULT hr;
1340 int index;
1341 saxlocator *This = impl_from_ISAXAttributes( iface );
1342 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1343 debugstr_w(pLocalName), nLocalName);
1345 hr = ISAXAttributes_getIndexFromName(iface,
1346 pUri, nUri, pLocalName, nLocalName, &index);
1347 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1349 return hr;
1352 static HRESULT WINAPI isaxattributes_getValueFromQName(
1353 ISAXAttributes* iface,
1354 const WCHAR *pQName,
1355 int nQName,
1356 const WCHAR **pValue,
1357 int *nValue)
1359 HRESULT hr;
1360 int index;
1361 saxlocator *This = impl_from_ISAXAttributes( iface );
1362 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1364 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1365 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1367 return hr;
1370 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1372 isaxattributes_QueryInterface,
1373 isaxattributes_AddRef,
1374 isaxattributes_Release,
1375 isaxattributes_getLength,
1376 isaxattributes_getURI,
1377 isaxattributes_getLocalName,
1378 isaxattributes_getQName,
1379 isaxattributes_getName,
1380 isaxattributes_getIndexFromName,
1381 isaxattributes_getIndexFromQName,
1382 isaxattributes_getType,
1383 isaxattributes_getTypeFromName,
1384 isaxattributes_getTypeFromQName,
1385 isaxattributes_getValue,
1386 isaxattributes_getValueFromName,
1387 isaxattributes_getValueFromQName
1390 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1391 so when document has escaped value with '&amp;' it's parsed to '&' and then
1392 escaped to '&#38;'. This function takes care of ampersands only. */
1393 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1395 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1396 WCHAR *dest, *ptrW, *str;
1397 DWORD str_len;
1398 BSTR bstr;
1400 if (!buf)
1401 return NULL;
1403 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1404 if (len != -1) str_len++;
1406 str = heap_alloc(str_len*sizeof(WCHAR));
1407 if (!str) return NULL;
1409 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1410 if (len != -1) str[str_len-1] = 0;
1412 ptrW = str;
1413 while ((dest = strstrW(ptrW, ampescW)))
1415 WCHAR *src;
1417 /* leave first '&' from a reference as a value */
1418 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1419 dest++;
1421 /* move together with null terminator */
1422 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1424 ptrW++;
1427 bstr = SysAllocString(str);
1428 heap_free(str);
1430 return bstr;
1433 static void free_attribute_values(saxlocator *locator)
1435 int i;
1437 for (i = 0; i < locator->attr_count; i++)
1439 SysFreeString(locator->attributes[i].szLocalname);
1440 locator->attributes[i].szLocalname = NULL;
1442 SysFreeString(locator->attributes[i].szValue);
1443 locator->attributes[i].szValue = NULL;
1445 SysFreeString(locator->attributes[i].szQName);
1446 locator->attributes[i].szQName = NULL;
1450 static HRESULT SAXAttributes_populate(saxlocator *locator,
1451 int nb_namespaces, const xmlChar **xmlNamespaces,
1452 int nb_attributes, const xmlChar **xmlAttributes)
1454 static const xmlChar xmlns[] = "xmlns";
1455 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1457 struct _attributes *attrs;
1458 int i;
1460 /* skip namespace definitions */
1461 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1462 nb_namespaces = 0;
1464 locator->attr_count = nb_namespaces + nb_attributes;
1465 if(locator->attr_count > locator->attr_alloc_count)
1467 int new_size = locator->attr_count * 2;
1468 attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1469 if(!attrs)
1471 free_attribute_values(locator);
1472 locator->attr_count = 0;
1473 return E_OUTOFMEMORY;
1475 locator->attributes = attrs;
1476 locator->attr_alloc_count = new_size;
1478 else
1480 attrs = locator->attributes;
1483 for (i = 0; i < nb_namespaces; i++)
1485 SysFreeString(attrs[nb_attributes+i].szLocalname);
1486 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1488 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1490 SysFreeString(attrs[nb_attributes+i].szValue);
1491 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1493 SysFreeString(attrs[nb_attributes+i].szQName);
1494 if(!xmlNamespaces[2*i])
1495 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1496 else
1497 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1500 for (i = 0; i < nb_attributes; i++)
1502 static const xmlChar xmlA[] = "xml";
1504 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1505 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1506 else
1507 /* that's an important feature to keep same uri pointer for every reported attribute */
1508 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1510 SysFreeString(attrs[i].szLocalname);
1511 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1513 SysFreeString(attrs[i].szValue);
1514 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1516 SysFreeString(attrs[i].szQName);
1517 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1520 return S_OK;
1523 /*** LibXML callbacks ***/
1524 static void libxmlStartDocument(void *ctx)
1526 saxlocator *This = ctx;
1527 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1528 HRESULT hr;
1530 if (This->saxreader->version >= MSXML4)
1532 const xmlChar *p = This->pParserCtxt->input->cur-1;
1533 update_position(This, FALSE);
1534 while(p>This->pParserCtxt->input->base && *p!='>')
1536 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1537 This->line--;
1538 p--;
1540 This->column = 0;
1541 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1542 This->column++;
1545 /* store version value, declaration has to contain version attribute */
1546 if (This->pParserCtxt->standalone != -1)
1548 SysFreeString(This->saxreader->xmldecl_version);
1549 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1552 if (saxreader_has_handler(This, SAXContentHandler))
1554 if(This->vbInterface)
1555 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1556 else
1557 hr = ISAXContentHandler_startDocument(handler->handler);
1559 if (sax_callback_failed(This, hr))
1560 format_error_message_from_id(This, hr);
1564 static void libxmlEndDocument(void *ctx)
1566 saxlocator *This = ctx;
1567 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1568 HRESULT hr;
1570 if (This->saxreader->version >= MSXML4) {
1571 update_position(This, FALSE);
1572 if(This->column > 1)
1573 This->line++;
1574 This->column = 0;
1575 } else {
1576 This->column = 0;
1577 This->line = 0;
1580 if(This->ret != S_OK) return;
1582 if (saxreader_has_handler(This, SAXContentHandler))
1584 if(This->vbInterface)
1585 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1586 else
1587 hr = ISAXContentHandler_endDocument(handler->handler);
1589 if (sax_callback_failed(This, hr))
1590 format_error_message_from_id(This, hr);
1594 static void libxmlStartElementNS(
1595 void *ctx,
1596 const xmlChar *localname,
1597 const xmlChar *prefix,
1598 const xmlChar *URI,
1599 int nb_namespaces,
1600 const xmlChar **namespaces,
1601 int nb_attributes,
1602 int nb_defaulted,
1603 const xmlChar **attributes)
1605 saxlocator *This = ctx;
1606 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1607 element_entry *element;
1608 HRESULT hr = S_OK;
1609 BSTR uri;
1611 update_position(This, TRUE);
1612 if(*(This->pParserCtxt->input->cur) == '/')
1613 This->column++;
1614 if(This->saxreader->version < MSXML4)
1615 This->column++;
1617 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1618 push_element_ns(This, element);
1620 if (is_namespaces_enabled(This->saxreader))
1622 int i;
1624 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1626 if (This->vbInterface)
1627 hr = IVBSAXContentHandler_startPrefixMapping(
1628 handler->vbhandler,
1629 &element->ns[i].prefix,
1630 &element->ns[i].uri);
1631 else
1632 hr = ISAXContentHandler_startPrefixMapping(
1633 handler->handler,
1634 element->ns[i].prefix,
1635 SysStringLen(element->ns[i].prefix),
1636 element->ns[i].uri,
1637 SysStringLen(element->ns[i].uri));
1639 if (sax_callback_failed(This, hr))
1641 format_error_message_from_id(This, hr);
1642 return;
1647 uri = find_element_uri(This, URI);
1648 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1649 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1651 BSTR local;
1653 if (is_namespaces_enabled(This->saxreader))
1654 local = element->local;
1655 else
1656 uri = local = NULL;
1658 if (This->vbInterface)
1659 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1660 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1661 else
1662 hr = ISAXContentHandler_startElement(handler->handler,
1663 uri, SysStringLen(uri),
1664 local, SysStringLen(local),
1665 element->qname, SysStringLen(element->qname),
1666 &This->ISAXAttributes_iface);
1668 if (sax_callback_failed(This, hr))
1669 format_error_message_from_id(This, hr);
1673 static void libxmlEndElementNS(
1674 void *ctx,
1675 const xmlChar *localname,
1676 const xmlChar *prefix,
1677 const xmlChar *URI)
1679 saxlocator *This = ctx;
1680 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1681 element_entry *element;
1682 const xmlChar *p;
1683 BSTR uri, local;
1684 HRESULT hr;
1686 update_position(This, FALSE);
1687 p = This->pParserCtxt->input->cur;
1689 if (This->saxreader->version >= MSXML4)
1691 p--;
1692 while(p>This->pParserCtxt->input->base && *p!='>')
1694 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1695 This->line--;
1696 p--;
1699 else if(*(p-1)!='>' || *(p-2)!='/')
1701 p--;
1702 while(p-2>=This->pParserCtxt->input->base
1703 && *(p-2)!='<' && *(p-1)!='/')
1705 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1706 This->line--;
1707 p--;
1710 This->column = 0;
1711 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1712 This->column++;
1714 uri = find_element_uri(This, URI);
1715 element = pop_element_ns(This);
1717 if (!saxreader_has_handler(This, SAXContentHandler))
1719 free_attribute_values(This);
1720 This->attr_count = 0;
1721 free_element_entry(element);
1722 return;
1725 if (is_namespaces_enabled(This->saxreader))
1726 local = element->local;
1727 else
1728 uri = local = NULL;
1730 if (This->vbInterface)
1731 hr = IVBSAXContentHandler_endElement(
1732 handler->vbhandler,
1733 &uri, &local, &element->qname);
1734 else
1735 hr = ISAXContentHandler_endElement(
1736 handler->handler,
1737 uri, SysStringLen(uri),
1738 local, SysStringLen(local),
1739 element->qname, SysStringLen(element->qname));
1741 free_attribute_values(This);
1742 This->attr_count = 0;
1744 if (sax_callback_failed(This, hr))
1746 format_error_message_from_id(This, hr);
1747 free_element_entry(element);
1748 return;
1751 if (is_namespaces_enabled(This->saxreader))
1753 int i = -1;
1754 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1756 if (This->vbInterface)
1757 hr = IVBSAXContentHandler_endPrefixMapping(
1758 handler->vbhandler, &element->ns[i].prefix);
1759 else
1760 hr = ISAXContentHandler_endPrefixMapping(
1761 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1763 if (sax_callback_failed(This, hr)) break;
1766 if (sax_callback_failed(This, hr))
1767 format_error_message_from_id(This, hr);
1770 free_element_entry(element);
1773 static void libxmlCharacters(
1774 void *ctx,
1775 const xmlChar *ch,
1776 int len)
1778 saxlocator *This = ctx;
1779 BSTR Chars;
1780 HRESULT hr;
1781 xmlChar *cur, *end;
1782 BOOL lastEvent = FALSE;
1784 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1786 update_position(This, FALSE);
1787 cur = (xmlChar*)This->pParserCtxt->input->cur;
1788 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1790 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1791 This->line--;
1792 cur--;
1794 This->column = 1;
1795 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1796 This->column++;
1798 cur = (xmlChar*)ch;
1799 if(*(ch-1)=='\r') cur--;
1800 end = cur;
1802 while(1)
1804 while(end-ch<len && *end!='\r') end++;
1805 if(end-ch==len)
1807 lastEvent = TRUE;
1809 else
1811 *end = '\n';
1812 end++;
1815 if (This->saxreader->version >= MSXML4)
1817 xmlChar *p;
1819 for(p=cur; p!=end; p++)
1821 if(*p=='\n')
1823 This->line++;
1824 This->column = 1;
1826 else
1828 This->column++;
1832 if(!lastEvent)
1833 This->column = 0;
1836 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1837 hr = saxreader_saxcharacters(This, Chars);
1839 if (sax_callback_failed(This, hr))
1841 format_error_message_from_id(This, hr);
1842 return;
1845 if (This->saxreader->version < MSXML4)
1846 This->column += end-cur;
1848 if(lastEvent)
1849 break;
1851 *(end-1) = '\r';
1852 if(*end == '\n')
1854 end++;
1855 This->column++;
1857 cur = end;
1859 if(end-ch == len) break;
1863 static void libxmlSetDocumentLocator(
1864 void *ctx,
1865 xmlSAXLocatorPtr loc)
1867 saxlocator *This = ctx;
1868 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1869 HRESULT hr = S_OK;
1871 if (saxreader_has_handler(This, SAXContentHandler))
1873 if(This->vbInterface)
1874 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1875 &This->IVBSAXLocator_iface);
1876 else
1877 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1880 if(FAILED(hr))
1881 format_error_message_from_id(This, hr);
1884 static void libxmlComment(void *ctx, const xmlChar *value)
1886 saxlocator *This = ctx;
1887 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1888 BSTR bValue;
1889 HRESULT hr;
1890 const xmlChar *p = This->pParserCtxt->input->cur;
1892 update_position(This, FALSE);
1893 while(p-4>=This->pParserCtxt->input->base
1894 && memcmp(p-4, "<!--", sizeof(char[4])))
1896 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1897 This->line--;
1898 p--;
1901 This->column = 0;
1902 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1903 This->column++;
1905 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1907 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1909 if (This->vbInterface)
1910 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1911 else
1912 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1914 if(FAILED(hr))
1915 format_error_message_from_id(This, hr);
1918 static void libxmlFatalError(void *ctx, const char *msg, ...)
1920 saxlocator *This = ctx;
1921 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1922 char message[1024];
1923 WCHAR *error;
1924 DWORD len;
1925 va_list args;
1927 if(This->ret != S_OK) {
1928 xmlStopParser(This->pParserCtxt);
1929 return;
1932 va_start(args, msg);
1933 vsprintf(message, msg, args);
1934 va_end(args);
1936 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1937 error = heap_alloc(sizeof(WCHAR)*len);
1938 if(error)
1940 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1941 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1944 if (!saxreader_has_handler(This, SAXErrorHandler))
1946 xmlStopParser(This->pParserCtxt);
1947 This->ret = E_FAIL;
1948 heap_free(error);
1949 return;
1952 FIXME("Error handling is not compatible.\n");
1954 if(This->vbInterface)
1956 BSTR bstrError = SysAllocString(error);
1957 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1958 &bstrError, E_FAIL);
1959 SysFreeString(bstrError);
1961 else
1962 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1964 heap_free(error);
1966 xmlStopParser(This->pParserCtxt);
1967 This->ret = E_FAIL;
1970 /* The only reason this helper exists is that CDATA section are reported by chunks,
1971 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1973 This helper should be called for substring with trailing newlines.
1975 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1977 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1978 WCHAR *ptr;
1980 len = SysStringLen(bstr);
1981 ptr = bstr + len - 1;
1982 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1983 ptr--;
1985 while (*++ptr)
1987 /* replace returns as:
1989 - "\r<char>" -> "\n<char>"
1990 - "\r\r" -> "\r"
1991 - "\r\n" -> "\n"
1993 if (*ptr == '\r')
1995 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1997 /* shift tail */
1998 memmove(ptr, ptr+1, len-- - (ptr-bstr));
2000 else
2001 *ptr = '\n';
2005 ret = SysAllocStringLen(bstr, len);
2006 SysFreeString(bstr);
2007 return ret;
2010 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2012 const xmlChar *start, *end;
2013 saxlocator *locator = ctx;
2014 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2015 HRESULT hr = S_OK;
2016 BSTR chars;
2017 int i;
2019 update_position(locator, FALSE);
2020 if (saxreader_has_handler(locator, SAXLexicalHandler))
2022 if (locator->vbInterface)
2023 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2024 else
2025 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2028 if(FAILED(hr))
2030 format_error_message_from_id(locator, hr);
2031 return;
2034 start = value;
2035 end = NULL;
2036 i = 0;
2038 while (i < len)
2040 /* scan for newlines */
2041 if (value[i] == '\r' || value[i] == '\n')
2043 /* skip newlines/linefeeds */
2044 while (i < len)
2046 if (value[i] != '\r' && value[i] != '\n') break;
2047 i++;
2049 end = &value[i];
2051 /* report */
2052 chars = saxreader_get_cdata_chunk(start, end-start);
2053 TRACE("(chunk %s)\n", debugstr_w(chars));
2054 hr = saxreader_saxcharacters(locator, chars);
2055 SysFreeString(chars);
2057 start = &value[i];
2058 end = NULL;
2060 i++;
2061 locator->column++;
2064 /* no newline chars (or last chunk) report as a whole */
2065 if (!end && start == value)
2067 /* report */
2068 chars = bstr_from_xmlCharN(start, len-(start-value));
2069 TRACE("(%s)\n", debugstr_w(chars));
2070 hr = saxreader_saxcharacters(locator, chars);
2071 SysFreeString(chars);
2074 if (saxreader_has_handler(locator, SAXLexicalHandler))
2076 if (locator->vbInterface)
2077 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2078 else
2079 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2082 if(FAILED(hr))
2083 format_error_message_from_id(locator, hr);
2086 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2088 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2089 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2092 /*** IVBSAXLocator interface ***/
2093 /*** IUnknown methods ***/
2094 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2096 saxlocator *This = impl_from_IVBSAXLocator( iface );
2098 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2100 *ppvObject = NULL;
2102 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2103 IsEqualGUID( riid, &IID_IDispatch) ||
2104 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2106 *ppvObject = iface;
2108 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2110 *ppvObject = &This->IVBSAXAttributes_iface;
2112 else
2114 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2115 return E_NOINTERFACE;
2118 IVBSAXLocator_AddRef( iface );
2120 return S_OK;
2123 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2125 saxlocator *This = impl_from_IVBSAXLocator( iface );
2126 TRACE("%p\n", This );
2127 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2130 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2132 saxlocator *This = impl_from_IVBSAXLocator( iface );
2133 return ISAXLocator_Release(&This->ISAXLocator_iface);
2136 /*** IDispatch methods ***/
2137 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2139 saxlocator *This = impl_from_IVBSAXLocator( iface );
2141 TRACE("(%p)->(%p)\n", This, pctinfo);
2143 *pctinfo = 1;
2145 return S_OK;
2148 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2149 IVBSAXLocator *iface,
2150 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2152 saxlocator *This = impl_from_IVBSAXLocator( iface );
2154 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2156 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2159 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2160 IVBSAXLocator *iface,
2161 REFIID riid,
2162 LPOLESTR* rgszNames,
2163 UINT cNames,
2164 LCID lcid,
2165 DISPID* rgDispId)
2167 saxlocator *This = impl_from_IVBSAXLocator( iface );
2168 ITypeInfo *typeinfo;
2169 HRESULT hr;
2171 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2172 lcid, rgDispId);
2174 if(!rgszNames || cNames == 0 || !rgDispId)
2175 return E_INVALIDARG;
2177 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2178 if(SUCCEEDED(hr))
2180 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2181 ITypeInfo_Release(typeinfo);
2184 return hr;
2187 static HRESULT WINAPI ivbsaxlocator_Invoke(
2188 IVBSAXLocator *iface,
2189 DISPID dispIdMember,
2190 REFIID riid,
2191 LCID lcid,
2192 WORD wFlags,
2193 DISPPARAMS* pDispParams,
2194 VARIANT* pVarResult,
2195 EXCEPINFO* pExcepInfo,
2196 UINT* puArgErr)
2198 saxlocator *This = impl_from_IVBSAXLocator( iface );
2199 ITypeInfo *typeinfo;
2200 HRESULT hr;
2202 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2203 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2205 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2206 if(SUCCEEDED(hr))
2208 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2209 pDispParams, pVarResult, pExcepInfo, puArgErr);
2210 ITypeInfo_Release(typeinfo);
2213 return hr;
2216 /*** IVBSAXLocator methods ***/
2217 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2218 IVBSAXLocator* iface,
2219 int *pnColumn)
2221 saxlocator *This = impl_from_IVBSAXLocator( iface );
2222 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2225 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2226 IVBSAXLocator* iface,
2227 int *pnLine)
2229 saxlocator *This = impl_from_IVBSAXLocator( iface );
2230 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2233 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2235 saxlocator *This = impl_from_IVBSAXLocator( iface );
2236 const WCHAR *publicidW;
2237 HRESULT hr;
2239 TRACE("(%p)->(%p)\n", This, ret);
2241 if (!ret)
2242 return E_POINTER;
2244 *ret = NULL;
2245 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2246 if (FAILED(hr))
2247 return hr;
2249 return return_bstr(publicidW, ret);
2252 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2254 saxlocator *This = impl_from_IVBSAXLocator( iface );
2255 const WCHAR *systemidW;
2256 HRESULT hr;
2258 TRACE("(%p)->(%p)\n", This, ret);
2260 if (!ret)
2261 return E_POINTER;
2263 *ret = NULL;
2264 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2265 if (FAILED(hr))
2266 return hr;
2268 return return_bstr(systemidW, ret);
2271 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2273 ivbsaxlocator_QueryInterface,
2274 ivbsaxlocator_AddRef,
2275 ivbsaxlocator_Release,
2276 ivbsaxlocator_GetTypeInfoCount,
2277 ivbsaxlocator_GetTypeInfo,
2278 ivbsaxlocator_GetIDsOfNames,
2279 ivbsaxlocator_Invoke,
2280 ivbsaxlocator_get_columnNumber,
2281 ivbsaxlocator_get_lineNumber,
2282 ivbsaxlocator_get_publicId,
2283 ivbsaxlocator_get_systemId
2286 /*** ISAXLocator interface ***/
2287 /*** IUnknown methods ***/
2288 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2290 saxlocator *This = impl_from_ISAXLocator( iface );
2292 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2294 *ppvObject = NULL;
2296 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2297 IsEqualGUID( riid, &IID_ISAXLocator ))
2299 *ppvObject = iface;
2301 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2303 *ppvObject = &This->ISAXAttributes_iface;
2305 else
2307 WARN("interface %s not implemented\n", debugstr_guid(riid));
2308 return E_NOINTERFACE;
2311 ISAXLocator_AddRef( iface );
2313 return S_OK;
2316 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2318 saxlocator *This = impl_from_ISAXLocator( iface );
2319 ULONG ref = InterlockedIncrement( &This->ref );
2320 TRACE("(%p)->(%d)\n", This, ref);
2321 return ref;
2324 static ULONG WINAPI isaxlocator_Release(
2325 ISAXLocator* iface)
2327 saxlocator *This = impl_from_ISAXLocator( iface );
2328 LONG ref = InterlockedDecrement( &This->ref );
2330 TRACE("(%p)->(%d)\n", This, ref );
2332 if (ref == 0)
2334 element_entry *element, *element2;
2335 int index;
2337 SysFreeString(This->publicId);
2338 SysFreeString(This->systemId);
2339 SysFreeString(This->namespaceUri);
2341 for(index = 0; index < This->attr_alloc_count; index++)
2343 SysFreeString(This->attributes[index].szLocalname);
2344 SysFreeString(This->attributes[index].szValue);
2345 SysFreeString(This->attributes[index].szQName);
2347 heap_free(This->attributes);
2349 /* element stack */
2350 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2352 list_remove(&element->entry);
2353 free_element_entry(element);
2356 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2357 heap_free( This );
2360 return ref;
2363 /*** ISAXLocator methods ***/
2364 static HRESULT WINAPI isaxlocator_getColumnNumber(
2365 ISAXLocator* iface,
2366 int *pnColumn)
2368 saxlocator *This = impl_from_ISAXLocator( iface );
2370 *pnColumn = This->column;
2371 return S_OK;
2374 static HRESULT WINAPI isaxlocator_getLineNumber(
2375 ISAXLocator* iface,
2376 int *pnLine)
2378 saxlocator *This = impl_from_ISAXLocator( iface );
2380 *pnLine = This->line;
2381 return S_OK;
2384 static HRESULT WINAPI isaxlocator_getPublicId(
2385 ISAXLocator* iface,
2386 const WCHAR ** ppwchPublicId)
2388 BSTR publicId;
2389 saxlocator *This = impl_from_ISAXLocator( iface );
2391 SysFreeString(This->publicId);
2393 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2394 if(SysStringLen(publicId))
2395 This->publicId = publicId;
2396 else
2398 SysFreeString(publicId);
2399 This->publicId = NULL;
2402 *ppwchPublicId = This->publicId;
2403 return S_OK;
2406 static HRESULT WINAPI isaxlocator_getSystemId(
2407 ISAXLocator* iface,
2408 const WCHAR ** ppwchSystemId)
2410 BSTR systemId;
2411 saxlocator *This = impl_from_ISAXLocator( iface );
2413 SysFreeString(This->systemId);
2415 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2416 if(SysStringLen(systemId))
2417 This->systemId = systemId;
2418 else
2420 SysFreeString(systemId);
2421 This->systemId = NULL;
2424 *ppwchSystemId = This->systemId;
2425 return S_OK;
2428 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2430 isaxlocator_QueryInterface,
2431 isaxlocator_AddRef,
2432 isaxlocator_Release,
2433 isaxlocator_getColumnNumber,
2434 isaxlocator_getLineNumber,
2435 isaxlocator_getPublicId,
2436 isaxlocator_getSystemId
2439 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2441 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2442 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2444 saxlocator *locator;
2446 locator = heap_alloc( sizeof (*locator) );
2447 if( !locator )
2448 return E_OUTOFMEMORY;
2450 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2451 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2452 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2453 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2454 locator->ref = 1;
2455 locator->vbInterface = vbInterface;
2457 locator->saxreader = reader;
2458 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2460 locator->pParserCtxt = NULL;
2461 locator->publicId = NULL;
2462 locator->systemId = NULL;
2463 locator->line = reader->version < MSXML4 ? 0 : 1;
2464 locator->column = 0;
2465 locator->ret = S_OK;
2466 if (locator->saxreader->version >= MSXML6)
2467 locator->namespaceUri = SysAllocString(w3xmlns);
2468 else
2469 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2470 if(!locator->namespaceUri)
2472 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2473 heap_free(locator);
2474 return E_OUTOFMEMORY;
2477 locator->attr_alloc_count = 8;
2478 locator->attr_count = 0;
2479 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2480 if(!locator->attributes)
2482 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2483 SysFreeString(locator->namespaceUri);
2484 heap_free(locator);
2485 return E_OUTOFMEMORY;
2488 list_init(&locator->elements);
2490 *ppsaxlocator = locator;
2492 TRACE("returning %p\n", *ppsaxlocator);
2494 return S_OK;
2497 /*** SAXXMLReader internal functions ***/
2498 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2500 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2501 xmlChar *enc_name = NULL;
2502 saxlocator *locator;
2503 HRESULT hr;
2505 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2507 hr = SAXLocator_create(This, &locator, vbInterface);
2508 if (FAILED(hr))
2509 return hr;
2511 if (size >= 4)
2513 const unsigned char *buff = (unsigned char*)buffer;
2515 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2516 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2517 TRACE("detected encoding: %s\n", enc_name);
2518 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2519 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2520 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2522 buffer += 3;
2523 size -= 3;
2527 /* if libxml2 detection failed try to guess */
2528 if (encoding == XML_CHAR_ENCODING_NONE)
2530 const WCHAR *ptr = (WCHAR*)buffer;
2531 /* an xml declaration with optional encoding will still be handled by the parser */
2532 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2534 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2535 encoding = XML_CHAR_ENCODING_UTF16LE;
2538 else if (encoding == XML_CHAR_ENCODING_UTF8)
2539 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2540 else
2541 enc_name = NULL;
2543 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2544 if (!locator->pParserCtxt)
2546 ISAXLocator_Release(&locator->ISAXLocator_iface);
2547 return E_FAIL;
2550 if (enc_name)
2552 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2553 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2554 TRACE("switching to %s\n", enc_name);
2555 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2559 xmlFree(locator->pParserCtxt->sax);
2560 locator->pParserCtxt->sax = &locator->saxreader->sax;
2561 locator->pParserCtxt->userData = locator;
2563 This->isParsing = TRUE;
2564 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2565 hr = E_FAIL;
2566 else
2567 hr = locator->ret;
2568 This->isParsing = FALSE;
2570 if(locator->pParserCtxt)
2572 locator->pParserCtxt->sax = NULL;
2573 xmlFreeParserCtxt(locator->pParserCtxt);
2574 locator->pParserCtxt = NULL;
2577 ISAXLocator_Release(&locator->ISAXLocator_iface);
2578 return hr;
2581 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2583 saxlocator *locator;
2584 HRESULT hr;
2585 ULONG dataRead;
2586 char data[2048];
2587 int ret;
2589 dataRead = 0;
2590 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2591 if(FAILED(hr)) return hr;
2593 hr = SAXLocator_create(This, &locator, vbInterface);
2594 if(FAILED(hr)) return hr;
2596 locator->pParserCtxt = xmlCreatePushParserCtxt(
2597 &locator->saxreader->sax, locator,
2598 data, dataRead, NULL);
2599 if(!locator->pParserCtxt)
2601 ISAXLocator_Release(&locator->ISAXLocator_iface);
2602 return E_FAIL;
2605 This->isParsing = TRUE;
2607 do {
2608 dataRead = 0;
2609 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2610 if (FAILED(hr) || !dataRead) break;
2612 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2613 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2614 }while(hr == S_OK);
2616 if(SUCCEEDED(hr))
2618 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2619 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2623 This->isParsing = FALSE;
2625 xmlFreeParserCtxt(locator->pParserCtxt);
2626 locator->pParserCtxt = NULL;
2627 ISAXLocator_Release(&locator->ISAXLocator_iface);
2628 return hr;
2631 static HRESULT internal_parse(
2632 saxreader* This,
2633 VARIANT varInput,
2634 BOOL vbInterface)
2636 HRESULT hr;
2638 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2640 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2641 free_bstr_pool(&This->pool);
2643 switch(V_VT(&varInput))
2645 case VT_BSTR:
2646 case VT_BSTR|VT_BYREF:
2648 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2649 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2650 break;
2652 case VT_ARRAY|VT_UI1: {
2653 void *pSAData;
2654 LONG lBound, uBound;
2655 ULONG dataRead;
2657 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2658 if(hr != S_OK) break;
2659 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2660 if(hr != S_OK) break;
2661 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2662 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2663 if(hr != S_OK) break;
2664 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2665 SafeArrayUnaccessData(V_ARRAY(&varInput));
2666 break;
2668 case VT_UNKNOWN:
2669 case VT_DISPATCH: {
2670 ISequentialStream *stream = NULL;
2671 IXMLDOMDocument *xmlDoc;
2673 if (!V_UNKNOWN(&varInput))
2674 return E_INVALIDARG;
2676 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2677 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2679 BSTR bstrData;
2681 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2682 hr = internal_parseBuffer(This, (const char*)bstrData,
2683 SysStringByteLen(bstrData), vbInterface);
2684 IXMLDOMDocument_Release(xmlDoc);
2685 SysFreeString(bstrData);
2686 break;
2689 /* try base interface first */
2690 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2691 if (!stream)
2692 /* this should never happen if IStream is implemented properly, but just in case */
2693 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2695 if(stream)
2697 hr = internal_parseStream(This, stream, vbInterface);
2698 ISequentialStream_Release(stream);
2700 else
2702 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2703 hr = E_INVALIDARG;
2706 break;
2708 default:
2709 WARN("vt %d not implemented\n", V_VT(&varInput));
2710 hr = E_INVALIDARG;
2713 return hr;
2716 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2718 saxreader *This = obj;
2720 return internal_parseBuffer(This, ptr, len, TRUE);
2723 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2725 saxreader *This = obj;
2727 return internal_parseBuffer(This, ptr, len, FALSE);
2730 static HRESULT internal_parseURL(
2731 saxreader* This,
2732 const WCHAR *url,
2733 BOOL vbInterface)
2735 IMoniker *mon;
2736 bsc_t *bsc;
2737 HRESULT hr;
2739 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2741 hr = create_moniker_from_url(url, &mon);
2742 if(FAILED(hr))
2743 return hr;
2745 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2746 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2747 IMoniker_Release(mon);
2749 if(FAILED(hr))
2750 return hr;
2752 return detach_bsc(bsc);
2755 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2757 const IID *riid;
2759 if (V_VT(v) == VT_EMPTY)
2760 return saxreader_put_handler(This, type, NULL, vb);
2762 switch (type)
2764 case SAXDeclHandler:
2765 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2766 break;
2767 case SAXLexicalHandler:
2768 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2769 break;
2770 default:
2771 ERR("wrong handler type %d\n", type);
2772 return E_FAIL;
2775 switch (V_VT(v))
2777 case VT_DISPATCH:
2778 case VT_UNKNOWN:
2780 IUnknown *handler = NULL;
2782 if (V_UNKNOWN(v))
2784 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2785 if (FAILED(hr)) return hr;
2788 saxreader_put_handler(This, type, handler, vb);
2789 if (handler) IUnknown_Release(handler);
2790 break;
2792 default:
2793 ERR("value type %d not supported\n", V_VT(v));
2794 return E_INVALIDARG;
2797 return S_OK;
2800 static HRESULT internal_putProperty(
2801 saxreader* This,
2802 const WCHAR *prop,
2803 VARIANT value,
2804 BOOL vbInterface)
2806 VARIANT *v;
2808 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2810 if (This->isParsing) return E_FAIL;
2812 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2813 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2814 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2816 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2817 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2819 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2821 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2822 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2823 return E_NOTIMPL;
2826 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2828 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2829 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2830 return E_NOTIMPL;
2833 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2835 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2836 return E_NOTIMPL;
2838 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2839 return E_FAIL;
2841 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2842 return E_NOTIMPL;
2844 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2845 return E_NOTIMPL;
2847 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2848 return E_FAIL;
2850 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2851 return E_FAIL;
2853 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2854 return E_FAIL;
2856 return E_INVALIDARG;
2859 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2861 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2863 if (!value) return E_POINTER;
2865 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2867 V_VT(value) = VT_UNKNOWN;
2868 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2869 return S_OK;
2872 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2874 V_VT(value) = VT_UNKNOWN;
2875 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2876 return S_OK;
2879 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2881 V_VT(value) = VT_BSTR;
2882 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2883 return S_OK;
2886 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2888 return E_NOTIMPL;
2891 /*** IVBSAXXMLReader interface ***/
2892 /*** IUnknown methods ***/
2893 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2895 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2897 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2899 *ppvObject = NULL;
2901 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2902 IsEqualGUID( riid, &IID_IDispatch ) ||
2903 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2905 *ppvObject = iface;
2907 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2909 *ppvObject = &This->ISAXXMLReader_iface;
2911 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2913 return *ppvObject ? S_OK : E_NOINTERFACE;
2915 else
2917 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2918 return E_NOINTERFACE;
2921 IVBSAXXMLReader_AddRef( iface );
2923 return S_OK;
2926 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2928 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2929 TRACE("%p\n", This );
2930 return InterlockedIncrement( &This->ref );
2933 static ULONG WINAPI saxxmlreader_Release(
2934 IVBSAXXMLReader* iface)
2936 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2937 LONG ref;
2939 TRACE("%p\n", This );
2941 ref = InterlockedDecrement( &This->ref );
2942 if ( ref == 0 )
2944 int i;
2946 for (i = 0; i < SAXHandler_Last; i++)
2948 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2950 if (saxiface->handler)
2951 IUnknown_Release(saxiface->handler);
2953 if (saxiface->vbhandler)
2954 IUnknown_Release(saxiface->vbhandler);
2957 SysFreeString(This->xmldecl_version);
2958 free_bstr_pool(&This->pool);
2960 heap_free( This );
2963 return ref;
2965 /*** IDispatch ***/
2966 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2968 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2969 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2972 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2973 IVBSAXXMLReader *iface,
2974 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2976 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2977 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2978 iTInfo, lcid, ppTInfo);
2981 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2982 IVBSAXXMLReader *iface,
2983 REFIID riid,
2984 LPOLESTR* rgszNames,
2985 UINT cNames,
2986 LCID lcid,
2987 DISPID* rgDispId)
2989 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2990 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2991 riid, rgszNames, cNames, lcid, rgDispId);
2994 static HRESULT WINAPI saxxmlreader_Invoke(
2995 IVBSAXXMLReader *iface,
2996 DISPID dispIdMember,
2997 REFIID riid,
2998 LCID lcid,
2999 WORD wFlags,
3000 DISPPARAMS* pDispParams,
3001 VARIANT* pVarResult,
3002 EXCEPINFO* pExcepInfo,
3003 UINT* puArgErr)
3005 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3006 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3007 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3010 /*** IVBSAXXMLReader methods ***/
3011 static HRESULT WINAPI saxxmlreader_getFeature(
3012 IVBSAXXMLReader* iface,
3013 BSTR feature_name,
3014 VARIANT_BOOL *value)
3016 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3017 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3020 static HRESULT WINAPI saxxmlreader_putFeature(
3021 IVBSAXXMLReader* iface,
3022 BSTR feature_name,
3023 VARIANT_BOOL value)
3025 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3026 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3029 static HRESULT WINAPI saxxmlreader_getProperty(
3030 IVBSAXXMLReader* iface,
3031 BSTR prop,
3032 VARIANT *value)
3034 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3035 return internal_getProperty(This, prop, value, TRUE);
3038 static HRESULT WINAPI saxxmlreader_putProperty(
3039 IVBSAXXMLReader* iface,
3040 BSTR pProp,
3041 VARIANT value)
3043 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3044 return internal_putProperty(This, pProp, value, TRUE);
3047 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3048 IVBSAXXMLReader* iface,
3049 IVBSAXEntityResolver **resolver)
3051 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3052 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3055 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3056 IVBSAXXMLReader* iface,
3057 IVBSAXEntityResolver *resolver)
3059 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3060 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3063 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3064 IVBSAXXMLReader* iface,
3065 IVBSAXContentHandler **handler)
3067 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3068 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3071 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3072 IVBSAXXMLReader* iface,
3073 IVBSAXContentHandler *handler)
3075 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3076 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3079 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3080 IVBSAXXMLReader* iface,
3081 IVBSAXDTDHandler **handler)
3083 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3084 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3087 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3088 IVBSAXXMLReader* iface,
3089 IVBSAXDTDHandler *handler)
3091 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3092 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3095 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3096 IVBSAXXMLReader* iface,
3097 IVBSAXErrorHandler **handler)
3099 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3100 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3103 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3104 IVBSAXXMLReader* iface,
3105 IVBSAXErrorHandler *handler)
3107 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3108 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3111 static HRESULT WINAPI saxxmlreader_get_baseURL(
3112 IVBSAXXMLReader* iface,
3113 BSTR *pBaseUrl)
3115 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3117 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3118 return E_NOTIMPL;
3121 static HRESULT WINAPI saxxmlreader_put_baseURL(
3122 IVBSAXXMLReader* iface,
3123 BSTR pBaseUrl)
3125 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3126 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3129 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3130 IVBSAXXMLReader* iface,
3131 BSTR *pSecureBaseUrl)
3133 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3135 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3136 return E_NOTIMPL;
3139 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3140 IVBSAXXMLReader* iface,
3141 BSTR secureBaseUrl)
3143 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3144 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3147 static HRESULT WINAPI saxxmlreader_parse(
3148 IVBSAXXMLReader* iface,
3149 VARIANT varInput)
3151 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3152 return internal_parse(This, varInput, TRUE);
3155 static HRESULT WINAPI saxxmlreader_parseURL(
3156 IVBSAXXMLReader* iface,
3157 BSTR url)
3159 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3160 return internal_parseURL(This, url, TRUE);
3163 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3165 saxxmlreader_QueryInterface,
3166 saxxmlreader_AddRef,
3167 saxxmlreader_Release,
3168 saxxmlreader_GetTypeInfoCount,
3169 saxxmlreader_GetTypeInfo,
3170 saxxmlreader_GetIDsOfNames,
3171 saxxmlreader_Invoke,
3172 saxxmlreader_getFeature,
3173 saxxmlreader_putFeature,
3174 saxxmlreader_getProperty,
3175 saxxmlreader_putProperty,
3176 saxxmlreader_get_entityResolver,
3177 saxxmlreader_put_entityResolver,
3178 saxxmlreader_get_contentHandler,
3179 saxxmlreader_put_contentHandler,
3180 saxxmlreader_get_dtdHandler,
3181 saxxmlreader_put_dtdHandler,
3182 saxxmlreader_get_errorHandler,
3183 saxxmlreader_put_errorHandler,
3184 saxxmlreader_get_baseURL,
3185 saxxmlreader_put_baseURL,
3186 saxxmlreader_get_secureBaseURL,
3187 saxxmlreader_put_secureBaseURL,
3188 saxxmlreader_parse,
3189 saxxmlreader_parseURL
3192 /*** ISAXXMLReader interface ***/
3193 /*** IUnknown methods ***/
3194 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3196 saxreader *This = impl_from_ISAXXMLReader( iface );
3197 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3200 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3202 saxreader *This = impl_from_ISAXXMLReader( iface );
3203 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3206 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3208 saxreader *This = impl_from_ISAXXMLReader( iface );
3209 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3212 /*** ISAXXMLReader methods ***/
3213 static HRESULT WINAPI isaxxmlreader_getFeature(
3214 ISAXXMLReader* iface,
3215 const WCHAR *feature_name,
3216 VARIANT_BOOL *value)
3218 saxreader *This = impl_from_ISAXXMLReader( iface );
3219 saxreader_feature feature;
3221 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3223 feature = get_saxreader_feature(feature_name);
3225 if (This->version < MSXML4 && feature == ExhaustiveErrors)
3226 return E_INVALIDARG;
3228 if (feature == Namespaces ||
3229 feature == NamespacePrefixes ||
3230 feature == ExhaustiveErrors)
3231 return get_feature_value(This, feature, value);
3233 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3234 return E_NOTIMPL;
3237 static HRESULT WINAPI isaxxmlreader_putFeature(
3238 ISAXXMLReader* iface,
3239 const WCHAR *feature_name,
3240 VARIANT_BOOL value)
3242 saxreader *This = impl_from_ISAXXMLReader( iface );
3243 saxreader_feature feature;
3245 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3247 feature = get_saxreader_feature(feature_name);
3249 /* accepted cases */
3250 if ((feature == ExhaustiveErrors && value == VARIANT_FALSE) ||
3251 feature == Namespaces ||
3252 feature == NamespacePrefixes)
3254 return set_feature_value(This, feature, value);
3257 if (feature == LexicalHandlerParEntities ||
3258 feature == ProhibitDTD ||
3259 feature == ExternalGeneralEntities ||
3260 feature == ExternalParameterEntities)
3262 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3263 return set_feature_value(This, feature, value);
3266 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3267 return E_NOTIMPL;
3270 static HRESULT WINAPI isaxxmlreader_getProperty(
3271 ISAXXMLReader* iface,
3272 const WCHAR *prop,
3273 VARIANT *value)
3275 saxreader *This = impl_from_ISAXXMLReader( iface );
3276 return internal_getProperty(This, prop, value, FALSE);
3279 static HRESULT WINAPI isaxxmlreader_putProperty(
3280 ISAXXMLReader* iface,
3281 const WCHAR *pProp,
3282 VARIANT value)
3284 saxreader *This = impl_from_ISAXXMLReader( iface );
3285 return internal_putProperty(This, pProp, value, FALSE);
3288 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3289 ISAXXMLReader* iface,
3290 ISAXEntityResolver **resolver)
3292 saxreader *This = impl_from_ISAXXMLReader( iface );
3293 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3296 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3297 ISAXXMLReader* iface,
3298 ISAXEntityResolver *resolver)
3300 saxreader *This = impl_from_ISAXXMLReader( iface );
3301 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3304 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3305 ISAXXMLReader* iface,
3306 ISAXContentHandler **handler)
3308 saxreader *This = impl_from_ISAXXMLReader( iface );
3309 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3312 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3313 ISAXXMLReader* iface,
3314 ISAXContentHandler *handler)
3316 saxreader *This = impl_from_ISAXXMLReader( iface );
3317 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3320 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3321 ISAXXMLReader* iface,
3322 ISAXDTDHandler **handler)
3324 saxreader *This = impl_from_ISAXXMLReader( iface );
3325 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3328 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3329 ISAXXMLReader* iface,
3330 ISAXDTDHandler *handler)
3332 saxreader *This = impl_from_ISAXXMLReader( iface );
3333 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3336 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3337 ISAXXMLReader* iface,
3338 ISAXErrorHandler **handler)
3340 saxreader *This = impl_from_ISAXXMLReader( iface );
3341 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3344 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3346 saxreader *This = impl_from_ISAXXMLReader( iface );
3347 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3350 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3351 ISAXXMLReader* iface,
3352 const WCHAR **base_url)
3354 saxreader *This = impl_from_ISAXXMLReader( iface );
3356 FIXME("(%p)->(%p) stub\n", This, base_url);
3357 return E_NOTIMPL;
3360 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3361 ISAXXMLReader* iface,
3362 const WCHAR *pBaseUrl)
3364 saxreader *This = impl_from_ISAXXMLReader( iface );
3366 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3367 return E_NOTIMPL;
3370 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3371 ISAXXMLReader* iface,
3372 const WCHAR **pSecureBaseUrl)
3374 saxreader *This = impl_from_ISAXXMLReader( iface );
3375 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3376 return E_NOTIMPL;
3379 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3380 ISAXXMLReader* iface,
3381 const WCHAR *secureBaseUrl)
3383 saxreader *This = impl_from_ISAXXMLReader( iface );
3385 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3386 return E_NOTIMPL;
3389 static HRESULT WINAPI isaxxmlreader_parse(
3390 ISAXXMLReader* iface,
3391 VARIANT varInput)
3393 saxreader *This = impl_from_ISAXXMLReader( iface );
3394 return internal_parse(This, varInput, FALSE);
3397 static HRESULT WINAPI isaxxmlreader_parseURL(
3398 ISAXXMLReader* iface,
3399 const WCHAR *url)
3401 saxreader *This = impl_from_ISAXXMLReader( iface );
3402 return internal_parseURL(This, url, FALSE);
3405 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3407 isaxxmlreader_QueryInterface,
3408 isaxxmlreader_AddRef,
3409 isaxxmlreader_Release,
3410 isaxxmlreader_getFeature,
3411 isaxxmlreader_putFeature,
3412 isaxxmlreader_getProperty,
3413 isaxxmlreader_putProperty,
3414 isaxxmlreader_getEntityResolver,
3415 isaxxmlreader_putEntityResolver,
3416 isaxxmlreader_getContentHandler,
3417 isaxxmlreader_putContentHandler,
3418 isaxxmlreader_getDTDHandler,
3419 isaxxmlreader_putDTDHandler,
3420 isaxxmlreader_getErrorHandler,
3421 isaxxmlreader_putErrorHandler,
3422 isaxxmlreader_getBaseURL,
3423 isaxxmlreader_putBaseURL,
3424 isaxxmlreader_getSecureBaseURL,
3425 isaxxmlreader_putSecureBaseURL,
3426 isaxxmlreader_parse,
3427 isaxxmlreader_parseURL
3430 static const tid_t saxreader_iface_tids[] = {
3431 IVBSAXXMLReader_tid,
3434 static dispex_static_data_t saxreader_dispex = {
3435 NULL,
3436 IVBSAXXMLReader_tid,
3437 NULL,
3438 saxreader_iface_tids
3441 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3443 saxreader *reader;
3445 TRACE("(%p)\n", ppObj);
3447 reader = heap_alloc( sizeof (*reader) );
3448 if( !reader )
3449 return E_OUTOFMEMORY;
3451 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3452 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3453 reader->ref = 1;
3454 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3455 reader->isParsing = FALSE;
3456 reader->xmldecl_version = NULL;
3457 reader->pool.pool = NULL;
3458 reader->pool.index = 0;
3459 reader->pool.len = 0;
3460 reader->features = Namespaces | NamespacePrefixes;
3461 reader->version = version;
3463 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3465 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3466 reader->sax.initialized = XML_SAX2_MAGIC;
3467 reader->sax.startDocument = libxmlStartDocument;
3468 reader->sax.endDocument = libxmlEndDocument;
3469 reader->sax.startElementNs = libxmlStartElementNS;
3470 reader->sax.endElementNs = libxmlEndElementNS;
3471 reader->sax.characters = libxmlCharacters;
3472 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3473 reader->sax.comment = libxmlComment;
3474 reader->sax.error = libxmlFatalError;
3475 reader->sax.fatalError = libxmlFatalError;
3476 reader->sax.cdataBlock = libxml_cdatablock;
3477 reader->sax.resolveEntity = libxmlresolveentity;
3479 *ppObj = &reader->IVBSAXXMLReader_iface;
3481 TRACE("returning iface %p\n", *ppObj);
3483 return S_OK;
3486 #else
3488 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3490 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3491 "libxml2 support was not present at compile time.\n");
3492 return E_NOTIMPL;
3495 #endif