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 --- 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);