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