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
22 #define NONAMELESSUNION
28 # include <libxml/parser.h>
29 # include <libxml/xmlerror.h>
30 # include <libxml/encoding.h>
39 #include "msxml_private.h"
41 #include "wine/debug.h"
42 #include "wine/list.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
61 #define DEFAULT_PREFIX_ALLOC_COUNT 16
63 static const WCHAR xmlW[] = {'x','m','l',0};
64 static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
65 '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
70 IMXNamespaceManager IMXNamespaceManager_iface;
71 IVBMXNamespaceManager IVBMXNamespaceManager_iface;
76 VARIANT_BOOL override;
79 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
81 return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
84 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
86 return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
89 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
91 struct nscontext *ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
92 static const WCHAR emptyW[] = {0};
96 if (ctxt->count == ctxt->max_alloc)
99 ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
102 if (!prefix) prefix = emptyW;
105 for (i = 0; i < ctxt->count; i++)
106 if (!strcmpW(ctxt->ns[i].prefix, prefix))
114 if (This->override == VARIANT_TRUE)
116 SysFreeString(ns->uri);
117 ns->uri = SysAllocString(uri);
125 ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
126 ctxt->ns[ctxt->count].uri = SysAllocString(uri);
133 /* returned stored pointer, caller needs to copy it */
134 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
138 if (index >= ctxt->count || index < 0) return E_FAIL;
140 if (index > 0) index = ctxt->count - index;
141 *prefix = ctxt->ns[index].prefix;
146 /* returned stored pointer, caller needs to copy it */
147 static HRESULT get_declared_prefix_uri(const struct nscontext *ctxt, const WCHAR *uri, BSTR *prefix)
151 for (i = 0; i < ctxt->count; i++)
152 if (!strcmpW(ctxt->ns[i].uri, uri))
154 *prefix = ctxt->ns[i].prefix;
162 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
166 for (i = 0; i < ctxt->count; i++)
167 if (!strcmpW(ctxt->ns[i].prefix, prefix))
169 *uri = ctxt->ns[i].uri;
177 static struct nscontext* alloc_ns_context(void)
179 struct nscontext *ctxt;
181 ctxt = heap_alloc(sizeof(*ctxt));
182 if (!ctxt) return NULL;
185 ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
186 ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
188 /* first allocated prefix is always 'xml' */
189 ctxt->ns[0].prefix = SysAllocString(xmlW);
190 ctxt->ns[0].uri = SysAllocString(xmluriW);
196 static void free_ns_context(struct nscontext *ctxt)
200 for (i = 0; i < ctxt->count; i++)
202 SysFreeString(ctxt->ns[i].prefix);
203 SysFreeString(ctxt->ns[i].uri);
210 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
212 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
213 return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
216 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
218 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
219 return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
222 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
224 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
225 return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
228 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
229 VARIANT_BOOL override)
231 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
232 return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
235 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
236 VARIANT_BOOL *override)
238 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
239 return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
242 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
244 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
245 return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
248 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
250 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
251 return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
254 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
255 IXMLDOMNode *node, VARIANT_BOOL deep)
257 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
258 return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
261 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
263 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
264 return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
267 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
268 const WCHAR *prefix, const WCHAR *namespaceURI)
270 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
272 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
274 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
276 if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
279 return declare_prefix(This, prefix, namespaceURI);
282 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
283 LONG index, WCHAR *prefix, int *prefix_len)
285 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
286 struct nscontext *ctxt;
290 TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
292 if (!prefix_len) return E_POINTER;
294 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
295 hr = get_declared_prefix_idx(ctxt, index, &prfx);
296 if (hr != S_OK) return hr;
300 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
301 strcpyW(prefix, prfx);
304 *prefix_len = SysStringLen(prfx);
309 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
310 const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
312 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
313 struct nscontext *ctxt;
317 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
319 if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
321 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
323 hr = get_declared_prefix_uri(ctxt, uri, &prfx);
326 /* TODO: figure out what index argument is for */
327 if (index) return E_FAIL;
331 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
332 strcpyW(prefix, prfx);
335 *prefix_len = SysStringLen(prfx);
336 TRACE("prefix=%s\n", debugstr_w(prfx));
342 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
343 const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
345 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
346 struct nscontext *ctxt;
350 TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
352 if (!prefix) return E_INVALIDARG;
353 if (!uri_len) return E_POINTER;
357 FIXME("namespaces from DOM node not supported\n");
361 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
362 hr = get_uri_from_prefix(ctxt, prefix, &urib);
367 if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
374 *uri_len = SysStringLen(urib);
379 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
381 namespacemanager_QueryInterface,
382 namespacemanager_AddRef,
383 namespacemanager_Release,
384 namespacemanager_putAllowOverride,
385 namespacemanager_getAllowOverride,
386 namespacemanager_reset,
387 namespacemanager_pushContext,
388 namespacemanager_pushNodeContext,
389 namespacemanager_popContext,
390 namespacemanager_declarePrefix,
391 namespacemanager_getDeclaredPrefix,
392 namespacemanager_getPrefix,
393 namespacemanager_getURI
396 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
398 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
399 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
401 if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
402 IsEqualGUID( riid, &IID_IUnknown) )
404 *obj = &This->IMXNamespaceManager_iface;
406 else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
407 IsEqualGUID( riid, &IID_IDispatch) )
409 *obj = &This->IVBMXNamespaceManager_iface;
411 else if (dispex_query_interface(&This->dispex, riid, obj))
413 return *obj ? S_OK : E_NOINTERFACE;
417 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
419 return E_NOINTERFACE;
422 IVBMXNamespaceManager_AddRef( iface );
427 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
429 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
430 ULONG ref = InterlockedIncrement( &This->ref );
431 TRACE("(%p)->(%u)\n", This, ref );
435 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
437 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
438 ULONG ref = InterlockedDecrement( &This->ref );
440 TRACE("(%p)->(%u)\n", This, ref );
444 struct nscontext *ctxt, *ctxt2;
446 LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
448 list_remove(&ctxt->entry);
449 free_ns_context(ctxt);
452 release_dispex(&This->dispex);
459 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
461 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
462 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
465 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
466 LCID lcid, ITypeInfo **ppTInfo)
468 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
469 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
470 iTInfo, lcid, ppTInfo);
473 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
474 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
476 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
477 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
478 riid, rgszNames, cNames, lcid, rgDispId);
481 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
482 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
483 EXCEPINFO *pExcepInfo, UINT *puArgErr)
485 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
486 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
487 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
490 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
491 VARIANT_BOOL override)
493 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
495 TRACE("(%p)->(%d)\n", This, override);
496 This->override = override;
501 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
502 VARIANT_BOOL *override)
504 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
506 TRACE("(%p)->(%p)\n", This, override);
508 if (!override) return E_POINTER;
509 *override = This->override;
514 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
516 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
517 FIXME("(%p): stub\n", This);
521 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
523 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
524 FIXME("(%p): stub\n", This);
528 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
529 IXMLDOMNode *node, VARIANT_BOOL deep)
531 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
532 FIXME("(%p)->(%p %d): stub\n", This, node, deep);
536 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
538 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
539 FIXME("(%p): stub\n", This);
543 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
544 BSTR prefix, BSTR namespaceURI)
546 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
547 return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
550 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
551 IMXNamespacePrefixes** prefixes)
553 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
554 FIXME("(%p)->(%p): stub\n", This, prefixes);
558 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
559 BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
561 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
562 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
566 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
567 BSTR prefix, VARIANT* uri)
569 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
570 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
574 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
575 BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
577 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
578 FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
582 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
584 vbnamespacemanager_QueryInterface,
585 vbnamespacemanager_AddRef,
586 vbnamespacemanager_Release,
587 vbnamespacemanager_GetTypeInfoCount,
588 vbnamespacemanager_GetTypeInfo,
589 vbnamespacemanager_GetIDsOfNames,
590 vbnamespacemanager_Invoke,
591 vbnamespacemanager_put_allowOverride,
592 vbnamespacemanager_get_allowOverride,
593 vbnamespacemanager_reset,
594 vbnamespacemanager_pushContext,
595 vbnamespacemanager_pushNodeContext,
596 vbnamespacemanager_popContext,
597 vbnamespacemanager_declarePrefix,
598 vbnamespacemanager_getDeclaredPrefixes,
599 vbnamespacemanager_getPrefixes,
600 vbnamespacemanager_getURI,
601 vbnamespacemanager_getURIFromNode
604 static const tid_t namespacemanager_iface_tids[] = {
605 IVBMXNamespaceManager_tid,
608 static dispex_static_data_t namespacemanager_dispex = {
610 IVBMXNamespaceManager_tid,
612 namespacemanager_iface_tids
615 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
617 namespacemanager *This;
618 struct nscontext *ctxt;
620 TRACE("(%p, %p)\n", outer, obj);
622 This = heap_alloc( sizeof (*This) );
624 return E_OUTOFMEMORY;
626 This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
627 This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
629 init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
631 list_init(&This->ctxts);
632 ctxt = alloc_ns_context();
633 list_add_head(&This->ctxts, &ctxt->entry);
635 This->override = VARIANT_TRUE;
637 *obj = &This->IMXNamespaceManager_iface;
639 TRACE("returning iface %p\n", *obj);