ntdll/tests: Skip test if LdrAddRefDll is missing.
[wine.git] / dlls / msxml3 / saxreader.c
blob61534ac2eb65f2d8851ee967b292d6bf50785432
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"
45 #include "wine/list.h"
47 #include "msxml_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
51 #ifdef HAVE_LIBXML2
53 typedef enum
55 FeatureUnknown = 0,
56 ExhaustiveErrors = 1 << 1,
57 ExternalGeneralEntities = 1 << 2,
58 ExternalParameterEntities = 1 << 3,
59 ForcedResync = 1 << 4,
60 NamespacePrefixes = 1 << 5,
61 Namespaces = 1 << 6,
62 ParameterEntities = 1 << 7,
63 PreserveSystemIndentifiers = 1 << 8,
64 ProhibitDTD = 1 << 9,
65 SchemaValidation = 1 << 10,
66 ServerHttpRequest = 1 << 11,
67 SuppressValidationfatalError = 1 << 12,
68 UseInlineSchema = 1 << 13,
69 UseSchemaLocation = 1 << 14,
70 LexicalHandlerParEntities = 1 << 15
71 } saxreader_feature;
73 /* feature names */
74 static const WCHAR FeatureExternalGeneralEntitiesW[] = {
75 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/',
76 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l',
77 '-','e','n','t','i','t','i','e','s',0
80 static const WCHAR FeatureExternalParameterEntitiesW[] = {
81 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
82 '/','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
85 static const WCHAR FeatureLexicalHandlerParEntitiesW[] = {
86 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
87 '/','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
90 static const WCHAR FeatureProhibitDTDW[] = {
91 'p','r','o','h','i','b','i','t','-','d','t','d',0
94 static const WCHAR FeatureNamespacesW[] = {
95 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
96 '/','n','a','m','e','s','p','a','c','e','s',0
99 static const WCHAR FeatureNamespacePrefixesW[] = {
100 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
101 '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
104 struct saxreader_feature_pair
106 saxreader_feature feature;
107 const WCHAR *name;
110 static const struct saxreader_feature_pair saxreader_feature_map[] = {
111 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
112 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
113 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
114 { NamespacePrefixes, FeatureNamespacePrefixesW },
115 { Namespaces, FeatureNamespacesW },
116 { ProhibitDTD, FeatureProhibitDTDW }
119 static saxreader_feature get_saxreader_feature(const WCHAR *name)
121 int min, max, n, c;
123 min = 0;
124 max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
126 while (min <= max)
128 n = (min+max)/2;
130 c = strcmpW(saxreader_feature_map[n].name, name);
131 if (!c)
132 return saxreader_feature_map[n].feature;
134 if (c > 0)
135 max = n-1;
136 else
137 min = n+1;
140 return FeatureUnknown;
143 struct bstrpool
145 BSTR *pool;
146 unsigned int index;
147 unsigned int len;
150 typedef struct
152 BSTR prefix;
153 BSTR uri;
154 } ns;
156 typedef struct
158 struct list entry;
159 BSTR prefix;
160 BSTR local;
161 BSTR qname;
162 ns *ns; /* namespaces defined in this particular element */
163 int ns_count;
164 } element_entry;
166 enum saxhandler_type
168 SAXContentHandler = 0,
169 SAXDeclHandler,
170 SAXDTDHandler,
171 SAXEntityResolver,
172 SAXErrorHandler,
173 SAXLexicalHandler,
174 SAXHandler_Last
177 struct saxanyhandler_iface
179 IUnknown *handler;
180 IUnknown *vbhandler;
183 struct saxcontenthandler_iface
185 ISAXContentHandler *handler;
186 IVBSAXContentHandler *vbhandler;
189 struct saxerrorhandler_iface
191 ISAXErrorHandler *handler;
192 IVBSAXErrorHandler *vbhandler;
195 struct saxlexicalhandler_iface
197 ISAXLexicalHandler *handler;
198 IVBSAXLexicalHandler *vbhandler;
201 struct saxentityresolver_iface
203 ISAXEntityResolver *handler;
204 IVBSAXEntityResolver *vbhandler;
207 struct saxhandler_iface
209 union {
210 struct saxcontenthandler_iface content;
211 struct saxentityresolver_iface entityresolver;
212 struct saxerrorhandler_iface error;
213 struct saxlexicalhandler_iface lexical;
214 struct saxanyhandler_iface anyhandler;
215 } u;
218 typedef struct
220 DispatchEx dispex;
221 IVBSAXXMLReader IVBSAXXMLReader_iface;
222 ISAXXMLReader ISAXXMLReader_iface;
223 LONG ref;
225 struct saxhandler_iface saxhandlers[SAXHandler_Last];
226 xmlSAXHandler sax;
227 BOOL isParsing;
228 struct bstrpool pool;
229 saxreader_feature features;
230 BSTR xmldecl_version;
231 MSXML_VERSION version;
232 } saxreader;
234 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
236 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
237 IUnknown *unk = (IUnknown*)ptr;
239 if (unk)
240 IUnknown_AddRef(unk);
242 if ((vb && iface->vbhandler) || (!vb && iface->handler))
243 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
245 if (vb)
246 iface->vbhandler = unk;
247 else
248 iface->handler = unk;
250 return S_OK;
253 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
255 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
257 if (!ret) return E_POINTER;
259 if ((vb && iface->vbhandler) || (!vb && iface->handler))
261 if (vb)
262 IUnknown_AddRef(iface->vbhandler);
263 else
264 IUnknown_AddRef(iface->handler);
267 *ret = vb ? iface->vbhandler : iface->handler;
269 return S_OK;
272 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
274 return &reader->saxhandlers[SAXContentHandler].u.content;
277 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
279 return &reader->saxhandlers[SAXErrorHandler].u.error;
282 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
284 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
287 typedef struct
289 IVBSAXLocator IVBSAXLocator_iface;
290 ISAXLocator ISAXLocator_iface;
291 IVBSAXAttributes IVBSAXAttributes_iface;
292 ISAXAttributes ISAXAttributes_iface;
293 LONG ref;
294 saxreader *saxreader;
295 HRESULT ret;
296 xmlParserCtxtPtr pParserCtxt;
297 BSTR publicId;
298 BSTR systemId;
299 int line;
300 int column;
301 BOOL vbInterface;
302 struct list elements;
304 BSTR namespaceUri;
305 int attributesSize;
306 int nb_attributes;
307 struct _attributes
309 BSTR szLocalname;
310 BSTR szURI;
311 BSTR szValue;
312 BSTR szQName;
313 } *attributes;
314 } saxlocator;
316 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
318 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
321 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
323 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
326 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
328 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
331 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
333 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
336 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
338 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
341 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
343 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
346 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
348 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
349 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
352 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
354 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
355 HRESULT hr;
357 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
359 if (locator->vbInterface)
360 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
361 else
362 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
364 return hr;
367 /* property names */
368 static const WCHAR PropertyCharsetW[] = {
369 'c','h','a','r','s','e','t',0
371 static const WCHAR PropertyXmlDeclVersionW[] = {
372 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
374 static const WCHAR PropertyDeclHandlerW[] = {
375 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
376 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
377 'd','e','c','l','a','r','a','t','i','o','n',
378 '-','h','a','n','d','l','e','r',0
380 static const WCHAR PropertyDomNodeW[] = {
381 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
382 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
383 'd','o','m','-','n','o','d','e',0
385 static const WCHAR PropertyInputSourceW[] = {
386 'i','n','p','u','t','-','s','o','u','r','c','e',0
388 static const WCHAR PropertyLexicalHandlerW[] = {
389 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
390 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
391 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
393 static const WCHAR PropertyMaxElementDepthW[] = {
394 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
396 static const WCHAR PropertyMaxXMLSizeW[] = {
397 'm','a','x','-','x','m','l','-','s','i','z','e',0
399 static const WCHAR PropertySchemaDeclHandlerW[] = {
400 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
401 'h','a','n','d','l','e','r',0
403 static const WCHAR PropertyXMLDeclEncodingW[] = {
404 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
406 static const WCHAR PropertyXMLDeclStandaloneW[] = {
407 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
409 static const WCHAR PropertyXMLDeclVersionW[] = {
410 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
413 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
415 /* handling of non-VARIANT_* values is version dependent */
416 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
417 value = VARIANT_FALSE;
418 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
419 value = VARIANT_TRUE;
421 if (value == VARIANT_TRUE)
422 reader->features |= feature;
423 else
424 reader->features &= ~feature;
426 return S_OK;
429 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
431 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
432 return S_OK;
435 static BOOL is_namespaces_enabled(const saxreader *reader)
437 return (reader->version < MSXML4) || (reader->features & Namespaces);
440 static BSTR build_qname(BSTR prefix, BSTR local)
442 if (prefix && *prefix)
444 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
445 WCHAR *ptr;
447 ptr = qname;
448 strcpyW(ptr, prefix);
449 ptr += SysStringLen(prefix);
450 *ptr++ = ':';
451 strcpyW(ptr, local);
452 return qname;
454 else
455 return SysAllocString(local);
458 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
459 const xmlChar **namespaces)
461 element_entry *ret;
462 int i;
464 ret = heap_alloc(sizeof(*ret));
465 if (!ret) return ret;
467 ret->local = bstr_from_xmlChar(local);
468 ret->prefix = bstr_from_xmlChar(prefix);
469 ret->qname = build_qname(ret->prefix, ret->local);
470 ret->ns = nb_ns ? heap_alloc(nb_ns*sizeof(ns)) : NULL;
471 ret->ns_count = nb_ns;
473 for (i=0; i < nb_ns; i++)
475 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
476 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
479 return ret;
482 static void free_element_entry(element_entry *element)
484 int i;
486 for (i=0; i<element->ns_count;i++)
488 SysFreeString(element->ns[i].prefix);
489 SysFreeString(element->ns[i].uri);
492 SysFreeString(element->prefix);
493 SysFreeString(element->local);
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 /*** IUnknown methods ***/
709 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
710 IVBSAXAttributes* iface,
711 REFIID riid,
712 void **ppvObject)
714 saxlocator *This = impl_from_IVBSAXAttributes(iface);
715 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
716 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
719 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
721 saxlocator *This = impl_from_IVBSAXAttributes(iface);
722 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
725 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
727 saxlocator *This = impl_from_IVBSAXAttributes(iface);
728 return ISAXLocator_Release(&This->ISAXLocator_iface);
731 /*** IDispatch methods ***/
732 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
734 saxlocator *This = impl_from_IVBSAXAttributes( iface );
736 TRACE("(%p)->(%p)\n", This, pctinfo);
738 *pctinfo = 1;
740 return S_OK;
743 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
744 IVBSAXAttributes *iface,
745 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
747 saxlocator *This = impl_from_IVBSAXAttributes( iface );
748 HRESULT hr;
750 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
752 hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
754 return hr;
757 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
758 IVBSAXAttributes *iface,
759 REFIID riid,
760 LPOLESTR* rgszNames,
761 UINT cNames,
762 LCID lcid,
763 DISPID* rgDispId)
765 saxlocator *This = impl_from_IVBSAXAttributes( iface );
766 ITypeInfo *typeinfo;
767 HRESULT hr;
769 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
770 lcid, rgDispId);
772 if(!rgszNames || cNames == 0 || !rgDispId)
773 return E_INVALIDARG;
775 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
776 if(SUCCEEDED(hr))
778 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
779 ITypeInfo_Release(typeinfo);
782 return hr;
785 static HRESULT WINAPI ivbsaxattributes_Invoke(
786 IVBSAXAttributes *iface,
787 DISPID dispIdMember,
788 REFIID riid,
789 LCID lcid,
790 WORD wFlags,
791 DISPPARAMS* pDispParams,
792 VARIANT* pVarResult,
793 EXCEPINFO* pExcepInfo,
794 UINT* puArgErr)
796 saxlocator *This = impl_from_IVBSAXAttributes( iface );
797 ITypeInfo *typeinfo;
798 HRESULT hr;
800 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
801 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
803 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
804 if(SUCCEEDED(hr))
806 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
807 pDispParams, pVarResult, pExcepInfo, puArgErr);
808 ITypeInfo_Release(typeinfo);
811 return hr;
814 /*** IVBSAXAttributes methods ***/
815 static HRESULT WINAPI ivbsaxattributes_get_length(
816 IVBSAXAttributes* iface,
817 int *nLength)
819 saxlocator *This = impl_from_IVBSAXAttributes( iface );
820 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
823 static HRESULT WINAPI ivbsaxattributes_getURI(
824 IVBSAXAttributes* iface,
825 int nIndex,
826 BSTR *uri)
828 int len;
829 saxlocator *This = impl_from_IVBSAXAttributes( iface );
830 return ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)uri, &len);
833 static HRESULT WINAPI ivbsaxattributes_getLocalName(
834 IVBSAXAttributes* iface,
835 int nIndex,
836 BSTR *localName)
838 int len;
839 saxlocator *This = impl_from_IVBSAXAttributes( iface );
840 return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex,
841 (const WCHAR**)localName, &len);
844 static HRESULT WINAPI ivbsaxattributes_getQName(
845 IVBSAXAttributes* iface,
846 int nIndex,
847 BSTR *QName)
849 int len;
850 saxlocator *This = impl_from_IVBSAXAttributes( iface );
851 return ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)QName, &len);
854 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
855 IVBSAXAttributes* iface,
856 BSTR uri,
857 BSTR localName,
858 int *index)
860 saxlocator *This = impl_from_IVBSAXAttributes( iface );
861 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
862 localName, SysStringLen(localName), index);
865 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
866 IVBSAXAttributes* iface,
867 BSTR QName,
868 int *index)
870 saxlocator *This = impl_from_IVBSAXAttributes( iface );
871 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
872 SysStringLen(QName), index);
875 static HRESULT WINAPI ivbsaxattributes_getType(
876 IVBSAXAttributes* iface,
877 int nIndex,
878 BSTR *type)
880 int len;
881 saxlocator *This = impl_from_IVBSAXAttributes( iface );
882 return ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)type, &len);
885 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
886 IVBSAXAttributes* iface,
887 BSTR uri,
888 BSTR localName,
889 BSTR *type)
891 int len;
892 saxlocator *This = impl_from_IVBSAXAttributes( iface );
893 return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
894 localName, SysStringLen(localName), (const WCHAR**)type, &len);
897 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
898 IVBSAXAttributes* iface,
899 BSTR QName,
900 BSTR *type)
902 int len;
903 saxlocator *This = impl_from_IVBSAXAttributes( iface );
904 return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
905 (const WCHAR**)type, &len);
908 static HRESULT WINAPI ivbsaxattributes_getValue(
909 IVBSAXAttributes* iface,
910 int nIndex,
911 BSTR *value)
913 int len;
914 saxlocator *This = impl_from_IVBSAXAttributes( iface );
915 return ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)value, &len);
918 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
919 IVBSAXAttributes* iface,
920 BSTR uri,
921 BSTR localName,
922 BSTR *value)
924 int len;
925 saxlocator *This = impl_from_IVBSAXAttributes( iface );
926 return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
927 localName, SysStringLen(localName), (const WCHAR**)value, &len);
930 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
931 IVBSAXAttributes* iface,
932 BSTR QName,
933 BSTR *value)
935 int len;
936 saxlocator *This = impl_from_IVBSAXAttributes( iface );
937 return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
938 SysStringLen(QName), (const WCHAR**)value, &len);
941 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
943 ivbsaxattributes_QueryInterface,
944 ivbsaxattributes_AddRef,
945 ivbsaxattributes_Release,
946 ivbsaxattributes_GetTypeInfoCount,
947 ivbsaxattributes_GetTypeInfo,
948 ivbsaxattributes_GetIDsOfNames,
949 ivbsaxattributes_Invoke,
950 ivbsaxattributes_get_length,
951 ivbsaxattributes_getURI,
952 ivbsaxattributes_getLocalName,
953 ivbsaxattributes_getQName,
954 ivbsaxattributes_getIndexFromName,
955 ivbsaxattributes_getIndexFromQName,
956 ivbsaxattributes_getType,
957 ivbsaxattributes_getTypeFromName,
958 ivbsaxattributes_getTypeFromQName,
959 ivbsaxattributes_getValue,
960 ivbsaxattributes_getValueFromName,
961 ivbsaxattributes_getValueFromQName
964 /*** ISAXAttributes interface ***/
965 /*** IUnknown methods ***/
966 static HRESULT WINAPI isaxattributes_QueryInterface(
967 ISAXAttributes* iface,
968 REFIID riid,
969 void **ppvObject)
971 saxlocator *This = impl_from_ISAXAttributes(iface);
972 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
973 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
976 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
978 saxlocator *This = impl_from_ISAXAttributes(iface);
979 TRACE("%p\n", This);
980 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
983 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
985 saxlocator *This = impl_from_ISAXAttributes(iface);
987 TRACE("%p\n", This);
988 return ISAXLocator_Release(&This->ISAXLocator_iface);
991 /*** ISAXAttributes methods ***/
992 static HRESULT WINAPI isaxattributes_getLength(
993 ISAXAttributes* iface,
994 int *length)
996 saxlocator *This = impl_from_ISAXAttributes( iface );
998 *length = This->nb_attributes;
999 TRACE("Length set to %d\n", *length);
1000 return S_OK;
1003 static HRESULT WINAPI isaxattributes_getURI(
1004 ISAXAttributes* iface,
1005 int index,
1006 const WCHAR **url,
1007 int *size)
1009 saxlocator *This = impl_from_ISAXAttributes( iface );
1010 TRACE("(%p)->(%d)\n", This, index);
1012 if(index >= This->nb_attributes || index < 0) return E_INVALIDARG;
1013 if(!url || !size) return E_POINTER;
1015 *size = SysStringLen(This->attributes[index].szURI);
1016 *url = This->attributes[index].szURI;
1018 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1020 return S_OK;
1023 static HRESULT WINAPI isaxattributes_getLocalName(
1024 ISAXAttributes* iface,
1025 int nIndex,
1026 const WCHAR **pLocalName,
1027 int *pLocalNameLength)
1029 saxlocator *This = impl_from_ISAXAttributes( iface );
1030 TRACE("(%p)->(%d)\n", This, nIndex);
1032 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1033 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1035 *pLocalNameLength = SysStringLen(This->attributes[nIndex].szLocalname);
1036 *pLocalName = This->attributes[nIndex].szLocalname;
1038 return S_OK;
1041 static HRESULT WINAPI isaxattributes_getQName(
1042 ISAXAttributes* iface,
1043 int nIndex,
1044 const WCHAR **pQName,
1045 int *pQNameLength)
1047 saxlocator *This = impl_from_ISAXAttributes( iface );
1048 TRACE("(%p)->(%d)\n", This, nIndex);
1050 if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
1051 if(!pQName || !pQNameLength) return E_POINTER;
1053 *pQNameLength = SysStringLen(This->attributes[nIndex].szQName);
1054 *pQName = This->attributes[nIndex].szQName;
1056 return S_OK;
1059 static HRESULT WINAPI isaxattributes_getName(
1060 ISAXAttributes* iface,
1061 int index,
1062 const WCHAR **uri,
1063 int *pUriLength,
1064 const WCHAR **localName,
1065 int *pLocalNameSize,
1066 const WCHAR **QName,
1067 int *pQNameLength)
1069 saxlocator *This = impl_from_ISAXAttributes( iface );
1070 TRACE("(%p)->(%d)\n", This, index);
1072 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1073 if(!uri || !pUriLength || !localName || !pLocalNameSize
1074 || !QName || !pQNameLength) return E_POINTER;
1076 *pUriLength = SysStringLen(This->attributes[index].szURI);
1077 *uri = This->attributes[index].szURI;
1078 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1079 *localName = This->attributes[index].szLocalname;
1080 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1081 *QName = This->attributes[index].szQName;
1083 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1085 return S_OK;
1088 static HRESULT WINAPI isaxattributes_getIndexFromName(
1089 ISAXAttributes* iface,
1090 const WCHAR *pUri,
1091 int cUriLength,
1092 const WCHAR *pLocalName,
1093 int cocalNameLength,
1094 int *index)
1096 saxlocator *This = impl_from_ISAXAttributes( iface );
1097 int i;
1098 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1099 debugstr_w(pLocalName), cocalNameLength);
1101 if(!pUri || !pLocalName || !index) return E_POINTER;
1103 for(i=0; i<This->nb_attributes; i++)
1105 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1106 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1107 continue;
1108 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1109 sizeof(WCHAR)*cUriLength))
1110 continue;
1111 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1112 sizeof(WCHAR)*cocalNameLength))
1113 continue;
1115 *index = i;
1116 return S_OK;
1119 return E_INVALIDARG;
1122 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1123 ISAXAttributes* iface,
1124 const WCHAR *pQName,
1125 int nQNameLength,
1126 int *index)
1128 saxlocator *This = impl_from_ISAXAttributes( iface );
1129 int i;
1130 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1132 if(!pQName || !index) return E_POINTER;
1133 if(!nQNameLength) return E_INVALIDARG;
1135 for(i=0; i<This->nb_attributes; i++)
1137 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1138 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1140 *index = i;
1141 return S_OK;
1144 return E_INVALIDARG;
1147 static HRESULT WINAPI isaxattributes_getType(
1148 ISAXAttributes* iface,
1149 int nIndex,
1150 const WCHAR **pType,
1151 int *pTypeLength)
1153 saxlocator *This = impl_from_ISAXAttributes( iface );
1155 FIXME("(%p)->(%d) stub\n", This, nIndex);
1156 return E_NOTIMPL;
1159 static HRESULT WINAPI isaxattributes_getTypeFromName(
1160 ISAXAttributes* iface,
1161 const WCHAR *pUri,
1162 int nUri,
1163 const WCHAR *pLocalName,
1164 int nLocalName,
1165 const WCHAR **pType,
1166 int *nType)
1168 saxlocator *This = impl_from_ISAXAttributes( iface );
1170 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1171 debugstr_w(pLocalName), nLocalName);
1172 return E_NOTIMPL;
1175 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1176 ISAXAttributes* iface,
1177 const WCHAR *pQName,
1178 int nQName,
1179 const WCHAR **pType,
1180 int *nType)
1182 saxlocator *This = impl_from_ISAXAttributes( iface );
1184 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1185 return E_NOTIMPL;
1188 static HRESULT WINAPI isaxattributes_getValue(
1189 ISAXAttributes* iface,
1190 int index,
1191 const WCHAR **value,
1192 int *nValue)
1194 saxlocator *This = impl_from_ISAXAttributes( iface );
1195 TRACE("(%p)->(%d)\n", This, index);
1197 if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
1198 if(!value || !nValue) return E_POINTER;
1200 *nValue = SysStringLen(This->attributes[index].szValue);
1201 *value = This->attributes[index].szValue;
1203 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1205 return S_OK;
1208 static HRESULT WINAPI isaxattributes_getValueFromName(
1209 ISAXAttributes* iface,
1210 const WCHAR *pUri,
1211 int nUri,
1212 const WCHAR *pLocalName,
1213 int nLocalName,
1214 const WCHAR **pValue,
1215 int *nValue)
1217 HRESULT hr;
1218 int index;
1219 saxlocator *This = impl_from_ISAXAttributes( iface );
1220 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1221 debugstr_w(pLocalName), nLocalName);
1223 hr = ISAXAttributes_getIndexFromName(iface,
1224 pUri, nUri, pLocalName, nLocalName, &index);
1225 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1227 return hr;
1230 static HRESULT WINAPI isaxattributes_getValueFromQName(
1231 ISAXAttributes* iface,
1232 const WCHAR *pQName,
1233 int nQName,
1234 const WCHAR **pValue,
1235 int *nValue)
1237 HRESULT hr;
1238 int index;
1239 saxlocator *This = impl_from_ISAXAttributes( iface );
1240 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1242 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1243 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1245 return hr;
1248 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1250 isaxattributes_QueryInterface,
1251 isaxattributes_AddRef,
1252 isaxattributes_Release,
1253 isaxattributes_getLength,
1254 isaxattributes_getURI,
1255 isaxattributes_getLocalName,
1256 isaxattributes_getQName,
1257 isaxattributes_getName,
1258 isaxattributes_getIndexFromName,
1259 isaxattributes_getIndexFromQName,
1260 isaxattributes_getType,
1261 isaxattributes_getTypeFromName,
1262 isaxattributes_getTypeFromQName,
1263 isaxattributes_getValue,
1264 isaxattributes_getValueFromName,
1265 isaxattributes_getValueFromQName
1268 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1269 so when document has escaped value with '&amp;' it's parsed to '&' and then
1270 escaped to '&#38;'. This function takes care of ampersands only. */
1271 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1273 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1274 WCHAR *dest, *ptrW, *str;
1275 DWORD str_len;
1276 BSTR bstr;
1278 if (!buf)
1279 return NULL;
1281 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1282 if (len != -1) str_len++;
1284 str = heap_alloc(str_len*sizeof(WCHAR));
1285 if (!str) return NULL;
1287 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1288 if (len != -1) str[str_len-1] = 0;
1290 ptrW = str;
1291 while ((dest = strstrW(ptrW, ampescW)))
1293 WCHAR *src;
1295 /* leave first '&' from a reference as a value */
1296 src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
1297 dest++;
1299 /* move together with null terminator */
1300 memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
1302 ptrW++;
1305 bstr = SysAllocString(str);
1306 heap_free(str);
1308 return bstr;
1311 static HRESULT SAXAttributes_populate(saxlocator *locator,
1312 int nb_namespaces, const xmlChar **xmlNamespaces,
1313 int nb_attributes, const xmlChar **xmlAttributes)
1315 static const xmlChar xmlns[] = "xmlns";
1316 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1318 struct _attributes *attrs;
1319 int i;
1321 /* skip namespace definitions */
1322 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1323 nb_namespaces = 0;
1325 locator->nb_attributes = nb_namespaces + nb_attributes;
1326 if(locator->nb_attributes > locator->attributesSize)
1328 attrs = heap_realloc(locator->attributes, sizeof(struct _attributes)*locator->nb_attributes*2);
1329 if(!attrs)
1331 locator->nb_attributes = 0;
1332 return E_OUTOFMEMORY;
1334 locator->attributes = attrs;
1336 else
1338 attrs = locator->attributes;
1341 for (i = 0; i < nb_namespaces; i++)
1343 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1344 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1345 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1346 if(!xmlNamespaces[2*i])
1347 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1348 else
1349 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1352 for (i = 0; i < nb_attributes; i++)
1354 static const xmlChar xmlA[] = "xml";
1356 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1357 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1358 else
1359 /* that's an important feature to keep same uri pointer for every reported attribute */
1360 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1362 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1363 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1364 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1],
1365 xmlAttributes[i*5]);
1368 return S_OK;
1371 /*** LibXML callbacks ***/
1372 static void libxmlStartDocument(void *ctx)
1374 saxlocator *This = ctx;
1375 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1376 HRESULT hr;
1378 if (This->saxreader->version >= MSXML4)
1380 const xmlChar *p = This->pParserCtxt->input->cur-1;
1381 update_position(This, FALSE);
1382 while(p>This->pParserCtxt->input->base && *p!='>')
1384 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1385 This->line--;
1386 p--;
1388 This->column = 0;
1389 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1390 This->column++;
1393 /* store version value, declaration has to contain version attribute */
1394 if (This->pParserCtxt->standalone != -1)
1396 SysFreeString(This->saxreader->xmldecl_version);
1397 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1400 if (saxreader_has_handler(This, SAXContentHandler))
1402 if(This->vbInterface)
1403 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1404 else
1405 hr = ISAXContentHandler_startDocument(handler->handler);
1407 if (sax_callback_failed(This, hr))
1408 format_error_message_from_id(This, hr);
1412 static void libxmlEndDocument(void *ctx)
1414 saxlocator *This = ctx;
1415 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1416 HRESULT hr;
1418 if (This->saxreader->version >= MSXML4) {
1419 update_position(This, FALSE);
1420 if(This->column > 1)
1421 This->line++;
1422 This->column = 0;
1423 } else {
1424 This->column = 0;
1425 This->line = 0;
1428 if(This->ret != S_OK) return;
1430 if (saxreader_has_handler(This, SAXContentHandler))
1432 if(This->vbInterface)
1433 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1434 else
1435 hr = ISAXContentHandler_endDocument(handler->handler);
1437 if (sax_callback_failed(This, hr))
1438 format_error_message_from_id(This, hr);
1442 static void libxmlStartElementNS(
1443 void *ctx,
1444 const xmlChar *localname,
1445 const xmlChar *prefix,
1446 const xmlChar *URI,
1447 int nb_namespaces,
1448 const xmlChar **namespaces,
1449 int nb_attributes,
1450 int nb_defaulted,
1451 const xmlChar **attributes)
1453 saxlocator *This = ctx;
1454 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1455 element_entry *element;
1456 HRESULT hr = S_OK;
1457 BSTR uri;
1459 update_position(This, TRUE);
1460 if(*(This->pParserCtxt->input->cur) == '/')
1461 This->column++;
1462 if(This->saxreader->version < MSXML4)
1463 This->column++;
1465 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1466 push_element_ns(This, element);
1468 if (is_namespaces_enabled(This->saxreader))
1470 int i;
1472 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1474 if (This->vbInterface)
1475 hr = IVBSAXContentHandler_startPrefixMapping(
1476 handler->vbhandler,
1477 &element->ns[i].prefix,
1478 &element->ns[i].uri);
1479 else
1480 hr = ISAXContentHandler_startPrefixMapping(
1481 handler->handler,
1482 element->ns[i].prefix,
1483 SysStringLen(element->ns[i].prefix),
1484 element->ns[i].uri,
1485 SysStringLen(element->ns[i].uri));
1487 if (sax_callback_failed(This, hr))
1489 format_error_message_from_id(This, hr);
1490 return;
1495 uri = find_element_uri(This, URI);
1496 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1497 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1499 BSTR local;
1501 if (is_namespaces_enabled(This->saxreader))
1502 local = element->local;
1503 else
1504 uri = local = NULL;
1506 if (This->vbInterface)
1507 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1508 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1509 else
1510 hr = ISAXContentHandler_startElement(handler->handler,
1511 uri, SysStringLen(uri),
1512 local, SysStringLen(local),
1513 element->qname, SysStringLen(element->qname),
1514 &This->ISAXAttributes_iface);
1516 if (sax_callback_failed(This, hr))
1517 format_error_message_from_id(This, hr);
1521 static void libxmlEndElementNS(
1522 void *ctx,
1523 const xmlChar *localname,
1524 const xmlChar *prefix,
1525 const xmlChar *URI)
1527 saxlocator *This = ctx;
1528 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1529 element_entry *element;
1530 const xmlChar *p;
1531 BSTR uri, local;
1532 HRESULT hr;
1534 update_position(This, FALSE);
1535 p = This->pParserCtxt->input->cur;
1537 if (This->saxreader->version >= MSXML4)
1539 p--;
1540 while(p>This->pParserCtxt->input->base && *p!='>')
1542 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1543 This->line--;
1544 p--;
1547 else if(*(p-1)!='>' || *(p-2)!='/')
1549 p--;
1550 while(p-2>=This->pParserCtxt->input->base
1551 && *(p-2)!='<' && *(p-1)!='/')
1553 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1554 This->line--;
1555 p--;
1558 This->column = 0;
1559 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1560 This->column++;
1562 uri = find_element_uri(This, URI);
1563 element = pop_element_ns(This);
1565 if (!saxreader_has_handler(This, SAXContentHandler))
1567 This->nb_attributes = 0;
1568 free_element_entry(element);
1569 return;
1572 if (is_namespaces_enabled(This->saxreader))
1573 local = element->local;
1574 else
1575 uri = local = NULL;
1577 if (This->vbInterface)
1578 hr = IVBSAXContentHandler_endElement(
1579 handler->vbhandler,
1580 &uri, &local, &element->qname);
1581 else
1582 hr = ISAXContentHandler_endElement(
1583 handler->handler,
1584 uri, SysStringLen(uri),
1585 local, SysStringLen(local),
1586 element->qname, SysStringLen(element->qname));
1588 This->nb_attributes = 0;
1590 if (sax_callback_failed(This, hr))
1592 format_error_message_from_id(This, hr);
1593 free_element_entry(element);
1594 return;
1597 if (is_namespaces_enabled(This->saxreader))
1599 int i = -1;
1600 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1602 if (This->vbInterface)
1603 hr = IVBSAXContentHandler_endPrefixMapping(
1604 handler->vbhandler, &element->ns[i].prefix);
1605 else
1606 hr = ISAXContentHandler_endPrefixMapping(
1607 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1609 if (sax_callback_failed(This, hr)) break;
1612 if (sax_callback_failed(This, hr))
1613 format_error_message_from_id(This, hr);
1616 free_element_entry(element);
1619 static void libxmlCharacters(
1620 void *ctx,
1621 const xmlChar *ch,
1622 int len)
1624 saxlocator *This = ctx;
1625 BSTR Chars;
1626 HRESULT hr;
1627 xmlChar *cur, *end;
1628 BOOL lastEvent = FALSE;
1630 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1632 update_position(This, FALSE);
1633 cur = (xmlChar*)This->pParserCtxt->input->cur;
1634 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1636 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1637 This->line--;
1638 cur--;
1640 This->column = 1;
1641 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1642 This->column++;
1644 cur = (xmlChar*)ch;
1645 if(*(ch-1)=='\r') cur--;
1646 end = cur;
1648 while(1)
1650 while(end-ch<len && *end!='\r') end++;
1651 if(end-ch==len)
1653 lastEvent = TRUE;
1655 else
1657 *end = '\n';
1658 end++;
1661 if (This->saxreader->version >= MSXML4)
1663 xmlChar *p;
1665 for(p=cur; p!=end; p++)
1667 if(*p=='\n')
1669 This->line++;
1670 This->column = 1;
1672 else
1674 This->column++;
1678 if(!lastEvent)
1679 This->column = 0;
1682 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1683 hr = saxreader_saxcharacters(This, Chars);
1685 if (sax_callback_failed(This, hr))
1687 format_error_message_from_id(This, hr);
1688 return;
1691 if (This->saxreader->version < MSXML4)
1692 This->column += end-cur;
1694 if(lastEvent)
1695 break;
1697 *(end-1) = '\r';
1698 if(*end == '\n')
1700 end++;
1701 This->column++;
1703 cur = end;
1705 if(end-ch == len) break;
1709 static void libxmlSetDocumentLocator(
1710 void *ctx,
1711 xmlSAXLocatorPtr loc)
1713 saxlocator *This = ctx;
1714 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1715 HRESULT hr = S_OK;
1717 if (saxreader_has_handler(This, SAXContentHandler))
1719 if(This->vbInterface)
1720 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1721 &This->IVBSAXLocator_iface);
1722 else
1723 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1726 if(FAILED(hr))
1727 format_error_message_from_id(This, hr);
1730 static void libxmlComment(void *ctx, const xmlChar *value)
1732 saxlocator *This = ctx;
1733 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1734 BSTR bValue;
1735 HRESULT hr;
1736 const xmlChar *p = This->pParserCtxt->input->cur;
1738 update_position(This, FALSE);
1739 while(p-4>=This->pParserCtxt->input->base
1740 && memcmp(p-4, "<!--", sizeof(char[4])))
1742 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1743 This->line--;
1744 p--;
1747 This->column = 0;
1748 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1749 This->column++;
1751 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1753 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1755 if (This->vbInterface)
1756 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1757 else
1758 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1760 if(FAILED(hr))
1761 format_error_message_from_id(This, hr);
1764 static void libxmlFatalError(void *ctx, const char *msg, ...)
1766 saxlocator *This = ctx;
1767 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1768 char message[1024];
1769 WCHAR *error;
1770 DWORD len;
1771 va_list args;
1773 if(This->ret != S_OK) {
1774 xmlStopParser(This->pParserCtxt);
1775 return;
1778 va_start(args, msg);
1779 vsprintf(message, msg, args);
1780 va_end(args);
1782 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1783 error = heap_alloc(sizeof(WCHAR)*len);
1784 if(error)
1786 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1787 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1790 if (!saxreader_has_handler(This, SAXErrorHandler))
1792 xmlStopParser(This->pParserCtxt);
1793 This->ret = E_FAIL;
1794 heap_free(error);
1795 return;
1798 FIXME("Error handling is not compatible.\n");
1800 if(This->vbInterface)
1802 BSTR bstrError = SysAllocString(error);
1803 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1804 &bstrError, E_FAIL);
1805 SysFreeString(bstrError);
1807 else
1808 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1810 heap_free(error);
1812 xmlStopParser(This->pParserCtxt);
1813 This->ret = E_FAIL;
1816 /* The only reason this helper exists is that CDATA section are reported by chunks,
1817 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1819 This helper should be called for substring with trailing newlines.
1821 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1823 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1824 WCHAR *ptr;
1826 ptr = bstr + len - 1;
1827 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1828 ptr--;
1830 while (*++ptr)
1832 /* replace returns as:
1834 - "\r<char>" -> "\n<char>"
1835 - "\r\r" -> "\r"
1836 - "\r\n" -> "\n"
1838 if (*ptr == '\r')
1840 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1842 /* shift tail */
1843 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1845 else
1846 *ptr = '\n';
1850 ret = SysAllocStringLen(bstr, len);
1851 SysFreeString(bstr);
1852 return ret;
1855 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
1857 const xmlChar *start, *end;
1858 saxlocator *locator = ctx;
1859 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
1860 HRESULT hr = S_OK;
1861 BSTR chars;
1862 int i;
1864 update_position(locator, FALSE);
1865 if (saxreader_has_handler(locator, SAXLexicalHandler))
1867 if (locator->vbInterface)
1868 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
1869 else
1870 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
1873 if(FAILED(hr))
1875 format_error_message_from_id(locator, hr);
1876 return;
1879 start = value;
1880 end = NULL;
1881 i = 0;
1883 while (i < len)
1885 /* scan for newlines */
1886 if (value[i] == '\r' || value[i] == '\n')
1888 /* skip newlines/linefeeds */
1889 while (i < len)
1891 if (value[i] != '\r' && value[i] != '\n') break;
1892 i++;
1894 end = &value[i];
1896 /* report */
1897 chars = saxreader_get_cdata_chunk(start, end-start);
1898 TRACE("(chunk %s)\n", debugstr_w(chars));
1899 hr = saxreader_saxcharacters(locator, chars);
1900 SysFreeString(chars);
1902 start = &value[i];
1903 end = NULL;
1905 i++;
1906 locator->column++;
1909 /* no newline chars (or last chunk) report as a whole */
1910 if (!end && start == value)
1912 /* report */
1913 chars = bstr_from_xmlCharN(start, len-(start-value));
1914 TRACE("(%s)\n", debugstr_w(chars));
1915 hr = saxreader_saxcharacters(locator, chars);
1916 SysFreeString(chars);
1919 if (saxreader_has_handler(locator, SAXLexicalHandler))
1921 if (locator->vbInterface)
1922 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
1923 else
1924 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
1927 if(FAILED(hr))
1928 format_error_message_from_id(locator, hr);
1931 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
1933 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
1934 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
1937 /*** IVBSAXLocator interface ***/
1938 /*** IUnknown methods ***/
1939 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1941 saxlocator *This = impl_from_IVBSAXLocator( iface );
1943 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1945 *ppvObject = NULL;
1947 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1948 IsEqualGUID( riid, &IID_IDispatch) ||
1949 IsEqualGUID( riid, &IID_IVBSAXLocator ))
1951 *ppvObject = iface;
1953 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
1955 *ppvObject = &This->IVBSAXAttributes_iface;
1957 else
1959 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1960 return E_NOINTERFACE;
1963 IVBSAXLocator_AddRef( iface );
1965 return S_OK;
1968 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1970 saxlocator *This = impl_from_IVBSAXLocator( iface );
1971 TRACE("%p\n", This );
1972 return InterlockedIncrement( &This->ref );
1975 static ULONG WINAPI ivbsaxlocator_Release(
1976 IVBSAXLocator* iface)
1978 saxlocator *This = impl_from_IVBSAXLocator( iface );
1979 return ISAXLocator_Release((ISAXLocator*)&This->IVBSAXLocator_iface);
1982 /*** IDispatch methods ***/
1983 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1985 saxlocator *This = impl_from_IVBSAXLocator( iface );
1987 TRACE("(%p)->(%p)\n", This, pctinfo);
1989 *pctinfo = 1;
1991 return S_OK;
1994 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1995 IVBSAXLocator *iface,
1996 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1998 saxlocator *This = impl_from_IVBSAXLocator( iface );
1999 HRESULT hr;
2001 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2003 hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2005 return hr;
2008 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2009 IVBSAXLocator *iface,
2010 REFIID riid,
2011 LPOLESTR* rgszNames,
2012 UINT cNames,
2013 LCID lcid,
2014 DISPID* rgDispId)
2016 saxlocator *This = impl_from_IVBSAXLocator( iface );
2017 ITypeInfo *typeinfo;
2018 HRESULT hr;
2020 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2021 lcid, rgDispId);
2023 if(!rgszNames || cNames == 0 || !rgDispId)
2024 return E_INVALIDARG;
2026 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2027 if(SUCCEEDED(hr))
2029 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2030 ITypeInfo_Release(typeinfo);
2033 return hr;
2036 static HRESULT WINAPI ivbsaxlocator_Invoke(
2037 IVBSAXLocator *iface,
2038 DISPID dispIdMember,
2039 REFIID riid,
2040 LCID lcid,
2041 WORD wFlags,
2042 DISPPARAMS* pDispParams,
2043 VARIANT* pVarResult,
2044 EXCEPINFO* pExcepInfo,
2045 UINT* puArgErr)
2047 saxlocator *This = impl_from_IVBSAXLocator( iface );
2048 ITypeInfo *typeinfo;
2049 HRESULT hr;
2051 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2052 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2054 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2055 if(SUCCEEDED(hr))
2057 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXLocator_iface, dispIdMember, wFlags,
2058 pDispParams, pVarResult, pExcepInfo, puArgErr);
2059 ITypeInfo_Release(typeinfo);
2062 return hr;
2065 /*** IVBSAXLocator methods ***/
2066 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2067 IVBSAXLocator* iface,
2068 int *pnColumn)
2070 saxlocator *This = impl_from_IVBSAXLocator( iface );
2071 return ISAXLocator_getColumnNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnColumn);
2074 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2075 IVBSAXLocator* iface,
2076 int *pnLine)
2078 saxlocator *This = impl_from_IVBSAXLocator( iface );
2079 return ISAXLocator_getLineNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnLine);
2082 static HRESULT WINAPI ivbsaxlocator_get_publicId(
2083 IVBSAXLocator* iface,
2084 BSTR* publicId)
2086 saxlocator *This = impl_from_IVBSAXLocator( iface );
2087 return ISAXLocator_getPublicId((ISAXLocator*)&This->IVBSAXLocator_iface,
2088 (const WCHAR**)publicId);
2091 static HRESULT WINAPI ivbsaxlocator_get_systemId(
2092 IVBSAXLocator* iface,
2093 BSTR* systemId)
2095 saxlocator *This = impl_from_IVBSAXLocator( iface );
2096 return ISAXLocator_getSystemId((ISAXLocator*)&This->IVBSAXLocator_iface,
2097 (const WCHAR**)systemId);
2100 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2102 ivbsaxlocator_QueryInterface,
2103 ivbsaxlocator_AddRef,
2104 ivbsaxlocator_Release,
2105 ivbsaxlocator_GetTypeInfoCount,
2106 ivbsaxlocator_GetTypeInfo,
2107 ivbsaxlocator_GetIDsOfNames,
2108 ivbsaxlocator_Invoke,
2109 ivbsaxlocator_get_columnNumber,
2110 ivbsaxlocator_get_lineNumber,
2111 ivbsaxlocator_get_publicId,
2112 ivbsaxlocator_get_systemId
2115 /*** ISAXLocator interface ***/
2116 /*** IUnknown methods ***/
2117 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2119 saxlocator *This = impl_from_ISAXLocator( iface );
2121 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2123 *ppvObject = NULL;
2125 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2126 IsEqualGUID( riid, &IID_ISAXLocator ))
2128 *ppvObject = iface;
2130 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2132 *ppvObject = &This->ISAXAttributes_iface;
2134 else
2136 WARN("interface %s not implemented\n", debugstr_guid(riid));
2137 return E_NOINTERFACE;
2140 ISAXLocator_AddRef( iface );
2142 return S_OK;
2145 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2147 saxlocator *This = impl_from_ISAXLocator( iface );
2148 ULONG ref = InterlockedIncrement( &This->ref );
2149 TRACE("(%p)->(%d)\n", This, ref);
2150 return ref;
2153 static ULONG WINAPI isaxlocator_Release(
2154 ISAXLocator* iface)
2156 saxlocator *This = impl_from_ISAXLocator( iface );
2157 LONG ref = InterlockedDecrement( &This->ref );
2159 TRACE("(%p)->(%d)\n", This, ref );
2161 if (ref == 0)
2163 element_entry *element, *element2;
2164 int index;
2166 SysFreeString(This->publicId);
2167 SysFreeString(This->systemId);
2168 SysFreeString(This->namespaceUri);
2170 for(index=0; index<This->nb_attributes; index++)
2172 SysFreeString(This->attributes[index].szLocalname);
2173 SysFreeString(This->attributes[index].szValue);
2174 SysFreeString(This->attributes[index].szQName);
2176 heap_free(This->attributes);
2178 /* element stack */
2179 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2181 list_remove(&element->entry);
2182 free_element_entry(element);
2185 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2186 heap_free( This );
2189 return ref;
2192 /*** ISAXLocator methods ***/
2193 static HRESULT WINAPI isaxlocator_getColumnNumber(
2194 ISAXLocator* iface,
2195 int *pnColumn)
2197 saxlocator *This = impl_from_ISAXLocator( iface );
2199 *pnColumn = This->column;
2200 return S_OK;
2203 static HRESULT WINAPI isaxlocator_getLineNumber(
2204 ISAXLocator* iface,
2205 int *pnLine)
2207 saxlocator *This = impl_from_ISAXLocator( iface );
2209 *pnLine = This->line;
2210 return S_OK;
2213 static HRESULT WINAPI isaxlocator_getPublicId(
2214 ISAXLocator* iface,
2215 const WCHAR ** ppwchPublicId)
2217 BSTR publicId;
2218 saxlocator *This = impl_from_ISAXLocator( iface );
2220 SysFreeString(This->publicId);
2222 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2223 if(SysStringLen(publicId))
2224 This->publicId = publicId;
2225 else
2227 SysFreeString(publicId);
2228 This->publicId = NULL;
2231 *ppwchPublicId = This->publicId;
2232 return S_OK;
2235 static HRESULT WINAPI isaxlocator_getSystemId(
2236 ISAXLocator* iface,
2237 const WCHAR ** ppwchSystemId)
2239 BSTR systemId;
2240 saxlocator *This = impl_from_ISAXLocator( iface );
2242 SysFreeString(This->systemId);
2244 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2245 if(SysStringLen(systemId))
2246 This->systemId = systemId;
2247 else
2249 SysFreeString(systemId);
2250 This->systemId = NULL;
2253 *ppwchSystemId = This->systemId;
2254 return S_OK;
2257 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2259 isaxlocator_QueryInterface,
2260 isaxlocator_AddRef,
2261 isaxlocator_Release,
2262 isaxlocator_getColumnNumber,
2263 isaxlocator_getLineNumber,
2264 isaxlocator_getPublicId,
2265 isaxlocator_getSystemId
2268 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2270 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2271 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2273 saxlocator *locator;
2275 locator = heap_alloc( sizeof (*locator) );
2276 if( !locator )
2277 return E_OUTOFMEMORY;
2279 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2280 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2281 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2282 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2283 locator->ref = 1;
2284 locator->vbInterface = vbInterface;
2286 locator->saxreader = reader;
2287 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2289 locator->pParserCtxt = NULL;
2290 locator->publicId = NULL;
2291 locator->systemId = NULL;
2292 locator->line = reader->version < MSXML4 ? 0 : 1;
2293 locator->column = 0;
2294 locator->ret = S_OK;
2295 if (locator->saxreader->version >= MSXML6)
2296 locator->namespaceUri = SysAllocString(w3xmlns);
2297 else
2298 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2299 if(!locator->namespaceUri)
2301 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2302 heap_free(locator);
2303 return E_OUTOFMEMORY;
2306 locator->attributesSize = 8;
2307 locator->nb_attributes = 0;
2308 locator->attributes = heap_alloc(sizeof(struct _attributes)*locator->attributesSize);
2309 if(!locator->attributes)
2311 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2312 SysFreeString(locator->namespaceUri);
2313 heap_free(locator);
2314 return E_OUTOFMEMORY;
2317 list_init(&locator->elements);
2319 *ppsaxlocator = locator;
2321 TRACE("returning %p\n", *ppsaxlocator);
2323 return S_OK;
2326 /*** SAXXMLReader internal functions ***/
2327 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2329 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2330 xmlChar *enc_name = NULL;
2331 saxlocator *locator;
2332 HRESULT hr;
2334 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2336 hr = SAXLocator_create(This, &locator, vbInterface);
2337 if (FAILED(hr))
2338 return hr;
2340 if (size >= 4)
2342 const unsigned char *buff = (unsigned char*)buffer;
2344 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2345 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2346 TRACE("detected encoding: %s\n", enc_name);
2347 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2348 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2349 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2351 buffer += 3;
2352 size -= 3;
2356 /* if libxml2 detection failed try to guess */
2357 if (encoding == XML_CHAR_ENCODING_NONE)
2359 const WCHAR *ptr = (WCHAR*)buffer;
2360 /* xml declaration with possibly specfied encoding will be still handled by parser */
2361 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2363 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2364 encoding = XML_CHAR_ENCODING_UTF16LE;
2367 else if (encoding == XML_CHAR_ENCODING_UTF8)
2368 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2369 else
2370 enc_name = NULL;
2372 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2373 if (!locator->pParserCtxt)
2375 ISAXLocator_Release(&locator->ISAXLocator_iface);
2376 return E_FAIL;
2379 if (enc_name)
2381 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2382 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2383 TRACE("switching to %s\n", enc_name);
2384 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2388 xmlFree(locator->pParserCtxt->sax);
2389 locator->pParserCtxt->sax = &locator->saxreader->sax;
2390 locator->pParserCtxt->userData = locator;
2392 This->isParsing = TRUE;
2393 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2394 hr = E_FAIL;
2395 else
2396 hr = locator->ret;
2397 This->isParsing = FALSE;
2399 if(locator->pParserCtxt)
2401 locator->pParserCtxt->sax = NULL;
2402 xmlFreeParserCtxt(locator->pParserCtxt);
2403 locator->pParserCtxt = NULL;
2406 ISAXLocator_Release(&locator->ISAXLocator_iface);
2407 return hr;
2410 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2412 saxlocator *locator;
2413 HRESULT hr;
2414 ULONG dataRead;
2415 char data[1024];
2416 int ret;
2418 dataRead = 0;
2419 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2420 if(FAILED(hr)) return hr;
2422 hr = SAXLocator_create(This, &locator, vbInterface);
2423 if(FAILED(hr)) return hr;
2425 locator->pParserCtxt = xmlCreatePushParserCtxt(
2426 &locator->saxreader->sax, locator,
2427 data, dataRead, NULL);
2428 if(!locator->pParserCtxt)
2430 ISAXLocator_Release(&locator->ISAXLocator_iface);
2431 return E_FAIL;
2434 This->isParsing = TRUE;
2436 if(dataRead != sizeof(data))
2438 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2439 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2441 else
2443 while(1)
2445 dataRead = 0;
2446 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2447 if (FAILED(hr)) break;
2449 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2450 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2452 if (hr != S_OK) break;
2454 if (dataRead != sizeof(data))
2456 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2457 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2458 break;
2463 This->isParsing = FALSE;
2465 xmlFreeParserCtxt(locator->pParserCtxt);
2466 locator->pParserCtxt = NULL;
2467 ISAXLocator_Release(&locator->ISAXLocator_iface);
2468 return hr;
2471 static HRESULT internal_parse(
2472 saxreader* This,
2473 VARIANT varInput,
2474 BOOL vbInterface)
2476 HRESULT hr;
2478 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2480 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2481 free_bstr_pool(&This->pool);
2483 switch(V_VT(&varInput))
2485 case VT_BSTR:
2486 hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2487 strlenW(V_BSTR(&varInput))*sizeof(WCHAR), vbInterface);
2488 break;
2489 case VT_ARRAY|VT_UI1: {
2490 void *pSAData;
2491 LONG lBound, uBound;
2492 ULONG dataRead;
2494 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2495 if(hr != S_OK) break;
2496 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2497 if(hr != S_OK) break;
2498 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2499 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2500 if(hr != S_OK) break;
2501 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2502 SafeArrayUnaccessData(V_ARRAY(&varInput));
2503 break;
2505 case VT_UNKNOWN:
2506 case VT_DISPATCH: {
2507 IPersistStream *persistStream;
2508 ISequentialStream *stream = NULL;
2509 IXMLDOMDocument *xmlDoc;
2511 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2512 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2514 BSTR bstrData;
2516 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2517 hr = internal_parseBuffer(This, (const char*)bstrData,
2518 SysStringByteLen(bstrData), vbInterface);
2519 IXMLDOMDocument_Release(xmlDoc);
2520 SysFreeString(bstrData);
2521 break;
2524 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2525 &IID_IPersistStream, (void**)&persistStream) == S_OK)
2527 IStream *stream_copy;
2529 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy);
2530 if(hr != S_OK)
2532 IPersistStream_Release(persistStream);
2533 return hr;
2536 hr = IPersistStream_Save(persistStream, stream_copy, TRUE);
2537 IPersistStream_Release(persistStream);
2538 if(hr == S_OK)
2539 IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream);
2541 IStream_Release(stream_copy);
2544 /* try base interface first */
2545 if(!stream)
2547 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2548 if (!stream)
2549 /* this should never happen if IStream is implemented properly, but just in case */
2550 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2553 if(stream)
2555 hr = internal_parseStream(This, stream, vbInterface);
2556 ISequentialStream_Release(stream);
2558 else
2560 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2561 hr = E_INVALIDARG;
2564 break;
2566 default:
2567 WARN("vt %d not implemented\n", V_VT(&varInput));
2568 hr = E_INVALIDARG;
2571 return hr;
2574 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2576 saxreader *This = obj;
2578 return internal_parseBuffer(This, ptr, len, TRUE);
2581 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2583 saxreader *This = obj;
2585 return internal_parseBuffer(This, ptr, len, FALSE);
2588 static HRESULT internal_parseURL(
2589 saxreader* This,
2590 const WCHAR *url,
2591 BOOL vbInterface)
2593 IMoniker *mon;
2594 bsc_t *bsc;
2595 HRESULT hr;
2597 TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2599 hr = create_moniker_from_url(url, &mon);
2600 if(FAILED(hr))
2601 return hr;
2603 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, This, &bsc);
2604 else hr = bind_url(mon, internal_onDataAvailable, This, &bsc);
2605 IMoniker_Release(mon);
2607 if(FAILED(hr))
2608 return hr;
2610 return detach_bsc(bsc);
2613 static HRESULT internal_putProperty(
2614 saxreader* This,
2615 const WCHAR *prop,
2616 VARIANT value,
2617 BOOL vbInterface)
2619 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2621 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2623 if(This->isParsing) return E_FAIL;
2625 switch (V_VT(&value))
2627 case VT_EMPTY:
2628 saxreader_put_handler(This, SAXDeclHandler, NULL, vbInterface);
2629 break;
2630 case VT_UNKNOWN:
2632 IUnknown *handler = NULL;
2634 if (V_UNKNOWN(&value))
2636 HRESULT hr;
2638 if (vbInterface)
2639 hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXDeclHandler, (void**)&handler);
2640 else
2641 hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_ISAXDeclHandler, (void**)&handler);
2642 if (FAILED(hr)) return hr;
2645 saxreader_put_handler(This, SAXDeclHandler, handler, vbInterface);
2646 if (handler) IUnknown_Release(handler);
2647 break;
2649 default:
2650 return E_INVALIDARG;
2653 return S_OK;
2656 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2658 if(This->isParsing) return E_FAIL;
2660 switch (V_VT(&value))
2662 case VT_EMPTY:
2663 saxreader_put_handler(This, SAXLexicalHandler, NULL, vbInterface);
2664 break;
2665 case VT_UNKNOWN:
2667 IUnknown *handler = NULL;
2669 if (V_UNKNOWN(&value))
2671 HRESULT hr;
2673 if (vbInterface)
2674 hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXLexicalHandler, (void**)&handler);
2675 else
2676 hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_ISAXLexicalHandler, (void**)&handler);
2677 if (FAILED(hr)) return hr;
2680 saxreader_put_handler(This, SAXLexicalHandler, handler, vbInterface);
2681 if (handler) IUnknown_Release(handler);
2682 break;
2684 default:
2685 return E_INVALIDARG;
2688 return S_OK;
2691 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2693 if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
2694 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(&value));
2695 return E_NOTIMPL;
2698 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2700 if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
2701 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(&value));
2702 return E_NOTIMPL;
2705 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(&value));
2707 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2708 return E_NOTIMPL;
2710 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2711 return E_FAIL;
2713 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2714 return E_NOTIMPL;
2716 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2717 return E_NOTIMPL;
2719 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2720 return E_FAIL;
2722 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2723 return E_FAIL;
2725 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2726 return E_FAIL;
2728 return E_INVALIDARG;
2731 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2733 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2735 if (!value) return E_POINTER;
2737 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2739 V_VT(value) = VT_UNKNOWN;
2740 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2741 return S_OK;
2744 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2746 V_VT(value) = VT_UNKNOWN;
2747 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2748 return S_OK;
2751 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2753 V_VT(value) = VT_BSTR;
2754 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2755 return S_OK;
2758 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2760 return E_NOTIMPL;
2763 /*** IVBSAXXMLReader interface ***/
2764 /*** IUnknown methods ***/
2765 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2767 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2769 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2771 *ppvObject = NULL;
2773 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2774 IsEqualGUID( riid, &IID_IDispatch ) ||
2775 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2777 *ppvObject = iface;
2779 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2781 *ppvObject = &This->ISAXXMLReader_iface;
2783 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2785 return *ppvObject ? S_OK : E_NOINTERFACE;
2787 else
2789 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2790 return E_NOINTERFACE;
2793 IVBSAXXMLReader_AddRef( iface );
2795 return S_OK;
2798 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2800 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2801 TRACE("%p\n", This );
2802 return InterlockedIncrement( &This->ref );
2805 static ULONG WINAPI saxxmlreader_Release(
2806 IVBSAXXMLReader* iface)
2808 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2809 LONG ref;
2811 TRACE("%p\n", This );
2813 ref = InterlockedDecrement( &This->ref );
2814 if ( ref == 0 )
2816 int i;
2818 for (i = 0; i < SAXHandler_Last; i++)
2820 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2822 if (saxiface->handler)
2823 IUnknown_Release(saxiface->handler);
2825 if (saxiface->vbhandler)
2826 IUnknown_Release(saxiface->vbhandler);
2829 SysFreeString(This->xmldecl_version);
2830 free_bstr_pool(&This->pool);
2832 release_dispex(&This->dispex);
2833 heap_free( This );
2836 return ref;
2838 /*** IDispatch ***/
2839 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2841 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2842 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2845 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2846 IVBSAXXMLReader *iface,
2847 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2849 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2850 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2851 iTInfo, lcid, ppTInfo);
2854 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2855 IVBSAXXMLReader *iface,
2856 REFIID riid,
2857 LPOLESTR* rgszNames,
2858 UINT cNames,
2859 LCID lcid,
2860 DISPID* rgDispId)
2862 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2863 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2864 riid, rgszNames, cNames, lcid, rgDispId);
2867 static HRESULT WINAPI saxxmlreader_Invoke(
2868 IVBSAXXMLReader *iface,
2869 DISPID dispIdMember,
2870 REFIID riid,
2871 LCID lcid,
2872 WORD wFlags,
2873 DISPPARAMS* pDispParams,
2874 VARIANT* pVarResult,
2875 EXCEPINFO* pExcepInfo,
2876 UINT* puArgErr)
2878 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2879 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2880 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2883 /*** IVBSAXXMLReader methods ***/
2884 static HRESULT WINAPI saxxmlreader_getFeature(
2885 IVBSAXXMLReader* iface,
2886 const WCHAR *feature_name,
2887 VARIANT_BOOL *value)
2889 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2890 saxreader_feature feature;
2892 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
2894 feature = get_saxreader_feature(feature_name);
2895 if (feature == Namespaces || feature == NamespacePrefixes)
2896 return get_feature_value(This, feature, value);
2898 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
2899 return E_NOTIMPL;
2902 static HRESULT WINAPI saxxmlreader_putFeature(
2903 IVBSAXXMLReader* iface,
2904 const WCHAR *feature_name,
2905 VARIANT_BOOL value)
2907 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2908 saxreader_feature feature;
2910 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
2912 feature = get_saxreader_feature(feature_name);
2914 /* accepted cases */
2915 if ((feature == ExternalGeneralEntities && value == VARIANT_FALSE) ||
2916 (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
2917 feature == Namespaces ||
2918 feature == NamespacePrefixes)
2920 return set_feature_value(This, feature, value);
2923 if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
2925 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
2926 return set_feature_value(This, feature, value);
2929 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
2930 return E_NOTIMPL;
2933 static HRESULT WINAPI saxxmlreader_getProperty(
2934 IVBSAXXMLReader* iface,
2935 const WCHAR *prop,
2936 VARIANT *value)
2938 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2939 return internal_getProperty(This, prop, value, TRUE);
2942 static HRESULT WINAPI saxxmlreader_putProperty(
2943 IVBSAXXMLReader* iface,
2944 const WCHAR *pProp,
2945 VARIANT value)
2947 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2948 return internal_putProperty(This, pProp, value, TRUE);
2951 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2952 IVBSAXXMLReader* iface,
2953 IVBSAXEntityResolver **resolver)
2955 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2956 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
2959 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2960 IVBSAXXMLReader* iface,
2961 IVBSAXEntityResolver *resolver)
2963 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2964 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
2967 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2968 IVBSAXXMLReader* iface,
2969 IVBSAXContentHandler **handler)
2971 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2972 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
2975 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2976 IVBSAXXMLReader* iface,
2977 IVBSAXContentHandler *handler)
2979 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2980 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
2983 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2984 IVBSAXXMLReader* iface,
2985 IVBSAXDTDHandler **handler)
2987 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2988 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
2991 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2992 IVBSAXXMLReader* iface,
2993 IVBSAXDTDHandler *handler)
2995 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2996 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
2999 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3000 IVBSAXXMLReader* iface,
3001 IVBSAXErrorHandler **handler)
3003 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3004 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3007 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3008 IVBSAXXMLReader* iface,
3009 IVBSAXErrorHandler *handler)
3011 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3012 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3015 static HRESULT WINAPI saxxmlreader_get_baseURL(
3016 IVBSAXXMLReader* iface,
3017 const WCHAR **pBaseUrl)
3019 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3021 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3022 return E_NOTIMPL;
3025 static HRESULT WINAPI saxxmlreader_put_baseURL(
3026 IVBSAXXMLReader* iface,
3027 const WCHAR *pBaseUrl)
3029 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3031 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3032 return E_NOTIMPL;
3035 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3036 IVBSAXXMLReader* iface,
3037 const WCHAR **pSecureBaseUrl)
3039 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3041 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3042 return E_NOTIMPL;
3046 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3047 IVBSAXXMLReader* iface,
3048 const WCHAR *secureBaseUrl)
3050 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3052 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3053 return E_NOTIMPL;
3056 static HRESULT WINAPI saxxmlreader_parse(
3057 IVBSAXXMLReader* iface,
3058 VARIANT varInput)
3060 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3061 return internal_parse(This, varInput, TRUE);
3064 static HRESULT WINAPI saxxmlreader_parseURL(
3065 IVBSAXXMLReader* iface,
3066 const WCHAR *url)
3068 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3069 return internal_parseURL(This, url, TRUE);
3072 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3074 saxxmlreader_QueryInterface,
3075 saxxmlreader_AddRef,
3076 saxxmlreader_Release,
3077 saxxmlreader_GetTypeInfoCount,
3078 saxxmlreader_GetTypeInfo,
3079 saxxmlreader_GetIDsOfNames,
3080 saxxmlreader_Invoke,
3081 saxxmlreader_getFeature,
3082 saxxmlreader_putFeature,
3083 saxxmlreader_getProperty,
3084 saxxmlreader_putProperty,
3085 saxxmlreader_get_entityResolver,
3086 saxxmlreader_put_entityResolver,
3087 saxxmlreader_get_contentHandler,
3088 saxxmlreader_put_contentHandler,
3089 saxxmlreader_get_dtdHandler,
3090 saxxmlreader_put_dtdHandler,
3091 saxxmlreader_get_errorHandler,
3092 saxxmlreader_put_errorHandler,
3093 saxxmlreader_get_baseURL,
3094 saxxmlreader_put_baseURL,
3095 saxxmlreader_get_secureBaseURL,
3096 saxxmlreader_put_secureBaseURL,
3097 saxxmlreader_parse,
3098 saxxmlreader_parseURL
3101 /*** ISAXXMLReader interface ***/
3102 /*** IUnknown methods ***/
3103 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3105 saxreader *This = impl_from_ISAXXMLReader( iface );
3106 return saxxmlreader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3109 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3111 saxreader *This = impl_from_ISAXXMLReader( iface );
3112 return saxxmlreader_AddRef(&This->IVBSAXXMLReader_iface);
3115 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3117 saxreader *This = impl_from_ISAXXMLReader( iface );
3118 return saxxmlreader_Release(&This->IVBSAXXMLReader_iface);
3121 /*** ISAXXMLReader methods ***/
3122 static HRESULT WINAPI isaxxmlreader_getFeature(
3123 ISAXXMLReader* iface,
3124 const WCHAR *pFeature,
3125 VARIANT_BOOL *pValue)
3127 saxreader *This = impl_from_ISAXXMLReader( iface );
3128 return IVBSAXXMLReader_getFeature(&This->IVBSAXXMLReader_iface, pFeature, pValue);
3131 static HRESULT WINAPI isaxxmlreader_putFeature(
3132 ISAXXMLReader* iface,
3133 const WCHAR *pFeature,
3134 VARIANT_BOOL vfValue)
3136 saxreader *This = impl_from_ISAXXMLReader( iface );
3137 return IVBSAXXMLReader_putFeature(&This->IVBSAXXMLReader_iface, pFeature, vfValue);
3140 static HRESULT WINAPI isaxxmlreader_getProperty(
3141 ISAXXMLReader* iface,
3142 const WCHAR *prop,
3143 VARIANT *value)
3145 saxreader *This = impl_from_ISAXXMLReader( iface );
3146 return internal_getProperty(This, prop, value, FALSE);
3149 static HRESULT WINAPI isaxxmlreader_putProperty(
3150 ISAXXMLReader* iface,
3151 const WCHAR *pProp,
3152 VARIANT value)
3154 saxreader *This = impl_from_ISAXXMLReader( iface );
3155 return internal_putProperty(This, pProp, value, FALSE);
3158 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3159 ISAXXMLReader* iface,
3160 ISAXEntityResolver **resolver)
3162 saxreader *This = impl_from_ISAXXMLReader( iface );
3163 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3166 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3167 ISAXXMLReader* iface,
3168 ISAXEntityResolver *resolver)
3170 saxreader *This = impl_from_ISAXXMLReader( iface );
3171 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3174 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3175 ISAXXMLReader* iface,
3176 ISAXContentHandler **handler)
3178 saxreader *This = impl_from_ISAXXMLReader( iface );
3179 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3182 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3183 ISAXXMLReader* iface,
3184 ISAXContentHandler *handler)
3186 saxreader *This = impl_from_ISAXXMLReader( iface );
3187 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3190 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3191 ISAXXMLReader* iface,
3192 ISAXDTDHandler **handler)
3194 saxreader *This = impl_from_ISAXXMLReader( iface );
3195 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3198 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3199 ISAXXMLReader* iface,
3200 ISAXDTDHandler *handler)
3202 saxreader *This = impl_from_ISAXXMLReader( iface );
3203 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3206 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3207 ISAXXMLReader* iface,
3208 ISAXErrorHandler **handler)
3210 saxreader *This = impl_from_ISAXXMLReader( iface );
3211 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3214 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3216 saxreader *This = impl_from_ISAXXMLReader( iface );
3217 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3220 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3221 ISAXXMLReader* iface,
3222 const WCHAR **pBaseUrl)
3224 saxreader *This = impl_from_ISAXXMLReader( iface );
3225 return IVBSAXXMLReader_get_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
3228 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3229 ISAXXMLReader* iface,
3230 const WCHAR *pBaseUrl)
3232 saxreader *This = impl_from_ISAXXMLReader( iface );
3233 return IVBSAXXMLReader_put_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
3236 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3237 ISAXXMLReader* iface,
3238 const WCHAR **pSecureBaseUrl)
3240 saxreader *This = impl_from_ISAXXMLReader( iface );
3241 return IVBSAXXMLReader_get_secureBaseURL(&This->IVBSAXXMLReader_iface, pSecureBaseUrl);
3244 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3245 ISAXXMLReader* iface,
3246 const WCHAR *secureBaseUrl)
3248 saxreader *This = impl_from_ISAXXMLReader( iface );
3249 return IVBSAXXMLReader_put_secureBaseURL(&This->IVBSAXXMLReader_iface, secureBaseUrl);
3252 static HRESULT WINAPI isaxxmlreader_parse(
3253 ISAXXMLReader* iface,
3254 VARIANT varInput)
3256 saxreader *This = impl_from_ISAXXMLReader( iface );
3257 return internal_parse(This, varInput, FALSE);
3260 static HRESULT WINAPI isaxxmlreader_parseURL(
3261 ISAXXMLReader* iface,
3262 const WCHAR *url)
3264 saxreader *This = impl_from_ISAXXMLReader( iface );
3265 return internal_parseURL(This, url, FALSE);
3268 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3270 isaxxmlreader_QueryInterface,
3271 isaxxmlreader_AddRef,
3272 isaxxmlreader_Release,
3273 isaxxmlreader_getFeature,
3274 isaxxmlreader_putFeature,
3275 isaxxmlreader_getProperty,
3276 isaxxmlreader_putProperty,
3277 isaxxmlreader_getEntityResolver,
3278 isaxxmlreader_putEntityResolver,
3279 isaxxmlreader_getContentHandler,
3280 isaxxmlreader_putContentHandler,
3281 isaxxmlreader_getDTDHandler,
3282 isaxxmlreader_putDTDHandler,
3283 isaxxmlreader_getErrorHandler,
3284 isaxxmlreader_putErrorHandler,
3285 isaxxmlreader_getBaseURL,
3286 isaxxmlreader_putBaseURL,
3287 isaxxmlreader_getSecureBaseURL,
3288 isaxxmlreader_putSecureBaseURL,
3289 isaxxmlreader_parse,
3290 isaxxmlreader_parseURL
3293 static const tid_t saxreader_iface_tids[] = {
3294 IVBSAXXMLReader_tid,
3297 static dispex_static_data_t saxreader_dispex = {
3298 NULL,
3299 IVBSAXXMLReader_tid,
3300 NULL,
3301 saxreader_iface_tids
3304 HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppObj)
3306 saxreader *reader;
3308 TRACE("(%p, %p)\n", outer, ppObj);
3310 reader = heap_alloc( sizeof (*reader) );
3311 if( !reader )
3312 return E_OUTOFMEMORY;
3314 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3315 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3316 reader->ref = 1;
3317 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3318 reader->isParsing = FALSE;
3319 reader->xmldecl_version = NULL;
3320 reader->pool.pool = NULL;
3321 reader->pool.index = 0;
3322 reader->pool.len = 0;
3323 reader->features = Namespaces | NamespacePrefixes;
3324 reader->version = version;
3326 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3328 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3329 reader->sax.initialized = XML_SAX2_MAGIC;
3330 reader->sax.startDocument = libxmlStartDocument;
3331 reader->sax.endDocument = libxmlEndDocument;
3332 reader->sax.startElementNs = libxmlStartElementNS;
3333 reader->sax.endElementNs = libxmlEndElementNS;
3334 reader->sax.characters = libxmlCharacters;
3335 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3336 reader->sax.comment = libxmlComment;
3337 reader->sax.error = libxmlFatalError;
3338 reader->sax.fatalError = libxmlFatalError;
3339 reader->sax.cdataBlock = libxml_cdatablock;
3340 reader->sax.resolveEntity = libxmlresolveentity;
3342 *ppObj = &reader->IVBSAXXMLReader_iface;
3344 TRACE("returning iface %p\n", *ppObj);
3346 return S_OK;
3349 #else
3351 HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *pUnkOuter, LPVOID *ppObj)
3353 MESSAGE("This program tried to use a SAX XML Reader object, but\n"
3354 "libxml2 support was not present at compile time.\n");
3355 return E_NOTIMPL;
3358 #endif