Huw Davies : oleaut32:
non-dual dispinterfaces should be marshaled via IDispatch.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri May 18 13:56:08 CDT 2007
Module: wine
Branch: master
Commit: c24a53dc2844c24fe44af7c1f4bba421831ea0f9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c24a53dc2844c24fe44af7c1f4bba421831ea0f9
Author: Huw Davies <huw at 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;
More information about the wine-cvs
mailing list