urlmon: Use wine lists to store namespaces and MIME filters.
[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 nscontext *ctxt, const WCHAR *uri, BSTR *prefix)
148 {
149     int i;
150
151     for (i = 0; i < ctxt->count; i++)
152         if (!strcmpW(ctxt->ns[i].uri, uri))
153         {
154             *prefix = ctxt->ns[i].prefix;
155             return S_OK;
156         }
157
158     *prefix = NULL;
159     return E_FAIL;
160 }
161
162 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
163 {
164     int i;
165
166     for (i = 0; i < ctxt->count; i++)
167         if (!strcmpW(ctxt->ns[i].prefix, prefix))
168         {
169             *uri = ctxt->ns[i].uri;
170             return S_OK;
171         }
172
173     *uri = NULL;
174     return S_FALSE;
175 }
176
177 static struct nscontext* alloc_ns_context(void)
178 {
179     struct nscontext *ctxt;
180
181     ctxt = heap_alloc(sizeof(*ctxt));
182     if (!ctxt) return NULL;
183
184     ctxt->count = 0;
185     ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
186     ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
187
188     /* first allocated prefix is always 'xml' */
189     ctxt->ns[0].prefix = SysAllocString(xmlW);
190     ctxt->ns[0].uri = SysAllocString(xmluriW);
191     ctxt->count++;
192
193     return ctxt;
194 }
195
196 static void free_ns_context(struct nscontext *ctxt)
197 {
198     int i;
199
200     for (i = 0; i < ctxt->count; i++)
201     {
202         SysFreeString(ctxt->ns[i].prefix);
203         SysFreeString(ctxt->ns[i].uri);
204     }
205
206     heap_free(ctxt->ns);
207     heap_free(ctxt);
208 }
209
210 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
211 {
212     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
213     return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
214 }
215
216 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
217 {
218     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
219     return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
220 }
221
222 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
223 {
224     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
225     return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
226 }
227
228 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
229     VARIANT_BOOL override)
230 {
231     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
232     return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
233 }
234
235 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
236     VARIANT_BOOL *override)
237 {
238     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
239     return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
240 }
241
242 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
243 {
244     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
245     return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
246 }
247
248 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
249 {
250     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
251     return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
252 }
253
254 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
255     IXMLDOMNode *node, VARIANT_BOOL deep)
256 {
257     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
258     return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
259 }
260
261 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
262 {
263     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
264     return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
265 }
266
267 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
268     const WCHAR *prefix, const WCHAR *namespaceURI)
269 {
270     static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
271
272     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
273
274     TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
275
276     if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
277         return E_INVALIDARG;
278
279     return declare_prefix(This, prefix, namespaceURI);
280 }
281
282 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
283     LONG index, WCHAR *prefix, int *prefix_len)
284 {
285     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
286     struct nscontext *ctxt;
287     HRESULT hr;
288     BSTR prfx;
289
290     TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
291
292     if (!prefix_len) return E_POINTER;
293
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;
297
298     if (prefix)
299     {
300         if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
301         strcpyW(prefix, prfx);
302     }
303
304     *prefix_len = SysStringLen(prfx);
305
306     return S_OK;
307 }
308
309 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
310     const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
311 {
312     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
313     struct nscontext *ctxt;
314     HRESULT hr;
315     BSTR prfx;
316
317     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
318
319     if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
320
321     ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
322
323     hr = get_declared_prefix_uri(ctxt, uri, &prfx);
324     if (hr == S_OK)
325     {
326         /* TODO: figure out what index argument is for */
327         if (index) return E_FAIL;
328
329         if (prefix)
330         {
331             if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
332             strcpyW(prefix, prfx);
333         }
334
335         *prefix_len = SysStringLen(prfx);
336         TRACE("prefix=%s\n", debugstr_w(prfx));
337     }
338
339     return hr;
340 }
341
342 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
343     const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
344 {
345     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
346     struct nscontext *ctxt;
347     HRESULT hr;
348     BSTR urib;
349
350     TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
351
352     if (!prefix) return E_INVALIDARG;
353     if (!uri_len) return E_POINTER;
354
355     if (node)
356     {
357         FIXME("namespaces from DOM node not supported\n");
358         return E_NOTIMPL;
359     }
360
361     ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
362     hr = get_uri_from_prefix(ctxt, prefix, &urib);
363     if (hr == S_OK)
364     {
365         if (uri)
366         {
367            if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
368            strcpyW(uri, urib);
369         }
370     }
371     else
372         if (uri) *uri = 0;
373
374     *uri_len = SysStringLen(urib);
375
376     return hr;
377 }
378
379 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
380 {
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
394 };
395
396 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
397 {
398     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
399     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
400
401     if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
402          IsEqualGUID( riid, &IID_IUnknown) )
403     {
404         *obj = &This->IMXNamespaceManager_iface;
405     }
406     else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
407               IsEqualGUID( riid, &IID_IDispatch) )
408     {
409         *obj = &This->IVBMXNamespaceManager_iface;
410     }
411     else if (dispex_query_interface(&This->dispex, riid, obj))
412     {
413         return *obj ? S_OK : E_NOINTERFACE;
414     }
415     else
416     {
417         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
418         *obj = NULL;
419         return E_NOINTERFACE;
420     }
421
422     IVBMXNamespaceManager_AddRef( iface );
423
424     return S_OK;
425 }
426
427 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
428 {
429     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
430     ULONG ref = InterlockedIncrement( &This->ref );
431     TRACE("(%p)->(%u)\n", This, ref );
432     return ref;
433 }
434
435 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
436 {
437     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
438     ULONG ref = InterlockedDecrement( &This->ref );
439
440     TRACE("(%p)->(%u)\n", This, ref );
441
442     if ( ref == 0 )
443     {
444         struct nscontext *ctxt, *ctxt2;
445
446         LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
447         {
448             list_remove(&ctxt->entry);
449             free_ns_context(ctxt);
450         }
451
452         release_dispex(&This->dispex);
453         heap_free( This );
454     }
455
456     return ref;
457 }
458
459 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
460 {
461     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
462     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
463 }
464
465 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
466         LCID lcid, ITypeInfo **ppTInfo)
467 {
468     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
469     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
470         iTInfo, lcid, ppTInfo);
471 }
472
473 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
474         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
475 {
476     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
477     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
478         riid, rgszNames, cNames, lcid, rgDispId);
479 }
480
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)
484 {
485     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
486     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
487         dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
488 }
489
490 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
491     VARIANT_BOOL override)
492 {
493     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
494
495     TRACE("(%p)->(%d)\n", This, override);
496     This->override = override;
497
498     return S_OK;
499 }
500
501 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
502     VARIANT_BOOL *override)
503 {
504     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
505
506     TRACE("(%p)->(%p)\n", This, override);
507
508     if (!override) return E_POINTER;
509     *override = This->override;
510
511     return S_OK;
512 }
513
514 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
515 {
516     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
517     FIXME("(%p): stub\n", This);
518     return E_NOTIMPL;
519 }
520
521 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
522 {
523     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
524     FIXME("(%p): stub\n", This);
525     return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
529     IXMLDOMNode *node, VARIANT_BOOL deep)
530 {
531     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
532     FIXME("(%p)->(%p %d): stub\n", This, node, deep);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
537 {
538     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
539     FIXME("(%p): stub\n", This);
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
544     BSTR prefix, BSTR namespaceURI)
545 {
546     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
547     return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
548 }
549
550 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
551     IMXNamespacePrefixes** prefixes)
552 {
553     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
554     FIXME("(%p)->(%p): stub\n", This, prefixes);
555     return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
559     BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
560 {
561     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
562     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
563     return E_NOTIMPL;
564 }
565
566 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
567     BSTR prefix, VARIANT* uri)
568 {
569     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
570     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
571     return E_NOTIMPL;
572 }
573
574 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
575     BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
576 {
577     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
578     FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
579     return E_NOTIMPL;
580 }
581
582 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
583 {
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
602 };
603
604 static const tid_t namespacemanager_iface_tids[] = {
605     IVBMXNamespaceManager_tid,
606     0
607 };
608 static dispex_static_data_t namespacemanager_dispex = {
609     NULL,
610     IVBMXNamespaceManager_tid,
611     NULL,
612     namespacemanager_iface_tids
613 };
614
615 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
616 {
617     namespacemanager *This;
618     struct nscontext *ctxt;
619
620     TRACE("(%p, %p)\n", outer, obj);
621
622     This = heap_alloc( sizeof (*This) );
623     if( !This )
624         return E_OUTOFMEMORY;
625
626     This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
627     This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
628     This->ref = 1;
629     init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
630
631     list_init(&This->ctxts);
632     ctxt = alloc_ns_context();
633     list_add_head(&This->ctxts, &ctxt->entry);
634
635     This->override = VARIANT_TRUE;
636
637     *obj = &This->IMXNamespaceManager_iface;
638
639     TRACE("returning iface %p\n", *obj);
640
641     return S_OK;
642 }