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