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 WIN32_NO_STATUS
25 #define NONAMELESSUNION
31 # include <libxml/parser.h>
32 //# include <libxml/xmlerror.h>
33 //# include <libxml/encoding.h>
38 //#include "winuser.h"
42 #include "msxml_private.h"
44 #include <wine/debug.h>
45 #include <wine/list.h>
47 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
64 #define DEFAULT_PREFIX_ALLOC_COUNT 16
66 static const WCHAR xmlW
[] = {'x','m','l',0};
67 static const WCHAR xmluriW
[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
68 '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
73 IMXNamespaceManager IMXNamespaceManager_iface
;
74 IVBMXNamespaceManager IVBMXNamespaceManager_iface
;
79 VARIANT_BOOL override
;
82 static inline namespacemanager
*impl_from_IMXNamespaceManager( IMXNamespaceManager
*iface
)
84 return CONTAINING_RECORD(iface
, namespacemanager
, IMXNamespaceManager_iface
);
87 static inline namespacemanager
*impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager
*iface
)
89 return CONTAINING_RECORD(iface
, namespacemanager
, IVBMXNamespaceManager_iface
);
92 static HRESULT
declare_prefix(namespacemanager
*This
, const WCHAR
*prefix
, const WCHAR
*uri
)
94 struct nscontext
*ctxt
= LIST_ENTRY(list_head(&This
->ctxts
), struct nscontext
, entry
);
95 static const WCHAR emptyW
[] = {0};
99 if (ctxt
->count
== ctxt
->max_alloc
)
101 ctxt
->max_alloc
*= 2;
102 ctxt
->ns
= heap_realloc(ctxt
->ns
, ctxt
->max_alloc
*sizeof(*ctxt
->ns
));
105 if (!prefix
) prefix
= emptyW
;
108 for (i
= 0; i
< ctxt
->count
; i
++)
109 if (!strcmpW(ctxt
->ns
[i
].prefix
, prefix
))
117 if (This
->override
== VARIANT_TRUE
)
119 SysFreeString(ns
->uri
);
120 ns
->uri
= SysAllocString(uri
);
128 ctxt
->ns
[ctxt
->count
].prefix
= SysAllocString(prefix
);
129 ctxt
->ns
[ctxt
->count
].uri
= SysAllocString(uri
);
136 /* returned stored pointer, caller needs to copy it */
137 static HRESULT
get_declared_prefix_idx(const struct nscontext
*ctxt
, LONG index
, BSTR
*prefix
)
141 if (index
>= ctxt
->count
|| index
< 0) return E_FAIL
;
143 if (index
> 0) index
= ctxt
->count
- index
;
144 *prefix
= ctxt
->ns
[index
].prefix
;
149 /* returned stored pointer, caller needs to copy it */
150 static HRESULT
get_declared_prefix_uri(const struct list
*ctxts
, const WCHAR
*uri
, BSTR
*prefix
)
152 struct nscontext
*ctxt
;
154 LIST_FOR_EACH_ENTRY(ctxt
, ctxts
, struct nscontext
, entry
)
157 for (i
= 0; i
< ctxt
->count
; i
++)
158 if (!strcmpW(ctxt
->ns
[i
].uri
, uri
))
160 *prefix
= ctxt
->ns
[i
].prefix
;
169 static HRESULT
get_uri_from_prefix(const struct nscontext
*ctxt
, const WCHAR
*prefix
, BSTR
*uri
)
173 for (i
= 0; i
< ctxt
->count
; i
++)
174 if (!strcmpW(ctxt
->ns
[i
].prefix
, prefix
))
176 *uri
= ctxt
->ns
[i
].uri
;
184 static struct nscontext
* alloc_ns_context(void)
186 struct nscontext
*ctxt
;
188 ctxt
= heap_alloc(sizeof(*ctxt
));
189 if (!ctxt
) return NULL
;
192 ctxt
->max_alloc
= DEFAULT_PREFIX_ALLOC_COUNT
;
193 ctxt
->ns
= heap_alloc(ctxt
->max_alloc
*sizeof(*ctxt
->ns
));
200 /* first allocated prefix is always 'xml' */
201 ctxt
->ns
[0].prefix
= SysAllocString(xmlW
);
202 ctxt
->ns
[0].uri
= SysAllocString(xmluriW
);
204 if (!ctxt
->ns
[0].prefix
|| !ctxt
->ns
[0].uri
)
214 static void free_ns_context(struct nscontext
*ctxt
)
218 for (i
= 0; i
< ctxt
->count
; i
++)
220 SysFreeString(ctxt
->ns
[i
].prefix
);
221 SysFreeString(ctxt
->ns
[i
].uri
);
228 static HRESULT WINAPI
namespacemanager_QueryInterface(IMXNamespaceManager
*iface
, REFIID riid
, void **ppvObject
)
230 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
231 return IVBMXNamespaceManager_QueryInterface(&This
->IVBMXNamespaceManager_iface
, riid
, ppvObject
);
234 static ULONG WINAPI
namespacemanager_AddRef(IMXNamespaceManager
*iface
)
236 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
237 return IVBMXNamespaceManager_AddRef(&This
->IVBMXNamespaceManager_iface
);
240 static ULONG WINAPI
namespacemanager_Release(IMXNamespaceManager
*iface
)
242 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
243 return IVBMXNamespaceManager_Release(&This
->IVBMXNamespaceManager_iface
);
246 static HRESULT WINAPI
namespacemanager_putAllowOverride(IMXNamespaceManager
*iface
,
247 VARIANT_BOOL override
)
249 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
250 return IVBMXNamespaceManager_put_allowOverride(&This
->IVBMXNamespaceManager_iface
, override
);
253 static HRESULT WINAPI
namespacemanager_getAllowOverride(IMXNamespaceManager
*iface
,
254 VARIANT_BOOL
*override
)
256 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
257 return IVBMXNamespaceManager_get_allowOverride(&This
->IVBMXNamespaceManager_iface
, override
);
260 static HRESULT WINAPI
namespacemanager_reset(IMXNamespaceManager
*iface
)
262 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
263 return IVBMXNamespaceManager_reset(&This
->IVBMXNamespaceManager_iface
);
266 static HRESULT WINAPI
namespacemanager_pushContext(IMXNamespaceManager
*iface
)
268 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
269 return IVBMXNamespaceManager_pushContext(&This
->IVBMXNamespaceManager_iface
);
272 static HRESULT WINAPI
namespacemanager_pushNodeContext(IMXNamespaceManager
*iface
,
273 IXMLDOMNode
*node
, VARIANT_BOOL deep
)
275 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
276 return IVBMXNamespaceManager_pushNodeContext(&This
->IVBMXNamespaceManager_iface
, node
, deep
);
279 static HRESULT WINAPI
namespacemanager_popContext(IMXNamespaceManager
*iface
)
281 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
282 return IVBMXNamespaceManager_popContext(&This
->IVBMXNamespaceManager_iface
);
285 static HRESULT WINAPI
namespacemanager_declarePrefix(IMXNamespaceManager
*iface
,
286 const WCHAR
*prefix
, const WCHAR
*namespaceURI
)
288 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
290 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
292 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(prefix
), debugstr_w(namespaceURI
));
294 if (prefix
&& (!strcmpW(prefix
, xmlW
) || !strcmpW(prefix
, xmlnsW
) || !namespaceURI
))
297 return declare_prefix(This
, prefix
, namespaceURI
);
300 static HRESULT WINAPI
namespacemanager_getDeclaredPrefix(IMXNamespaceManager
*iface
,
301 LONG index
, WCHAR
*prefix
, int *prefix_len
)
303 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
304 struct nscontext
*ctxt
;
308 TRACE("(%p)->(%d %p %p)\n", This
, index
, prefix
, prefix_len
);
310 if (!prefix_len
) return E_POINTER
;
312 ctxt
= LIST_ENTRY(list_head(&This
->ctxts
), struct nscontext
, entry
);
313 hr
= get_declared_prefix_idx(ctxt
, index
, &prfx
);
314 if (hr
!= S_OK
) return hr
;
318 if (*prefix_len
< (INT
)SysStringLen(prfx
)) return E_XML_BUFFERTOOSMALL
;
319 strcpyW(prefix
, prfx
);
322 *prefix_len
= SysStringLen(prfx
);
327 static HRESULT WINAPI
namespacemanager_getPrefix(IMXNamespaceManager
*iface
,
328 const WCHAR
*uri
, LONG index
, WCHAR
*prefix
, int *prefix_len
)
330 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
334 TRACE("(%p)->(%s %d %p %p)\n", This
, debugstr_w(uri
), index
, prefix
, prefix_len
);
336 if (!uri
|| !*uri
|| !prefix_len
) return E_INVALIDARG
;
338 hr
= get_declared_prefix_uri(&This
->ctxts
, uri
, &prfx
);
341 /* TODO: figure out what index argument is for */
342 if (index
) return E_FAIL
;
346 if (*prefix_len
< (INT
)SysStringLen(prfx
)) return E_XML_BUFFERTOOSMALL
;
347 strcpyW(prefix
, prfx
);
350 *prefix_len
= SysStringLen(prfx
);
351 TRACE("prefix=%s\n", debugstr_w(prfx
));
357 static HRESULT WINAPI
namespacemanager_getURI(IMXNamespaceManager
*iface
,
358 const WCHAR
*prefix
, IXMLDOMNode
*node
, WCHAR
*uri
, int *uri_len
)
360 namespacemanager
*This
= impl_from_IMXNamespaceManager( iface
);
361 struct nscontext
*ctxt
;
365 TRACE("(%p)->(%s %p %p %p)\n", This
, debugstr_w(prefix
), node
, uri
, uri_len
);
367 if (!prefix
) return E_INVALIDARG
;
368 if (!uri_len
) return E_POINTER
;
372 FIXME("namespaces from DOM node not supported\n");
376 ctxt
= LIST_ENTRY(list_head(&This
->ctxts
), struct nscontext
, entry
);
377 hr
= get_uri_from_prefix(ctxt
, prefix
, &urib
);
382 if (*uri_len
< (INT
)SysStringLen(urib
)) return E_XML_BUFFERTOOSMALL
;
389 *uri_len
= SysStringLen(urib
);
394 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl
=
396 namespacemanager_QueryInterface
,
397 namespacemanager_AddRef
,
398 namespacemanager_Release
,
399 namespacemanager_putAllowOverride
,
400 namespacemanager_getAllowOverride
,
401 namespacemanager_reset
,
402 namespacemanager_pushContext
,
403 namespacemanager_pushNodeContext
,
404 namespacemanager_popContext
,
405 namespacemanager_declarePrefix
,
406 namespacemanager_getDeclaredPrefix
,
407 namespacemanager_getPrefix
,
408 namespacemanager_getURI
411 static HRESULT WINAPI
vbnamespacemanager_QueryInterface(IVBMXNamespaceManager
*iface
, REFIID riid
, void **obj
)
413 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
414 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
416 if ( IsEqualGUID( riid
, &IID_IMXNamespaceManager
) ||
417 IsEqualGUID( riid
, &IID_IUnknown
) )
419 *obj
= &This
->IMXNamespaceManager_iface
;
421 else if ( IsEqualGUID( riid
, &IID_IVBMXNamespaceManager
) ||
422 IsEqualGUID( riid
, &IID_IDispatch
) )
424 *obj
= &This
->IVBMXNamespaceManager_iface
;
426 else if (dispex_query_interface(&This
->dispex
, riid
, obj
))
428 return *obj
? S_OK
: E_NOINTERFACE
;
432 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
434 return E_NOINTERFACE
;
437 IVBMXNamespaceManager_AddRef( iface
);
442 static ULONG WINAPI
vbnamespacemanager_AddRef(IVBMXNamespaceManager
*iface
)
444 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
445 ULONG ref
= InterlockedIncrement( &This
->ref
);
446 TRACE("(%p)->(%u)\n", This
, ref
);
450 static ULONG WINAPI
vbnamespacemanager_Release(IVBMXNamespaceManager
*iface
)
452 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
453 ULONG ref
= InterlockedDecrement( &This
->ref
);
455 TRACE("(%p)->(%u)\n", This
, ref
);
459 struct nscontext
*ctxt
, *ctxt2
;
461 LIST_FOR_EACH_ENTRY_SAFE(ctxt
, ctxt2
, &This
->ctxts
, struct nscontext
, entry
)
463 list_remove(&ctxt
->entry
);
464 free_ns_context(ctxt
);
467 release_dispex(&This
->dispex
);
474 static HRESULT WINAPI
vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager
*iface
, UINT
*pctinfo
)
476 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
477 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
480 static HRESULT WINAPI
vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager
*iface
, UINT iTInfo
,
481 LCID lcid
, ITypeInfo
**ppTInfo
)
483 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
484 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
485 iTInfo
, lcid
, ppTInfo
);
488 static HRESULT WINAPI
vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager
*iface
, REFIID riid
,
489 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
491 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
492 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
493 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
496 static HRESULT WINAPI
vbnamespacemanager_Invoke(IVBMXNamespaceManager
*iface
, DISPID dispIdMember
, REFIID riid
,
497 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
498 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
500 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
501 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
502 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
505 static HRESULT WINAPI
vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager
*iface
,
506 VARIANT_BOOL override
)
508 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
510 TRACE("(%p)->(%d)\n", This
, override
);
511 This
->override
= override
;
516 static HRESULT WINAPI
vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager
*iface
,
517 VARIANT_BOOL
*override
)
519 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
521 TRACE("(%p)->(%p)\n", This
, override
);
523 if (!override
) return E_POINTER
;
524 *override
= This
->override
;
529 static HRESULT WINAPI
vbnamespacemanager_reset(IVBMXNamespaceManager
*iface
)
531 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
532 FIXME("(%p): stub\n", This
);
536 static HRESULT WINAPI
vbnamespacemanager_pushContext(IVBMXNamespaceManager
*iface
)
538 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
539 struct nscontext
*ctxt
;
541 TRACE("(%p)\n", This
);
543 ctxt
= alloc_ns_context();
544 if (!ctxt
) return E_OUTOFMEMORY
;
546 list_add_head(&This
->ctxts
, &ctxt
->entry
);
551 static HRESULT WINAPI
vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager
*iface
,
552 IXMLDOMNode
*node
, VARIANT_BOOL deep
)
554 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
555 FIXME("(%p)->(%p %d): stub\n", This
, node
, deep
);
559 static HRESULT WINAPI
vbnamespacemanager_popContext(IVBMXNamespaceManager
*iface
)
561 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
562 const struct list
*next
;
563 struct nscontext
*ctxt
;
565 TRACE("(%p)\n", This
);
567 next
= list_next(&This
->ctxts
, list_head(&This
->ctxts
));
568 if (!next
) return E_FAIL
;
570 ctxt
= LIST_ENTRY(list_head(&This
->ctxts
), struct nscontext
, entry
);
571 list_remove(list_head(&This
->ctxts
));
573 free_ns_context(ctxt
);
578 static HRESULT WINAPI
vbnamespacemanager_declarePrefix(IVBMXNamespaceManager
*iface
,
579 BSTR prefix
, BSTR namespaceURI
)
581 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
582 return IMXNamespaceManager_declarePrefix(&This
->IMXNamespaceManager_iface
, prefix
, namespaceURI
);
585 static HRESULT WINAPI
vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager
*iface
,
586 IMXNamespacePrefixes
** prefixes
)
588 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
589 FIXME("(%p)->(%p): stub\n", This
, prefixes
);
593 static HRESULT WINAPI
vbnamespacemanager_getPrefixes(IVBMXNamespaceManager
*iface
,
594 BSTR namespaceURI
, IMXNamespacePrefixes
** prefixes
)
596 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
597 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(namespaceURI
), prefixes
);
601 static HRESULT WINAPI
vbnamespacemanager_getURI(IVBMXNamespaceManager
*iface
,
602 BSTR prefix
, VARIANT
* uri
)
604 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
605 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_w(prefix
), uri
);
609 static HRESULT WINAPI
vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager
*iface
,
610 BSTR prefix
, IXMLDOMNode
*node
, VARIANT
*uri
)
612 namespacemanager
*This
= impl_from_IVBMXNamespaceManager( iface
);
613 FIXME("(%p)->(%s %p %p): stub\n", This
, debugstr_w(prefix
), node
, uri
);
617 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl
=
619 vbnamespacemanager_QueryInterface
,
620 vbnamespacemanager_AddRef
,
621 vbnamespacemanager_Release
,
622 vbnamespacemanager_GetTypeInfoCount
,
623 vbnamespacemanager_GetTypeInfo
,
624 vbnamespacemanager_GetIDsOfNames
,
625 vbnamespacemanager_Invoke
,
626 vbnamespacemanager_put_allowOverride
,
627 vbnamespacemanager_get_allowOverride
,
628 vbnamespacemanager_reset
,
629 vbnamespacemanager_pushContext
,
630 vbnamespacemanager_pushNodeContext
,
631 vbnamespacemanager_popContext
,
632 vbnamespacemanager_declarePrefix
,
633 vbnamespacemanager_getDeclaredPrefixes
,
634 vbnamespacemanager_getPrefixes
,
635 vbnamespacemanager_getURI
,
636 vbnamespacemanager_getURIFromNode
639 static const tid_t namespacemanager_iface_tids
[] = {
640 IVBMXNamespaceManager_tid
,
644 static dispex_static_data_t namespacemanager_dispex
= {
646 IVBMXNamespaceManager_tid
,
648 namespacemanager_iface_tids
651 HRESULT
MXNamespaceManager_create(IUnknown
*outer
, void **obj
)
653 namespacemanager
*This
;
654 struct nscontext
*ctxt
;
656 TRACE("(%p, %p)\n", outer
, obj
);
658 This
= heap_alloc( sizeof (*This
) );
660 return E_OUTOFMEMORY
;
662 This
->IMXNamespaceManager_iface
.lpVtbl
= &MXNamespaceManagerVtbl
;
663 This
->IVBMXNamespaceManager_iface
.lpVtbl
= &VBMXNamespaceManagerVtbl
;
665 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IVBMXNamespaceManager_iface
, &namespacemanager_dispex
);
667 list_init(&This
->ctxts
);
668 ctxt
= alloc_ns_context();
672 return E_OUTOFMEMORY
;
675 list_add_head(&This
->ctxts
, &ctxt
->entry
);
677 This
->override
= VARIANT_TRUE
;
679 *obj
= &This
->IMXNamespaceManager_iface
;
681 TRACE("returning iface %p\n", *obj
);