odbccp32: Add ordinals to spec file.
[wine.git] / dlls / msxml3 / saxreader.c
blob7a9e410ea38f61b16bdf5ae30d8c4592fdb14cee
1 /*
2 * SAX Reader implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2008 Piotr Caban
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 # include <libxml/SAX2.h>
30 # include <libxml/parserInternals.h>
31 #endif
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "winnls.h"
37 #include "ole2.h"
38 #include "msxml6.h"
39 #include "wininet.h"
40 #include "urlmon.h"
41 #include "winreg.h"
42 #include "shlwapi.h"
44 #include "wine/debug.h"
46 #include "msxml_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 #ifdef HAVE_LIBXML2
52 typedef enum
54 FeatureUnknown = 0,
55 ExhaustiveErrors = 1 << 1,
56 ExternalGeneralEntities = 1 << 2,
57 ExternalParameterEntities = 1 << 3,
58 ForcedResync = 1 << 4,
59 NamespacePrefixes = 1 << 5,
60 Namespaces = 1 << 6,
61 ParameterEntities = 1 << 7,
62 PreserveSystemIndentifiers = 1 << 8,
63 ProhibitDTD = 1 << 9,
64 SchemaValidation = 1 << 10,
65 ServerHttpRequest = 1 << 11,
66 SuppressValidationfatalError = 1 << 12,
67 UseInlineSchema = 1 << 13,
68 UseSchemaLocation = 1 << 14,
69 LexicalHandlerParEntities = 1 << 15
70 } saxreader_feature;
72 /* feature names */
73 static const WCHAR FeatureExternalGeneralEntitiesW[] = {
74 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/',
75 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l',
76 '-','e','n','t','i','t','i','e','s',0
79 static const WCHAR FeatureExternalParameterEntitiesW[] = {
80 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
81 '/','e','x','t','e','r','n','a','l','-','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
84 static const WCHAR FeatureLexicalHandlerParEntitiesW[] = {
85 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
86 '/','l','e','x','i','c','a','l','-','h','a','n','d','l','e','r','/','p','a','r','a','m','e','t','e','r','-','e','n','t','i','t','i','e','s',0
89 static const WCHAR FeatureProhibitDTDW[] = {
90 'p','r','o','h','i','b','i','t','-','d','t','d',0
93 static const WCHAR FeatureNamespacesW[] = {
94 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
95 '/','n','a','m','e','s','p','a','c','e','s',0
98 static const WCHAR FeatureNamespacePrefixesW[] = {
99 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
100 '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
103 struct saxreader_feature_pair
105 saxreader_feature feature;
106 const WCHAR *name;
109 static const struct saxreader_feature_pair saxreader_feature_map[] = {
110 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
111 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
112 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
113 { NamespacePrefixes, FeatureNamespacePrefixesW },
114 { Namespaces, FeatureNamespacesW },
115 { ProhibitDTD, FeatureProhibitDTDW }
118 static saxreader_feature get_saxreader_feature(const WCHAR *name)
120 int min, max, n, c;
122 min = 0;
123 max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
125 while (min <= max)
127 n = (min+max)/2;
129 c = strcmpW(saxreader_feature_map[n].name, name);
130 if (!c)
131 return saxreader_feature_map[n].feature;
133 if (c > 0)
134 max = n-1;
135 else
136 min = n+1;
139 return FeatureUnknown;
142 struct bstrpool
144 BSTR *pool;
145 unsigned int index;
146 unsigned int len;
149 typedef struct
151 BSTR prefix;
152 BSTR uri;
153 } ns;
155 typedef struct
157 struct list entry;
158 BSTR prefix;
159 BSTR local;
160 BSTR qname;
161 ns *ns; /* namespaces defined in this particular element */
162 int ns_count;
163 } element_entry;
165 enum saxhandler_type
167 SAXContentHandler = 0,
168 SAXDeclHandler,
169 SAXDTDHandler,
170 SAXEntityResolver,
171 SAXErrorHandler,
172 SAXLexicalHandler,
173 SAXHandler_Last
176 struct saxanyhandler_iface
178 IUnknown *handler;
179 IUnknown *vbhandler;
182 struct saxcontenthandler_iface
184 ISAXContentHandler *handler;
185 IVBSAXContentHandler *vbhandler;
188 struct saxerrorhandler_iface
190 ISAXErrorHandler *handler;
191 IVBSAXErrorHandler *vbhandler;
194 struct saxlexicalhandler_iface
196 ISAXLexicalHandler *handler;
197 IVBSAXLexicalHandler *vbhandler;
200 struct saxentityresolver_iface
202 ISAXEntityResolver *handler;
203 IVBSAXEntityResolver *vbhandler;
206 struct saxhandler_iface
208 union {
209 struct saxcontenthandler_iface content;
210 struct saxentityresolver_iface entityresolver;
211 struct saxerrorhandler_iface error;
212 struct saxlexicalhandler_iface lexical;
213 struct saxanyhandler_iface anyhandler;
214 } u;
217 typedef struct
219 DispatchEx dispex;
220 IVBSAXXMLReader IVBSAXXMLReader_iface;
221 ISAXXMLReader ISAXXMLReader_iface;
222 LONG ref;
224 struct saxhandler_iface saxhandlers[SAXHandler_Last];
225 xmlSAXHandler sax;
226 BOOL isParsing;
227 struct bstrpool pool;
228 saxreader_feature features;
229 BSTR xmldecl_version;
230 MSXML_VERSION version;
231 } saxreader;
233 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
235 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
236 IUnknown *unk = (IUnknown*)ptr;
238 if (unk)
239 IUnknown_AddRef(unk);
241 if ((vb && iface->vbhandler) || (!vb && iface->handler))
242 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
244 if (vb)
245 iface->vbhandler = unk;
246 else
247 iface->handler = unk;
249 return S_OK;
252 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
254 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
256 if (!ret) return E_POINTER;
258 if ((vb && iface->vbhandler) || (!vb && iface->handler))
260 if (vb)
261 IUnknown_AddRef(iface->vbhandler);
262 else
263 IUnknown_AddRef(iface->handler);
266 *ret = vb ? iface->vbhandler : iface->handler;
268 return S_OK;
271 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
273 return &reader->saxhandlers[SAXContentHandler].u.content;
276 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
278 return &reader->saxhandlers[SAXErrorHandler].u.error;
281 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
283 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
286 typedef struct
288 IVBSAXLocator IVBSAXLocator_iface;
289 ISAXLocator ISAXLocator_iface;
290 IVBSAXAttributes IVBSAXAttributes_iface;
291 ISAXAttributes ISAXAttributes_iface;
292 LONG ref;
293 saxreader *saxreader;
294 HRESULT ret;
295 xmlParserCtxtPtr pParserCtxt;
296 BSTR publicId;
297 BSTR systemId;
298 int line;
299 int column;
300 BOOL vbInterface;
301 struct list elements;
303 BSTR namespaceUri;
304 int attributesSize;
305 int nb_attributes;
306 struct _attributes
308 BSTR szLocalname;
309 BSTR szURI;
310 BSTR szValue;
311 BSTR szQName;
312 } *attributes;
313 } saxlocator;
315 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
317 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
320 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
322 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
325 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
327 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
330 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
332 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
335 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
337 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
340 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
342 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
345 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
347 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
348 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
351 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
353 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
354 HRESULT hr;
356 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
358 if (locator->vbInterface)
359 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
360 else
361 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
363 return hr;
366 /* property names */
367 static const WCHAR PropertyCharsetW[] = {
368 'c','h','a','r','s','e','t',0
370 static const WCHAR PropertyXmlDeclVersionW[] = {
371 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
373 static const WCHAR PropertyDeclHandlerW[] = {
374 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
375 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
376 'd','e','c','l','a','r','a','t','i','o','n',
377 '-','h','a','n','d','l','e','r',0
379 static const WCHAR PropertyDomNodeW[] = {
380 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
381 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
382 'd','o','m','-','n','o','d','e',0
384 static const WCHAR PropertyInputSourceW[] = {
385 'i','n','p','u','t','-','s','o','u','r','c','e',0
387 static const WCHAR PropertyLexicalHandlerW[] = {
388 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
389 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
390 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
392 static const WCHAR PropertyMaxElementDepthW[] = {
393 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
395 static const WCHAR PropertyMaxXMLSizeW[] = {
396 'm','a','x','-','x','m','l','-','s','i','z','e',0
398 static const WCHAR PropertySchemaDeclHandlerW[] = {
399 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
400 'h','a','n','d','l','e','r',0
402 static const WCHAR PropertyXMLDeclEncodingW[] = {
403 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
405 static const WCHAR PropertyXMLDeclStandaloneW[] = {
406 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
408 static const WCHAR PropertyXMLDeclVersionW[] = {
409 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
412 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
414 /* handling of non-VARIANT_* values is version dependent */
415 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
416 value = VARIANT_FALSE;
417 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
418 value = VARIANT_TRUE;
420 if (value == VARIANT_TRUE)
421 reader->features |= feature;
422 else
423 reader->features &= ~feature;
425 return S_OK;
428 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
430 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
431 return S_OK;
434 static BOOL is_namespaces_enabled(const saxreader *reader)
436 return (reader->version < MSXML4) || (reader->features & Namespaces);
439 static BSTR build_qname(BSTR prefix, BSTR local)
441 if (prefix && *prefix)
443 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
444 WCHAR *ptr;
446 ptr = qname;
447 strcpyW(ptr, prefix);
448 ptr += SysStringLen(prefix);
449 *ptr++ = ':';
450 strcpyW(ptr, local);
451 return qname;
453 else
454 return SysAllocString(local);
457 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
458 const xmlChar **namespaces)
460 element_entry *ret;
461 int i;
463 ret = heap_alloc(sizeof(*ret));
464 if (!ret) return ret;
466 ret->local = bstr_from_xmlChar(local);
467 ret->prefix = bstr_from_xmlChar(prefix);
468 ret->qname = build_qname(ret->prefix, ret->local);
469 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
470 ret->ns_count = nb_ns;
472 for (i=0; i < nb_ns; i++)
474 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
475 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
478 return ret;
481 static void free_element_entry(element_entry *element)
483 int i;
485 for (i=0; i<element->ns_count;i++)
487 SysFreeString(element->ns[i].prefix);
488 SysFreeString(element->ns[i].uri);
491 SysFreeString(element->prefix);
492 SysFreeString(element->local);
493 SysFreeString(element->qname);
495 heap_free(element->ns);
496 heap_free(element);
499 static void push_element_ns(saxlocator *locator, element_entry *element)
501 list_add_head(&locator->elements, &element->entry);
504 static element_entry * pop_element_ns(saxlocator *locator)
506 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
508 if (element)
509 list_remove(&element->entry);
511 return element;
514 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
516 element_entry *element;
517 BSTR uriW;
518 int i;
520 if (!uri) return NULL;
522 uriW = bstr_from_xmlChar(uri);
524 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
526 for (i=0; i < element->ns_count; i++)
527 if (!strcmpW(uriW, element->ns[i].uri))
529 SysFreeString(uriW);
530 return element->ns[i].uri;
534 SysFreeString(uriW);
535 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
536 return NULL;
539 /* used to localize version dependent error check behaviour */
540 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
542 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
545 /* index value -1 means it tries to loop for a first time */
546 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
548 if (This->saxreader->version >= MSXML4)
550 if (*i == -1) *i = 0; else ++*i;
551 return *i < element->ns_count;
553 else
555 if (*i == -1) *i = element->ns_count-1; else --*i;
556 return *i >= 0;
560 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
562 if (!pool->pool)
564 pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool));
565 if (!pool->pool)
566 return FALSE;
568 pool->index = 0;
569 pool->len = 16;
571 else if (pool->index == pool->len)
573 BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc));
575 if (!realloc)
576 return FALSE;
578 pool->pool = realloc;
579 pool->len *= 2;
582 pool->pool[pool->index++] = pool_entry;
583 return TRUE;
586 static void free_bstr_pool(struct bstrpool *pool)
588 unsigned int i;
590 for (i = 0; i < pool->index; i++)
591 SysFreeString(pool->pool[i]);
593 HeapFree(GetProcessHeap(), 0, pool->pool);
595 pool->pool = NULL;
596 pool->index = pool->len = 0;
599 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
601 DWORD dLen;
602 BSTR bstr;
604 if (!buf)
605 return NULL;
607 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
608 if(len != -1) dLen++;
609 bstr = SysAllocStringLen(NULL, dLen-1);
610 if (!bstr)
611 return NULL;
612 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
613 if(len != -1) bstr[dLen-1] = '\0';
615 return bstr;
618 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
620 xmlChar *qname;
621 BSTR bstr;
623 if(!name) return NULL;
625 if(!prefix || !*prefix)
626 return bstr_from_xmlChar(name);
628 qname = xmlBuildQName(name, prefix, NULL, 0);
629 bstr = bstr_from_xmlChar(qname);
630 xmlFree(qname);
632 return bstr;
635 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
637 BSTR pool_entry = bstr_from_xmlChar(buf);
639 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
641 SysFreeString(pool_entry);
642 return NULL;
645 return pool_entry;
648 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
650 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
652 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
654 SysFreeString(pool_entry);
655 return NULL;
658 return pool_entry;
661 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
663 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
664 xmlStopParser(This->pParserCtxt);
665 This->ret = hr;
667 if (saxreader_has_handler(This, SAXErrorHandler))
669 WCHAR msg[1024];
670 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
671 NULL, hr, 0, msg, sizeof(msg), NULL))
673 FIXME("MSXML errors not yet supported.\n");
674 msg[0] = '\0';
677 if(This->vbInterface)
679 BSTR bstrMsg = SysAllocString(msg);
680 IVBSAXErrorHandler_fatalError(handler->vbhandler,
681 &This->IVBSAXLocator_iface, &bstrMsg, hr);
682 SysFreeString(bstrMsg);
684 else
685 ISAXErrorHandler_fatalError(handler->handler,
686 &This->ISAXLocator_iface, msg, hr);
690 static void update_position(saxlocator *This, BOOL fix_column)
692 const xmlChar *p = This->pParserCtxt->input->cur-1;
694 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
695 if(fix_column)
697 This->column = 1;
698 for(; *p!='\n' && *p!='\r' && p>=This->pParserCtxt->input->base; p--)
699 This->column++;
701 else
703 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
707 /*** IVBSAXAttributes interface ***/
708 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
709 IVBSAXAttributes* iface,
710 REFIID riid,
711 void **ppvObject)
713 saxlocator *This = impl_from_IVBSAXAttributes(iface);
714 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
715 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
718 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
720 saxlocator *This = impl_from_IVBSAXAttributes(iface);
721 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
724 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
726 saxlocator *This = impl_from_IVBSAXAttributes(iface);
727 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
730 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
732 saxlocator *This = impl_from_IVBSAXAttributes( iface );
734 TRACE("(%p)->(%p)\n", This, pctinfo);
736 *pctinfo = 1;
738 return S_OK;
741 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
742 IVBSAXAttributes *iface,
743 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
745 saxlocator *This = impl_from_IVBSAXAttributes( iface );
747 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
749 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
752 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
753 IVBSAXAttributes *iface,
754 REFIID riid,
755 LPOLESTR* rgszNames,
756 UINT cNames,
757 LCID lcid,
758 DISPID* rgDispId)
760 saxlocator *This = impl_from_IVBSAXAttributes( iface );
761 ITypeInfo *typeinfo;
762 HRESULT hr;
764 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
765 lcid, rgDispId);
767 if(!rgszNames || cNames == 0 || !rgDispId)
768 return E_INVALIDARG;
770 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
771 if(SUCCEEDED(hr))
773 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
774 ITypeInfo_Release(typeinfo);
777 return hr;
780 static HRESULT WINAPI ivbsaxattributes_Invoke(
781 IVBSAXAttributes *iface,
782 DISPID dispIdMember,
783 REFIID riid,
784 LCID lcid,
785 WORD wFlags,
786 DISPPARAMS* pDispParams,
787 VARIANT* pVarResult,
788 EXCEPINFO* pExcepInfo,
789 UINT* puArgErr)
791 saxlocator *This = impl_from_IVBSAXAttributes( iface );
792 ITypeInfo *typeinfo;
793 HRESULT hr;
795 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
796 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
798 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
799 if(SUCCEEDED(hr))
801 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
802 pDispParams, pVarResult, pExcepInfo, puArgErr);
803 ITypeInfo_Release(typeinfo);
806 return hr;
809 /*** IVBSAXAttributes methods ***/
810 static HRESULT WINAPI ivbsaxattributes_get_length(
811 IVBSAXAttributes* iface,
812 int *nLength)
814 saxlocator *This = impl_from_IVBSAXAttributes( iface );
815 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
818 static HRESULT WINAPI ivbsaxattributes_getURI(
819 IVBSAXAttributes* iface,
820 int nIndex,
821 BSTR *uri)
823 saxlocator *This = impl_from_IVBSAXAttributes( iface );
824 const WCHAR *uriW;
825 HRESULT hr;
826 int len;
828 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
830 if (!uri)
831 return E_POINTER;
833 *uri = NULL;
834 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
835 if (FAILED(hr))
836 return hr;
838 return return_bstrn(uriW, len, uri);
841 static HRESULT WINAPI ivbsaxattributes_getLocalName(
842 IVBSAXAttributes* iface,
843 int nIndex,
844 BSTR *name)
846 saxlocator *This = impl_from_IVBSAXAttributes( iface );
847 const WCHAR *nameW;
848 HRESULT hr;
849 int len;
851 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
853 if (!name)
854 return E_POINTER;
856 *name = NULL;
857 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
858 if (FAILED(hr))
859 return hr;
861 return return_bstrn(nameW, len, name);
864 static HRESULT WINAPI ivbsaxattributes_getQName(
865 IVBSAXAttributes* iface,
866 int nIndex,
867 BSTR *QName)
869 saxlocator *This = impl_from_IVBSAXAttributes( iface );
870 const WCHAR *nameW;
871 HRESULT hr;
872 int len;
874 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
876 if (!QName)
877 return E_POINTER;
879 *QName = NULL;
880 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
881 if (FAILED(hr))
882 return hr;
884 return return_bstrn(nameW, len, QName);
887 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
888 IVBSAXAttributes* iface,
889 BSTR uri,
890 BSTR localName,
891 int *index)
893 saxlocator *This = impl_from_IVBSAXAttributes( iface );
894 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
895 localName, SysStringLen(localName), index);
898 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
899 IVBSAXAttributes* iface,
900 BSTR QName,
901 int *index)
903 saxlocator *This = impl_from_IVBSAXAttributes( iface );
904 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
905 SysStringLen(QName), index);
908 static HRESULT WINAPI ivbsaxattributes_getType(
909 IVBSAXAttributes* iface,
910 int nIndex,
911 BSTR *type)
913 saxlocator *This = impl_from_IVBSAXAttributes( iface );
914 const WCHAR *typeW;
915 HRESULT hr;
916 int len;
918 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
920 if (!type)
921 return E_POINTER;
923 *type = NULL;
924 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
925 if (FAILED(hr))
926 return hr;
928 return return_bstrn(typeW, len, type);
931 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
932 IVBSAXAttributes* iface,
933 BSTR uri,
934 BSTR localName,
935 BSTR *type)
937 saxlocator *This = impl_from_IVBSAXAttributes( iface );
938 const WCHAR *typeW;
939 HRESULT hr;
940 int len;
942 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
944 if (!type)
945 return E_POINTER;
947 *type = NULL;
948 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
949 localName, SysStringLen(localName), &typeW, &len);
950 if (FAILED(hr))
951 return hr;
953 return return_bstrn(typeW, len, type);
956 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
957 IVBSAXAttributes* iface,
958 BSTR QName,
959 BSTR *type)
961 saxlocator *This = impl_from_IVBSAXAttributes( iface );
962 const WCHAR *typeW;
963 HRESULT hr;
964 int len;
966 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
968 if (!type)
969 return E_POINTER;
971 *type = NULL;
972 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
973 &typeW, &len);
974 if (FAILED(hr))
975 return hr;
977 return return_bstrn(typeW, len, type);
980 static HRESULT WINAPI ivbsaxattributes_getValue(
981 IVBSAXAttributes* iface,
982 int nIndex,
983 BSTR *value)
985 saxlocator *This = impl_from_IVBSAXAttributes( iface );
986 const WCHAR *valueW;
987 HRESULT hr;
988 int len;
990 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
992 if (!value)
993 return E_POINTER;
995 *value = NULL;
996 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
997 if (FAILED(hr))
998 return hr;
1000 return return_bstrn(valueW, len, value);
1003 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1004 IVBSAXAttributes* iface,
1005 BSTR uri,
1006 BSTR localName,
1007 BSTR *value)
1009 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1010 const WCHAR *valueW;
1011 HRESULT hr;
1012 int len;
1014 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1016 if (!value)
1017 return E_POINTER;
1019 *value = NULL;
1020 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1021 localName, SysStringLen(localName), &valueW, &len);
1022 if (FAILED(hr))
1023 return hr;
1025 return return_bstrn(valueW, len, value);
1028 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1029 IVBSAXAttributes* iface,
1030 BSTR QName,
1031 BSTR *value)
1033 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1034 const WCHAR *valueW;
1035 HRESULT hr;
1036 int len;
1038 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1040 if (!value)
1041 return E_POINTER;
1043 *value = NULL;
1044 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1045 SysStringLen(QName), &valueW, &len);
1046 if (FAILED(hr))
1047 return hr;
1049 return return_bstrn(valueW, len, value);
1052 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1054 ivbsaxattributes_QueryInterface,
1055 ivbsaxattributes_AddRef,
1056 ivbsaxattributes_Release,
1057 ivbsaxattributes_GetTypeInfoCount,
1058 ivbsaxattributes_GetTypeInfo,
1059 ivbsaxattributes_GetIDsOfNames,
1060 ivbsaxattributes_Invoke,
1061 ivbsaxattributes_get_length,
1062 ivbsaxattributes_getURI,
1063 ivbsaxattributes_getLocalName,
1064 ivbsaxattributes_getQName,
1065 ivbsaxattributes_getIndexFromName,
1066 ivbsaxattributes_getIndexFromQName,
1067 ivbsaxattributes_getType,
1068 ivbsaxattributes_getTypeFromName,
1069 ivbsaxattributes_getTypeFromQName,
1070 ivbsaxattributes_getValue,
1071 ivbsaxattributes_getValueFromName,
1072 ivbsaxattributes_getValueFromQName
1075 /*** ISAXAttributes interface ***/
1076 /*** IUnknown methods ***/
1077 static HRESULT WINAPI isaxattributes_QueryInterface(
1078 ISAXAttributes* iface,
1079 REFIID riid,
1080 void **ppvObject)
1082 saxlocator *This = impl_from_ISAXAttributes(iface);
1083 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1084 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1087 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1089 saxlocator *This = impl_from_ISAXAttributes(iface);
1090 TRACE("%p\n", This);
1091 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1094 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1096 saxlocator *This = impl_from_ISAXAttributes(iface);
1098 TRACE("%p\n", This);
1099 return ISAXLocator_Release(&This->ISAXLocator_iface);
1102 /*** ISAXAttributes methods ***/
1103 static HRESULT WINAPI isaxattributes_getLength(
1104 ISAXAttributes* iface,
1105 int *length)
1107 saxlocator *This = impl_from_ISAXAttributes( iface );
1109 *length = This->nb_attributes;
1110 TRACE("Length set to %d\n", *length);
1111 return S_OK;
1114 static HRESULT WINAPI isaxattributes_getURI(
1115 ISAXAttributes* iface,
1116 int index,
1117 const WCHAR **url,
1118 int *size)
1120 saxlocator *This = impl_from_ISAXAttributes( iface );
1121 TRACE("(%p)->(%d)\n", This, index);
1123 if(index >= This->nb_attributes || index < 0) return E_INVALIDARG;
1124 if(!url || !size) return E_POINTER;
1126 *size = SysStringLen(This->attributes[index].szURI);
1127 *url = This->attributes[index].szURI;
1129 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1131 return S_OK;
1134 static HRESULT WINAPI isaxattributes_getLocalName(
1135 ISAXAttributes* iface,
1136 int nIndex,
1137 const WCHAR **pLocalName,
1138 int *pLocalNameLength)
1140 saxlocator *This = impl_from_ISAXAttributes( iface );
1141 TRACE("(%p)->(%d)\n", This, nIndex);
1143 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1144 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1146 *pLocalNameLength = SysStringLen(This->attributes[nIndex].szLocalname);
1147 *pLocalName = This->attributes[nIndex].szLocalname;
1149 return S_OK;
1152 static HRESULT WINAPI isaxattributes_getQName(
1153 ISAXAttributes* iface,
1154 int nIndex,
1155 const WCHAR **pQName,
1156 int *pQNameLength)
1158 saxlocator *This = impl_from_ISAXAttributes( iface );
1159 TRACE("(%p)->(%d)\n", This, nIndex);
1161 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1162 if(!pQName || !pQNameLength) return E_POINTER;
1164 *pQNameLength = SysStringLen(This->attributes[nIndex].szQName);
1165 *pQName = This->attributes[nIndex].szQName;
1167 return S_OK;
1170 static HRESULT WINAPI isaxattributes_getName(
1171 ISAXAttributes* iface,
1172 int index,
1173 const WCHAR **uri,
1174 int *pUriLength,
1175 const WCHAR **localName,
1176 int *pLocalNameSize,
1177 const WCHAR **QName,
1178 int *pQNameLength)
1180 saxlocator *This = impl_from_ISAXAttributes( iface );
1181 TRACE("(%p)->(%d)\n", This, index);
1183 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1184 if(!uri || !pUriLength || !localName || !pLocalNameSize
1185 || !QName || !pQNameLength) return E_POINTER;
1187 *pUriLength = SysStringLen(This->attributes[index].szURI);
1188 *uri = This->attributes[index].szURI;
1189 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1190 *localName = This->attributes[index].szLocalname;
1191 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1192 *QName = This->attributes[index].szQName;
1194 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1196 return S_OK;
1199 static HRESULT WINAPI isaxattributes_getIndexFromName(
1200 ISAXAttributes* iface,
1201 const WCHAR *pUri,
1202 int cUriLength,
1203 const WCHAR *pLocalName,
1204 int cocalNameLength,
1205 int *index)
1207 saxlocator *This = impl_from_ISAXAttributes( iface );
1208 int i;
1209 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1210 debugstr_w(pLocalName), cocalNameLength);
1212 if(!pUri || !pLocalName || !index) return E_POINTER;
1214 for(i=0; i<This->nb_attributes; i++)
1216 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1217 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1218 continue;
1219 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1220 sizeof(WCHAR)*cUriLength))
1221 continue;
1222 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1223 sizeof(WCHAR)*cocalNameLength))
1224 continue;
1226 *index = i;
1227 return S_OK;
1230 return E_INVALIDARG;
1233 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1234 ISAXAttributes* iface,
1235 const WCHAR *pQName,
1236 int nQNameLength,
1237 int *index)
1239 saxlocator *This = impl_from_ISAXAttributes( iface );
1240 int i;
1241 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1243 if(!pQName || !index) return E_POINTER;
1244 if(!nQNameLength) return E_INVALIDARG;
1246 for(i=0; i<This->nb_attributes; i++)
1248 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1249 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1251 *index = i;
1252 return S_OK;
1255 return E_INVALIDARG;
1258 static HRESULT WINAPI isaxattributes_getType(
1259 ISAXAttributes* iface,
1260 int nIndex,
1261 const WCHAR **pType,
1262 int *pTypeLength)
1264 saxlocator *This = impl_from_ISAXAttributes( iface );
1266 FIXME("(%p)->(%d) stub\n", This, nIndex);
1267 return E_NOTIMPL;
1270 static HRESULT WINAPI isaxattributes_getTypeFromName(
1271 ISAXAttributes* iface,
1272 const WCHAR *pUri,
1273 int nUri,
1274 const WCHAR *pLocalName,
1275 int nLocalName,
1276 const WCHAR **pType,
1277 int *nType)
1279 saxlocator *This = impl_from_ISAXAttributes( iface );
1281 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1282 debugstr_w(pLocalName), nLocalName);
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1287 ISAXAttributes* iface,
1288 const WCHAR *pQName,
1289 int nQName,
1290 const WCHAR **pType,
1291 int *nType)
1293 saxlocator *This = impl_from_ISAXAttributes( iface );
1295 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1296 return E_NOTIMPL;
1299 static HRESULT WINAPI isaxattributes_getValue(
1300 ISAXAttributes* iface,
1301 int index,
1302 const WCHAR **value,
1303 int *nValue)
1305 saxlocator *This = impl_from_ISAXAttributes( iface );
1306 TRACE("(%p)->(%d)\n", This, index);
1308 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1309 if(!value || !nValue) return E_POINTER;
1311 *nValue = SysStringLen(This->attributes[index].szValue);
1312 *value = This->attributes[index].szValue;
1314 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1316 return S_OK;
1319 static HRESULT WINAPI isaxattributes_getValueFromName(
1320 ISAXAttributes* iface,
1321 const WCHAR *pUri,
1322 int nUri,
1323 const WCHAR *pLocalName,
1324 int nLocalName,
1325 const WCHAR **pValue,
1326 int *nValue)
1328 HRESULT hr;
1329 int index;
1330 saxlocator *This = impl_from_ISAXAttributes( iface );
1331 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1332 debugstr_w(pLocalName), nLocalName);
1334 hr = ISAXAttributes_getIndexFromName(iface,
1335 pUri, nUri, pLocalName, nLocalName, &index);
1336 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1338 return hr;
1341 static HRESULT WINAPI isaxattributes_getValueFromQName(
1342 ISAXAttributes* iface,
1343 const WCHAR *pQName,
1344 int nQName,
1345 const WCHAR **pValue,
1346 int *nValue)
1348 HRESULT hr;
1349 int index;
1350 saxlocator *This = impl_from_ISAXAttributes( iface );
1351 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1353 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1354 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1356 return hr;
1359 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1361 isaxattributes_QueryInterface,
1362 isaxattributes_AddRef,
1363 isaxattributes_Release,
1364 isaxattributes_getLength,
1365 isaxattributes_getURI,
1366 isaxattributes_getLocalName,
1367 isaxattributes_getQName,
1368 isaxattributes_getName,
1369 isaxattributes_getIndexFromName,
1370 isaxattributes_getIndexFromQName,
1371 isaxattributes_getType,
1372 isaxattributes_getTypeFromName,
1373 isaxattributes_getTypeFromQName,
1374 isaxattributes_getValue,
1375 isaxattributes_getValueFromName,
1376 isaxattributes_getValueFromQName
1379 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1380 so when document has escaped value with '&amp;' it's parsed to '&' and then
1381 escaped to '&#38;'. This function takes care of ampersands only. */
1382 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1384 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1385 WCHAR *dest, *ptrW, *str;
1386 DWORD str_len;
1387 BSTR bstr;
1389 if (!buf)
1390 return NULL;
1392 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1393 if (len != -1) str_len++;
1395 str = heap_alloc(str_len*sizeof(WCHAR));
1396 if (!str) return NULL;
1398 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1399 if (len != -1) str[str_len-1] = 0;
1401 ptrW = str;
1402 while ((dest = strstrW(ptrW, ampescW)))
1404 WCHAR *src;
1406 /* leave first '&' from a reference as a value */
1407 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1408 dest++;
1410 /* move together with null terminator */
1411 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1413 ptrW++;
1416 bstr = SysAllocString(str);
1417 heap_free(str);
1419 return bstr;
1422 static HRESULT SAXAttributes_populate(saxlocator *locator,
1423 int nb_namespaces, const xmlChar **xmlNamespaces,
1424 int nb_attributes, const xmlChar **xmlAttributes)
1426 static const xmlChar xmlns[] = "xmlns";
1427 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1429 struct _attributes *attrs;
1430 int i;
1432 /* skip namespace definitions */
1433 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1434 nb_namespaces = 0;
1436 locator->nb_attributes = nb_namespaces + nb_attributes;
1437 if(locator->nb_attributes > locator->attributesSize)
1439 attrs = heap_realloc(locator->attributes, sizeof(struct _attributes)*locator->nb_attributes*2);
1440 if(!attrs)
1442 locator->nb_attributes = 0;
1443 return E_OUTOFMEMORY;
1445 locator->attributes = attrs;
1447 else
1449 attrs = locator->attributes;
1452 for (i = 0; i < nb_namespaces; i++)
1454 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1455 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1456 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1457 if(!xmlNamespaces[2*i])
1458 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1459 else
1460 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1463 for (i = 0; i < nb_attributes; i++)
1465 static const xmlChar xmlA[] = "xml";
1467 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1468 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1469 else
1470 /* that's an important feature to keep same uri pointer for every reported attribute */
1471 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1473 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1474 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1475 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1],
1476 xmlAttributes[i*5]);
1479 return S_OK;
1482 /*** LibXML callbacks ***/
1483 static void libxmlStartDocument(void *ctx)
1485 saxlocator *This = ctx;
1486 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1487 HRESULT hr;
1489 if (This->saxreader->version >= MSXML4)
1491 const xmlChar *p = This->pParserCtxt->input->cur-1;
1492 update_position(This, FALSE);
1493 while(p>This->pParserCtxt->input->base && *p!='>')
1495 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1496 This->line--;
1497 p--;
1499 This->column = 0;
1500 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1501 This->column++;
1504 /* store version value, declaration has to contain version attribute */
1505 if (This->pParserCtxt->standalone != -1)
1507 SysFreeString(This->saxreader->xmldecl_version);
1508 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1511 if (saxreader_has_handler(This, SAXContentHandler))
1513 if(This->vbInterface)
1514 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1515 else
1516 hr = ISAXContentHandler_startDocument(handler->handler);
1518 if (sax_callback_failed(This, hr))
1519 format_error_message_from_id(This, hr);
1523 static void libxmlEndDocument(void *ctx)
1525 saxlocator *This = ctx;
1526 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1527 HRESULT hr;
1529 if (This->saxreader->version >= MSXML4) {
1530 update_position(This, FALSE);
1531 if(This->column > 1)
1532 This->line++;
1533 This->column = 0;
1534 } else {
1535 This->column = 0;
1536 This->line = 0;
1539 if(This->ret != S_OK) return;
1541 if (saxreader_has_handler(This, SAXContentHandler))
1543 if(This->vbInterface)
1544 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1545 else
1546 hr = ISAXContentHandler_endDocument(handler->handler);
1548 if (sax_callback_failed(This, hr))
1549 format_error_message_from_id(This, hr);
1553 static void libxmlStartElementNS(
1554 void *ctx,
1555 const xmlChar *localname,
1556 const xmlChar *prefix,
1557 const xmlChar *URI,
1558 int nb_namespaces,
1559 const xmlChar **namespaces,
1560 int nb_attributes,
1561 int nb_defaulted,
1562 const xmlChar **attributes)
1564 saxlocator *This = ctx;
1565 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1566 element_entry *element;
1567 HRESULT hr = S_OK;
1568 BSTR uri;
1570 update_position(This, TRUE);
1571 if(*(This->pParserCtxt->input->cur) == '/')
1572 This->column++;
1573 if(This->saxreader->version < MSXML4)
1574 This->column++;
1576 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1577 push_element_ns(This, element);
1579 if (is_namespaces_enabled(This->saxreader))
1581 int i;
1583 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1585 if (This->vbInterface)
1586 hr = IVBSAXContentHandler_startPrefixMapping(
1587 handler->vbhandler,
1588 &element->ns[i].prefix,
1589 &element->ns[i].uri);
1590 else
1591 hr = ISAXContentHandler_startPrefixMapping(
1592 handler->handler,
1593 element->ns[i].prefix,
1594 SysStringLen(element->ns[i].prefix),
1595 element->ns[i].uri,
1596 SysStringLen(element->ns[i].uri));
1598 if (sax_callback_failed(This, hr))
1600 format_error_message_from_id(This, hr);
1601 return;
1606 uri = find_element_uri(This, URI);
1607 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1608 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1610 BSTR local;
1612 if (is_namespaces_enabled(This->saxreader))
1613 local = element->local;
1614 else
1615 uri = local = NULL;
1617 if (This->vbInterface)
1618 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1619 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1620 else
1621 hr = ISAXContentHandler_startElement(handler->handler,
1622 uri, SysStringLen(uri),
1623 local, SysStringLen(local),
1624 element->qname, SysStringLen(element->qname),
1625 &This->ISAXAttributes_iface);
1627 if (sax_callback_failed(This, hr))
1628 format_error_message_from_id(This, hr);
1632 static void libxmlEndElementNS(
1633 void *ctx,
1634 const xmlChar *localname,
1635 const xmlChar *prefix,
1636 const xmlChar *URI)
1638 saxlocator *This = ctx;
1639 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1640 element_entry *element;
1641 const xmlChar *p;
1642 BSTR uri, local;
1643 HRESULT hr;
1645 update_position(This, FALSE);
1646 p = This->pParserCtxt->input->cur;
1648 if (This->saxreader->version >= MSXML4)
1650 p--;
1651 while(p>This->pParserCtxt->input->base && *p!='>')
1653 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1654 This->line--;
1655 p--;
1658 else if(*(p-1)!='>' || *(p-2)!='/')
1660 p--;
1661 while(p-2>=This->pParserCtxt->input->base
1662 && *(p-2)!='<' && *(p-1)!='/')
1664 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1665 This->line--;
1666 p--;
1669 This->column = 0;
1670 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1671 This->column++;
1673 uri = find_element_uri(This, URI);
1674 element = pop_element_ns(This);
1676 if (!saxreader_has_handler(This, SAXContentHandler))
1678 This->nb_attributes = 0;
1679 free_element_entry(element);
1680 return;
1683 if (is_namespaces_enabled(This->saxreader))
1684 local = element->local;
1685 else
1686 uri = local = NULL;
1688 if (This->vbInterface)
1689 hr = IVBSAXContentHandler_endElement(
1690 handler->vbhandler,
1691 &uri, &local, &element->qname);
1692 else
1693 hr = ISAXContentHandler_endElement(
1694 handler->handler,
1695 uri, SysStringLen(uri),
1696 local, SysStringLen(local),
1697 element->qname, SysStringLen(element->qname));
1699 This->nb_attributes = 0;
1701 if (sax_callback_failed(This, hr))
1703 format_error_message_from_id(This, hr);
1704 free_element_entry(element);
1705 return;
1708 if (is_namespaces_enabled(This->saxreader))
1710 int i = -1;
1711 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1713 if (This->vbInterface)
1714 hr = IVBSAXContentHandler_endPrefixMapping(
1715 handler->vbhandler, &element->ns[i].prefix);
1716 else
1717 hr = ISAXContentHandler_endPrefixMapping(
1718 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1720 if (sax_callback_failed(This, hr)) break;
1723 if (sax_callback_failed(This, hr))
1724 format_error_message_from_id(This, hr);
1727 free_element_entry(element);
1730 static void libxmlCharacters(
1731 void *ctx,
1732 const xmlChar *ch,
1733 int len)
1735 saxlocator *This = ctx;
1736 BSTR Chars;
1737 HRESULT hr;
1738 xmlChar *cur, *end;
1739 BOOL lastEvent = FALSE;
1741 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1743 update_position(This, FALSE);
1744 cur = (xmlChar*)This->pParserCtxt->input->cur;
1745 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1747 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1748 This->line--;
1749 cur--;
1751 This->column = 1;
1752 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1753 This->column++;
1755 cur = (xmlChar*)ch;
1756 if(*(ch-1)=='\r') cur--;
1757 end = cur;
1759 while(1)
1761 while(end-ch<len && *end!='\r') end++;
1762 if(end-ch==len)
1764 lastEvent = TRUE;
1766 else
1768 *end = '\n';
1769 end++;
1772 if (This->saxreader->version >= MSXML4)
1774 xmlChar *p;
1776 for(p=cur; p!=end; p++)
1778 if(*p=='\n')
1780 This->line++;
1781 This->column = 1;
1783 else
1785 This->column++;
1789 if(!lastEvent)
1790 This->column = 0;
1793 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1794 hr = saxreader_saxcharacters(This, Chars);
1796 if (sax_callback_failed(This, hr))
1798 format_error_message_from_id(This, hr);
1799 return;
1802 if (This->saxreader->version < MSXML4)
1803 This->column += end-cur;
1805 if(lastEvent)
1806 break;
1808 *(end-1) = '\r';
1809 if(*end == '\n')
1811 end++;
1812 This->column++;
1814 cur = end;
1816 if(end-ch == len) break;
1820 static void libxmlSetDocumentLocator(
1821 void *ctx,
1822 xmlSAXLocatorPtr loc)
1824 saxlocator *This = ctx;
1825 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1826 HRESULT hr = S_OK;
1828 if (saxreader_has_handler(This, SAXContentHandler))
1830 if(This->vbInterface)
1831 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1832 &This->IVBSAXLocator_iface);
1833 else
1834 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1837 if(FAILED(hr))
1838 format_error_message_from_id(This, hr);
1841 static void libxmlComment(void *ctx, const xmlChar *value)
1843 saxlocator *This = ctx;
1844 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1845 BSTR bValue;
1846 HRESULT hr;
1847 const xmlChar *p = This->pParserCtxt->input->cur;
1849 update_position(This, FALSE);
1850 while(p-4>=This->pParserCtxt->input->base
1851 && memcmp(p-4, "<!--", sizeof(char[4])))
1853 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1854 This->line--;
1855 p--;
1858 This->column = 0;
1859 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1860 This->column++;
1862 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1864 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1866 if (This->vbInterface)
1867 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1868 else
1869 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1871 if(FAILED(hr))
1872 format_error_message_from_id(This, hr);
1875 static void libxmlFatalError(void *ctx, const char *msg, ...)
1877 saxlocator *This = ctx;
1878 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1879 char message[1024];
1880 WCHAR *error;
1881 DWORD len;
1882 va_list args;
1884 if(This->ret != S_OK) {
1885 xmlStopParser(This->pParserCtxt);
1886 return;
1889 va_start(args, msg);
1890 vsprintf(message, msg, args);
1891 va_end(args);
1893 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1894 error = heap_alloc(sizeof(WCHAR)*len);
1895 if(error)
1897 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1898 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1901 if (!saxreader_has_handler(This, SAXErrorHandler))
1903 xmlStopParser(This->pParserCtxt);
1904 This->ret = E_FAIL;
1905 heap_free(error);
1906 return;
1909 FIXME("Error handling is not compatible.\n");
1911 if(This->vbInterface)
1913 BSTR bstrError = SysAllocString(error);
1914 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1915 &bstrError, E_FAIL);
1916 SysFreeString(bstrError);
1918 else
1919 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1921 heap_free(error);
1923 xmlStopParser(This->pParserCtxt);
1924 This->ret = E_FAIL;
1927 /* The only reason this helper exists is that CDATA section are reported by chunks,
1928 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1930 This helper should be called for substring with trailing newlines.
1932 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1934 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1935 WCHAR *ptr;
1937 ptr = bstr + len - 1;
1938 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1939 ptr--;
1941 while (*++ptr)
1943 /* replace returns as:
1945 - "\r<char>" -> "\n<char>"
1946 - "\r\r" -> "\r"
1947 - "\r\n" -> "\n"
1949 if (*ptr == '\r')
1951 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1953 /* shift tail */
1954 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1956 else
1957 *ptr = '\n';
1961 ret = SysAllocStringLen(bstr, len);
1962 SysFreeString(bstr);
1963 return ret;
1966 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
1968 const xmlChar *start, *end;
1969 saxlocator *locator = ctx;
1970 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
1971 HRESULT hr = S_OK;
1972 BSTR chars;
1973 int i;
1975 update_position(locator, FALSE);
1976 if (saxreader_has_handler(locator, SAXLexicalHandler))
1978 if (locator->vbInterface)
1979 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
1980 else
1981 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
1984 if(FAILED(hr))
1986 format_error_message_from_id(locator, hr);
1987 return;
1990 start = value;
1991 end = NULL;
1992 i = 0;
1994 while (i < len)
1996 /* scan for newlines */
1997 if (value[i] == '\r' || value[i] == '\n')
1999 /* skip newlines/linefeeds */
2000 while (i < len)
2002 if (value[i] != '\r' && value[i] != '\n') break;
2003 i++;
2005 end = &value[i];
2007 /* report */
2008 chars = saxreader_get_cdata_chunk(start, end-start);
2009 TRACE("(chunk %s)\n", debugstr_w(chars));
2010 hr = saxreader_saxcharacters(locator, chars);
2011 SysFreeString(chars);
2013 start = &value[i];
2014 end = NULL;
2016 i++;
2017 locator->column++;
2020 /* no newline chars (or last chunk) report as a whole */
2021 if (!end && start == value)
2023 /* report */
2024 chars = bstr_from_xmlCharN(start, len-(start-value));
2025 TRACE("(%s)\n", debugstr_w(chars));
2026 hr = saxreader_saxcharacters(locator, chars);
2027 SysFreeString(chars);
2030 if (saxreader_has_handler(locator, SAXLexicalHandler))
2032 if (locator->vbInterface)
2033 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2034 else
2035 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2038 if(FAILED(hr))
2039 format_error_message_from_id(locator, hr);
2042 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2044 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2045 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2048 /*** IVBSAXLocator interface ***/
2049 /*** IUnknown methods ***/
2050 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2052 saxlocator *This = impl_from_IVBSAXLocator( iface );
2054 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2056 *ppvObject = NULL;
2058 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2059 IsEqualGUID( riid, &IID_IDispatch) ||
2060 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2062 *ppvObject = iface;
2064 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2066 *ppvObject = &This->IVBSAXAttributes_iface;
2068 else
2070 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2071 return E_NOINTERFACE;
2074 IVBSAXLocator_AddRef( iface );
2076 return S_OK;
2079 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2081 saxlocator *This = impl_from_IVBSAXLocator( iface );
2082 TRACE("%p\n", This );
2083 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2086 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2088 saxlocator *This = impl_from_IVBSAXLocator( iface );
2089 return ISAXLocator_Release(&This->ISAXLocator_iface);
2092 /*** IDispatch methods ***/
2093 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2095 saxlocator *This = impl_from_IVBSAXLocator( iface );
2097 TRACE("(%p)->(%p)\n", This, pctinfo);
2099 *pctinfo = 1;
2101 return S_OK;
2104 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2105 IVBSAXLocator *iface,
2106 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2108 saxlocator *This = impl_from_IVBSAXLocator( iface );
2110 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2112 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2115 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2116 IVBSAXLocator *iface,
2117 REFIID riid,
2118 LPOLESTR* rgszNames,
2119 UINT cNames,
2120 LCID lcid,
2121 DISPID* rgDispId)
2123 saxlocator *This = impl_from_IVBSAXLocator( iface );
2124 ITypeInfo *typeinfo;
2125 HRESULT hr;
2127 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2128 lcid, rgDispId);
2130 if(!rgszNames || cNames == 0 || !rgDispId)
2131 return E_INVALIDARG;
2133 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2134 if(SUCCEEDED(hr))
2136 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2137 ITypeInfo_Release(typeinfo);
2140 return hr;
2143 static HRESULT WINAPI ivbsaxlocator_Invoke(
2144 IVBSAXLocator *iface,
2145 DISPID dispIdMember,
2146 REFIID riid,
2147 LCID lcid,
2148 WORD wFlags,
2149 DISPPARAMS* pDispParams,
2150 VARIANT* pVarResult,
2151 EXCEPINFO* pExcepInfo,
2152 UINT* puArgErr)
2154 saxlocator *This = impl_from_IVBSAXLocator( iface );
2155 ITypeInfo *typeinfo;
2156 HRESULT hr;
2158 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2159 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2161 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2162 if(SUCCEEDED(hr))
2164 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2165 pDispParams, pVarResult, pExcepInfo, puArgErr);
2166 ITypeInfo_Release(typeinfo);
2169 return hr;
2172 /*** IVBSAXLocator methods ***/
2173 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2174 IVBSAXLocator* iface,
2175 int *pnColumn)
2177 saxlocator *This = impl_from_IVBSAXLocator( iface );
2178 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2181 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2182 IVBSAXLocator* iface,
2183 int *pnLine)
2185 saxlocator *This = impl_from_IVBSAXLocator( iface );
2186 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2189 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2191 saxlocator *This = impl_from_IVBSAXLocator( iface );
2192 const WCHAR *publicidW;
2193 HRESULT hr;
2195 TRACE("(%p)->(%p)\n", This, ret);
2197 if (!ret)
2198 return E_POINTER;
2200 *ret = NULL;
2201 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2202 if (FAILED(hr))
2203 return hr;
2205 return return_bstr(publicidW, ret);
2208 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2210 saxlocator *This = impl_from_IVBSAXLocator( iface );
2211 const WCHAR *systemidW;
2212 HRESULT hr;
2214 TRACE("(%p)->(%p)\n", This, ret);
2216 if (!ret)
2217 return E_POINTER;
2219 *ret = NULL;
2220 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2221 if (FAILED(hr))
2222 return hr;
2224 return return_bstr(systemidW, ret);
2227 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2229 ivbsaxlocator_QueryInterface,
2230 ivbsaxlocator_AddRef,
2231 ivbsaxlocator_Release,
2232 ivbsaxlocator_GetTypeInfoCount,
2233 ivbsaxlocator_GetTypeInfo,
2234 ivbsaxlocator_GetIDsOfNames,
2235 ivbsaxlocator_Invoke,
2236 ivbsaxlocator_get_columnNumber,
2237 ivbsaxlocator_get_lineNumber,
2238 ivbsaxlocator_get_publicId,
2239 ivbsaxlocator_get_systemId
2242 /*** ISAXLocator interface ***/
2243 /*** IUnknown methods ***/
2244 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2246 saxlocator *This = impl_from_ISAXLocator( iface );
2248 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2250 *ppvObject = NULL;
2252 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2253 IsEqualGUID( riid, &IID_ISAXLocator ))
2255 *ppvObject = iface;
2257 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2259 *ppvObject = &This->ISAXAttributes_iface;
2261 else
2263 WARN("interface %s not implemented\n", debugstr_guid(riid));
2264 return E_NOINTERFACE;
2267 ISAXLocator_AddRef( iface );
2269 return S_OK;
2272 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2274 saxlocator *This = impl_from_ISAXLocator( iface );
2275 ULONG ref = InterlockedIncrement( &This->ref );
2276 TRACE("(%p)->(%d)\n", This, ref);
2277 return ref;
2280 static ULONG WINAPI isaxlocator_Release(
2281 ISAXLocator* iface)
2283 saxlocator *This = impl_from_ISAXLocator( iface );
2284 LONG ref = InterlockedDecrement( &This->ref );
2286 TRACE("(%p)->(%d)\n", This, ref );
2288 if (ref == 0)
2290 element_entry *element, *element2;
2291 int index;
2293 SysFreeString(This->publicId);
2294 SysFreeString(This->systemId);
2295 SysFreeString(This->namespaceUri);
2297 for(index=0; index<This->nb_attributes; index++)
2299 SysFreeString(This->attributes[index].szLocalname);
2300 SysFreeString(This->attributes[index].szValue);
2301 SysFreeString(This->attributes[index].szQName);
2303 heap_free(This->attributes);
2305 /* element stack */
2306 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2308 list_remove(&element->entry);
2309 free_element_entry(element);
2312 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2313 heap_free( This );
2316 return ref;
2319 /*** ISAXLocator methods ***/
2320 static HRESULT WINAPI isaxlocator_getColumnNumber(
2321 ISAXLocator* iface,
2322 int *pnColumn)
2324 saxlocator *This = impl_from_ISAXLocator( iface );
2326 *pnColumn = This->column;
2327 return S_OK;
2330 static HRESULT WINAPI isaxlocator_getLineNumber(
2331 ISAXLocator* iface,
2332 int *pnLine)
2334 saxlocator *This = impl_from_ISAXLocator( iface );
2336 *pnLine = This->line;
2337 return S_OK;
2340 static HRESULT WINAPI isaxlocator_getPublicId(
2341 ISAXLocator* iface,
2342 const WCHAR ** ppwchPublicId)
2344 BSTR publicId;
2345 saxlocator *This = impl_from_ISAXLocator( iface );
2347 SysFreeString(This->publicId);
2349 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2350 if(SysStringLen(publicId))
2351 This->publicId = publicId;
2352 else
2354 SysFreeString(publicId);
2355 This->publicId = NULL;
2358 *ppwchPublicId = This->publicId;
2359 return S_OK;
2362 static HRESULT WINAPI isaxlocator_getSystemId(
2363 ISAXLocator* iface,
2364 const WCHAR ** ppwchSystemId)
2366 BSTR systemId;
2367 saxlocator *This = impl_from_ISAXLocator( iface );
2369 SysFreeString(This->systemId);
2371 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2372 if(SysStringLen(systemId))
2373 This->systemId = systemId;
2374 else
2376 SysFreeString(systemId);
2377 This->systemId = NULL;
2380 *ppwchSystemId = This->systemId;
2381 return S_OK;
2384 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2386 isaxlocator_QueryInterface,
2387 isaxlocator_AddRef,
2388 isaxlocator_Release,
2389 isaxlocator_getColumnNumber,
2390 isaxlocator_getLineNumber,
2391 isaxlocator_getPublicId,
2392 isaxlocator_getSystemId
2395 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2397 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2398 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2400 saxlocator *locator;
2402 locator = heap_alloc( sizeof (*locator) );
2403 if( !locator )
2404 return E_OUTOFMEMORY;
2406 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2407 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2408 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2409 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2410 locator->ref = 1;
2411 locator->vbInterface = vbInterface;
2413 locator->saxreader = reader;
2414 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2416 locator->pParserCtxt = NULL;
2417 locator->publicId = NULL;
2418 locator->systemId = NULL;
2419 locator->line = reader->version < MSXML4 ? 0 : 1;
2420 locator->column = 0;
2421 locator->ret = S_OK;
2422 if (locator->saxreader->version >= MSXML6)
2423 locator->namespaceUri = SysAllocString(w3xmlns);
2424 else
2425 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2426 if(!locator->namespaceUri)
2428 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2429 heap_free(locator);
2430 return E_OUTOFMEMORY;
2433 locator->attributesSize = 8;
2434 locator->nb_attributes = 0;
2435 locator->attributes = heap_alloc(sizeof(struct _attributes)*locator->attributesSize);
2436 if(!locator->attributes)
2438 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2439 SysFreeString(locator->namespaceUri);
2440 heap_free(locator);
2441 return E_OUTOFMEMORY;
2444 list_init(&locator->elements);
2446 *ppsaxlocator = locator;
2448 TRACE("returning %p\n", *ppsaxlocator);
2450 return S_OK;
2453 /*** SAXXMLReader internal functions ***/
2454 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2456 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2457 xmlChar *enc_name = NULL;
2458 saxlocator *locator;
2459 HRESULT hr;
2461 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2463 hr = SAXLocator_create(This, &locator, vbInterface);
2464 if (FAILED(hr))
2465 return hr;
2467 if (size >= 4)
2469 const unsigned char *buff = (unsigned char*)buffer;
2471 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2472 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2473 TRACE("detected encoding: %s\n", enc_name);
2474 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2475 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2476 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2478 buffer += 3;
2479 size -= 3;
2483 /* if libxml2 detection failed try to guess */
2484 if (encoding == XML_CHAR_ENCODING_NONE)
2486 const WCHAR *ptr = (WCHAR*)buffer;
2487 /* xml declaration with possibly specfied encoding will be still handled by parser */
2488 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2490 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2491 encoding = XML_CHAR_ENCODING_UTF16LE;
2494 else if (encoding == XML_CHAR_ENCODING_UTF8)
2495 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2496 else
2497 enc_name = NULL;
2499 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2500 if (!locator->pParserCtxt)
2502 ISAXLocator_Release(&locator->ISAXLocator_iface);
2503 return E_FAIL;
2506 if (enc_name)
2508 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2509 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2510 TRACE("switching to %s\n", enc_name);
2511 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2515 xmlFree(locator->pParserCtxt->sax);
2516 locator->pParserCtxt->sax = &locator->saxreader->sax;
2517 locator->pParserCtxt->userData = locator;
2519 This->isParsing = TRUE;
2520 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2521 hr = E_FAIL;
2522 else
2523 hr = locator->ret;
2524 This->isParsing = FALSE;
2526 if(locator->pParserCtxt)
2528 locator->pParserCtxt->sax = NULL;
2529 xmlFreeParserCtxt(locator->pParserCtxt);
2530 locator->pParserCtxt = NULL;
2533 ISAXLocator_Release(&locator->ISAXLocator_iface);
2534 return hr;
2537 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2539 saxlocator *locator;
2540 HRESULT hr;
2541 ULONG dataRead;
2542 char data[2048];
2543 int ret;
2545 dataRead = 0;
2546 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2547 if(FAILED(hr)) return hr;
2549 hr = SAXLocator_create(This, &locator, vbInterface);
2550 if(FAILED(hr)) return hr;
2552 locator->pParserCtxt = xmlCreatePushParserCtxt(
2553 &locator->saxreader->sax, locator,
2554 data, dataRead, NULL);
2555 if(!locator->pParserCtxt)
2557 ISAXLocator_Release(&locator->ISAXLocator_iface);
2558 return E_FAIL;
2561 This->isParsing = TRUE;
2563 do {
2564 dataRead = 0;
2565 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2566 if (FAILED(hr) || !dataRead) break;
2568 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2569 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2570 }while(hr == S_OK);
2572 if(SUCCEEDED(hr))
2574 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2575 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2579 This->isParsing = FALSE;
2581 xmlFreeParserCtxt(locator->pParserCtxt);
2582 locator->pParserCtxt = NULL;
2583 ISAXLocator_Release(&locator->ISAXLocator_iface);
2584 return hr;
2587 static HRESULT internal_parse(
2588 saxreader* This,
2589 VARIANT varInput,
2590 BOOL vbInterface)
2592 HRESULT hr;
2594 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2596 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2597 free_bstr_pool(&This->pool);
2599 switch(V_VT(&varInput))
2601 case VT_BSTR:
2602 case VT_BSTR|VT_BYREF:
2604 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2605 hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
2606 break;
2608 case VT_ARRAY|VT_UI1: {
2609 void *pSAData;
2610 LONG lBound, uBound;
2611 ULONG dataRead;
2613 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2614 if(hr != S_OK) break;
2615 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2616 if(hr != S_OK) break;
2617 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2618 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2619 if(hr != S_OK) break;
2620 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2621 SafeArrayUnaccessData(V_ARRAY(&varInput));
2622 break;
2624 case VT_UNKNOWN:
2625 case VT_DISPATCH: {
2626 IPersistStream *persistStream;
2627 ISequentialStream *stream = NULL;
2628 IXMLDOMDocument *xmlDoc;
2630 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2631 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2633 BSTR bstrData;
2635 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2636 hr = internal_parseBuffer(This, (const char*)bstrData,
2637 SysStringByteLen(bstrData), vbInterface);
2638 IXMLDOMDocument_Release(xmlDoc);
2639 SysFreeString(bstrData);
2640 break;
2643 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2644 &IID_IPersistStream, (void**)&persistStream) == S_OK)
2646 IStream *stream_copy;
2648 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy);
2649 if(hr != S_OK)
2651 IPersistStream_Release(persistStream);
2652 return hr;
2655 hr = IPersistStream_Save(persistStream, stream_copy, TRUE);
2656 IPersistStream_Release(persistStream);
2657 if(hr == S_OK)
2658 IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream);
2660 IStream_Release(stream_copy);
2663 /* try base interface first */
2664 if(!stream)
2666 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2667 if (!stream)
2668 /* this should never happen if IStream is implemented properly, but just in case */
2669 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2672 if(stream)
2674 hr = internal_parseStream(This, stream, vbInterface);
2675 ISequentialStream_Release(stream);
2677 else
2679 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2680 hr = E_INVALIDARG;
2683 break;
2685 default:
2686 WARN("vt %d not implemented\n", V_VT(&varInput));
2687 hr = E_INVALIDARG;
2690 return hr;
2693 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2695 saxreader *This = obj;
2697 return internal_parseBuffer(This, ptr, len, TRUE);
2700 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2702 saxreader *This = obj;
2704 return internal_parseBuffer(This, ptr, len, FALSE);
2707 static HRESULT internal_parseURL(
2708 saxreader* This,
2709 const WCHAR *url,
2710 BOOL vbInterface)
2712 IMoniker *mon;
2713 bsc_t *bsc;
2714 HRESULT hr;
2716 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2718 hr = create_moniker_from_url(url, &mon);
2719 if(FAILED(hr))
2720 return hr;
2722 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2723 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2724 IMoniker_Release(mon);
2726 if(FAILED(hr))
2727 return hr;
2729 return detach_bsc(bsc);
2732 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2734 const IID *riid;
2736 if (V_VT(v) == VT_EMPTY)
2737 return saxreader_put_handler(This, type, NULL, vb);
2739 switch (type)
2741 case SAXDeclHandler:
2742 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2743 break;
2744 case SAXLexicalHandler:
2745 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2746 break;
2747 default:
2748 ERR("wrong handler type %d\n", type);
2749 return E_FAIL;
2752 switch (V_VT(v))
2754 case VT_DISPATCH:
2755 case VT_UNKNOWN:
2757 IUnknown *handler = NULL;
2759 if (V_UNKNOWN(v))
2761 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2762 if (FAILED(hr)) return hr;
2765 saxreader_put_handler(This, type, handler, vb);
2766 if (handler) IUnknown_Release(handler);
2767 break;
2769 default:
2770 ERR("value type %d not supported\n", V_VT(v));
2771 return E_INVALIDARG;
2774 return S_OK;
2777 static HRESULT internal_putProperty(
2778 saxreader* This,
2779 const WCHAR *prop,
2780 VARIANT value,
2781 BOOL vbInterface)
2783 VARIANT *v;
2785 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2787 if (This->isParsing) return E_FAIL;
2789 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2790 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2791 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2793 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2794 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2796 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2798 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2799 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2800 return E_NOTIMPL;
2803 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2805 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2806 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2807 return E_NOTIMPL;
2810 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2812 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2813 return E_NOTIMPL;
2815 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2816 return E_FAIL;
2818 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2819 return E_NOTIMPL;
2821 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2822 return E_NOTIMPL;
2824 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2825 return E_FAIL;
2827 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2828 return E_FAIL;
2830 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2831 return E_FAIL;
2833 return E_INVALIDARG;
2836 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2838 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2840 if (!value) return E_POINTER;
2842 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2844 V_VT(value) = VT_UNKNOWN;
2845 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2846 return S_OK;
2849 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2851 V_VT(value) = VT_UNKNOWN;
2852 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2853 return S_OK;
2856 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2858 V_VT(value) = VT_BSTR;
2859 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2860 return S_OK;
2863 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2865 return E_NOTIMPL;
2868 /*** IVBSAXXMLReader interface ***/
2869 /*** IUnknown methods ***/
2870 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2872 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2874 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2876 *ppvObject = NULL;
2878 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2879 IsEqualGUID( riid, &IID_IDispatch ) ||
2880 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2882 *ppvObject = iface;
2884 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2886 *ppvObject = &This->ISAXXMLReader_iface;
2888 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2890 return *ppvObject ? S_OK : E_NOINTERFACE;
2892 else
2894 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2895 return E_NOINTERFACE;
2898 IVBSAXXMLReader_AddRef( iface );
2900 return S_OK;
2903 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2905 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2906 TRACE("%p\n", This );
2907 return InterlockedIncrement( &This->ref );
2910 static ULONG WINAPI saxxmlreader_Release(
2911 IVBSAXXMLReader* iface)
2913 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2914 LONG ref;
2916 TRACE("%p\n", This );
2918 ref = InterlockedDecrement( &This->ref );
2919 if ( ref == 0 )
2921 int i;
2923 for (i = 0; i < SAXHandler_Last; i++)
2925 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2927 if (saxiface->handler)
2928 IUnknown_Release(saxiface->handler);
2930 if (saxiface->vbhandler)
2931 IUnknown_Release(saxiface->vbhandler);
2934 SysFreeString(This->xmldecl_version);
2935 free_bstr_pool(&This->pool);
2937 heap_free( This );
2940 return ref;
2942 /*** IDispatch ***/
2943 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2945 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2946 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2949 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2950 IVBSAXXMLReader *iface,
2951 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2953 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2954 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2955 iTInfo, lcid, ppTInfo);
2958 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2959 IVBSAXXMLReader *iface,
2960 REFIID riid,
2961 LPOLESTR* rgszNames,
2962 UINT cNames,
2963 LCID lcid,
2964 DISPID* rgDispId)
2966 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2967 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2968 riid, rgszNames, cNames, lcid, rgDispId);
2971 static HRESULT WINAPI saxxmlreader_Invoke(
2972 IVBSAXXMLReader *iface,
2973 DISPID dispIdMember,
2974 REFIID riid,
2975 LCID lcid,
2976 WORD wFlags,
2977 DISPPARAMS* pDispParams,
2978 VARIANT* pVarResult,
2979 EXCEPINFO* pExcepInfo,
2980 UINT* puArgErr)
2982 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2983 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2984 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2987 /*** IVBSAXXMLReader methods ***/
2988 static HRESULT WINAPI saxxmlreader_getFeature(
2989 IVBSAXXMLReader* iface,
2990 BSTR feature_name,
2991 VARIANT_BOOL *value)
2993 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2994 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
2997 static HRESULT WINAPI saxxmlreader_putFeature(
2998 IVBSAXXMLReader* iface,
2999 BSTR feature_name,
3000 VARIANT_BOOL value)
3002 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3003 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3006 static HRESULT WINAPI saxxmlreader_getProperty(
3007 IVBSAXXMLReader* iface,
3008 BSTR prop,
3009 VARIANT *value)
3011 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3012 return internal_getProperty(This, prop, value, TRUE);
3015 static HRESULT WINAPI saxxmlreader_putProperty(
3016 IVBSAXXMLReader* iface,
3017 BSTR pProp,
3018 VARIANT value)
3020 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3021 return internal_putProperty(This, pProp, value, TRUE);
3024 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3025 IVBSAXXMLReader* iface,
3026 IVBSAXEntityResolver **resolver)
3028 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3029 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3032 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3033 IVBSAXXMLReader* iface,
3034 IVBSAXEntityResolver *resolver)
3036 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3037 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3040 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3041 IVBSAXXMLReader* iface,
3042 IVBSAXContentHandler **handler)
3044 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3045 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3048 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3049 IVBSAXXMLReader* iface,
3050 IVBSAXContentHandler *handler)
3052 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3053 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3056 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3057 IVBSAXXMLReader* iface,
3058 IVBSAXDTDHandler **handler)
3060 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3061 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3064 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3065 IVBSAXXMLReader* iface,
3066 IVBSAXDTDHandler *handler)
3068 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3069 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3072 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3073 IVBSAXXMLReader* iface,
3074 IVBSAXErrorHandler **handler)
3076 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3077 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3080 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3081 IVBSAXXMLReader* iface,
3082 IVBSAXErrorHandler *handler)
3084 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3085 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3088 static HRESULT WINAPI saxxmlreader_get_baseURL(
3089 IVBSAXXMLReader* iface,
3090 BSTR *pBaseUrl)
3092 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3094 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3095 return E_NOTIMPL;
3098 static HRESULT WINAPI saxxmlreader_put_baseURL(
3099 IVBSAXXMLReader* iface,
3100 BSTR pBaseUrl)
3102 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3103 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3106 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3107 IVBSAXXMLReader* iface,
3108 BSTR *pSecureBaseUrl)
3110 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3112 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3113 return E_NOTIMPL;
3116 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3117 IVBSAXXMLReader* iface,
3118 BSTR secureBaseUrl)
3120 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3121 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3124 static HRESULT WINAPI saxxmlreader_parse(
3125 IVBSAXXMLReader* iface,
3126 VARIANT varInput)
3128 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3129 return internal_parse(This, varInput, TRUE);
3132 static HRESULT WINAPI saxxmlreader_parseURL(
3133 IVBSAXXMLReader* iface,
3134 BSTR url)
3136 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3137 return internal_parseURL(This, url, TRUE);
3140 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3142 saxxmlreader_QueryInterface,
3143 saxxmlreader_AddRef,
3144 saxxmlreader_Release,
3145 saxxmlreader_GetTypeInfoCount,
3146 saxxmlreader_GetTypeInfo,
3147 saxxmlreader_GetIDsOfNames,
3148 saxxmlreader_Invoke,
3149 saxxmlreader_getFeature,
3150 saxxmlreader_putFeature,
3151 saxxmlreader_getProperty,
3152 saxxmlreader_putProperty,
3153 saxxmlreader_get_entityResolver,
3154 saxxmlreader_put_entityResolver,
3155 saxxmlreader_get_contentHandler,
3156 saxxmlreader_put_contentHandler,
3157 saxxmlreader_get_dtdHandler,
3158 saxxmlreader_put_dtdHandler,
3159 saxxmlreader_get_errorHandler,
3160 saxxmlreader_put_errorHandler,
3161 saxxmlreader_get_baseURL,
3162 saxxmlreader_put_baseURL,
3163 saxxmlreader_get_secureBaseURL,
3164 saxxmlreader_put_secureBaseURL,
3165 saxxmlreader_parse,
3166 saxxmlreader_parseURL
3169 /*** ISAXXMLReader interface ***/
3170 /*** IUnknown methods ***/
3171 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3173 saxreader *This = impl_from_ISAXXMLReader( iface );
3174 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3177 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3179 saxreader *This = impl_from_ISAXXMLReader( iface );
3180 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3183 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3185 saxreader *This = impl_from_ISAXXMLReader( iface );
3186 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3189 /*** ISAXXMLReader methods ***/
3190 static HRESULT WINAPI isaxxmlreader_getFeature(
3191 ISAXXMLReader* iface,
3192 const WCHAR *feature_name,
3193 VARIANT_BOOL *value)
3195 saxreader *This = impl_from_ISAXXMLReader( iface );
3196 saxreader_feature feature;
3198 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3200 feature = get_saxreader_feature(feature_name);
3201 if (feature == Namespaces || feature == NamespacePrefixes)
3202 return get_feature_value(This, feature, value);
3204 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3205 return E_NOTIMPL;
3208 static HRESULT WINAPI isaxxmlreader_putFeature(
3209 ISAXXMLReader* iface,
3210 const WCHAR *feature_name,
3211 VARIANT_BOOL value)
3213 saxreader *This = impl_from_ISAXXMLReader( iface );
3214 saxreader_feature feature;
3216 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3218 feature = get_saxreader_feature(feature_name);
3220 /* accepted cases */
3221 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
3222 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
3223 feature == Namespaces ||
3224 feature == NamespacePrefixes)
3226 return set_feature_value(This, feature, value);
3229 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
3231 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3232 return set_feature_value(This, feature, value);
3235 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3236 return E_NOTIMPL;
3239 static HRESULT WINAPI isaxxmlreader_getProperty(
3240 ISAXXMLReader* iface,
3241 const WCHAR *prop,
3242 VARIANT *value)
3244 saxreader *This = impl_from_ISAXXMLReader( iface );
3245 return internal_getProperty(This, prop, value, FALSE);
3248 static HRESULT WINAPI isaxxmlreader_putProperty(
3249 ISAXXMLReader* iface,
3250 const WCHAR *pProp,
3251 VARIANT value)
3253 saxreader *This = impl_from_ISAXXMLReader( iface );
3254 return internal_putProperty(This, pProp, value, FALSE);
3257 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3258 ISAXXMLReader* iface,
3259 ISAXEntityResolver **resolver)
3261 saxreader *This = impl_from_ISAXXMLReader( iface );
3262 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3265 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3266 ISAXXMLReader* iface,
3267 ISAXEntityResolver *resolver)
3269 saxreader *This = impl_from_ISAXXMLReader( iface );
3270 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3273 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3274 ISAXXMLReader* iface,
3275 ISAXContentHandler **handler)
3277 saxreader *This = impl_from_ISAXXMLReader( iface );
3278 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3281 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3282 ISAXXMLReader* iface,
3283 ISAXContentHandler *handler)
3285 saxreader *This = impl_from_ISAXXMLReader( iface );
3286 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3289 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3290 ISAXXMLReader* iface,
3291 ISAXDTDHandler **handler)
3293 saxreader *This = impl_from_ISAXXMLReader( iface );
3294 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3297 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3298 ISAXXMLReader* iface,
3299 ISAXDTDHandler *handler)
3301 saxreader *This = impl_from_ISAXXMLReader( iface );
3302 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3305 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3306 ISAXXMLReader* iface,
3307 ISAXErrorHandler **handler)
3309 saxreader *This = impl_from_ISAXXMLReader( iface );
3310 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3313 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3315 saxreader *This = impl_from_ISAXXMLReader( iface );
3316 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3319 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3320 ISAXXMLReader* iface,
3321 const WCHAR **base_url)
3323 saxreader *This = impl_from_ISAXXMLReader( iface );
3325 FIXME("(%p)->(%p) stub\n", This, base_url);
3326 return E_NOTIMPL;
3329 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3330 ISAXXMLReader* iface,
3331 const WCHAR *pBaseUrl)
3333 saxreader *This = impl_from_ISAXXMLReader( iface );
3335 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3336 return E_NOTIMPL;
3339 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3340 ISAXXMLReader* iface,
3341 const WCHAR **pSecureBaseUrl)
3343 saxreader *This = impl_from_ISAXXMLReader( iface );
3344 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3345 return E_NOTIMPL;
3348 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3349 ISAXXMLReader* iface,
3350 const WCHAR *secureBaseUrl)
3352 saxreader *This = impl_from_ISAXXMLReader( iface );
3354 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3355 return E_NOTIMPL;
3358 static HRESULT WINAPI isaxxmlreader_parse(
3359 ISAXXMLReader* iface,
3360 VARIANT varInput)
3362 saxreader *This = impl_from_ISAXXMLReader( iface );
3363 return internal_parse(This, varInput, FALSE);
3366 static HRESULT WINAPI isaxxmlreader_parseURL(
3367 ISAXXMLReader* iface,
3368 const WCHAR *url)
3370 saxreader *This = impl_from_ISAXXMLReader( iface );
3371 return internal_parseURL(This, url, FALSE);
3374 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3376 isaxxmlreader_QueryInterface,
3377 isaxxmlreader_AddRef,
3378 isaxxmlreader_Release,
3379 isaxxmlreader_getFeature,
3380 isaxxmlreader_putFeature,
3381 isaxxmlreader_getProperty,
3382 isaxxmlreader_putProperty,
3383 isaxxmlreader_getEntityResolver,
3384 isaxxmlreader_putEntityResolver,
3385 isaxxmlreader_getContentHandler,
3386 isaxxmlreader_putContentHandler,
3387 isaxxmlreader_getDTDHandler,
3388 isaxxmlreader_putDTDHandler,
3389 isaxxmlreader_getErrorHandler,
3390 isaxxmlreader_putErrorHandler,
3391 isaxxmlreader_getBaseURL,
3392 isaxxmlreader_putBaseURL,
3393 isaxxmlreader_getSecureBaseURL,
3394 isaxxmlreader_putSecureBaseURL,
3395 isaxxmlreader_parse,
3396 isaxxmlreader_parseURL
3399 static const tid_t saxreader_iface_tids[] = {
3400 IVBSAXXMLReader_tid,
3403 static dispex_static_data_t saxreader_dispex = {
3404 NULL,
3405 IVBSAXXMLReader_tid,
3406 NULL,
3407 saxreader_iface_tids
3410 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3412 saxreader *reader;
3414 TRACE("(%p)\n", ppObj);
3416 reader = heap_alloc( sizeof (*reader) );
3417 if( !reader )
3418 return E_OUTOFMEMORY;
3420 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3421 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3422 reader->ref = 1;
3423 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3424 reader->isParsing = FALSE;
3425 reader->xmldecl_version = NULL;
3426 reader->pool.pool = NULL;
3427 reader->pool.index = 0;
3428 reader->pool.len = 0;
3429 reader->features = Namespaces | NamespacePrefixes;
3430 reader->version = version;
3432 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3434 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3435 reader->sax.initialized = XML_SAX2_MAGIC;
3436 reader->sax.startDocument = libxmlStartDocument;
3437 reader->sax.endDocument = libxmlEndDocument;
3438 reader->sax.startElementNs = libxmlStartElementNS;
3439 reader->sax.endElementNs = libxmlEndElementNS;
3440 reader->sax.characters = libxmlCharacters;
3441 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3442 reader->sax.comment = libxmlComment;
3443 reader->sax.error = libxmlFatalError;
3444 reader->sax.fatalError = libxmlFatalError;
3445 reader->sax.cdataBlock = libxml_cdatablock;
3446 reader->sax.resolveEntity = libxmlresolveentity;
3448 *ppObj = &reader->IVBSAXXMLReader_iface;
3450 TRACE("returning iface %p\n", *ppObj);
3452 return S_OK;
3455 #else
3457 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3459 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3460 "libxml2 support was not present at compile time.\n");
3461 return E_NOTIMPL;
3464 #endif