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