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