urlmon: Support BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS in BindProtocol object.
[wine.git] / dlls / msxml3 / saxreader.c
blob0549bc82ebe07994bc79970e47943f6dcaf78246
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 struct saxreader_feature_pair
105 saxreader_feature feature;
106 const WCHAR *name;
109 static const struct saxreader_feature_pair saxreader_feature_map[] = {
110 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
111 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
112 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
113 { NamespacePrefixes, FeatureNamespacePrefixesW },
114 { Namespaces, FeatureNamespacesW },
115 { ProhibitDTD, FeatureProhibitDTDW }
118 static saxreader_feature get_saxreader_feature(const WCHAR *name)
120 int min, max, n, c;
122 min = 0;
123 max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
125 while (min <= max)
127 n = (min+max)/2;
129 c = strcmpW(saxreader_feature_map[n].name, name);
130 if (!c)
131 return saxreader_feature_map[n].feature;
133 if (c > 0)
134 max = n-1;
135 else
136 min = n+1;
139 return FeatureUnknown;
142 struct bstrpool
144 BSTR *pool;
145 unsigned int index;
146 unsigned int len;
149 typedef struct
151 BSTR prefix;
152 BSTR uri;
153 } ns;
155 typedef struct
157 struct list entry;
158 BSTR prefix;
159 BSTR local;
160 BSTR qname;
161 ns *ns; /* namespaces defined in this particular element */
162 int ns_count;
163 } element_entry;
165 enum saxhandler_type
167 SAXContentHandler = 0,
168 SAXDeclHandler,
169 SAXDTDHandler,
170 SAXEntityResolver,
171 SAXErrorHandler,
172 SAXLexicalHandler,
173 SAXHandler_Last
176 struct saxanyhandler_iface
178 IUnknown *handler;
179 IUnknown *vbhandler;
182 struct saxcontenthandler_iface
184 ISAXContentHandler *handler;
185 IVBSAXContentHandler *vbhandler;
188 struct saxerrorhandler_iface
190 ISAXErrorHandler *handler;
191 IVBSAXErrorHandler *vbhandler;
194 struct saxlexicalhandler_iface
196 ISAXLexicalHandler *handler;
197 IVBSAXLexicalHandler *vbhandler;
200 struct saxentityresolver_iface
202 ISAXEntityResolver *handler;
203 IVBSAXEntityResolver *vbhandler;
206 struct saxhandler_iface
208 union {
209 struct saxcontenthandler_iface content;
210 struct saxentityresolver_iface entityresolver;
211 struct saxerrorhandler_iface error;
212 struct saxlexicalhandler_iface lexical;
213 struct saxanyhandler_iface anyhandler;
214 } u;
217 typedef struct
219 DispatchEx dispex;
220 IVBSAXXMLReader IVBSAXXMLReader_iface;
221 ISAXXMLReader ISAXXMLReader_iface;
222 LONG ref;
224 struct saxhandler_iface saxhandlers[SAXHandler_Last];
225 xmlSAXHandler sax;
226 BOOL isParsing;
227 struct bstrpool pool;
228 saxreader_feature features;
229 BSTR xmldecl_version;
230 MSXML_VERSION version;
231 } saxreader;
233 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
235 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
236 IUnknown *unk = (IUnknown*)ptr;
238 if (unk)
239 IUnknown_AddRef(unk);
241 if ((vb && iface->vbhandler) || (!vb && iface->handler))
242 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
244 if (vb)
245 iface->vbhandler = unk;
246 else
247 iface->handler = unk;
249 return S_OK;
252 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
254 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
256 if (!ret) return E_POINTER;
258 if ((vb && iface->vbhandler) || (!vb && iface->handler))
260 if (vb)
261 IUnknown_AddRef(iface->vbhandler);
262 else
263 IUnknown_AddRef(iface->handler);
266 *ret = vb ? iface->vbhandler : iface->handler;
268 return S_OK;
271 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
273 return &reader->saxhandlers[SAXContentHandler].u.content;
276 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
278 return &reader->saxhandlers[SAXErrorHandler].u.error;
281 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
283 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
286 typedef struct
288 IVBSAXLocator IVBSAXLocator_iface;
289 ISAXLocator ISAXLocator_iface;
290 IVBSAXAttributes IVBSAXAttributes_iface;
291 ISAXAttributes ISAXAttributes_iface;
292 LONG ref;
293 saxreader *saxreader;
294 HRESULT ret;
295 xmlParserCtxtPtr pParserCtxt;
296 BSTR publicId;
297 BSTR systemId;
298 int line;
299 int column;
300 BOOL vbInterface;
301 struct list elements;
303 BSTR namespaceUri;
304 int attr_alloc_count;
305 int attr_count;
306 struct _attributes
308 BSTR szLocalname;
309 BSTR szURI;
310 BSTR szValue;
311 BSTR szQName;
312 } *attributes;
313 } saxlocator;
315 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
317 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
320 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
322 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
325 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
327 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
330 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
332 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
335 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
337 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
340 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
342 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
345 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
347 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
348 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
351 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
353 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
354 HRESULT hr;
356 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
358 if (locator->vbInterface)
359 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
360 else
361 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
363 return hr;
366 /* property names */
367 static const WCHAR PropertyCharsetW[] = {
368 'c','h','a','r','s','e','t',0
370 static const WCHAR PropertyXmlDeclVersionW[] = {
371 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
373 static const WCHAR PropertyDeclHandlerW[] = {
374 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
375 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
376 'd','e','c','l','a','r','a','t','i','o','n',
377 '-','h','a','n','d','l','e','r',0
379 static const WCHAR PropertyDomNodeW[] = {
380 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
381 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
382 'd','o','m','-','n','o','d','e',0
384 static const WCHAR PropertyInputSourceW[] = {
385 'i','n','p','u','t','-','s','o','u','r','c','e',0
387 static const WCHAR PropertyLexicalHandlerW[] = {
388 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
389 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
390 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
392 static const WCHAR PropertyMaxElementDepthW[] = {
393 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
395 static const WCHAR PropertyMaxXMLSizeW[] = {
396 'm','a','x','-','x','m','l','-','s','i','z','e',0
398 static const WCHAR PropertySchemaDeclHandlerW[] = {
399 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
400 'h','a','n','d','l','e','r',0
402 static const WCHAR PropertyXMLDeclEncodingW[] = {
403 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
405 static const WCHAR PropertyXMLDeclStandaloneW[] = {
406 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
408 static const WCHAR PropertyXMLDeclVersionW[] = {
409 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
412 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
414 /* handling of non-VARIANT_* values is version dependent */
415 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
416 value = VARIANT_FALSE;
417 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
418 value = VARIANT_TRUE;
420 if (value == VARIANT_TRUE)
421 reader->features |= feature;
422 else
423 reader->features &= ~feature;
425 return S_OK;
428 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
430 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
431 return S_OK;
434 static BOOL is_namespaces_enabled(const saxreader *reader)
436 return (reader->version < MSXML4) || (reader->features & Namespaces);
439 static BSTR build_qname(BSTR prefix, BSTR local)
441 if (prefix && *prefix)
443 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
444 WCHAR *ptr;
446 ptr = qname;
447 strcpyW(ptr, prefix);
448 ptr += SysStringLen(prefix);
449 *ptr++ = ':';
450 strcpyW(ptr, local);
451 return qname;
453 else
454 return SysAllocString(local);
457 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
458 const xmlChar **namespaces)
460 element_entry *ret;
461 int i;
463 ret = heap_alloc(sizeof(*ret));
464 if (!ret) return ret;
466 ret->local = bstr_from_xmlChar(local);
467 ret->prefix = bstr_from_xmlChar(prefix);
468 ret->qname = build_qname(ret->prefix, ret->local);
469 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
470 ret->ns_count = nb_ns;
472 for (i=0; i < nb_ns; i++)
474 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
475 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
478 return ret;
481 static void free_element_entry(element_entry *element)
483 int i;
485 for (i=0; i<element->ns_count;i++)
487 SysFreeString(element->ns[i].prefix);
488 SysFreeString(element->ns[i].uri);
491 SysFreeString(element->prefix);
492 SysFreeString(element->local);
493 SysFreeString(element->qname);
495 heap_free(element->ns);
496 heap_free(element);
499 static void push_element_ns(saxlocator *locator, element_entry *element)
501 list_add_head(&locator->elements, &element->entry);
504 static element_entry * pop_element_ns(saxlocator *locator)
506 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
508 if (element)
509 list_remove(&element->entry);
511 return element;
514 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
516 element_entry *element;
517 BSTR uriW;
518 int i;
520 if (!uri) return NULL;
522 uriW = bstr_from_xmlChar(uri);
524 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
526 for (i=0; i < element->ns_count; i++)
527 if (!strcmpW(uriW, element->ns[i].uri))
529 SysFreeString(uriW);
530 return element->ns[i].uri;
534 SysFreeString(uriW);
535 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
536 return NULL;
539 /* used to localize version dependent error check behaviour */
540 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
542 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
545 /* index value -1 means it tries to loop for a first time */
546 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
548 if (This->saxreader->version >= MSXML4)
550 if (*i == -1) *i = 0; else ++*i;
551 return *i < element->ns_count;
553 else
555 if (*i == -1) *i = element->ns_count-1; else --*i;
556 return *i >= 0;
560 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
562 if (!pool->pool)
564 pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool));
565 if (!pool->pool)
566 return FALSE;
568 pool->index = 0;
569 pool->len = 16;
571 else if (pool->index == pool->len)
573 BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc));
575 if (!realloc)
576 return FALSE;
578 pool->pool = realloc;
579 pool->len *= 2;
582 pool->pool[pool->index++] = pool_entry;
583 return TRUE;
586 static void free_bstr_pool(struct bstrpool *pool)
588 unsigned int i;
590 for (i = 0; i < pool->index; i++)
591 SysFreeString(pool->pool[i]);
593 HeapFree(GetProcessHeap(), 0, pool->pool);
595 pool->pool = NULL;
596 pool->index = pool->len = 0;
599 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
601 DWORD dLen;
602 BSTR bstr;
604 if (!buf)
605 return NULL;
607 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
608 if(len != -1) dLen++;
609 bstr = SysAllocStringLen(NULL, dLen-1);
610 if (!bstr)
611 return NULL;
612 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
613 if(len != -1) bstr[dLen-1] = '\0';
615 return bstr;
618 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
620 xmlChar *qname;
621 BSTR bstr;
623 if(!name) return NULL;
625 if(!prefix || !*prefix)
626 return bstr_from_xmlChar(name);
628 qname = xmlBuildQName(name, prefix, NULL, 0);
629 bstr = bstr_from_xmlChar(qname);
630 xmlFree(qname);
632 return bstr;
635 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
637 BSTR pool_entry = bstr_from_xmlChar(buf);
639 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
641 SysFreeString(pool_entry);
642 return NULL;
645 return pool_entry;
648 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
650 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
652 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
654 SysFreeString(pool_entry);
655 return NULL;
658 return pool_entry;
661 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
663 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
664 xmlStopParser(This->pParserCtxt);
665 This->ret = hr;
667 if (saxreader_has_handler(This, SAXErrorHandler))
669 WCHAR msg[1024];
670 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
671 NULL, hr, 0, msg, sizeof(msg)/sizeof(msg[0]), NULL))
673 FIXME("MSXML errors not yet supported.\n");
674 msg[0] = '\0';
677 if(This->vbInterface)
679 BSTR bstrMsg = SysAllocString(msg);
680 IVBSAXErrorHandler_fatalError(handler->vbhandler,
681 &This->IVBSAXLocator_iface, &bstrMsg, hr);
682 SysFreeString(bstrMsg);
684 else
685 ISAXErrorHandler_fatalError(handler->handler,
686 &This->ISAXLocator_iface, msg, hr);
690 static void update_position(saxlocator *This, BOOL fix_column)
692 const xmlChar *p = This->pParserCtxt->input->cur-1;
693 const xmlChar *baseP = This->pParserCtxt->input->base;
695 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
696 if(fix_column)
698 This->column = 1;
699 for(;p>=baseP && *p!='\n' && *p!='\r'; p--)
700 This->column++;
702 else
704 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
708 /*** IVBSAXAttributes interface ***/
709 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
710 IVBSAXAttributes* iface,
711 REFIID riid,
712 void **ppvObject)
714 saxlocator *This = impl_from_IVBSAXAttributes(iface);
715 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
716 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
719 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
721 saxlocator *This = impl_from_IVBSAXAttributes(iface);
722 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
725 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
727 saxlocator *This = impl_from_IVBSAXAttributes(iface);
728 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
731 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
733 saxlocator *This = impl_from_IVBSAXAttributes( iface );
735 TRACE("(%p)->(%p)\n", This, pctinfo);
737 *pctinfo = 1;
739 return S_OK;
742 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
743 IVBSAXAttributes *iface,
744 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
746 saxlocator *This = impl_from_IVBSAXAttributes( iface );
748 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
750 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
753 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
754 IVBSAXAttributes *iface,
755 REFIID riid,
756 LPOLESTR* rgszNames,
757 UINT cNames,
758 LCID lcid,
759 DISPID* rgDispId)
761 saxlocator *This = impl_from_IVBSAXAttributes( iface );
762 ITypeInfo *typeinfo;
763 HRESULT hr;
765 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
766 lcid, rgDispId);
768 if(!rgszNames || cNames == 0 || !rgDispId)
769 return E_INVALIDARG;
771 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
772 if(SUCCEEDED(hr))
774 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
775 ITypeInfo_Release(typeinfo);
778 return hr;
781 static HRESULT WINAPI ivbsaxattributes_Invoke(
782 IVBSAXAttributes *iface,
783 DISPID dispIdMember,
784 REFIID riid,
785 LCID lcid,
786 WORD wFlags,
787 DISPPARAMS* pDispParams,
788 VARIANT* pVarResult,
789 EXCEPINFO* pExcepInfo,
790 UINT* puArgErr)
792 saxlocator *This = impl_from_IVBSAXAttributes( iface );
793 ITypeInfo *typeinfo;
794 HRESULT hr;
796 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
797 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
799 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
800 if(SUCCEEDED(hr))
802 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
803 pDispParams, pVarResult, pExcepInfo, puArgErr);
804 ITypeInfo_Release(typeinfo);
807 return hr;
810 /*** IVBSAXAttributes methods ***/
811 static HRESULT WINAPI ivbsaxattributes_get_length(
812 IVBSAXAttributes* iface,
813 int *nLength)
815 saxlocator *This = impl_from_IVBSAXAttributes( iface );
816 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
819 static HRESULT WINAPI ivbsaxattributes_getURI(
820 IVBSAXAttributes* iface,
821 int nIndex,
822 BSTR *uri)
824 saxlocator *This = impl_from_IVBSAXAttributes( iface );
825 const WCHAR *uriW;
826 HRESULT hr;
827 int len;
829 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
831 if (!uri)
832 return E_POINTER;
834 *uri = NULL;
835 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
836 if (FAILED(hr))
837 return hr;
839 return return_bstrn(uriW, len, uri);
842 static HRESULT WINAPI ivbsaxattributes_getLocalName(
843 IVBSAXAttributes* iface,
844 int nIndex,
845 BSTR *name)
847 saxlocator *This = impl_from_IVBSAXAttributes( iface );
848 const WCHAR *nameW;
849 HRESULT hr;
850 int len;
852 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
854 if (!name)
855 return E_POINTER;
857 *name = NULL;
858 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
859 if (FAILED(hr))
860 return hr;
862 return return_bstrn(nameW, len, name);
865 static HRESULT WINAPI ivbsaxattributes_getQName(
866 IVBSAXAttributes* iface,
867 int nIndex,
868 BSTR *QName)
870 saxlocator *This = impl_from_IVBSAXAttributes( iface );
871 const WCHAR *nameW;
872 HRESULT hr;
873 int len;
875 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
877 if (!QName)
878 return E_POINTER;
880 *QName = NULL;
881 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
882 if (FAILED(hr))
883 return hr;
885 return return_bstrn(nameW, len, QName);
888 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
889 IVBSAXAttributes* iface,
890 BSTR uri,
891 BSTR localName,
892 int *index)
894 saxlocator *This = impl_from_IVBSAXAttributes( iface );
895 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
896 localName, SysStringLen(localName), index);
899 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
900 IVBSAXAttributes* iface,
901 BSTR QName,
902 int *index)
904 saxlocator *This = impl_from_IVBSAXAttributes( iface );
905 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
906 SysStringLen(QName), index);
909 static HRESULT WINAPI ivbsaxattributes_getType(
910 IVBSAXAttributes* iface,
911 int nIndex,
912 BSTR *type)
914 saxlocator *This = impl_from_IVBSAXAttributes( iface );
915 const WCHAR *typeW;
916 HRESULT hr;
917 int len;
919 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
921 if (!type)
922 return E_POINTER;
924 *type = NULL;
925 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
926 if (FAILED(hr))
927 return hr;
929 return return_bstrn(typeW, len, type);
932 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
933 IVBSAXAttributes* iface,
934 BSTR uri,
935 BSTR localName,
936 BSTR *type)
938 saxlocator *This = impl_from_IVBSAXAttributes( iface );
939 const WCHAR *typeW;
940 HRESULT hr;
941 int len;
943 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
945 if (!type)
946 return E_POINTER;
948 *type = NULL;
949 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
950 localName, SysStringLen(localName), &typeW, &len);
951 if (FAILED(hr))
952 return hr;
954 return return_bstrn(typeW, len, type);
957 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
958 IVBSAXAttributes* iface,
959 BSTR QName,
960 BSTR *type)
962 saxlocator *This = impl_from_IVBSAXAttributes( iface );
963 const WCHAR *typeW;
964 HRESULT hr;
965 int len;
967 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
969 if (!type)
970 return E_POINTER;
972 *type = NULL;
973 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
974 &typeW, &len);
975 if (FAILED(hr))
976 return hr;
978 return return_bstrn(typeW, len, type);
981 static HRESULT WINAPI ivbsaxattributes_getValue(
982 IVBSAXAttributes* iface,
983 int nIndex,
984 BSTR *value)
986 saxlocator *This = impl_from_IVBSAXAttributes( iface );
987 const WCHAR *valueW;
988 HRESULT hr;
989 int len;
991 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
993 if (!value)
994 return E_POINTER;
996 *value = NULL;
997 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
998 if (FAILED(hr))
999 return hr;
1001 return return_bstrn(valueW, len, value);
1004 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1005 IVBSAXAttributes* iface,
1006 BSTR uri,
1007 BSTR localName,
1008 BSTR *value)
1010 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1011 const WCHAR *valueW;
1012 HRESULT hr;
1013 int len;
1015 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1017 if (!value)
1018 return E_POINTER;
1020 *value = NULL;
1021 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1022 localName, SysStringLen(localName), &valueW, &len);
1023 if (FAILED(hr))
1024 return hr;
1026 return return_bstrn(valueW, len, value);
1029 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1030 IVBSAXAttributes* iface,
1031 BSTR QName,
1032 BSTR *value)
1034 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1035 const WCHAR *valueW;
1036 HRESULT hr;
1037 int len;
1039 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1041 if (!value)
1042 return E_POINTER;
1044 *value = NULL;
1045 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1046 SysStringLen(QName), &valueW, &len);
1047 if (FAILED(hr))
1048 return hr;
1050 return return_bstrn(valueW, len, value);
1053 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1055 ivbsaxattributes_QueryInterface,
1056 ivbsaxattributes_AddRef,
1057 ivbsaxattributes_Release,
1058 ivbsaxattributes_GetTypeInfoCount,
1059 ivbsaxattributes_GetTypeInfo,
1060 ivbsaxattributes_GetIDsOfNames,
1061 ivbsaxattributes_Invoke,
1062 ivbsaxattributes_get_length,
1063 ivbsaxattributes_getURI,
1064 ivbsaxattributes_getLocalName,
1065 ivbsaxattributes_getQName,
1066 ivbsaxattributes_getIndexFromName,
1067 ivbsaxattributes_getIndexFromQName,
1068 ivbsaxattributes_getType,
1069 ivbsaxattributes_getTypeFromName,
1070 ivbsaxattributes_getTypeFromQName,
1071 ivbsaxattributes_getValue,
1072 ivbsaxattributes_getValueFromName,
1073 ivbsaxattributes_getValueFromQName
1076 /*** ISAXAttributes interface ***/
1077 /*** IUnknown methods ***/
1078 static HRESULT WINAPI isaxattributes_QueryInterface(
1079 ISAXAttributes* iface,
1080 REFIID riid,
1081 void **ppvObject)
1083 saxlocator *This = impl_from_ISAXAttributes(iface);
1084 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1085 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1088 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1090 saxlocator *This = impl_from_ISAXAttributes(iface);
1091 TRACE("%p\n", This);
1092 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1095 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1097 saxlocator *This = impl_from_ISAXAttributes(iface);
1099 TRACE("%p\n", This);
1100 return ISAXLocator_Release(&This->ISAXLocator_iface);
1103 /*** ISAXAttributes methods ***/
1104 static HRESULT WINAPI isaxattributes_getLength(
1105 ISAXAttributes* iface,
1106 int *length)
1108 saxlocator *This = impl_from_ISAXAttributes( iface );
1110 *length = This->attr_count;
1111 TRACE("Length set to %d\n", *length);
1112 return S_OK;
1115 static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
1117 return index < locator->attr_count && index >= 0;
1120 static HRESULT WINAPI isaxattributes_getURI(
1121 ISAXAttributes* iface,
1122 int index,
1123 const WCHAR **url,
1124 int *size)
1126 saxlocator *This = impl_from_ISAXAttributes( iface );
1127 TRACE("(%p)->(%d)\n", This, index);
1129 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1130 if(!url || !size) return E_POINTER;
1132 *size = SysStringLen(This->attributes[index].szURI);
1133 *url = This->attributes[index].szURI;
1135 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1137 return S_OK;
1140 static HRESULT WINAPI isaxattributes_getLocalName(
1141 ISAXAttributes* iface,
1142 int index,
1143 const WCHAR **pLocalName,
1144 int *pLocalNameLength)
1146 saxlocator *This = impl_from_ISAXAttributes( iface );
1147 TRACE("(%p)->(%d)\n", This, index);
1149 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1150 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1152 *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
1153 *pLocalName = This->attributes[index].szLocalname;
1155 return S_OK;
1158 static HRESULT WINAPI isaxattributes_getQName(
1159 ISAXAttributes* iface,
1160 int index,
1161 const WCHAR **pQName,
1162 int *pQNameLength)
1164 saxlocator *This = impl_from_ISAXAttributes( iface );
1165 TRACE("(%p)->(%d)\n", This, index);
1167 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1168 if(!pQName || !pQNameLength) return E_POINTER;
1170 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1171 *pQName = This->attributes[index].szQName;
1173 return S_OK;
1176 static HRESULT WINAPI isaxattributes_getName(
1177 ISAXAttributes* iface,
1178 int index,
1179 const WCHAR **uri,
1180 int *pUriLength,
1181 const WCHAR **localName,
1182 int *pLocalNameSize,
1183 const WCHAR **QName,
1184 int *pQNameLength)
1186 saxlocator *This = impl_from_ISAXAttributes( iface );
1187 TRACE("(%p)->(%d)\n", This, index);
1189 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1190 if(!uri || !pUriLength || !localName || !pLocalNameSize
1191 || !QName || !pQNameLength) return E_POINTER;
1193 *pUriLength = SysStringLen(This->attributes[index].szURI);
1194 *uri = This->attributes[index].szURI;
1195 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1196 *localName = This->attributes[index].szLocalname;
1197 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1198 *QName = This->attributes[index].szQName;
1200 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1202 return S_OK;
1205 static HRESULT WINAPI isaxattributes_getIndexFromName(
1206 ISAXAttributes* iface,
1207 const WCHAR *pUri,
1208 int cUriLength,
1209 const WCHAR *pLocalName,
1210 int cocalNameLength,
1211 int *index)
1213 saxlocator *This = impl_from_ISAXAttributes( iface );
1214 int i;
1215 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1216 debugstr_w(pLocalName), cocalNameLength);
1218 if(!pUri || !pLocalName || !index) return E_POINTER;
1220 for(i=0; i<This->attr_count; i++)
1222 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1223 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1224 continue;
1225 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1226 sizeof(WCHAR)*cUriLength))
1227 continue;
1228 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1229 sizeof(WCHAR)*cocalNameLength))
1230 continue;
1232 *index = i;
1233 return S_OK;
1236 return E_INVALIDARG;
1239 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1240 ISAXAttributes* iface,
1241 const WCHAR *pQName,
1242 int nQNameLength,
1243 int *index)
1245 saxlocator *This = impl_from_ISAXAttributes( iface );
1246 int i;
1247 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1249 if(!pQName || !index) return E_POINTER;
1250 if(!nQNameLength) return E_INVALIDARG;
1252 for(i=0; i<This->attr_count; i++)
1254 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1255 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1257 *index = i;
1258 return S_OK;
1261 return E_INVALIDARG;
1264 static HRESULT WINAPI isaxattributes_getType(
1265 ISAXAttributes* iface,
1266 int nIndex,
1267 const WCHAR **pType,
1268 int *pTypeLength)
1270 saxlocator *This = impl_from_ISAXAttributes( iface );
1272 FIXME("(%p)->(%d) stub\n", This, nIndex);
1273 return E_NOTIMPL;
1276 static HRESULT WINAPI isaxattributes_getTypeFromName(
1277 ISAXAttributes* iface,
1278 const WCHAR *pUri,
1279 int nUri,
1280 const WCHAR *pLocalName,
1281 int nLocalName,
1282 const WCHAR **pType,
1283 int *nType)
1285 saxlocator *This = impl_from_ISAXAttributes( iface );
1287 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1288 debugstr_w(pLocalName), nLocalName);
1289 return E_NOTIMPL;
1292 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1293 ISAXAttributes* iface,
1294 const WCHAR *pQName,
1295 int nQName,
1296 const WCHAR **pType,
1297 int *nType)
1299 saxlocator *This = impl_from_ISAXAttributes( iface );
1301 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1302 return E_NOTIMPL;
1305 static HRESULT WINAPI isaxattributes_getValue(
1306 ISAXAttributes* iface,
1307 int index,
1308 const WCHAR **value,
1309 int *nValue)
1311 saxlocator *This = impl_from_ISAXAttributes( iface );
1312 TRACE("(%p)->(%d)\n", This, index);
1314 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1315 if(!value || !nValue) return E_POINTER;
1317 *nValue = SysStringLen(This->attributes[index].szValue);
1318 *value = This->attributes[index].szValue;
1320 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1322 return S_OK;
1325 static HRESULT WINAPI isaxattributes_getValueFromName(
1326 ISAXAttributes* iface,
1327 const WCHAR *pUri,
1328 int nUri,
1329 const WCHAR *pLocalName,
1330 int nLocalName,
1331 const WCHAR **pValue,
1332 int *nValue)
1334 HRESULT hr;
1335 int index;
1336 saxlocator *This = impl_from_ISAXAttributes( iface );
1337 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1338 debugstr_w(pLocalName), nLocalName);
1340 hr = ISAXAttributes_getIndexFromName(iface,
1341 pUri, nUri, pLocalName, nLocalName, &index);
1342 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1344 return hr;
1347 static HRESULT WINAPI isaxattributes_getValueFromQName(
1348 ISAXAttributes* iface,
1349 const WCHAR *pQName,
1350 int nQName,
1351 const WCHAR **pValue,
1352 int *nValue)
1354 HRESULT hr;
1355 int index;
1356 saxlocator *This = impl_from_ISAXAttributes( iface );
1357 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1359 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1360 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1362 return hr;
1365 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1367 isaxattributes_QueryInterface,
1368 isaxattributes_AddRef,
1369 isaxattributes_Release,
1370 isaxattributes_getLength,
1371 isaxattributes_getURI,
1372 isaxattributes_getLocalName,
1373 isaxattributes_getQName,
1374 isaxattributes_getName,
1375 isaxattributes_getIndexFromName,
1376 isaxattributes_getIndexFromQName,
1377 isaxattributes_getType,
1378 isaxattributes_getTypeFromName,
1379 isaxattributes_getTypeFromQName,
1380 isaxattributes_getValue,
1381 isaxattributes_getValueFromName,
1382 isaxattributes_getValueFromQName
1385 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1386 so when document has escaped value with '&amp;' it's parsed to '&' and then
1387 escaped to '&#38;'. This function takes care of ampersands only. */
1388 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1390 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1391 WCHAR *dest, *ptrW, *str;
1392 DWORD str_len;
1393 BSTR bstr;
1395 if (!buf)
1396 return NULL;
1398 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1399 if (len != -1) str_len++;
1401 str = heap_alloc(str_len*sizeof(WCHAR));
1402 if (!str) return NULL;
1404 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1405 if (len != -1) str[str_len-1] = 0;
1407 ptrW = str;
1408 while ((dest = strstrW(ptrW, ampescW)))
1410 WCHAR *src;
1412 /* leave first '&' from a reference as a value */
1413 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1414 dest++;
1416 /* move together with null terminator */
1417 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1419 ptrW++;
1422 bstr = SysAllocString(str);
1423 heap_free(str);
1425 return bstr;
1428 static void free_attribute_values(saxlocator *locator)
1430 int i;
1432 for (i = 0; i < locator->attr_count; i++)
1434 SysFreeString(locator->attributes[i].szLocalname);
1435 locator->attributes[i].szLocalname = NULL;
1437 SysFreeString(locator->attributes[i].szValue);
1438 locator->attributes[i].szValue = NULL;
1440 SysFreeString(locator->attributes[i].szQName);
1441 locator->attributes[i].szQName = NULL;
1445 static HRESULT SAXAttributes_populate(saxlocator *locator,
1446 int nb_namespaces, const xmlChar **xmlNamespaces,
1447 int nb_attributes, const xmlChar **xmlAttributes)
1449 static const xmlChar xmlns[] = "xmlns";
1450 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1452 struct _attributes *attrs;
1453 int i;
1455 /* skip namespace definitions */
1456 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1457 nb_namespaces = 0;
1459 locator->attr_count = nb_namespaces + nb_attributes;
1460 if(locator->attr_count > locator->attr_alloc_count)
1462 int new_size = locator->attr_count * 2;
1463 attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1464 if(!attrs)
1466 free_attribute_values(locator);
1467 locator->attr_count = 0;
1468 return E_OUTOFMEMORY;
1470 locator->attributes = attrs;
1471 locator->attr_alloc_count = new_size;
1473 else
1475 attrs = locator->attributes;
1478 for (i = 0; i < nb_namespaces; i++)
1480 SysFreeString(attrs[nb_attributes+i].szLocalname);
1481 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1483 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1485 SysFreeString(attrs[nb_attributes+i].szValue);
1486 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1488 SysFreeString(attrs[nb_attributes+i].szQName);
1489 if(!xmlNamespaces[2*i])
1490 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1491 else
1492 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1495 for (i = 0; i < nb_attributes; i++)
1497 static const xmlChar xmlA[] = "xml";
1499 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1500 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1501 else
1502 /* that's an important feature to keep same uri pointer for every reported attribute */
1503 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1505 SysFreeString(attrs[i].szLocalname);
1506 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1508 SysFreeString(attrs[i].szValue);
1509 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1511 SysFreeString(attrs[i].szQName);
1512 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1515 return S_OK;
1518 /*** LibXML callbacks ***/
1519 static void libxmlStartDocument(void *ctx)
1521 saxlocator *This = ctx;
1522 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1523 HRESULT hr;
1525 if (This->saxreader->version >= MSXML4)
1527 const xmlChar *p = This->pParserCtxt->input->cur-1;
1528 update_position(This, FALSE);
1529 while(p>This->pParserCtxt->input->base && *p!='>')
1531 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1532 This->line--;
1533 p--;
1535 This->column = 0;
1536 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1537 This->column++;
1540 /* store version value, declaration has to contain version attribute */
1541 if (This->pParserCtxt->standalone != -1)
1543 SysFreeString(This->saxreader->xmldecl_version);
1544 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1547 if (saxreader_has_handler(This, SAXContentHandler))
1549 if(This->vbInterface)
1550 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1551 else
1552 hr = ISAXContentHandler_startDocument(handler->handler);
1554 if (sax_callback_failed(This, hr))
1555 format_error_message_from_id(This, hr);
1559 static void libxmlEndDocument(void *ctx)
1561 saxlocator *This = ctx;
1562 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1563 HRESULT hr;
1565 if (This->saxreader->version >= MSXML4) {
1566 update_position(This, FALSE);
1567 if(This->column > 1)
1568 This->line++;
1569 This->column = 0;
1570 } else {
1571 This->column = 0;
1572 This->line = 0;
1575 if(This->ret != S_OK) return;
1577 if (saxreader_has_handler(This, SAXContentHandler))
1579 if(This->vbInterface)
1580 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1581 else
1582 hr = ISAXContentHandler_endDocument(handler->handler);
1584 if (sax_callback_failed(This, hr))
1585 format_error_message_from_id(This, hr);
1589 static void libxmlStartElementNS(
1590 void *ctx,
1591 const xmlChar *localname,
1592 const xmlChar *prefix,
1593 const xmlChar *URI,
1594 int nb_namespaces,
1595 const xmlChar **namespaces,
1596 int nb_attributes,
1597 int nb_defaulted,
1598 const xmlChar **attributes)
1600 saxlocator *This = ctx;
1601 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1602 element_entry *element;
1603 HRESULT hr = S_OK;
1604 BSTR uri;
1606 update_position(This, TRUE);
1607 if(*(This->pParserCtxt->input->cur) == '/')
1608 This->column++;
1609 if(This->saxreader->version < MSXML4)
1610 This->column++;
1612 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1613 push_element_ns(This, element);
1615 if (is_namespaces_enabled(This->saxreader))
1617 int i;
1619 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1621 if (This->vbInterface)
1622 hr = IVBSAXContentHandler_startPrefixMapping(
1623 handler->vbhandler,
1624 &element->ns[i].prefix,
1625 &element->ns[i].uri);
1626 else
1627 hr = ISAXContentHandler_startPrefixMapping(
1628 handler->handler,
1629 element->ns[i].prefix,
1630 SysStringLen(element->ns[i].prefix),
1631 element->ns[i].uri,
1632 SysStringLen(element->ns[i].uri));
1634 if (sax_callback_failed(This, hr))
1636 format_error_message_from_id(This, hr);
1637 return;
1642 uri = find_element_uri(This, URI);
1643 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1644 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1646 BSTR local;
1648 if (is_namespaces_enabled(This->saxreader))
1649 local = element->local;
1650 else
1651 uri = local = NULL;
1653 if (This->vbInterface)
1654 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1655 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1656 else
1657 hr = ISAXContentHandler_startElement(handler->handler,
1658 uri, SysStringLen(uri),
1659 local, SysStringLen(local),
1660 element->qname, SysStringLen(element->qname),
1661 &This->ISAXAttributes_iface);
1663 if (sax_callback_failed(This, hr))
1664 format_error_message_from_id(This, hr);
1668 static void libxmlEndElementNS(
1669 void *ctx,
1670 const xmlChar *localname,
1671 const xmlChar *prefix,
1672 const xmlChar *URI)
1674 saxlocator *This = ctx;
1675 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1676 element_entry *element;
1677 const xmlChar *p;
1678 BSTR uri, local;
1679 HRESULT hr;
1681 update_position(This, FALSE);
1682 p = This->pParserCtxt->input->cur;
1684 if (This->saxreader->version >= MSXML4)
1686 p--;
1687 while(p>This->pParserCtxt->input->base && *p!='>')
1689 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1690 This->line--;
1691 p--;
1694 else if(*(p-1)!='>' || *(p-2)!='/')
1696 p--;
1697 while(p-2>=This->pParserCtxt->input->base
1698 && *(p-2)!='<' && *(p-1)!='/')
1700 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1701 This->line--;
1702 p--;
1705 This->column = 0;
1706 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1707 This->column++;
1709 uri = find_element_uri(This, URI);
1710 element = pop_element_ns(This);
1712 if (!saxreader_has_handler(This, SAXContentHandler))
1714 free_attribute_values(This);
1715 This->attr_count = 0;
1716 free_element_entry(element);
1717 return;
1720 if (is_namespaces_enabled(This->saxreader))
1721 local = element->local;
1722 else
1723 uri = local = NULL;
1725 if (This->vbInterface)
1726 hr = IVBSAXContentHandler_endElement(
1727 handler->vbhandler,
1728 &uri, &local, &element->qname);
1729 else
1730 hr = ISAXContentHandler_endElement(
1731 handler->handler,
1732 uri, SysStringLen(uri),
1733 local, SysStringLen(local),
1734 element->qname, SysStringLen(element->qname));
1736 free_attribute_values(This);
1737 This->attr_count = 0;
1739 if (sax_callback_failed(This, hr))
1741 format_error_message_from_id(This, hr);
1742 free_element_entry(element);
1743 return;
1746 if (is_namespaces_enabled(This->saxreader))
1748 int i = -1;
1749 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1751 if (This->vbInterface)
1752 hr = IVBSAXContentHandler_endPrefixMapping(
1753 handler->vbhandler, &element->ns[i].prefix);
1754 else
1755 hr = ISAXContentHandler_endPrefixMapping(
1756 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1758 if (sax_callback_failed(This, hr)) break;
1761 if (sax_callback_failed(This, hr))
1762 format_error_message_from_id(This, hr);
1765 free_element_entry(element);
1768 static void libxmlCharacters(
1769 void *ctx,
1770 const xmlChar *ch,
1771 int len)
1773 saxlocator *This = ctx;
1774 BSTR Chars;
1775 HRESULT hr;
1776 xmlChar *cur, *end;
1777 BOOL lastEvent = FALSE;
1779 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1781 update_position(This, FALSE);
1782 cur = (xmlChar*)This->pParserCtxt->input->cur;
1783 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1785 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1786 This->line--;
1787 cur--;
1789 This->column = 1;
1790 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1791 This->column++;
1793 cur = (xmlChar*)ch;
1794 if(*(ch-1)=='\r') cur--;
1795 end = cur;
1797 while(1)
1799 while(end-ch<len && *end!='\r') end++;
1800 if(end-ch==len)
1802 lastEvent = TRUE;
1804 else
1806 *end = '\n';
1807 end++;
1810 if (This->saxreader->version >= MSXML4)
1812 xmlChar *p;
1814 for(p=cur; p!=end; p++)
1816 if(*p=='\n')
1818 This->line++;
1819 This->column = 1;
1821 else
1823 This->column++;
1827 if(!lastEvent)
1828 This->column = 0;
1831 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1832 hr = saxreader_saxcharacters(This, Chars);
1834 if (sax_callback_failed(This, hr))
1836 format_error_message_from_id(This, hr);
1837 return;
1840 if (This->saxreader->version < MSXML4)
1841 This->column += end-cur;
1843 if(lastEvent)
1844 break;
1846 *(end-1) = '\r';
1847 if(*end == '\n')
1849 end++;
1850 This->column++;
1852 cur = end;
1854 if(end-ch == len) break;
1858 static void libxmlSetDocumentLocator(
1859 void *ctx,
1860 xmlSAXLocatorPtr loc)
1862 saxlocator *This = ctx;
1863 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1864 HRESULT hr = S_OK;
1866 if (saxreader_has_handler(This, SAXContentHandler))
1868 if(This->vbInterface)
1869 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1870 &This->IVBSAXLocator_iface);
1871 else
1872 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1875 if(FAILED(hr))
1876 format_error_message_from_id(This, hr);
1879 static void libxmlComment(void *ctx, const xmlChar *value)
1881 saxlocator *This = ctx;
1882 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1883 BSTR bValue;
1884 HRESULT hr;
1885 const xmlChar *p = This->pParserCtxt->input->cur;
1887 update_position(This, FALSE);
1888 while(p-4>=This->pParserCtxt->input->base
1889 && memcmp(p-4, "<!--", sizeof(char[4])))
1891 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1892 This->line--;
1893 p--;
1896 This->column = 0;
1897 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1898 This->column++;
1900 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1902 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1904 if (This->vbInterface)
1905 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1906 else
1907 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1909 if(FAILED(hr))
1910 format_error_message_from_id(This, hr);
1913 static void libxmlFatalError(void *ctx, const char *msg, ...)
1915 saxlocator *This = ctx;
1916 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1917 char message[1024];
1918 WCHAR *error;
1919 DWORD len;
1920 va_list args;
1922 if(This->ret != S_OK) {
1923 xmlStopParser(This->pParserCtxt);
1924 return;
1927 va_start(args, msg);
1928 vsprintf(message, msg, args);
1929 va_end(args);
1931 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1932 error = heap_alloc(sizeof(WCHAR)*len);
1933 if(error)
1935 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1936 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1939 if (!saxreader_has_handler(This, SAXErrorHandler))
1941 xmlStopParser(This->pParserCtxt);
1942 This->ret = E_FAIL;
1943 heap_free(error);
1944 return;
1947 FIXME("Error handling is not compatible.\n");
1949 if(This->vbInterface)
1951 BSTR bstrError = SysAllocString(error);
1952 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1953 &bstrError, E_FAIL);
1954 SysFreeString(bstrError);
1956 else
1957 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1959 heap_free(error);
1961 xmlStopParser(This->pParserCtxt);
1962 This->ret = E_FAIL;
1965 /* The only reason this helper exists is that CDATA section are reported by chunks,
1966 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1968 This helper should be called for substring with trailing newlines.
1970 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1972 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1973 WCHAR *ptr;
1975 ptr = bstr + len - 1;
1976 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1977 ptr--;
1979 while (*++ptr)
1981 /* replace returns as:
1983 - "\r<char>" -> "\n<char>"
1984 - "\r\r" -> "\r"
1985 - "\r\n" -> "\n"
1987 if (*ptr == '\r')
1989 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1991 /* shift tail */
1992 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1994 else
1995 *ptr = '\n';
1999 ret = SysAllocStringLen(bstr, len);
2000 SysFreeString(bstr);
2001 return ret;
2004 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2006 const xmlChar *start, *end;
2007 saxlocator *locator = ctx;
2008 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2009 HRESULT hr = S_OK;
2010 BSTR chars;
2011 int i;
2013 update_position(locator, FALSE);
2014 if (saxreader_has_handler(locator, SAXLexicalHandler))
2016 if (locator->vbInterface)
2017 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2018 else
2019 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2022 if(FAILED(hr))
2024 format_error_message_from_id(locator, hr);
2025 return;
2028 start = value;
2029 end = NULL;
2030 i = 0;
2032 while (i < len)
2034 /* scan for newlines */
2035 if (value[i] == '\r' || value[i] == '\n')
2037 /* skip newlines/linefeeds */
2038 while (i < len)
2040 if (value[i] != '\r' && value[i] != '\n') break;
2041 i++;
2043 end = &value[i];
2045 /* report */
2046 chars = saxreader_get_cdata_chunk(start, end-start);
2047 TRACE("(chunk %s)\n", debugstr_w(chars));
2048 hr = saxreader_saxcharacters(locator, chars);
2049 SysFreeString(chars);
2051 start = &value[i];
2052 end = NULL;
2054 i++;
2055 locator->column++;
2058 /* no newline chars (or last chunk) report as a whole */
2059 if (!end && start == value)
2061 /* report */
2062 chars = bstr_from_xmlCharN(start, len-(start-value));
2063 TRACE("(%s)\n", debugstr_w(chars));
2064 hr = saxreader_saxcharacters(locator, chars);
2065 SysFreeString(chars);
2068 if (saxreader_has_handler(locator, SAXLexicalHandler))
2070 if (locator->vbInterface)
2071 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2072 else
2073 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2076 if(FAILED(hr))
2077 format_error_message_from_id(locator, hr);
2080 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2082 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2083 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2086 /*** IVBSAXLocator interface ***/
2087 /*** IUnknown methods ***/
2088 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2090 saxlocator *This = impl_from_IVBSAXLocator( iface );
2092 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2094 *ppvObject = NULL;
2096 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2097 IsEqualGUID( riid, &IID_IDispatch) ||
2098 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2100 *ppvObject = iface;
2102 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2104 *ppvObject = &This->IVBSAXAttributes_iface;
2106 else
2108 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2109 return E_NOINTERFACE;
2112 IVBSAXLocator_AddRef( iface );
2114 return S_OK;
2117 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2119 saxlocator *This = impl_from_IVBSAXLocator( iface );
2120 TRACE("%p\n", This );
2121 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2124 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2126 saxlocator *This = impl_from_IVBSAXLocator( iface );
2127 return ISAXLocator_Release(&This->ISAXLocator_iface);
2130 /*** IDispatch methods ***/
2131 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2133 saxlocator *This = impl_from_IVBSAXLocator( iface );
2135 TRACE("(%p)->(%p)\n", This, pctinfo);
2137 *pctinfo = 1;
2139 return S_OK;
2142 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2143 IVBSAXLocator *iface,
2144 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2146 saxlocator *This = impl_from_IVBSAXLocator( iface );
2148 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2150 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2153 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2154 IVBSAXLocator *iface,
2155 REFIID riid,
2156 LPOLESTR* rgszNames,
2157 UINT cNames,
2158 LCID lcid,
2159 DISPID* rgDispId)
2161 saxlocator *This = impl_from_IVBSAXLocator( iface );
2162 ITypeInfo *typeinfo;
2163 HRESULT hr;
2165 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2166 lcid, rgDispId);
2168 if(!rgszNames || cNames == 0 || !rgDispId)
2169 return E_INVALIDARG;
2171 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2172 if(SUCCEEDED(hr))
2174 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2175 ITypeInfo_Release(typeinfo);
2178 return hr;
2181 static HRESULT WINAPI ivbsaxlocator_Invoke(
2182 IVBSAXLocator *iface,
2183 DISPID dispIdMember,
2184 REFIID riid,
2185 LCID lcid,
2186 WORD wFlags,
2187 DISPPARAMS* pDispParams,
2188 VARIANT* pVarResult,
2189 EXCEPINFO* pExcepInfo,
2190 UINT* puArgErr)
2192 saxlocator *This = impl_from_IVBSAXLocator( iface );
2193 ITypeInfo *typeinfo;
2194 HRESULT hr;
2196 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2197 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2199 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2200 if(SUCCEEDED(hr))
2202 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2203 pDispParams, pVarResult, pExcepInfo, puArgErr);
2204 ITypeInfo_Release(typeinfo);
2207 return hr;
2210 /*** IVBSAXLocator methods ***/
2211 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2212 IVBSAXLocator* iface,
2213 int *pnColumn)
2215 saxlocator *This = impl_from_IVBSAXLocator( iface );
2216 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2219 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2220 IVBSAXLocator* iface,
2221 int *pnLine)
2223 saxlocator *This = impl_from_IVBSAXLocator( iface );
2224 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2227 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2229 saxlocator *This = impl_from_IVBSAXLocator( iface );
2230 const WCHAR *publicidW;
2231 HRESULT hr;
2233 TRACE("(%p)->(%p)\n", This, ret);
2235 if (!ret)
2236 return E_POINTER;
2238 *ret = NULL;
2239 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2240 if (FAILED(hr))
2241 return hr;
2243 return return_bstr(publicidW, ret);
2246 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2248 saxlocator *This = impl_from_IVBSAXLocator( iface );
2249 const WCHAR *systemidW;
2250 HRESULT hr;
2252 TRACE("(%p)->(%p)\n", This, ret);
2254 if (!ret)
2255 return E_POINTER;
2257 *ret = NULL;
2258 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2259 if (FAILED(hr))
2260 return hr;
2262 return return_bstr(systemidW, ret);
2265 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2267 ivbsaxlocator_QueryInterface,
2268 ivbsaxlocator_AddRef,
2269 ivbsaxlocator_Release,
2270 ivbsaxlocator_GetTypeInfoCount,
2271 ivbsaxlocator_GetTypeInfo,
2272 ivbsaxlocator_GetIDsOfNames,
2273 ivbsaxlocator_Invoke,
2274 ivbsaxlocator_get_columnNumber,
2275 ivbsaxlocator_get_lineNumber,
2276 ivbsaxlocator_get_publicId,
2277 ivbsaxlocator_get_systemId
2280 /*** ISAXLocator interface ***/
2281 /*** IUnknown methods ***/
2282 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2284 saxlocator *This = impl_from_ISAXLocator( iface );
2286 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2288 *ppvObject = NULL;
2290 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2291 IsEqualGUID( riid, &IID_ISAXLocator ))
2293 *ppvObject = iface;
2295 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2297 *ppvObject = &This->ISAXAttributes_iface;
2299 else
2301 WARN("interface %s not implemented\n", debugstr_guid(riid));
2302 return E_NOINTERFACE;
2305 ISAXLocator_AddRef( iface );
2307 return S_OK;
2310 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2312 saxlocator *This = impl_from_ISAXLocator( iface );
2313 ULONG ref = InterlockedIncrement( &This->ref );
2314 TRACE("(%p)->(%d)\n", This, ref);
2315 return ref;
2318 static ULONG WINAPI isaxlocator_Release(
2319 ISAXLocator* iface)
2321 saxlocator *This = impl_from_ISAXLocator( iface );
2322 LONG ref = InterlockedDecrement( &This->ref );
2324 TRACE("(%p)->(%d)\n", This, ref );
2326 if (ref == 0)
2328 element_entry *element, *element2;
2329 int index;
2331 SysFreeString(This->publicId);
2332 SysFreeString(This->systemId);
2333 SysFreeString(This->namespaceUri);
2335 for(index = 0; index < This->attr_alloc_count; index++)
2337 SysFreeString(This->attributes[index].szLocalname);
2338 SysFreeString(This->attributes[index].szValue);
2339 SysFreeString(This->attributes[index].szQName);
2341 heap_free(This->attributes);
2343 /* element stack */
2344 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2346 list_remove(&element->entry);
2347 free_element_entry(element);
2350 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2351 heap_free( This );
2354 return ref;
2357 /*** ISAXLocator methods ***/
2358 static HRESULT WINAPI isaxlocator_getColumnNumber(
2359 ISAXLocator* iface,
2360 int *pnColumn)
2362 saxlocator *This = impl_from_ISAXLocator( iface );
2364 *pnColumn = This->column;
2365 return S_OK;
2368 static HRESULT WINAPI isaxlocator_getLineNumber(
2369 ISAXLocator* iface,
2370 int *pnLine)
2372 saxlocator *This = impl_from_ISAXLocator( iface );
2374 *pnLine = This->line;
2375 return S_OK;
2378 static HRESULT WINAPI isaxlocator_getPublicId(
2379 ISAXLocator* iface,
2380 const WCHAR ** ppwchPublicId)
2382 BSTR publicId;
2383 saxlocator *This = impl_from_ISAXLocator( iface );
2385 SysFreeString(This->publicId);
2387 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2388 if(SysStringLen(publicId))
2389 This->publicId = publicId;
2390 else
2392 SysFreeString(publicId);
2393 This->publicId = NULL;
2396 *ppwchPublicId = This->publicId;
2397 return S_OK;
2400 static HRESULT WINAPI isaxlocator_getSystemId(
2401 ISAXLocator* iface,
2402 const WCHAR ** ppwchSystemId)
2404 BSTR systemId;
2405 saxlocator *This = impl_from_ISAXLocator( iface );
2407 SysFreeString(This->systemId);
2409 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2410 if(SysStringLen(systemId))
2411 This->systemId = systemId;
2412 else
2414 SysFreeString(systemId);
2415 This->systemId = NULL;
2418 *ppwchSystemId = This->systemId;
2419 return S_OK;
2422 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2424 isaxlocator_QueryInterface,
2425 isaxlocator_AddRef,
2426 isaxlocator_Release,
2427 isaxlocator_getColumnNumber,
2428 isaxlocator_getLineNumber,
2429 isaxlocator_getPublicId,
2430 isaxlocator_getSystemId
2433 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2435 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2436 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2438 saxlocator *locator;
2440 locator = heap_alloc( sizeof (*locator) );
2441 if( !locator )
2442 return E_OUTOFMEMORY;
2444 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2445 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2446 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2447 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2448 locator->ref = 1;
2449 locator->vbInterface = vbInterface;
2451 locator->saxreader = reader;
2452 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2454 locator->pParserCtxt = NULL;
2455 locator->publicId = NULL;
2456 locator->systemId = NULL;
2457 locator->line = reader->version < MSXML4 ? 0 : 1;
2458 locator->column = 0;
2459 locator->ret = S_OK;
2460 if (locator->saxreader->version >= MSXML6)
2461 locator->namespaceUri = SysAllocString(w3xmlns);
2462 else
2463 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2464 if(!locator->namespaceUri)
2466 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2467 heap_free(locator);
2468 return E_OUTOFMEMORY;
2471 locator->attr_alloc_count = 8;
2472 locator->attr_count = 0;
2473 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2474 if(!locator->attributes)
2476 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2477 SysFreeString(locator->namespaceUri);
2478 heap_free(locator);
2479 return E_OUTOFMEMORY;
2482 list_init(&locator->elements);
2484 *ppsaxlocator = locator;
2486 TRACE("returning %p\n", *ppsaxlocator);
2488 return S_OK;
2491 /*** SAXXMLReader internal functions ***/
2492 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2494 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2495 xmlChar *enc_name = NULL;
2496 saxlocator *locator;
2497 HRESULT hr;
2499 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2501 hr = SAXLocator_create(This, &locator, vbInterface);
2502 if (FAILED(hr))
2503 return hr;
2505 if (size >= 4)
2507 const unsigned char *buff = (unsigned char*)buffer;
2509 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2510 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2511 TRACE("detected encoding: %s\n", enc_name);
2512 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2513 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2514 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2516 buffer += 3;
2517 size -= 3;
2521 /* if libxml2 detection failed try to guess */
2522 if (encoding == XML_CHAR_ENCODING_NONE)
2524 const WCHAR *ptr = (WCHAR*)buffer;
2525 /* an xml declaration with optional encoding will still be handled by the parser */
2526 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2528 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2529 encoding = XML_CHAR_ENCODING_UTF16LE;
2532 else if (encoding == XML_CHAR_ENCODING_UTF8)
2533 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2534 else
2535 enc_name = NULL;
2537 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2538 if (!locator->pParserCtxt)
2540 ISAXLocator_Release(&locator->ISAXLocator_iface);
2541 return E_FAIL;
2544 if (enc_name)
2546 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2547 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2548 TRACE("switching to %s\n", enc_name);
2549 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2553 xmlFree(locator->pParserCtxt->sax);
2554 locator->pParserCtxt->sax = &locator->saxreader->sax;
2555 locator->pParserCtxt->userData = locator;
2557 This->isParsing = TRUE;
2558 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2559 hr = E_FAIL;
2560 else
2561 hr = locator->ret;
2562 This->isParsing = FALSE;
2564 if(locator->pParserCtxt)
2566 locator->pParserCtxt->sax = NULL;
2567 xmlFreeParserCtxt(locator->pParserCtxt);
2568 locator->pParserCtxt = NULL;
2571 ISAXLocator_Release(&locator->ISAXLocator_iface);
2572 return hr;
2575 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2577 saxlocator *locator;
2578 HRESULT hr;
2579 ULONG dataRead;
2580 char data[2048];
2581 int ret;
2583 dataRead = 0;
2584 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2585 if(FAILED(hr)) return hr;
2587 hr = SAXLocator_create(This, &locator, vbInterface);
2588 if(FAILED(hr)) return hr;
2590 locator->pParserCtxt = xmlCreatePushParserCtxt(
2591 &locator->saxreader->sax, locator,
2592 data, dataRead, NULL);
2593 if(!locator->pParserCtxt)
2595 ISAXLocator_Release(&locator->ISAXLocator_iface);
2596 return E_FAIL;
2599 This->isParsing = TRUE;
2601 do {
2602 dataRead = 0;
2603 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2604 if (FAILED(hr) || !dataRead) break;
2606 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2607 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2608 }while(hr == S_OK);
2610 if(SUCCEEDED(hr))
2612 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2613 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2617 This->isParsing = FALSE;
2619 xmlFreeParserCtxt(locator->pParserCtxt);
2620 locator->pParserCtxt = NULL;
2621 ISAXLocator_Release(&locator->ISAXLocator_iface);
2622 return hr;
2625 static HRESULT internal_parse(
2626 saxreader* This,
2627 VARIANT varInput,
2628 BOOL vbInterface)
2630 HRESULT hr;
2632 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2634 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2635 free_bstr_pool(&This->pool);
2637 switch(V_VT(&varInput))
2639 case VT_BSTR:
2640 case VT_BSTR|VT_BYREF:
2642 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2643 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2644 break;
2646 case VT_ARRAY|VT_UI1: {
2647 void *pSAData;
2648 LONG lBound, uBound;
2649 ULONG dataRead;
2651 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2652 if(hr != S_OK) break;
2653 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2654 if(hr != S_OK) break;
2655 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2656 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2657 if(hr != S_OK) break;
2658 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2659 SafeArrayUnaccessData(V_ARRAY(&varInput));
2660 break;
2662 case VT_UNKNOWN:
2663 case VT_DISPATCH: {
2664 ISequentialStream *stream = NULL;
2665 IXMLDOMDocument *xmlDoc;
2667 if (!V_UNKNOWN(&varInput))
2668 return E_INVALIDARG;
2670 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2671 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2673 BSTR bstrData;
2675 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2676 hr = internal_parseBuffer(This, (const char*)bstrData,
2677 SysStringByteLen(bstrData), vbInterface);
2678 IXMLDOMDocument_Release(xmlDoc);
2679 SysFreeString(bstrData);
2680 break;
2683 /* try base interface first */
2684 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2685 if (!stream)
2686 /* this should never happen if IStream is implemented properly, but just in case */
2687 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2689 if(stream)
2691 hr = internal_parseStream(This, stream, vbInterface);
2692 ISequentialStream_Release(stream);
2694 else
2696 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2697 hr = E_INVALIDARG;
2700 break;
2702 default:
2703 WARN("vt %d not implemented\n", V_VT(&varInput));
2704 hr = E_INVALIDARG;
2707 return hr;
2710 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2712 saxreader *This = obj;
2714 return internal_parseBuffer(This, ptr, len, TRUE);
2717 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2719 saxreader *This = obj;
2721 return internal_parseBuffer(This, ptr, len, FALSE);
2724 static HRESULT internal_parseURL(
2725 saxreader* This,
2726 const WCHAR *url,
2727 BOOL vbInterface)
2729 IMoniker *mon;
2730 bsc_t *bsc;
2731 HRESULT hr;
2733 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2735 hr = create_moniker_from_url(url, &mon);
2736 if(FAILED(hr))
2737 return hr;
2739 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2740 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2741 IMoniker_Release(mon);
2743 if(FAILED(hr))
2744 return hr;
2746 return detach_bsc(bsc);
2749 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2751 const IID *riid;
2753 if (V_VT(v) == VT_EMPTY)
2754 return saxreader_put_handler(This, type, NULL, vb);
2756 switch (type)
2758 case SAXDeclHandler:
2759 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2760 break;
2761 case SAXLexicalHandler:
2762 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2763 break;
2764 default:
2765 ERR("wrong handler type %d\n", type);
2766 return E_FAIL;
2769 switch (V_VT(v))
2771 case VT_DISPATCH:
2772 case VT_UNKNOWN:
2774 IUnknown *handler = NULL;
2776 if (V_UNKNOWN(v))
2778 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2779 if (FAILED(hr)) return hr;
2782 saxreader_put_handler(This, type, handler, vb);
2783 if (handler) IUnknown_Release(handler);
2784 break;
2786 default:
2787 ERR("value type %d not supported\n", V_VT(v));
2788 return E_INVALIDARG;
2791 return S_OK;
2794 static HRESULT internal_putProperty(
2795 saxreader* This,
2796 const WCHAR *prop,
2797 VARIANT value,
2798 BOOL vbInterface)
2800 VARIANT *v;
2802 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2804 if (This->isParsing) return E_FAIL;
2806 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2807 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2808 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2810 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2811 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2813 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2815 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2816 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2817 return E_NOTIMPL;
2820 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2822 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2823 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2824 return E_NOTIMPL;
2827 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2829 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2830 return E_NOTIMPL;
2832 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2833 return E_FAIL;
2835 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2836 return E_NOTIMPL;
2838 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2839 return E_NOTIMPL;
2841 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2842 return E_FAIL;
2844 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2845 return E_FAIL;
2847 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2848 return E_FAIL;
2850 return E_INVALIDARG;
2853 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2855 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2857 if (!value) return E_POINTER;
2859 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2861 V_VT(value) = VT_UNKNOWN;
2862 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2863 return S_OK;
2866 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2868 V_VT(value) = VT_UNKNOWN;
2869 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2870 return S_OK;
2873 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2875 V_VT(value) = VT_BSTR;
2876 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2877 return S_OK;
2880 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2882 return E_NOTIMPL;
2885 /*** IVBSAXXMLReader interface ***/
2886 /*** IUnknown methods ***/
2887 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2889 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2891 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2893 *ppvObject = NULL;
2895 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2896 IsEqualGUID( riid, &IID_IDispatch ) ||
2897 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2899 *ppvObject = iface;
2901 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2903 *ppvObject = &This->ISAXXMLReader_iface;
2905 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2907 return *ppvObject ? S_OK : E_NOINTERFACE;
2909 else
2911 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2912 return E_NOINTERFACE;
2915 IVBSAXXMLReader_AddRef( iface );
2917 return S_OK;
2920 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2922 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2923 TRACE("%p\n", This );
2924 return InterlockedIncrement( &This->ref );
2927 static ULONG WINAPI saxxmlreader_Release(
2928 IVBSAXXMLReader* iface)
2930 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2931 LONG ref;
2933 TRACE("%p\n", This );
2935 ref = InterlockedDecrement( &This->ref );
2936 if ( ref == 0 )
2938 int i;
2940 for (i = 0; i < SAXHandler_Last; i++)
2942 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2944 if (saxiface->handler)
2945 IUnknown_Release(saxiface->handler);
2947 if (saxiface->vbhandler)
2948 IUnknown_Release(saxiface->vbhandler);
2951 SysFreeString(This->xmldecl_version);
2952 free_bstr_pool(&This->pool);
2954 heap_free( This );
2957 return ref;
2959 /*** IDispatch ***/
2960 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2962 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2963 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2966 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2967 IVBSAXXMLReader *iface,
2968 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2970 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2971 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2972 iTInfo, lcid, ppTInfo);
2975 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2976 IVBSAXXMLReader *iface,
2977 REFIID riid,
2978 LPOLESTR* rgszNames,
2979 UINT cNames,
2980 LCID lcid,
2981 DISPID* rgDispId)
2983 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2984 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2985 riid, rgszNames, cNames, lcid, rgDispId);
2988 static HRESULT WINAPI saxxmlreader_Invoke(
2989 IVBSAXXMLReader *iface,
2990 DISPID dispIdMember,
2991 REFIID riid,
2992 LCID lcid,
2993 WORD wFlags,
2994 DISPPARAMS* pDispParams,
2995 VARIANT* pVarResult,
2996 EXCEPINFO* pExcepInfo,
2997 UINT* puArgErr)
2999 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3000 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3001 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3004 /*** IVBSAXXMLReader methods ***/
3005 static HRESULT WINAPI saxxmlreader_getFeature(
3006 IVBSAXXMLReader* iface,
3007 BSTR feature_name,
3008 VARIANT_BOOL *value)
3010 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3011 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3014 static HRESULT WINAPI saxxmlreader_putFeature(
3015 IVBSAXXMLReader* iface,
3016 BSTR feature_name,
3017 VARIANT_BOOL value)
3019 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3020 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3023 static HRESULT WINAPI saxxmlreader_getProperty(
3024 IVBSAXXMLReader* iface,
3025 BSTR prop,
3026 VARIANT *value)
3028 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3029 return internal_getProperty(This, prop, value, TRUE);
3032 static HRESULT WINAPI saxxmlreader_putProperty(
3033 IVBSAXXMLReader* iface,
3034 BSTR pProp,
3035 VARIANT value)
3037 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3038 return internal_putProperty(This, pProp, value, TRUE);
3041 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3042 IVBSAXXMLReader* iface,
3043 IVBSAXEntityResolver **resolver)
3045 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3046 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3049 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3050 IVBSAXXMLReader* iface,
3051 IVBSAXEntityResolver *resolver)
3053 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3054 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3057 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3058 IVBSAXXMLReader* iface,
3059 IVBSAXContentHandler **handler)
3061 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3062 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3065 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3066 IVBSAXXMLReader* iface,
3067 IVBSAXContentHandler *handler)
3069 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3070 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3073 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3074 IVBSAXXMLReader* iface,
3075 IVBSAXDTDHandler **handler)
3077 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3078 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3081 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3082 IVBSAXXMLReader* iface,
3083 IVBSAXDTDHandler *handler)
3085 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3086 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3089 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3090 IVBSAXXMLReader* iface,
3091 IVBSAXErrorHandler **handler)
3093 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3094 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3097 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3098 IVBSAXXMLReader* iface,
3099 IVBSAXErrorHandler *handler)
3101 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3102 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3105 static HRESULT WINAPI saxxmlreader_get_baseURL(
3106 IVBSAXXMLReader* iface,
3107 BSTR *pBaseUrl)
3109 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3111 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3112 return E_NOTIMPL;
3115 static HRESULT WINAPI saxxmlreader_put_baseURL(
3116 IVBSAXXMLReader* iface,
3117 BSTR pBaseUrl)
3119 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3120 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3123 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3124 IVBSAXXMLReader* iface,
3125 BSTR *pSecureBaseUrl)
3127 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3129 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3130 return E_NOTIMPL;
3133 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3134 IVBSAXXMLReader* iface,
3135 BSTR secureBaseUrl)
3137 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3138 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3141 static HRESULT WINAPI saxxmlreader_parse(
3142 IVBSAXXMLReader* iface,
3143 VARIANT varInput)
3145 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3146 return internal_parse(This, varInput, TRUE);
3149 static HRESULT WINAPI saxxmlreader_parseURL(
3150 IVBSAXXMLReader* iface,
3151 BSTR url)
3153 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3154 return internal_parseURL(This, url, TRUE);
3157 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3159 saxxmlreader_QueryInterface,
3160 saxxmlreader_AddRef,
3161 saxxmlreader_Release,
3162 saxxmlreader_GetTypeInfoCount,
3163 saxxmlreader_GetTypeInfo,
3164 saxxmlreader_GetIDsOfNames,
3165 saxxmlreader_Invoke,
3166 saxxmlreader_getFeature,
3167 saxxmlreader_putFeature,
3168 saxxmlreader_getProperty,
3169 saxxmlreader_putProperty,
3170 saxxmlreader_get_entityResolver,
3171 saxxmlreader_put_entityResolver,
3172 saxxmlreader_get_contentHandler,
3173 saxxmlreader_put_contentHandler,
3174 saxxmlreader_get_dtdHandler,
3175 saxxmlreader_put_dtdHandler,
3176 saxxmlreader_get_errorHandler,
3177 saxxmlreader_put_errorHandler,
3178 saxxmlreader_get_baseURL,
3179 saxxmlreader_put_baseURL,
3180 saxxmlreader_get_secureBaseURL,
3181 saxxmlreader_put_secureBaseURL,
3182 saxxmlreader_parse,
3183 saxxmlreader_parseURL
3186 /*** ISAXXMLReader interface ***/
3187 /*** IUnknown methods ***/
3188 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3190 saxreader *This = impl_from_ISAXXMLReader( iface );
3191 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3194 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3196 saxreader *This = impl_from_ISAXXMLReader( iface );
3197 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3200 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3202 saxreader *This = impl_from_ISAXXMLReader( iface );
3203 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3206 /*** ISAXXMLReader methods ***/
3207 static HRESULT WINAPI isaxxmlreader_getFeature(
3208 ISAXXMLReader* iface,
3209 const WCHAR *feature_name,
3210 VARIANT_BOOL *value)
3212 saxreader *This = impl_from_ISAXXMLReader( iface );
3213 saxreader_feature feature;
3215 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3217 feature = get_saxreader_feature(feature_name);
3218 if (feature == Namespaces || feature == NamespacePrefixes)
3219 return get_feature_value(This, feature, value);
3221 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3222 return E_NOTIMPL;
3225 static HRESULT WINAPI isaxxmlreader_putFeature(
3226 ISAXXMLReader* iface,
3227 const WCHAR *feature_name,
3228 VARIANT_BOOL value)
3230 saxreader *This = impl_from_ISAXXMLReader( iface );
3231 saxreader_feature feature;
3233 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3235 feature = get_saxreader_feature(feature_name);
3237 /* accepted cases */
3238 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
3239 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
3240 feature == Namespaces ||
3241 feature == NamespacePrefixes)
3243 return set_feature_value(This, feature, value);
3246 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
3248 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3249 return set_feature_value(This, feature, value);
3252 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3253 return E_NOTIMPL;
3256 static HRESULT WINAPI isaxxmlreader_getProperty(
3257 ISAXXMLReader* iface,
3258 const WCHAR *prop,
3259 VARIANT *value)
3261 saxreader *This = impl_from_ISAXXMLReader( iface );
3262 return internal_getProperty(This, prop, value, FALSE);
3265 static HRESULT WINAPI isaxxmlreader_putProperty(
3266 ISAXXMLReader* iface,
3267 const WCHAR *pProp,
3268 VARIANT value)
3270 saxreader *This = impl_from_ISAXXMLReader( iface );
3271 return internal_putProperty(This, pProp, value, FALSE);
3274 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3275 ISAXXMLReader* iface,
3276 ISAXEntityResolver **resolver)
3278 saxreader *This = impl_from_ISAXXMLReader( iface );
3279 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3282 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3283 ISAXXMLReader* iface,
3284 ISAXEntityResolver *resolver)
3286 saxreader *This = impl_from_ISAXXMLReader( iface );
3287 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3290 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3291 ISAXXMLReader* iface,
3292 ISAXContentHandler **handler)
3294 saxreader *This = impl_from_ISAXXMLReader( iface );
3295 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3298 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3299 ISAXXMLReader* iface,
3300 ISAXContentHandler *handler)
3302 saxreader *This = impl_from_ISAXXMLReader( iface );
3303 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3306 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3307 ISAXXMLReader* iface,
3308 ISAXDTDHandler **handler)
3310 saxreader *This = impl_from_ISAXXMLReader( iface );
3311 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3314 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3315 ISAXXMLReader* iface,
3316 ISAXDTDHandler *handler)
3318 saxreader *This = impl_from_ISAXXMLReader( iface );
3319 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3322 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3323 ISAXXMLReader* iface,
3324 ISAXErrorHandler **handler)
3326 saxreader *This = impl_from_ISAXXMLReader( iface );
3327 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3330 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3332 saxreader *This = impl_from_ISAXXMLReader( iface );
3333 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3336 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3337 ISAXXMLReader* iface,
3338 const WCHAR **base_url)
3340 saxreader *This = impl_from_ISAXXMLReader( iface );
3342 FIXME("(%p)->(%p) stub\n", This, base_url);
3343 return E_NOTIMPL;
3346 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3347 ISAXXMLReader* iface,
3348 const WCHAR *pBaseUrl)
3350 saxreader *This = impl_from_ISAXXMLReader( iface );
3352 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3353 return E_NOTIMPL;
3356 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3357 ISAXXMLReader* iface,
3358 const WCHAR **pSecureBaseUrl)
3360 saxreader *This = impl_from_ISAXXMLReader( iface );
3361 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3362 return E_NOTIMPL;
3365 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3366 ISAXXMLReader* iface,
3367 const WCHAR *secureBaseUrl)
3369 saxreader *This = impl_from_ISAXXMLReader( iface );
3371 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3372 return E_NOTIMPL;
3375 static HRESULT WINAPI isaxxmlreader_parse(
3376 ISAXXMLReader* iface,
3377 VARIANT varInput)
3379 saxreader *This = impl_from_ISAXXMLReader( iface );
3380 return internal_parse(This, varInput, FALSE);
3383 static HRESULT WINAPI isaxxmlreader_parseURL(
3384 ISAXXMLReader* iface,
3385 const WCHAR *url)
3387 saxreader *This = impl_from_ISAXXMLReader( iface );
3388 return internal_parseURL(This, url, FALSE);
3391 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3393 isaxxmlreader_QueryInterface,
3394 isaxxmlreader_AddRef,
3395 isaxxmlreader_Release,
3396 isaxxmlreader_getFeature,
3397 isaxxmlreader_putFeature,
3398 isaxxmlreader_getProperty,
3399 isaxxmlreader_putProperty,
3400 isaxxmlreader_getEntityResolver,
3401 isaxxmlreader_putEntityResolver,
3402 isaxxmlreader_getContentHandler,
3403 isaxxmlreader_putContentHandler,
3404 isaxxmlreader_getDTDHandler,
3405 isaxxmlreader_putDTDHandler,
3406 isaxxmlreader_getErrorHandler,
3407 isaxxmlreader_putErrorHandler,
3408 isaxxmlreader_getBaseURL,
3409 isaxxmlreader_putBaseURL,
3410 isaxxmlreader_getSecureBaseURL,
3411 isaxxmlreader_putSecureBaseURL,
3412 isaxxmlreader_parse,
3413 isaxxmlreader_parseURL
3416 static const tid_t saxreader_iface_tids[] = {
3417 IVBSAXXMLReader_tid,
3420 static dispex_static_data_t saxreader_dispex = {
3421 NULL,
3422 IVBSAXXMLReader_tid,
3423 NULL,
3424 saxreader_iface_tids
3427 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3429 saxreader *reader;
3431 TRACE("(%p)\n", ppObj);
3433 reader = heap_alloc( sizeof (*reader) );
3434 if( !reader )
3435 return E_OUTOFMEMORY;
3437 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3438 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3439 reader->ref = 1;
3440 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3441 reader->isParsing = FALSE;
3442 reader->xmldecl_version = NULL;
3443 reader->pool.pool = NULL;
3444 reader->pool.index = 0;
3445 reader->pool.len = 0;
3446 reader->features = Namespaces | NamespacePrefixes;
3447 reader->version = version;
3449 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3451 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3452 reader->sax.initialized = XML_SAX2_MAGIC;
3453 reader->sax.startDocument = libxmlStartDocument;
3454 reader->sax.endDocument = libxmlEndDocument;
3455 reader->sax.startElementNs = libxmlStartElementNS;
3456 reader->sax.endElementNs = libxmlEndElementNS;
3457 reader->sax.characters = libxmlCharacters;
3458 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3459 reader->sax.comment = libxmlComment;
3460 reader->sax.error = libxmlFatalError;
3461 reader->sax.fatalError = libxmlFatalError;
3462 reader->sax.cdataBlock = libxml_cdatablock;
3463 reader->sax.resolveEntity = libxmlresolveentity;
3465 *ppObj = &reader->IVBSAXXMLReader_iface;
3467 TRACE("returning iface %p\n", *ppObj);
3469 return S_OK;
3472 #else
3474 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3476 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3477 "libxml2 support was not present at compile time.\n");
3478 return E_NOTIMPL;
3481 #endif