>From af84765fd68e23a1b5dcf30a07e1abf527da1553 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Sun, 11 Dec 2011 14:31:05 +0300
Subject: [PATCH 8/9] IDispatchEx support for MXNamespaceManager

---
 dlls/msxml3/mxnamespace.c  |   96 ++++++++++++++-------------------
 dlls/msxml3/tests/domdoc.c |  129 +++++++++++++++++++++++--------------------
 2 files changed, 109 insertions(+), 116 deletions(-)

diff --git a/dlls/msxml3/mxnamespace.c b/dlls/msxml3/mxnamespace.c
index 17fbab8..dbfbdc6 100644
--- a/dlls/msxml3/mxnamespace.c
+++ b/dlls/msxml3/mxnamespace.c
@@ -66,6 +66,7 @@ static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w',
 
 typedef struct
 {
+    DispatchEx dispex;
     IMXNamespaceManager   IMXNamespaceManager_iface;
     IVBMXNamespaceManager IVBMXNamespaceManager_iface;
     LONG ref;
@@ -351,25 +352,29 @@ static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
     namespacemanager_getURI
 };
 
-static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **ppvObject)
+static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
 
     if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
          IsEqualGUID( riid, &IID_IUnknown) )
     {
-        *ppvObject = &This->IMXNamespaceManager_iface;
+        *obj = &This->IMXNamespaceManager_iface;
     }
     else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
               IsEqualGUID( riid, &IID_IDispatch) )
     {
-        *ppvObject = &This->IVBMXNamespaceManager_iface;
+        *obj = &This->IVBMXNamespaceManager_iface;
+    }
+    else if (dispex_query_interface(&This->dispex, riid, obj))
+    {
+        return *obj ? S_OK : E_NOINTERFACE;
     }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
-        *ppvObject = NULL;
+        *obj = NULL;
         return E_NOINTERFACE;
     }
 
@@ -403,6 +408,7 @@ static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
             free_ns_context(ctxt);
         }
 
+        release_dispex(&This->dispex);
         heap_free( This );
     }
 
@@ -412,44 +418,23 @@ static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-
-    TRACE("(%p)->(%p)\n", This, pctinfo);
-    *pctinfo = 1;
-
-    return S_OK;
+    return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
 }
 
 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
         LCID lcid, ITypeInfo **ppTInfo)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-
-    TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
-
-    return get_typeinfo(IVBMXNamespaceManager_tid, ppTInfo);
+    return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
+        iTInfo, lcid, ppTInfo);
 }
 
 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-    ITypeInfo *typeinfo;
-    HRESULT hr;
-
-    TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
-          lcid, rgDispId);
-
-    if(!rgszNames || cNames == 0 || !rgDispId)
-        return E_INVALIDARG;
-
-    hr = get_typeinfo(IVBMXNamespaceManager_tid, &typeinfo);
-    if(SUCCEEDED(hr))
-    {
-        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
-        ITypeInfo_Release(typeinfo);
-    }
-
-    return hr;
+    return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
+        riid, rgszNames, cNames, lcid, rgDispId);
 }
 
 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
@@ -457,21 +442,8 @@ static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DI
         EXCEPINFO *pExcepInfo, UINT *puArgErr)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-    ITypeInfo *typeinfo;
-    HRESULT hr;
-
-    TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
-          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
-
-    hr = get_typeinfo(IVBMXNamespaceManager_tid, &typeinfo);
-    if(SUCCEEDED(hr))
-    {
-        hr = ITypeInfo_Invoke(typeinfo, &This->IVBMXNamespaceManager_iface, dispIdMember, wFlags,
-                pDispParams, pVarResult, pExcepInfo, puArgErr);
-        ITypeInfo_Release(typeinfo);
-    }
-
-    return hr;
+    return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
+        dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
 }
 
 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
@@ -588,28 +560,40 @@ static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
     vbnamespacemanager_getURIFromNode
 };
 
+static const tid_t namespacemanager_iface_tids[] = {
+    IVBMXNamespaceManager_tid,
+    0
+};
+static dispex_static_data_t namespacemanager_dispex = {
+    NULL,
+    IVBMXNamespaceManager_tid,
+    NULL,
+    namespacemanager_iface_tids
+};
+
 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
 {
-    namespacemanager *ns;
+    namespacemanager *This;
     struct nscontext *ctxt;
 
     TRACE("(%p, %p)\n", outer, obj);
 
-    ns = heap_alloc( sizeof (*ns) );
-    if( !ns )
+    This = heap_alloc( sizeof (*This) );
+    if( !This )
         return E_OUTOFMEMORY;
 
-    ns->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
-    ns->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
-    ns->ref = 1;
+    This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
+    This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
+    This->ref = 1;
+    init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
 
-    list_init(&ns->ctxts);
+    list_init(&This->ctxts);
     ctxt = alloc_ns_context();
-    list_add_head(&ns->ctxts, &ctxt->entry);
+    list_add_head(&This->ctxts, &ctxt->entry);
 
-    ns->override = VARIANT_TRUE;
+    This->override = VARIANT_TRUE;
 
-    *obj = &ns->IMXNamespaceManager_iface;
+    *obj = &This->IMXNamespaceManager_iface;
 
     TRACE("returning iface %p\n", *obj);
 
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 3895db9..285147d 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -10417,23 +10417,66 @@ static void test_load(void)
     free_bstrs();
 }
 
+static void test_domobj_dispex(IUnknown *obj)
+{
+    DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
+    IDispatchEx *dispex;
+    IUnknown *unk;
+    DWORD props;
+    UINT ticnt;
+    HRESULT hr;
+    BSTR name;
+
+    hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
+    EXPECT_HR(hr, S_OK);
+    if (FAILED(hr)) return;
+
+    ticnt = 0;
+    hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
+    EXPECT_HR(hr, S_OK);
+    ok(ticnt == 1, "ticnt=%u\n", ticnt);
+
+    name = SysAllocString(szstar);
+    hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
+    EXPECT_HR(hr, E_NOTIMPL);
+    SysFreeString(name);
+
+    hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
+    EXPECT_HR(hr, E_NOTIMPL);
+
+    props = 0;
+    hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
+    EXPECT_HR(hr, E_NOTIMPL);
+    ok(props == 0, "expected 0 got %d\n", props);
+
+    hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
+    EXPECT_HR(hr, E_NOTIMPL);
+    if (SUCCEEDED(hr)) SysFreeString(name);
+
+    hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
+    EXPECT_HR(hr, E_NOTIMPL);
+
+    hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
+    EXPECT_HR(hr, E_NOTIMPL);
+    if (hr == S_OK && unk) IUnknown_Release(unk);
+
+    IDispatchEx_Release(dispex);
+}
+
 static void test_nsnamespacemanager(void)
 {
     static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
-    IMXNamespaceManager *nsmgr;
     IVBMXNamespaceManager *mgr2;
+    IMXNamespaceManager *nsmgr;
+    WCHAR buffW[250];
     IDispatch *disp;
+    IUnknown *unk;
     HRESULT hr;
-    WCHAR buffW[250];
     INT len;
 
     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
         &IID_IMXNamespaceManager, (void**)&nsmgr);
-    if (hr != S_OK)
-    {
-        win_skip("MXNamespaceManager is not available\n");
-        return;
-    }
+    EXPECT_HR(hr, S_OK);
 
     /* IMXNamespaceManager inherits from IUnknown */
     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IDispatch, (void**)&disp);
@@ -10530,6 +10573,12 @@ todo_wine {
     ok(buffW[0] == 0, "got %x\n", buffW[0]);
     ok(len == 0, "got %d\n", len);
 
+    /* IDispatchEx tests */
+    hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IUnknown, (void**)&unk);
+    EXPECT_HR(hr, S_OK);
+    test_domobj_dispex(unk);
+    IUnknown_Release(unk);
+
     IMXNamespaceManager_Release(nsmgr);
 
     free_bstrs();
@@ -10545,11 +10594,7 @@ static void test_nsnamespacemanager_override(void)
 
     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
         &IID_IMXNamespaceManager, (void**)&nsmgr);
-    if (hr != S_OK)
-    {
-        win_skip("MXNamespaceManager is not available\n");
-        return;
-    }
+    EXPECT_HR(hr, S_OK);
 
     len = sizeof(buffW)/sizeof(WCHAR);
     buffW[0] = 0;
@@ -10645,52 +10690,6 @@ static void test_nsnamespacemanager_override(void)
     free_bstrs();
 }
 
-static void test_domobj_dispex(IUnknown *obj)
-{
-    DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
-    IDispatchEx *dispex;
-    IUnknown *unk;
-    DWORD props;
-    UINT ticnt;
-    HRESULT hr;
-    BSTR name;
-
-    hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
-    EXPECT_HR(hr, S_OK);
-    if (FAILED(hr)) return;
-
-    ticnt = 0;
-    hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
-    EXPECT_HR(hr, S_OK);
-    ok(ticnt == 1, "ticnt=%u\n", ticnt);
-
-    name = SysAllocString(szstar);
-    hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
-    EXPECT_HR(hr, E_NOTIMPL);
-    SysFreeString(name);
-
-    hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
-    EXPECT_HR(hr, E_NOTIMPL);
-
-    props = 0;
-    hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
-    EXPECT_HR(hr, E_NOTIMPL);
-    ok(props == 0, "expected 0 got %d\n", props);
-
-    hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
-    EXPECT_HR(hr, E_NOTIMPL);
-    if (SUCCEEDED(hr)) SysFreeString(name);
-
-    hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
-    EXPECT_HR(hr, E_NOTIMPL);
-
-    hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
-    EXPECT_HR(hr, E_NOTIMPL);
-    if (hr == S_OK && unk) IUnknown_Release(unk);
-
-    IDispatchEx_Release(dispex);
-}
-
 static const DOMNodeType nodetypes_test[] =
 {
     NODE_ELEMENT,
@@ -11194,6 +11193,7 @@ static void test_nodeValue(void)
 START_TEST(domdoc)
 {
     IXMLDOMDocument *doc;
+    IUnknown *unk;
     HRESULT hr;
 
     hr = CoInitialize( NULL );
@@ -11270,8 +11270,17 @@ START_TEST(domdoc)
 
     test_xsltemplate();
 
-    test_nsnamespacemanager();
-    test_nsnamespacemanager_override();
+    hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IMXNamespaceManager, (void**)&unk);
+    if (hr == S_OK)
+    {
+        test_nsnamespacemanager();
+        test_nsnamespacemanager_override();
+
+        IUnknown_Release(unk);
+    }
+    else
+        win_skip("MXNamespaceManager is not available\n");
 
     CoUninitialize();
 }
-- 
1.5.6.5


