2 * IMXNamespaceManager implementation
4 * Copyright 2011 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};
69 IMXNamespaceManager IMXNamespaceManager_iface;
70 IVBMXNamespaceManager IVBMXNamespaceManager_iface;
75 VARIANT_BOOL override;
78 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
80 return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
83 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
85 return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
88 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
90 struct nscontext *ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
91 static const WCHAR emptyW[] = {0};
95 if (ctxt->count == ctxt->max_alloc)
98 ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
101 if (!prefix) prefix = emptyW;
104 for (i = 0; i < ctxt->count; i++)
105 if (!strcmpW(ctxt->ns[i].prefix, prefix))
113 if (This->override == VARIANT_TRUE)
115 SysFreeString(ns->uri);
116 ns->uri = SysAllocString(uri);
124 ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
125 ctxt->ns[ctxt->count].uri = SysAllocString(uri);
132 /* returned stored pointer, caller needs to copy it */
133 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
137 if (index >= ctxt->count || index < 0) return E_FAIL;
139 if (index > 0) index = ctxt->count - index;
140 *prefix = ctxt->ns[index].prefix;
145 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
149 for (i = 0; i < ctxt->count; i++)
150 if (!strcmpW(ctxt->ns[i].prefix, prefix))
152 *uri = ctxt->ns[i].uri;
160 static struct nscontext* alloc_ns_context(void)
162 struct nscontext *ctxt;
164 ctxt = heap_alloc(sizeof(*ctxt));
165 if (!ctxt) return NULL;
168 ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
169 ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
171 /* first allocated prefix is always 'xml' */
172 ctxt->ns[0].prefix = SysAllocString(xmlW);
173 ctxt->ns[0].uri = SysAllocString(xmluriW);
179 static void free_ns_context(struct nscontext *ctxt)
183 for (i = 0; i < ctxt->count; i++)
185 SysFreeString(ctxt->ns[i].prefix);
186 SysFreeString(ctxt->ns[i].uri);
193 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
195 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
196 return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
199 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
201 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
202 return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
205 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
207 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
208 return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
211 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
212 VARIANT_BOOL override)
214 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
215 return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
218 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
219 VARIANT_BOOL *override)
221 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
222 return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
225 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
227 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
228 return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
231 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
233 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
234 return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
237 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
238 IXMLDOMNode *node, VARIANT_BOOL deep)
240 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
241 return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
244 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
246 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
247 return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
250 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
251 const WCHAR *prefix, const WCHAR *namespaceURI)
253 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
255 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
257 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
259 if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
262 return declare_prefix(This, prefix, namespaceURI);
265 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
266 LONG index, WCHAR *prefix, int *prefix_len)
268 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
269 struct nscontext *ctxt;
273 TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
275 if (!prefix_len) return E_POINTER;
277 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
278 hr = get_declared_prefix_idx(ctxt, index, &prfx);
279 if (hr != S_OK) return hr;
283 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
284 strcpyW(prefix, prfx);
287 *prefix_len = SysStringLen(prfx);
292 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
293 const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
295 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
296 FIXME("(%p)->(%s %d %p %p): stub\n", This, debugstr_w(uri), index, prefix, prefix_len);
300 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
301 const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
303 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
304 struct nscontext *ctxt;
308 TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
310 if (!prefix) return E_INVALIDARG;
311 if (!uri_len) return E_POINTER;
315 FIXME("namespaces from DOM node not supported\n");
319 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
320 hr = get_uri_from_prefix(ctxt, prefix, &urib);
325 if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
332 *uri_len = SysStringLen(urib);
337 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
339 namespacemanager_QueryInterface,
340 namespacemanager_AddRef,
341 namespacemanager_Release,
342 namespacemanager_putAllowOverride,
343 namespacemanager_getAllowOverride,
344 namespacemanager_reset,
345 namespacemanager_pushContext,
346 namespacemanager_pushNodeContext,
347 namespacemanager_popContext,
348 namespacemanager_declarePrefix,
349 namespacemanager_getDeclaredPrefix,
350 namespacemanager_getPrefix,
351 namespacemanager_getURI
354 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **ppvObject)
356 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
357 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
359 if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
360 IsEqualGUID( riid, &IID_IUnknown) )
362 *ppvObject = &This->IMXNamespaceManager_iface;
364 else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
365 IsEqualGUID( riid, &IID_IDispatch) )
367 *ppvObject = &This->IVBMXNamespaceManager_iface;
371 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
373 return E_NOINTERFACE;
376 IVBMXNamespaceManager_AddRef( iface );
381 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
383 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
384 ULONG ref = InterlockedIncrement( &This->ref );
385 TRACE("(%p)->(%u)\n", This, ref );
389 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
391 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
392 ULONG ref = InterlockedDecrement( &This->ref );
394 TRACE("(%p)->(%u)\n", This, ref );
398 struct nscontext *ctxt, *ctxt2;
400 LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
402 list_remove(&ctxt->entry);
403 free_ns_context(ctxt);
412 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
414 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
416 TRACE("(%p)->(%p)\n", This, pctinfo);
422 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
423 LCID lcid, ITypeInfo **ppTInfo)
425 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
427 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
429 return get_typeinfo(IVBMXNamespaceManager_tid, ppTInfo);
432 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
433 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
435 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
439 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
442 if(!rgszNames || cNames == 0 || !rgDispId)
445 hr = get_typeinfo(IVBMXNamespaceManager_tid, &typeinfo);
448 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
449 ITypeInfo_Release(typeinfo);
455 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
456 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
457 EXCEPINFO *pExcepInfo, UINT *puArgErr)
459 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
463 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
464 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
466 hr = get_typeinfo(IVBMXNamespaceManager_tid, &typeinfo);
469 hr = ITypeInfo_Invoke(typeinfo, &This->IVBMXNamespaceManager_iface, dispIdMember, wFlags,
470 pDispParams, pVarResult, pExcepInfo, puArgErr);
471 ITypeInfo_Release(typeinfo);
477 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
478 VARIANT_BOOL override)
480 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
482 TRACE("(%p)->(%d)\n", This, override);
483 This->override = override;
488 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
489 VARIANT_BOOL *override)
491 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
493 TRACE("(%p)->(%p)\n", This, override);
495 if (!override) return E_POINTER;
496 *override = This->override;
501 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
503 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
504 FIXME("(%p): stub\n", This);
508 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
510 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
511 FIXME("(%p): stub\n", This);
515 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
516 IXMLDOMNode *node, VARIANT_BOOL deep)
518 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
519 FIXME("(%p)->(%p %d): stub\n", This, node, deep);
523 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
525 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
526 FIXME("(%p): stub\n", This);
530 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
531 BSTR prefix, BSTR namespaceURI)
533 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
534 return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
537 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
538 IMXNamespacePrefixes** prefixes)
540 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
541 FIXME("(%p)->(%p): stub\n", This, prefixes);
545 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
546 BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
548 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
549 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
553 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
554 BSTR prefix, VARIANT* uri)
556 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
557 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
561 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
562 BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
564 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
565 FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
569 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
571 vbnamespacemanager_QueryInterface,
572 vbnamespacemanager_AddRef,
573 vbnamespacemanager_Release,
574 vbnamespacemanager_GetTypeInfoCount,
575 vbnamespacemanager_GetTypeInfo,
576 vbnamespacemanager_GetIDsOfNames,
577 vbnamespacemanager_Invoke,
578 vbnamespacemanager_put_allowOverride,
579 vbnamespacemanager_get_allowOverride,
580 vbnamespacemanager_reset,
581 vbnamespacemanager_pushContext,
582 vbnamespacemanager_pushNodeContext,
583 vbnamespacemanager_popContext,
584 vbnamespacemanager_declarePrefix,
585 vbnamespacemanager_getDeclaredPrefixes,
586 vbnamespacemanager_getPrefixes,
587 vbnamespacemanager_getURI,
588 vbnamespacemanager_getURIFromNode
591 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
593 namespacemanager *ns;
594 struct nscontext *ctxt;
596 TRACE("(%p, %p)\n", outer, obj);
598 ns = heap_alloc( sizeof (*ns) );
600 return E_OUTOFMEMORY;
602 ns->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
603 ns->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
606 list_init(&ns->ctxts);
607 ctxt = alloc_ns_context();
608 list_add_head(&ns->ctxts, &ctxt->entry);
610 ns->override = VARIANT_TRUE;
612 *obj = &ns->IMXNamespaceManager_iface;
614 TRACE("returning iface %p\n", *obj);