[PATCH] oleaut32: Unify the typelib and dispatch proxy/stub factories.

Zebediah Figura z.figura12 at gmail.com
Thu Feb 28 11:26:56 CST 2019


Both seem to be able to handle either kind of interface on Windows.

f72f8e5c4 was not enough, since the IDispatch proxy/stub factory
delegates to the typelib proxy/stub factory if the IID is not
IDispatch.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/oleaut32/oleaut.c         | 155 +++++++++++++++------------------
 dlls/oleaut32/tests/tmarshal.c |  35 +++++++-
 2 files changed, 102 insertions(+), 88 deletions(-)

diff --git a/dlls/oleaut32/oleaut.c b/dlls/oleaut32/oleaut.c
index 3161d5e1dd..16345f7d4b 100644
--- a/dlls/oleaut32/oleaut.c
+++ b/dlls/oleaut32/oleaut.c
@@ -923,7 +923,7 @@ static HRESULT get_typeinfo_for_iid(REFIID iid, ITypeInfo **typeinfo)
     return hr;
 }
 
-static HRESULT WINAPI typelib_ps_QueryInterface(IPSFactoryBuffer *iface, REFIID iid, void **out)
+static HRESULT WINAPI dispatch_typelib_ps_QueryInterface(IPSFactoryBuffer *iface, REFIID iid, void **out)
 {
     if (IsEqualIID(iid, &IID_IPSFactoryBuffer) || IsEqualIID(iid, &IID_IUnknown))
     {
@@ -936,135 +936,121 @@ static HRESULT WINAPI typelib_ps_QueryInterface(IPSFactoryBuffer *iface, REFIID
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI typelib_ps_AddRef(IPSFactoryBuffer *iface)
+static ULONG WINAPI dispatch_typelib_ps_AddRef(IPSFactoryBuffer *iface)
 {
     return 2;
 }
 
-static ULONG WINAPI typelib_ps_Release(IPSFactoryBuffer *iface)
+static ULONG WINAPI dispatch_typelib_ps_Release(IPSFactoryBuffer *iface)
 {
     return 1;
 }
 
-static HRESULT WINAPI typelib_ps_CreateProxy(IPSFactoryBuffer *iface,
-    IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **out)
+static HRESULT dispatch_create_proxy(IUnknown *outer, IRpcProxyBuffer **proxy, void **out)
 {
-    ITypeInfo *typeinfo;
+    IPSFactoryBuffer *factory;
     HRESULT hr;
 
-    hr = get_typeinfo_for_iid(iid, &typeinfo);
+    hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
     if (FAILED(hr)) return hr;
 
-    hr = CreateProxyFromTypeInfo(typeinfo, outer, iid, proxy, out);
-    if (FAILED(hr))
-        ERR("Failed to create proxy, hr %#x.\n", hr);
-
-    ITypeInfo_Release(typeinfo);
+    hr = IPSFactoryBuffer_CreateProxy(factory, outer, &IID_IDispatch, proxy, out);
+    IPSFactoryBuffer_Release(factory);
     return hr;
 }
 
-static HRESULT WINAPI typelib_ps_CreateStub(IPSFactoryBuffer *iface, REFIID iid,
-    IUnknown *server, IRpcStubBuffer **stub)
+static HRESULT WINAPI dispatch_typelib_ps_CreateProxy(IPSFactoryBuffer *iface,
+    IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **out)
 {
     ITypeInfo *typeinfo;
+    TYPEATTR *attr;
     HRESULT hr;
 
+    if (IsEqualGUID(iid, &IID_IDispatch))
+        return dispatch_create_proxy(outer, proxy, out);
+
     hr = get_typeinfo_for_iid(iid, &typeinfo);
     if (FAILED(hr)) return hr;
 
-    hr = CreateStubFromTypeInfo(typeinfo, iid, server, stub);
+    hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
     if (FAILED(hr))
-        ERR("Failed to create stub, hr %#x.\n", hr);
-
-    ITypeInfo_Release(typeinfo);
-    return hr;
-}
-
-static const IPSFactoryBufferVtbl typelib_ps_vtbl =
-{
-    typelib_ps_QueryInterface,
-    typelib_ps_AddRef,
-    typelib_ps_Release,
-    typelib_ps_CreateProxy,
-    typelib_ps_CreateStub,
-};
-
-static IPSFactoryBuffer typelib_ps = { &typelib_ps_vtbl };
-
-extern void _get_STDFONT_CF(LPVOID *);
-extern void _get_STDPIC_CF(LPVOID *);
-
-static HRESULT WINAPI PSDispatchFacBuf_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv)
-{
-    if (IsEqualIID(riid, &IID_IUnknown) ||
-        IsEqualIID(riid, &IID_IPSFactoryBuffer))
     {
-        IPSFactoryBuffer_AddRef(iface);
-        *ppv = iface;
-        return S_OK;
+        ITypeInfo_Release(typeinfo);
+        return hr;
     }
-    return E_NOINTERFACE;
-}
 
-static ULONG WINAPI PSDispatchFacBuf_AddRef(IPSFactoryBuffer *iface)
-{
-    return 2;
-}
+    if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
+        hr = CreateProxyFromTypeInfo(typeinfo, outer, iid, proxy, out);
+    else
+        hr = dispatch_create_proxy(outer, proxy, out);
 
-static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface)
-{
-    return 1;
+    if (FAILED(hr))
+        ERR("Failed to create proxy, hr %#x.\n", hr);
+
+    ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
+    ITypeInfo_Release(typeinfo);
+    return hr;
 }
 
-static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface,
-    IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **obj)
+static HRESULT dispatch_create_stub(IUnknown *server, IRpcStubBuffer **stub)
 {
     IPSFactoryBuffer *factory;
     HRESULT hr;
 
-    if (IsEqualIID(iid, &IID_IDispatch))
-    {
-        hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
-        if (FAILED(hr)) return hr;
+    hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
+    if (FAILED(hr)) return hr;
 
-        hr = IPSFactoryBuffer_CreateProxy(factory, outer, iid, proxy, obj);
-        IPSFactoryBuffer_Release(factory);
-        return hr;
-    }
-    else
-        return IPSFactoryBuffer_CreateProxy(&typelib_ps, outer, iid, proxy, obj);
+    hr = IPSFactoryBuffer_CreateStub(factory, &IID_IDispatch, server, stub);
+    IPSFactoryBuffer_Release(factory);
+    return hr;
 }
 
-static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface,
+static HRESULT WINAPI dispatch_typelib_ps_CreateStub(IPSFactoryBuffer *iface,
     REFIID iid, IUnknown *server, IRpcStubBuffer **stub)
 {
-    IPSFactoryBuffer *factory;
+    ITypeInfo *typeinfo;
+    TYPEATTR *attr;
     HRESULT hr;
 
-    if (IsEqualIID(iid, &IID_IDispatch))
-    {
-        hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
-        if (FAILED(hr)) return hr;
+    if (IsEqualGUID(iid, &IID_IDispatch))
+        return dispatch_create_stub(server, stub);
+
+    hr = get_typeinfo_for_iid(iid, &typeinfo);
+    if (FAILED(hr)) return hr;
 
-        hr = IPSFactoryBuffer_CreateStub(factory, iid, server, stub);
-        IPSFactoryBuffer_Release(factory);
+    hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
+    if (FAILED(hr))
+    {
+        ITypeInfo_Release(typeinfo);
         return hr;
     }
+
+    if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
+        hr = CreateStubFromTypeInfo(typeinfo, iid, server, stub);
     else
-        return IPSFactoryBuffer_CreateStub(&typelib_ps, iid, server, stub);
+        hr = dispatch_create_stub(server, stub);
+
+    if (FAILED(hr))
+        ERR("Failed to create proxy, hr %#x.\n", hr);
+
+    ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
+    ITypeInfo_Release(typeinfo);
+    return hr;
 }
 
-static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl =
+static const IPSFactoryBufferVtbl dispatch_typelib_ps_vtbl =
 {
-    PSDispatchFacBuf_QueryInterface,
-    PSDispatchFacBuf_AddRef,
-    PSDispatchFacBuf_Release,
-    PSDispatchFacBuf_CreateProxy,
-    PSDispatchFacBuf_CreateStub
+    dispatch_typelib_ps_QueryInterface,
+    dispatch_typelib_ps_AddRef,
+    dispatch_typelib_ps_Release,
+    dispatch_typelib_ps_CreateProxy,
+    dispatch_typelib_ps_CreateStub,
 };
 
-/* This is the whole PSFactoryBuffer object, just the vtableptr */
-static const IPSFactoryBufferVtbl *pPSDispatchFacBuf = &PSDispatchFacBuf_Vtbl;
+static IPSFactoryBuffer dispatch_typelib_ps = { &dispatch_typelib_ps_vtbl };
+
+extern void _get_STDFONT_CF(LPVOID *);
+extern void _get_STDPIC_CF(LPVOID *);
 
 /***********************************************************************
  *		DllGetClassObject (OLEAUT32.@)
@@ -1086,14 +1072,9 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
 	    return S_OK;
 	}
     }
-    if (IsEqualCLSID(rclsid, &CLSID_PSDispatch) && IsEqualIID(iid, &IID_IPSFactoryBuffer)) {
-        *ppv = &pPSDispatchFacBuf;
-        IPSFactoryBuffer_AddRef((IPSFactoryBuffer *)*ppv);
-        return S_OK;
-    }
 
-    if (IsEqualGUID(rclsid, &CLSID_PSOAInterface))
-        return IPSFactoryBuffer_QueryInterface(&typelib_ps, iid, ppv);
+    if (IsEqualGUID(rclsid, &CLSID_PSDispatch) || IsEqualGUID(rclsid, &CLSID_PSOAInterface))
+        return IPSFactoryBuffer_QueryInterface(&dispatch_typelib_ps, iid, ppv);
 
     if (IsEqualCLSID(rclsid, &CLSID_PSTypeComp) ||
         IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) ||
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c
index f3cc1f96f9..32cd5e9f39 100644
--- a/dlls/oleaut32/tests/tmarshal.c
+++ b/dlls/oleaut32/tests/tmarshal.c
@@ -410,7 +410,8 @@ static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDi
 static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out)
 {
     if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IDispatch)
-            || IsEqualGUID(iid, &IID_ISomethingFromDispatch))
+            || IsEqualGUID(iid, &IID_ISomethingFromDispatch)
+            || IsEqualGUID(iid, &DIID_ItestIF4))
     {
         *out = iface;
         ISomethingFromDispatch_AddRef(iface);
@@ -3637,6 +3638,37 @@ static void test_external_connection(void)
     IStream_Release(stream);
 }
 
+static void test_marshal_dispinterface(void)
+{
+    static const LARGE_INTEGER zero = {0};
+
+    ISomethingFromDispatch *disp_obj = create_disp_obj();
+    ITypeInfo *typeinfo = NULL;
+    IDispatch *proxy_disp;
+    IStream *stream;
+    HANDLE thread;
+    HRESULT hr;
+    ULONG ref;
+    DWORD tid;
+
+    CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    tid = start_host_object(stream, &DIID_ItestIF4, (IUnknown *)disp_obj, MSHLFLAGS_NORMAL, &thread);
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hr = CoUnmarshalInterface(stream, &DIID_ItestIF4, (void **)&proxy_disp);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IDispatch_GetTypeInfo(proxy_disp, 0xdeadbeef, 0, &typeinfo);
+    ok(hr == 0xbeefdead, "Got hr %#x.\n", hr);
+
+    ref = IDispatch_Release(proxy_disp);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+    ref = IStream_Release(stream);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+    end_host_object(tid, thread);
+    ref = ISomethingFromDispatch_Release(disp_obj);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
 START_TEST(tmarshal)
 {
     HRESULT hr;
@@ -3658,6 +3690,7 @@ START_TEST(tmarshal)
     test_StaticWidget();
     test_libattr();
     test_external_connection();
+    test_marshal_dispinterface();
 
     hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
                            sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
-- 
2.20.1




More information about the wine-devel mailing list