kernel32/tests: Also test wrong architecture with matching 32/64 bitness.
[wine.git] / dlls / msxml3 / mxnamespace.c
blobdc6ff9c85ad9c99139ec5e47b927b70f77375db8
1 /*
2 * IMXNamespaceManager implementation
4 * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 # include <libxml/encoding.h>
30 #endif
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "ole2.h"
36 #include "msxml6.h"
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 struct ns
46 BSTR prefix;
47 BSTR uri;
50 struct nscontext
52 struct list entry;
54 struct ns *ns;
55 int count;
56 int max_alloc;
59 #define DEFAULT_PREFIX_ALLOC_COUNT 16
61 static const WCHAR xmlW[] = {'x','m','l',0};
62 static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
63 '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
65 typedef struct
67 DispatchEx dispex;
68 IMXNamespaceManager IMXNamespaceManager_iface;
69 IVBMXNamespaceManager IVBMXNamespaceManager_iface;
70 LONG ref;
72 struct list ctxts;
74 VARIANT_BOOL override;
75 } namespacemanager;
77 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
79 return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
82 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
84 return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
87 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
89 struct nscontext *ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
90 static const WCHAR emptyW[] = {0};
91 struct ns *ns;
92 int i;
94 if (ctxt->count == ctxt->max_alloc)
96 ctxt->max_alloc *= 2;
97 ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
100 if (!prefix) prefix = emptyW;
102 ns = NULL;
103 for (i = 0; i < ctxt->count; i++)
104 if (!strcmpW(ctxt->ns[i].prefix, prefix))
106 ns = &ctxt->ns[i];
107 break;
110 if (ns)
112 if (This->override == VARIANT_TRUE)
114 SysFreeString(ns->uri);
115 ns->uri = SysAllocString(uri);
116 return S_FALSE;
118 else
119 return E_FAIL;
121 else
123 ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
124 ctxt->ns[ctxt->count].uri = SysAllocString(uri);
125 ctxt->count++;
128 return S_OK;
131 /* returned stored pointer, caller needs to copy it */
132 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
134 *prefix = NULL;
136 if (index >= ctxt->count || index < 0) return E_FAIL;
138 if (index > 0) index = ctxt->count - index;
139 *prefix = ctxt->ns[index].prefix;
141 return S_OK;
144 /* returned stored pointer, caller needs to copy it */
145 static HRESULT get_declared_prefix_uri(const struct list *ctxts, const WCHAR *uri, BSTR *prefix)
147 struct nscontext *ctxt;
149 LIST_FOR_EACH_ENTRY(ctxt, ctxts, struct nscontext, entry)
151 int i;
152 for (i = 0; i < ctxt->count; i++)
153 if (!strcmpW(ctxt->ns[i].uri, uri))
155 *prefix = ctxt->ns[i].prefix;
156 return S_OK;
160 *prefix = NULL;
161 return E_FAIL;
164 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
166 int i;
168 for (i = 0; i < ctxt->count; i++)
169 if (!strcmpW(ctxt->ns[i].prefix, prefix))
171 *uri = ctxt->ns[i].uri;
172 return S_OK;
175 *uri = NULL;
176 return S_FALSE;
179 static struct nscontext* alloc_ns_context(void)
181 struct nscontext *ctxt;
183 ctxt = heap_alloc(sizeof(*ctxt));
184 if (!ctxt) return NULL;
186 ctxt->count = 0;
187 ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
188 ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
189 if (!ctxt->ns)
191 heap_free(ctxt);
192 return NULL;
195 /* first allocated prefix is always 'xml' */
196 ctxt->ns[0].prefix = SysAllocString(xmlW);
197 ctxt->ns[0].uri = SysAllocString(xmluriW);
198 ctxt->count++;
199 if (!ctxt->ns[0].prefix || !ctxt->ns[0].uri)
201 heap_free(ctxt->ns);
202 heap_free(ctxt);
203 return NULL;
206 return ctxt;
209 static void free_ns_context(struct nscontext *ctxt)
211 int i;
213 for (i = 0; i < ctxt->count; i++)
215 SysFreeString(ctxt->ns[i].prefix);
216 SysFreeString(ctxt->ns[i].uri);
219 heap_free(ctxt->ns);
220 heap_free(ctxt);
223 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
225 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
226 return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
229 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
231 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
232 return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
235 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
237 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
238 return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
241 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
242 VARIANT_BOOL override)
244 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
245 return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
248 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
249 VARIANT_BOOL *override)
251 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
252 return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
255 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
257 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
258 return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
261 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
263 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
264 return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
267 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
268 IXMLDOMNode *node, VARIANT_BOOL deep)
270 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
271 return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
274 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
276 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
277 return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
280 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
281 const WCHAR *prefix, const WCHAR *namespaceURI)
283 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
285 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
287 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
289 if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
290 return E_INVALIDARG;
292 return declare_prefix(This, prefix, namespaceURI);
295 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
296 LONG index, WCHAR *prefix, int *prefix_len)
298 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
299 struct nscontext *ctxt;
300 HRESULT hr;
301 BSTR prfx;
303 TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
305 if (!prefix_len) return E_POINTER;
307 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
308 hr = get_declared_prefix_idx(ctxt, index, &prfx);
309 if (hr != S_OK) return hr;
311 if (prefix)
313 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
314 strcpyW(prefix, prfx);
317 *prefix_len = SysStringLen(prfx);
319 return S_OK;
322 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
323 const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
325 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
326 HRESULT hr;
327 BSTR prfx;
329 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
331 if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
333 hr = get_declared_prefix_uri(&This->ctxts, uri, &prfx);
334 if (hr == S_OK)
336 /* TODO: figure out what index argument is for */
337 if (index) return E_FAIL;
339 if (prefix)
341 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
342 strcpyW(prefix, prfx);
345 *prefix_len = SysStringLen(prfx);
346 TRACE("prefix=%s\n", debugstr_w(prfx));
349 return hr;
352 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
353 const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
355 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
356 struct nscontext *ctxt;
357 HRESULT hr;
358 BSTR urib;
360 TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
362 if (!prefix) return E_INVALIDARG;
363 if (!uri_len) return E_POINTER;
365 if (node)
367 FIXME("namespaces from DOM node not supported\n");
368 return E_NOTIMPL;
371 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
372 hr = get_uri_from_prefix(ctxt, prefix, &urib);
373 if (hr == S_OK)
375 if (uri)
377 if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
378 strcpyW(uri, urib);
381 else
382 if (uri) *uri = 0;
384 *uri_len = SysStringLen(urib);
386 return hr;
389 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
391 namespacemanager_QueryInterface,
392 namespacemanager_AddRef,
393 namespacemanager_Release,
394 namespacemanager_putAllowOverride,
395 namespacemanager_getAllowOverride,
396 namespacemanager_reset,
397 namespacemanager_pushContext,
398 namespacemanager_pushNodeContext,
399 namespacemanager_popContext,
400 namespacemanager_declarePrefix,
401 namespacemanager_getDeclaredPrefix,
402 namespacemanager_getPrefix,
403 namespacemanager_getURI
406 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
408 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
409 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
411 if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
412 IsEqualGUID( riid, &IID_IUnknown) )
414 *obj = &This->IMXNamespaceManager_iface;
416 else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
417 IsEqualGUID( riid, &IID_IDispatch) )
419 *obj = &This->IVBMXNamespaceManager_iface;
421 else if (dispex_query_interface(&This->dispex, riid, obj))
423 return *obj ? S_OK : E_NOINTERFACE;
425 else
427 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
428 *obj = NULL;
429 return E_NOINTERFACE;
432 IVBMXNamespaceManager_AddRef( iface );
434 return S_OK;
437 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
439 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
440 ULONG ref = InterlockedIncrement( &This->ref );
441 TRACE("(%p)->(%u)\n", This, ref );
442 return ref;
445 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
447 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
448 ULONG ref = InterlockedDecrement( &This->ref );
450 TRACE("(%p)->(%u)\n", This, ref );
452 if ( ref == 0 )
454 struct nscontext *ctxt, *ctxt2;
456 LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
458 list_remove(&ctxt->entry);
459 free_ns_context(ctxt);
462 heap_free( This );
465 return ref;
468 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
470 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
471 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
474 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
475 LCID lcid, ITypeInfo **ppTInfo)
477 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
478 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
479 iTInfo, lcid, ppTInfo);
482 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
483 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
485 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
486 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
487 riid, rgszNames, cNames, lcid, rgDispId);
490 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
491 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
492 EXCEPINFO *pExcepInfo, UINT *puArgErr)
494 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
495 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
496 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
499 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
500 VARIANT_BOOL override)
502 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
504 TRACE("(%p)->(%d)\n", This, override);
505 This->override = override;
507 return S_OK;
510 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
511 VARIANT_BOOL *override)
513 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
515 TRACE("(%p)->(%p)\n", This, override);
517 if (!override) return E_POINTER;
518 *override = This->override;
520 return S_OK;
523 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
525 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
526 FIXME("(%p): stub\n", This);
527 return E_NOTIMPL;
530 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
532 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
533 struct nscontext *ctxt;
535 TRACE("(%p)\n", This);
537 ctxt = alloc_ns_context();
538 if (!ctxt) return E_OUTOFMEMORY;
540 list_add_head(&This->ctxts, &ctxt->entry);
542 return S_OK;
545 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
546 IXMLDOMNode *node, VARIANT_BOOL deep)
548 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
549 FIXME("(%p)->(%p %d): stub\n", This, node, deep);
550 return E_NOTIMPL;
553 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
555 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
556 const struct list *next;
557 struct nscontext *ctxt;
559 TRACE("(%p)\n", This);
561 next = list_next(&This->ctxts, list_head(&This->ctxts));
562 if (!next) return E_FAIL;
564 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
565 list_remove(list_head(&This->ctxts));
567 free_ns_context(ctxt);
569 return S_OK;
572 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
573 BSTR prefix, BSTR namespaceURI)
575 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
576 return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
579 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
580 IMXNamespacePrefixes** prefixes)
582 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
583 FIXME("(%p)->(%p): stub\n", This, prefixes);
584 return E_NOTIMPL;
587 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
588 BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
590 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
591 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
592 return E_NOTIMPL;
595 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
596 BSTR prefix, VARIANT* uri)
598 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
599 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
600 return E_NOTIMPL;
603 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
604 BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
606 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
607 FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
608 return E_NOTIMPL;
611 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
613 vbnamespacemanager_QueryInterface,
614 vbnamespacemanager_AddRef,
615 vbnamespacemanager_Release,
616 vbnamespacemanager_GetTypeInfoCount,
617 vbnamespacemanager_GetTypeInfo,
618 vbnamespacemanager_GetIDsOfNames,
619 vbnamespacemanager_Invoke,
620 vbnamespacemanager_put_allowOverride,
621 vbnamespacemanager_get_allowOverride,
622 vbnamespacemanager_reset,
623 vbnamespacemanager_pushContext,
624 vbnamespacemanager_pushNodeContext,
625 vbnamespacemanager_popContext,
626 vbnamespacemanager_declarePrefix,
627 vbnamespacemanager_getDeclaredPrefixes,
628 vbnamespacemanager_getPrefixes,
629 vbnamespacemanager_getURI,
630 vbnamespacemanager_getURIFromNode
633 static const tid_t namespacemanager_iface_tids[] = {
634 IVBMXNamespaceManager_tid,
638 static dispex_static_data_t namespacemanager_dispex = {
639 NULL,
640 IVBMXNamespaceManager_tid,
641 NULL,
642 namespacemanager_iface_tids
645 HRESULT MXNamespaceManager_create(void **obj)
647 namespacemanager *This;
648 struct nscontext *ctxt;
650 TRACE("(%p)\n", obj);
652 This = heap_alloc( sizeof (*This) );
653 if( !This )
654 return E_OUTOFMEMORY;
656 This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
657 This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
658 This->ref = 1;
659 init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
661 list_init(&This->ctxts);
662 ctxt = alloc_ns_context();
663 if (!ctxt)
665 heap_free(This);
666 return E_OUTOFMEMORY;
669 list_add_head(&This->ctxts, &ctxt->entry);
671 This->override = VARIANT_TRUE;
673 *obj = &This->IMXNamespaceManager_iface;
675 TRACE("returning iface %p\n", *obj);
677 return S_OK;