msvcp110: Add tr2_sys__Remove_dir_wchar implementation and test.
[wine/multimedia.git] / dlls / msxml3 / saxreader.c
blob3b5bd7cb50eec9bfe3b9a2b6304664f641a8aa94
1 /*
2 * SAX Reader implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2008 Piotr Caban
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 # include <libxml/SAX2.h>
30 # include <libxml/parserInternals.h>
31 #endif
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "winnls.h"
37 #include "ole2.h"
38 #include "msxml6.h"
39 #include "wininet.h"
40 #include "urlmon.h"
41 #include "winreg.h"
42 #include "shlwapi.h"
44 #include "wine/debug.h"
46 #include "msxml_private.h"
48 #ifdef HAVE_LIBXML2
50 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
52 typedef enum
54 FeatureUnknown = 0,
55 ExhaustiveErrors = 1 << 1,
56 ExternalGeneralEntities = 1 << 2,
57 ExternalParameterEntities = 1 << 3,
58 ForcedResync = 1 << 4,
59 NamespacePrefixes = 1 << 5,
60 Namespaces = 1 << 6,
61 ParameterEntities = 1 << 7,
62 PreserveSystemIndentifiers = 1 << 8,
63 ProhibitDTD = 1 << 9,
64 SchemaValidation = 1 << 10,
65 ServerHttpRequest = 1 << 11,
66 SuppressValidationfatalError = 1 << 12,
67 UseInlineSchema = 1 << 13,
68 UseSchemaLocation = 1 << 14,
69 LexicalHandlerParEntities = 1 << 15
70 } saxreader_feature;
72 /* feature names */
73 static const WCHAR FeatureExternalGeneralEntitiesW[] = {
74 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/',
75 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l',
76 '-','e','n','t','i','t','i','e','s',0
79 static const WCHAR FeatureExternalParameterEntitiesW[] = {
80 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
81 '/','e','x','t','e','r','n','a','l','-','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
84 static const WCHAR FeatureLexicalHandlerParEntitiesW[] = {
85 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
86 '/','l','e','x','i','c','a','l','-','h','a','n','d','l','e','r','/','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
89 static const WCHAR FeatureProhibitDTDW[] = {
90 'p','r','o','h','i','b','i','t','-','d','t','d',0
93 static const WCHAR FeatureNamespacesW[] = {
94 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
95 '/','n','a','m','e','s','p','a','c','e','s',0
98 static const WCHAR FeatureNamespacePrefixesW[] = {
99 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
100 '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
103 struct saxreader_feature_pair
105 saxreader_feature feature;
106 const WCHAR *name;
109 static const struct saxreader_feature_pair saxreader_feature_map[] = {
110 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
111 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
112 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
113 { NamespacePrefixes, FeatureNamespacePrefixesW },
114 { Namespaces, FeatureNamespacesW },
115 { ProhibitDTD, FeatureProhibitDTDW }
118 static saxreader_feature get_saxreader_feature(const WCHAR *name)
120 int min, max, n, c;
122 min = 0;
123 max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
125 while (min <= max)
127 n = (min+max)/2;
129 c = strcmpW(saxreader_feature_map[n].name, name);
130 if (!c)
131 return saxreader_feature_map[n].feature;
133 if (c > 0)
134 max = n-1;
135 else
136 min = n+1;
139 return FeatureUnknown;
142 struct bstrpool
144 BSTR *pool;
145 unsigned int index;
146 unsigned int len;
149 typedef struct
151 BSTR prefix;
152 BSTR uri;
153 } ns;
155 typedef struct
157 struct list entry;
158 BSTR prefix;
159 BSTR local;
160 BSTR qname;
161 ns *ns; /* namespaces defined in this particular element */
162 int ns_count;
163 } element_entry;
165 enum saxhandler_type
167 SAXContentHandler = 0,
168 SAXDeclHandler,
169 SAXDTDHandler,
170 SAXEntityResolver,
171 SAXErrorHandler,
172 SAXLexicalHandler,
173 SAXHandler_Last
176 struct saxanyhandler_iface
178 IUnknown *handler;
179 IUnknown *vbhandler;
182 struct saxcontenthandler_iface
184 ISAXContentHandler *handler;
185 IVBSAXContentHandler *vbhandler;
188 struct saxerrorhandler_iface
190 ISAXErrorHandler *handler;
191 IVBSAXErrorHandler *vbhandler;
194 struct saxlexicalhandler_iface
196 ISAXLexicalHandler *handler;
197 IVBSAXLexicalHandler *vbhandler;
200 struct saxentityresolver_iface
202 ISAXEntityResolver *handler;
203 IVBSAXEntityResolver *vbhandler;
206 struct saxhandler_iface
208 union {
209 struct saxcontenthandler_iface content;
210 struct saxentityresolver_iface entityresolver;
211 struct saxerrorhandler_iface error;
212 struct saxlexicalhandler_iface lexical;
213 struct saxanyhandler_iface anyhandler;
214 } u;
217 typedef struct
219 DispatchEx dispex;
220 IVBSAXXMLReader IVBSAXXMLReader_iface;
221 ISAXXMLReader ISAXXMLReader_iface;
222 LONG ref;
224 struct saxhandler_iface saxhandlers[SAXHandler_Last];
225 xmlSAXHandler sax;
226 BOOL isParsing;
227 struct bstrpool pool;
228 saxreader_feature features;
229 BSTR xmldecl_version;
230 MSXML_VERSION version;
231 } saxreader;
233 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
235 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
236 IUnknown *unk = (IUnknown*)ptr;
238 if (unk)
239 IUnknown_AddRef(unk);
241 if ((vb && iface->vbhandler) || (!vb && iface->handler))
242 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
244 if (vb)
245 iface->vbhandler = unk;
246 else
247 iface->handler = unk;
249 return S_OK;
252 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
254 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
256 if (!ret) return E_POINTER;
258 if ((vb && iface->vbhandler) || (!vb && iface->handler))
260 if (vb)
261 IUnknown_AddRef(iface->vbhandler);
262 else
263 IUnknown_AddRef(iface->handler);
266 *ret = vb ? iface->vbhandler : iface->handler;
268 return S_OK;
271 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
273 return &reader->saxhandlers[SAXContentHandler].u.content;
276 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
278 return &reader->saxhandlers[SAXErrorHandler].u.error;
281 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
283 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
286 typedef struct
288 IVBSAXLocator IVBSAXLocator_iface;
289 ISAXLocator ISAXLocator_iface;
290 IVBSAXAttributes IVBSAXAttributes_iface;
291 ISAXAttributes ISAXAttributes_iface;
292 LONG ref;
293 saxreader *saxreader;
294 HRESULT ret;
295 xmlParserCtxtPtr pParserCtxt;
296 BSTR publicId;
297 BSTR systemId;
298 int line;
299 int column;
300 BOOL vbInterface;
301 struct list elements;
303 BSTR namespaceUri;
304 int attr_alloc_count;
305 int attr_count;
306 struct _attributes
308 BSTR szLocalname;
309 BSTR szURI;
310 BSTR szValue;
311 BSTR szQName;
312 } *attributes;
313 } saxlocator;
315 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
317 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
320 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
322 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
325 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
327 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
330 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
332 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
335 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
337 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
340 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
342 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
345 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
347 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
348 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
351 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
353 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
354 HRESULT hr;
356 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
358 if (locator->vbInterface)
359 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
360 else
361 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
363 return hr;
366 /* property names */
367 static const WCHAR PropertyCharsetW[] = {
368 'c','h','a','r','s','e','t',0
370 static const WCHAR PropertyXmlDeclVersionW[] = {
371 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
373 static const WCHAR PropertyDeclHandlerW[] = {
374 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
375 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
376 'd','e','c','l','a','r','a','t','i','o','n',
377 '-','h','a','n','d','l','e','r',0
379 static const WCHAR PropertyDomNodeW[] = {
380 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
381 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
382 'd','o','m','-','n','o','d','e',0
384 static const WCHAR PropertyInputSourceW[] = {
385 'i','n','p','u','t','-','s','o','u','r','c','e',0
387 static const WCHAR PropertyLexicalHandlerW[] = {
388 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
389 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
390 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
392 static const WCHAR PropertyMaxElementDepthW[] = {
393 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
395 static const WCHAR PropertyMaxXMLSizeW[] = {
396 'm','a','x','-','x','m','l','-','s','i','z','e',0
398 static const WCHAR PropertySchemaDeclHandlerW[] = {
399 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
400 'h','a','n','d','l','e','r',0
402 static const WCHAR PropertyXMLDeclEncodingW[] = {
403 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
405 static const WCHAR PropertyXMLDeclStandaloneW[] = {
406 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
408 static const WCHAR PropertyXMLDeclVersionW[] = {
409 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
412 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
414 /* handling of non-VARIANT_* values is version dependent */
415 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
416 value = VARIANT_FALSE;
417 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
418 value = VARIANT_TRUE;
420 if (value == VARIANT_TRUE)
421 reader->features |= feature;
422 else
423 reader->features &= ~feature;
425 return S_OK;
428 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
430 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
431 return S_OK;
434 static BOOL is_namespaces_enabled(const saxreader *reader)
436 return (reader->version < MSXML4) || (reader->features & Namespaces);
439 static BSTR build_qname(BSTR prefix, BSTR local)
441 if (prefix && *prefix)
443 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
444 WCHAR *ptr;
446 ptr = qname;
447 strcpyW(ptr, prefix);
448 ptr += SysStringLen(prefix);
449 *ptr++ = ':';
450 strcpyW(ptr, local);
451 return qname;
453 else
454 return SysAllocString(local);
457 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
458 const xmlChar **namespaces)
460 element_entry *ret;
461 int i;
463 ret = heap_alloc(sizeof(*ret));
464 if (!ret) return ret;
466 ret->local = bstr_from_xmlChar(local);
467 ret->prefix = bstr_from_xmlChar(prefix);
468 ret->qname = build_qname(ret->prefix, ret->local);
469 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
470 ret->ns_count = nb_ns;
472 for (i=0; i < nb_ns; i++)
474 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
475 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
478 return ret;
481 static void free_element_entry(element_entry *element)
483 int i;
485 for (i=0; i<element->ns_count;i++)
487 SysFreeString(element->ns[i].prefix);
488 SysFreeString(element->ns[i].uri);
491 SysFreeString(element->prefix);
492 SysFreeString(element->local);
493 SysFreeString(element->qname);
495 heap_free(element->ns);
496 heap_free(element);
499 static void push_element_ns(saxlocator *locator, element_entry *element)
501 list_add_head(&locator->elements, &element->entry);
504 static element_entry * pop_element_ns(saxlocator *locator)
506 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
508 if (element)
509 list_remove(&element->entry);
511 return element;
514 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
516 element_entry *element;
517 BSTR uriW;
518 int i;
520 if (!uri) return NULL;
522 uriW = bstr_from_xmlChar(uri);
524 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
526 for (i=0; i < element->ns_count; i++)
527 if (!strcmpW(uriW, element->ns[i].uri))
529 SysFreeString(uriW);
530 return element->ns[i].uri;
534 SysFreeString(uriW);
535 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
536 return NULL;
539 /* used to localize version dependent error check behaviour */
540 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
542 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
545 /* index value -1 means it tries to loop for a first time */
546 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
548 if (This->saxreader->version >= MSXML4)
550 if (*i == -1) *i = 0; else ++*i;
551 return *i < element->ns_count;
553 else
555 if (*i == -1) *i = element->ns_count-1; else --*i;
556 return *i >= 0;
560 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
562 if (!pool->pool)
564 pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool));
565 if (!pool->pool)
566 return FALSE;
568 pool->index = 0;
569 pool->len = 16;
571 else if (pool->index == pool->len)
573 BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc));
575 if (!realloc)
576 return FALSE;
578 pool->pool = realloc;
579 pool->len *= 2;
582 pool->pool[pool->index++] = pool_entry;
583 return TRUE;
586 static void free_bstr_pool(struct bstrpool *pool)
588 unsigned int i;
590 for (i = 0; i < pool->index; i++)
591 SysFreeString(pool->pool[i]);
593 HeapFree(GetProcessHeap(), 0, pool->pool);
595 pool->pool = NULL;
596 pool->index = pool->len = 0;
599 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
601 DWORD dLen;
602 BSTR bstr;
604 if (!buf)
605 return NULL;
607 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
608 if(len != -1) dLen++;
609 bstr = SysAllocStringLen(NULL, dLen-1);
610 if (!bstr)
611 return NULL;
612 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
613 if(len != -1) bstr[dLen-1] = '\0';
615 return bstr;
618 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
620 xmlChar *qname;
621 BSTR bstr;
623 if(!name) return NULL;
625 if(!prefix || !*prefix)
626 return bstr_from_xmlChar(name);
628 qname = xmlBuildQName(name, prefix, NULL, 0);
629 bstr = bstr_from_xmlChar(qname);
630 xmlFree(qname);
632 return bstr;
635 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
637 BSTR pool_entry = bstr_from_xmlChar(buf);
639 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
641 SysFreeString(pool_entry);
642 return NULL;
645 return pool_entry;
648 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
650 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
652 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
654 SysFreeString(pool_entry);
655 return NULL;
658 return pool_entry;
661 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
663 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
664 xmlStopParser(This->pParserCtxt);
665 This->ret = hr;
667 if (saxreader_has_handler(This, SAXErrorHandler))
669 WCHAR msg[1024];
670 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
671 NULL, hr, 0, msg, sizeof(msg)/sizeof(msg[0]), NULL))
673 FIXME("MSXML errors not yet supported.\n");
674 msg[0] = '\0';
677 if(This->vbInterface)
679 BSTR bstrMsg = SysAllocString(msg);
680 IVBSAXErrorHandler_fatalError(handler->vbhandler,
681 &This->IVBSAXLocator_iface, &bstrMsg, hr);
682 SysFreeString(bstrMsg);
684 else
685 ISAXErrorHandler_fatalError(handler->handler,
686 &This->ISAXLocator_iface, msg, hr);
690 static void update_position(saxlocator *This, BOOL fix_column)
692 const xmlChar *p = This->pParserCtxt->input->cur-1;
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->attr_count;
1110 TRACE("Length set to %d\n", *length);
1111 return S_OK;
1114 static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
1116 return index < locator->attr_count && index >= 0;
1119 static HRESULT WINAPI isaxattributes_getURI(
1120 ISAXAttributes* iface,
1121 int index,
1122 const WCHAR **url,
1123 int *size)
1125 saxlocator *This = impl_from_ISAXAttributes( iface );
1126 TRACE("(%p)->(%d)\n", This, index);
1128 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1129 if(!url || !size) return E_POINTER;
1131 *size = SysStringLen(This->attributes[index].szURI);
1132 *url = This->attributes[index].szURI;
1134 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1136 return S_OK;
1139 static HRESULT WINAPI isaxattributes_getLocalName(
1140 ISAXAttributes* iface,
1141 int index,
1142 const WCHAR **pLocalName,
1143 int *pLocalNameLength)
1145 saxlocator *This = impl_from_ISAXAttributes( iface );
1146 TRACE("(%p)->(%d)\n", This, index);
1148 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1149 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1151 *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
1152 *pLocalName = This->attributes[index].szLocalname;
1154 return S_OK;
1157 static HRESULT WINAPI isaxattributes_getQName(
1158 ISAXAttributes* iface,
1159 int index,
1160 const WCHAR **pQName,
1161 int *pQNameLength)
1163 saxlocator *This = impl_from_ISAXAttributes( iface );
1164 TRACE("(%p)->(%d)\n", This, index);
1166 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1167 if(!pQName || !pQNameLength) return E_POINTER;
1169 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1170 *pQName = This->attributes[index].szQName;
1172 return S_OK;
1175 static HRESULT WINAPI isaxattributes_getName(
1176 ISAXAttributes* iface,
1177 int index,
1178 const WCHAR **uri,
1179 int *pUriLength,
1180 const WCHAR **localName,
1181 int *pLocalNameSize,
1182 const WCHAR **QName,
1183 int *pQNameLength)
1185 saxlocator *This = impl_from_ISAXAttributes( iface );
1186 TRACE("(%p)->(%d)\n", This, index);
1188 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1189 if(!uri || !pUriLength || !localName || !pLocalNameSize
1190 || !QName || !pQNameLength) return E_POINTER;
1192 *pUriLength = SysStringLen(This->attributes[index].szURI);
1193 *uri = This->attributes[index].szURI;
1194 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1195 *localName = This->attributes[index].szLocalname;
1196 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1197 *QName = This->attributes[index].szQName;
1199 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1201 return S_OK;
1204 static HRESULT WINAPI isaxattributes_getIndexFromName(
1205 ISAXAttributes* iface,
1206 const WCHAR *pUri,
1207 int cUriLength,
1208 const WCHAR *pLocalName,
1209 int cocalNameLength,
1210 int *index)
1212 saxlocator *This = impl_from_ISAXAttributes( iface );
1213 int i;
1214 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1215 debugstr_w(pLocalName), cocalNameLength);
1217 if(!pUri || !pLocalName || !index) return E_POINTER;
1219 for(i=0; i<This->attr_count; i++)
1221 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1222 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1223 continue;
1224 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1225 sizeof(WCHAR)*cUriLength))
1226 continue;
1227 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1228 sizeof(WCHAR)*cocalNameLength))
1229 continue;
1231 *index = i;
1232 return S_OK;
1235 return E_INVALIDARG;
1238 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1239 ISAXAttributes* iface,
1240 const WCHAR *pQName,
1241 int nQNameLength,
1242 int *index)
1244 saxlocator *This = impl_from_ISAXAttributes( iface );
1245 int i;
1246 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1248 if(!pQName || !index) return E_POINTER;
1249 if(!nQNameLength) return E_INVALIDARG;
1251 for(i=0; i<This->attr_count; i++)
1253 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1254 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1256 *index = i;
1257 return S_OK;
1260 return E_INVALIDARG;
1263 static HRESULT WINAPI isaxattributes_getType(
1264 ISAXAttributes* iface,
1265 int nIndex,
1266 const WCHAR **pType,
1267 int *pTypeLength)
1269 saxlocator *This = impl_from_ISAXAttributes( iface );
1271 FIXME("(%p)->(%d) stub\n", This, nIndex);
1272 return E_NOTIMPL;
1275 static HRESULT WINAPI isaxattributes_getTypeFromName(
1276 ISAXAttributes* iface,
1277 const WCHAR *pUri,
1278 int nUri,
1279 const WCHAR *pLocalName,
1280 int nLocalName,
1281 const WCHAR **pType,
1282 int *nType)
1284 saxlocator *This = impl_from_ISAXAttributes( iface );
1286 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1287 debugstr_w(pLocalName), nLocalName);
1288 return E_NOTIMPL;
1291 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1292 ISAXAttributes* iface,
1293 const WCHAR *pQName,
1294 int nQName,
1295 const WCHAR **pType,
1296 int *nType)
1298 saxlocator *This = impl_from_ISAXAttributes( iface );
1300 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1301 return E_NOTIMPL;
1304 static HRESULT WINAPI isaxattributes_getValue(
1305 ISAXAttributes* iface,
1306 int index,
1307 const WCHAR **value,
1308 int *nValue)
1310 saxlocator *This = impl_from_ISAXAttributes( iface );
1311 TRACE("(%p)->(%d)\n", This, index);
1313 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1314 if(!value || !nValue) return E_POINTER;
1316 *nValue = SysStringLen(This->attributes[index].szValue);
1317 *value = This->attributes[index].szValue;
1319 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1321 return S_OK;
1324 static HRESULT WINAPI isaxattributes_getValueFromName(
1325 ISAXAttributes* iface,
1326 const WCHAR *pUri,
1327 int nUri,
1328 const WCHAR *pLocalName,
1329 int nLocalName,
1330 const WCHAR **pValue,
1331 int *nValue)
1333 HRESULT hr;
1334 int index;
1335 saxlocator *This = impl_from_ISAXAttributes( iface );
1336 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1337 debugstr_w(pLocalName), nLocalName);
1339 hr = ISAXAttributes_getIndexFromName(iface,
1340 pUri, nUri, pLocalName, nLocalName, &index);
1341 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1343 return hr;
1346 static HRESULT WINAPI isaxattributes_getValueFromQName(
1347 ISAXAttributes* iface,
1348 const WCHAR *pQName,
1349 int nQName,
1350 const WCHAR **pValue,
1351 int *nValue)
1353 HRESULT hr;
1354 int index;
1355 saxlocator *This = impl_from_ISAXAttributes( iface );
1356 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1358 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1359 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1361 return hr;
1364 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1366 isaxattributes_QueryInterface,
1367 isaxattributes_AddRef,
1368 isaxattributes_Release,
1369 isaxattributes_getLength,
1370 isaxattributes_getURI,
1371 isaxattributes_getLocalName,
1372 isaxattributes_getQName,
1373 isaxattributes_getName,
1374 isaxattributes_getIndexFromName,
1375 isaxattributes_getIndexFromQName,
1376 isaxattributes_getType,
1377 isaxattributes_getTypeFromName,
1378 isaxattributes_getTypeFromQName,
1379 isaxattributes_getValue,
1380 isaxattributes_getValueFromName,
1381 isaxattributes_getValueFromQName
1384 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1385 so when document has escaped value with '&amp;' it's parsed to '&' and then
1386 escaped to '&#38;'. This function takes care of ampersands only. */
1387 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1389 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1390 WCHAR *dest, *ptrW, *str;
1391 DWORD str_len;
1392 BSTR bstr;
1394 if (!buf)
1395 return NULL;
1397 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1398 if (len != -1) str_len++;
1400 str = heap_alloc(str_len*sizeof(WCHAR));
1401 if (!str) return NULL;
1403 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1404 if (len != -1) str[str_len-1] = 0;
1406 ptrW = str;
1407 while ((dest = strstrW(ptrW, ampescW)))
1409 WCHAR *src;
1411 /* leave first '&' from a reference as a value */
1412 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1413 dest++;
1415 /* move together with null terminator */
1416 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1418 ptrW++;
1421 bstr = SysAllocString(str);
1422 heap_free(str);
1424 return bstr;
1427 static void free_attribute_values(saxlocator *locator)
1429 int i;
1431 for (i = 0; i < locator->attr_count; i++)
1433 SysFreeString(locator->attributes[i].szLocalname);
1434 locator->attributes[i].szLocalname = NULL;
1436 SysFreeString(locator->attributes[i].szValue);
1437 locator->attributes[i].szValue = NULL;
1439 SysFreeString(locator->attributes[i].szQName);
1440 locator->attributes[i].szQName = NULL;
1444 static HRESULT SAXAttributes_populate(saxlocator *locator,
1445 int nb_namespaces, const xmlChar **xmlNamespaces,
1446 int nb_attributes, const xmlChar **xmlAttributes)
1448 static const xmlChar xmlns[] = "xmlns";
1449 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1451 struct _attributes *attrs;
1452 int i;
1454 /* skip namespace definitions */
1455 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1456 nb_namespaces = 0;
1458 locator->attr_count = nb_namespaces + nb_attributes;
1459 if(locator->attr_count > locator->attr_alloc_count)
1461 int new_size = locator->attr_count * 2;
1462 attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1463 if(!attrs)
1465 free_attribute_values(locator);
1466 locator->attr_count = 0;
1467 return E_OUTOFMEMORY;
1469 locator->attributes = attrs;
1470 locator->attr_alloc_count = new_size;
1472 else
1474 attrs = locator->attributes;
1477 for (i = 0; i < nb_namespaces; i++)
1479 SysFreeString(attrs[nb_attributes+i].szLocalname);
1480 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1482 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1484 SysFreeString(attrs[nb_attributes+i].szValue);
1485 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1487 SysFreeString(attrs[nb_attributes+i].szQName);
1488 if(!xmlNamespaces[2*i])
1489 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1490 else
1491 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1494 for (i = 0; i < nb_attributes; i++)
1496 static const xmlChar xmlA[] = "xml";
1498 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1499 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1500 else
1501 /* that's an important feature to keep same uri pointer for every reported attribute */
1502 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1504 SysFreeString(attrs[i].szLocalname);
1505 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1507 SysFreeString(attrs[i].szValue);
1508 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1510 SysFreeString(attrs[i].szQName);
1511 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1514 return S_OK;
1517 /*** LibXML callbacks ***/
1518 static void libxmlStartDocument(void *ctx)
1520 saxlocator *This = ctx;
1521 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1522 HRESULT hr;
1524 if (This->saxreader->version >= MSXML4)
1526 const xmlChar *p = This->pParserCtxt->input->cur-1;
1527 update_position(This, FALSE);
1528 while(p>This->pParserCtxt->input->base && *p!='>')
1530 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1531 This->line--;
1532 p--;
1534 This->column = 0;
1535 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1536 This->column++;
1539 /* store version value, declaration has to contain version attribute */
1540 if (This->pParserCtxt->standalone != -1)
1542 SysFreeString(This->saxreader->xmldecl_version);
1543 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1546 if (saxreader_has_handler(This, SAXContentHandler))
1548 if(This->vbInterface)
1549 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1550 else
1551 hr = ISAXContentHandler_startDocument(handler->handler);
1553 if (sax_callback_failed(This, hr))
1554 format_error_message_from_id(This, hr);
1558 static void libxmlEndDocument(void *ctx)
1560 saxlocator *This = ctx;
1561 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1562 HRESULT hr;
1564 if (This->saxreader->version >= MSXML4) {
1565 update_position(This, FALSE);
1566 if(This->column > 1)
1567 This->line++;
1568 This->column = 0;
1569 } else {
1570 This->column = 0;
1571 This->line = 0;
1574 if(This->ret != S_OK) return;
1576 if (saxreader_has_handler(This, SAXContentHandler))
1578 if(This->vbInterface)
1579 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1580 else
1581 hr = ISAXContentHandler_endDocument(handler->handler);
1583 if (sax_callback_failed(This, hr))
1584 format_error_message_from_id(This, hr);
1588 static void libxmlStartElementNS(
1589 void *ctx,
1590 const xmlChar *localname,
1591 const xmlChar *prefix,
1592 const xmlChar *URI,
1593 int nb_namespaces,
1594 const xmlChar **namespaces,
1595 int nb_attributes,
1596 int nb_defaulted,
1597 const xmlChar **attributes)
1599 saxlocator *This = ctx;
1600 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1601 element_entry *element;
1602 HRESULT hr = S_OK;
1603 BSTR uri;
1605 update_position(This, TRUE);
1606 if(*(This->pParserCtxt->input->cur) == '/')
1607 This->column++;
1608 if(This->saxreader->version < MSXML4)
1609 This->column++;
1611 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1612 push_element_ns(This, element);
1614 if (is_namespaces_enabled(This->saxreader))
1616 int i;
1618 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1620 if (This->vbInterface)
1621 hr = IVBSAXContentHandler_startPrefixMapping(
1622 handler->vbhandler,
1623 &element->ns[i].prefix,
1624 &element->ns[i].uri);
1625 else
1626 hr = ISAXContentHandler_startPrefixMapping(
1627 handler->handler,
1628 element->ns[i].prefix,
1629 SysStringLen(element->ns[i].prefix),
1630 element->ns[i].uri,
1631 SysStringLen(element->ns[i].uri));
1633 if (sax_callback_failed(This, hr))
1635 format_error_message_from_id(This, hr);
1636 return;
1641 uri = find_element_uri(This, URI);
1642 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1643 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1645 BSTR local;
1647 if (is_namespaces_enabled(This->saxreader))
1648 local = element->local;
1649 else
1650 uri = local = NULL;
1652 if (This->vbInterface)
1653 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1654 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1655 else
1656 hr = ISAXContentHandler_startElement(handler->handler,
1657 uri, SysStringLen(uri),
1658 local, SysStringLen(local),
1659 element->qname, SysStringLen(element->qname),
1660 &This->ISAXAttributes_iface);
1662 if (sax_callback_failed(This, hr))
1663 format_error_message_from_id(This, hr);
1667 static void libxmlEndElementNS(
1668 void *ctx,
1669 const xmlChar *localname,
1670 const xmlChar *prefix,
1671 const xmlChar *URI)
1673 saxlocator *This = ctx;
1674 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1675 element_entry *element;
1676 const xmlChar *p;
1677 BSTR uri, local;
1678 HRESULT hr;
1680 update_position(This, FALSE);
1681 p = This->pParserCtxt->input->cur;
1683 if (This->saxreader->version >= MSXML4)
1685 p--;
1686 while(p>This->pParserCtxt->input->base && *p!='>')
1688 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1689 This->line--;
1690 p--;
1693 else if(*(p-1)!='>' || *(p-2)!='/')
1695 p--;
1696 while(p-2>=This->pParserCtxt->input->base
1697 && *(p-2)!='<' && *(p-1)!='/')
1699 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1700 This->line--;
1701 p--;
1704 This->column = 0;
1705 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1706 This->column++;
1708 uri = find_element_uri(This, URI);
1709 element = pop_element_ns(This);
1711 if (!saxreader_has_handler(This, SAXContentHandler))
1713 free_attribute_values(This);
1714 This->attr_count = 0;
1715 free_element_entry(element);
1716 return;
1719 if (is_namespaces_enabled(This->saxreader))
1720 local = element->local;
1721 else
1722 uri = local = NULL;
1724 if (This->vbInterface)
1725 hr = IVBSAXContentHandler_endElement(
1726 handler->vbhandler,
1727 &uri, &local, &element->qname);
1728 else
1729 hr = ISAXContentHandler_endElement(
1730 handler->handler,
1731 uri, SysStringLen(uri),
1732 local, SysStringLen(local),
1733 element->qname, SysStringLen(element->qname));
1735 free_attribute_values(This);
1736 This->attr_count = 0;
1738 if (sax_callback_failed(This, hr))
1740 format_error_message_from_id(This, hr);
1741 free_element_entry(element);
1742 return;
1745 if (is_namespaces_enabled(This->saxreader))
1747 int i = -1;
1748 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1750 if (This->vbInterface)
1751 hr = IVBSAXContentHandler_endPrefixMapping(
1752 handler->vbhandler, &element->ns[i].prefix);
1753 else
1754 hr = ISAXContentHandler_endPrefixMapping(
1755 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1757 if (sax_callback_failed(This, hr)) break;
1760 if (sax_callback_failed(This, hr))
1761 format_error_message_from_id(This, hr);
1764 free_element_entry(element);
1767 static void libxmlCharacters(
1768 void *ctx,
1769 const xmlChar *ch,
1770 int len)
1772 saxlocator *This = ctx;
1773 BSTR Chars;
1774 HRESULT hr;
1775 xmlChar *cur, *end;
1776 BOOL lastEvent = FALSE;
1778 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1780 update_position(This, FALSE);
1781 cur = (xmlChar*)This->pParserCtxt->input->cur;
1782 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1784 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1785 This->line--;
1786 cur--;
1788 This->column = 1;
1789 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1790 This->column++;
1792 cur = (xmlChar*)ch;
1793 if(*(ch-1)=='\r') cur--;
1794 end = cur;
1796 while(1)
1798 while(end-ch<len && *end!='\r') end++;
1799 if(end-ch==len)
1801 lastEvent = TRUE;
1803 else
1805 *end = '\n';
1806 end++;
1809 if (This->saxreader->version >= MSXML4)
1811 xmlChar *p;
1813 for(p=cur; p!=end; p++)
1815 if(*p=='\n')
1817 This->line++;
1818 This->column = 1;
1820 else
1822 This->column++;
1826 if(!lastEvent)
1827 This->column = 0;
1830 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1831 hr = saxreader_saxcharacters(This, Chars);
1833 if (sax_callback_failed(This, hr))
1835 format_error_message_from_id(This, hr);
1836 return;
1839 if (This->saxreader->version < MSXML4)
1840 This->column += end-cur;
1842 if(lastEvent)
1843 break;
1845 *(end-1) = '\r';
1846 if(*end == '\n')
1848 end++;
1849 This->column++;
1851 cur = end;
1853 if(end-ch == len) break;
1857 static void libxmlSetDocumentLocator(
1858 void *ctx,
1859 xmlSAXLocatorPtr loc)
1861 saxlocator *This = ctx;
1862 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1863 HRESULT hr = S_OK;
1865 if (saxreader_has_handler(This, SAXContentHandler))
1867 if(This->vbInterface)
1868 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1869 &This->IVBSAXLocator_iface);
1870 else
1871 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1874 if(FAILED(hr))
1875 format_error_message_from_id(This, hr);
1878 static void libxmlComment(void *ctx, const xmlChar *value)
1880 saxlocator *This = ctx;
1881 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1882 BSTR bValue;
1883 HRESULT hr;
1884 const xmlChar *p = This->pParserCtxt->input->cur;
1886 update_position(This, FALSE);
1887 while(p-4>=This->pParserCtxt->input->base
1888 && memcmp(p-4, "<!--", sizeof(char[4])))
1890 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1891 This->line--;
1892 p--;
1895 This->column = 0;
1896 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1897 This->column++;
1899 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1901 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1903 if (This->vbInterface)
1904 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1905 else
1906 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1908 if(FAILED(hr))
1909 format_error_message_from_id(This, hr);
1912 static void libxmlFatalError(void *ctx, const char *msg, ...)
1914 saxlocator *This = ctx;
1915 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1916 char message[1024];
1917 WCHAR *error;
1918 DWORD len;
1919 va_list args;
1921 if(This->ret != S_OK) {
1922 xmlStopParser(This->pParserCtxt);
1923 return;
1926 va_start(args, msg);
1927 vsprintf(message, msg, args);
1928 va_end(args);
1930 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1931 error = heap_alloc(sizeof(WCHAR)*len);
1932 if(error)
1934 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1935 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1938 if (!saxreader_has_handler(This, SAXErrorHandler))
1940 xmlStopParser(This->pParserCtxt);
1941 This->ret = E_FAIL;
1942 heap_free(error);
1943 return;
1946 FIXME("Error handling is not compatible.\n");
1948 if(This->vbInterface)
1950 BSTR bstrError = SysAllocString(error);
1951 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1952 &bstrError, E_FAIL);
1953 SysFreeString(bstrError);
1955 else
1956 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1958 heap_free(error);
1960 xmlStopParser(This->pParserCtxt);
1961 This->ret = E_FAIL;
1964 /* The only reason this helper exists is that CDATA section are reported by chunks,
1965 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1967 This helper should be called for substring with trailing newlines.
1969 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1971 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1972 WCHAR *ptr;
1974 ptr = bstr + len - 1;
1975 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1976 ptr--;
1978 while (*++ptr)
1980 /* replace returns as:
1982 - "\r<char>" -> "\n<char>"
1983 - "\r\r" -> "\r"
1984 - "\r\n" -> "\n"
1986 if (*ptr == '\r')
1988 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1990 /* shift tail */
1991 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1993 else
1994 *ptr = '\n';
1998 ret = SysAllocStringLen(bstr, len);
1999 SysFreeString(bstr);
2000 return ret;
2003 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2005 const xmlChar *start, *end;
2006 saxlocator *locator = ctx;
2007 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2008 HRESULT hr = S_OK;
2009 BSTR chars;
2010 int i;
2012 update_position(locator, FALSE);
2013 if (saxreader_has_handler(locator, SAXLexicalHandler))
2015 if (locator->vbInterface)
2016 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2017 else
2018 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2021 if(FAILED(hr))
2023 format_error_message_from_id(locator, hr);
2024 return;
2027 start = value;
2028 end = NULL;
2029 i = 0;
2031 while (i < len)
2033 /* scan for newlines */
2034 if (value[i] == '\r' || value[i] == '\n')
2036 /* skip newlines/linefeeds */
2037 while (i < len)
2039 if (value[i] != '\r' && value[i] != '\n') break;
2040 i++;
2042 end = &value[i];
2044 /* report */
2045 chars = saxreader_get_cdata_chunk(start, end-start);
2046 TRACE("(chunk %s)\n", debugstr_w(chars));
2047 hr = saxreader_saxcharacters(locator, chars);
2048 SysFreeString(chars);
2050 start = &value[i];
2051 end = NULL;
2053 i++;
2054 locator->column++;
2057 /* no newline chars (or last chunk) report as a whole */
2058 if (!end && start == value)
2060 /* report */
2061 chars = bstr_from_xmlCharN(start, len-(start-value));
2062 TRACE("(%s)\n", debugstr_w(chars));
2063 hr = saxreader_saxcharacters(locator, chars);
2064 SysFreeString(chars);
2067 if (saxreader_has_handler(locator, SAXLexicalHandler))
2069 if (locator->vbInterface)
2070 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2071 else
2072 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2075 if(FAILED(hr))
2076 format_error_message_from_id(locator, hr);
2079 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2081 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2082 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2085 /*** IVBSAXLocator interface ***/
2086 /*** IUnknown methods ***/
2087 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2089 saxlocator *This = impl_from_IVBSAXLocator( iface );
2091 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2093 *ppvObject = NULL;
2095 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2096 IsEqualGUID( riid, &IID_IDispatch) ||
2097 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2099 *ppvObject = iface;
2101 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2103 *ppvObject = &This->IVBSAXAttributes_iface;
2105 else
2107 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2108 return E_NOINTERFACE;
2111 IVBSAXLocator_AddRef( iface );
2113 return S_OK;
2116 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2118 saxlocator *This = impl_from_IVBSAXLocator( iface );
2119 TRACE("%p\n", This );
2120 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2123 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2125 saxlocator *This = impl_from_IVBSAXLocator( iface );
2126 return ISAXLocator_Release(&This->ISAXLocator_iface);
2129 /*** IDispatch methods ***/
2130 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2132 saxlocator *This = impl_from_IVBSAXLocator( iface );
2134 TRACE("(%p)->(%p)\n", This, pctinfo);
2136 *pctinfo = 1;
2138 return S_OK;
2141 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2142 IVBSAXLocator *iface,
2143 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2145 saxlocator *This = impl_from_IVBSAXLocator( iface );
2147 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2149 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2152 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2153 IVBSAXLocator *iface,
2154 REFIID riid,
2155 LPOLESTR* rgszNames,
2156 UINT cNames,
2157 LCID lcid,
2158 DISPID* rgDispId)
2160 saxlocator *This = impl_from_IVBSAXLocator( iface );
2161 ITypeInfo *typeinfo;
2162 HRESULT hr;
2164 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2165 lcid, rgDispId);
2167 if(!rgszNames || cNames == 0 || !rgDispId)
2168 return E_INVALIDARG;
2170 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2171 if(SUCCEEDED(hr))
2173 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2174 ITypeInfo_Release(typeinfo);
2177 return hr;
2180 static HRESULT WINAPI ivbsaxlocator_Invoke(
2181 IVBSAXLocator *iface,
2182 DISPID dispIdMember,
2183 REFIID riid,
2184 LCID lcid,
2185 WORD wFlags,
2186 DISPPARAMS* pDispParams,
2187 VARIANT* pVarResult,
2188 EXCEPINFO* pExcepInfo,
2189 UINT* puArgErr)
2191 saxlocator *This = impl_from_IVBSAXLocator( iface );
2192 ITypeInfo *typeinfo;
2193 HRESULT hr;
2195 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2196 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2198 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2199 if(SUCCEEDED(hr))
2201 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2202 pDispParams, pVarResult, pExcepInfo, puArgErr);
2203 ITypeInfo_Release(typeinfo);
2206 return hr;
2209 /*** IVBSAXLocator methods ***/
2210 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2211 IVBSAXLocator* iface,
2212 int *pnColumn)
2214 saxlocator *This = impl_from_IVBSAXLocator( iface );
2215 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2218 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2219 IVBSAXLocator* iface,
2220 int *pnLine)
2222 saxlocator *This = impl_from_IVBSAXLocator( iface );
2223 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2226 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2228 saxlocator *This = impl_from_IVBSAXLocator( iface );
2229 const WCHAR *publicidW;
2230 HRESULT hr;
2232 TRACE("(%p)->(%p)\n", This, ret);
2234 if (!ret)
2235 return E_POINTER;
2237 *ret = NULL;
2238 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2239 if (FAILED(hr))
2240 return hr;
2242 return return_bstr(publicidW, ret);
2245 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2247 saxlocator *This = impl_from_IVBSAXLocator( iface );
2248 const WCHAR *systemidW;
2249 HRESULT hr;
2251 TRACE("(%p)->(%p)\n", This, ret);
2253 if (!ret)
2254 return E_POINTER;
2256 *ret = NULL;
2257 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2258 if (FAILED(hr))
2259 return hr;
2261 return return_bstr(systemidW, ret);
2264 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2266 ivbsaxlocator_QueryInterface,
2267 ivbsaxlocator_AddRef,
2268 ivbsaxlocator_Release,
2269 ivbsaxlocator_GetTypeInfoCount,
2270 ivbsaxlocator_GetTypeInfo,
2271 ivbsaxlocator_GetIDsOfNames,
2272 ivbsaxlocator_Invoke,
2273 ivbsaxlocator_get_columnNumber,
2274 ivbsaxlocator_get_lineNumber,
2275 ivbsaxlocator_get_publicId,
2276 ivbsaxlocator_get_systemId
2279 /*** ISAXLocator interface ***/
2280 /*** IUnknown methods ***/
2281 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2283 saxlocator *This = impl_from_ISAXLocator( iface );
2285 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2287 *ppvObject = NULL;
2289 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2290 IsEqualGUID( riid, &IID_ISAXLocator ))
2292 *ppvObject = iface;
2294 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2296 *ppvObject = &This->ISAXAttributes_iface;
2298 else
2300 WARN("interface %s not implemented\n", debugstr_guid(riid));
2301 return E_NOINTERFACE;
2304 ISAXLocator_AddRef( iface );
2306 return S_OK;
2309 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2311 saxlocator *This = impl_from_ISAXLocator( iface );
2312 ULONG ref = InterlockedIncrement( &This->ref );
2313 TRACE("(%p)->(%d)\n", This, ref);
2314 return ref;
2317 static ULONG WINAPI isaxlocator_Release(
2318 ISAXLocator* iface)
2320 saxlocator *This = impl_from_ISAXLocator( iface );
2321 LONG ref = InterlockedDecrement( &This->ref );
2323 TRACE("(%p)->(%d)\n", This, ref );
2325 if (ref == 0)
2327 element_entry *element, *element2;
2328 int index;
2330 SysFreeString(This->publicId);
2331 SysFreeString(This->systemId);
2332 SysFreeString(This->namespaceUri);
2334 for(index = 0; index < This->attr_alloc_count; index++)
2336 SysFreeString(This->attributes[index].szLocalname);
2337 SysFreeString(This->attributes[index].szValue);
2338 SysFreeString(This->attributes[index].szQName);
2340 heap_free(This->attributes);
2342 /* element stack */
2343 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2345 list_remove(&element->entry);
2346 free_element_entry(element);
2349 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2350 heap_free( This );
2353 return ref;
2356 /*** ISAXLocator methods ***/
2357 static HRESULT WINAPI isaxlocator_getColumnNumber(
2358 ISAXLocator* iface,
2359 int *pnColumn)
2361 saxlocator *This = impl_from_ISAXLocator( iface );
2363 *pnColumn = This->column;
2364 return S_OK;
2367 static HRESULT WINAPI isaxlocator_getLineNumber(
2368 ISAXLocator* iface,
2369 int *pnLine)
2371 saxlocator *This = impl_from_ISAXLocator( iface );
2373 *pnLine = This->line;
2374 return S_OK;
2377 static HRESULT WINAPI isaxlocator_getPublicId(
2378 ISAXLocator* iface,
2379 const WCHAR ** ppwchPublicId)
2381 BSTR publicId;
2382 saxlocator *This = impl_from_ISAXLocator( iface );
2384 SysFreeString(This->publicId);
2386 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2387 if(SysStringLen(publicId))
2388 This->publicId = publicId;
2389 else
2391 SysFreeString(publicId);
2392 This->publicId = NULL;
2395 *ppwchPublicId = This->publicId;
2396 return S_OK;
2399 static HRESULT WINAPI isaxlocator_getSystemId(
2400 ISAXLocator* iface,
2401 const WCHAR ** ppwchSystemId)
2403 BSTR systemId;
2404 saxlocator *This = impl_from_ISAXLocator( iface );
2406 SysFreeString(This->systemId);
2408 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2409 if(SysStringLen(systemId))
2410 This->systemId = systemId;
2411 else
2413 SysFreeString(systemId);
2414 This->systemId = NULL;
2417 *ppwchSystemId = This->systemId;
2418 return S_OK;
2421 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2423 isaxlocator_QueryInterface,
2424 isaxlocator_AddRef,
2425 isaxlocator_Release,
2426 isaxlocator_getColumnNumber,
2427 isaxlocator_getLineNumber,
2428 isaxlocator_getPublicId,
2429 isaxlocator_getSystemId
2432 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2434 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2435 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2437 saxlocator *locator;
2439 locator = heap_alloc( sizeof (*locator) );
2440 if( !locator )
2441 return E_OUTOFMEMORY;
2443 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2444 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2445 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2446 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2447 locator->ref = 1;
2448 locator->vbInterface = vbInterface;
2450 locator->saxreader = reader;
2451 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2453 locator->pParserCtxt = NULL;
2454 locator->publicId = NULL;
2455 locator->systemId = NULL;
2456 locator->line = reader->version < MSXML4 ? 0 : 1;
2457 locator->column = 0;
2458 locator->ret = S_OK;
2459 if (locator->saxreader->version >= MSXML6)
2460 locator->namespaceUri = SysAllocString(w3xmlns);
2461 else
2462 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2463 if(!locator->namespaceUri)
2465 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2466 heap_free(locator);
2467 return E_OUTOFMEMORY;
2470 locator->attr_alloc_count = 8;
2471 locator->attr_count = 0;
2472 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2473 if(!locator->attributes)
2475 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2476 SysFreeString(locator->namespaceUri);
2477 heap_free(locator);
2478 return E_OUTOFMEMORY;
2481 list_init(&locator->elements);
2483 *ppsaxlocator = locator;
2485 TRACE("returning %p\n", *ppsaxlocator);
2487 return S_OK;
2490 /*** SAXXMLReader internal functions ***/
2491 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2493 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2494 xmlChar *enc_name = NULL;
2495 saxlocator *locator;
2496 HRESULT hr;
2498 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2500 hr = SAXLocator_create(This, &locator, vbInterface);
2501 if (FAILED(hr))
2502 return hr;
2504 if (size >= 4)
2506 const unsigned char *buff = (unsigned char*)buffer;
2508 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2509 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2510 TRACE("detected encoding: %s\n", enc_name);
2511 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2512 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2513 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2515 buffer += 3;
2516 size -= 3;
2520 /* if libxml2 detection failed try to guess */
2521 if (encoding == XML_CHAR_ENCODING_NONE)
2523 const WCHAR *ptr = (WCHAR*)buffer;
2524 /* xml declaration with possibly specfied encoding will be still handled by parser */
2525 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2527 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2528 encoding = XML_CHAR_ENCODING_UTF16LE;
2531 else if (encoding == XML_CHAR_ENCODING_UTF8)
2532 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2533 else
2534 enc_name = NULL;
2536 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2537 if (!locator->pParserCtxt)
2539 ISAXLocator_Release(&locator->ISAXLocator_iface);
2540 return E_FAIL;
2543 if (enc_name)
2545 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2546 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2547 TRACE("switching to %s\n", enc_name);
2548 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2552 xmlFree(locator->pParserCtxt->sax);
2553 locator->pParserCtxt->sax = &locator->saxreader->sax;
2554 locator->pParserCtxt->userData = locator;
2556 This->isParsing = TRUE;
2557 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2558 hr = E_FAIL;
2559 else
2560 hr = locator->ret;
2561 This->isParsing = FALSE;
2563 if(locator->pParserCtxt)
2565 locator->pParserCtxt->sax = NULL;
2566 xmlFreeParserCtxt(locator->pParserCtxt);
2567 locator->pParserCtxt = NULL;
2570 ISAXLocator_Release(&locator->ISAXLocator_iface);
2571 return hr;
2574 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2576 saxlocator *locator;
2577 HRESULT hr;
2578 ULONG dataRead;
2579 char data[2048];
2580 int ret;
2582 dataRead = 0;
2583 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2584 if(FAILED(hr)) return hr;
2586 hr = SAXLocator_create(This, &locator, vbInterface);
2587 if(FAILED(hr)) return hr;
2589 locator->pParserCtxt = xmlCreatePushParserCtxt(
2590 &locator->saxreader->sax, locator,
2591 data, dataRead, NULL);
2592 if(!locator->pParserCtxt)
2594 ISAXLocator_Release(&locator->ISAXLocator_iface);
2595 return E_FAIL;
2598 This->isParsing = TRUE;
2600 do {
2601 dataRead = 0;
2602 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2603 if (FAILED(hr) || !dataRead) break;
2605 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2606 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2607 }while(hr == S_OK);
2609 if(SUCCEEDED(hr))
2611 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2612 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2616 This->isParsing = FALSE;
2618 xmlFreeParserCtxt(locator->pParserCtxt);
2619 locator->pParserCtxt = NULL;
2620 ISAXLocator_Release(&locator->ISAXLocator_iface);
2621 return hr;
2624 static HRESULT internal_parse(
2625 saxreader* This,
2626 VARIANT varInput,
2627 BOOL vbInterface)
2629 HRESULT hr;
2631 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2633 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2634 free_bstr_pool(&This->pool);
2636 switch(V_VT(&varInput))
2638 case VT_BSTR:
2639 case VT_BSTR|VT_BYREF:
2641 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2642 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2643 break;
2645 case VT_ARRAY|VT_UI1: {
2646 void *pSAData;
2647 LONG lBound, uBound;
2648 ULONG dataRead;
2650 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2651 if(hr != S_OK) break;
2652 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2653 if(hr != S_OK) break;
2654 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2655 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2656 if(hr != S_OK) break;
2657 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2658 SafeArrayUnaccessData(V_ARRAY(&varInput));
2659 break;
2661 case VT_UNKNOWN:
2662 case VT_DISPATCH: {
2663 IPersistStream *persistStream;
2664 ISequentialStream *stream = NULL;
2665 IXMLDOMDocument *xmlDoc;
2667 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2668 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2670 BSTR bstrData;
2672 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2673 hr = internal_parseBuffer(This, (const char*)bstrData,
2674 SysStringByteLen(bstrData), vbInterface);
2675 IXMLDOMDocument_Release(xmlDoc);
2676 SysFreeString(bstrData);
2677 break;
2680 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2681 &IID_IPersistStream, (void**)&persistStream) == S_OK)
2683 IStream *stream_copy;
2685 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy);
2686 if(hr != S_OK)
2688 IPersistStream_Release(persistStream);
2689 return hr;
2692 hr = IPersistStream_Save(persistStream, stream_copy, TRUE);
2693 IPersistStream_Release(persistStream);
2694 if(hr == S_OK)
2695 IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream);
2697 IStream_Release(stream_copy);
2700 /* try base interface first */
2701 if(!stream)
2703 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2704 if (!stream)
2705 /* this should never happen if IStream is implemented properly, but just in case */
2706 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2709 if(stream)
2711 hr = internal_parseStream(This, stream, vbInterface);
2712 ISequentialStream_Release(stream);
2714 else
2716 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2717 hr = E_INVALIDARG;
2720 break;
2722 default:
2723 WARN("vt %d not implemented\n", V_VT(&varInput));
2724 hr = E_INVALIDARG;
2727 return hr;
2730 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2732 saxreader *This = obj;
2734 return internal_parseBuffer(This, ptr, len, TRUE);
2737 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2739 saxreader *This = obj;
2741 return internal_parseBuffer(This, ptr, len, FALSE);
2744 static HRESULT internal_parseURL(
2745 saxreader* This,
2746 const WCHAR *url,
2747 BOOL vbInterface)
2749 IMoniker *mon;
2750 bsc_t *bsc;
2751 HRESULT hr;
2753 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2755 hr = create_moniker_from_url(url, &mon);
2756 if(FAILED(hr))
2757 return hr;
2759 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2760 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2761 IMoniker_Release(mon);
2763 if(FAILED(hr))
2764 return hr;
2766 return detach_bsc(bsc);
2769 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2771 const IID *riid;
2773 if (V_VT(v) == VT_EMPTY)
2774 return saxreader_put_handler(This, type, NULL, vb);
2776 switch (type)
2778 case SAXDeclHandler:
2779 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2780 break;
2781 case SAXLexicalHandler:
2782 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2783 break;
2784 default:
2785 ERR("wrong handler type %d\n", type);
2786 return E_FAIL;
2789 switch (V_VT(v))
2791 case VT_DISPATCH:
2792 case VT_UNKNOWN:
2794 IUnknown *handler = NULL;
2796 if (V_UNKNOWN(v))
2798 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2799 if (FAILED(hr)) return hr;
2802 saxreader_put_handler(This, type, handler, vb);
2803 if (handler) IUnknown_Release(handler);
2804 break;
2806 default:
2807 ERR("value type %d not supported\n", V_VT(v));
2808 return E_INVALIDARG;
2811 return S_OK;
2814 static HRESULT internal_putProperty(
2815 saxreader* This,
2816 const WCHAR *prop,
2817 VARIANT value,
2818 BOOL vbInterface)
2820 VARIANT *v;
2822 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2824 if (This->isParsing) return E_FAIL;
2826 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2827 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2828 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2830 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2831 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2833 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2835 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2836 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2837 return E_NOTIMPL;
2840 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2842 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2843 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2844 return E_NOTIMPL;
2847 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2849 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2850 return E_NOTIMPL;
2852 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2853 return E_FAIL;
2855 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2856 return E_NOTIMPL;
2858 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2859 return E_NOTIMPL;
2861 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2862 return E_FAIL;
2864 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2865 return E_FAIL;
2867 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2868 return E_FAIL;
2870 return E_INVALIDARG;
2873 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2875 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2877 if (!value) return E_POINTER;
2879 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2881 V_VT(value) = VT_UNKNOWN;
2882 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2883 return S_OK;
2886 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2888 V_VT(value) = VT_UNKNOWN;
2889 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2890 return S_OK;
2893 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2895 V_VT(value) = VT_BSTR;
2896 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2897 return S_OK;
2900 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2902 return E_NOTIMPL;
2905 /*** IVBSAXXMLReader interface ***/
2906 /*** IUnknown methods ***/
2907 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2909 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2911 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2913 *ppvObject = NULL;
2915 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2916 IsEqualGUID( riid, &IID_IDispatch ) ||
2917 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2919 *ppvObject = iface;
2921 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2923 *ppvObject = &This->ISAXXMLReader_iface;
2925 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2927 return *ppvObject ? S_OK : E_NOINTERFACE;
2929 else
2931 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2932 return E_NOINTERFACE;
2935 IVBSAXXMLReader_AddRef( iface );
2937 return S_OK;
2940 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2942 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2943 TRACE("%p\n", This );
2944 return InterlockedIncrement( &This->ref );
2947 static ULONG WINAPI saxxmlreader_Release(
2948 IVBSAXXMLReader* iface)
2950 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2951 LONG ref;
2953 TRACE("%p\n", This );
2955 ref = InterlockedDecrement( &This->ref );
2956 if ( ref == 0 )
2958 int i;
2960 for (i = 0; i < SAXHandler_Last; i++)
2962 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2964 if (saxiface->handler)
2965 IUnknown_Release(saxiface->handler);
2967 if (saxiface->vbhandler)
2968 IUnknown_Release(saxiface->vbhandler);
2971 SysFreeString(This->xmldecl_version);
2972 free_bstr_pool(&This->pool);
2974 heap_free( This );
2977 return ref;
2979 /*** IDispatch ***/
2980 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2982 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2983 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2986 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2987 IVBSAXXMLReader *iface,
2988 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2990 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2991 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2992 iTInfo, lcid, ppTInfo);
2995 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2996 IVBSAXXMLReader *iface,
2997 REFIID riid,
2998 LPOLESTR* rgszNames,
2999 UINT cNames,
3000 LCID lcid,
3001 DISPID* rgDispId)
3003 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3004 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
3005 riid, rgszNames, cNames, lcid, rgDispId);
3008 static HRESULT WINAPI saxxmlreader_Invoke(
3009 IVBSAXXMLReader *iface,
3010 DISPID dispIdMember,
3011 REFIID riid,
3012 LCID lcid,
3013 WORD wFlags,
3014 DISPPARAMS* pDispParams,
3015 VARIANT* pVarResult,
3016 EXCEPINFO* pExcepInfo,
3017 UINT* puArgErr)
3019 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3020 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3021 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3024 /*** IVBSAXXMLReader methods ***/
3025 static HRESULT WINAPI saxxmlreader_getFeature(
3026 IVBSAXXMLReader* iface,
3027 BSTR feature_name,
3028 VARIANT_BOOL *value)
3030 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3031 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3034 static HRESULT WINAPI saxxmlreader_putFeature(
3035 IVBSAXXMLReader* iface,
3036 BSTR feature_name,
3037 VARIANT_BOOL value)
3039 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3040 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3043 static HRESULT WINAPI saxxmlreader_getProperty(
3044 IVBSAXXMLReader* iface,
3045 BSTR prop,
3046 VARIANT *value)
3048 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3049 return internal_getProperty(This, prop, value, TRUE);
3052 static HRESULT WINAPI saxxmlreader_putProperty(
3053 IVBSAXXMLReader* iface,
3054 BSTR pProp,
3055 VARIANT value)
3057 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3058 return internal_putProperty(This, pProp, value, TRUE);
3061 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3062 IVBSAXXMLReader* iface,
3063 IVBSAXEntityResolver **resolver)
3065 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3066 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3069 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3070 IVBSAXXMLReader* iface,
3071 IVBSAXEntityResolver *resolver)
3073 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3074 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3077 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3078 IVBSAXXMLReader* iface,
3079 IVBSAXContentHandler **handler)
3081 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3082 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3085 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3086 IVBSAXXMLReader* iface,
3087 IVBSAXContentHandler *handler)
3089 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3090 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3093 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3094 IVBSAXXMLReader* iface,
3095 IVBSAXDTDHandler **handler)
3097 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3098 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3101 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3102 IVBSAXXMLReader* iface,
3103 IVBSAXDTDHandler *handler)
3105 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3106 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3109 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3110 IVBSAXXMLReader* iface,
3111 IVBSAXErrorHandler **handler)
3113 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3114 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3117 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3118 IVBSAXXMLReader* iface,
3119 IVBSAXErrorHandler *handler)
3121 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3122 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3125 static HRESULT WINAPI saxxmlreader_get_baseURL(
3126 IVBSAXXMLReader* iface,
3127 BSTR *pBaseUrl)
3129 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3131 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3132 return E_NOTIMPL;
3135 static HRESULT WINAPI saxxmlreader_put_baseURL(
3136 IVBSAXXMLReader* iface,
3137 BSTR pBaseUrl)
3139 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3140 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3143 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3144 IVBSAXXMLReader* iface,
3145 BSTR *pSecureBaseUrl)
3147 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3149 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3150 return E_NOTIMPL;
3153 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3154 IVBSAXXMLReader* iface,
3155 BSTR secureBaseUrl)
3157 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3158 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3161 static HRESULT WINAPI saxxmlreader_parse(
3162 IVBSAXXMLReader* iface,
3163 VARIANT varInput)
3165 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3166 return internal_parse(This, varInput, TRUE);
3169 static HRESULT WINAPI saxxmlreader_parseURL(
3170 IVBSAXXMLReader* iface,
3171 BSTR url)
3173 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3174 return internal_parseURL(This, url, TRUE);
3177 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3179 saxxmlreader_QueryInterface,
3180 saxxmlreader_AddRef,
3181 saxxmlreader_Release,
3182 saxxmlreader_GetTypeInfoCount,
3183 saxxmlreader_GetTypeInfo,
3184 saxxmlreader_GetIDsOfNames,
3185 saxxmlreader_Invoke,
3186 saxxmlreader_getFeature,
3187 saxxmlreader_putFeature,
3188 saxxmlreader_getProperty,
3189 saxxmlreader_putProperty,
3190 saxxmlreader_get_entityResolver,
3191 saxxmlreader_put_entityResolver,
3192 saxxmlreader_get_contentHandler,
3193 saxxmlreader_put_contentHandler,
3194 saxxmlreader_get_dtdHandler,
3195 saxxmlreader_put_dtdHandler,
3196 saxxmlreader_get_errorHandler,
3197 saxxmlreader_put_errorHandler,
3198 saxxmlreader_get_baseURL,
3199 saxxmlreader_put_baseURL,
3200 saxxmlreader_get_secureBaseURL,
3201 saxxmlreader_put_secureBaseURL,
3202 saxxmlreader_parse,
3203 saxxmlreader_parseURL
3206 /*** ISAXXMLReader interface ***/
3207 /*** IUnknown methods ***/
3208 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3210 saxreader *This = impl_from_ISAXXMLReader( iface );
3211 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3214 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3216 saxreader *This = impl_from_ISAXXMLReader( iface );
3217 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3220 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3222 saxreader *This = impl_from_ISAXXMLReader( iface );
3223 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3226 /*** ISAXXMLReader methods ***/
3227 static HRESULT WINAPI isaxxmlreader_getFeature(
3228 ISAXXMLReader* iface,
3229 const WCHAR *feature_name,
3230 VARIANT_BOOL *value)
3232 saxreader *This = impl_from_ISAXXMLReader( iface );
3233 saxreader_feature feature;
3235 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3237 feature = get_saxreader_feature(feature_name);
3238 if (feature == Namespaces || feature == NamespacePrefixes)
3239 return get_feature_value(This, feature, value);
3241 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3242 return E_NOTIMPL;
3245 static HRESULT WINAPI isaxxmlreader_putFeature(
3246 ISAXXMLReader* iface,
3247 const WCHAR *feature_name,
3248 VARIANT_BOOL value)
3250 saxreader *This = impl_from_ISAXXMLReader( iface );
3251 saxreader_feature feature;
3253 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3255 feature = get_saxreader_feature(feature_name);
3257 /* accepted cases */
3258 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
3259 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
3260 feature == Namespaces ||
3261 feature == NamespacePrefixes)
3263 return set_feature_value(This, feature, value);
3266 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
3268 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3269 return set_feature_value(This, feature, value);
3272 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3273 return E_NOTIMPL;
3276 static HRESULT WINAPI isaxxmlreader_getProperty(
3277 ISAXXMLReader* iface,
3278 const WCHAR *prop,
3279 VARIANT *value)
3281 saxreader *This = impl_from_ISAXXMLReader( iface );
3282 return internal_getProperty(This, prop, value, FALSE);
3285 static HRESULT WINAPI isaxxmlreader_putProperty(
3286 ISAXXMLReader* iface,
3287 const WCHAR *pProp,
3288 VARIANT value)
3290 saxreader *This = impl_from_ISAXXMLReader( iface );
3291 return internal_putProperty(This, pProp, value, FALSE);
3294 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3295 ISAXXMLReader* iface,
3296 ISAXEntityResolver **resolver)
3298 saxreader *This = impl_from_ISAXXMLReader( iface );
3299 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3302 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3303 ISAXXMLReader* iface,
3304 ISAXEntityResolver *resolver)
3306 saxreader *This = impl_from_ISAXXMLReader( iface );
3307 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3310 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3311 ISAXXMLReader* iface,
3312 ISAXContentHandler **handler)
3314 saxreader *This = impl_from_ISAXXMLReader( iface );
3315 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3318 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3319 ISAXXMLReader* iface,
3320 ISAXContentHandler *handler)
3322 saxreader *This = impl_from_ISAXXMLReader( iface );
3323 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3326 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3327 ISAXXMLReader* iface,
3328 ISAXDTDHandler **handler)
3330 saxreader *This = impl_from_ISAXXMLReader( iface );
3331 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3334 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3335 ISAXXMLReader* iface,
3336 ISAXDTDHandler *handler)
3338 saxreader *This = impl_from_ISAXXMLReader( iface );
3339 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3342 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3343 ISAXXMLReader* iface,
3344 ISAXErrorHandler **handler)
3346 saxreader *This = impl_from_ISAXXMLReader( iface );
3347 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3350 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3352 saxreader *This = impl_from_ISAXXMLReader( iface );
3353 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3356 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3357 ISAXXMLReader* iface,
3358 const WCHAR **base_url)
3360 saxreader *This = impl_from_ISAXXMLReader( iface );
3362 FIXME("(%p)->(%p) stub\n", This, base_url);
3363 return E_NOTIMPL;
3366 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3367 ISAXXMLReader* iface,
3368 const WCHAR *pBaseUrl)
3370 saxreader *This = impl_from_ISAXXMLReader( iface );
3372 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3373 return E_NOTIMPL;
3376 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3377 ISAXXMLReader* iface,
3378 const WCHAR **pSecureBaseUrl)
3380 saxreader *This = impl_from_ISAXXMLReader( iface );
3381 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3382 return E_NOTIMPL;
3385 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3386 ISAXXMLReader* iface,
3387 const WCHAR *secureBaseUrl)
3389 saxreader *This = impl_from_ISAXXMLReader( iface );
3391 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3392 return E_NOTIMPL;
3395 static HRESULT WINAPI isaxxmlreader_parse(
3396 ISAXXMLReader* iface,
3397 VARIANT varInput)
3399 saxreader *This = impl_from_ISAXXMLReader( iface );
3400 return internal_parse(This, varInput, FALSE);
3403 static HRESULT WINAPI isaxxmlreader_parseURL(
3404 ISAXXMLReader* iface,
3405 const WCHAR *url)
3407 saxreader *This = impl_from_ISAXXMLReader( iface );
3408 return internal_parseURL(This, url, FALSE);
3411 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3413 isaxxmlreader_QueryInterface,
3414 isaxxmlreader_AddRef,
3415 isaxxmlreader_Release,
3416 isaxxmlreader_getFeature,
3417 isaxxmlreader_putFeature,
3418 isaxxmlreader_getProperty,
3419 isaxxmlreader_putProperty,
3420 isaxxmlreader_getEntityResolver,
3421 isaxxmlreader_putEntityResolver,
3422 isaxxmlreader_getContentHandler,
3423 isaxxmlreader_putContentHandler,
3424 isaxxmlreader_getDTDHandler,
3425 isaxxmlreader_putDTDHandler,
3426 isaxxmlreader_getErrorHandler,
3427 isaxxmlreader_putErrorHandler,
3428 isaxxmlreader_getBaseURL,
3429 isaxxmlreader_putBaseURL,
3430 isaxxmlreader_getSecureBaseURL,
3431 isaxxmlreader_putSecureBaseURL,
3432 isaxxmlreader_parse,
3433 isaxxmlreader_parseURL
3436 static const tid_t saxreader_iface_tids[] = {
3437 IVBSAXXMLReader_tid,
3440 static dispex_static_data_t saxreader_dispex = {
3441 NULL,
3442 IVBSAXXMLReader_tid,
3443 NULL,
3444 saxreader_iface_tids
3447 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3449 saxreader *reader;
3451 TRACE("(%p)\n", ppObj);
3453 reader = heap_alloc( sizeof (*reader) );
3454 if( !reader )
3455 return E_OUTOFMEMORY;
3457 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3458 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3459 reader->ref = 1;
3460 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3461 reader->isParsing = FALSE;
3462 reader->xmldecl_version = NULL;
3463 reader->pool.pool = NULL;
3464 reader->pool.index = 0;
3465 reader->pool.len = 0;
3466 reader->features = Namespaces | NamespacePrefixes;
3467 reader->version = version;
3469 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3471 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3472 reader->sax.initialized = XML_SAX2_MAGIC;
3473 reader->sax.startDocument = libxmlStartDocument;
3474 reader->sax.endDocument = libxmlEndDocument;
3475 reader->sax.startElementNs = libxmlStartElementNS;
3476 reader->sax.endElementNs = libxmlEndElementNS;
3477 reader->sax.characters = libxmlCharacters;
3478 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3479 reader->sax.comment = libxmlComment;
3480 reader->sax.error = libxmlFatalError;
3481 reader->sax.fatalError = libxmlFatalError;
3482 reader->sax.cdataBlock = libxml_cdatablock;
3483 reader->sax.resolveEntity = libxmlresolveentity;
3485 *ppObj = &reader->IVBSAXXMLReader_iface;
3487 TRACE("returning iface %p\n", *ppObj);
3489 return S_OK;
3492 #else
3494 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3496 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3497 "libxml2 support was not present at compile time.\n");
3498 return E_NOTIMPL;
3501 #endif