[PATCH v2 2/3] widl: Properly implement syntax 2 dispinterfaces.

Huw Davies huw at codeweavers.com
Tue May 29 02:49:35 CDT 2018


From: Zebediah Figura <z.figura12 at gmail.com>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/oleaut32/tests/typelib.c | 18 ------------------
 tools/widl/typetree.c         | 13 +++++++++++--
 tools/widl/typetree.h         |  7 +++++++
 tools/widl/widltypes.h        |  1 +
 tools/widl/write_msft.c       | 40 +++++++++++++++++++++++++++++++++++++++-
 5 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index b518e1ad1c..05476a3976 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -1530,13 +1530,10 @@ static void test_inheritance(void)
     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
     ok(pTA->cbSizeVft == 7 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft);
     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
-if(use_midl_tlb) {
     ok(pTA->cFuncs == 6, "cfuncs %d\n", pTA->cFuncs);
     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
-}
     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
 
-if(use_midl_tlb) {
     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
     ok(hr == S_OK, "hr %08x\n", hr);
     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
@@ -1555,7 +1552,6 @@ if(use_midl_tlb) {
     ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid);
     ok(pFD->oVft == 5 * sizeof(void *), "oVft %d\n", pFD->oVft);
     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
-}
     ITypeInfo_Release(pTI);
 
 
@@ -1616,12 +1612,10 @@ if(use_midl_tlb) {
     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
     ITypeInfo_Release(pTI_p);
-if(use_midl_tlb) {
     hr = ITypeInfo_GetFuncDesc(pTI, 6, &pFD);
     ok(hr == S_OK, "hr %08x\n", hr);
     ok(pFD->memid == 0x1234, "memid %08x\n", pFD->memid);
     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
-}
     ITypeInfo_Release(pTI);
 
     /* ItestIF7 is dual with inherited ifaces which derive from Dispatch */
@@ -1662,13 +1656,10 @@ if(use_midl_tlb) {
     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
     ok(pTA->cbSizeVft == 7 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft);
     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
-if(use_midl_tlb) {
     ok(pTA->cFuncs == 3, "cfuncs %d\n", pTA->cFuncs);
     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
-}
     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
 
-if(use_midl_tlb) {
     hr = ITypeInfo_GetRefTypeOfImplType(pTI, -1, &href);
     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
@@ -1689,7 +1680,6 @@ if(use_midl_tlb) {
     ok(pFD->memid == 0x60010000, "memid %08x\n", pFD->memid);
     ok(pFD->oVft == 2 * sizeof(void *), "oVft %d\n", pFD->oVft);
     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
-}
     ITypeInfo_Release(pTI);
 
     /* ItestIF11 is a syntax 2 dispinterface which derives from IDispatch */
@@ -1701,13 +1691,10 @@ if(use_midl_tlb) {
     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
     ok(pTA->cbSizeVft == 7 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft);
     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
-if(use_midl_tlb) {
     ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs);
     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
-}
     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
 
-if(use_midl_tlb) {
     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
     ok(hr == S_OK, "hr %08x\n", hr);
     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
@@ -1736,7 +1723,6 @@ if(use_midl_tlb) {
     ok(hr == S_OK, "hr %08x\n", hr);
     if (SUCCEEDED(hr)) ITypeInfo_Release(pTI_p);
     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
-}
     ITypeInfo_Release(pTI);
 
 
@@ -1749,13 +1735,10 @@ if(use_midl_tlb) {
     ok(pTA->typekind == TKIND_INTERFACE, "kind %04x\n", pTA->typekind);
     ok(pTA->cbSizeVft == 6 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft);
     ok(pTA->wTypeFlags == 0, "typeflags %x\n", pTA->wTypeFlags);
-if(use_midl_tlb) {
     ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs);
     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
-}
     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
 
-if(use_midl_tlb) {
     /* Should have one method */
     hr = ITypeInfo_GetFuncDesc(pTI, 1, &pFD);
     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
@@ -1764,7 +1747,6 @@ if(use_midl_tlb) {
     ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid);
     ok(pFD->oVft == 5 * sizeof(void *), "oVft %d\n", pFD->oVft);
     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
-}
     ITypeInfo_Release(pTI);
 
     ITypeLib_Release(pTL);
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index e3166145b6..baf53a11a6 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -442,6 +442,7 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm
     iface->details.iface->disp_methods = NULL;
     iface->details.iface->stmts = stmts;
     iface->details.iface->inherit = inherit;
+    iface->details.iface->disp_inherit = NULL;
     iface->defined = TRUE;
     compute_method_indexes(iface);
 }
@@ -454,14 +455,22 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met
     iface->details.iface->stmts = NULL;
     iface->details.iface->inherit = find_type("IDispatch", NULL, 0);
     if (!iface->details.iface->inherit) error_loc("IDispatch is undefined\n");
+    iface->details.iface->disp_inherit = NULL;
     iface->defined = TRUE;
     compute_method_indexes(iface);
 }
 
 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface)
 {
-    type_dispinterface_define(dispiface, iface->details.iface->disp_props,
-                              iface->details.iface->disp_methods);
+    dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface));
+    dispiface->details.iface->disp_props = NULL;
+    dispiface->details.iface->disp_methods = NULL;
+    dispiface->details.iface->stmts = NULL;
+    dispiface->details.iface->inherit = find_type("IDispatch", NULL, 0);
+    if (!dispiface->details.iface->inherit) error_loc("IDispatch is undefined\n");
+    dispiface->details.iface->disp_inherit = iface;
+    dispiface->defined = TRUE;
+    compute_method_indexes(dispiface);
 }
 
 void type_module_define(type_t *module, statement_list_t *stmts)
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index bf05f25951..fc134cd575 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -176,6 +176,13 @@ static inline var_list_t *type_dispiface_get_methods(const type_t *type)
     return type->details.iface->disp_methods;
 }
 
+static inline type_t *type_dispiface_get_inherit(const type_t *type)
+{
+    type = type_get_real_type(type);
+    assert(type_get_type(type) == TYPE_INTERFACE);
+    return type->details.iface->disp_inherit;
+}
+
 static inline int type_is_defined(const type_t *type)
 {
     return type->defined;
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 1f4a9dd10f..0387846137 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -343,6 +343,7 @@ struct iface_details
   var_list_t *disp_methods;
   var_list_t *disp_props;
   struct _type_t *inherit;
+  struct _type_t *disp_inherit;
 };
 
 struct module_details
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c
index 8ce34d9566..3775a31ad7 100644
--- a/tools/widl/write_msft.c
+++ b/tools/widl/write_msft.c
@@ -2040,11 +2040,29 @@ static void add_dispatch(msft_typelib_t *typelib)
 
 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
 {
+    int num_parents = 0, num_funcs = 0;
+    importinfo_t *importinfo = NULL;
+    const statement_t *stmt_func;
+    type_t *inherit, *ref;
     int idx = 0;
     var_t *func;
     var_t *var;
     msft_typeinfo_t *msft_typeinfo;
 
+    if (-1 < dispinterface->typelib_idx)
+        return;
+
+    inherit = type_dispiface_get_inherit(dispinterface);
+
+    if (inherit)
+    {
+        importinfo = find_importinfo(typelib, inherit->name);
+
+        if (!importinfo && type_iface_get_inherit(inherit) && inherit->typelib_idx == -1)
+            add_interface_typeinfo(typelib, inherit);
+    }
+
+    /* check typelib_idx again, it could have been added while resolving the parent interface */
     if (-1 < dispinterface->typelib_idx)
         return;
 
@@ -2057,7 +2075,27 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte
 
     msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
     add_dispatch(typelib);
-    msft_typeinfo->typeinfo->cImplTypes = 1;
+
+    if (inherit)
+    {
+        add_impl_type(msft_typeinfo, inherit, importinfo);
+        msft_typeinfo->typeinfo->typekind |= 0x10;
+    }
+
+    /* count the number of inherited interfaces and non-local functions */
+    for (ref = inherit; ref; ref = type_iface_get_inherit(ref))
+    {
+        num_parents++;
+        STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) )
+        {
+            var_t *func = stmt_func->u.var;
+            if (!is_local(func->attrs)) num_funcs++;
+        }
+    }
+    msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
+    msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size;
+
+    msft_typeinfo->typeinfo->cImplTypes = 1;    /* IDispatch */
 
     /* count the no of methods, as the variable indices come after the funcs */
     if (dispinterface->details.iface->disp_methods)
-- 
2.16.2




More information about the wine-devel mailing list