imm32/tests: Test ImmTranslateMessage / ImeToAsciiEx calls.
[wine.git] / dlls / msxml3 / saxreader.c
blob0e886a2d05189eb66b25e62d192b593f5d863e8c
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 <stdarg.h>
24 #include <libxml/parser.h>
25 #include <libxml/xmlerror.h>
26 #include <libxml/SAX2.h>
27 #include <libxml/parserInternals.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winnls.h"
33 #include "ole2.h"
34 #include "msxml6.h"
35 #include "wininet.h"
36 #include "urlmon.h"
37 #include "winreg.h"
38 #include "shlwapi.h"
40 #include "wine/debug.h"
42 #include "msxml_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
46 typedef enum
48 FeatureUnknown = 0,
49 ExhaustiveErrors = 1 << 1,
50 ExternalGeneralEntities = 1 << 2,
51 ExternalParameterEntities = 1 << 3,
52 ForcedResync = 1 << 4,
53 NamespacePrefixes = 1 << 5,
54 Namespaces = 1 << 6,
55 ParameterEntities = 1 << 7,
56 PreserveSystemIndentifiers = 1 << 8,
57 ProhibitDTD = 1 << 9,
58 SchemaValidation = 1 << 10,
59 ServerHttpRequest = 1 << 11,
60 SuppressValidationfatalError = 1 << 12,
61 UseInlineSchema = 1 << 13,
62 UseSchemaLocation = 1 << 14,
63 LexicalHandlerParEntities = 1 << 15
64 } saxreader_feature;
66 /* feature names */
67 static const WCHAR FeatureExternalGeneralEntitiesW[] = {
68 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/',
69 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l',
70 '-','e','n','t','i','t','i','e','s',0
73 static const WCHAR FeatureExternalParameterEntitiesW[] = {
74 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
75 '/','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
78 static const WCHAR FeatureLexicalHandlerParEntitiesW[] = {
79 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
80 '/','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
83 static const WCHAR FeatureProhibitDTDW[] = {
84 'p','r','o','h','i','b','i','t','-','d','t','d',0
87 static const WCHAR FeatureNamespacesW[] = {
88 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
89 '/','n','a','m','e','s','p','a','c','e','s',0
92 static const WCHAR FeatureNamespacePrefixesW[] = {
93 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s',
94 '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
97 static const WCHAR ExhaustiveErrorsW[] = {
98 'e','x','h','a','u','s','t','i','v','e','-','e','r','r','o','r','s',0
101 static const WCHAR SchemaValidationW[] = {
102 's','c','h','e','m','a','-','v','a','l','i','d','a','t','i','o','n',0
105 struct saxreader_feature_pair
107 saxreader_feature feature;
108 const WCHAR *name;
111 static const struct saxreader_feature_pair saxreader_feature_map[] = {
112 { ExhaustiveErrors, ExhaustiveErrorsW },
113 { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
114 { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
115 { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
116 { NamespacePrefixes, FeatureNamespacePrefixesW },
117 { Namespaces, FeatureNamespacesW },
118 { ProhibitDTD, FeatureProhibitDTDW },
119 { SchemaValidation, SchemaValidationW },
122 static saxreader_feature get_saxreader_feature(const WCHAR *name)
124 int min, max, n, c;
126 min = 0;
127 max = ARRAY_SIZE(saxreader_feature_map) - 1;
129 while (min <= max)
131 n = (min+max)/2;
133 c = wcscmp(saxreader_feature_map[n].name, name);
134 if (!c)
135 return saxreader_feature_map[n].feature;
137 if (c > 0)
138 max = n-1;
139 else
140 min = n+1;
143 return FeatureUnknown;
146 static const WCHAR empty_str;
148 struct bstrpool
150 BSTR *pool;
151 unsigned int index;
152 unsigned int len;
155 typedef struct
157 BSTR prefix;
158 BSTR uri;
159 } ns;
161 typedef struct
163 struct list entry;
164 BSTR prefix;
165 BSTR local;
166 BSTR qname;
167 ns *ns; /* namespaces defined in this particular element */
168 int ns_count;
169 } element_entry;
171 enum saxhandler_type
173 SAXContentHandler = 0,
174 SAXDeclHandler,
175 SAXDTDHandler,
176 SAXEntityResolver,
177 SAXErrorHandler,
178 SAXLexicalHandler,
179 SAXHandler_Last
182 struct saxanyhandler_iface
184 IUnknown *handler;
185 IUnknown *vbhandler;
188 struct saxcontenthandler_iface
190 ISAXContentHandler *handler;
191 IVBSAXContentHandler *vbhandler;
194 struct saxerrorhandler_iface
196 ISAXErrorHandler *handler;
197 IVBSAXErrorHandler *vbhandler;
200 struct saxlexicalhandler_iface
202 ISAXLexicalHandler *handler;
203 IVBSAXLexicalHandler *vbhandler;
206 struct saxentityresolver_iface
208 ISAXEntityResolver *handler;
209 IVBSAXEntityResolver *vbhandler;
212 struct saxhandler_iface
214 union {
215 struct saxcontenthandler_iface content;
216 struct saxentityresolver_iface entityresolver;
217 struct saxerrorhandler_iface error;
218 struct saxlexicalhandler_iface lexical;
219 struct saxanyhandler_iface anyhandler;
220 } u;
223 typedef struct
225 DispatchEx dispex;
226 IVBSAXXMLReader IVBSAXXMLReader_iface;
227 ISAXXMLReader ISAXXMLReader_iface;
228 LONG ref;
230 struct saxhandler_iface saxhandlers[SAXHandler_Last];
231 xmlSAXHandler sax;
232 BOOL isParsing;
233 struct bstrpool pool;
234 saxreader_feature features;
235 BSTR xmldecl_version;
236 MSXML_VERSION version;
237 } saxreader;
239 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
241 struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
242 IUnknown *unk = (IUnknown*)ptr;
244 if (unk)
245 IUnknown_AddRef(unk);
247 if ((vb && iface->vbhandler) || (!vb && iface->handler))
248 IUnknown_Release(vb ? iface->vbhandler : iface->handler);
250 if (vb)
251 iface->vbhandler = unk;
252 else
253 iface->handler = unk;
255 return S_OK;
258 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
260 const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
262 if (!ret) return E_POINTER;
264 if ((vb && iface->vbhandler) || (!vb && iface->handler))
266 if (vb)
267 IUnknown_AddRef(iface->vbhandler);
268 else
269 IUnknown_AddRef(iface->handler);
272 *ret = vb ? iface->vbhandler : iface->handler;
274 return S_OK;
277 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
279 return &reader->saxhandlers[SAXContentHandler].u.content;
282 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
284 return &reader->saxhandlers[SAXErrorHandler].u.error;
287 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
289 return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
292 typedef struct
294 IVBSAXLocator IVBSAXLocator_iface;
295 ISAXLocator ISAXLocator_iface;
296 IVBSAXAttributes IVBSAXAttributes_iface;
297 ISAXAttributes ISAXAttributes_iface;
298 LONG ref;
299 saxreader *saxreader;
300 HRESULT ret;
301 xmlParserCtxtPtr pParserCtxt;
302 BSTR publicId;
303 BSTR systemId;
304 int line;
305 int column;
306 BOOL vbInterface;
307 struct list elements;
309 BSTR namespaceUri;
310 int attr_alloc_count;
311 int attr_count;
312 struct _attributes
314 BSTR szLocalname;
315 BSTR szURI;
316 BSTR szValue;
317 BSTR szQName;
318 } *attributes;
319 } saxlocator;
321 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
323 return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface);
326 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
328 return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface);
331 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
333 return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface);
336 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
338 return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface);
341 static inline saxlocator *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
343 return CONTAINING_RECORD(iface, saxlocator, IVBSAXAttributes_iface);
346 static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
348 return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
351 static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
353 struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
354 return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
357 static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
359 struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
360 HRESULT hr;
362 if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
364 if (locator->vbInterface)
365 hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
366 else
367 hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
369 return hr;
372 /* property names */
373 static const WCHAR PropertyCharsetW[] = {
374 'c','h','a','r','s','e','t',0
376 static const WCHAR PropertyXmlDeclVersionW[] = {
377 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
379 static const WCHAR PropertyDeclHandlerW[] = {
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','e','c','l','a','r','a','t','i','o','n',
383 '-','h','a','n','d','l','e','r',0
385 static const WCHAR PropertyDomNodeW[] = {
386 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
387 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
388 'd','o','m','-','n','o','d','e',0
390 static const WCHAR PropertyInputSourceW[] = {
391 'i','n','p','u','t','-','s','o','u','r','c','e',0
393 static const WCHAR PropertyLexicalHandlerW[] = {
394 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
395 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
396 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
398 static const WCHAR PropertyMaxElementDepthW[] = {
399 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
401 static const WCHAR PropertyMaxXMLSizeW[] = {
402 'm','a','x','-','x','m','l','-','s','i','z','e',0
404 static const WCHAR PropertySchemaDeclHandlerW[] = {
405 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-',
406 'h','a','n','d','l','e','r',0
408 static const WCHAR PropertyXMLDeclEncodingW[] = {
409 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
411 static const WCHAR PropertyXMLDeclStandaloneW[] = {
412 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0
414 static const WCHAR PropertyXMLDeclVersionW[] = {
415 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
418 static inline HRESULT set_feature_value(saxreader *reader, saxreader_feature feature, VARIANT_BOOL value)
420 /* handling of non-VARIANT_* values is version dependent */
421 if ((reader->version < MSXML4) && (value != VARIANT_TRUE))
422 value = VARIANT_FALSE;
423 if ((reader->version >= MSXML4) && (value != VARIANT_FALSE))
424 value = VARIANT_TRUE;
426 if (value == VARIANT_TRUE)
427 reader->features |= feature;
428 else
429 reader->features &= ~feature;
431 return S_OK;
434 static inline HRESULT get_feature_value(const saxreader *reader, saxreader_feature feature, VARIANT_BOOL *value)
436 *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE;
437 return S_OK;
440 static BOOL is_namespaces_enabled(const saxreader *reader)
442 return (reader->version < MSXML4) || (reader->features & Namespaces);
445 static BSTR build_qname(BSTR prefix, BSTR local)
447 if (prefix && *prefix)
449 BSTR qname = SysAllocStringLen(NULL, SysStringLen(prefix) + SysStringLen(local) + 1);
450 WCHAR *ptr;
452 ptr = qname;
453 lstrcpyW(ptr, prefix);
454 ptr += SysStringLen(prefix);
455 *ptr++ = ':';
456 lstrcpyW(ptr, local);
457 return qname;
459 else
460 return SysAllocString(local);
463 static element_entry* alloc_element_entry(const xmlChar *local, const xmlChar *prefix, int nb_ns,
464 const xmlChar **namespaces)
466 element_entry *ret;
467 int i;
469 ret = malloc(sizeof(*ret));
470 if (!ret) return ret;
472 ret->local = bstr_from_xmlChar(local);
473 ret->prefix = bstr_from_xmlChar(prefix);
474 ret->qname = build_qname(ret->prefix, ret->local);
475 ret->ns = nb_ns ? malloc(nb_ns * sizeof(ns)) : NULL;
476 ret->ns_count = nb_ns;
478 for (i=0; i < nb_ns; i++)
480 ret->ns[i].prefix = bstr_from_xmlChar(namespaces[2*i]);
481 ret->ns[i].uri = bstr_from_xmlChar(namespaces[2*i+1]);
484 return ret;
487 static void free_element_entry(element_entry *element)
489 int i;
491 for (i=0; i<element->ns_count;i++)
493 SysFreeString(element->ns[i].prefix);
494 SysFreeString(element->ns[i].uri);
497 SysFreeString(element->prefix);
498 SysFreeString(element->local);
499 SysFreeString(element->qname);
501 free(element->ns);
502 free(element);
505 static void push_element_ns(saxlocator *locator, element_entry *element)
507 list_add_head(&locator->elements, &element->entry);
510 static element_entry * pop_element_ns(saxlocator *locator)
512 element_entry *element = LIST_ENTRY(list_head(&locator->elements), element_entry, entry);
514 if (element)
515 list_remove(&element->entry);
517 return element;
520 static BSTR find_element_uri(saxlocator *locator, const xmlChar *uri)
522 element_entry *element;
523 BSTR uriW;
524 int i;
526 if (!uri) return NULL;
528 uriW = bstr_from_xmlChar(uri);
530 LIST_FOR_EACH_ENTRY(element, &locator->elements, element_entry, entry)
532 for (i=0; i < element->ns_count; i++)
533 if (!wcscmp(uriW, element->ns[i].uri))
535 SysFreeString(uriW);
536 return element->ns[i].uri;
540 SysFreeString(uriW);
541 ERR("namespace uri not found, %s\n", debugstr_a((char*)uri));
542 return NULL;
545 /* used to localize version dependent error check behaviour */
546 static inline BOOL sax_callback_failed(saxlocator *This, HRESULT hr)
548 return This->saxreader->version >= MSXML4 ? FAILED(hr) : hr != S_OK;
551 /* index value -1 means it tries to loop for a first time */
552 static inline BOOL iterate_endprefix_index(saxlocator *This, const element_entry *element, int *i)
554 if (This->saxreader->version >= MSXML4)
556 if (*i == -1) *i = 0; else ++*i;
557 return *i < element->ns_count;
559 else
561 if (*i == -1) *i = element->ns_count-1; else --*i;
562 return *i >= 0;
566 static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
568 if (!pool->pool)
570 pool->pool = malloc(16 * sizeof(*pool->pool));
571 if (!pool->pool)
572 return FALSE;
574 pool->index = 0;
575 pool->len = 16;
577 else if (pool->index == pool->len)
579 BSTR *new_pool = realloc(pool->pool, pool->len * 2 * sizeof(*new_pool));
581 if (!new_pool)
582 return FALSE;
584 pool->pool = new_pool;
585 pool->len *= 2;
588 pool->pool[pool->index++] = pool_entry;
589 return TRUE;
592 static void free_bstr_pool(struct bstrpool *pool)
594 unsigned int i;
596 for (i = 0; i < pool->index; i++)
597 SysFreeString(pool->pool[i]);
599 free(pool->pool);
601 pool->pool = NULL;
602 pool->index = pool->len = 0;
605 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
607 DWORD dLen;
608 BSTR bstr;
610 if (!buf)
611 return NULL;
613 dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
614 if(len != -1) dLen++;
615 bstr = SysAllocStringLen(NULL, dLen-1);
616 if (!bstr)
617 return NULL;
618 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen);
619 if(len != -1) bstr[dLen-1] = '\0';
621 return bstr;
624 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
626 xmlChar *qname;
627 BSTR bstr;
629 if(!name) return NULL;
631 if(!prefix || !*prefix)
632 return bstr_from_xmlChar(name);
634 qname = xmlBuildQName(name, prefix, NULL, 0);
635 bstr = bstr_from_xmlChar(qname);
636 xmlFree(qname);
638 return bstr;
641 static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
643 BSTR pool_entry = bstr_from_xmlChar(buf);
645 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
647 SysFreeString(pool_entry);
648 return NULL;
651 return pool_entry;
654 static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
656 BSTR pool_entry = bstr_from_xmlCharN(buf, len);
658 if (pool_entry && !bstr_pool_insert(pool, pool_entry))
660 SysFreeString(pool_entry);
661 return NULL;
664 return pool_entry;
667 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
669 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
670 xmlStopParser(This->pParserCtxt);
671 This->ret = hr;
673 if (saxreader_has_handler(This, SAXErrorHandler))
675 WCHAR msg[1024];
676 if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
677 NULL, hr, 0, msg, ARRAY_SIZE(msg), NULL))
679 FIXME("MSXML errors not yet supported.\n");
680 msg[0] = '\0';
683 if(This->vbInterface)
685 BSTR bstrMsg = SysAllocString(msg);
686 IVBSAXErrorHandler_fatalError(handler->vbhandler,
687 &This->IVBSAXLocator_iface, &bstrMsg, hr);
688 SysFreeString(bstrMsg);
690 else
691 ISAXErrorHandler_fatalError(handler->handler,
692 &This->ISAXLocator_iface, msg, hr);
696 static void update_position(saxlocator *This, BOOL fix_column)
698 const xmlChar *p = This->pParserCtxt->input->cur-1;
699 const xmlChar *baseP = This->pParserCtxt->input->base;
701 This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
702 if(fix_column)
704 This->column = 1;
705 for(;p>=baseP && *p!='\n' && *p!='\r'; p--)
706 This->column++;
708 else
710 This->column = xmlSAX2GetColumnNumber(This->pParserCtxt);
714 /*** IVBSAXAttributes interface ***/
715 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
716 IVBSAXAttributes* iface,
717 REFIID riid,
718 void **ppvObject)
720 saxlocator *This = impl_from_IVBSAXAttributes(iface);
721 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
722 return IVBSAXLocator_QueryInterface(&This->IVBSAXLocator_iface, riid, ppvObject);
725 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
727 saxlocator *This = impl_from_IVBSAXAttributes(iface);
728 return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
731 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
733 saxlocator *This = impl_from_IVBSAXAttributes(iface);
734 return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
737 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
739 saxlocator *This = impl_from_IVBSAXAttributes( iface );
741 TRACE("(%p)->(%p)\n", This, pctinfo);
743 *pctinfo = 1;
745 return S_OK;
748 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
749 IVBSAXAttributes *iface,
750 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
752 TRACE("%p, %u, %lx, %p.\n", iface, iTInfo, lcid, ppTInfo);
754 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
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 ITypeInfo *typeinfo;
766 HRESULT hr;
768 TRACE("%p, %s, %p, %u, %lx %p.\n", iface, debugstr_guid(riid), rgszNames, cNames,
769 lcid, rgDispId);
771 if(!rgszNames || cNames == 0 || !rgDispId)
772 return E_INVALIDARG;
774 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
775 if(SUCCEEDED(hr))
777 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
778 ITypeInfo_Release(typeinfo);
781 return hr;
784 static HRESULT WINAPI ivbsaxattributes_Invoke(
785 IVBSAXAttributes *iface,
786 DISPID dispIdMember,
787 REFIID riid,
788 LCID lcid,
789 WORD wFlags,
790 DISPPARAMS* pDispParams,
791 VARIANT* pVarResult,
792 EXCEPINFO* pExcepInfo,
793 UINT* puArgErr)
795 ITypeInfo *typeinfo;
796 HRESULT hr;
798 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface, dispIdMember, debugstr_guid(riid),
799 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
801 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
802 if(SUCCEEDED(hr))
804 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
805 ITypeInfo_Release(typeinfo);
808 return hr;
811 /*** IVBSAXAttributes methods ***/
812 static HRESULT WINAPI ivbsaxattributes_get_length(
813 IVBSAXAttributes* iface,
814 int *nLength)
816 saxlocator *This = impl_from_IVBSAXAttributes( iface );
817 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength);
820 static HRESULT WINAPI ivbsaxattributes_getURI(
821 IVBSAXAttributes* iface,
822 int nIndex,
823 BSTR *uri)
825 saxlocator *This = impl_from_IVBSAXAttributes( iface );
826 const WCHAR *uriW;
827 HRESULT hr;
828 int len;
830 TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
832 if (!uri)
833 return E_POINTER;
835 *uri = NULL;
836 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
837 if (FAILED(hr))
838 return hr;
840 return return_bstrn(uriW, len, uri);
843 static HRESULT WINAPI ivbsaxattributes_getLocalName(
844 IVBSAXAttributes* iface,
845 int nIndex,
846 BSTR *name)
848 saxlocator *This = impl_from_IVBSAXAttributes( iface );
849 const WCHAR *nameW;
850 HRESULT hr;
851 int len;
853 TRACE("(%p)->(%d %p)\n", This, nIndex, name);
855 if (!name)
856 return E_POINTER;
858 *name = NULL;
859 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
860 if (FAILED(hr))
861 return hr;
863 return return_bstrn(nameW, len, name);
866 static HRESULT WINAPI ivbsaxattributes_getQName(
867 IVBSAXAttributes* iface,
868 int nIndex,
869 BSTR *QName)
871 saxlocator *This = impl_from_IVBSAXAttributes( iface );
872 const WCHAR *nameW;
873 HRESULT hr;
874 int len;
876 TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
878 if (!QName)
879 return E_POINTER;
881 *QName = NULL;
882 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
883 if (FAILED(hr))
884 return hr;
886 return return_bstrn(nameW, len, QName);
889 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
890 IVBSAXAttributes* iface,
891 BSTR uri,
892 BSTR localName,
893 int *index)
895 saxlocator *This = impl_from_IVBSAXAttributes( iface );
896 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
897 localName, SysStringLen(localName), index);
900 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
901 IVBSAXAttributes* iface,
902 BSTR QName,
903 int *index)
905 saxlocator *This = impl_from_IVBSAXAttributes( iface );
906 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName,
907 SysStringLen(QName), index);
910 static HRESULT WINAPI ivbsaxattributes_getType(
911 IVBSAXAttributes* iface,
912 int nIndex,
913 BSTR *type)
915 saxlocator *This = impl_from_IVBSAXAttributes( iface );
916 const WCHAR *typeW;
917 HRESULT hr;
918 int len;
920 TRACE("(%p)->(%d %p)\n", This, nIndex, type);
922 if (!type)
923 return E_POINTER;
925 *type = NULL;
926 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
927 if (FAILED(hr))
928 return hr;
930 return return_bstrn(typeW, len, type);
933 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
934 IVBSAXAttributes* iface,
935 BSTR uri,
936 BSTR localName,
937 BSTR *type)
939 saxlocator *This = impl_from_IVBSAXAttributes( iface );
940 const WCHAR *typeW;
941 HRESULT hr;
942 int len;
944 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
946 if (!type)
947 return E_POINTER;
949 *type = NULL;
950 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
951 localName, SysStringLen(localName), &typeW, &len);
952 if (FAILED(hr))
953 return hr;
955 return return_bstrn(typeW, len, type);
958 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
959 IVBSAXAttributes* iface,
960 BSTR QName,
961 BSTR *type)
963 saxlocator *This = impl_from_IVBSAXAttributes( iface );
964 const WCHAR *typeW;
965 HRESULT hr;
966 int len;
968 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), type);
970 if (!type)
971 return E_POINTER;
973 *type = NULL;
974 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
975 &typeW, &len);
976 if (FAILED(hr))
977 return hr;
979 return return_bstrn(typeW, len, type);
982 static HRESULT WINAPI ivbsaxattributes_getValue(
983 IVBSAXAttributes* iface,
984 int nIndex,
985 BSTR *value)
987 saxlocator *This = impl_from_IVBSAXAttributes( iface );
988 const WCHAR *valueW;
989 HRESULT hr;
990 int len;
992 TRACE("(%p)->(%d %p)\n", This, nIndex, value);
994 if (!value)
995 return E_POINTER;
997 *value = NULL;
998 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
999 if (FAILED(hr))
1000 return hr;
1002 return return_bstrn(valueW, len, value);
1005 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
1006 IVBSAXAttributes* iface,
1007 BSTR uri,
1008 BSTR localName,
1009 BSTR *value)
1011 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1012 const WCHAR *valueW;
1013 HRESULT hr;
1014 int len;
1016 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
1018 if (!value)
1019 return E_POINTER;
1021 *value = NULL;
1022 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
1023 localName, SysStringLen(localName), &valueW, &len);
1024 if (FAILED(hr))
1025 return hr;
1027 return return_bstrn(valueW, len, value);
1030 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
1031 IVBSAXAttributes* iface,
1032 BSTR QName,
1033 BSTR *value)
1035 saxlocator *This = impl_from_IVBSAXAttributes( iface );
1036 const WCHAR *valueW;
1037 HRESULT hr;
1038 int len;
1040 TRACE("(%p)->(%s %p)\n", This, debugstr_w(QName), value);
1042 if (!value)
1043 return E_POINTER;
1045 *value = NULL;
1046 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
1047 SysStringLen(QName), &valueW, &len);
1048 if (FAILED(hr))
1049 return hr;
1051 return return_bstrn(valueW, len, value);
1054 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
1056 ivbsaxattributes_QueryInterface,
1057 ivbsaxattributes_AddRef,
1058 ivbsaxattributes_Release,
1059 ivbsaxattributes_GetTypeInfoCount,
1060 ivbsaxattributes_GetTypeInfo,
1061 ivbsaxattributes_GetIDsOfNames,
1062 ivbsaxattributes_Invoke,
1063 ivbsaxattributes_get_length,
1064 ivbsaxattributes_getURI,
1065 ivbsaxattributes_getLocalName,
1066 ivbsaxattributes_getQName,
1067 ivbsaxattributes_getIndexFromName,
1068 ivbsaxattributes_getIndexFromQName,
1069 ivbsaxattributes_getType,
1070 ivbsaxattributes_getTypeFromName,
1071 ivbsaxattributes_getTypeFromQName,
1072 ivbsaxattributes_getValue,
1073 ivbsaxattributes_getValueFromName,
1074 ivbsaxattributes_getValueFromQName
1077 /*** ISAXAttributes interface ***/
1078 /*** IUnknown methods ***/
1079 static HRESULT WINAPI isaxattributes_QueryInterface(
1080 ISAXAttributes* iface,
1081 REFIID riid,
1082 void **ppvObject)
1084 saxlocator *This = impl_from_ISAXAttributes(iface);
1085 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
1086 return ISAXLocator_QueryInterface(&This->ISAXLocator_iface, riid, ppvObject);
1089 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
1091 saxlocator *This = impl_from_ISAXAttributes(iface);
1092 TRACE("%p\n", This);
1093 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
1096 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
1098 saxlocator *This = impl_from_ISAXAttributes(iface);
1100 TRACE("%p\n", This);
1101 return ISAXLocator_Release(&This->ISAXLocator_iface);
1104 /*** ISAXAttributes methods ***/
1105 static HRESULT WINAPI isaxattributes_getLength(
1106 ISAXAttributes* iface,
1107 int *length)
1109 saxlocator *This = impl_from_ISAXAttributes( iface );
1111 *length = This->attr_count;
1112 TRACE("Length set to %d\n", *length);
1113 return S_OK;
1116 static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
1118 return index < locator->attr_count && index >= 0;
1121 static HRESULT WINAPI isaxattributes_getURI(
1122 ISAXAttributes* iface,
1123 int index,
1124 const WCHAR **url,
1125 int *size)
1127 saxlocator *This = impl_from_ISAXAttributes( iface );
1128 TRACE("(%p)->(%d)\n", This, index);
1130 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1131 if(!url || !size) return E_POINTER;
1133 *size = SysStringLen(This->attributes[index].szURI);
1134 *url = This->attributes[index].szURI;
1136 TRACE("(%s:%d)\n", debugstr_w(This->attributes[index].szURI), *size);
1138 return S_OK;
1141 static HRESULT WINAPI isaxattributes_getLocalName(
1142 ISAXAttributes* iface,
1143 int index,
1144 const WCHAR **pLocalName,
1145 int *pLocalNameLength)
1147 saxlocator *This = impl_from_ISAXAttributes( iface );
1148 TRACE("(%p)->(%d)\n", This, index);
1150 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1151 if(!pLocalName || !pLocalNameLength) return E_POINTER;
1153 *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
1154 *pLocalName = This->attributes[index].szLocalname;
1156 return S_OK;
1159 static HRESULT WINAPI isaxattributes_getQName(
1160 ISAXAttributes* iface,
1161 int index,
1162 const WCHAR **pQName,
1163 int *pQNameLength)
1165 saxlocator *This = impl_from_ISAXAttributes( iface );
1166 TRACE("(%p)->(%d)\n", This, index);
1168 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1169 if(!pQName || !pQNameLength) return E_POINTER;
1171 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1172 *pQName = This->attributes[index].szQName;
1174 return S_OK;
1177 static HRESULT WINAPI isaxattributes_getName(
1178 ISAXAttributes* iface,
1179 int index,
1180 const WCHAR **uri,
1181 int *pUriLength,
1182 const WCHAR **localName,
1183 int *pLocalNameSize,
1184 const WCHAR **QName,
1185 int *pQNameLength)
1187 saxlocator *This = impl_from_ISAXAttributes( iface );
1188 TRACE("(%p)->(%d)\n", This, index);
1190 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1191 if(!uri || !pUriLength || !localName || !pLocalNameSize
1192 || !QName || !pQNameLength) return E_POINTER;
1194 *pUriLength = SysStringLen(This->attributes[index].szURI);
1195 *uri = This->attributes[index].szURI;
1196 *pLocalNameSize = SysStringLen(This->attributes[index].szLocalname);
1197 *localName = This->attributes[index].szLocalname;
1198 *pQNameLength = SysStringLen(This->attributes[index].szQName);
1199 *QName = This->attributes[index].szQName;
1201 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName));
1203 return S_OK;
1206 static HRESULT WINAPI isaxattributes_getIndexFromName(
1207 ISAXAttributes* iface,
1208 const WCHAR *pUri,
1209 int cUriLength,
1210 const WCHAR *pLocalName,
1211 int cocalNameLength,
1212 int *index)
1214 saxlocator *This = impl_from_ISAXAttributes( iface );
1215 int i;
1216 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
1217 debugstr_w(pLocalName), cocalNameLength);
1219 if(!pUri || !pLocalName || !index) return E_POINTER;
1221 for(i=0; i<This->attr_count; i++)
1223 if(cUriLength!=SysStringLen(This->attributes[i].szURI)
1224 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
1225 continue;
1226 if(cUriLength && memcmp(pUri, This->attributes[i].szURI,
1227 sizeof(WCHAR)*cUriLength))
1228 continue;
1229 if(cocalNameLength && memcmp(pLocalName, This->attributes[i].szLocalname,
1230 sizeof(WCHAR)*cocalNameLength))
1231 continue;
1233 *index = i;
1234 return S_OK;
1237 return E_INVALIDARG;
1240 static HRESULT WINAPI isaxattributes_getIndexFromQName(
1241 ISAXAttributes* iface,
1242 const WCHAR *pQName,
1243 int nQNameLength,
1244 int *index)
1246 saxlocator *This = impl_from_ISAXAttributes( iface );
1247 int i;
1248 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
1250 if(!pQName || !index) return E_POINTER;
1251 if(!nQNameLength) return E_INVALIDARG;
1253 for(i=0; i<This->attr_count; i++)
1255 if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
1256 if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
1258 *index = i;
1259 return S_OK;
1262 return E_INVALIDARG;
1265 static HRESULT WINAPI isaxattributes_getType(
1266 ISAXAttributes* iface,
1267 int nIndex,
1268 const WCHAR **pType,
1269 int *pTypeLength)
1271 saxlocator *This = impl_from_ISAXAttributes( iface );
1273 FIXME("(%p)->(%d) stub\n", This, nIndex);
1274 return E_NOTIMPL;
1277 static HRESULT WINAPI isaxattributes_getTypeFromName(
1278 ISAXAttributes* iface,
1279 const WCHAR *pUri,
1280 int nUri,
1281 const WCHAR *pLocalName,
1282 int nLocalName,
1283 const WCHAR **pType,
1284 int *nType)
1286 saxlocator *This = impl_from_ISAXAttributes( iface );
1288 FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
1289 debugstr_w(pLocalName), nLocalName);
1290 return E_NOTIMPL;
1293 static HRESULT WINAPI isaxattributes_getTypeFromQName(
1294 ISAXAttributes* iface,
1295 const WCHAR *pQName,
1296 int nQName,
1297 const WCHAR **pType,
1298 int *nType)
1300 saxlocator *This = impl_from_ISAXAttributes( iface );
1302 FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
1303 return E_NOTIMPL;
1306 static HRESULT WINAPI isaxattributes_getValue(
1307 ISAXAttributes* iface,
1308 int index,
1309 const WCHAR **value,
1310 int *nValue)
1312 saxlocator *This = impl_from_ISAXAttributes( iface );
1313 TRACE("(%p)->(%d)\n", This, index);
1315 if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
1316 if(!value || !nValue) return E_POINTER;
1318 *nValue = SysStringLen(This->attributes[index].szValue);
1319 *value = This->attributes[index].szValue;
1321 TRACE("(%s:%d)\n", debugstr_w(*value), *nValue);
1323 return S_OK;
1326 static HRESULT WINAPI isaxattributes_getValueFromName(
1327 ISAXAttributes* iface,
1328 const WCHAR *pUri,
1329 int nUri,
1330 const WCHAR *pLocalName,
1331 int nLocalName,
1332 const WCHAR **pValue,
1333 int *nValue)
1335 HRESULT hr;
1336 int index;
1337 saxlocator *This = impl_from_ISAXAttributes( iface );
1338 TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
1339 debugstr_w(pLocalName), nLocalName);
1341 hr = ISAXAttributes_getIndexFromName(iface,
1342 pUri, nUri, pLocalName, nLocalName, &index);
1343 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1345 return hr;
1348 static HRESULT WINAPI isaxattributes_getValueFromQName(
1349 ISAXAttributes* iface,
1350 const WCHAR *pQName,
1351 int nQName,
1352 const WCHAR **pValue,
1353 int *nValue)
1355 HRESULT hr;
1356 int index;
1357 saxlocator *This = impl_from_ISAXAttributes( iface );
1358 TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
1360 hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
1361 if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
1363 return hr;
1366 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
1368 isaxattributes_QueryInterface,
1369 isaxattributes_AddRef,
1370 isaxattributes_Release,
1371 isaxattributes_getLength,
1372 isaxattributes_getURI,
1373 isaxattributes_getLocalName,
1374 isaxattributes_getQName,
1375 isaxattributes_getName,
1376 isaxattributes_getIndexFromName,
1377 isaxattributes_getIndexFromQName,
1378 isaxattributes_getType,
1379 isaxattributes_getTypeFromName,
1380 isaxattributes_getTypeFromQName,
1381 isaxattributes_getValue,
1382 isaxattributes_getValueFromName,
1383 isaxattributes_getValueFromQName
1386 /* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
1387 so when document has escaped value with '&amp;' it's parsed to '&' and then
1388 escaped to '&#38;'. This function takes care of ampersands only. */
1389 static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
1391 static const WCHAR ampescW[] = {'&','#','3','8',';',0};
1392 WCHAR *dest, *ptrW, *str;
1393 DWORD str_len;
1394 BSTR bstr;
1396 if (!buf)
1397 return NULL;
1399 str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
1400 if (len != -1) str_len++;
1402 str = malloc(str_len * sizeof(WCHAR));
1403 if (!str) return NULL;
1405 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
1406 if (len != -1) str[str_len-1] = 0;
1408 ptrW = str;
1409 while ((dest = wcsstr(ptrW, ampescW)))
1411 WCHAR *src;
1413 /* leave first '&' from a reference as a value */
1414 src = dest + ARRAY_SIZE(ampescW) - 1;
1415 dest++;
1417 /* move together with null terminator */
1418 memmove(dest, src, (lstrlenW(src) + 1)*sizeof(WCHAR));
1420 ptrW++;
1423 bstr = SysAllocString(str);
1424 free(str);
1426 return bstr;
1429 static void free_attribute_values(saxlocator *locator)
1431 int i;
1433 for (i = 0; i < locator->attr_count; i++)
1435 SysFreeString(locator->attributes[i].szLocalname);
1436 locator->attributes[i].szLocalname = NULL;
1438 SysFreeString(locator->attributes[i].szValue);
1439 locator->attributes[i].szValue = NULL;
1441 SysFreeString(locator->attributes[i].szQName);
1442 locator->attributes[i].szQName = NULL;
1446 static HRESULT SAXAttributes_populate(saxlocator *locator,
1447 int nb_namespaces, const xmlChar **xmlNamespaces,
1448 int nb_attributes, const xmlChar **xmlAttributes)
1450 static const xmlChar xmlns[] = "xmlns";
1451 static const WCHAR xmlnsW[] = { 'x','m','l','n','s',0 };
1453 struct _attributes *attrs;
1454 int i;
1456 /* skip namespace definitions */
1457 if ((locator->saxreader->features & NamespacePrefixes) == 0)
1458 nb_namespaces = 0;
1460 locator->attr_count = nb_namespaces + nb_attributes;
1461 if(locator->attr_count > locator->attr_alloc_count)
1463 int new_size = locator->attr_count * 2;
1464 attrs = realloc(locator->attributes, new_size * sizeof(*locator->attributes));
1465 if(!attrs)
1467 free_attribute_values(locator);
1468 locator->attr_count = 0;
1469 return E_OUTOFMEMORY;
1471 memset(attrs + locator->attr_alloc_count, 0,
1472 (new_size - locator->attr_alloc_count) * sizeof(*locator->attributes));
1473 locator->attributes = attrs;
1474 locator->attr_alloc_count = new_size;
1476 else
1478 attrs = locator->attributes;
1481 for (i = 0; i < nb_namespaces; i++)
1483 SysFreeString(attrs[nb_attributes+i].szLocalname);
1484 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1486 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1488 SysFreeString(attrs[nb_attributes+i].szValue);
1489 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1491 SysFreeString(attrs[nb_attributes+i].szQName);
1492 if(!xmlNamespaces[2*i])
1493 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1494 else
1495 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1498 for (i = 0; i < nb_attributes; i++)
1500 static const xmlChar xmlA[] = "xml";
1502 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1503 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1504 else
1505 /* that's an important feature to keep same uri pointer for every reported attribute */
1506 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1508 SysFreeString(attrs[i].szLocalname);
1509 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1511 SysFreeString(attrs[i].szValue);
1512 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1514 SysFreeString(attrs[i].szQName);
1515 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1518 return S_OK;
1521 /*** LibXML callbacks ***/
1522 static void libxmlStartDocument(void *ctx)
1524 saxlocator *This = ctx;
1525 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1526 HRESULT hr;
1528 if (This->saxreader->version >= MSXML4)
1530 const xmlChar *p = This->pParserCtxt->input->cur-1;
1531 update_position(This, FALSE);
1532 while(p>This->pParserCtxt->input->base && *p!='>')
1534 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1535 This->line--;
1536 p--;
1538 This->column = 0;
1539 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1540 This->column++;
1543 /* store version value, declaration has to contain version attribute */
1544 if (This->pParserCtxt->standalone != -1)
1546 SysFreeString(This->saxreader->xmldecl_version);
1547 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1550 if (saxreader_has_handler(This, SAXContentHandler))
1552 if(This->vbInterface)
1553 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1554 else
1555 hr = ISAXContentHandler_startDocument(handler->handler);
1557 if (sax_callback_failed(This, hr))
1558 format_error_message_from_id(This, hr);
1562 static void libxmlEndDocument(void *ctx)
1564 saxlocator *This = ctx;
1565 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1566 HRESULT hr;
1568 if (This->saxreader->version >= MSXML4) {
1569 update_position(This, FALSE);
1570 if(This->column > 1)
1571 This->line++;
1572 This->column = 0;
1573 } else {
1574 This->column = 0;
1575 This->line = 0;
1578 if(This->ret != S_OK) return;
1580 if (saxreader_has_handler(This, SAXContentHandler))
1582 if(This->vbInterface)
1583 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1584 else
1585 hr = ISAXContentHandler_endDocument(handler->handler);
1587 if (sax_callback_failed(This, hr))
1588 format_error_message_from_id(This, hr);
1592 static void libxmlStartElementNS(
1593 void *ctx,
1594 const xmlChar *localname,
1595 const xmlChar *prefix,
1596 const xmlChar *URI,
1597 int nb_namespaces,
1598 const xmlChar **namespaces,
1599 int nb_attributes,
1600 int nb_defaulted,
1601 const xmlChar **attributes)
1603 saxlocator *This = ctx;
1604 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1605 element_entry *element;
1606 HRESULT hr = S_OK;
1607 BSTR uri;
1609 update_position(This, TRUE);
1610 if(*(This->pParserCtxt->input->cur) == '/')
1611 This->column++;
1612 if(This->saxreader->version < MSXML4)
1613 This->column++;
1615 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1616 push_element_ns(This, element);
1618 if (is_namespaces_enabled(This->saxreader))
1620 int i;
1622 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1624 if (This->vbInterface)
1625 hr = IVBSAXContentHandler_startPrefixMapping(
1626 handler->vbhandler,
1627 &element->ns[i].prefix,
1628 &element->ns[i].uri);
1629 else
1630 hr = ISAXContentHandler_startPrefixMapping(
1631 handler->handler,
1632 element->ns[i].prefix,
1633 SysStringLen(element->ns[i].prefix),
1634 element->ns[i].uri,
1635 SysStringLen(element->ns[i].uri));
1637 if (sax_callback_failed(This, hr))
1639 format_error_message_from_id(This, hr);
1640 return;
1645 uri = find_element_uri(This, URI);
1646 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1647 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1649 BSTR local;
1651 if (is_namespaces_enabled(This->saxreader))
1652 local = element->local;
1653 else
1654 uri = local = NULL;
1656 if (This->vbInterface)
1657 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1658 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1659 else
1660 hr = ISAXContentHandler_startElement(handler->handler,
1661 uri ? uri : &empty_str, SysStringLen(uri),
1662 local ? local : &empty_str, SysStringLen(local),
1663 element->qname, SysStringLen(element->qname),
1664 &This->ISAXAttributes_iface);
1666 if (sax_callback_failed(This, hr))
1667 format_error_message_from_id(This, hr);
1671 static void libxmlEndElementNS(
1672 void *ctx,
1673 const xmlChar *localname,
1674 const xmlChar *prefix,
1675 const xmlChar *URI)
1677 saxlocator *This = ctx;
1678 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1679 element_entry *element;
1680 const xmlChar *p;
1681 BSTR uri, local;
1682 HRESULT hr;
1684 update_position(This, FALSE);
1685 p = This->pParserCtxt->input->cur;
1687 if (This->saxreader->version >= MSXML4)
1689 p--;
1690 while(p>This->pParserCtxt->input->base && *p!='>')
1692 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1693 This->line--;
1694 p--;
1697 else if(*(p-1)!='>' || *(p-2)!='/')
1699 p--;
1700 while(p-2>=This->pParserCtxt->input->base
1701 && *(p-2)!='<' && *(p-1)!='/')
1703 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1704 This->line--;
1705 p--;
1708 This->column = 0;
1709 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1710 This->column++;
1712 uri = find_element_uri(This, URI);
1713 element = pop_element_ns(This);
1715 if (!saxreader_has_handler(This, SAXContentHandler))
1717 free_attribute_values(This);
1718 This->attr_count = 0;
1719 free_element_entry(element);
1720 return;
1723 if (is_namespaces_enabled(This->saxreader))
1724 local = element->local;
1725 else
1726 uri = local = NULL;
1728 if (This->vbInterface)
1729 hr = IVBSAXContentHandler_endElement(
1730 handler->vbhandler,
1731 &uri, &local, &element->qname);
1732 else
1733 hr = ISAXContentHandler_endElement(
1734 handler->handler,
1735 uri ? uri : &empty_str, SysStringLen(uri),
1736 local ? local : &empty_str, SysStringLen(local),
1737 element->qname, SysStringLen(element->qname));
1739 free_attribute_values(This);
1740 This->attr_count = 0;
1742 if (sax_callback_failed(This, hr))
1744 format_error_message_from_id(This, hr);
1745 free_element_entry(element);
1746 return;
1749 if (is_namespaces_enabled(This->saxreader))
1751 int i = -1;
1752 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1754 if (This->vbInterface)
1755 hr = IVBSAXContentHandler_endPrefixMapping(
1756 handler->vbhandler, &element->ns[i].prefix);
1757 else
1758 hr = ISAXContentHandler_endPrefixMapping(
1759 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1761 if (sax_callback_failed(This, hr)) break;
1764 if (sax_callback_failed(This, hr))
1765 format_error_message_from_id(This, hr);
1768 free_element_entry(element);
1771 static void libxmlCharacters(
1772 void *ctx,
1773 const xmlChar *ch,
1774 int len)
1776 saxlocator *This = ctx;
1777 BSTR Chars;
1778 HRESULT hr;
1779 xmlChar *cur, *end;
1780 BOOL lastEvent = FALSE;
1782 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1784 update_position(This, FALSE);
1785 cur = (xmlChar*)This->pParserCtxt->input->cur;
1786 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1788 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1789 This->line--;
1790 cur--;
1792 This->column = 1;
1793 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1794 This->column++;
1796 cur = (xmlChar*)ch;
1797 if(*(ch-1)=='\r') cur--;
1798 end = cur;
1800 while(1)
1802 while(end-ch<len && *end!='\r') end++;
1803 if(end-ch==len)
1805 lastEvent = TRUE;
1807 else
1809 *end = '\n';
1810 end++;
1813 if (This->saxreader->version >= MSXML4)
1815 xmlChar *p;
1817 for(p=cur; p!=end; p++)
1819 if(*p=='\n')
1821 This->line++;
1822 This->column = 1;
1824 else
1826 This->column++;
1830 if(!lastEvent)
1831 This->column = 0;
1834 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1835 hr = saxreader_saxcharacters(This, Chars);
1837 if (sax_callback_failed(This, hr))
1839 format_error_message_from_id(This, hr);
1840 return;
1843 if (This->saxreader->version < MSXML4)
1844 This->column += end-cur;
1846 if(lastEvent)
1847 break;
1849 *(end-1) = '\r';
1850 if(*end == '\n')
1852 end++;
1853 This->column++;
1855 cur = end;
1857 if(end-ch == len) break;
1861 static void libxmlSetDocumentLocator(
1862 void *ctx,
1863 xmlSAXLocatorPtr loc)
1865 saxlocator *This = ctx;
1866 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1867 HRESULT hr = S_OK;
1869 if (saxreader_has_handler(This, SAXContentHandler))
1871 if(This->vbInterface)
1872 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1873 &This->IVBSAXLocator_iface);
1874 else
1875 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1878 if(FAILED(hr))
1879 format_error_message_from_id(This, hr);
1882 static void libxmlComment(void *ctx, const xmlChar *value)
1884 saxlocator *This = ctx;
1885 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1886 BSTR bValue;
1887 HRESULT hr;
1888 const xmlChar *p = This->pParserCtxt->input->cur;
1890 update_position(This, FALSE);
1891 while(p-4>=This->pParserCtxt->input->base
1892 && memcmp(p-4, "<!--", sizeof(char[4])))
1894 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1895 This->line--;
1896 p--;
1899 This->column = 0;
1900 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1901 This->column++;
1903 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1905 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1907 if (This->vbInterface)
1908 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1909 else
1910 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1912 if(FAILED(hr))
1913 format_error_message_from_id(This, hr);
1916 static void WINAPIV libxmlFatalError(void *ctx, const char *msg, ...)
1918 saxlocator *This = ctx;
1919 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1920 char message[1024];
1921 WCHAR *error;
1922 DWORD len;
1923 va_list args;
1925 if(This->ret != S_OK) {
1926 xmlStopParser(This->pParserCtxt);
1927 return;
1930 va_start(args, msg);
1931 vsprintf(message, msg, args);
1932 va_end(args);
1934 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1935 error = malloc(sizeof(WCHAR) * len);
1936 if(error)
1938 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1939 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1942 if (!saxreader_has_handler(This, SAXErrorHandler))
1944 xmlStopParser(This->pParserCtxt);
1945 This->ret = E_FAIL;
1946 free(error);
1947 return;
1950 FIXME("Error handling is not compatible.\n");
1952 if(This->vbInterface)
1954 BSTR bstrError = SysAllocString(error);
1955 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1956 &bstrError, E_FAIL);
1957 SysFreeString(bstrError);
1959 else
1960 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1962 free(error);
1964 xmlStopParser(This->pParserCtxt);
1965 This->ret = E_FAIL;
1968 /* The only reason this helper exists is that CDATA section are reported by chunks,
1969 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1971 This helper should be called for substring with trailing newlines.
1973 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1975 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1976 WCHAR *ptr;
1978 len = SysStringLen(bstr);
1979 ptr = bstr + len - 1;
1980 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1981 ptr--;
1983 while (*++ptr)
1985 /* replace returns as:
1987 - "\r<char>" -> "\n<char>"
1988 - "\r\r" -> "\r"
1989 - "\r\n" -> "\n"
1991 if (*ptr == '\r')
1993 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1995 /* shift tail */
1996 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1998 else
1999 *ptr = '\n';
2003 ret = SysAllocStringLen(bstr, len);
2004 SysFreeString(bstr);
2005 return ret;
2008 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2010 const xmlChar *start, *end;
2011 saxlocator *locator = ctx;
2012 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2013 HRESULT hr = S_OK;
2014 BSTR chars;
2015 int i;
2017 update_position(locator, FALSE);
2018 if (saxreader_has_handler(locator, SAXLexicalHandler))
2020 if (locator->vbInterface)
2021 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2022 else
2023 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2026 if(FAILED(hr))
2028 format_error_message_from_id(locator, hr);
2029 return;
2032 start = value;
2033 end = NULL;
2034 i = 0;
2036 while (i < len)
2038 /* scan for newlines */
2039 if (value[i] == '\r' || value[i] == '\n')
2041 /* skip newlines/linefeeds */
2042 while (i < len)
2044 if (value[i] != '\r' && value[i] != '\n') break;
2045 i++;
2047 end = &value[i];
2049 /* report */
2050 chars = saxreader_get_cdata_chunk(start, end-start);
2051 TRACE("(chunk %s)\n", debugstr_w(chars));
2052 hr = saxreader_saxcharacters(locator, chars);
2053 SysFreeString(chars);
2055 start = &value[i];
2056 end = NULL;
2058 i++;
2059 locator->column++;
2062 /* no newline chars (or last chunk) report as a whole */
2063 if (!end && start == value)
2065 /* report */
2066 chars = bstr_from_xmlCharN(start, len-(start-value));
2067 TRACE("(%s)\n", debugstr_w(chars));
2068 hr = saxreader_saxcharacters(locator, chars);
2069 SysFreeString(chars);
2072 if (saxreader_has_handler(locator, SAXLexicalHandler))
2074 if (locator->vbInterface)
2075 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2076 else
2077 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2080 if(FAILED(hr))
2081 format_error_message_from_id(locator, hr);
2084 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2086 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2087 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2090 /*** IVBSAXLocator interface ***/
2091 /*** IUnknown methods ***/
2092 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2094 saxlocator *This = impl_from_IVBSAXLocator( iface );
2096 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2098 *ppvObject = NULL;
2100 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2101 IsEqualGUID( riid, &IID_IDispatch) ||
2102 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2104 *ppvObject = iface;
2106 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2108 *ppvObject = &This->IVBSAXAttributes_iface;
2110 else
2112 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2113 return E_NOINTERFACE;
2116 IVBSAXLocator_AddRef( iface );
2118 return S_OK;
2121 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2123 saxlocator *This = impl_from_IVBSAXLocator( iface );
2124 TRACE("%p\n", This );
2125 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2128 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2130 saxlocator *This = impl_from_IVBSAXLocator( iface );
2131 return ISAXLocator_Release(&This->ISAXLocator_iface);
2134 /*** IDispatch methods ***/
2135 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2137 saxlocator *This = impl_from_IVBSAXLocator( iface );
2139 TRACE("(%p)->(%p)\n", This, pctinfo);
2141 *pctinfo = 1;
2143 return S_OK;
2146 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2147 IVBSAXLocator *iface,
2148 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2150 TRACE("%p, %u, %lx, %p.\n", iface, iTInfo, lcid, ppTInfo);
2152 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2155 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2156 IVBSAXLocator *iface,
2157 REFIID riid,
2158 LPOLESTR* rgszNames,
2159 UINT cNames,
2160 LCID lcid,
2161 DISPID* rgDispId)
2163 ITypeInfo *typeinfo;
2164 HRESULT hr;
2166 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface, debugstr_guid(riid), rgszNames, cNames,
2167 lcid, rgDispId);
2169 if(!rgszNames || cNames == 0 || !rgDispId)
2170 return E_INVALIDARG;
2172 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2173 if(SUCCEEDED(hr))
2175 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2176 ITypeInfo_Release(typeinfo);
2179 return hr;
2182 static HRESULT WINAPI ivbsaxlocator_Invoke(
2183 IVBSAXLocator *iface,
2184 DISPID dispIdMember,
2185 REFIID riid,
2186 LCID lcid,
2187 WORD wFlags,
2188 DISPPARAMS* pDispParams,
2189 VARIANT* pVarResult,
2190 EXCEPINFO* pExcepInfo,
2191 UINT* puArgErr)
2193 ITypeInfo *typeinfo;
2194 HRESULT hr;
2196 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface, dispIdMember, debugstr_guid(riid),
2197 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2199 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2200 if(SUCCEEDED(hr))
2202 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2203 ITypeInfo_Release(typeinfo);
2206 return hr;
2209 /*** IVBSAXLocator methods ***/
2210 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2211 IVBSAXLocator* iface,
2212 int *pnColumn)
2214 saxlocator *This = impl_from_IVBSAXLocator( iface );
2215 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2218 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2219 IVBSAXLocator* iface,
2220 int *pnLine)
2222 saxlocator *This = impl_from_IVBSAXLocator( iface );
2223 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2226 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2228 saxlocator *This = impl_from_IVBSAXLocator( iface );
2229 const WCHAR *publicidW;
2230 HRESULT hr;
2232 TRACE("(%p)->(%p)\n", This, ret);
2234 if (!ret)
2235 return E_POINTER;
2237 *ret = NULL;
2238 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2239 if (FAILED(hr))
2240 return hr;
2242 return return_bstr(publicidW, ret);
2245 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2247 saxlocator *This = impl_from_IVBSAXLocator( iface );
2248 const WCHAR *systemidW;
2249 HRESULT hr;
2251 TRACE("(%p)->(%p)\n", This, ret);
2253 if (!ret)
2254 return E_POINTER;
2256 *ret = NULL;
2257 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2258 if (FAILED(hr))
2259 return hr;
2261 return return_bstr(systemidW, ret);
2264 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2266 ivbsaxlocator_QueryInterface,
2267 ivbsaxlocator_AddRef,
2268 ivbsaxlocator_Release,
2269 ivbsaxlocator_GetTypeInfoCount,
2270 ivbsaxlocator_GetTypeInfo,
2271 ivbsaxlocator_GetIDsOfNames,
2272 ivbsaxlocator_Invoke,
2273 ivbsaxlocator_get_columnNumber,
2274 ivbsaxlocator_get_lineNumber,
2275 ivbsaxlocator_get_publicId,
2276 ivbsaxlocator_get_systemId
2279 /*** ISAXLocator interface ***/
2280 /*** IUnknown methods ***/
2281 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2283 saxlocator *This = impl_from_ISAXLocator( iface );
2285 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2287 *ppvObject = NULL;
2289 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2290 IsEqualGUID( riid, &IID_ISAXLocator ))
2292 *ppvObject = iface;
2294 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2296 *ppvObject = &This->ISAXAttributes_iface;
2298 else
2300 WARN("interface %s not implemented\n", debugstr_guid(riid));
2301 return E_NOINTERFACE;
2304 ISAXLocator_AddRef( iface );
2306 return S_OK;
2309 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2311 saxlocator *This = impl_from_ISAXLocator( iface );
2312 ULONG ref = InterlockedIncrement( &This->ref );
2313 TRACE("%p, refcount %lu.\n", iface, ref);
2314 return ref;
2317 static ULONG WINAPI isaxlocator_Release(
2318 ISAXLocator* iface)
2320 saxlocator *This = impl_from_ISAXLocator( iface );
2321 ULONG ref = InterlockedDecrement( &This->ref );
2323 TRACE("%p, refcount %ld.\n", iface, ref );
2325 if (!ref)
2327 element_entry *element, *element2;
2328 int index;
2330 SysFreeString(This->publicId);
2331 SysFreeString(This->systemId);
2332 SysFreeString(This->namespaceUri);
2334 for(index = 0; index < This->attr_alloc_count; index++)
2336 SysFreeString(This->attributes[index].szLocalname);
2337 SysFreeString(This->attributes[index].szValue);
2338 SysFreeString(This->attributes[index].szQName);
2340 free(This->attributes);
2342 /* element stack */
2343 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2345 list_remove(&element->entry);
2346 free_element_entry(element);
2349 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2350 free(This);
2353 return ref;
2356 /*** ISAXLocator methods ***/
2357 static HRESULT WINAPI isaxlocator_getColumnNumber(
2358 ISAXLocator* iface,
2359 int *pnColumn)
2361 saxlocator *This = impl_from_ISAXLocator( iface );
2363 *pnColumn = This->column;
2364 return S_OK;
2367 static HRESULT WINAPI isaxlocator_getLineNumber(
2368 ISAXLocator* iface,
2369 int *pnLine)
2371 saxlocator *This = impl_from_ISAXLocator( iface );
2373 *pnLine = This->line;
2374 return S_OK;
2377 static HRESULT WINAPI isaxlocator_getPublicId(
2378 ISAXLocator* iface,
2379 const WCHAR ** ppwchPublicId)
2381 BSTR publicId;
2382 saxlocator *This = impl_from_ISAXLocator( iface );
2384 SysFreeString(This->publicId);
2386 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2387 if(SysStringLen(publicId))
2388 This->publicId = publicId;
2389 else
2391 SysFreeString(publicId);
2392 This->publicId = NULL;
2395 *ppwchPublicId = This->publicId;
2396 return S_OK;
2399 static HRESULT WINAPI isaxlocator_getSystemId(
2400 ISAXLocator* iface,
2401 const WCHAR ** ppwchSystemId)
2403 BSTR systemId;
2404 saxlocator *This = impl_from_ISAXLocator( iface );
2406 SysFreeString(This->systemId);
2408 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2409 if(SysStringLen(systemId))
2410 This->systemId = systemId;
2411 else
2413 SysFreeString(systemId);
2414 This->systemId = NULL;
2417 *ppwchSystemId = This->systemId;
2418 return S_OK;
2421 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2423 isaxlocator_QueryInterface,
2424 isaxlocator_AddRef,
2425 isaxlocator_Release,
2426 isaxlocator_getColumnNumber,
2427 isaxlocator_getLineNumber,
2428 isaxlocator_getPublicId,
2429 isaxlocator_getSystemId
2432 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2434 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2435 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2437 saxlocator *locator;
2439 locator = malloc(sizeof(*locator));
2440 if( !locator )
2441 return E_OUTOFMEMORY;
2443 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2444 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2445 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2446 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2447 locator->ref = 1;
2448 locator->vbInterface = vbInterface;
2450 locator->saxreader = reader;
2451 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2453 locator->pParserCtxt = NULL;
2454 locator->publicId = NULL;
2455 locator->systemId = NULL;
2456 locator->line = reader->version < MSXML4 ? 0 : 1;
2457 locator->column = 0;
2458 locator->ret = S_OK;
2459 if (locator->saxreader->version >= MSXML6)
2460 locator->namespaceUri = SysAllocString(w3xmlns);
2461 else
2462 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2463 if(!locator->namespaceUri)
2465 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2466 free(locator);
2467 return E_OUTOFMEMORY;
2470 locator->attr_alloc_count = 8;
2471 locator->attr_count = 0;
2472 locator->attributes = calloc(locator->attr_alloc_count, sizeof(*locator->attributes));
2473 if(!locator->attributes)
2475 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2476 SysFreeString(locator->namespaceUri);
2477 free(locator);
2478 return E_OUTOFMEMORY;
2481 list_init(&locator->elements);
2483 *ppsaxlocator = locator;
2485 TRACE("returning %p\n", *ppsaxlocator);
2487 return S_OK;
2490 /*** SAXXMLReader internal functions ***/
2491 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2493 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2494 xmlChar *enc_name = NULL;
2495 saxlocator *locator;
2496 HRESULT hr;
2498 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2500 hr = SAXLocator_create(This, &locator, vbInterface);
2501 if (FAILED(hr))
2502 return hr;
2504 if (size >= 4)
2506 const unsigned char *buff = (unsigned char*)buffer;
2508 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2509 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2510 TRACE("detected encoding: %s\n", enc_name);
2511 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2512 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2513 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2515 buffer += 3;
2516 size -= 3;
2520 /* if libxml2 detection failed try to guess */
2521 if (encoding == XML_CHAR_ENCODING_NONE)
2523 const WCHAR *ptr = (WCHAR*)buffer;
2524 /* an xml declaration with optional encoding will still be handled by the parser */
2525 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2527 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2528 encoding = XML_CHAR_ENCODING_UTF16LE;
2531 else if (encoding == XML_CHAR_ENCODING_UTF8)
2532 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2533 else
2534 enc_name = NULL;
2536 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2537 if (!locator->pParserCtxt)
2539 ISAXLocator_Release(&locator->ISAXLocator_iface);
2540 return E_FAIL;
2543 if (enc_name)
2545 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2546 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2547 TRACE("switching to %s\n", enc_name);
2548 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2552 xmlFree(locator->pParserCtxt->sax);
2553 locator->pParserCtxt->sax = &locator->saxreader->sax;
2554 locator->pParserCtxt->userData = locator;
2556 This->isParsing = TRUE;
2557 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2558 hr = E_FAIL;
2559 else
2560 hr = locator->ret;
2561 This->isParsing = FALSE;
2563 if(locator->pParserCtxt)
2565 locator->pParserCtxt->sax = NULL;
2566 xmlFreeParserCtxt(locator->pParserCtxt);
2567 locator->pParserCtxt = NULL;
2570 ISAXLocator_Release(&locator->ISAXLocator_iface);
2571 return hr;
2574 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2576 saxlocator *locator;
2577 HRESULT hr;
2578 ULONG dataRead;
2579 char data[2048];
2580 int ret;
2582 dataRead = 0;
2583 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2584 if(FAILED(hr)) return hr;
2586 hr = SAXLocator_create(This, &locator, vbInterface);
2587 if(FAILED(hr)) return hr;
2589 locator->pParserCtxt = xmlCreatePushParserCtxt(
2590 &locator->saxreader->sax, locator,
2591 data, dataRead, NULL);
2592 if(!locator->pParserCtxt)
2594 ISAXLocator_Release(&locator->ISAXLocator_iface);
2595 return E_FAIL;
2598 This->isParsing = TRUE;
2600 do {
2601 dataRead = 0;
2602 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2603 if (FAILED(hr) || !dataRead) break;
2605 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2606 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2607 }while(hr == S_OK);
2609 if(SUCCEEDED(hr))
2611 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2612 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2616 This->isParsing = FALSE;
2618 xmlFreeParserCtxt(locator->pParserCtxt);
2619 locator->pParserCtxt = NULL;
2620 ISAXLocator_Release(&locator->ISAXLocator_iface);
2621 return hr;
2624 static HRESULT internal_parse(
2625 saxreader* This,
2626 VARIANT varInput,
2627 BOOL vbInterface)
2629 HRESULT hr;
2631 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2633 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2634 free_bstr_pool(&This->pool);
2636 switch(V_VT(&varInput))
2638 case VT_BSTR:
2639 case VT_BSTR|VT_BYREF:
2641 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2642 hr = internal_parseBuffer(This, (const char*)str, lstrlenW(str)*sizeof(WCHAR), vbInterface);
2643 break;
2645 case VT_ARRAY|VT_UI1: {
2646 void *pSAData;
2647 LONG lBound, uBound;
2648 ULONG dataRead;
2650 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2651 if(hr != S_OK) break;
2652 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2653 if(hr != S_OK) break;
2654 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2655 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2656 if(hr != S_OK) break;
2657 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2658 SafeArrayUnaccessData(V_ARRAY(&varInput));
2659 break;
2661 case VT_UNKNOWN:
2662 case VT_DISPATCH: {
2663 ISequentialStream *stream = NULL;
2664 IXMLDOMDocument *xmlDoc;
2666 if (!V_UNKNOWN(&varInput))
2667 return E_INVALIDARG;
2669 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2670 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2672 BSTR bstrData;
2674 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2675 hr = internal_parseBuffer(This, (const char*)bstrData,
2676 SysStringByteLen(bstrData), vbInterface);
2677 IXMLDOMDocument_Release(xmlDoc);
2678 SysFreeString(bstrData);
2679 break;
2682 /* try base interface first */
2683 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2684 if (!stream)
2685 /* this should never happen if IStream is implemented properly, but just in case */
2686 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2688 if(stream)
2690 hr = internal_parseStream(This, stream, vbInterface);
2691 ISequentialStream_Release(stream);
2693 else
2695 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2696 hr = E_INVALIDARG;
2699 break;
2701 default:
2702 WARN("vt %d not implemented\n", V_VT(&varInput));
2703 hr = E_INVALIDARG;
2706 return hr;
2709 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2711 saxreader *This = obj;
2713 return internal_parseBuffer(This, ptr, len, TRUE);
2716 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2718 saxreader *This = obj;
2720 return internal_parseBuffer(This, ptr, len, FALSE);
2723 static HRESULT internal_parseURL(saxreader *reader, const WCHAR *url, BOOL vbInterface)
2725 IMoniker *mon;
2726 bsc_t *bsc;
2727 HRESULT hr;
2729 TRACE("%p, %s.\n", reader, debugstr_w(url));
2731 if (!url && reader->version < MSXML4)
2732 return E_INVALIDARG;
2734 hr = create_moniker_from_url(url, &mon);
2735 if(FAILED(hr))
2736 return hr;
2738 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, reader, &bsc);
2739 else hr = bind_url(mon, internal_onDataAvailable, reader, &bsc);
2740 IMoniker_Release(mon);
2742 if(FAILED(hr))
2743 return hr;
2745 return detach_bsc(bsc);
2748 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2750 const IID *riid;
2752 if (V_VT(v) == VT_EMPTY)
2753 return saxreader_put_handler(This, type, NULL, vb);
2755 switch (type)
2757 case SAXDeclHandler:
2758 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2759 break;
2760 case SAXLexicalHandler:
2761 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2762 break;
2763 default:
2764 ERR("wrong handler type %d\n", type);
2765 return E_FAIL;
2768 switch (V_VT(v))
2770 case VT_DISPATCH:
2771 case VT_UNKNOWN:
2773 IUnknown *handler = NULL;
2775 if (V_UNKNOWN(v))
2777 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2778 if (FAILED(hr)) return hr;
2781 saxreader_put_handler(This, type, handler, vb);
2782 if (handler) IUnknown_Release(handler);
2783 break;
2785 default:
2786 ERR("value type %d not supported\n", V_VT(v));
2787 return E_INVALIDARG;
2790 return S_OK;
2793 static HRESULT internal_putProperty(
2794 saxreader* This,
2795 const WCHAR *prop,
2796 VARIANT value,
2797 BOOL vbInterface)
2799 VARIANT *v;
2801 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2803 if (This->isParsing) return E_FAIL;
2805 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2806 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2807 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2809 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2810 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2812 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2814 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2815 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2816 return E_NOTIMPL;
2819 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2821 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2822 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2823 return E_NOTIMPL;
2826 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2828 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2829 return E_NOTIMPL;
2831 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2832 return E_FAIL;
2834 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2835 return E_NOTIMPL;
2837 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2838 return E_NOTIMPL;
2840 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2841 return E_FAIL;
2843 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2844 return E_FAIL;
2846 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2847 return E_FAIL;
2849 return E_INVALIDARG;
2852 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2854 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2856 if (!value) return E_POINTER;
2858 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2860 V_VT(value) = VT_UNKNOWN;
2861 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2862 return S_OK;
2865 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2867 V_VT(value) = VT_UNKNOWN;
2868 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2869 return S_OK;
2872 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2874 V_VT(value) = VT_BSTR;
2875 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2876 return S_OK;
2879 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2881 return E_NOTIMPL;
2884 /*** IVBSAXXMLReader interface ***/
2885 /*** IUnknown methods ***/
2886 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2888 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2890 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2892 *ppvObject = NULL;
2894 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2895 IsEqualGUID( riid, &IID_IDispatch ) ||
2896 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2898 *ppvObject = iface;
2900 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2902 *ppvObject = &This->ISAXXMLReader_iface;
2904 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2906 return *ppvObject ? S_OK : E_NOINTERFACE;
2908 else
2910 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2911 return E_NOINTERFACE;
2914 IVBSAXXMLReader_AddRef( iface );
2916 return S_OK;
2919 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2921 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2922 TRACE("%p\n", This );
2923 return InterlockedIncrement( &This->ref );
2926 static ULONG WINAPI saxxmlreader_Release(
2927 IVBSAXXMLReader* iface)
2929 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2930 LONG ref;
2932 TRACE("%p\n", This );
2934 ref = InterlockedDecrement( &This->ref );
2935 if ( ref == 0 )
2937 int i;
2939 for (i = 0; i < SAXHandler_Last; i++)
2941 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2943 if (saxiface->handler)
2944 IUnknown_Release(saxiface->handler);
2946 if (saxiface->vbhandler)
2947 IUnknown_Release(saxiface->vbhandler);
2950 SysFreeString(This->xmldecl_version);
2951 free_bstr_pool(&This->pool);
2953 free(This);
2956 return ref;
2958 /*** IDispatch ***/
2959 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2961 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2962 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2965 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2966 IVBSAXXMLReader *iface,
2967 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2969 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2970 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2971 iTInfo, lcid, ppTInfo);
2974 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2975 IVBSAXXMLReader *iface,
2976 REFIID riid,
2977 LPOLESTR* rgszNames,
2978 UINT cNames,
2979 LCID lcid,
2980 DISPID* rgDispId)
2982 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2983 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2984 riid, rgszNames, cNames, lcid, rgDispId);
2987 static HRESULT WINAPI saxxmlreader_Invoke(
2988 IVBSAXXMLReader *iface,
2989 DISPID dispIdMember,
2990 REFIID riid,
2991 LCID lcid,
2992 WORD wFlags,
2993 DISPPARAMS* pDispParams,
2994 VARIANT* pVarResult,
2995 EXCEPINFO* pExcepInfo,
2996 UINT* puArgErr)
2998 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2999 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
3000 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3003 /*** IVBSAXXMLReader methods ***/
3004 static HRESULT WINAPI saxxmlreader_getFeature(
3005 IVBSAXXMLReader* iface,
3006 BSTR feature_name,
3007 VARIANT_BOOL *value)
3009 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3010 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3013 static HRESULT WINAPI saxxmlreader_putFeature(
3014 IVBSAXXMLReader* iface,
3015 BSTR feature_name,
3016 VARIANT_BOOL value)
3018 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3019 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3022 static HRESULT WINAPI saxxmlreader_getProperty(
3023 IVBSAXXMLReader* iface,
3024 BSTR prop,
3025 VARIANT *value)
3027 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3028 return internal_getProperty(This, prop, value, TRUE);
3031 static HRESULT WINAPI saxxmlreader_putProperty(
3032 IVBSAXXMLReader* iface,
3033 BSTR pProp,
3034 VARIANT value)
3036 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3037 return internal_putProperty(This, pProp, value, TRUE);
3040 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3041 IVBSAXXMLReader* iface,
3042 IVBSAXEntityResolver **resolver)
3044 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3045 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3048 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3049 IVBSAXXMLReader* iface,
3050 IVBSAXEntityResolver *resolver)
3052 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3053 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3056 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3057 IVBSAXXMLReader* iface,
3058 IVBSAXContentHandler **handler)
3060 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3061 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3064 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3065 IVBSAXXMLReader* iface,
3066 IVBSAXContentHandler *handler)
3068 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3069 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3072 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3073 IVBSAXXMLReader* iface,
3074 IVBSAXDTDHandler **handler)
3076 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3077 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3080 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3081 IVBSAXXMLReader* iface,
3082 IVBSAXDTDHandler *handler)
3084 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3085 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3088 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3089 IVBSAXXMLReader* iface,
3090 IVBSAXErrorHandler **handler)
3092 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3093 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3096 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3097 IVBSAXXMLReader* iface,
3098 IVBSAXErrorHandler *handler)
3100 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3101 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3104 static HRESULT WINAPI saxxmlreader_get_baseURL(
3105 IVBSAXXMLReader* iface,
3106 BSTR *pBaseUrl)
3108 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3110 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3111 return E_NOTIMPL;
3114 static HRESULT WINAPI saxxmlreader_put_baseURL(
3115 IVBSAXXMLReader* iface,
3116 BSTR pBaseUrl)
3118 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3119 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3122 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3123 IVBSAXXMLReader* iface,
3124 BSTR *pSecureBaseUrl)
3126 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3128 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3129 return E_NOTIMPL;
3132 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3133 IVBSAXXMLReader* iface,
3134 BSTR secureBaseUrl)
3136 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3137 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3140 static HRESULT WINAPI saxxmlreader_parse(
3141 IVBSAXXMLReader* iface,
3142 VARIANT varInput)
3144 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3145 return internal_parse(This, varInput, TRUE);
3148 static HRESULT WINAPI saxxmlreader_parseURL(
3149 IVBSAXXMLReader* iface,
3150 BSTR url)
3152 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3153 return internal_parseURL(This, url, TRUE);
3156 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3158 saxxmlreader_QueryInterface,
3159 saxxmlreader_AddRef,
3160 saxxmlreader_Release,
3161 saxxmlreader_GetTypeInfoCount,
3162 saxxmlreader_GetTypeInfo,
3163 saxxmlreader_GetIDsOfNames,
3164 saxxmlreader_Invoke,
3165 saxxmlreader_getFeature,
3166 saxxmlreader_putFeature,
3167 saxxmlreader_getProperty,
3168 saxxmlreader_putProperty,
3169 saxxmlreader_get_entityResolver,
3170 saxxmlreader_put_entityResolver,
3171 saxxmlreader_get_contentHandler,
3172 saxxmlreader_put_contentHandler,
3173 saxxmlreader_get_dtdHandler,
3174 saxxmlreader_put_dtdHandler,
3175 saxxmlreader_get_errorHandler,
3176 saxxmlreader_put_errorHandler,
3177 saxxmlreader_get_baseURL,
3178 saxxmlreader_put_baseURL,
3179 saxxmlreader_get_secureBaseURL,
3180 saxxmlreader_put_secureBaseURL,
3181 saxxmlreader_parse,
3182 saxxmlreader_parseURL
3185 /*** ISAXXMLReader interface ***/
3186 /*** IUnknown methods ***/
3187 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3189 saxreader *This = impl_from_ISAXXMLReader( iface );
3190 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3193 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3195 saxreader *This = impl_from_ISAXXMLReader( iface );
3196 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3199 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3201 saxreader *This = impl_from_ISAXXMLReader( iface );
3202 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3205 /*** ISAXXMLReader methods ***/
3206 static HRESULT WINAPI isaxxmlreader_getFeature(
3207 ISAXXMLReader* iface,
3208 const WCHAR *feature_name,
3209 VARIANT_BOOL *value)
3211 saxreader *This = impl_from_ISAXXMLReader( iface );
3212 saxreader_feature feature;
3214 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3216 feature = get_saxreader_feature(feature_name);
3218 if (This->version < MSXML4 && (feature == ExhaustiveErrors || feature == SchemaValidation))
3219 return E_INVALIDARG;
3221 if (feature == Namespaces ||
3222 feature == NamespacePrefixes ||
3223 feature == ExhaustiveErrors ||
3224 feature == SchemaValidation)
3225 return get_feature_value(This, feature, value);
3227 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3228 return E_NOTIMPL;
3231 static HRESULT WINAPI isaxxmlreader_putFeature(
3232 ISAXXMLReader* iface,
3233 const WCHAR *feature_name,
3234 VARIANT_BOOL value)
3236 saxreader *This = impl_from_ISAXXMLReader( iface );
3237 saxreader_feature feature;
3239 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3241 feature = get_saxreader_feature(feature_name);
3243 /* accepted cases */
3244 if ((feature == ExhaustiveErrors && value == VARIANT_FALSE) ||
3245 (feature == SchemaValidation && value == VARIANT_FALSE) ||
3246 feature == Namespaces ||
3247 feature == NamespacePrefixes)
3249 return set_feature_value(This, feature, value);
3252 if (feature == LexicalHandlerParEntities ||
3253 feature == ProhibitDTD ||
3254 feature == ExternalGeneralEntities ||
3255 feature == ExternalParameterEntities)
3257 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3258 return set_feature_value(This, feature, value);
3261 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3262 return E_NOTIMPL;
3265 static HRESULT WINAPI isaxxmlreader_getProperty(
3266 ISAXXMLReader* iface,
3267 const WCHAR *prop,
3268 VARIANT *value)
3270 saxreader *This = impl_from_ISAXXMLReader( iface );
3271 return internal_getProperty(This, prop, value, FALSE);
3274 static HRESULT WINAPI isaxxmlreader_putProperty(
3275 ISAXXMLReader* iface,
3276 const WCHAR *pProp,
3277 VARIANT value)
3279 saxreader *This = impl_from_ISAXXMLReader( iface );
3280 return internal_putProperty(This, pProp, value, FALSE);
3283 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3284 ISAXXMLReader* iface,
3285 ISAXEntityResolver **resolver)
3287 saxreader *This = impl_from_ISAXXMLReader( iface );
3288 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3291 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3292 ISAXXMLReader* iface,
3293 ISAXEntityResolver *resolver)
3295 saxreader *This = impl_from_ISAXXMLReader( iface );
3296 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3299 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3300 ISAXXMLReader* iface,
3301 ISAXContentHandler **handler)
3303 saxreader *This = impl_from_ISAXXMLReader( iface );
3304 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3307 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3308 ISAXXMLReader* iface,
3309 ISAXContentHandler *handler)
3311 saxreader *This = impl_from_ISAXXMLReader( iface );
3312 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3315 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3316 ISAXXMLReader* iface,
3317 ISAXDTDHandler **handler)
3319 saxreader *This = impl_from_ISAXXMLReader( iface );
3320 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3323 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3324 ISAXXMLReader* iface,
3325 ISAXDTDHandler *handler)
3327 saxreader *This = impl_from_ISAXXMLReader( iface );
3328 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3331 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3332 ISAXXMLReader* iface,
3333 ISAXErrorHandler **handler)
3335 saxreader *This = impl_from_ISAXXMLReader( iface );
3336 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3339 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3341 saxreader *This = impl_from_ISAXXMLReader( iface );
3342 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3345 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3346 ISAXXMLReader* iface,
3347 const WCHAR **base_url)
3349 saxreader *This = impl_from_ISAXXMLReader( iface );
3351 FIXME("(%p)->(%p) stub\n", This, base_url);
3352 return E_NOTIMPL;
3355 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3356 ISAXXMLReader* iface,
3357 const WCHAR *pBaseUrl)
3359 saxreader *This = impl_from_ISAXXMLReader( iface );
3361 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3362 return E_NOTIMPL;
3365 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3366 ISAXXMLReader* iface,
3367 const WCHAR **pSecureBaseUrl)
3369 saxreader *This = impl_from_ISAXXMLReader( iface );
3370 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3371 return E_NOTIMPL;
3374 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3375 ISAXXMLReader* iface,
3376 const WCHAR *secureBaseUrl)
3378 saxreader *This = impl_from_ISAXXMLReader( iface );
3380 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3381 return E_NOTIMPL;
3384 static HRESULT WINAPI isaxxmlreader_parse(
3385 ISAXXMLReader* iface,
3386 VARIANT varInput)
3388 saxreader *This = impl_from_ISAXXMLReader( iface );
3389 return internal_parse(This, varInput, FALSE);
3392 static HRESULT WINAPI isaxxmlreader_parseURL(
3393 ISAXXMLReader* iface,
3394 const WCHAR *url)
3396 saxreader *This = impl_from_ISAXXMLReader( iface );
3397 return internal_parseURL(This, url, FALSE);
3400 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3402 isaxxmlreader_QueryInterface,
3403 isaxxmlreader_AddRef,
3404 isaxxmlreader_Release,
3405 isaxxmlreader_getFeature,
3406 isaxxmlreader_putFeature,
3407 isaxxmlreader_getProperty,
3408 isaxxmlreader_putProperty,
3409 isaxxmlreader_getEntityResolver,
3410 isaxxmlreader_putEntityResolver,
3411 isaxxmlreader_getContentHandler,
3412 isaxxmlreader_putContentHandler,
3413 isaxxmlreader_getDTDHandler,
3414 isaxxmlreader_putDTDHandler,
3415 isaxxmlreader_getErrorHandler,
3416 isaxxmlreader_putErrorHandler,
3417 isaxxmlreader_getBaseURL,
3418 isaxxmlreader_putBaseURL,
3419 isaxxmlreader_getSecureBaseURL,
3420 isaxxmlreader_putSecureBaseURL,
3421 isaxxmlreader_parse,
3422 isaxxmlreader_parseURL
3425 static const tid_t saxreader_iface_tids[] = {
3426 IVBSAXXMLReader_tid,
3429 static dispex_static_data_t saxreader_dispex = {
3430 NULL,
3431 IVBSAXXMLReader_tid,
3432 NULL,
3433 saxreader_iface_tids
3436 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3438 saxreader *reader;
3440 TRACE("(%p)\n", ppObj);
3442 reader = malloc(sizeof(*reader));
3443 if( !reader )
3444 return E_OUTOFMEMORY;
3446 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3447 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3448 reader->ref = 1;
3449 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3450 reader->isParsing = FALSE;
3451 reader->xmldecl_version = NULL;
3452 reader->pool.pool = NULL;
3453 reader->pool.index = 0;
3454 reader->pool.len = 0;
3455 reader->features = Namespaces | NamespacePrefixes;
3456 reader->version = version;
3458 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3460 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3461 reader->sax.initialized = XML_SAX2_MAGIC;
3462 reader->sax.startDocument = libxmlStartDocument;
3463 reader->sax.endDocument = libxmlEndDocument;
3464 reader->sax.startElementNs = libxmlStartElementNS;
3465 reader->sax.endElementNs = libxmlEndElementNS;
3466 reader->sax.characters = libxmlCharacters;
3467 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3468 reader->sax.comment = libxmlComment;
3469 reader->sax.error = libxmlFatalError;
3470 reader->sax.fatalError = libxmlFatalError;
3471 reader->sax.cdataBlock = libxml_cdatablock;
3472 reader->sax.resolveEntity = libxmlresolveentity;
3474 *ppObj = &reader->IVBSAXXMLReader_iface;
3476 TRACE("returning iface %p\n", *ppObj);
3478 return S_OK;