widl #30: inherited interfaces

Huw D M Davies h.davies1 at physics.ox.ac.uk
Wed Jan 26 05:58:03 CST 2005


        Huw Davies <huw at codeweavers.com>
        When adding an interface, midl adds the inherited interface first
        unless the inherited interface doesn't itself inherit.
        Fix the id, sizevft and datatype2 fields for interfaces that inherit.
        Prevent a crash if the typelib is empty.
        Clarify a few more entries on typelib_struct.h
-- 
Huw Davies
huw at codeweavers.com
Index: tools/widl/typelib_struct.h
===================================================================
RCS file: /home/wine/wine/tools/widl/typelib_struct.h,v
retrieving revision 1.3
diff -u -p -r1.3 typelib_struct.h
--- tools/widl/typelib_struct.h	19 Jan 2005 19:08:01 -0000	1.3
+++ tools/widl/typelib_struct.h	26 Jan 2005 11:48:40 -0000
@@ -137,11 +137,11 @@ typedef struct tagMSFT_TypeInfoBase {
         INT     helpcontext;    /* */
         INT     oCustData;          /* offset in customer data table */
 #ifdef WORDS_BIGENDIAN
-        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+        INT16   cbSizeVft;      /* virtual table size, including inherits */
         INT16   cImplTypes;     /* nr of implemented interfaces */
 #else
         INT16   cImplTypes;     /* nr of implemented interfaces */
-        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+        INT16   cbSizeVft;      /* virtual table size, including inherits */
 #endif
 /*050*/ INT     size;           /* size in bytes, at least for structures */
         /* FIXME: name of this field */
@@ -149,9 +149,8 @@ typedef struct tagMSFT_TypeInfoBase {
                                 /* or in base intefaces */
                                 /* if coclass: offset in reftable */
                                 /* if interface: reference to inherited if */
-        INT     datatype2;      /* if 0x8000, entry above is valid */
-                                /* actually dunno */
-                                /* else it is zero? */
+        INT     datatype2;      /* for interfaces: hiword is num of inherited funcs */
+                                /*                 loword is num of inherited interfaces */
         INT     res18;          /* always? 0 */
 /*060*/ INT     res19;          /* always? -1 */
     } MSFT_TypeInfoBase;
@@ -272,9 +271,11 @@ typedef struct {
 			   to the typeinfo itself or to a member of
 			   the typeinfo */
     INT   next_hash;    /* offset to next name in the hash bucket */
-    INT   namelen;      /* only lower 8 bits are valid,
-			   lower-middle 8 bits are unknown (flags?),
-			   upper 16 bits are hash code */
+    INT   namelen;      /* only lower 8 bits are valid */
+                        /* 0x1000 if name is only used once as a variable name */
+                        /* 0x2000 if name is a variable in an enumeration */
+                        /* 0x3800 if name is typeinfo name */
+			/* upper 16 bits are hash code */
 } MSFT_NameIntro;
 /* the custom data table directory has enties like this */
 typedef struct {
Index: tools/widl/write_msft.c
===================================================================
RCS file: /home/wine/wine/tools/widl/write_msft.c,v
retrieving revision 1.23
diff -u -p -r1.23 write_msft.c
--- tools/widl/write_msft.c	25 Jan 2005 20:02:09 -0000	1.23
+++ tools/widl/write_msft.c	26 Jan 2005 11:48:40 -0000
@@ -1179,7 +1179,7 @@ static HRESULT add_func_desc(msft_typein
     unsigned int funckind = 1 /* FUNC_PUREVIRTUAL */, invokekind = 1 /* INVOKE_FUNC */;
     int help_context = 0, help_string_context = 0, help_string_offset = -1;
 
-    id = ((0x6000 | typeinfo->typeinfo->cImplTypes) << 16) | index;
+    id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index;
 
     chat("add_func_desc(%p,%d)\n", typeinfo, index);
 
@@ -1580,12 +1580,19 @@ static msft_typeinfo_t *create_msft_type
     return msft_typeinfo;
 }
 
-
 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
 {
     int idx = 0;
-    func_t *cur = interface->funcs;
+    func_t *func;
+    type_t *ref;
     msft_typeinfo_t *msft_typeinfo;
+    int num_parents = 0, num_funcs = 0;
+
+    /* midl adds the parent interface first, unless the parent itself
+       has no parent (i.e. it stops before IUnknown). */
+
+    if(interface->ref && interface->ref->ref && interface->ref->typelib_idx == -1)
+        add_interface_typeinfo(typelib, interface->ref);
 
     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs,
@@ -1596,11 +1603,27 @@ static void add_interface_typeinfo(msft_
     if(interface->ref)
         add_impl_type(msft_typeinfo, interface->ref);
 
-    while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-    while(cur) {
-        if(add_func_desc(msft_typeinfo, cur, idx) == S_OK)
+    /* count the number of inherited interfaces and non-local functions */
+    for(ref = interface->ref; ref; ref = ref->ref) {
+        num_parents++;
+        for(func = ref->funcs; func; func = NEXT_LINK(func)) {
+            attr_t *attr;
+            for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr))
+                if(attr->type == ATTR_LOCAL)
+                    break;
+            if(!attr)
+                num_funcs++;
+        }
+    }
+    msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
+    msft_typeinfo->typeinfo->cbSizeVft = num_funcs * 4;
+
+    func = interface->funcs;
+    while(NEXT_LINK(func)) func = NEXT_LINK(func);
+    while(func) {
+        if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
             idx++;
-        cur = PREV_LINK(cur);
+        func = PREV_LINK(func);
     }
 }
 
@@ -1985,7 +2008,7 @@ int create_msft_typelib(typelib_t *typel
     set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
     set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
 
-    for(entry = typelib->entry; NEXT_LINK(entry); entry = NEXT_LINK(entry))
+    for(entry = typelib->entry; entry && NEXT_LINK(entry); entry = NEXT_LINK(entry))
         ;
 
     for( ; entry; entry = PREV_LINK(entry))



More information about the wine-patches mailing list