Module: wine Branch: master Commit: c24a53dc2844c24fe44af7c1f4bba421831ea0f9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c24a53dc2844c24fe44af7c1f4...
Author: Huw Davies huw@codeweavers.com Date: Thu May 17 15:29:41 2007 +0100
oleaut32: non-dual dispinterfaces should be marshaled via IDispatch.
---
dlls/oleaut32/tmarshal.c | 167 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 118 insertions(+), 49 deletions(-)
diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c index f11d835..3772910 100644 --- a/dlls/oleaut32/tmarshal.c +++ b/dlls/oleaut32/tmarshal.c @@ -320,49 +320,49 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) { return hres; }
-/* Determine nr of functions. Since we use the toplevel interface and all - * inherited ones have lower numbers, we are ok to not to descent into - * the inheritance tree I think. +/* + * Determine the number of functions including all inherited functions. + * Note for non-dual dispinterfaces we simply return the size of IDispatch. */ -static int _nroffuncs(ITypeInfo *tinfo) { - int n, i, j; - const FUNCDESC *fdesc; - HRESULT hres; +static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num) +{ + HRESULT hres; TYPEATTR *attr; ITypeInfo *tinfo2;
- n=0; + *num = 0; hres = ITypeInfo_GetTypeAttr(tinfo, &attr); if (hres) { ERR("GetTypeAttr failed with %x\n",hres); return hres; } - /* look in inherited ifaces. */ - for (j=0;j<attr->cImplTypes;j++) { + + if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL)) + { HREFTYPE href; - hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href); - if (hres) { - ERR("Did not find a reftype for interface offset %d?\n",j); - break; + hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); + if(FAILED(hres)) + { + ERR("Unable to get interface href from dual dispinterface\n"); + goto end; } hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); - if (hres) { - ERR("Did not find a typeinfo for reftype %d?\n",href); - continue; + if(FAILED(hres)) + { + ERR("Unable to get interface from dual dispinterface\n"); + goto end; } - n += _nroffuncs(tinfo2); + hres = num_of_funcs(tinfo2, num); ITypeInfo_Release(tinfo2); } - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - i = 0; - while (1) { - hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,i,&fdesc); - if (hres) - return n; - n++; - i++; + else + { + *num = attr->cbSizeVft / 4; } - /*NOTREACHED*/ + + end: + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hres; }
#ifdef __i386__ @@ -1215,6 +1215,37 @@ static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, ERR("GetTypeAttr failed with %x\n",hr); return hr; } + + if(attr->typekind == TKIND_DISPATCH) + { + if(attr->wTypeFlags & TYPEFLAG_FDUAL) + { + HREFTYPE href; + ITypeInfo *tinfo2; + + hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); + if(FAILED(hr)) + { + ERR("Cannot get interface href from dual dispinterface\n"); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); + if(FAILED(hr)) + { + ERR("Cannot get interface from dual dispinterface\n"); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + hr = get_funcdesc(tinfo2, iMethod, tactual, fdesc, iname, fname, num); + ITypeInfo_Release(tinfo2); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + ERR("Shouldn't be called with a non-dual dispinterface\n"); + return E_FAIL; + } + impl_types = attr->cImplTypes; ITypeInfo_ReleaseTypeAttr(tinfo, attr);
@@ -1699,9 +1730,10 @@ PSFacBuf_CreateProxy( { HRESULT hres; ITypeInfo *tinfo; - int i, nroffuncs; + unsigned int i, nroffuncs; TMProxyImpl *proxy; TYPEATTR *typeattr; + BOOL defer_to_dispatch = FALSE;
TRACE("(...%s...)\n",debugstr_guid(riid)); hres = _get_typeinfo_for_iid(riid,&tinfo); @@ -1709,7 +1741,14 @@ PSFacBuf_CreateProxy( ERR("No typeinfo for %s?\n",debugstr_guid(riid)); return hres; } - nroffuncs = _nroffuncs(tinfo); + + hres = num_of_funcs(tinfo, &nroffuncs); + if (FAILED(hres)) { + ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid)); + ITypeInfo_Release(tinfo); + return hres; + } + proxy = CoTaskMemAlloc(sizeof(TMProxyImpl)); if (!proxy) return E_OUTOFMEMORY;
@@ -1735,22 +1774,6 @@ PSFacBuf_CreateProxy( proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit");
proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs); - for (i=0;i<nroffuncs;i++) { - switch (i) { - case 0: - proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; - break; - case 1: - proxy->lpvtbl[i] = ProxyIUnknown_AddRef; - break; - case 2: - proxy->lpvtbl[i] = ProxyIUnknown_Release; - break; - default: - hres = init_proxy_entry_point(proxy, i); - if(FAILED(hres)) return hres; - } - }
/* if we derive from IDispatch then defer to its proxy for its methods */ hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); @@ -1774,15 +1797,61 @@ PSFacBuf_CreateProxy( } if (hres == S_OK) { - proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; - proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; - proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; - proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + defer_to_dispatch = TRUE; } } ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); }
+ for (i=0;i<nroffuncs;i++) { + switch (i) { + case 0: + proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; + break; + case 1: + proxy->lpvtbl[i] = ProxyIUnknown_AddRef; + break; + case 2: + proxy->lpvtbl[i] = ProxyIUnknown_Release; + break; + case 3: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; + break; + case 4: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; + break; + case 5: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; + break; + case 6: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + break; + default: + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + } + if (hres == S_OK) { *ppv = (LPVOID)proxy;