xref: /reactos/dll/win32/msxml3/mxnamespace.c (revision 02e84521)
1 /*
2  *    IMXNamespaceManager implementation
3  *
4  * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #define COBJMACROS
22 
23 #include "config.h"
24 
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
31 
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "ole2.h"
36 #include "msxml6.h"
37 
38 #include "msxml_private.h"
39 
40 #include "wine/debug.h"
41 
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 
44 struct ns
45 {
46     BSTR prefix;
47     BSTR uri;
48 };
49 
50 struct nscontext
51 {
52     struct list entry;
53 
54     struct ns *ns;
55     int   count;
56     int   max_alloc;
57 };
58 
59 #define DEFAULT_PREFIX_ALLOC_COUNT 16
60 
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};
64 
65 typedef struct
66 {
67     DispatchEx dispex;
68     IMXNamespaceManager   IMXNamespaceManager_iface;
69     IVBMXNamespaceManager IVBMXNamespaceManager_iface;
70     LONG ref;
71 
72     struct list ctxts;
73 
74     VARIANT_BOOL override;
75 } namespacemanager;
76 
77 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
78 {
79     return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
80 }
81 
82 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
83 {
84     return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
85 }
86 
87 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
88 {
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;
93 
94     if (ctxt->count == ctxt->max_alloc)
95     {
96         ctxt->max_alloc *= 2;
97         ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
98     }
99 
100     if (!prefix) prefix = emptyW;
101 
102     ns = NULL;
103     for (i = 0; i < ctxt->count; i++)
104         if (!strcmpW(ctxt->ns[i].prefix, prefix))
105         {
106             ns = &ctxt->ns[i];
107             break;
108         }
109 
110     if (ns)
111     {
112         if (This->override == VARIANT_TRUE)
113         {
114             SysFreeString(ns->uri);
115             ns->uri = SysAllocString(uri);
116             return S_FALSE;
117         }
118         else
119             return E_FAIL;
120     }
121     else
122     {
123         ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
124         ctxt->ns[ctxt->count].uri = SysAllocString(uri);
125         ctxt->count++;
126     }
127 
128     return S_OK;
129 }
130 
131 /* returned stored pointer, caller needs to copy it */
132 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
133 {
134     *prefix = NULL;
135 
136     if (index >= ctxt->count || index < 0) return E_FAIL;
137 
138     if (index > 0) index = ctxt->count - index;
139     *prefix = ctxt->ns[index].prefix;
140 
141     return S_OK;
142 }
143 
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)
146 {
147     struct nscontext *ctxt;
148 
149     LIST_FOR_EACH_ENTRY(ctxt, ctxts, struct nscontext, entry)
150     {
151         int i;
152         for (i = 0; i < ctxt->count; i++)
153             if (!strcmpW(ctxt->ns[i].uri, uri))
154             {
155                 *prefix = ctxt->ns[i].prefix;
156                 return S_OK;
157             }
158     }
159 
160     *prefix = NULL;
161     return E_FAIL;
162 }
163 
164 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
165 {
166     int i;
167 
168     for (i = 0; i < ctxt->count; i++)
169         if (!strcmpW(ctxt->ns[i].prefix, prefix))
170         {
171             *uri = ctxt->ns[i].uri;
172             return S_OK;
173         }
174 
175     *uri = NULL;
176     return S_FALSE;
177 }
178 
179 static struct nscontext* alloc_ns_context(void)
180 {
181     struct nscontext *ctxt;
182 
183     ctxt = heap_alloc(sizeof(*ctxt));
184     if (!ctxt) return NULL;
185 
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)
190     {
191         heap_free(ctxt);
192         return NULL;
193     }
194 
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)
200     {
201         heap_free(ctxt->ns);
202         heap_free(ctxt);
203         return NULL;
204     }
205 
206     return ctxt;
207 }
208 
209 static void free_ns_context(struct nscontext *ctxt)
210 {
211     int i;
212 
213     for (i = 0; i < ctxt->count; i++)
214     {
215         SysFreeString(ctxt->ns[i].prefix);
216         SysFreeString(ctxt->ns[i].uri);
217     }
218 
219     heap_free(ctxt->ns);
220     heap_free(ctxt);
221 }
222 
223 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
224 {
225     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
226     return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
227 }
228 
229 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
230 {
231     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
232     return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
233 }
234 
235 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
236 {
237     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
238     return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
239 }
240 
241 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
242     VARIANT_BOOL override)
243 {
244     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
245     return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
246 }
247 
248 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
249     VARIANT_BOOL *override)
250 {
251     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
252     return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
253 }
254 
255 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
256 {
257     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
258     return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
259 }
260 
261 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
262 {
263     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
264     return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
265 }
266 
267 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
268     IXMLDOMNode *node, VARIANT_BOOL deep)
269 {
270     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
271     return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
272 }
273 
274 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
275 {
276     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
277     return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
278 }
279 
280 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
281     const WCHAR *prefix, const WCHAR *namespaceURI)
282 {
283     static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
284 
285     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
286 
287     TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
288 
289     if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
290         return E_INVALIDARG;
291 
292     return declare_prefix(This, prefix, namespaceURI);
293 }
294 
295 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
296     LONG index, WCHAR *prefix, int *prefix_len)
297 {
298     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
299     struct nscontext *ctxt;
300     HRESULT hr;
301     BSTR prfx;
302 
303     TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
304 
305     if (!prefix_len) return E_POINTER;
306 
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;
310 
311     if (prefix)
312     {
313         if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
314         strcpyW(prefix, prfx);
315     }
316 
317     *prefix_len = SysStringLen(prfx);
318 
319     return S_OK;
320 }
321 
322 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
323     const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
324 {
325     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
326     HRESULT hr;
327     BSTR prfx;
328 
329     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
330 
331     if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
332 
333     hr = get_declared_prefix_uri(&This->ctxts, uri, &prfx);
334     if (hr == S_OK)
335     {
336         /* TODO: figure out what index argument is for */
337         if (index) return E_FAIL;
338 
339         if (prefix)
340         {
341             if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
342             strcpyW(prefix, prfx);
343         }
344 
345         *prefix_len = SysStringLen(prfx);
346         TRACE("prefix=%s\n", debugstr_w(prfx));
347     }
348 
349     return hr;
350 }
351 
352 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
353     const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
354 {
355     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
356     struct nscontext *ctxt;
357     HRESULT hr;
358     BSTR urib;
359 
360     TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
361 
362     if (!prefix) return E_INVALIDARG;
363     if (!uri_len) return E_POINTER;
364 
365     if (node)
366     {
367         FIXME("namespaces from DOM node not supported\n");
368         return E_NOTIMPL;
369     }
370 
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)
374     {
375         if (uri)
376         {
377            if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
378            strcpyW(uri, urib);
379         }
380     }
381     else
382         if (uri) *uri = 0;
383 
384     *uri_len = SysStringLen(urib);
385 
386     return hr;
387 }
388 
389 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
390 {
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
404 };
405 
406 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
407 {
408     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
409     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
410 
411     if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
412          IsEqualGUID( riid, &IID_IUnknown) )
413     {
414         *obj = &This->IMXNamespaceManager_iface;
415     }
416     else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
417               IsEqualGUID( riid, &IID_IDispatch) )
418     {
419         *obj = &This->IVBMXNamespaceManager_iface;
420     }
421     else if (dispex_query_interface(&This->dispex, riid, obj))
422     {
423         return *obj ? S_OK : E_NOINTERFACE;
424     }
425     else
426     {
427         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
428         *obj = NULL;
429         return E_NOINTERFACE;
430     }
431 
432     IVBMXNamespaceManager_AddRef( iface );
433 
434     return S_OK;
435 }
436 
437 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
438 {
439     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
440     ULONG ref = InterlockedIncrement( &This->ref );
441     TRACE("(%p)->(%u)\n", This, ref );
442     return ref;
443 }
444 
445 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
446 {
447     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
448     ULONG ref = InterlockedDecrement( &This->ref );
449 
450     TRACE("(%p)->(%u)\n", This, ref );
451 
452     if ( ref == 0 )
453     {
454         struct nscontext *ctxt, *ctxt2;
455 
456         LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
457         {
458             list_remove(&ctxt->entry);
459             free_ns_context(ctxt);
460         }
461 
462         heap_free( This );
463     }
464 
465     return ref;
466 }
467 
468 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
469 {
470     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
471     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
472 }
473 
474 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
475         LCID lcid, ITypeInfo **ppTInfo)
476 {
477     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
478     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
479         iTInfo, lcid, ppTInfo);
480 }
481 
482 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
483         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
484 {
485     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
486     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
487         riid, rgszNames, cNames, lcid, rgDispId);
488 }
489 
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)
493 {
494     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
495     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
496         dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
497 }
498 
499 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
500     VARIANT_BOOL override)
501 {
502     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
503 
504     TRACE("(%p)->(%d)\n", This, override);
505     This->override = override;
506 
507     return S_OK;
508 }
509 
510 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
511     VARIANT_BOOL *override)
512 {
513     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
514 
515     TRACE("(%p)->(%p)\n", This, override);
516 
517     if (!override) return E_POINTER;
518     *override = This->override;
519 
520     return S_OK;
521 }
522 
523 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
524 {
525     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
526     FIXME("(%p): stub\n", This);
527     return E_NOTIMPL;
528 }
529 
530 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
531 {
532     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
533     struct nscontext *ctxt;
534 
535     TRACE("(%p)\n", This);
536 
537     ctxt = alloc_ns_context();
538     if (!ctxt) return E_OUTOFMEMORY;
539 
540     list_add_head(&This->ctxts, &ctxt->entry);
541 
542     return S_OK;
543 }
544 
545 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
546     IXMLDOMNode *node, VARIANT_BOOL deep)
547 {
548     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
549     FIXME("(%p)->(%p %d): stub\n", This, node, deep);
550     return E_NOTIMPL;
551 }
552 
553 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
554 {
555     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
556     const struct list *next;
557     struct nscontext *ctxt;
558 
559     TRACE("(%p)\n", This);
560 
561     next = list_next(&This->ctxts, list_head(&This->ctxts));
562     if (!next) return E_FAIL;
563 
564     ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
565     list_remove(list_head(&This->ctxts));
566 
567     free_ns_context(ctxt);
568 
569     return S_OK;
570 }
571 
572 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
573     BSTR prefix, BSTR namespaceURI)
574 {
575     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
576     return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
577 }
578 
579 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
580     IMXNamespacePrefixes** prefixes)
581 {
582     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
583     FIXME("(%p)->(%p): stub\n", This, prefixes);
584     return E_NOTIMPL;
585 }
586 
587 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
588     BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
589 {
590     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
591     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
592     return E_NOTIMPL;
593 }
594 
595 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
596     BSTR prefix, VARIANT* uri)
597 {
598     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
599     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
600     return E_NOTIMPL;
601 }
602 
603 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
604     BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
605 {
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;
609 }
610 
611 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
612 {
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
631 };
632 
633 static const tid_t namespacemanager_iface_tids[] = {
634     IVBMXNamespaceManager_tid,
635     0
636 };
637 
638 static dispex_static_data_t namespacemanager_dispex = {
639     NULL,
640     IVBMXNamespaceManager_tid,
641     NULL,
642     namespacemanager_iface_tids
643 };
644 
645 HRESULT MXNamespaceManager_create(void **obj)
646 {
647     namespacemanager *This;
648     struct nscontext *ctxt;
649 
650     TRACE("(%p)\n", obj);
651 
652     This = heap_alloc( sizeof (*This) );
653     if( !This )
654         return E_OUTOFMEMORY;
655 
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);
660 
661     list_init(&This->ctxts);
662     ctxt = alloc_ns_context();
663     if (!ctxt)
664     {
665         heap_free(This);
666         return E_OUTOFMEMORY;
667     }
668 
669     list_add_head(&This->ctxts, &ctxt->entry);
670 
671     This->override = VARIANT_TRUE;
672 
673     *obj = &This->IMXNamespaceManager_iface;
674 
675     TRACE("returning iface %p\n", *obj);
676 
677     return S_OK;
678 }
679