Huw Davies : oleaut32: Fix the typelib marshaler when the vtbl has holes.

Alexandre Julliard julliard at winehq.org
Thu Apr 7 07:36:55 CDT 2011


Module: wine
Branch: stable
Commit: 6d51d3106ba45733e10ea8af52e6912609a4c68b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6d51d3106ba45733e10ea8af52e6912609a4c68b

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Feb 24 10:09:36 2011 +0000

oleaut32: Fix the typelib marshaler when the vtbl has holes.
(cherry picked from commit ac5e9812fdb6929e0fc3c9f3805223dd6062da62)

---

 dlls/oleaut32/tmarshal.c |   91 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 65 insertions(+), 26 deletions(-)

diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c
index 76b64f1..ce5778b 100644
--- a/dlls/oleaut32/tmarshal.c
+++ b/dlls/oleaut32/tmarshal.c
@@ -322,48 +322,85 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
 }
 
 /*
- * Determine the number of functions including all inherited functions.
+ * Determine the number of functions including all inherited functions
+ * and well as the size of the vtbl.
  * Note for non-dual dispinterfaces we simply return the size of IDispatch.
  */
-static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num)
+static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num,
+                            unsigned int *vtbl_size)
 {
-    HRESULT hres;
+    HRESULT hr;
     TYPEATTR *attr;
     ITypeInfo *tinfo2;
+    UINT inherited_funcs = 0, i;
 
     *num = 0;
-    hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
-    if (hres) {
-        ERR("GetTypeAttr failed with %x\n",hres);
-        return hres;
+    if(vtbl_size) *vtbl_size = 0;
+
+    hr = ITypeInfo_GetTypeAttr(tinfo, &attr);
+    if (hr)
+    {
+        ERR("GetTypeAttr failed with %x\n", hr);
+        return hr;
     }
 
-    if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL))
+    if(attr->typekind == TKIND_DISPATCH)
     {
-        HREFTYPE href;
-        hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
-        if(FAILED(hres))
+        if(attr->wTypeFlags & TYPEFLAG_FDUAL)
         {
-            ERR("Unable to get interface href from dual dispinterface\n");
-            goto end;
+            HREFTYPE href;
+
+            ITypeInfo_ReleaseTypeAttr(tinfo, attr);
+            hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
+            if(FAILED(hr))
+            {
+                ERR("Unable to get interface href from dual dispinterface\n");
+                return hr;
+            }
+            hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
+            if(FAILED(hr))
+            {
+                ERR("Unable to get interface from dual dispinterface\n");
+                return hr;
+            }
+            hr = num_of_funcs(tinfo2, num, vtbl_size);
+            ITypeInfo_Release(tinfo2);
+            return hr;
         }
-        hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
-        if(FAILED(hres))
+        else /* non-dual dispinterface */
         {
-            ERR("Unable to get interface from dual dispinterface\n");
-            goto end;
+            /* These will be the size of IDispatchVtbl */
+            *num = attr->cbSizeVft / sizeof(void *);
+            if(vtbl_size) *vtbl_size = attr->cbSizeVft;
+            ITypeInfo_ReleaseTypeAttr(tinfo, attr);
+            return hr;
         }
-        hres = num_of_funcs(tinfo2, num);
-        ITypeInfo_Release(tinfo2);
     }
-    else
+
+    for (i = 0; i < attr->cImplTypes; i++)
     {
-        *num = attr->cbSizeVft / 4;
+        HREFTYPE href;
+        ITypeInfo *pSubTypeInfo;
+        UINT sub_funcs;
+
+        hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href);
+        if (FAILED(hr)) goto end;
+        hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo);
+        if (FAILED(hr)) goto end;
+
+        hr = num_of_funcs(pSubTypeInfo, &sub_funcs, NULL);
+        ITypeInfo_Release(pSubTypeInfo);
+
+        if(FAILED(hr)) goto end;
+        inherited_funcs += sub_funcs;
     }
 
+    *num = inherited_funcs + attr->cFuncs;
+    if(vtbl_size) *vtbl_size = attr->cbSizeVft;
+
  end:
     ITypeInfo_ReleaseTypeAttr(tinfo, attr);
-    return hres;
+    return hr;
 }
 
 #ifdef __i386__
@@ -1687,7 +1724,7 @@ static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num)
     xasm->lret          = 0xc2;
     xasm->bytestopop    = (nrofargs+2)*4; /* pop args, This, iMethod */
     xasm->nop           = 0x90;
-    proxy->lpvtbl[num]  = xasm;
+    proxy->lpvtbl[fdesc->oVft / sizeof(void *)] = xasm;
 #else
     FIXME("not implemented on non i386\n");
     return E_FAIL;
@@ -1702,7 +1739,7 @@ PSFacBuf_CreateProxy(
 {
     HRESULT	hres;
     ITypeInfo	*tinfo;
-    unsigned int i, nroffuncs;
+    unsigned int i, nroffuncs, vtbl_size;
     TMProxyImpl	*proxy;
     TYPEATTR	*typeattr;
     BOOL        defer_to_dispatch = FALSE;
@@ -1714,7 +1751,9 @@ PSFacBuf_CreateProxy(
 	return hres;
     }
 
-    hres = num_of_funcs(tinfo, &nroffuncs);
+    hres = num_of_funcs(tinfo, &nroffuncs, &vtbl_size);
+    TRACE("Got %d funcs, vtbl size %d\n", nroffuncs, vtbl_size);
+
     if (FAILED(hres)) {
         ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid));
         ITypeInfo_Release(tinfo);
@@ -1745,7 +1784,7 @@ PSFacBuf_CreateProxy(
     InitializeCriticalSection(&proxy->crit);
     proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit");
 
-    proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
+    proxy->lpvtbl = HeapAlloc(GetProcessHeap(), 0, vtbl_size);
 
     /* if we derive from IDispatch then defer to its proxy for its methods */
     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);




More information about the wine-cvs mailing list