[PATCH 4/4] oleaut32: Implement ICreateTypeInfo::LayOut

Andrew Eikum aeikum at codeweavers.com
Wed May 29 15:00:33 CDT 2013


---
 dlls/oleaut32/typelib.c | 142 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 134 insertions(+), 8 deletions(-)

diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 7fa395a..2711aac 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -1119,6 +1119,7 @@ typedef struct tagITypeInfoImpl
     ICreateTypeInfo2 ICreateTypeInfo2_iface;
     LONG ref;
     BOOL not_attached_to_typelib;
+    BOOL needs_layout;
     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
     int index;                  /* index in this typelib; */
@@ -5608,6 +5609,9 @@ static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
     if (!ppFuncDesc)
         return E_INVALIDARG;
 
+    if (This->needs_layout)
+        ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
+
     if (This->TypeAttr.typekind == TKIND_DISPATCH)
         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
                                                        &internal_funcdesc, NULL,
@@ -5702,6 +5706,9 @@ static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
     if(index >= This->TypeAttr.cVars)
         return TYPE_E_ELEMENTNOTFOUND;
 
+    if (This->needs_layout)
+        ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
+
     return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
 }
 
@@ -7175,12 +7182,6 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
         ITypeInfo_AddRef(*ppTInfo);
 
         result = S_OK;
-    }
-    else if (This->hreftype == hRefType)
-    {
-        *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
-        ITypeInfo_AddRef(*ppTInfo);
-        result = S_OK;
     } else if ((hRefType & DISPATCH_HREF_MASK) &&
         (This->TypeAttr.typekind   == TKIND_DISPATCH))
     {
@@ -8457,6 +8458,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
         UINT typeFlags)
 {
     ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
+    WORD old_flags;
+    HRESULT hres;
 
     TRACE("%p %x\n", This, typeFlags);
 
@@ -8482,8 +8485,15 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
             return hres;
     }
 
+    old_flags = This->TypeAttr.wTypeFlags;
     This->TypeAttr.wTypeFlags = typeFlags;
 
+    hres = ICreateTypeInfo2_LayOut(iface);
+    if (FAILED(hres)) {
+        This->TypeAttr.wTypeFlags = old_flags;
+        return hres;
+    }
+
     return S_OK;
 }
 
@@ -8753,6 +8763,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
 
     ++This->TypeAttr.cFuncs;
 
+    This->needs_layout = TRUE;
+
     return S_OK;
 }
 
@@ -8761,6 +8773,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
 {
     ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
     TLBImplType *impl_type;
+    HRESULT hres;
 
     TRACE("%p %u %d\n", This, index, refType);
 
@@ -8823,6 +8836,10 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
     if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
         This->TypeAttr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
 
+    hres = ICreateTypeInfo2_LayOut(iface);
+    if (FAILED(hres))
+        return hres;
+
     return S_OK;
 }
 
@@ -9017,8 +9034,117 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
 {
     ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
-    FIXME("%p - stub\n", This);
-    return E_NOTIMPL;
+    ITypeInfo *tinfo;
+    TLBFuncDesc *func_desc;
+    UINT user_vft = 0, i, depth = 0;
+    HRESULT hres = S_OK;
+
+    TRACE("%p\n", This);
+
+    This->needs_layout = FALSE;
+
+    hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
+    if (FAILED(hres))
+        return hres;
+
+    if (This->TypeAttr.typekind == TKIND_INTERFACE) {
+        ITypeInfo *inh;
+        TYPEATTR *attr;
+        HREFTYPE inh_href;
+
+        hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
+
+        if (SUCCEEDED(hres)) {
+            hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
+
+            if (SUCCEEDED(hres)) {
+                hres = ITypeInfo_GetTypeAttr(inh, &attr);
+                if (FAILED(hres)) {
+                    ITypeInfo_Release(inh);
+                    ITypeInfo_Release(tinfo);
+                    return hres;
+                }
+                This->TypeAttr.cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
+                ITypeInfo_ReleaseTypeAttr(inh, attr);
+
+                do{
+                    ++depth;
+                    hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
+                    if(SUCCEEDED(hres)){
+                        ITypeInfo *next;
+                        hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
+                        if(SUCCEEDED(hres)){
+                            ITypeInfo_Release(inh);
+                            inh = next;
+                        }
+                    }
+                }while(SUCCEEDED(hres));
+                hres = S_OK;
+
+                ITypeInfo_Release(inh);
+            } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
+                This->TypeAttr.cbSizeVft = 0;
+                hres = S_OK;
+            } else {
+                ITypeInfo_Release(tinfo);
+                return hres;
+            }
+        } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
+            This->TypeAttr.cbSizeVft = 0;
+            hres = S_OK;
+        } else {
+            ITypeInfo_Release(tinfo);
+            return hres;
+        }
+    } else if (This->TypeAttr.typekind == TKIND_DISPATCH)
+        This->TypeAttr.cbSizeVft = 7 * sizeof(void*);
+    else
+        This->TypeAttr.cbSizeVft = 0;
+
+    func_desc = This->funcdescs;
+    i = 0;
+    while (i < This->TypeAttr.cFuncs) {
+        if (!(func_desc->funcdesc.oVft & 0x1))
+            func_desc->funcdesc.oVft = This->TypeAttr.cbSizeVft;
+
+        if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
+            user_vft = func_desc->funcdesc.oVft & 0xFFFC;
+
+        This->TypeAttr.cbSizeVft += sizeof(void*);
+
+        if (func_desc->funcdesc.memid == MEMBERID_NIL) {
+            TLBFuncDesc *iter;
+            UINT j = 0;
+            BOOL reset = FALSE;
+
+            func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
+
+            iter = This->funcdescs;
+            while (j < This->TypeAttr.cFuncs) {
+                if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
+                    if (!reset) {
+                        func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->TypeAttr.cFuncs;
+                        reset = TRUE;
+                    } else
+                        ++func_desc->funcdesc.memid;
+                    iter = This->funcdescs;
+                    j = 0;
+                } else {
+                    ++iter;
+                    ++j;
+                }
+            }
+        }
+
+        ++func_desc;
+        ++i;
+    }
+
+    if (user_vft > This->TypeAttr.cbSizeVft)
+        This->TypeAttr.cbSizeVft = user_vft + sizeof(void*);
+
+    ITypeInfo_Release(tinfo);
+    return hres;
 }
 
 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
-- 
1.8.3




More information about the wine-patches mailing list