win32u: Move NtUserTranslateMessage implementation from user32.
[wine.git] / dlls / msxml3 / saxreader.c
blob8d58ed1d94bf3afefbcd101f44d625ee9b407e78
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 = heap_alloc(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 ? heap_alloc(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 heap_free(element->ns);
502 heap_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 = heap_alloc(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 *realloc = heap_realloc(pool->pool, pool->len * 2 * sizeof(*realloc));
581 if (!realloc)
582 return FALSE;
584 pool->pool = realloc;
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 heap_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 = heap_alloc(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 heap_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 = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
1465 if(!attrs)
1467 free_attribute_values(locator);
1468 locator->attr_count = 0;
1469 return E_OUTOFMEMORY;
1471 locator->attributes = attrs;
1472 locator->attr_alloc_count = new_size;
1474 else
1476 attrs = locator->attributes;
1479 for (i = 0; i < nb_namespaces; i++)
1481 SysFreeString(attrs[nb_attributes+i].szLocalname);
1482 attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
1484 attrs[nb_attributes+i].szURI = locator->namespaceUri;
1486 SysFreeString(attrs[nb_attributes+i].szValue);
1487 attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
1489 SysFreeString(attrs[nb_attributes+i].szQName);
1490 if(!xmlNamespaces[2*i])
1491 attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
1492 else
1493 attrs[nb_attributes+i].szQName = QName_from_xmlChar(xmlns, xmlNamespaces[2*i]);
1496 for (i = 0; i < nb_attributes; i++)
1498 static const xmlChar xmlA[] = "xml";
1500 if (xmlStrEqual(xmlAttributes[i*5+1], xmlA))
1501 attrs[i].szURI = bstr_from_xmlChar(xmlAttributes[i*5+2]);
1502 else
1503 /* that's an important feature to keep same uri pointer for every reported attribute */
1504 attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
1506 SysFreeString(attrs[i].szLocalname);
1507 attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
1509 SysFreeString(attrs[i].szValue);
1510 attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
1512 SysFreeString(attrs[i].szQName);
1513 attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
1516 return S_OK;
1519 /*** LibXML callbacks ***/
1520 static void libxmlStartDocument(void *ctx)
1522 saxlocator *This = ctx;
1523 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1524 HRESULT hr;
1526 if (This->saxreader->version >= MSXML4)
1528 const xmlChar *p = This->pParserCtxt->input->cur-1;
1529 update_position(This, FALSE);
1530 while(p>This->pParserCtxt->input->base && *p!='>')
1532 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1533 This->line--;
1534 p--;
1536 This->column = 0;
1537 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1538 This->column++;
1541 /* store version value, declaration has to contain version attribute */
1542 if (This->pParserCtxt->standalone != -1)
1544 SysFreeString(This->saxreader->xmldecl_version);
1545 This->saxreader->xmldecl_version = bstr_from_xmlChar(This->pParserCtxt->version);
1548 if (saxreader_has_handler(This, SAXContentHandler))
1550 if(This->vbInterface)
1551 hr = IVBSAXContentHandler_startDocument(handler->vbhandler);
1552 else
1553 hr = ISAXContentHandler_startDocument(handler->handler);
1555 if (sax_callback_failed(This, hr))
1556 format_error_message_from_id(This, hr);
1560 static void libxmlEndDocument(void *ctx)
1562 saxlocator *This = ctx;
1563 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1564 HRESULT hr;
1566 if (This->saxreader->version >= MSXML4) {
1567 update_position(This, FALSE);
1568 if(This->column > 1)
1569 This->line++;
1570 This->column = 0;
1571 } else {
1572 This->column = 0;
1573 This->line = 0;
1576 if(This->ret != S_OK) return;
1578 if (saxreader_has_handler(This, SAXContentHandler))
1580 if(This->vbInterface)
1581 hr = IVBSAXContentHandler_endDocument(handler->vbhandler);
1582 else
1583 hr = ISAXContentHandler_endDocument(handler->handler);
1585 if (sax_callback_failed(This, hr))
1586 format_error_message_from_id(This, hr);
1590 static void libxmlStartElementNS(
1591 void *ctx,
1592 const xmlChar *localname,
1593 const xmlChar *prefix,
1594 const xmlChar *URI,
1595 int nb_namespaces,
1596 const xmlChar **namespaces,
1597 int nb_attributes,
1598 int nb_defaulted,
1599 const xmlChar **attributes)
1601 saxlocator *This = ctx;
1602 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1603 element_entry *element;
1604 HRESULT hr = S_OK;
1605 BSTR uri;
1607 update_position(This, TRUE);
1608 if(*(This->pParserCtxt->input->cur) == '/')
1609 This->column++;
1610 if(This->saxreader->version < MSXML4)
1611 This->column++;
1613 element = alloc_element_entry(localname, prefix, nb_namespaces, namespaces);
1614 push_element_ns(This, element);
1616 if (is_namespaces_enabled(This->saxreader))
1618 int i;
1620 for (i = 0; i < nb_namespaces && saxreader_has_handler(This, SAXContentHandler); i++)
1622 if (This->vbInterface)
1623 hr = IVBSAXContentHandler_startPrefixMapping(
1624 handler->vbhandler,
1625 &element->ns[i].prefix,
1626 &element->ns[i].uri);
1627 else
1628 hr = ISAXContentHandler_startPrefixMapping(
1629 handler->handler,
1630 element->ns[i].prefix,
1631 SysStringLen(element->ns[i].prefix),
1632 element->ns[i].uri,
1633 SysStringLen(element->ns[i].uri));
1635 if (sax_callback_failed(This, hr))
1637 format_error_message_from_id(This, hr);
1638 return;
1643 uri = find_element_uri(This, URI);
1644 hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
1645 if (hr == S_OK && saxreader_has_handler(This, SAXContentHandler))
1647 BSTR local;
1649 if (is_namespaces_enabled(This->saxreader))
1650 local = element->local;
1651 else
1652 uri = local = NULL;
1654 if (This->vbInterface)
1655 hr = IVBSAXContentHandler_startElement(handler->vbhandler,
1656 &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
1657 else
1658 hr = ISAXContentHandler_startElement(handler->handler,
1659 uri ? uri : &empty_str, SysStringLen(uri),
1660 local ? local : &empty_str, SysStringLen(local),
1661 element->qname, SysStringLen(element->qname),
1662 &This->ISAXAttributes_iface);
1664 if (sax_callback_failed(This, hr))
1665 format_error_message_from_id(This, hr);
1669 static void libxmlEndElementNS(
1670 void *ctx,
1671 const xmlChar *localname,
1672 const xmlChar *prefix,
1673 const xmlChar *URI)
1675 saxlocator *This = ctx;
1676 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1677 element_entry *element;
1678 const xmlChar *p;
1679 BSTR uri, local;
1680 HRESULT hr;
1682 update_position(This, FALSE);
1683 p = This->pParserCtxt->input->cur;
1685 if (This->saxreader->version >= MSXML4)
1687 p--;
1688 while(p>This->pParserCtxt->input->base && *p!='>')
1690 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1691 This->line--;
1692 p--;
1695 else if(*(p-1)!='>' || *(p-2)!='/')
1697 p--;
1698 while(p-2>=This->pParserCtxt->input->base
1699 && *(p-2)!='<' && *(p-1)!='/')
1701 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1702 This->line--;
1703 p--;
1706 This->column = 0;
1707 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1708 This->column++;
1710 uri = find_element_uri(This, URI);
1711 element = pop_element_ns(This);
1713 if (!saxreader_has_handler(This, SAXContentHandler))
1715 free_attribute_values(This);
1716 This->attr_count = 0;
1717 free_element_entry(element);
1718 return;
1721 if (is_namespaces_enabled(This->saxreader))
1722 local = element->local;
1723 else
1724 uri = local = NULL;
1726 if (This->vbInterface)
1727 hr = IVBSAXContentHandler_endElement(
1728 handler->vbhandler,
1729 &uri, &local, &element->qname);
1730 else
1731 hr = ISAXContentHandler_endElement(
1732 handler->handler,
1733 uri ? uri : &empty_str, SysStringLen(uri),
1734 local ? local : &empty_str, SysStringLen(local),
1735 element->qname, SysStringLen(element->qname));
1737 free_attribute_values(This);
1738 This->attr_count = 0;
1740 if (sax_callback_failed(This, hr))
1742 format_error_message_from_id(This, hr);
1743 free_element_entry(element);
1744 return;
1747 if (is_namespaces_enabled(This->saxreader))
1749 int i = -1;
1750 while (iterate_endprefix_index(This, element, &i) && saxreader_has_handler(This, SAXContentHandler))
1752 if (This->vbInterface)
1753 hr = IVBSAXContentHandler_endPrefixMapping(
1754 handler->vbhandler, &element->ns[i].prefix);
1755 else
1756 hr = ISAXContentHandler_endPrefixMapping(
1757 handler->handler, element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
1759 if (sax_callback_failed(This, hr)) break;
1762 if (sax_callback_failed(This, hr))
1763 format_error_message_from_id(This, hr);
1766 free_element_entry(element);
1769 static void libxmlCharacters(
1770 void *ctx,
1771 const xmlChar *ch,
1772 int len)
1774 saxlocator *This = ctx;
1775 BSTR Chars;
1776 HRESULT hr;
1777 xmlChar *cur, *end;
1778 BOOL lastEvent = FALSE;
1780 if (!saxreader_has_handler(This, SAXContentHandler)) return;
1782 update_position(This, FALSE);
1783 cur = (xmlChar*)This->pParserCtxt->input->cur;
1784 while(cur>=This->pParserCtxt->input->base && *cur!='>')
1786 if(*cur=='\n' || (*cur=='\r' && *(cur+1)!='\n'))
1787 This->line--;
1788 cur--;
1790 This->column = 1;
1791 for(; cur>=This->pParserCtxt->input->base && *cur!='\n' && *cur!='\r'; cur--)
1792 This->column++;
1794 cur = (xmlChar*)ch;
1795 if(*(ch-1)=='\r') cur--;
1796 end = cur;
1798 while(1)
1800 while(end-ch<len && *end!='\r') end++;
1801 if(end-ch==len)
1803 lastEvent = TRUE;
1805 else
1807 *end = '\n';
1808 end++;
1811 if (This->saxreader->version >= MSXML4)
1813 xmlChar *p;
1815 for(p=cur; p!=end; p++)
1817 if(*p=='\n')
1819 This->line++;
1820 This->column = 1;
1822 else
1824 This->column++;
1828 if(!lastEvent)
1829 This->column = 0;
1832 Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
1833 hr = saxreader_saxcharacters(This, Chars);
1835 if (sax_callback_failed(This, hr))
1837 format_error_message_from_id(This, hr);
1838 return;
1841 if (This->saxreader->version < MSXML4)
1842 This->column += end-cur;
1844 if(lastEvent)
1845 break;
1847 *(end-1) = '\r';
1848 if(*end == '\n')
1850 end++;
1851 This->column++;
1853 cur = end;
1855 if(end-ch == len) break;
1859 static void libxmlSetDocumentLocator(
1860 void *ctx,
1861 xmlSAXLocatorPtr loc)
1863 saxlocator *This = ctx;
1864 struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
1865 HRESULT hr = S_OK;
1867 if (saxreader_has_handler(This, SAXContentHandler))
1869 if(This->vbInterface)
1870 hr = IVBSAXContentHandler_putref_documentLocator(handler->vbhandler,
1871 &This->IVBSAXLocator_iface);
1872 else
1873 hr = ISAXContentHandler_putDocumentLocator(handler->handler, &This->ISAXLocator_iface);
1876 if(FAILED(hr))
1877 format_error_message_from_id(This, hr);
1880 static void libxmlComment(void *ctx, const xmlChar *value)
1882 saxlocator *This = ctx;
1883 struct saxlexicalhandler_iface *handler = saxreader_get_lexicalhandler(This->saxreader);
1884 BSTR bValue;
1885 HRESULT hr;
1886 const xmlChar *p = This->pParserCtxt->input->cur;
1888 update_position(This, FALSE);
1889 while(p-4>=This->pParserCtxt->input->base
1890 && memcmp(p-4, "<!--", sizeof(char[4])))
1892 if(*p=='\n' || (*p=='\r' && *(p+1)!='\n'))
1893 This->line--;
1894 p--;
1897 This->column = 0;
1898 for(; p>=This->pParserCtxt->input->base && *p!='\n' && *p!='\r'; p--)
1899 This->column++;
1901 if (!saxreader_has_handler(This, SAXLexicalHandler)) return;
1903 bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
1905 if (This->vbInterface)
1906 hr = IVBSAXLexicalHandler_comment(handler->vbhandler, &bValue);
1907 else
1908 hr = ISAXLexicalHandler_comment(handler->handler, bValue, SysStringLen(bValue));
1910 if(FAILED(hr))
1911 format_error_message_from_id(This, hr);
1914 static void WINAPIV libxmlFatalError(void *ctx, const char *msg, ...)
1916 saxlocator *This = ctx;
1917 struct saxerrorhandler_iface *handler = saxreader_get_errorhandler(This->saxreader);
1918 char message[1024];
1919 WCHAR *error;
1920 DWORD len;
1921 va_list args;
1923 if(This->ret != S_OK) {
1924 xmlStopParser(This->pParserCtxt);
1925 return;
1928 va_start(args, msg);
1929 vsprintf(message, msg, args);
1930 va_end(args);
1932 len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1933 error = heap_alloc(sizeof(WCHAR)*len);
1934 if(error)
1936 MultiByteToWideChar(CP_UNIXCP, 0, message, -1, error, len);
1937 TRACE("fatal error for %p: %s\n", This, debugstr_w(error));
1940 if (!saxreader_has_handler(This, SAXErrorHandler))
1942 xmlStopParser(This->pParserCtxt);
1943 This->ret = E_FAIL;
1944 heap_free(error);
1945 return;
1948 FIXME("Error handling is not compatible.\n");
1950 if(This->vbInterface)
1952 BSTR bstrError = SysAllocString(error);
1953 IVBSAXErrorHandler_fatalError(handler->vbhandler, &This->IVBSAXLocator_iface,
1954 &bstrError, E_FAIL);
1955 SysFreeString(bstrError);
1957 else
1958 ISAXErrorHandler_fatalError(handler->handler, &This->ISAXLocator_iface, error, E_FAIL);
1960 heap_free(error);
1962 xmlStopParser(This->pParserCtxt);
1963 This->ret = E_FAIL;
1966 /* The only reason this helper exists is that CDATA section are reported by chunks,
1967 newlines are used as delimiter. More than that, reader even alters input data before reporting.
1969 This helper should be called for substring with trailing newlines.
1971 static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
1973 BSTR bstr = bstr_from_xmlCharN(str, len), ret;
1974 WCHAR *ptr;
1976 len = SysStringLen(bstr);
1977 ptr = bstr + len - 1;
1978 while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
1979 ptr--;
1981 while (*++ptr)
1983 /* replace returns as:
1985 - "\r<char>" -> "\n<char>"
1986 - "\r\r" -> "\r"
1987 - "\r\n" -> "\n"
1989 if (*ptr == '\r')
1991 if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
1993 /* shift tail */
1994 memmove(ptr, ptr+1, len-- - (ptr-bstr));
1996 else
1997 *ptr = '\n';
2001 ret = SysAllocStringLen(bstr, len);
2002 SysFreeString(bstr);
2003 return ret;
2006 static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
2008 const xmlChar *start, *end;
2009 saxlocator *locator = ctx;
2010 struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
2011 HRESULT hr = S_OK;
2012 BSTR chars;
2013 int i;
2015 update_position(locator, FALSE);
2016 if (saxreader_has_handler(locator, SAXLexicalHandler))
2018 if (locator->vbInterface)
2019 hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
2020 else
2021 hr = ISAXLexicalHandler_startCDATA(lexical->handler);
2024 if(FAILED(hr))
2026 format_error_message_from_id(locator, hr);
2027 return;
2030 start = value;
2031 end = NULL;
2032 i = 0;
2034 while (i < len)
2036 /* scan for newlines */
2037 if (value[i] == '\r' || value[i] == '\n')
2039 /* skip newlines/linefeeds */
2040 while (i < len)
2042 if (value[i] != '\r' && value[i] != '\n') break;
2043 i++;
2045 end = &value[i];
2047 /* report */
2048 chars = saxreader_get_cdata_chunk(start, end-start);
2049 TRACE("(chunk %s)\n", debugstr_w(chars));
2050 hr = saxreader_saxcharacters(locator, chars);
2051 SysFreeString(chars);
2053 start = &value[i];
2054 end = NULL;
2056 i++;
2057 locator->column++;
2060 /* no newline chars (or last chunk) report as a whole */
2061 if (!end && start == value)
2063 /* report */
2064 chars = bstr_from_xmlCharN(start, len-(start-value));
2065 TRACE("(%s)\n", debugstr_w(chars));
2066 hr = saxreader_saxcharacters(locator, chars);
2067 SysFreeString(chars);
2070 if (saxreader_has_handler(locator, SAXLexicalHandler))
2072 if (locator->vbInterface)
2073 hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
2074 else
2075 hr = ISAXLexicalHandler_endCDATA(lexical->handler);
2078 if(FAILED(hr))
2079 format_error_message_from_id(locator, hr);
2082 static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
2084 FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
2085 return xmlSAX2ResolveEntity(ctx, publicid, systemid);
2088 /*** IVBSAXLocator interface ***/
2089 /*** IUnknown methods ***/
2090 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
2092 saxlocator *This = impl_from_IVBSAXLocator( iface );
2094 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
2096 *ppvObject = NULL;
2098 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2099 IsEqualGUID( riid, &IID_IDispatch) ||
2100 IsEqualGUID( riid, &IID_IVBSAXLocator ))
2102 *ppvObject = iface;
2104 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2106 *ppvObject = &This->IVBSAXAttributes_iface;
2108 else
2110 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2111 return E_NOINTERFACE;
2114 IVBSAXLocator_AddRef( iface );
2116 return S_OK;
2119 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
2121 saxlocator *This = impl_from_IVBSAXLocator( iface );
2122 TRACE("%p\n", This );
2123 return ISAXLocator_AddRef(&This->ISAXLocator_iface);
2126 static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
2128 saxlocator *This = impl_from_IVBSAXLocator( iface );
2129 return ISAXLocator_Release(&This->ISAXLocator_iface);
2132 /*** IDispatch methods ***/
2133 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
2135 saxlocator *This = impl_from_IVBSAXLocator( iface );
2137 TRACE("(%p)->(%p)\n", This, pctinfo);
2139 *pctinfo = 1;
2141 return S_OK;
2144 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
2145 IVBSAXLocator *iface,
2146 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2148 TRACE("%p, %u, %lx, %p.\n", iface, iTInfo, lcid, ppTInfo);
2150 return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
2153 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
2154 IVBSAXLocator *iface,
2155 REFIID riid,
2156 LPOLESTR* rgszNames,
2157 UINT cNames,
2158 LCID lcid,
2159 DISPID* rgDispId)
2161 ITypeInfo *typeinfo;
2162 HRESULT hr;
2164 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface, debugstr_guid(riid), rgszNames, cNames,
2165 lcid, rgDispId);
2167 if(!rgszNames || cNames == 0 || !rgDispId)
2168 return E_INVALIDARG;
2170 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2171 if(SUCCEEDED(hr))
2173 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2174 ITypeInfo_Release(typeinfo);
2177 return hr;
2180 static HRESULT WINAPI ivbsaxlocator_Invoke(
2181 IVBSAXLocator *iface,
2182 DISPID dispIdMember,
2183 REFIID riid,
2184 LCID lcid,
2185 WORD wFlags,
2186 DISPPARAMS* pDispParams,
2187 VARIANT* pVarResult,
2188 EXCEPINFO* pExcepInfo,
2189 UINT* puArgErr)
2191 ITypeInfo *typeinfo;
2192 HRESULT hr;
2194 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface, dispIdMember, debugstr_guid(riid),
2195 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2197 hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
2198 if(SUCCEEDED(hr))
2200 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2201 ITypeInfo_Release(typeinfo);
2204 return hr;
2207 /*** IVBSAXLocator methods ***/
2208 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
2209 IVBSAXLocator* iface,
2210 int *pnColumn)
2212 saxlocator *This = impl_from_IVBSAXLocator( iface );
2213 return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
2216 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
2217 IVBSAXLocator* iface,
2218 int *pnLine)
2220 saxlocator *This = impl_from_IVBSAXLocator( iface );
2221 return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
2224 static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
2226 saxlocator *This = impl_from_IVBSAXLocator( iface );
2227 const WCHAR *publicidW;
2228 HRESULT hr;
2230 TRACE("(%p)->(%p)\n", This, ret);
2232 if (!ret)
2233 return E_POINTER;
2235 *ret = NULL;
2236 hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
2237 if (FAILED(hr))
2238 return hr;
2240 return return_bstr(publicidW, ret);
2243 static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
2245 saxlocator *This = impl_from_IVBSAXLocator( iface );
2246 const WCHAR *systemidW;
2247 HRESULT hr;
2249 TRACE("(%p)->(%p)\n", This, ret);
2251 if (!ret)
2252 return E_POINTER;
2254 *ret = NULL;
2255 hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
2256 if (FAILED(hr))
2257 return hr;
2259 return return_bstr(systemidW, ret);
2262 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
2264 ivbsaxlocator_QueryInterface,
2265 ivbsaxlocator_AddRef,
2266 ivbsaxlocator_Release,
2267 ivbsaxlocator_GetTypeInfoCount,
2268 ivbsaxlocator_GetTypeInfo,
2269 ivbsaxlocator_GetIDsOfNames,
2270 ivbsaxlocator_Invoke,
2271 ivbsaxlocator_get_columnNumber,
2272 ivbsaxlocator_get_lineNumber,
2273 ivbsaxlocator_get_publicId,
2274 ivbsaxlocator_get_systemId
2277 /*** ISAXLocator interface ***/
2278 /*** IUnknown methods ***/
2279 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
2281 saxlocator *This = impl_from_ISAXLocator( iface );
2283 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2285 *ppvObject = NULL;
2287 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2288 IsEqualGUID( riid, &IID_ISAXLocator ))
2290 *ppvObject = iface;
2292 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2294 *ppvObject = &This->ISAXAttributes_iface;
2296 else
2298 WARN("interface %s not implemented\n", debugstr_guid(riid));
2299 return E_NOINTERFACE;
2302 ISAXLocator_AddRef( iface );
2304 return S_OK;
2307 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
2309 saxlocator *This = impl_from_ISAXLocator( iface );
2310 ULONG ref = InterlockedIncrement( &This->ref );
2311 TRACE("%p, refcount %lu.\n", iface, ref);
2312 return ref;
2315 static ULONG WINAPI isaxlocator_Release(
2316 ISAXLocator* iface)
2318 saxlocator *This = impl_from_ISAXLocator( iface );
2319 ULONG ref = InterlockedDecrement( &This->ref );
2321 TRACE("%p, refcount %ld.\n", iface, ref );
2323 if (!ref)
2325 element_entry *element, *element2;
2326 int index;
2328 SysFreeString(This->publicId);
2329 SysFreeString(This->systemId);
2330 SysFreeString(This->namespaceUri);
2332 for(index = 0; index < This->attr_alloc_count; index++)
2334 SysFreeString(This->attributes[index].szLocalname);
2335 SysFreeString(This->attributes[index].szValue);
2336 SysFreeString(This->attributes[index].szQName);
2338 heap_free(This->attributes);
2340 /* element stack */
2341 LIST_FOR_EACH_ENTRY_SAFE(element, element2, &This->elements, element_entry, entry)
2343 list_remove(&element->entry);
2344 free_element_entry(element);
2347 ISAXXMLReader_Release(&This->saxreader->ISAXXMLReader_iface);
2348 heap_free( This );
2351 return ref;
2354 /*** ISAXLocator methods ***/
2355 static HRESULT WINAPI isaxlocator_getColumnNumber(
2356 ISAXLocator* iface,
2357 int *pnColumn)
2359 saxlocator *This = impl_from_ISAXLocator( iface );
2361 *pnColumn = This->column;
2362 return S_OK;
2365 static HRESULT WINAPI isaxlocator_getLineNumber(
2366 ISAXLocator* iface,
2367 int *pnLine)
2369 saxlocator *This = impl_from_ISAXLocator( iface );
2371 *pnLine = This->line;
2372 return S_OK;
2375 static HRESULT WINAPI isaxlocator_getPublicId(
2376 ISAXLocator* iface,
2377 const WCHAR ** ppwchPublicId)
2379 BSTR publicId;
2380 saxlocator *This = impl_from_ISAXLocator( iface );
2382 SysFreeString(This->publicId);
2384 publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
2385 if(SysStringLen(publicId))
2386 This->publicId = publicId;
2387 else
2389 SysFreeString(publicId);
2390 This->publicId = NULL;
2393 *ppwchPublicId = This->publicId;
2394 return S_OK;
2397 static HRESULT WINAPI isaxlocator_getSystemId(
2398 ISAXLocator* iface,
2399 const WCHAR ** ppwchSystemId)
2401 BSTR systemId;
2402 saxlocator *This = impl_from_ISAXLocator( iface );
2404 SysFreeString(This->systemId);
2406 systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
2407 if(SysStringLen(systemId))
2408 This->systemId = systemId;
2409 else
2411 SysFreeString(systemId);
2412 This->systemId = NULL;
2415 *ppwchSystemId = This->systemId;
2416 return S_OK;
2419 static const struct ISAXLocatorVtbl SAXLocatorVtbl =
2421 isaxlocator_QueryInterface,
2422 isaxlocator_AddRef,
2423 isaxlocator_Release,
2424 isaxlocator_getColumnNumber,
2425 isaxlocator_getLineNumber,
2426 isaxlocator_getPublicId,
2427 isaxlocator_getSystemId
2430 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
2432 static const WCHAR w3xmlns[] = { 'h','t','t','p',':','/','/', 'w','w','w','.','w','3','.',
2433 'o','r','g','/','2','0','0','0','/','x','m','l','n','s','/',0 };
2435 saxlocator *locator;
2437 locator = heap_alloc( sizeof (*locator) );
2438 if( !locator )
2439 return E_OUTOFMEMORY;
2441 locator->IVBSAXLocator_iface.lpVtbl = &VBSAXLocatorVtbl;
2442 locator->ISAXLocator_iface.lpVtbl = &SAXLocatorVtbl;
2443 locator->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl;
2444 locator->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl;
2445 locator->ref = 1;
2446 locator->vbInterface = vbInterface;
2448 locator->saxreader = reader;
2449 ISAXXMLReader_AddRef(&reader->ISAXXMLReader_iface);
2451 locator->pParserCtxt = NULL;
2452 locator->publicId = NULL;
2453 locator->systemId = NULL;
2454 locator->line = reader->version < MSXML4 ? 0 : 1;
2455 locator->column = 0;
2456 locator->ret = S_OK;
2457 if (locator->saxreader->version >= MSXML6)
2458 locator->namespaceUri = SysAllocString(w3xmlns);
2459 else
2460 locator->namespaceUri = SysAllocStringLen(NULL, 0);
2461 if(!locator->namespaceUri)
2463 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2464 heap_free(locator);
2465 return E_OUTOFMEMORY;
2468 locator->attr_alloc_count = 8;
2469 locator->attr_count = 0;
2470 locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
2471 if(!locator->attributes)
2473 ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
2474 SysFreeString(locator->namespaceUri);
2475 heap_free(locator);
2476 return E_OUTOFMEMORY;
2479 list_init(&locator->elements);
2481 *ppsaxlocator = locator;
2483 TRACE("returning %p\n", *ppsaxlocator);
2485 return S_OK;
2488 /*** SAXXMLReader internal functions ***/
2489 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
2491 xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;
2492 xmlChar *enc_name = NULL;
2493 saxlocator *locator;
2494 HRESULT hr;
2496 TRACE("(%p)->(%p %d)\n", This, buffer, size);
2498 hr = SAXLocator_create(This, &locator, vbInterface);
2499 if (FAILED(hr))
2500 return hr;
2502 if (size >= 4)
2504 const unsigned char *buff = (unsigned char*)buffer;
2506 encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4);
2507 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2508 TRACE("detected encoding: %s\n", enc_name);
2509 /* skip BOM, parser won't switch encodings and so won't skip it on its own */
2510 if ((encoding == XML_CHAR_ENCODING_UTF8) &&
2511 buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF)
2513 buffer += 3;
2514 size -= 3;
2518 /* if libxml2 detection failed try to guess */
2519 if (encoding == XML_CHAR_ENCODING_NONE)
2521 const WCHAR *ptr = (WCHAR*)buffer;
2522 /* an xml declaration with optional encoding will still be handled by the parser */
2523 if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
2525 enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
2526 encoding = XML_CHAR_ENCODING_UTF16LE;
2529 else if (encoding == XML_CHAR_ENCODING_UTF8)
2530 enc_name = (xmlChar*)xmlGetCharEncodingName(encoding);
2531 else
2532 enc_name = NULL;
2534 locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
2535 if (!locator->pParserCtxt)
2537 ISAXLocator_Release(&locator->ISAXLocator_iface);
2538 return E_FAIL;
2541 if (enc_name)
2543 locator->pParserCtxt->encoding = xmlStrdup(enc_name);
2544 if (encoding == XML_CHAR_ENCODING_UTF16LE) {
2545 TRACE("switching to %s\n", enc_name);
2546 xmlSwitchEncoding(locator->pParserCtxt, encoding);
2550 xmlFree(locator->pParserCtxt->sax);
2551 locator->pParserCtxt->sax = &locator->saxreader->sax;
2552 locator->pParserCtxt->userData = locator;
2554 This->isParsing = TRUE;
2555 if(xmlParseDocument(locator->pParserCtxt) == -1 && locator->ret == S_OK)
2556 hr = E_FAIL;
2557 else
2558 hr = locator->ret;
2559 This->isParsing = FALSE;
2561 if(locator->pParserCtxt)
2563 locator->pParserCtxt->sax = NULL;
2564 xmlFreeParserCtxt(locator->pParserCtxt);
2565 locator->pParserCtxt = NULL;
2568 ISAXLocator_Release(&locator->ISAXLocator_iface);
2569 return hr;
2572 static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream, BOOL vbInterface)
2574 saxlocator *locator;
2575 HRESULT hr;
2576 ULONG dataRead;
2577 char data[2048];
2578 int ret;
2580 dataRead = 0;
2581 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2582 if(FAILED(hr)) return hr;
2584 hr = SAXLocator_create(This, &locator, vbInterface);
2585 if(FAILED(hr)) return hr;
2587 locator->pParserCtxt = xmlCreatePushParserCtxt(
2588 &locator->saxreader->sax, locator,
2589 data, dataRead, NULL);
2590 if(!locator->pParserCtxt)
2592 ISAXLocator_Release(&locator->ISAXLocator_iface);
2593 return E_FAIL;
2596 This->isParsing = TRUE;
2598 do {
2599 dataRead = 0;
2600 hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
2601 if (FAILED(hr) || !dataRead) break;
2603 ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
2604 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2605 }while(hr == S_OK);
2607 if(SUCCEEDED(hr))
2609 ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
2610 hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
2614 This->isParsing = FALSE;
2616 xmlFreeParserCtxt(locator->pParserCtxt);
2617 locator->pParserCtxt = NULL;
2618 ISAXLocator_Release(&locator->ISAXLocator_iface);
2619 return hr;
2622 static HRESULT internal_parse(
2623 saxreader* This,
2624 VARIANT varInput,
2625 BOOL vbInterface)
2627 HRESULT hr;
2629 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
2631 /* Dispose of the BSTRs in the pool from a prior run, if any. */
2632 free_bstr_pool(&This->pool);
2634 switch(V_VT(&varInput))
2636 case VT_BSTR:
2637 case VT_BSTR|VT_BYREF:
2639 BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
2640 hr = internal_parseBuffer(This, (const char*)str, lstrlenW(str)*sizeof(WCHAR), vbInterface);
2641 break;
2643 case VT_ARRAY|VT_UI1: {
2644 void *pSAData;
2645 LONG lBound, uBound;
2646 ULONG dataRead;
2648 hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2649 if(hr != S_OK) break;
2650 hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2651 if(hr != S_OK) break;
2652 dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2653 hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2654 if(hr != S_OK) break;
2655 hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2656 SafeArrayUnaccessData(V_ARRAY(&varInput));
2657 break;
2659 case VT_UNKNOWN:
2660 case VT_DISPATCH: {
2661 ISequentialStream *stream = NULL;
2662 IXMLDOMDocument *xmlDoc;
2664 if (!V_UNKNOWN(&varInput))
2665 return E_INVALIDARG;
2667 if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2668 &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2670 BSTR bstrData;
2672 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2673 hr = internal_parseBuffer(This, (const char*)bstrData,
2674 SysStringByteLen(bstrData), vbInterface);
2675 IXMLDOMDocument_Release(xmlDoc);
2676 SysFreeString(bstrData);
2677 break;
2680 /* try base interface first */
2681 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
2682 if (!stream)
2683 /* this should never happen if IStream is implemented properly, but just in case */
2684 IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
2686 if(stream)
2688 hr = internal_parseStream(This, stream, vbInterface);
2689 ISequentialStream_Release(stream);
2691 else
2693 WARN("IUnknown* input doesn't support any of expected interfaces\n");
2694 hr = E_INVALIDARG;
2697 break;
2699 default:
2700 WARN("vt %d not implemented\n", V_VT(&varInput));
2701 hr = E_INVALIDARG;
2704 return hr;
2707 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2709 saxreader *This = obj;
2711 return internal_parseBuffer(This, ptr, len, TRUE);
2714 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2716 saxreader *This = obj;
2718 return internal_parseBuffer(This, ptr, len, FALSE);
2721 static HRESULT internal_parseURL(saxreader *reader, const WCHAR *url, BOOL vbInterface)
2723 IMoniker *mon;
2724 bsc_t *bsc;
2725 HRESULT hr;
2727 TRACE("%p, %s.\n", reader, debugstr_w(url));
2729 if (!url && reader->version < MSXML4)
2730 return E_INVALIDARG;
2732 hr = create_moniker_from_url(url, &mon);
2733 if(FAILED(hr))
2734 return hr;
2736 if(vbInterface) hr = bind_url(mon, internal_vbonDataAvailable, reader, &bsc);
2737 else hr = bind_url(mon, internal_onDataAvailable, reader, &bsc);
2738 IMoniker_Release(mon);
2740 if(FAILED(hr))
2741 return hr;
2743 return detach_bsc(bsc);
2746 static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
2748 const IID *riid;
2750 if (V_VT(v) == VT_EMPTY)
2751 return saxreader_put_handler(This, type, NULL, vb);
2753 switch (type)
2755 case SAXDeclHandler:
2756 riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
2757 break;
2758 case SAXLexicalHandler:
2759 riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
2760 break;
2761 default:
2762 ERR("wrong handler type %d\n", type);
2763 return E_FAIL;
2766 switch (V_VT(v))
2768 case VT_DISPATCH:
2769 case VT_UNKNOWN:
2771 IUnknown *handler = NULL;
2773 if (V_UNKNOWN(v))
2775 HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
2776 if (FAILED(hr)) return hr;
2779 saxreader_put_handler(This, type, handler, vb);
2780 if (handler) IUnknown_Release(handler);
2781 break;
2783 default:
2784 ERR("value type %d not supported\n", V_VT(v));
2785 return E_INVALIDARG;
2788 return S_OK;
2791 static HRESULT internal_putProperty(
2792 saxreader* This,
2793 const WCHAR *prop,
2794 VARIANT value,
2795 BOOL vbInterface)
2797 VARIANT *v;
2799 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
2801 if (This->isParsing) return E_FAIL;
2803 v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
2804 if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
2805 return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
2807 if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
2808 return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
2810 if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
2812 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2813 FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
2814 return E_NOTIMPL;
2817 if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
2819 if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
2820 FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
2821 return E_NOTIMPL;
2824 FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
2826 if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
2827 return E_NOTIMPL;
2829 if(!memcmp(prop, PropertyDomNodeW, sizeof(PropertyDomNodeW)))
2830 return E_FAIL;
2832 if(!memcmp(prop, PropertyInputSourceW, sizeof(PropertyInputSourceW)))
2833 return E_NOTIMPL;
2835 if(!memcmp(prop, PropertySchemaDeclHandlerW, sizeof(PropertySchemaDeclHandlerW)))
2836 return E_NOTIMPL;
2838 if(!memcmp(prop, PropertyXMLDeclEncodingW, sizeof(PropertyXMLDeclEncodingW)))
2839 return E_FAIL;
2841 if(!memcmp(prop, PropertyXMLDeclStandaloneW, sizeof(PropertyXMLDeclStandaloneW)))
2842 return E_FAIL;
2844 if(!memcmp(prop, PropertyXMLDeclVersionW, sizeof(PropertyXMLDeclVersionW)))
2845 return E_FAIL;
2847 return E_INVALIDARG;
2850 static HRESULT internal_getProperty(const saxreader* This, const WCHAR *prop, VARIANT *value, BOOL vb)
2852 TRACE("(%p)->(%s)\n", This, debugstr_w(prop));
2854 if (!value) return E_POINTER;
2856 if (!memcmp(PropertyLexicalHandlerW, prop, sizeof(PropertyLexicalHandlerW)))
2858 V_VT(value) = VT_UNKNOWN;
2859 saxreader_get_handler(This, SAXLexicalHandler, vb, (void**)&V_UNKNOWN(value));
2860 return S_OK;
2863 if (!memcmp(PropertyDeclHandlerW, prop, sizeof(PropertyDeclHandlerW)))
2865 V_VT(value) = VT_UNKNOWN;
2866 saxreader_get_handler(This, SAXDeclHandler, vb, (void**)&V_UNKNOWN(value));
2867 return S_OK;
2870 if (!memcmp(PropertyXmlDeclVersionW, prop, sizeof(PropertyXmlDeclVersionW)))
2872 V_VT(value) = VT_BSTR;
2873 V_BSTR(value) = SysAllocString(This->xmldecl_version);
2874 return S_OK;
2877 FIXME("(%p)->(%s) unsupported property\n", This, debugstr_w(prop));
2879 return E_NOTIMPL;
2882 /*** IVBSAXXMLReader interface ***/
2883 /*** IUnknown methods ***/
2884 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2886 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2888 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2890 *ppvObject = NULL;
2892 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2893 IsEqualGUID( riid, &IID_IDispatch ) ||
2894 IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2896 *ppvObject = iface;
2898 else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2900 *ppvObject = &This->ISAXXMLReader_iface;
2902 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
2904 return *ppvObject ? S_OK : E_NOINTERFACE;
2906 else
2908 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2909 return E_NOINTERFACE;
2912 IVBSAXXMLReader_AddRef( iface );
2914 return S_OK;
2917 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2919 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2920 TRACE("%p\n", This );
2921 return InterlockedIncrement( &This->ref );
2924 static ULONG WINAPI saxxmlreader_Release(
2925 IVBSAXXMLReader* iface)
2927 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2928 LONG ref;
2930 TRACE("%p\n", This );
2932 ref = InterlockedDecrement( &This->ref );
2933 if ( ref == 0 )
2935 int i;
2937 for (i = 0; i < SAXHandler_Last; i++)
2939 struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
2941 if (saxiface->handler)
2942 IUnknown_Release(saxiface->handler);
2944 if (saxiface->vbhandler)
2945 IUnknown_Release(saxiface->vbhandler);
2948 SysFreeString(This->xmldecl_version);
2949 free_bstr_pool(&This->pool);
2951 heap_free( This );
2954 return ref;
2956 /*** IDispatch ***/
2957 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2959 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2960 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2963 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2964 IVBSAXXMLReader *iface,
2965 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2967 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2968 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
2969 iTInfo, lcid, ppTInfo);
2972 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2973 IVBSAXXMLReader *iface,
2974 REFIID riid,
2975 LPOLESTR* rgszNames,
2976 UINT cNames,
2977 LCID lcid,
2978 DISPID* rgDispId)
2980 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2981 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2982 riid, rgszNames, cNames, lcid, rgDispId);
2985 static HRESULT WINAPI saxxmlreader_Invoke(
2986 IVBSAXXMLReader *iface,
2987 DISPID dispIdMember,
2988 REFIID riid,
2989 LCID lcid,
2990 WORD wFlags,
2991 DISPPARAMS* pDispParams,
2992 VARIANT* pVarResult,
2993 EXCEPINFO* pExcepInfo,
2994 UINT* puArgErr)
2996 saxreader *This = impl_from_IVBSAXXMLReader( iface );
2997 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2998 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3001 /*** IVBSAXXMLReader methods ***/
3002 static HRESULT WINAPI saxxmlreader_getFeature(
3003 IVBSAXXMLReader* iface,
3004 BSTR feature_name,
3005 VARIANT_BOOL *value)
3007 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3008 return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
3011 static HRESULT WINAPI saxxmlreader_putFeature(
3012 IVBSAXXMLReader* iface,
3013 BSTR feature_name,
3014 VARIANT_BOOL value)
3016 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3017 return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
3020 static HRESULT WINAPI saxxmlreader_getProperty(
3021 IVBSAXXMLReader* iface,
3022 BSTR prop,
3023 VARIANT *value)
3025 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3026 return internal_getProperty(This, prop, value, TRUE);
3029 static HRESULT WINAPI saxxmlreader_putProperty(
3030 IVBSAXXMLReader* iface,
3031 BSTR pProp,
3032 VARIANT value)
3034 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3035 return internal_putProperty(This, pProp, value, TRUE);
3038 static HRESULT WINAPI saxxmlreader_get_entityResolver(
3039 IVBSAXXMLReader* iface,
3040 IVBSAXEntityResolver **resolver)
3042 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3043 return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
3046 static HRESULT WINAPI saxxmlreader_put_entityResolver(
3047 IVBSAXXMLReader* iface,
3048 IVBSAXEntityResolver *resolver)
3050 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3051 return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
3054 static HRESULT WINAPI saxxmlreader_get_contentHandler(
3055 IVBSAXXMLReader* iface,
3056 IVBSAXContentHandler **handler)
3058 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3059 return saxreader_get_handler(This, SAXContentHandler, TRUE, (void**)handler);
3062 static HRESULT WINAPI saxxmlreader_put_contentHandler(
3063 IVBSAXXMLReader* iface,
3064 IVBSAXContentHandler *handler)
3066 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3067 return saxreader_put_handler(This, SAXContentHandler, handler, TRUE);
3070 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
3071 IVBSAXXMLReader* iface,
3072 IVBSAXDTDHandler **handler)
3074 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3075 return saxreader_get_handler(This, SAXDTDHandler, TRUE, (void**)handler);
3078 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
3079 IVBSAXXMLReader* iface,
3080 IVBSAXDTDHandler *handler)
3082 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3083 return saxreader_put_handler(This, SAXDTDHandler, handler, TRUE);
3086 static HRESULT WINAPI saxxmlreader_get_errorHandler(
3087 IVBSAXXMLReader* iface,
3088 IVBSAXErrorHandler **handler)
3090 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3091 return saxreader_get_handler(This, SAXErrorHandler, TRUE, (void**)handler);
3094 static HRESULT WINAPI saxxmlreader_put_errorHandler(
3095 IVBSAXXMLReader* iface,
3096 IVBSAXErrorHandler *handler)
3098 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3099 return saxreader_put_handler(This, SAXErrorHandler, handler, TRUE);
3102 static HRESULT WINAPI saxxmlreader_get_baseURL(
3103 IVBSAXXMLReader* iface,
3104 BSTR *pBaseUrl)
3106 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3108 FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
3109 return E_NOTIMPL;
3112 static HRESULT WINAPI saxxmlreader_put_baseURL(
3113 IVBSAXXMLReader* iface,
3114 BSTR pBaseUrl)
3116 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3117 return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
3120 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
3121 IVBSAXXMLReader* iface,
3122 BSTR *pSecureBaseUrl)
3124 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3126 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3127 return E_NOTIMPL;
3130 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
3131 IVBSAXXMLReader* iface,
3132 BSTR secureBaseUrl)
3134 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3135 return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
3138 static HRESULT WINAPI saxxmlreader_parse(
3139 IVBSAXXMLReader* iface,
3140 VARIANT varInput)
3142 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3143 return internal_parse(This, varInput, TRUE);
3146 static HRESULT WINAPI saxxmlreader_parseURL(
3147 IVBSAXXMLReader* iface,
3148 BSTR url)
3150 saxreader *This = impl_from_IVBSAXXMLReader( iface );
3151 return internal_parseURL(This, url, TRUE);
3154 static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
3156 saxxmlreader_QueryInterface,
3157 saxxmlreader_AddRef,
3158 saxxmlreader_Release,
3159 saxxmlreader_GetTypeInfoCount,
3160 saxxmlreader_GetTypeInfo,
3161 saxxmlreader_GetIDsOfNames,
3162 saxxmlreader_Invoke,
3163 saxxmlreader_getFeature,
3164 saxxmlreader_putFeature,
3165 saxxmlreader_getProperty,
3166 saxxmlreader_putProperty,
3167 saxxmlreader_get_entityResolver,
3168 saxxmlreader_put_entityResolver,
3169 saxxmlreader_get_contentHandler,
3170 saxxmlreader_put_contentHandler,
3171 saxxmlreader_get_dtdHandler,
3172 saxxmlreader_put_dtdHandler,
3173 saxxmlreader_get_errorHandler,
3174 saxxmlreader_put_errorHandler,
3175 saxxmlreader_get_baseURL,
3176 saxxmlreader_put_baseURL,
3177 saxxmlreader_get_secureBaseURL,
3178 saxxmlreader_put_secureBaseURL,
3179 saxxmlreader_parse,
3180 saxxmlreader_parseURL
3183 /*** ISAXXMLReader interface ***/
3184 /*** IUnknown methods ***/
3185 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
3187 saxreader *This = impl_from_ISAXXMLReader( iface );
3188 return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
3191 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
3193 saxreader *This = impl_from_ISAXXMLReader( iface );
3194 return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
3197 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
3199 saxreader *This = impl_from_ISAXXMLReader( iface );
3200 return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
3203 /*** ISAXXMLReader methods ***/
3204 static HRESULT WINAPI isaxxmlreader_getFeature(
3205 ISAXXMLReader* iface,
3206 const WCHAR *feature_name,
3207 VARIANT_BOOL *value)
3209 saxreader *This = impl_from_ISAXXMLReader( iface );
3210 saxreader_feature feature;
3212 TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
3214 feature = get_saxreader_feature(feature_name);
3216 if (This->version < MSXML4 && (feature == ExhaustiveErrors || feature == SchemaValidation))
3217 return E_INVALIDARG;
3219 if (feature == Namespaces ||
3220 feature == NamespacePrefixes ||
3221 feature == ExhaustiveErrors ||
3222 feature == SchemaValidation)
3223 return get_feature_value(This, feature, value);
3225 FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
3226 return E_NOTIMPL;
3229 static HRESULT WINAPI isaxxmlreader_putFeature(
3230 ISAXXMLReader* iface,
3231 const WCHAR *feature_name,
3232 VARIANT_BOOL value)
3234 saxreader *This = impl_from_ISAXXMLReader( iface );
3235 saxreader_feature feature;
3237 TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
3239 feature = get_saxreader_feature(feature_name);
3241 /* accepted cases */
3242 if ((feature == ExhaustiveErrors && value == VARIANT_FALSE) ||
3243 (feature == SchemaValidation && value == VARIANT_FALSE) ||
3244 feature == Namespaces ||
3245 feature == NamespacePrefixes)
3247 return set_feature_value(This, feature, value);
3250 if (feature == LexicalHandlerParEntities ||
3251 feature == ProhibitDTD ||
3252 feature == ExternalGeneralEntities ||
3253 feature == ExternalParameterEntities)
3255 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3256 return set_feature_value(This, feature, value);
3259 FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
3260 return E_NOTIMPL;
3263 static HRESULT WINAPI isaxxmlreader_getProperty(
3264 ISAXXMLReader* iface,
3265 const WCHAR *prop,
3266 VARIANT *value)
3268 saxreader *This = impl_from_ISAXXMLReader( iface );
3269 return internal_getProperty(This, prop, value, FALSE);
3272 static HRESULT WINAPI isaxxmlreader_putProperty(
3273 ISAXXMLReader* iface,
3274 const WCHAR *pProp,
3275 VARIANT value)
3277 saxreader *This = impl_from_ISAXXMLReader( iface );
3278 return internal_putProperty(This, pProp, value, FALSE);
3281 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
3282 ISAXXMLReader* iface,
3283 ISAXEntityResolver **resolver)
3285 saxreader *This = impl_from_ISAXXMLReader( iface );
3286 return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
3289 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
3290 ISAXXMLReader* iface,
3291 ISAXEntityResolver *resolver)
3293 saxreader *This = impl_from_ISAXXMLReader( iface );
3294 return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
3297 static HRESULT WINAPI isaxxmlreader_getContentHandler(
3298 ISAXXMLReader* iface,
3299 ISAXContentHandler **handler)
3301 saxreader *This = impl_from_ISAXXMLReader( iface );
3302 return saxreader_get_handler(This, SAXContentHandler, FALSE, (void**)handler);
3305 static HRESULT WINAPI isaxxmlreader_putContentHandler(
3306 ISAXXMLReader* iface,
3307 ISAXContentHandler *handler)
3309 saxreader *This = impl_from_ISAXXMLReader( iface );
3310 return saxreader_put_handler(This, SAXContentHandler, handler, FALSE);
3313 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
3314 ISAXXMLReader* iface,
3315 ISAXDTDHandler **handler)
3317 saxreader *This = impl_from_ISAXXMLReader( iface );
3318 return saxreader_get_handler(This, SAXDTDHandler, FALSE, (void**)handler);
3321 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
3322 ISAXXMLReader* iface,
3323 ISAXDTDHandler *handler)
3325 saxreader *This = impl_from_ISAXXMLReader( iface );
3326 return saxreader_put_handler(This, SAXDTDHandler, handler, FALSE);
3329 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
3330 ISAXXMLReader* iface,
3331 ISAXErrorHandler **handler)
3333 saxreader *This = impl_from_ISAXXMLReader( iface );
3334 return saxreader_get_handler(This, SAXErrorHandler, FALSE, (void**)handler);
3337 static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXErrorHandler *handler)
3339 saxreader *This = impl_from_ISAXXMLReader( iface );
3340 return saxreader_put_handler(This, SAXErrorHandler, handler, FALSE);
3343 static HRESULT WINAPI isaxxmlreader_getBaseURL(
3344 ISAXXMLReader* iface,
3345 const WCHAR **base_url)
3347 saxreader *This = impl_from_ISAXXMLReader( iface );
3349 FIXME("(%p)->(%p) stub\n", This, base_url);
3350 return E_NOTIMPL;
3353 static HRESULT WINAPI isaxxmlreader_putBaseURL(
3354 ISAXXMLReader* iface,
3355 const WCHAR *pBaseUrl)
3357 saxreader *This = impl_from_ISAXXMLReader( iface );
3359 FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
3360 return E_NOTIMPL;
3363 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
3364 ISAXXMLReader* iface,
3365 const WCHAR **pSecureBaseUrl)
3367 saxreader *This = impl_from_ISAXXMLReader( iface );
3368 FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
3369 return E_NOTIMPL;
3372 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
3373 ISAXXMLReader* iface,
3374 const WCHAR *secureBaseUrl)
3376 saxreader *This = impl_from_ISAXXMLReader( iface );
3378 FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
3379 return E_NOTIMPL;
3382 static HRESULT WINAPI isaxxmlreader_parse(
3383 ISAXXMLReader* iface,
3384 VARIANT varInput)
3386 saxreader *This = impl_from_ISAXXMLReader( iface );
3387 return internal_parse(This, varInput, FALSE);
3390 static HRESULT WINAPI isaxxmlreader_parseURL(
3391 ISAXXMLReader* iface,
3392 const WCHAR *url)
3394 saxreader *This = impl_from_ISAXXMLReader( iface );
3395 return internal_parseURL(This, url, FALSE);
3398 static const struct ISAXXMLReaderVtbl SAXXMLReaderVtbl =
3400 isaxxmlreader_QueryInterface,
3401 isaxxmlreader_AddRef,
3402 isaxxmlreader_Release,
3403 isaxxmlreader_getFeature,
3404 isaxxmlreader_putFeature,
3405 isaxxmlreader_getProperty,
3406 isaxxmlreader_putProperty,
3407 isaxxmlreader_getEntityResolver,
3408 isaxxmlreader_putEntityResolver,
3409 isaxxmlreader_getContentHandler,
3410 isaxxmlreader_putContentHandler,
3411 isaxxmlreader_getDTDHandler,
3412 isaxxmlreader_putDTDHandler,
3413 isaxxmlreader_getErrorHandler,
3414 isaxxmlreader_putErrorHandler,
3415 isaxxmlreader_getBaseURL,
3416 isaxxmlreader_putBaseURL,
3417 isaxxmlreader_getSecureBaseURL,
3418 isaxxmlreader_putSecureBaseURL,
3419 isaxxmlreader_parse,
3420 isaxxmlreader_parseURL
3423 static const tid_t saxreader_iface_tids[] = {
3424 IVBSAXXMLReader_tid,
3427 static dispex_static_data_t saxreader_dispex = {
3428 NULL,
3429 IVBSAXXMLReader_tid,
3430 NULL,
3431 saxreader_iface_tids
3434 HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
3436 saxreader *reader;
3438 TRACE("(%p)\n", ppObj);
3440 reader = heap_alloc( sizeof (*reader) );
3441 if( !reader )
3442 return E_OUTOFMEMORY;
3444 reader->IVBSAXXMLReader_iface.lpVtbl = &VBSAXXMLReaderVtbl;
3445 reader->ISAXXMLReader_iface.lpVtbl = &SAXXMLReaderVtbl;
3446 reader->ref = 1;
3447 memset(reader->saxhandlers, 0, sizeof(reader->saxhandlers));
3448 reader->isParsing = FALSE;
3449 reader->xmldecl_version = NULL;
3450 reader->pool.pool = NULL;
3451 reader->pool.index = 0;
3452 reader->pool.len = 0;
3453 reader->features = Namespaces | NamespacePrefixes;
3454 reader->version = version;
3456 init_dispex(&reader->dispex, (IUnknown*)&reader->IVBSAXXMLReader_iface, &saxreader_dispex);
3458 memset(&reader->sax, 0, sizeof(xmlSAXHandler));
3459 reader->sax.initialized = XML_SAX2_MAGIC;
3460 reader->sax.startDocument = libxmlStartDocument;
3461 reader->sax.endDocument = libxmlEndDocument;
3462 reader->sax.startElementNs = libxmlStartElementNS;
3463 reader->sax.endElementNs = libxmlEndElementNS;
3464 reader->sax.characters = libxmlCharacters;
3465 reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
3466 reader->sax.comment = libxmlComment;
3467 reader->sax.error = libxmlFatalError;
3468 reader->sax.fatalError = libxmlFatalError;
3469 reader->sax.cdataBlock = libxml_cdatablock;
3470 reader->sax.resolveEntity = libxmlresolveentity;
3472 *ppObj = &reader->IVBSAXXMLReader_iface;
3474 TRACE("returning iface %p\n", *ppObj);
3476 return S_OK;