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

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@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-02-28 11:26:56 -06:00 committed by Alexandre Julliard
parent a6ca2001eb
commit 968eda4b18
2 changed files with 110 additions and 96 deletions

View File

@ -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,136 +936,122 @@ 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,
static HRESULT dispatch_create_proxy(IUnknown *outer, IRpcProxyBuffer **proxy, void **out)
{
IPSFactoryBuffer *factory;
HRESULT hr;
hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
if (FAILED(hr)) return hr;
hr = IPSFactoryBuffer_CreateProxy(factory, outer, &IID_IDispatch, proxy, out);
IPSFactoryBuffer_Release(factory);
return hr;
}
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 = ITypeInfo_GetTypeAttr(typeinfo, &attr);
if (FAILED(hr))
{
ITypeInfo_Release(typeinfo);
return hr;
}
if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
hr = CreateProxyFromTypeInfo(typeinfo, outer, iid, proxy, out);
else
hr = dispatch_create_proxy(outer, proxy, out);
if (FAILED(hr))
ERR("Failed to create proxy, hr %#x.\n", hr);
ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
ITypeInfo_Release(typeinfo);
return hr;
}
static HRESULT WINAPI typelib_ps_CreateStub(IPSFactoryBuffer *iface, REFIID iid,
IUnknown *server, IRpcStubBuffer **stub)
static HRESULT dispatch_create_stub(IUnknown *server, IRpcStubBuffer **stub)
{
IPSFactoryBuffer *factory;
HRESULT hr;
hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
if (FAILED(hr)) return hr;
hr = IPSFactoryBuffer_CreateStub(factory, &IID_IDispatch, server, stub);
IPSFactoryBuffer_Release(factory);
return hr;
}
static HRESULT WINAPI dispatch_typelib_ps_CreateStub(IPSFactoryBuffer *iface,
REFIID iid, IUnknown *server, IRpcStubBuffer **stub)
{
ITypeInfo *typeinfo;
TYPEATTR *attr;
HRESULT 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 = 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 =
if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
hr = CreateStubFromTypeInfo(typeinfo, iid, server, stub);
else
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 dispatch_typelib_ps_vtbl =
{
typelib_ps_QueryInterface,
typelib_ps_AddRef,
typelib_ps_Release,
typelib_ps_CreateProxy,
typelib_ps_CreateStub,
dispatch_typelib_ps_QueryInterface,
dispatch_typelib_ps_AddRef,
dispatch_typelib_ps_Release,
dispatch_typelib_ps_CreateProxy,
dispatch_typelib_ps_CreateStub,
};
static IPSFactoryBuffer typelib_ps = { &typelib_ps_vtbl };
static IPSFactoryBuffer dispatch_typelib_ps = { &dispatch_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;
}
return E_NOINTERFACE;
}
static ULONG WINAPI PSDispatchFacBuf_AddRef(IPSFactoryBuffer *iface)
{
return 2;
}
static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface)
{
return 1;
}
static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface,
IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **obj)
{
IPSFactoryBuffer *factory;
HRESULT hr;
if (IsEqualIID(iid, &IID_IDispatch))
{
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);
}
static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface,
REFIID iid, 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 = IPSFactoryBuffer_CreateStub(factory, iid, server, stub);
IPSFactoryBuffer_Release(factory);
return hr;
}
else
return IPSFactoryBuffer_CreateStub(&typelib_ps, iid, server, stub);
}
static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl =
{
PSDispatchFacBuf_QueryInterface,
PSDispatchFacBuf_AddRef,
PSDispatchFacBuf_Release,
PSDispatchFacBuf_CreateProxy,
PSDispatchFacBuf_CreateStub
};
/* This is the whole PSFactoryBuffer object, just the vtableptr */
static const IPSFactoryBufferVtbl *pPSDispatchFacBuf = &PSDispatchFacBuf_Vtbl;
/***********************************************************************
* 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) ||

View File

@ -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);
@ -3592,6 +3593,37 @@ static void test_external_connection(void)
IStream_Release(stream);
}
static void test_marshal_dispinterface(void)
{
static const LARGE_INTEGER zero;
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;
@ -3613,6 +3645,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);