From 06845a443e44f8a4fcb3fc44f46e771507d1c372 Mon Sep 17 00:00:00 2001
From: Piotr Caban <piotr@codeweavers.com>
Date: Thu, 11 Apr 2013 13:55:54 +0200
Subject: [PATCH] oleaut32: Use MSFT_VarFunc to store FUNCDESC.

---
 dlls/oleaut32/typelib2.c | 271 ++++++++++++++++++---------------------
 1 file changed, 123 insertions(+), 148 deletions(-)

diff --git a/dlls/oleaut32/typelib2.c b/dlls/oleaut32/typelib2.c
index 399ac06a6ac..1aeb27abb3b 100644
--- a/dlls/oleaut32/typelib2.c
+++ b/dlls/oleaut32/typelib2.c
@@ -132,6 +132,7 @@ typedef struct tagCyclicList {
     union {
         int val;
         MSFT_VarRecord *var;
+        MSFT_FuncRecord *func;
         int *data;
     }u;
 } CyclicList;
@@ -256,6 +257,33 @@ static inline INT ctl2_get_record_size(const CyclicList *iter)
     return iter->u.data[0] & 0xFFFF;
 }
 
+static void ctl2_update_func_size(const ICreateTypeInfo2Impl *This, MSFT_FuncRecord *func)
+{
+    int old = func->Info & 0xFFFF, size;
+
+    if(func->oCustData != -1)
+        size = FIELD_OFFSET(MSFT_FuncRecord, oArgCustData);
+    else if(func->HelpStringContext)
+        size = FIELD_OFFSET(MSFT_FuncRecord, oCustData);
+    else if(func->resA != -1)
+        size = FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext);
+    else if(func->res9 != -1)
+        size = FIELD_OFFSET(MSFT_FuncRecord, resA);
+    else if(func->oEntry != -1)
+        size = FIELD_OFFSET(MSFT_FuncRecord, res9);
+    else if(func->oHelpString != -1)
+        size = FIELD_OFFSET(MSFT_FuncRecord, oEntry);
+    else if(func->HelpContext)
+        size = FIELD_OFFSET(MSFT_FuncRecord, oHelpString);
+    else
+        size = FIELD_OFFSET(MSFT_FuncRecord, HelpContext);
+
+    size += func->nrargs * (func->FKCCIC&0x1000 ? 16 : 12);
+
+    func->Info += size - old;
+    This->typedata->next->u.val += size - old;
+}
+
 static void ctl2_update_var_size(const ICreateTypeInfo2Impl *This, MSFT_VarRecord *var)
 {
     int old = var->Info & 0xFFFF, size;
@@ -271,11 +299,10 @@ static void ctl2_update_var_size(const ICreateTypeInfo2Impl *This, MSFT_VarRecor
     This->typedata->next->u.val += size - old;
 }
 
-/* NOTE: entry always assumed to be a function */
-static inline INVOKEKIND ctl2_get_invokekind(const CyclicList *func)
+static inline INVOKEKIND ctl2_get_invokekind(const MSFT_FuncRecord *func)
 {
     /* INVOKEKIND uses bit flags up to 8 */
-    return (func->u.data[4] >> 3) & 0xF;
+    return (func->FKCCIC >> 3) & 0xF;
 }
 
 static inline SYSKIND ctl2_get_syskind(const ICreateTypeLib2Impl *This)
@@ -1523,69 +1550,6 @@ static HRESULT ctl2_find_typeinfo_from_offset(
     return TYPE_E_ELEMENTNOTFOUND;
 }
 
-/****************************************************************************
- *      funcrecord_reallochdr
- *
- *  Ensure FuncRecord data block contains header of required size
- *
- *  PARAMS
- *
- *   typedata [IO] - reference to pointer to data block
- *   need     [I]  - required size of block in bytes
- *
- * RETURNS
- *
- *  Number of additionally allocated bytes
- */
-static INT funcrecord_reallochdr(INT **typedata, int need)
-{
-    int tail = (*typedata)[5]*((*typedata)[4]&0x1000?16:12);
-    int hdr = (*typedata)[0] - tail;
-    int i;
-
-    if (hdr >= need)
-        return 0;
-
-    *typedata = heap_realloc(*typedata, need + tail);
-    if (!*typedata)
-        return -1;
-
-    if (tail)
-        memmove((char*)*typedata + need, (const char*)*typedata + hdr, tail);
-    (*typedata)[0] = need + tail;
-
-    /* fill in default values */
-    for(i = (hdr+3)/4; (i+1)*4 <= need; i++)
-    {
-        switch(i)
-        {
-            case 2:
-                (*typedata)[i] = 0;
-                break;
-            case 7:
-                (*typedata)[i] = -1;
-                break;
-            case 8:
-                (*typedata)[i] = -1;
-                break;
-            case 9:
-                (*typedata)[i] = -1;
-                break;
-            case 10:
-                (*typedata)[i] = -1;
-                break;
-            case 11:
-                (*typedata)[i] = 0;
-                break;
-            case 12:
-                (*typedata)[i] = -1;
-                break;
-        }
-    }
-
-    return need - hdr;
-}
-
 /*================== ICreateTypeInfo2 Implementation ===================================*/
 
 /******************************************************************************
@@ -1946,7 +1910,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     ICreateTypeInfo2Impl *This = impl_from_ICreateTypeInfo2(iface);
 
     CyclicList *iter, *insert;
-    int *typedata;
+    MSFT_FuncRecord *typedata;
     int i, num_defaults = 0, num_retval = 0;
     int decoded_size;
     HRESULT hres;
@@ -2009,44 +1973,49 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     insert = alloc_cyclic_list_item(CyclicListFunc);
     if(!insert)
         return E_OUTOFMEMORY;
-    insert->u.data = heap_alloc(FIELD_OFFSET(MSFT_FuncRecord, HelpContext) +
-                            sizeof(int)*(num_defaults?4:3)*pFuncDesc->cParams);
-    if(!insert->u.data) {
+    insert->u.func = heap_alloc(sizeof(MSFT_FuncRecord) + sizeof(int)*(num_defaults?4:3)*pFuncDesc->cParams);
+    if(!insert->u.func) {
         heap_free(insert);
         return E_OUTOFMEMORY;
     }
 
     /* fill out the basic type information */
-    typedata = insert->u.data;
-    typedata[0] = FIELD_OFFSET(MSFT_FuncRecord, HelpContext) + pFuncDesc->cParams*(num_defaults?16:12);
-    ctl2_encode_typedesc(This->typelib, &pFuncDesc->elemdescFunc.tdesc, &typedata[1], NULL, NULL, &decoded_size);
-    typedata[2] = pFuncDesc->wFuncFlags;
-    typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | (unsigned short)(pFuncDesc->oVft?pFuncDesc->oVft+1:0);
-    typedata[4] = (pFuncDesc->callconv << 8) | (pFuncDesc->invkind << 3) | pFuncDesc->funckind;
-    if(num_defaults) typedata[4] |= 0x1000;
-    if (num_retval) typedata[4] |= 0x4000;
-    typedata[5] = pFuncDesc->cParams;
-
-    /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
+    typedata = insert->u.func;
+    memset(typedata, 0xff, sizeof(MSFT_FuncRecord));
+    typedata->HelpContext = 0;
+    typedata->HelpStringContext = 0;
+
+    typedata->Info = FIELD_OFFSET(MSFT_FuncRecord, HelpContext) + pFuncDesc->cParams*(num_defaults?16:12);
+    ctl2_encode_typedesc(This->typelib, &pFuncDesc->elemdescFunc.tdesc, &typedata->DataType, NULL, NULL, &decoded_size);
+    typedata->Flags = pFuncDesc->wFuncFlags;
+    typedata->VtableOffset = pFuncDesc->oVft ? pFuncDesc->oVft+1 : 0;
+    typedata->funcdescsize = sizeof(FUNCDESC) + decoded_size;
+    typedata->FKCCIC = (pFuncDesc->callconv << 8) | (pFuncDesc->invkind << 3) | pFuncDesc->funckind;
+    if(num_defaults) typedata->FKCCIC |= 0x1000;
+    if (num_retval) typedata->FKCCIC |= 0x4000;
+    typedata->nrargs = pFuncDesc->cParams;
+    typedata->nroargs = 0;
+
+    /* NOTE: typedata->funcdescsize is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
-    typedata[3] += (sizeof(ELEMDESC) * pFuncDesc->cParams) << 16;
-    typedata[3] += (sizeof(PARAMDESCEX) * num_defaults) << 16;
+    typedata->funcdescsize += sizeof(ELEMDESC) * pFuncDesc->cParams;
+    typedata->funcdescsize += sizeof(PARAMDESCEX) * num_defaults;
 
     /* add default values */
     if(num_defaults) {
         for (i = 0; i < pFuncDesc->cParams; i++)
             if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
-                hres = ctl2_encode_variant(This->typelib, typedata+6+i,
+                hres = ctl2_encode_variant(This->typelib, &typedata->oArgCustData[i],
                         &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue,
                         pFuncDesc->lprgelemdescParam[i].tdesc.vt);
 
                 if(FAILED(hres)) {
-                    heap_free(insert->u.data);
+                    heap_free(insert->u.func);
                     heap_free(insert);
                     return hres;
                 }
             } else
-                typedata[6+i] = 0xffffffff;
+                typedata->oArgCustData[i] = -1;
 
         num_defaults = pFuncDesc->cParams;
     }
@@ -2054,10 +2023,10 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     /* add arguments */
     for (i = 0; i < pFuncDesc->cParams; i++) {
 	ctl2_encode_typedesc(This->typelib, &pFuncDesc->lprgelemdescParam[i].tdesc,
-                &typedata[6+num_defaults+(i*3)], NULL, NULL, &decoded_size);
-	typedata[7+num_defaults+(i*3)] = -1;
-	typedata[8+num_defaults+(i*3)] = pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
-	typedata[3] += decoded_size << 16;
+                &typedata->oArgCustData[num_defaults+(i*3)], NULL, NULL, &decoded_size);
+	typedata->oArgCustData[num_defaults+(i*3)+1] = -1;
+	typedata->oArgCustData[num_defaults+(i*3)+2] = pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
+        typedata->funcdescsize += decoded_size;
     }
 
     /* update the index data */
@@ -2084,7 +2053,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     }
 
     /* update type data size */
-    This->typedata->next->u.val += FIELD_OFFSET(MSFT_FuncRecord, HelpContext) + pFuncDesc->cParams*(num_defaults?16:12);
+    This->typedata->next->u.val += typedata->Info;
 
     /* Increment the number of function elements */
     This->typeinfo->cElement += 1;
@@ -2394,7 +2363,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(
                 break;
 
     /* cNames == cParams for put or putref accessor, cParams+1 otherwise */
-    if(cNames != iter->u.data[5] + (ctl2_get_invokekind(iter) & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF) ? 0 : 1))
+    if(cNames != iter->u.func->nrargs + (ctl2_get_invokekind(iter->u.func) & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF) ? 0 : 1))
         return TYPE_E_ELEMENTNOTFOUND;
 
     TRACE("function name %s\n", debugstr_w(names[0]));
@@ -2404,8 +2373,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(
         int cmp = memcmp(namedata, This->typelib->typelib_segment_data[MSFT_SEG_NAME]+iter2->name+8, len);
         if (iter2->name != -1 && cmp == 0) {
             if (iter2->type == CyclicListFunc) {
-                INVOKEKIND inv1 = ctl2_get_invokekind(iter);
-                INVOKEKIND inv2 = ctl2_get_invokekind(iter2);
+                INVOKEKIND inv1 = ctl2_get_invokekind(iter->u.func);
+                INVOKEKIND inv2 = ctl2_get_invokekind(iter2->u.func);
 
                 /* it's allowed to have PUT, PUTREF and GET methods with the same name */
                 if ((inv1 != inv2) &&
@@ -2428,11 +2397,14 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(
     if (*((INT*)namedata) == -1)
 	    *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
 
-    len = ctl2_get_record_size(iter)/4 - iter->u.data[5]*3;
+    if(iter->u.func->FKCCIC & 0x1000)
+        len = iter->u.func->nrargs;
+    else
+        len = 0;
 
     for (i = 1; i < cNames; i++) {
 	offset = ctl2_alloc_name(This->typelib, names[i]);
-	iter->u.data[len + ((i-1)*3) + 1] = offset;
+	iter->u.func->oArgCustData[len+(i-1)*3+1] = offset;
     }
 
     return S_OK;
@@ -2589,11 +2561,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(
                 if(index-- == 0)
                     break;
 
-    This->typedata->next->u.val += funcrecord_reallochdr(&func->u.data, 7*sizeof(int));
-    if(!func->u.data)
-        return E_OUTOFMEMORY;
-
-    func->u.data[6] = dwHelpContext;
+    func->u.func->HelpContext = dwHelpContext;
+    ctl2_update_func_size(This, func->u.func);
     return S_OK;
 }
 
@@ -2775,8 +2744,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
         if (iter->type == CyclicListFunc)
             last = iter;
 
-    if(last && last->u.data[3]&1)
-        user_vft = last->u.data[3]&0xffff;
+    if(last && last->u.func->VtableOffset & 1)
+        user_vft = last->u.func->VtableOffset;
 
     i = 0;
     for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
@@ -2807,37 +2776,37 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
 
         typedata[i] = iter;
 
-        iter->u.data[0] = ctl2_get_record_size(iter) | (i<<16);
+        iter->u.func->Info = (iter->u.func->Info&0xffff) | (i<<16);
 
-        if((iter->u.data[3]&1) != (user_vft&1)) {
+        if((iter->u.func->VtableOffset&1) != (user_vft&1)) {
             heap_free(typedata);
             return TYPE_E_INVALIDID;
         }
 
         if(user_vft&1) {
-            if(user_vft < (iter->u.data[3]&0xffff))
-                user_vft = (iter->u.data[3]&0xffff);
+            if(user_vft < iter->u.func->VtableOffset)
+                user_vft = iter->u.func->VtableOffset;
 
-            if((iter->u.data[3]&0xffff) < This->typeinfo->cbSizeVft) {
+            if((unsigned short)iter->u.func->VtableOffset < This->typeinfo->cbSizeVft) {
                 heap_free(typedata);
                 return TYPE_E_INVALIDID;
             }
         } else if(This->typekind != TKIND_MODULE) {
-            iter->u.data[3] = (iter->u.data[3]&0xffff0000) | This->typeinfo->cbSizeVft;
+            iter->u.func->VtableOffset = This->typeinfo->cbSizeVft;
             This->typeinfo->cbSizeVft += 4;
         }
 
         /* Construct a list of elements with the same memberid */
-        iter->u.data[4] = (iter->u.data[4]&0xffff) | (i<<16);
+        iter->u.func->FKCCIC = (iter->u.func->FKCCIC&0xffff) | (i<<16);
         for(iter2=This->typedata->next->next; iter2!=iter; iter2=iter2->next) {
             if(iter->indice == iter2->indice) {
                 int v1, v2;
 
-                v1 = iter->u.data[4] >> 16;
-                v2 = iter2->u.data[4] >> 16;
+                v1 = iter->u.func->FKCCIC >> 16;
+                v2 = iter2->u.func->FKCCIC >> 16;
 
-                iter->u.data[4] = (iter->u.data[4]&0xffff) | (v2<<16);
-                iter2->u.data[4] = (iter2->u.data[4]&0xffff) | (v1<<16);
+                iter->u.func->FKCCIC = (iter->u.func->FKCCIC&0xffff) | (v2<<16);
+                iter2->u.func->FKCCIC = (iter2->u.func->FKCCIC&0xffff) | (v1<<16);
                 break;
             }
         }
@@ -2849,20 +2818,20 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
         This->typeinfo->cbSizeVft = user_vft+3;
 
     for(i=0; i< cti2_get_func_count(This->typeinfo); i++) {
-        if(typedata[i]->u.data[4]>>16 > i) {
-            INVOKEKIND inv = ctl2_get_invokekind(typedata[i]);
+        if(typedata[i]->u.func->FKCCIC>>16 > i) {
+            INVOKEKIND inv = ctl2_get_invokekind(typedata[i]->u.func);
 
-            i = typedata[i]->u.data[4] >> 16;
+            i = typedata[i]->u.func->FKCCIC >> 16;
 
-            while(i > typedata[i]->u.data[4]>>16) {
-                INVOKEKIND invkind = ctl2_get_invokekind(typedata[i]);
+            while(i > typedata[i]->u.func->FKCCIC >>16) {
+                INVOKEKIND invkind = ctl2_get_invokekind(typedata[i]->u.func);
 
                 if(inv & invkind) {
                     heap_free(typedata);
                     return TYPE_E_DUPLICATEID;
                 }
 
-                i = typedata[i]->u.data[4] >> 16;
+                i = typedata[i]->u.func->FKCCIC >> 16;
                 inv |= invkind;
             }
 
@@ -3013,6 +2982,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(
 {
     ICreateTypeInfo2Impl *This = impl_from_ICreateTypeInfo2(iface);
     CyclicList *iter;
+    HRESULT hres;
 
     TRACE("(%p,%d,%s,%p)\n", iface, index, debugstr_guid(guid), pVarVal);
 
@@ -3024,12 +2994,13 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(
             if (index-- == 0)
                 break;
 
-    This->typedata->next->u.val += funcrecord_reallochdr(&iter->u.data, 13*sizeof(int));
-    if(!iter->u.data)
-        return E_OUTOFMEMORY;
+    hres = ctl2_set_custdata(This->typelib, guid, pVarVal, &iter->u.func->oCustData);
+    if(FAILED(hres))
+        return hres;
 
-    iter->u.data[4] |= 0x80;
-    return ctl2_set_custdata(This->typelib, guid, pVarVal, &iter->u.data[12]);
+    ctl2_update_func_size(This, iter->u.func);
+    iter->u.func->FKCCIC |= 0x80;
+    return S_OK;
 }
 
 /******************************************************************************
@@ -3286,7 +3257,8 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
         FUNCDESC** ppFuncDesc)
 {
     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
-    int i, *typedata, num_defaults = 0, hdr_len, tail, has_defaults;
+    MSFT_FuncRecord *typedata;
+    int i, num_defaults = 0, has_defaults;
     CyclicList *desc;
     HRESULT hres;
 
@@ -3309,7 +3281,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
             --i;
     }
 
-    typedata = desc->u.data;
+    typedata = desc->u.func;
 
     *ppFuncDesc = heap_alloc_zero(sizeof(FUNCDESC));
     if (!*ppFuncDesc)
@@ -3317,24 +3289,22 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
 
     (*ppFuncDesc)->memid = desc->indice;
     (*ppFuncDesc)->lprgscode = NULL; /* FIXME: Unimplemented */
-    (*ppFuncDesc)->funckind = typedata[4] & 0x7;
-    (*ppFuncDesc)->invkind = (typedata[4] >> 3) & 0xF;
-    (*ppFuncDesc)->callconv = (typedata[4] >> 8) & 0xF;
-    (*ppFuncDesc)->cParams = typedata[5];
-    (*ppFuncDesc)->cParamsOpt = 0; /* FIXME: Unimplemented*/
-    (*ppFuncDesc)->oVft = typedata[3] & 0xFFFC;
+    (*ppFuncDesc)->funckind = typedata->FKCCIC & 0x7;
+    (*ppFuncDesc)->invkind = (typedata->FKCCIC >> 3) & 0xF;
+    (*ppFuncDesc)->callconv = (typedata->FKCCIC >> 8) & 0xF;
+    (*ppFuncDesc)->cParams = typedata->nrargs;
+    (*ppFuncDesc)->cParamsOpt = typedata->nroargs;
+    (*ppFuncDesc)->oVft = typedata->VtableOffset & 0xFFFC;
     (*ppFuncDesc)->cScodes = 0; /* FIXME: Unimplemented*/
-    hres = ctl2_decode_typedesc(This->typelib, typedata[1],
+    hres = ctl2_decode_typedesc(This->typelib, typedata->DataType,
             &(*ppFuncDesc)->elemdescFunc.tdesc);
     if (FAILED(hres)) {
         heap_free(*ppFuncDesc);
         return hres;
     }
-    (*ppFuncDesc)->wFuncFlags = typedata[2];
+    (*ppFuncDesc)->wFuncFlags = typedata->Flags;
 
-    has_defaults = typedata[4] & 0x1000;
-    tail = typedata[5] * (has_defaults ? 16 : 12);
-    hdr_len = (ctl2_get_record_size(desc) - tail) / sizeof(int);
+    has_defaults = typedata->FKCCIC & 0x1000;
 
     if ((*ppFuncDesc)->cParams > 0) {
         (*ppFuncDesc)->lprgelemdescParam = heap_alloc_zero((*ppFuncDesc)->cParams * sizeof(ELEMDESC));
@@ -3346,7 +3316,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
             num_defaults = (*ppFuncDesc)->cParams;
 
             for (i = 0; i < num_defaults; ++i) {
-                if (typedata[hdr_len + i] != 0xFFFFFFFF) {
+                if (typedata->oArgCustData[i] != 0xFFFFFFFF) {
                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.wParamFlags |= PARAMFLAG_FHASDEFAULT;
 
                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex = heap_alloc(sizeof(PARAMDESCEX));
@@ -3357,7 +3327,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
 
                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex->cBytes = sizeof(PARAMDESCEX);
                     VariantInit(&(*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
-                    hres = ctl2_decode_variant(This->typelib, typedata[hdr_len + i],
+                    hres = ctl2_decode_variant(This->typelib, typedata->oArgCustData[i],
                             &(*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
                     if (FAILED(hres)) {
                         ITypeInfo2_ReleaseFuncDesc(iface, *ppFuncDesc);
@@ -3368,13 +3338,13 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
         }
 
         for (i = 0; i < (*ppFuncDesc)->cParams; ++i) {
-            hres = ctl2_decode_typedesc(This->typelib, typedata[hdr_len + num_defaults + (i * 3)],
+            hres = ctl2_decode_typedesc(This->typelib, typedata->oArgCustData[num_defaults+i*3],
                     &((*ppFuncDesc)->lprgelemdescParam + i)->tdesc);
             if (FAILED(hres)) {
                 ITypeInfo2_ReleaseFuncDesc(iface, *ppFuncDesc);
                 return hres;
             }
-            (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.wParamFlags = typedata[hdr_len + num_defaults + (i * 3) + 2];
+            (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.wParamFlags = typedata->oArgCustData[num_defaults+i*3+2];
         }
     }
 
@@ -3545,13 +3515,10 @@ static HRESULT WINAPI ITypeInfo2_fnGetDocumentation(
             for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
                 if (iter->indice == memid) {
                     if (iter->type == CyclicListFunc) {
-                        const int *typedata = iter->u.data;
-                        int size = ctl2_get_record_size(iter) - typedata[5]*(typedata[4]&0x1000?16:12);
-
                         nameoffset = iter->name;
                         /* FIXME implement this once SetFuncDocString is implemented */
                         docstringoffset = -1;
-                        helpcontext = (size < 7*sizeof(int)) ? 0 : typedata[6];
+                        helpcontext = iter->u.func->HelpContext;
 
                         status = S_OK;
                     } else {
@@ -4623,9 +4590,17 @@ static int ctl2_write_typeinfos(ICreateTypeLib2Impl *This, HANDLE hFile)
         iter = typeinfo->typedata->next;
         if (!ctl2_write_chunk(hFile, &iter->u.val, sizeof(int)))
             return 0;
-        for(iter=iter->next; iter!=typeinfo->typedata->next; iter=iter->next)
-            if (!ctl2_write_chunk(hFile, iter->u.data, ctl2_get_record_size(iter)))
+        for(iter=iter->next; iter!=typeinfo->typedata->next; iter=iter->next) {
+            if(iter->type == CyclicListFunc) {
+                DWORD cust_size = iter->u.func->nrargs * (iter->u.func->FKCCIC&0x1000 ? 16 : 12);
+                if(!ctl2_write_chunk(hFile, iter->u.func, (iter->u.func->Info&0xffff)-cust_size))
+                    return 0;
+                if(!ctl2_write_chunk(hFile, iter->u.func->oArgCustData, cust_size))
+                    return 0;
+            }else if (!ctl2_write_chunk(hFile, iter->u.data, ctl2_get_record_size(iter))) {
                 return 0;
+            }
+        }
 
         for(iter=typeinfo->typedata->next->next; iter!=typeinfo->typedata->next; iter=iter->next)
             if (!ctl2_write_chunk(hFile, &iter->indice, sizeof(int)))
-- 
GitLab