[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