msxml3/tests: Null-terminate a string before A->W conversion (Valgrind).
[wine/wine-gecko.git] / dlls / msxml3 / saxreader.c
blob0d58db3c29140a18b03c1a2ad3fa2996106c4797
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 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 #ifdef HAVE_LIBXML2
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 attributesSize;
305 int nb_attributes;
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), 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;
694 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
695 if(fix_column)
697 This->column = 1;
698 for(; *p!='\n' && *p!='\r' && p>=This->pParserCtxt->input->base; p--)
699 This->column++;
701 else
703 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
707 /*** IVBSAXAttributes interface ***/
708 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
709 IVBSAXAttributes* iface,
710 REFIID riid,
711 void **ppvObject)
713 saxlocator *This = impl_from_IVBSAXAttributes(iface);
714 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
715 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
718 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
720 saxlocator *This = impl_from_IVBSAXAttributes(iface);
721 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
724 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
726 saxlocator *This = impl_from_IVBSAXAttributes(iface);
727 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
730 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
732 saxlocator *This = impl_from_IVBSAXAttributes( iface );
734 TRACE("(%p)->(%p)\n", This, pctinfo);
736 *pctinfo = 1;
738 return S_OK;
741 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
742 IVBSAXAttributes *iface,
743 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
745 saxlocator *This = impl_from_IVBSAXAttributes( iface );
747 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
749 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
752 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
753 IVBSAXAttributes *iface,
754 REFIID riid,
755 LPOLESTR* rgszNames,
756 UINT cNames,
757 LCID lcid,
758 DISPID* rgDispId)
760 saxlocator *This = impl_from_IVBSAXAttributes( iface );
761 ITypeInfo *typeinfo;
762 HRESULT hr;
764 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
765 lcid, rgDispId);
767 if(!rgszNames || cNames == 0 || !rgDispId)
768 return E_INVALIDARG;
770 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
771 if(SUCCEEDED(hr))
773 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
774 ITypeInfo_Release(typeinfo);
777 return hr;
780 static HRESULT WINAPI ivbsaxattributes_Invoke(
781 IVBSAXAttributes *iface,
782 DISPID dispIdMember,
783 REFIID riid,
784 LCID lcid,
785 WORD wFlags,
786 DISPPARAMS* pDispParams,
787 VARIANT* pVarResult,
788 EXCEPINFO* pExcepInfo,
789 UINT* puArgErr)
791 saxlocator *This = impl_from_IVBSAXAttributes( iface );
792 ITypeInfo *typeinfo;
793 HRESULT hr;
795 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
796 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
798 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
799 if(SUCCEEDED(hr))
801 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
802 pDispParams, pVarResult, pExcepInfo, puArgErr);
803 ITypeInfo_Release(typeinfo);
806 return hr;
809 /*** IVBSAXAttributes methods ***/
810 static HRESULT WINAPI ivbsaxattributes_get_length(
811 IVBSAXAttributes* iface,
812 int *nLength)
814 saxlocator *This = impl_from_IVBSAXAttributes( iface );
815 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
818 static HRESULT WINAPI ivbsaxattributes_getURI(
819 IVBSAXAttributes* iface,
820 int nIndex,
821 BSTR *uri)
823 saxlocator *This = impl_from_IVBSAXAttributes( iface );
824 const WCHAR *uriW;
825 HRESULT hr;
826 int len;
828 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
830 if (!uri)
831 return E_POINTER;
833 *uri = NULL;
834 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
835 if (FAILED(hr))
836 return hr;
838 return return_bstrn(uriW, len, uri);
841 static HRESULT WINAPI ivbsaxattributes_getLocalName(
842 IVBSAXAttributes* iface,
843 int nIndex,
844 BSTR *name)
846 saxlocator *This = impl_from_IVBSAXAttributes( iface );
847 const WCHAR *nameW;
848 HRESULT hr;
849 int len;
851 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
853 if (!name)
854 return E_POINTER;
856 *name = NULL;
857 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
858 if (FAILED(hr))
859 return hr;
861 return return_bstrn(nameW, len, name);
864 static HRESULT WINAPI ivbsaxattributes_getQName(
865 IVBSAXAttributes* iface,
866 int nIndex,
867 BSTR *QName)
869 saxlocator *This = impl_from_IVBSAXAttributes( iface );
870 const WCHAR *nameW;
871 HRESULT hr;
872 int len;
874 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
876 if (!QName)
877 return E_POINTER;
879 *QName = NULL;
880 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
881 if (FAILED(hr))
882 return hr;
884 return return_bstrn(nameW, len, QName);
887 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
888 IVBSAXAttributes* iface,
889 BSTR uri,
890 BSTR localName,
891 int *index)
893 saxlocator *This = impl_from_IVBSAXAttributes( iface );
894 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
895 localName, SysStringLen(localName), index);
898 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
899 IVBSAXAttributes* iface,
900 BSTR QName,
901 int *index)
903 saxlocator *This = impl_from_IVBSAXAttributes( iface );
904 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
905 SysStringLen(QName), index);
908 static HRESULT WINAPI ivbsaxattributes_getType(
909 IVBSAXAttributes* iface,
910 int nIndex,
911 BSTR *type)
913 saxlocator *This = impl_from_IVBSAXAttributes( iface );
914 const WCHAR *typeW;
915 HRESULT hr;
916 int len;
918 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
920 if (!type)
921 return E_POINTER;
923 *type = NULL;
924 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
925 if (FAILED(hr))
926 return hr;
928 return return_bstrn(typeW, len, type);
931 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
932 IVBSAXAttributes* iface,
933 BSTR uri,
934 BSTR localName,
935 BSTR *type)
937 saxlocator *This = impl_from_IVBSAXAttributes( iface );
938 const WCHAR *typeW;
939 HRESULT hr;
940 int len;
942 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
944 if (!type)
945 return E_POINTER;
947 *type = NULL;
948 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
949 localName, SysStringLen(localName), &typeW, &len);
950 if (FAILED(hr))
951 return hr;
953 return return_bstrn(typeW, len, type);
956 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
957 IVBSAXAttributes* iface,
958 BSTR QName,
959 BSTR *type)
961 saxlocator *This = impl_from_IVBSAXAttributes( iface );
962 const WCHAR *typeW;
963 HRESULT hr;
964 int len;
966 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
968 if (!type)
969 return E_POINTER;
971 *type = NULL;
972 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
973 &typeW, &len);
974 if (FAILED(hr))
975 return hr;
977 return return_bstrn(typeW, len, type);
980 static HRESULT WINAPI ivbsaxattributes_getValue(
981 IVBSAXAttributes* iface,
982 int nIndex,
983 BSTR *value)
985 saxlocator *This = impl_from_IVBSAXAttributes( iface );
986 const WCHAR *valueW;
987 HRESULT hr;
988 int len;
990 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
992 if (!value)
993 return E_POINTER;
995 *value = NULL;
996 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
997 if (FAILED(hr))
998 return hr;
1000 return return_bstrn(valueW, len, value);
1003 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1004 IVBSAXAttributes* iface,
1005 BSTR uri,
1006 BSTR localName,
1007 BSTR *value)
1009 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1010 const WCHAR *valueW;
1011 HRESULT hr;
1012 int len;
1014 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1016 if (!value)
1017 return E_POINTER;
1019 *value = NULL;
1020 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1021 localName, SysStringLen(localName), &valueW, &len);
1022 if (FAILED(hr))
1023 return hr;
1025 return return_bstrn(valueW, len, value);
1028 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1029 IVBSAXAttributes* iface,
1030 BSTR QName,
1031 BSTR *value)
1033 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1034 const WCHAR *valueW;
1035 HRESULT hr;
1036 int len;
1038 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1040 if (!value)
1041 return E_POINTER;
1043 *value = NULL;
1044 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1045 SysStringLen(QName), &valueW, &len);
1046 if (FAILED(hr))
1047 return hr;
1049 return return_bstrn(valueW, len, value);
1052 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1054 ivbsaxattributes_QueryInterface,
1055 ivbsaxattributes_AddRef,
1056 ivbsaxattributes_Release,
1057 ivbsaxattributes_GetTypeInfoCount,
1058 ivbsaxattributes_GetTypeInfo,
1059 ivbsaxattributes_GetIDsOfNames,
1060 ivbsaxattributes_Invoke,
1061 ivbsaxattributes_get_length,
1062 ivbsaxattributes_getURI,
1063 ivbsaxattributes_getLocalName,
1064 ivbsaxattributes_getQName,
1065 ivbsaxattributes_getIndexFromName,
1066 ivbsaxattributes_getIndexFromQName,
1067 ivbsaxattributes_getType,
1068 ivbsaxattributes_getTypeFromName,
1069 ivbsaxattributes_getTypeFromQName,
1070 ivbsaxattributes_getValue,
1071 ivbsaxattributes_getValueFromName,
1072 ivbsaxattributes_getValueFromQName
1075 /*** ISAXAttributes interface ***/
1076 /*** IUnknown methods ***/
1077 static HRESULT WINAPI isaxattributes_QueryInterface(
1078 ISAXAttributes* iface,
1079 REFIID riid,
1080 void **ppvObject)
1082 saxlocator *This = impl_from_ISAXAttributes(iface);
1083 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1084 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1087 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1089 saxlocator *This = impl_from_ISAXAttributes(iface);
1090 TRACE("%p\n", This);
1091 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1094 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1096 saxlocator *This = impl_from_ISAXAttributes(iface);
1098 TRACE("%p\n", This);
1099 return ISAXLocator_Release(&This->ISAXLocator_iface);
1102 /*** ISAXAttributes methods ***/
1103 static HRESULT WINAPI isaxattributes_getLength(
1104 ISAXAttributes* iface,
1105 int *length)
1107 saxlocator *This = impl_from_ISAXAttributes( iface );
1109 *length = This->nb_attributes;
1110 TRACE("Length set to %d\n", *length);
1111 return S_OK;
1114 static HRESULT WINAPI isaxattributes_getURI(
1115 ISAXAttributes* iface,
1116 int index,
1117 const WCHAR **url,
1118 int *size)
1120 saxlocator *This = impl_from_ISAXAttributes( iface );
1121 TRACE("(%p)->(%d)\n", This, index);
1123 if(index >= This->nb_attributes || index < 0) return E_INVALIDARG;
1124 if(!url || !size) return E_POINTER;
1126 *size = SysStringLen(This->attributes[index].szURI);
1127 *url = This->attributes[index].szURI;
1129 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1131 return S_OK;
1134 static HRESULT WINAPI isaxattributes_getLocalName(
1135 ISAXAttributes* iface,
1136 int nIndex,
1137 const WCHAR **pLocalName,
1138 int *pLocalNameLength)
1140 saxlocator *This = impl_from_ISAXAttributes( iface );
1141 TRACE("(%p)->(%d)\n", This, nIndex);
1143 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1144 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1146 *pLocalNameLength = SysStringLen(This->attributes[nIndex].szLocalname);
1147 *pLocalName = This->attributes[nIndex].szLocalname;
1149 return S_OK;
1152 static HRESULT WINAPI isaxattributes_getQName(
1153 ISAXAttributes* iface,
1154 int nIndex,
1155 const WCHAR **pQName,
1156 int *pQNameLength)
1158 saxlocator *This = impl_from_ISAXAttributes( iface );
1159 TRACE("(%p)->(%d)\n", This, nIndex);
1161 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1162 if(!pQName || !pQNameLength) return E_POINTER;
1164 *pQNameLength = SysStringLen(This->attributes[nIndex].szQName);
1165 *pQName = This->attributes[nIndex].szQName;
1167 return S_OK;
1170 static HRESULT WINAPI isaxattributes_getName(
1171 ISAXAttributes* iface,
1172 int index,
1173 const WCHAR **uri,
1174 int *pUriLength,
1175 const WCHAR **localName,
1176 int *pLocalNameSize,
1177 const WCHAR **QName,
1178 int *pQNameLength)
1180 saxlocator *This = impl_from_ISAXAttributes( iface );
1181 TRACE("(%p)->(%d)\n", This, index);
1183 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1184 if(!uri || !pUriLength || !localName || !pLocalNameSize
1185 || !QName || !pQNameLength) return E_POINTER;
1187 *pUriLength = SysStringLen(This->attributes[index].szURI);
1188 *uri = This->attributes[index].szURI;
1189 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1190 *localName = This->attributes[index].szLocalname;
1191 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1192 *QName = This->attributes[index].szQName;
1194 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1196 return S_OK;
1199 static HRESULT WINAPI isaxattributes_getIndexFromName(
1200 ISAXAttributes* iface,
1201 const WCHAR *pUri,
1202 int cUriLength,
1203 const WCHAR *pLocalName,
1204 int cocalNameLength,
1205 int *index)
1207 saxlocator *This = impl_from_ISAXAttributes( iface );
1208 int i;
1209 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1210 debugstr_w(pLocalName), cocalNameLength);
1212 if(!pUri || !pLocalName || !index) return E_POINTER;
1214 for(i=0; i<This->nb_attributes; i++)
1216 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1217 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1218 continue;
1219 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1220 sizeof(WCHAR)*cUriLength))
1221 continue;
1222 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1223 sizeof(WCHAR)*cocalNameLength))
1224 continue;
1226 *index = i;
1227 return S_OK;
1230 return E_INVALIDARG;
1233 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1234 ISAXAttributes* iface,
1235 const WCHAR *pQName,
1236 int nQNameLength,
1237 int *index)
1239 saxlocator *This = impl_from_ISAXAttributes( iface );
1240 int i;
1241 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1243 if(!pQName || !index) return E_POINTER;
1244 if(!nQNameLength) return E_INVALIDARG;
1246 for(i=0; i<This->nb_attributes; i++)
1248 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1249 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1251 *index = i;
1252 return S_OK;
1255 return E_INVALIDARG;
1258 static HRESULT WINAPI isaxattributes_getType(
1259 ISAXAttributes* iface,
1260 int nIndex,
1261 const WCHAR **pType,
1262 int *pTypeLength)
1264 saxlocator *This = impl_from_ISAXAttributes( iface );
1266 FIXME("(%p)->(%d) stub\n", This, nIndex);
1267 return E_NOTIMPL;
1270 static HRESULT WINAPI isaxattributes_getTypeFromName(
1271 ISAXAttributes* iface,
1272 const WCHAR *pUri,
1273 int nUri,
1274 const WCHAR *pLocalName,
1275 int nLocalName,
1276 const WCHAR **pType,
1277 int *nType)
1279 saxlocator *This = impl_from_ISAXAttributes( iface );
1281 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1282 debugstr_w(pLocalName), nLocalName);
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1287 ISAXAttributes* iface,
1288 const WCHAR *pQName,
1289 int nQName,
1290 const WCHAR **pType,
1291 int *nType)
1293 saxlocator *This = impl_from_ISAXAttributes( iface );
1295 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1296 return E_NOTIMPL;
1299 static HRESULT WINAPI isaxattributes_getValue(
1300 ISAXAttributes* iface,
1301 int index,
1302 const WCHAR **value,
1303 int *nValue)
1305 saxlocator *This = impl_from_ISAXAttributes( iface );
1306 TRACE("(%p)->(%d)\n", This, index);
1308 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1309 if(!value || !nValue) return E_POINTER;
1311 *nValue = SysStringLen(This->attributes[index].szValue);
1312 *value = This->attributes[index].szValue;
1314 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1316 return S_OK;
1319 static HRESULT WINAPI isaxattributes_getValueFromName(
1320 ISAXAttributes* iface,
1321 const WCHAR *pUri,
1322 int nUri,
1323 const WCHAR *pLocalName,
1324 int nLocalName,
1325 const WCHAR **pValue,
1326 int *nValue)
1328 HRESULT hr;
1329 int index;
1330 saxlocator *This = impl_from_ISAXAttributes( iface );
1331 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1332 debugstr_w(pLocalName), nLocalName);
1334 hr = ISAXAttributes_getIndexFromName(iface,
1335 pUri, nUri, pLocalName, nLocalName, &index);
1336 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1338 return hr;
1341 static HRESULT WINAPI isaxattributes_getValueFromQName(
1342 ISAXAttributes* iface,
1343 const WCHAR *pQName,
1344 int nQName,
1345 const WCHAR **pValue,
1346 int *nValue)
1348 HRESULT hr;
1349 int index;
1350 saxlocator *This = impl_from_ISAXAttributes( iface );
1351 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1353 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1354 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1356 return hr;
1359 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1361 isaxattributes_QueryInterface,
1362 isaxattributes_AddRef,
1363 isaxattributes_Release,
1364 isaxattributes_getLength,
1365 isaxattributes_getURI,
1366 isaxattributes_getLocalName,
1367 isaxattributes_getQName,
1368 isaxattributes_getName,
1369 isaxattributes_getIndexFromName,
1370 isaxattributes_getIndexFromQName,
1371 isaxattributes_getType,
1372 isaxattributes_getTypeFromName,
1373 isaxattributes_getTypeFromQName,
1374 isaxattributes_getValue,
1375 isaxattributes_getValueFromName,
1376 isaxattributes_getValueFromQName
1379 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1380 so when document has escaped value with '&amp;' it's parsed to '&' and then
1381 escaped to '&#38;'. This function takes care of ampersands only. */
1382 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1384 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1385 WCHAR *dest, *ptrW, *str;
1386 DWORD str_len;
1387 BSTR bstr;
1389 if (!buf)
1390 return NULL;
1392 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1393 if (len != -1) str_len++;
1395 str = heap_alloc(str_len*sizeof(WCHAR));
1396 if (!str) return NULL;
1398 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1399 if (len != -1) str[str_len-1] = 0;
1401 ptrW = str;
1402 while ((dest = strstrW(ptrW, ampescW)))
1404 WCHAR *src;
1406 /* leave first '&' from a reference as a value */
1407 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1408 dest++;
1410 /* move together with null terminator */
1411 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1413 ptrW++;
1416 bstr = SysAllocString(str);
1417 heap_free(str);
1419 return bstr;
1422 static void free_attribute_values(saxlocator *locator)
1424 int i;
1426 for (i = 0; i < locator->nb_attributes; i++)
1428 SysFreeString(locator->attributes[i].szLocalname);
1429 locator->attributes[i].szLocalname = NULL;
1431 SysFreeString(locator->attributes[i].szValue);
1432 locator->attributes[i].szValue = NULL;
1434 SysFreeString(locator->attributes[i].szQName);
1435 locator->attributes[i].szQName = NULL;
1439 static HRESULT SAXAttributes_populate(saxlocator *locator,
1440 int nb_namespaces, const xmlChar **xmlNamespaces,
1441 int nb_attributes, const xmlChar **xmlAttributes)
1443 static const xmlChar xmlns[] = "xmlns";
1444 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1446 struct _attributes *attrs;
1447 int i;
1449 /* skip namespace definitions */
1450 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1451 nb_namespaces = 0;
1453 locator->nb_attributes = nb_namespaces + nb_attributes;
1454 if(locator->nb_attributes > locator->attributesSize)
1456 int new_size = locator->attributesSize * 2;
1457 attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1458 if(!attrs)
1460 free_attribute_values(locator);
1461 locator->nb_attributes = 0;
1462 return E_OUTOFMEMORY;
1464 locator->attributes = attrs;
1465 locator->attributesSize = new_size;
1467 else
1469 attrs = locator->attributes;
1472 for (i = 0; i < nb_namespaces; i++)
1474 SysFreeString(attrs[nb_attributes+i].szLocalname);
1475 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1477 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1479 SysFreeString(attrs[nb_attributes+i].szValue);
1480 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1482 SysFreeString(attrs[nb_attributes+i].szQName);
1483 if(!xmlNamespaces[2*i])
1484 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1485 else
1486 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1489 for (i = 0; i < nb_attributes; i++)
1491 static const xmlChar xmlA[] = "xml";
1493 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1494 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1495 else
1496 /* that's an important feature to keep same uri pointer for every reported attribute */
1497 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1499 SysFreeString(attrs[i].szLocalname);
1500 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1502 SysFreeString(attrs[i].szValue);
1503 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1505 SysFreeString(attrs[i].szQName);
1506 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1509 return S_OK;
1512 /*** LibXML callbacks ***/
1513 static void libxmlStartDocument(void *ctx)
1515 saxlocator *This = ctx;
1516 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1517 HRESULT hr;
1519 if (This->saxreader->version >= MSXML4)
1521 const xmlChar *p = This->pParserCtxt->input->cur-1;
1522 update_position(This, FALSE);
1523 while(p>This->pParserCtxt->input->base && *p!='>')
1525 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1526 This->line--;
1527 p--;
1529 This->column = 0;
1530 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1531 This->column++;
1534 /* store version value, declaration has to contain version attribute */
1535 if (This->pParserCtxt->standalone != -1)
1537 SysFreeString(This->saxreader->xmldecl_version);
1538 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1541 if (saxreader_has_handler(This, SAXContentHandler))
1543 if(This->vbInterface)
1544 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1545 else
1546 hr = ISAXContentHandler_startDocument(handler->handler);
1548 if (sax_callback_failed(This, hr))
1549 format_error_message_from_id(This, hr);
1553 static void libxmlEndDocument(void *ctx)
1555 saxlocator *This = ctx;
1556 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1557 HRESULT hr;
1559 if (This->saxreader->version >= MSXML4) {
1560 update_position(This, FALSE);
1561 if(This->column > 1)
1562 This->line++;
1563 This->column = 0;
1564 } else {
1565 This->column = 0;
1566 This->line = 0;
1569 if(This->ret != S_OK) return;
1571 if (saxreader_has_handler(This, SAXContentHandler))
1573 if(This->vbInterface)
1574 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1575 else
1576 hr = ISAXContentHandler_endDocument(handler->handler);
1578 if (sax_callback_failed(This, hr))
1579 format_error_message_from_id(This, hr);
1583 static void libxmlStartElementNS(
1584 void *ctx,
1585 const xmlChar *localname,
1586 const xmlChar *prefix,
1587 const xmlChar *URI,
1588 int nb_namespaces,
1589 const xmlChar **namespaces,
1590 int nb_attributes,
1591 int nb_defaulted,
1592 const xmlChar **attributes)
1594 saxlocator *This = ctx;
1595 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1596 element_entry *element;
1597 HRESULT hr = S_OK;
1598 BSTR uri;
1600 update_position(This, TRUE);
1601 if(*(This->pParserCtxt->input->cur) == '/')
1602 This->column++;
1603 if(This->saxreader->version < MSXML4)
1604 This->column++;
1606 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1607 push_element_ns(This, element);
1609 if (is_namespaces_enabled(This->saxreader))
1611 int i;
1613 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1615 if (This->vbInterface)
1616 hr = IVBSAXContentHandler_startPrefixMapping(
1617 handler->vbhandler,
1618 &element->ns[i].prefix,
1619 &element->ns[i].uri);
1620 else
1621 hr = ISAXContentHandler_startPrefixMapping(
1622 handler->handler,
1623 element->ns[i].prefix,
1624 SysStringLen(element->ns[i].prefix),
1625 element->ns[i].uri,
1626 SysStringLen(element->ns[i].uri));
1628 if (sax_callback_failed(This, hr))
1630 format_error_message_from_id(This, hr);
1631 return;
1636 uri = find_element_uri(This, URI);
1637 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1638 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1640 BSTR local;
1642 if (is_namespaces_enabled(This->saxreader))
1643 local = element->local;
1644 else
1645 uri = local = NULL;
1647 if (This->vbInterface)
1648 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1649 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1650 else
1651 hr = ISAXContentHandler_startElement(handler->handler,
1652 uri, SysStringLen(uri),
1653 local, SysStringLen(local),
1654 element->qname, SysStringLen(element->qname),
1655 &This->ISAXAttributes_iface);
1657 if (sax_callback_failed(This, hr))
1658 format_error_message_from_id(This, hr);
1662 static void libxmlEndElementNS(
1663 void *ctx,
1664 const xmlChar *localname,
1665 const xmlChar *prefix,
1666 const xmlChar *URI)
1668 saxlocator *This = ctx;
1669 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1670 element_entry *element;
1671 const xmlChar *p;
1672 BSTR uri, local;
1673 HRESULT hr;
1675 update_position(This, FALSE);
1676 p = This->pParserCtxt->input->cur;
1678 if (This->saxreader->version >= MSXML4)
1680 p--;
1681 while(p>This->pParserCtxt->input->base && *p!='>')
1683 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1684 This->line--;
1685 p--;
1688 else if(*(p-1)!='>' || *(p-2)!='/')
1690 p--;
1691 while(p-2>=This->pParserCtxt->input->base
1692 && *(p-2)!='<' && *(p-1)!='/')
1694 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1695 This->line--;
1696 p--;
1699 This->column = 0;
1700 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1701 This->column++;
1703 uri = find_element_uri(This, URI);
1704 element = pop_element_ns(This);
1706 if (!saxreader_has_handler(This, SAXContentHandler))
1708 free_attribute_values(This);
1709 This->nb_attributes = 0;
1710 free_element_entry(element);
1711 return;
1714 if (is_namespaces_enabled(This->saxreader))
1715 local = element->local;
1716 else
1717 uri = local = NULL;
1719 if (This->vbInterface)
1720 hr = IVBSAXContentHandler_endElement(
1721 handler->vbhandler,
1722 &uri, &local, &element->qname);
1723 else
1724 hr = ISAXContentHandler_endElement(
1725 handler->handler,
1726 uri, SysStringLen(uri),
1727 local, SysStringLen(local),
1728 element->qname, SysStringLen(element->qname));
1730 free_attribute_values(This);
1731 This->nb_attributes = 0;
1733 if (sax_callback_failed(This, hr))
1735 format_error_message_from_id(This, hr);
1736 free_element_entry(element);
1737 return;
1740 if (is_namespaces_enabled(This->saxreader))
1742 int i = -1;
1743 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1745 if (This->vbInterface)
1746 hr = IVBSAXContentHandler_endPrefixMapping(
1747 handler->vbhandler, &element->ns[i].prefix);
1748 else
1749 hr = ISAXContentHandler_endPrefixMapping(
1750 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1752 if (sax_callback_failed(This, hr)) break;
1755 if (sax_callback_failed(This, hr))
1756 format_error_message_from_id(This, hr);
1759 free_element_entry(element);
1762 static void libxmlCharacters(
1763 void *ctx,
1764 const xmlChar *ch,
1765 int len)
1767 saxlocator *This = ctx;
1768 BSTR Chars;
1769 HRESULT hr;
1770 xmlChar *cur, *end;
1771 BOOL lastEvent = FALSE;
1773 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1775 update_position(This, FALSE);
1776 cur = (xmlChar*)This->pParserCtxt->input->cur;
1777 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1779 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1780 This->line--;
1781 cur--;
1783 This->column = 1;
1784 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1785 This->column++;
1787 cur = (xmlChar*)ch;
1788 if(*(ch-1)=='\r') cur--;
1789 end = cur;
1791 while(1)
1793 while(end-ch<len && *end!='\r') end++;
1794 if(end-ch==len)
1796 lastEvent = TRUE;
1798 else
1800 *end = '\n';
1801 end++;
1804 if (This->saxreader->version >= MSXML4)
1806 xmlChar *p;
1808 for(p=cur; p!=end; p++)
1810 if(*p=='\n')
1812 This->line++;
1813 This->column = 1;
1815 else
1817 This->column++;
1821 if(!lastEvent)
1822 This->column = 0;
1825 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1826 hr = saxreader_saxcharacters(This, Chars);
1828 if (sax_callback_failed(This, hr))
1830 format_error_message_from_id(This, hr);
1831 return;
1834 if (This->saxreader->version < MSXML4)
1835 This->column += end-cur;
1837 if(lastEvent)
1838 break;
1840 *(end-1) = '\r';
1841 if(*end == '\n')
1843 end++;
1844 This->column++;
1846 cur = end;
1848 if(end-ch == len) break;
1852 static void libxmlSetDocumentLocator(
1853 void *ctx,
1854 xmlSAXLocatorPtr loc)
1856 saxlocator *This = ctx;
1857 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1858 HRESULT hr = S_OK;
1860 if (saxreader_has_handler(This, SAXContentHandler))
1862 if(This->vbInterface)
1863 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1864 &This->IVBSAXLocator_iface);
1865 else
1866 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1869 if(FAILED(hr))
1870 format_error_message_from_id(This, hr);
1873 static void libxmlComment(void *ctx, const xmlChar *value)
1875 saxlocator *This = ctx;
1876 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1877 BSTR bValue;
1878 HRESULT hr;
1879 const xmlChar *p = This->pParserCtxt->input->cur;
1881 update_position(This, FALSE);
1882 while(p-4>=This->pParserCtxt->input->base
1883 && memcmp(p-4, "<!--", sizeof(char[4])))
1885 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1886 This->line--;
1887 p--;
1890 This->column = 0;
1891 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1892 This->column++;
1894 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1896 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1898 if (This->vbInterface)
1899 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1900 else
1901 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1903 if(FAILED(hr))
1904 format_error_message_from_id(This, hr);
1907 static void libxmlFatalError(void *ctx, const char *msg, ...)
1909 saxlocator *This = ctx;
1910 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1911 char message[1024];
1912 WCHAR *error;
1913 DWORD len;
1914 va_list args;
1916 if(This->ret != S_OK) {
1917 xmlStopParser(This->pParserCtxt);
1918 return;
1921 va_start(args, msg);
1922 vsprintf(message, msg, args);
1923 va_end(args);
1925 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1926 error = heap_alloc(sizeof(WCHAR)*len);
1927 if(error)
1929 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1930 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1933 if (!saxreader_has_handler(This, SAXErrorHandler))
1935 xmlStopParser(This->pParserCtxt);
1936 This->ret = E_FAIL;
1937 heap_free(error);
1938 return;
1941 FIXME("Error handling is not compatible.\n");
1943 if(This->vbInterface)
1945 BSTR bstrError = SysAllocString(error);
1946 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1947 &bstrError, E_FAIL);
1948 SysFreeString(bstrError);
1950 else
1951 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1953 heap_free(error);
1955 xmlStopParser(This->pParserCtxt);
1956 This->ret = E_FAIL;
1959 /* The only reason this helper exists is that CDATA section are reported by chunks,
1960 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1962 This helper should be called for substring with trailing newlines.
1964 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1966 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1967 WCHAR *ptr;
1969 ptr = bstr + len - 1;
1970 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1971 ptr--;
1973 while (*++ptr)
1975 /* replace returns as:
1977 - "\r<char>" -> "\n<char>"
1978 - "\r\r" -> "\r"
1979 - "\r\n" -> "\n"
1981 if (*ptr == '\r')
1983 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1985 /* shift tail */
1986 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1988 else
1989 *ptr = '\n';
1993 ret = SysAllocStringLen(bstr, len);
1994 SysFreeString(bstr);
1995 return ret;
1998 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2000 const xmlChar *start, *end;
2001 saxlocator *locator = ctx;
2002 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2003 HRESULT hr = S_OK;
2004 BSTR chars;
2005 int i;
2007 update_position(locator, FALSE);
2008 if (saxreader_has_handler(locator, SAXLexicalHandler))
2010 if (locator->vbInterface)
2011 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2012 else
2013 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2016 if(FAILED(hr))
2018 format_error_message_from_id(locator, hr);
2019 return;
2022 start = value;
2023 end = NULL;
2024 i = 0;
2026 while (i < len)
2028 /* scan for newlines */
2029 if (value[i] == '\r' || value[i] == '\n')
2031 /* skip newlines/linefeeds */
2032 while (i < len)
2034 if (value[i] != '\r' && value[i] != '\n') break;
2035 i++;
2037 end = &value[i];
2039 /* report */
2040 chars = saxreader_get_cdata_chunk(start, end-start);
2041 TRACE("(chunk %s)\n", debugstr_w(chars));
2042 hr = saxreader_saxcharacters(locator, chars);
2043 SysFreeString(chars);
2045 start = &value[i];
2046 end = NULL;
2048 i++;
2049 locator->column++;
2052 /* no newline chars (or last chunk) report as a whole */
2053 if (!end && start == value)
2055 /* report */
2056 chars = bstr_from_xmlCharN(start, len-(start-value));
2057 TRACE("(%s)\n", debugstr_w(chars));
2058 hr = saxreader_saxcharacters(locator, chars);
2059 SysFreeString(chars);
2062 if (saxreader_has_handler(locator, SAXLexicalHandler))
2064 if (locator->vbInterface)
2065 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2066 else
2067 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2070 if(FAILED(hr))
2071 format_error_message_from_id(locator, hr);
2074 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2076 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2077 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2080 /*** IVBSAXLocator interface ***/
2081 /*** IUnknown methods ***/
2082 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2084 saxlocator *This = impl_from_IVBSAXLocator( iface );
2086 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2088 *ppvObject = NULL;
2090 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2091 IsEqualGUID( riid, &IID_IDispatch) ||
2092 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2094 *ppvObject = iface;
2096 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2098 *ppvObject = &This->IVBSAXAttributes_iface;
2100 else
2102 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2103 return E_NOINTERFACE;
2106 IVBSAXLocator_AddRef( iface );
2108 return S_OK;
2111 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2113 saxlocator *This = impl_from_IVBSAXLocator( iface );
2114 TRACE("%p\n", This );
2115 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2118 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2120 saxlocator *This = impl_from_IVBSAXLocator( iface );
2121 return ISAXLocator_Release(&This->ISAXLocator_iface);
2124 /*** IDispatch methods ***/
2125 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2127 saxlocator *This = impl_from_IVBSAXLocator( iface );
2129 TRACE("(%p)->(%p)\n", This, pctinfo);
2131 *pctinfo = 1;
2133 return S_OK;
2136 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2137 IVBSAXLocator *iface,
2138 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2140 saxlocator *This = impl_from_IVBSAXLocator( iface );
2142 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2144 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2147 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2148 IVBSAXLocator *iface,
2149 REFIID riid,
2150 LPOLESTR* rgszNames,
2151 UINT cNames,
2152 LCID lcid,
2153 DISPID* rgDispId)
2155 saxlocator *This = impl_from_IVBSAXLocator( iface );
2156 ITypeInfo *typeinfo;
2157 HRESULT hr;
2159 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2160 lcid, rgDispId);
2162 if(!rgszNames || cNames == 0 || !rgDispId)
2163 return E_INVALIDARG;
2165 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2166 if(SUCCEEDED(hr))
2168 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2169 ITypeInfo_Release(typeinfo);
2172 return hr;
2175 static HRESULT WINAPI ivbsaxlocator_Invoke(
2176 IVBSAXLocator *iface,
2177 DISPID dispIdMember,
2178 REFIID riid,
2179 LCID lcid,
2180 WORD wFlags,
2181 DISPPARAMS* pDispParams,
2182 VARIANT* pVarResult,
2183 EXCEPINFO* pExcepInfo,
2184 UINT* puArgErr)
2186 saxlocator *This = impl_from_IVBSAXLocator( iface );
2187 ITypeInfo *typeinfo;
2188 HRESULT hr;
2190 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2191 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2193 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2194 if(SUCCEEDED(hr))
2196 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2197 pDispParams, pVarResult, pExcepInfo, puArgErr);
2198 ITypeInfo_Release(typeinfo);
2201 return hr;
2204 /*** IVBSAXLocator methods ***/
2205 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2206 IVBSAXLocator* iface,
2207 int *pnColumn)
2209 saxlocator *This = impl_from_IVBSAXLocator( iface );
2210 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2213 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2214 IVBSAXLocator* iface,
2215 int *pnLine)
2217 saxlocator *This = impl_from_IVBSAXLocator( iface );
2218 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2221 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2223 saxlocator *This = impl_from_IVBSAXLocator( iface );
2224 const WCHAR *publicidW;
2225 HRESULT hr;
2227 TRACE("(%p)->(%p)\n", This, ret);
2229 if (!ret)
2230 return E_POINTER;
2232 *ret = NULL;
2233 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2234 if (FAILED(hr))
2235 return hr;
2237 return return_bstr(publicidW, ret);
2240 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2242 saxlocator *This = impl_from_IVBSAXLocator( iface );
2243 const WCHAR *systemidW;
2244 HRESULT hr;
2246 TRACE("(%p)->(%p)\n", This, ret);
2248 if (!ret)
2249 return E_POINTER;
2251 *ret = NULL;
2252 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2253 if (FAILED(hr))
2254 return hr;
2256 return return_bstr(systemidW, ret);
2259 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2261 ivbsaxlocator_QueryInterface,
2262 ivbsaxlocator_AddRef,
2263 ivbsaxlocator_Release,
2264 ivbsaxlocator_GetTypeInfoCount,
2265 ivbsaxlocator_GetTypeInfo,
2266 ivbsaxlocator_GetIDsOfNames,
2267 ivbsaxlocator_Invoke,
2268 ivbsaxlocator_get_columnNumber,
2269 ivbsaxlocator_get_lineNumber,
2270 ivbsaxlocator_get_publicId,
2271 ivbsaxlocator_get_systemId
2274 /*** ISAXLocator interface ***/
2275 /*** IUnknown methods ***/
2276 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2278 saxlocator *This = impl_from_ISAXLocator( iface );
2280 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2282 *ppvObject = NULL;
2284 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2285 IsEqualGUID( riid, &IID_ISAXLocator ))
2287 *ppvObject = iface;
2289 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2291 *ppvObject = &This->ISAXAttributes_iface;
2293 else
2295 WARN("interface %s not implemented\n", debugstr_guid(riid));
2296 return E_NOINTERFACE;
2299 ISAXLocator_AddRef( iface );
2301 return S_OK;
2304 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2306 saxlocator *This = impl_from_ISAXLocator( iface );
2307 ULONG ref = InterlockedIncrement( &This->ref );
2308 TRACE("(%p)->(%d)\n", This, ref);
2309 return ref;
2312 static ULONG WINAPI isaxlocator_Release(
2313 ISAXLocator* iface)
2315 saxlocator *This = impl_from_ISAXLocator( iface );
2316 LONG ref = InterlockedDecrement( &This->ref );
2318 TRACE("(%p)->(%d)\n", This, ref );
2320 if (ref == 0)
2322 element_entry *element, *element2;
2323 int index;
2325 SysFreeString(This->publicId);
2326 SysFreeString(This->systemId);
2327 SysFreeString(This->namespaceUri);
2329 for(index=0; index<This->attributesSize; index++)
2331 SysFreeString(This->attributes[index].szLocalname);
2332 SysFreeString(This->attributes[index].szValue);
2333 SysFreeString(This->attributes[index].szQName);
2335 heap_free(This->attributes);
2337 /* element stack */
2338 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2340 list_remove(&element->entry);
2341 free_element_entry(element);
2344 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2345 heap_free( This );
2348 return ref;
2351 /*** ISAXLocator methods ***/
2352 static HRESULT WINAPI isaxlocator_getColumnNumber(
2353 ISAXLocator* iface,
2354 int *pnColumn)
2356 saxlocator *This = impl_from_ISAXLocator( iface );
2358 *pnColumn = This->column;
2359 return S_OK;
2362 static HRESULT WINAPI isaxlocator_getLineNumber(
2363 ISAXLocator* iface,
2364 int *pnLine)
2366 saxlocator *This = impl_from_ISAXLocator( iface );
2368 *pnLine = This->line;
2369 return S_OK;
2372 static HRESULT WINAPI isaxlocator_getPublicId(
2373 ISAXLocator* iface,
2374 const WCHAR ** ppwchPublicId)
2376 BSTR publicId;
2377 saxlocator *This = impl_from_ISAXLocator( iface );
2379 SysFreeString(This->publicId);
2381 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2382 if(SysStringLen(publicId))
2383 This->publicId = publicId;
2384 else
2386 SysFreeString(publicId);
2387 This->publicId = NULL;
2390 *ppwchPublicId = This->publicId;
2391 return S_OK;
2394 static HRESULT WINAPI isaxlocator_getSystemId(
2395 ISAXLocator* iface,
2396 const WCHAR ** ppwchSystemId)
2398 BSTR systemId;
2399 saxlocator *This = impl_from_ISAXLocator( iface );
2401 SysFreeString(This->systemId);
2403 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2404 if(SysStringLen(systemId))
2405 This->systemId = systemId;
2406 else
2408 SysFreeString(systemId);
2409 This->systemId = NULL;
2412 *ppwchSystemId = This->systemId;
2413 return S_OK;
2416 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2418 isaxlocator_QueryInterface,
2419 isaxlocator_AddRef,
2420 isaxlocator_Release,
2421 isaxlocator_getColumnNumber,
2422 isaxlocator_getLineNumber,
2423 isaxlocator_getPublicId,
2424 isaxlocator_getSystemId
2427 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2429 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2430 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2432 saxlocator *locator;
2434 locator = heap_alloc( sizeof (*locator) );
2435 if( !locator )
2436 return E_OUTOFMEMORY;
2438 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2439 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2440 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2441 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2442 locator->ref = 1;
2443 locator->vbInterface = vbInterface;
2445 locator->saxreader = reader;
2446 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2448 locator->pParserCtxt = NULL;
2449 locator->publicId = NULL;
2450 locator->systemId = NULL;
2451 locator->line = reader->version < MSXML4 ? 0 : 1;
2452 locator->column = 0;
2453 locator->ret = S_OK;
2454 if (locator->saxreader->version >= MSXML6)
2455 locator->namespaceUri = SysAllocString(w3xmlns);
2456 else
2457 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2458 if(!locator->namespaceUri)
2460 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2461 heap_free(locator);
2462 return E_OUTOFMEMORY;
2465 locator->attributesSize = 8;
2466 locator->nb_attributes = 0;
2467 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attributesSize);
2468 if(!locator->attributes)
2470 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2471 SysFreeString(locator->namespaceUri);
2472 heap_free(locator);
2473 return E_OUTOFMEMORY;
2476 list_init(&locator->elements);
2478 *ppsaxlocator = locator;
2480 TRACE("returning %p\n", *ppsaxlocator);
2482 return S_OK;
2485 /*** SAXXMLReader internal functions ***/
2486 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2488 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2489 xmlChar *enc_name = NULL;
2490 saxlocator *locator;
2491 HRESULT hr;
2493 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2495 hr = SAXLocator_create(This, &locator, vbInterface);
2496 if (FAILED(hr))
2497 return hr;
2499 if (size >= 4)
2501 const unsigned char *buff = (unsigned char*)buffer;
2503 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2504 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2505 TRACE("detected encoding: %s\n", enc_name);
2506 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2507 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2508 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2510 buffer += 3;
2511 size -= 3;
2515 /* if libxml2 detection failed try to guess */
2516 if (encoding == XML_CHAR_ENCODING_NONE)
2518 const WCHAR *ptr = (WCHAR*)buffer;
2519 /* xml declaration with possibly specfied encoding will be still handled by parser */
2520 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2522 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2523 encoding = XML_CHAR_ENCODING_UTF16LE;
2526 else if (encoding == XML_CHAR_ENCODING_UTF8)
2527 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2528 else
2529 enc_name = NULL;
2531 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2532 if (!locator->pParserCtxt)
2534 ISAXLocator_Release(&locator->ISAXLocator_iface);
2535 return E_FAIL;
2538 if (enc_name)
2540 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2541 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2542 TRACE("switching to %s\n", enc_name);
2543 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2547 xmlFree(locator->pParserCtxt->sax);
2548 locator->pParserCtxt->sax = &locator->saxreader->sax;
2549 locator->pParserCtxt->userData = locator;
2551 This->isParsing = TRUE;
2552 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2553 hr = E_FAIL;
2554 else
2555 hr = locator->ret;
2556 This->isParsing = FALSE;
2558 if(locator->pParserCtxt)
2560 locator->pParserCtxt->sax = NULL;
2561 xmlFreeParserCtxt(locator->pParserCtxt);
2562 locator->pParserCtxt = NULL;
2565 ISAXLocator_Release(&locator->ISAXLocator_iface);
2566 return hr;
2569 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2571 saxlocator *locator;
2572 HRESULT hr;
2573 ULONG dataRead;
2574 char data[2048];
2575 int ret;
2577 dataRead = 0;
2578 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2579 if(FAILED(hr)) return hr;
2581 hr = SAXLocator_create(This, &locator, vbInterface);
2582 if(FAILED(hr)) return hr;
2584 locator->pParserCtxt = xmlCreatePushParserCtxt(
2585 &locator->saxreader->sax, locator,
2586 data, dataRead, NULL);
2587 if(!locator->pParserCtxt)
2589 ISAXLocator_Release(&locator->ISAXLocator_iface);
2590 return E_FAIL;
2593 This->isParsing = TRUE;
2595 do {
2596 dataRead = 0;
2597 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2598 if (FAILED(hr) || !dataRead) break;
2600 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2601 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2602 }while(hr == S_OK);
2604 if(SUCCEEDED(hr))
2606 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2607 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2611 This->isParsing = FALSE;
2613 xmlFreeParserCtxt(locator->pParserCtxt);
2614 locator->pParserCtxt = NULL;
2615 ISAXLocator_Release(&locator->ISAXLocator_iface);
2616 return hr;
2619 static HRESULT internal_parse(
2620 saxreader* This,
2621 VARIANT varInput,
2622 BOOL vbInterface)
2624 HRESULT hr;
2626 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2628 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2629 free_bstr_pool(&This->pool);
2631 switch(V_VT(&varInput))
2633 case VT_BSTR:
2634 case VT_BSTR|VT_BYREF:
2636 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2637 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2638 break;
2640 case VT_ARRAY|VT_UI1: {
2641 void *pSAData;
2642 LONG lBound, uBound;
2643 ULONG dataRead;
2645 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2646 if(hr != S_OK) break;
2647 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2648 if(hr != S_OK) break;
2649 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2650 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2651 if(hr != S_OK) break;
2652 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2653 SafeArrayUnaccessData(V_ARRAY(&varInput));
2654 break;
2656 case VT_UNKNOWN:
2657 case VT_DISPATCH: {
2658 IPersistStream *persistStream;
2659 ISequentialStream *stream = NULL;
2660 IXMLDOMDocument *xmlDoc;
2662 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2663 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2665 BSTR bstrData;
2667 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2668 hr = internal_parseBuffer(This, (const char*)bstrData,
2669 SysStringByteLen(bstrData), vbInterface);
2670 IXMLDOMDocument_Release(xmlDoc);
2671 SysFreeString(bstrData);
2672 break;
2675 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2676 &IID_IPersistStream, (void**)&persistStream) == S_OK)
2678 IStream *stream_copy;
2680 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy);
2681 if(hr != S_OK)
2683 IPersistStream_Release(persistStream);
2684 return hr;
2687 hr = IPersistStream_Save(persistStream, stream_copy, TRUE);
2688 IPersistStream_Release(persistStream);
2689 if(hr == S_OK)
2690 IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream);
2692 IStream_Release(stream_copy);
2695 /* try base interface first */
2696 if(!stream)
2698 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2699 if (!stream)
2700 /* this should never happen if IStream is implemented properly, but just in case */
2701 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2704 if(stream)
2706 hr = internal_parseStream(This, stream, vbInterface);
2707 ISequentialStream_Release(stream);
2709 else
2711 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2712 hr = E_INVALIDARG;
2715 break;
2717 default:
2718 WARN("vt %d not implemented\n", V_VT(&varInput));
2719 hr = E_INVALIDARG;
2722 return hr;
2725 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2727 saxreader *This = obj;
2729 return internal_parseBuffer(This, ptr, len, TRUE);
2732 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2734 saxreader *This = obj;
2736 return internal_parseBuffer(This, ptr, len, FALSE);
2739 static HRESULT internal_parseURL(
2740 saxreader* This,
2741 const WCHAR *url,
2742 BOOL vbInterface)
2744 IMoniker *mon;
2745 bsc_t *bsc;
2746 HRESULT hr;
2748 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2750 hr = create_moniker_from_url(url, &mon);
2751 if(FAILED(hr))
2752 return hr;
2754 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2755 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2756 IMoniker_Release(mon);
2758 if(FAILED(hr))
2759 return hr;
2761 return detach_bsc(bsc);
2764 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2766 const IID *riid;
2768 if (V_VT(v) == VT_EMPTY)
2769 return saxreader_put_handler(This, type, NULL, vb);
2771 switch (type)
2773 case SAXDeclHandler:
2774 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2775 break;
2776 case SAXLexicalHandler:
2777 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2778 break;
2779 default:
2780 ERR("wrong handler type %d\n", type);
2781 return E_FAIL;
2784 switch (V_VT(v))
2786 case VT_DISPATCH:
2787 case VT_UNKNOWN:
2789 IUnknown *handler = NULL;
2791 if (V_UNKNOWN(v))
2793 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2794 if (FAILED(hr)) return hr;
2797 saxreader_put_handler(This, type, handler, vb);
2798 if (handler) IUnknown_Release(handler);
2799 break;
2801 default:
2802 ERR("value type %d not supported\n", V_VT(v));
2803 return E_INVALIDARG;
2806 return S_OK;
2809 static HRESULT internal_putProperty(
2810 saxreader* This,
2811 const WCHAR *prop,
2812 VARIANT value,
2813 BOOL vbInterface)
2815 VARIANT *v;
2817 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2819 if (This->isParsing) return E_FAIL;
2821 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2822 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2823 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2825 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2826 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2828 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2830 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2831 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2832 return E_NOTIMPL;
2835 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2837 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2838 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2839 return E_NOTIMPL;
2842 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2844 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2845 return E_NOTIMPL;
2847 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2848 return E_FAIL;
2850 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2851 return E_NOTIMPL;
2853 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2854 return E_NOTIMPL;
2856 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2857 return E_FAIL;
2859 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2860 return E_FAIL;
2862 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2863 return E_FAIL;
2865 return E_INVALIDARG;
2868 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2870 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2872 if (!value) return E_POINTER;
2874 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2876 V_VT(value) = VT_UNKNOWN;
2877 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2878 return S_OK;
2881 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2883 V_VT(value) = VT_UNKNOWN;
2884 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2885 return S_OK;
2888 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2890 V_VT(value) = VT_BSTR;
2891 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2892 return S_OK;
2895 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2897 return E_NOTIMPL;
2900 /*** IVBSAXXMLReader interface ***/
2901 /*** IUnknown methods ***/
2902 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2904 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2906 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2908 *ppvObject = NULL;
2910 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2911 IsEqualGUID( riid, &IID_IDispatch ) ||
2912 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2914 *ppvObject = iface;
2916 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2918 *ppvObject = &This->ISAXXMLReader_iface;
2920 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2922 return *ppvObject ? S_OK : E_NOINTERFACE;
2924 else
2926 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2927 return E_NOINTERFACE;
2930 IVBSAXXMLReader_AddRef( iface );
2932 return S_OK;
2935 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2937 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2938 TRACE("%p\n", This );
2939 return InterlockedIncrement( &This->ref );
2942 static ULONG WINAPI saxxmlreader_Release(
2943 IVBSAXXMLReader* iface)
2945 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2946 LONG ref;
2948 TRACE("%p\n", This );
2950 ref = InterlockedDecrement( &This->ref );
2951 if ( ref == 0 )
2953 int i;
2955 for (i = 0; i < SAXHandler_Last; i++)
2957 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2959 if (saxiface->handler)
2960 IUnknown_Release(saxiface->handler);
2962 if (saxiface->vbhandler)
2963 IUnknown_Release(saxiface->vbhandler);
2966 SysFreeString(This->xmldecl_version);
2967 free_bstr_pool(&This->pool);
2969 heap_free( This );
2972 return ref;
2974 /*** IDispatch ***/
2975 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2977 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2978 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2981 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2982 IVBSAXXMLReader *iface,
2983 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2985 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2986 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2987 iTInfo, lcid, ppTInfo);
2990 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2991 IVBSAXXMLReader *iface,
2992 REFIID riid,
2993 LPOLESTR* rgszNames,
2994 UINT cNames,
2995 LCID lcid,
2996 DISPID* rgDispId)
2998 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2999 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
3000 riid, rgszNames, cNames, lcid, rgDispId);
3003 static HRESULT WINAPI saxxmlreader_Invoke(
3004 IVBSAXXMLReader *iface,
3005 DISPID dispIdMember,
3006 REFIID riid,
3007 LCID lcid,
3008 WORD wFlags,
3009 DISPPARAMS* pDispParams,
3010 VARIANT* pVarResult,
3011 EXCEPINFO* pExcepInfo,
3012 UINT* puArgErr)
3014 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3015 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3016 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3019 /*** IVBSAXXMLReader methods ***/
3020 static HRESULT WINAPI saxxmlreader_getFeature(
3021 IVBSAXXMLReader* iface,
3022 BSTR feature_name,
3023 VARIANT_BOOL *value)
3025 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3026 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3029 static HRESULT WINAPI saxxmlreader_putFeature(
3030 IVBSAXXMLReader* iface,
3031 BSTR feature_name,
3032 VARIANT_BOOL value)
3034 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3035 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3038 static HRESULT WINAPI saxxmlreader_getProperty(
3039 IVBSAXXMLReader* iface,
3040 BSTR prop,
3041 VARIANT *value)
3043 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3044 return internal_getProperty(This, prop, value, TRUE);
3047 static HRESULT WINAPI saxxmlreader_putProperty(
3048 IVBSAXXMLReader* iface,
3049 BSTR pProp,
3050 VARIANT value)
3052 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3053 return internal_putProperty(This, pProp, value, TRUE);
3056 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3057 IVBSAXXMLReader* iface,
3058 IVBSAXEntityResolver **resolver)
3060 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3061 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3064 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3065 IVBSAXXMLReader* iface,
3066 IVBSAXEntityResolver *resolver)
3068 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3069 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3072 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3073 IVBSAXXMLReader* iface,
3074 IVBSAXContentHandler **handler)
3076 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3077 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3080 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3081 IVBSAXXMLReader* iface,
3082 IVBSAXContentHandler *handler)
3084 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3085 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3088 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3089 IVBSAXXMLReader* iface,
3090 IVBSAXDTDHandler **handler)
3092 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3093 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3096 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3097 IVBSAXXMLReader* iface,
3098 IVBSAXDTDHandler *handler)
3100 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3101 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3104 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3105 IVBSAXXMLReader* iface,
3106 IVBSAXErrorHandler **handler)
3108 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3109 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3112 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3113 IVBSAXXMLReader* iface,
3114 IVBSAXErrorHandler *handler)
3116 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3117 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3120 static HRESULT WINAPI saxxmlreader_get_baseURL(
3121 IVBSAXXMLReader* iface,
3122 BSTR *pBaseUrl)
3124 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3126 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3127 return E_NOTIMPL;
3130 static HRESULT WINAPI saxxmlreader_put_baseURL(
3131 IVBSAXXMLReader* iface,
3132 BSTR pBaseUrl)
3134 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3135 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3138 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3139 IVBSAXXMLReader* iface,
3140 BSTR *pSecureBaseUrl)
3142 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3144 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3145 return E_NOTIMPL;
3148 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3149 IVBSAXXMLReader* iface,
3150 BSTR secureBaseUrl)
3152 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3153 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3156 static HRESULT WINAPI saxxmlreader_parse(
3157 IVBSAXXMLReader* iface,
3158 VARIANT varInput)
3160 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3161 return internal_parse(This, varInput, TRUE);
3164 static HRESULT WINAPI saxxmlreader_parseURL(
3165 IVBSAXXMLReader* iface,
3166 BSTR url)
3168 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3169 return internal_parseURL(This, url, TRUE);
3172 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3174 saxxmlreader_QueryInterface,
3175 saxxmlreader_AddRef,
3176 saxxmlreader_Release,
3177 saxxmlreader_GetTypeInfoCount,
3178 saxxmlreader_GetTypeInfo,
3179 saxxmlreader_GetIDsOfNames,
3180 saxxmlreader_Invoke,
3181 saxxmlreader_getFeature,
3182 saxxmlreader_putFeature,
3183 saxxmlreader_getProperty,
3184 saxxmlreader_putProperty,
3185 saxxmlreader_get_entityResolver,
3186 saxxmlreader_put_entityResolver,
3187 saxxmlreader_get_contentHandler,
3188 saxxmlreader_put_contentHandler,
3189 saxxmlreader_get_dtdHandler,
3190 saxxmlreader_put_dtdHandler,
3191 saxxmlreader_get_errorHandler,
3192 saxxmlreader_put_errorHandler,
3193 saxxmlreader_get_baseURL,
3194 saxxmlreader_put_baseURL,
3195 saxxmlreader_get_secureBaseURL,
3196 saxxmlreader_put_secureBaseURL,
3197 saxxmlreader_parse,
3198 saxxmlreader_parseURL
3201 /*** ISAXXMLReader interface ***/
3202 /*** IUnknown methods ***/
3203 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3205 saxreader *This = impl_from_ISAXXMLReader( iface );
3206 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3209 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3211 saxreader *This = impl_from_ISAXXMLReader( iface );
3212 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3215 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3217 saxreader *This = impl_from_ISAXXMLReader( iface );
3218 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3221 /*** ISAXXMLReader methods ***/
3222 static HRESULT WINAPI isaxxmlreader_getFeature(
3223 ISAXXMLReader* iface,
3224 const WCHAR *feature_name,
3225 VARIANT_BOOL *value)
3227 saxreader *This = impl_from_ISAXXMLReader( iface );
3228 saxreader_feature feature;
3230 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3232 feature = get_saxreader_feature(feature_name);
3233 if (feature == Namespaces || feature == NamespacePrefixes)
3234 return get_feature_value(This, feature, value);
3236 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3237 return E_NOTIMPL;
3240 static HRESULT WINAPI isaxxmlreader_putFeature(
3241 ISAXXMLReader* iface,
3242 const WCHAR *feature_name,
3243 VARIANT_BOOL value)
3245 saxreader *This = impl_from_ISAXXMLReader( iface );
3246 saxreader_feature feature;
3248 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3250 feature = get_saxreader_feature(feature_name);
3252 /* accepted cases */
3253 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
3254 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
3255 feature == Namespaces ||
3256 feature == NamespacePrefixes)
3258 return set_feature_value(This, feature, value);
3261 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
3263 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3264 return set_feature_value(This, feature, value);
3267 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3268 return E_NOTIMPL;
3271 static HRESULT WINAPI isaxxmlreader_getProperty(
3272 ISAXXMLReader* iface,
3273 const WCHAR *prop,
3274 VARIANT *value)
3276 saxreader *This = impl_from_ISAXXMLReader( iface );
3277 return internal_getProperty(This, prop, value, FALSE);
3280 static HRESULT WINAPI isaxxmlreader_putProperty(
3281 ISAXXMLReader* iface,
3282 const WCHAR *pProp,
3283 VARIANT value)
3285 saxreader *This = impl_from_ISAXXMLReader( iface );
3286 return internal_putProperty(This, pProp, value, FALSE);
3289 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3290 ISAXXMLReader* iface,
3291 ISAXEntityResolver **resolver)
3293 saxreader *This = impl_from_ISAXXMLReader( iface );
3294 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3297 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3298 ISAXXMLReader* iface,
3299 ISAXEntityResolver *resolver)
3301 saxreader *This = impl_from_ISAXXMLReader( iface );
3302 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3305 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3306 ISAXXMLReader* iface,
3307 ISAXContentHandler **handler)
3309 saxreader *This = impl_from_ISAXXMLReader( iface );
3310 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3313 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3314 ISAXXMLReader* iface,
3315 ISAXContentHandler *handler)
3317 saxreader *This = impl_from_ISAXXMLReader( iface );
3318 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3321 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3322 ISAXXMLReader* iface,
3323 ISAXDTDHandler **handler)
3325 saxreader *This = impl_from_ISAXXMLReader( iface );
3326 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3329 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3330 ISAXXMLReader* iface,
3331 ISAXDTDHandler *handler)
3333 saxreader *This = impl_from_ISAXXMLReader( iface );
3334 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3337 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3338 ISAXXMLReader* iface,
3339 ISAXErrorHandler **handler)
3341 saxreader *This = impl_from_ISAXXMLReader( iface );
3342 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3345 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3347 saxreader *This = impl_from_ISAXXMLReader( iface );
3348 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3351 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3352 ISAXXMLReader* iface,
3353 const WCHAR **base_url)
3355 saxreader *This = impl_from_ISAXXMLReader( iface );
3357 FIXME("(%p)->(%p) stub\n", This, base_url);
3358 return E_NOTIMPL;
3361 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3362 ISAXXMLReader* iface,
3363 const WCHAR *pBaseUrl)
3365 saxreader *This = impl_from_ISAXXMLReader( iface );
3367 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3368 return E_NOTIMPL;
3371 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3372 ISAXXMLReader* iface,
3373 const WCHAR **pSecureBaseUrl)
3375 saxreader *This = impl_from_ISAXXMLReader( iface );
3376 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3377 return E_NOTIMPL;
3380 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3381 ISAXXMLReader* iface,
3382 const WCHAR *secureBaseUrl)
3384 saxreader *This = impl_from_ISAXXMLReader( iface );
3386 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3387 return E_NOTIMPL;
3390 static HRESULT WINAPI isaxxmlreader_parse(
3391 ISAXXMLReader* iface,
3392 VARIANT varInput)
3394 saxreader *This = impl_from_ISAXXMLReader( iface );
3395 return internal_parse(This, varInput, FALSE);
3398 static HRESULT WINAPI isaxxmlreader_parseURL(
3399 ISAXXMLReader* iface,
3400 const WCHAR *url)
3402 saxreader *This = impl_from_ISAXXMLReader( iface );
3403 return internal_parseURL(This, url, FALSE);
3406 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3408 isaxxmlreader_QueryInterface,
3409 isaxxmlreader_AddRef,
3410 isaxxmlreader_Release,
3411 isaxxmlreader_getFeature,
3412 isaxxmlreader_putFeature,
3413 isaxxmlreader_getProperty,
3414 isaxxmlreader_putProperty,
3415 isaxxmlreader_getEntityResolver,
3416 isaxxmlreader_putEntityResolver,
3417 isaxxmlreader_getContentHandler,
3418 isaxxmlreader_putContentHandler,
3419 isaxxmlreader_getDTDHandler,
3420 isaxxmlreader_putDTDHandler,
3421 isaxxmlreader_getErrorHandler,
3422 isaxxmlreader_putErrorHandler,
3423 isaxxmlreader_getBaseURL,
3424 isaxxmlreader_putBaseURL,
3425 isaxxmlreader_getSecureBaseURL,
3426 isaxxmlreader_putSecureBaseURL,
3427 isaxxmlreader_parse,
3428 isaxxmlreader_parseURL
3431 static const tid_t saxreader_iface_tids[] = {
3432 IVBSAXXMLReader_tid,
3435 static dispex_static_data_t saxreader_dispex = {
3436 NULL,
3437 IVBSAXXMLReader_tid,
3438 NULL,
3439 saxreader_iface_tids
3442 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3444 saxreader *reader;
3446 TRACE("(%p)\n", ppObj);
3448 reader = heap_alloc( sizeof (*reader) );
3449 if( !reader )
3450 return E_OUTOFMEMORY;
3452 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3453 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3454 reader->ref = 1;
3455 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3456 reader->isParsing = FALSE;
3457 reader->xmldecl_version = NULL;
3458 reader->pool.pool = NULL;
3459 reader->pool.index = 0;
3460 reader->pool.len = 0;
3461 reader->features = Namespaces | NamespacePrefixes;
3462 reader->version = version;
3464 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3466 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3467 reader->sax.initialized = XML_SAX2_MAGIC;
3468 reader->sax.startDocument = libxmlStartDocument;
3469 reader->sax.endDocument = libxmlEndDocument;
3470 reader->sax.startElementNs = libxmlStartElementNS;
3471 reader->sax.endElementNs = libxmlEndElementNS;
3472 reader->sax.characters = libxmlCharacters;
3473 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3474 reader->sax.comment = libxmlComment;
3475 reader->sax.error = libxmlFatalError;
3476 reader->sax.fatalError = libxmlFatalError;
3477 reader->sax.cdataBlock = libxml_cdatablock;
3478 reader->sax.resolveEntity = libxmlresolveentity;
3480 *ppObj = &reader->IVBSAXXMLReader_iface;
3482 TRACE("returning iface %p\n", *ppObj);
3484 return S_OK;
3487 #else
3489 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3491 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3492 "libxml2 support was not present at compile time.\n");
3493 return E_NOTIMPL;
3496 #endif