[PATCH 06/13] oleaut32: Fix rewriting FUNCDESC to FUNC_DISPATCH.

Puetz Kevin A PuetzKevinA at JohnDeere.com
Thu Aug 6 23:11:08 CDT 2020


A [retval] parameter overwrites any return type, not just HRESULT.
But HRESULT is special even without a [retval] to replace it;
it's translated into pExcepInfo and so the return type becomes void.

[lcid] parameters are supplied from IDispatch::Invoke's parameters,
rather than via DISPPARAMS::rgvargs[] and should also be removed
from the FUNC_DISPATCH translation.

This rewriting should occur only for functions not originally
defined as FUNC_DISPACH (e.g. inherited or [dual]).
A FUNCDESC originally declared as a dispinterface is left as-is,
and might e.g. return HRESULT.

When GetFuncDesc removes parameters in this fashion,
GetNames must also omit their names to match cParams.

FUNC_DISPATCH from dispinterface should have oVft == 0
(a dispinterface has no vtbl beyond IDispatch itself)

Add examples in test_tlb which exercise FUNCDESC rewriting in:
1. dispinterface FUNC_DISPATCH declarations
2. dual interface
3. dispinterface which implements another interface

Signed-off-by: Kevin Puetz <PuetzKevinA at JohnDeere.com>
---
 dlls/oleaut32/tests/test_tlb.idl |  36 ++
 dlls/oleaut32/tests/typelib.c    | 653 +++++++++++++++++++++++++++++++
 dlls/oleaut32/typelib.c          |  96 +++--
 3 files changed, 757 insertions(+), 28 deletions(-)

diff --git a/dlls/oleaut32/tests/test_tlb.idl b/dlls/oleaut32/tests/test_tlb.idl
index ad35af40c3..b8fecc9a01 100644
--- a/dlls/oleaut32/tests/test_tlb.idl
+++ b/dlls/oleaut32/tests/test_tlb.idl
@@ -134,4 +134,40 @@ library Test
 		HRESULT test5(e value);
 		HRESULT test6(f value);
 	}
+
+	[uuid(2d4430d5-99ea-4645-85f0-c5814b72804b)]
+	dispinterface ITestDispatch
+	{
+		properties:
+		[id(10)] int property_int;
+		[id(11)] HRESULT property_HRESULT;
+
+		methods:
+		[id(1)] void test_void();
+		[id(2)] void test_void_retval([out,retval] double* ret);
+		[id(3)] HRESULT test_HRESULT();
+		[id(4)] HRESULT test_HRESULT_retval([out,retval] double* ret);
+		[id(5)] int test_int();
+		[id(6)] int test_int_retval([out,retval] double* ret);
+		[id(7)] double parse_lcid([in] BSTR x, [lcid] long lcid);
+
+	}
+
+	[uuid(79ca07f9-ac22-44ac-9aaf-811f45412293), dual]
+	interface ITestDispDual : IDispatch
+	{
+		[id(1)] void test_void();
+		[id(2)] void test_void_retval([out,retval] double* ret);
+		[id(3)] HRESULT test_HRESULT();
+		[id(4)] HRESULT test_HRESULT_retval([out,retval] double* ret);
+		[id(5)] int test_int();
+		[id(6)] int test_int_retval([out,retval] double* ret);
+		[id(7)] HRESULT parse_lcid([in] BSTR x, [lcid] long lcid, [out,retval] double *ret);
+	}
+
+	[uuid(cdb105e3-24fb-4ae6-b826-801b7b2a0a07)]
+	dispinterface ITestDispInherit
+	{
+		interface ITestDispDual;
+	}
 }
diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index 2f23949c7d..d4b573eb7a 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -5277,6 +5277,659 @@ static const type_info info[] = {
     },
   },
   { /* vars */ },
+},
+{
+  "ITestDispatch",
+  "{2d4430d5-99ea-4645-85f0-c5814b72804b}",
+  /*kind*/ TKIND_DISPATCH, /*flags*/ TYPEFLAG_FDISPATCHABLE, /*align*/ TYPE_ALIGNMENT(ITestDispatch*), /*size*/ sizeof(ITestDispatch*),
+  /*helpctx*/ 0x0000, /*version*/ 0x00000000, /*#vtbl*/ 7, /*#func*/ 7, /*#var*/ 2,
+  { /* funcs */
+    {
+      /*id*/ 0x1, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x2, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x3, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x4, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x5, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x6, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x7, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 2, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_BSTR, -1, PARAMFLAG_FIN},
+        {VT_I4, -1, PARAMFLAG_FLCID},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "parse_lcid",
+        "x",
+        "lcid",
+        NULL,
+      },
+    },
+  },
+  { /* vars */
+    {
+      /*id*/ 0xa, /*name*/ "property_int", /*flags*/ 0, /*kind*/ VAR_DISPATCH,
+      { /* DUMMYUNIONNAME unused*/ },
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+    },
+    {
+      /*id*/ 0xb, /*name*/ "property_HRESULT", /*flags*/ 0, /*kind*/ VAR_DISPATCH,
+      { /* DUMMYUNIONNAME unused*/ },
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+    },
+  },
+},
+{
+  "ITestDispDual",
+  "{79ca07f9-ac22-44ac-9aaf-811f45412293}",
+  /*kind*/ TKIND_DISPATCH, /*flags*/ TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL, /*align*/ TYPE_ALIGNMENT(ITestDispDual*), /*size*/ sizeof(ITestDispDual*),
+  /*helpctx*/ 0x0000, /*version*/ 0x00000000, /*#vtbl*/ 7, /*#func*/ 14, /*#var*/ 0,
+  { /* funcs */
+    {
+      /*id*/ 0x60000000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 2, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "QueryInterface",
+        "riid",
+        "ppvObj",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60000001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 1, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_UI4, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "AddRef",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60000002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 2, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_UI4, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "Release",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 3, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetTypeInfoCount",
+        "pctinfo",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 3, /*#opt*/ 0, /*vtbl*/ 4, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_UINT, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetTypeInfo",
+        "itinfo",
+        "lcid",
+        "pptinfo",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 5, /*#opt*/ 0, /*vtbl*/ 5, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_UINT, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetIDsOfNames",
+        "riid",
+        "rgszNames",
+        "cNames",
+        "lcid",
+        "rgdispid",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010003, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 8, /*#opt*/ 0, /*vtbl*/ 6, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_I4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_UI2, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "Invoke",
+        "dispidMember",
+        "riid",
+        "lcid",
+        "wFlags",
+        "pdispparams",
+        "pvarResult",
+        "pexcepinfo",
+        "puArgErr",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x1, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x2, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 8, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x3, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 9, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x4, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 10, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x5, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 11, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x6, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 12, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x7, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 13, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_BSTR, -1, PARAMFLAG_FIN},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "parse_lcid",
+        "x",
+        NULL,
+      },
+    },
+  },
+  { /* vars */ },
+},
+{
+  "ITestDispDual",
+  "{79ca07f9-ac22-44ac-9aaf-811f45412293}",
+  /*kind*/ TKIND_INTERFACE, /*flags*/ TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL, /*align*/ TYPE_ALIGNMENT(ITestDispDual*), /*size*/ sizeof(ITestDispDual*),
+  /*helpctx*/ 0x0000, /*version*/ 0x00000000, /*#vtbl*/ 14, /*#func*/ 7, /*#var*/ 0,
+  { /* funcs */
+    {
+      /*id*/ 0x1, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x2, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 8, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x3, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 9, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x4, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 10, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x5, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 11, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x6, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 12, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int_retval",
+        "ret",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x7, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 3, /*#opt*/ 0, /*vtbl*/ 13, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_HRESULT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_BSTR, -1, PARAMFLAG_FIN},
+        {VT_I4, -1, PARAMFLAG_FLCID},
+        {VT_PTR, -1, PARAMFLAG_FOUT|PARAMFLAG_FRETVAL},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "parse_lcid",
+        "x",
+        "lcid",
+        "ret",
+        NULL,
+      },
+    },
+  },
+  { /* vars */ },
+},
+{
+  "ITestDispInherit",
+  "{cdb105e3-24fb-4ae6-b826-801b7b2a0a07}",
+  /*kind*/ TKIND_DISPATCH, /*flags*/ TYPEFLAG_FDISPATCHABLE, /*align*/ TYPE_ALIGNMENT(ITestDispInherit*), /*size*/ sizeof(ITestDispInherit*),
+  /*helpctx*/ 0x0000, /*version*/ 0x00000000, /*#vtbl*/ 7, /*#func*/ 14, /*#var*/ 0,
+  { /* funcs */
+    {
+      /*id*/ 0x60000000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 2, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "QueryInterface",
+        "riid",
+        "ppvObj",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60000001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 1, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_UI4, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "AddRef",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60000002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 2, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_UI4, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "Release",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 3, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetTypeInfoCount",
+        "pctinfo",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 3, /*#opt*/ 0, /*vtbl*/ 4, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_UINT, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetTypeInfo",
+        "itinfo",
+        "lcid",
+        "pptinfo",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 5, /*#opt*/ 0, /*vtbl*/ 5, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_UINT, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "GetIDsOfNames",
+        "riid",
+        "rgszNames",
+        "cNames",
+        "lcid",
+        "rgdispid",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x60010003, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 8, /*#opt*/ 0, /*vtbl*/ 6, /*#scodes*/ 0, /*flags*/ FUNCFLAG_FRESTRICTED,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_I4, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_UI4, -1, PARAMFLAG_FIN},
+        {VT_UI2, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FIN},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {VT_PTR, -1, PARAMFLAG_FOUT},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "Invoke",
+        "dispidMember",
+        "riid",
+        "lcid",
+        "wFlags",
+        "pdispparams",
+        "pvarResult",
+        "pexcepinfo",
+        "puArgErr",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x1, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x2, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 8, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_void_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x3, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 9, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_VOID, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x4, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 10, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_HRESULT_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x5, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 11, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_INT, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x6, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 12, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {-1, 0, 0}
+      },
+      { /* names */
+        "test_int_retval",
+        NULL,
+      },
+    },
+    {
+      /*id*/ 0x7, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
+      /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 13, /*#scodes*/ 0, /*flags*/ 0,
+      {VT_R8, -1, PARAMFLAG_NONE}, /* ret */
+      { /* params */
+        {VT_BSTR, -1, PARAMFLAG_FIN},
+        {-1, 0, 0}
+      },
+      { /* names */
+        "parse_lcid",
+        "x",
+        NULL,
+      },
+    },
+  },
+  { /* vars */ },
 }
 };
 
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 06667850a3..2f7ce53b1c 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -2465,7 +2465,11 @@ MSFT_DoFuncs(TLBContext*     pcx,
         ptfd->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
         ptfd->funcdesc.cParams    =   pFuncRec->nrargs  ;
         ptfd->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
-        ptfd->funcdesc.oVft       =   (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
+        if(ptfd->funcdesc.funckind == FUNC_DISPATCH) {
+            ptfd->funcdesc.oVft       =   0;
+        } else {
+            ptfd->funcdesc.oVft       =   (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
+        }
         ptfd->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
 
         /* nameoffset is sometimes -1 on the second half of a propget/propput
@@ -4179,7 +4183,11 @@ static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
 	pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
 	pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
 	pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
-	pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
+	if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH) {
+	    pFuncDesc->funcdesc.oVft = 0;
+	} else {
+	    pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
+	}
 
 	if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
 	    pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
@@ -5849,11 +5857,13 @@ static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_pt
     } else
         dest->lprgelemdescParam = NULL;
 
-    /* special treatment for dispinterfaces: this makes functions appear
-     * to return their [retval] value when it is really returning an
-     * HRESULT */
-    if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
+    /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
+     * This accounts for several arguments that are seperate in the signature of
+     * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
+    if (dispinterface && (src->funckind != FUNC_DISPATCH))
     {
+        /* functions that have a [retval] parameter return this value into pVarResult.
+         * [retval] is always the last parameter (if present) */
         if (dest->cParams &&
             (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
         {
@@ -5866,19 +5876,28 @@ static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_pt
                 return E_UNEXPECTED;
             }
 
-            /* copy last parameter to the return value. we are using a flat
-             * buffer so there is no danger of leaking memory in
-             * elemdescFunc */
+            /* the type pointed to by this [retval] becomes elemdescFunc,
+             * i.e. functions signature's return type (replacing HRESULT/void/anything else)
+             * We are using a flat buffer so there is no danger of leaking memory */
             dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
 
             /* remove the last parameter */
             dest->cParams--;
         }
-        else
-            /* otherwise this function is made to appear to have no return
-             * value */
+        else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
+            /* Even if not otherwise replaced (by [retval],
+             * HRESULT is returned in pExcepInfo->scode, not pVarResult.
+             * So the function signature should show no return value. */
             dest->elemdescFunc.tdesc.vt = VT_VOID;
 
+        /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
+         * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
+        if (dest->cParams &&
+            (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
+        {
+            /* remove the last parameter */
+            dest->cParams--;
+        }
     }
 
     *dest_ptr = dest;
@@ -6105,36 +6124,38 @@ static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
     return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
 }
 
-/* ITypeInfo_GetNames
- *
- * Retrieves the variable with the specified member ID (or the name of the
- * property or method and its parameters) that correspond to the specified
- * function ID.
- */
-static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
-        BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
+/* internal function to make the inherited interfaces' methods appear
+ * part of the interface, remembering if the top-level was dispinterface */
+static HRESULT ITypeInfoImpl_GetNames( ITypeInfo *iface,
+        MEMBERID memid, BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames,
+        BOOL dispinterface)
 {
-    ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
+    ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
     const TLBFuncDesc *pFDesc;
     const TLBVarDesc *pVDesc;
     int i;
-    TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
-
-    if(!rgBstrNames)
-        return E_INVALIDARG;
 
     *pcNames = 0;
 
     pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
     if(pFDesc)
     {
+        UINT cParams = pFDesc->funcdesc.cParams;
         if(!cMaxNames || !pFDesc->Name)
             return S_OK;
 
         *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
         ++(*pcNames);
 
-        for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
+        if(dispinterface && (pFDesc->funcdesc.funckind != FUNC_DISPATCH)) {
+            /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc; */
+            if ((cParams > 0) && (pFDesc->funcdesc.lprgelemdescParam[cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
+                --cParams; /* Invoke(pVarResult) supplies the [retval] parameter, so its hidden from DISPPARAMS*/
+            if ((cParams > 0) && (pFDesc->funcdesc.lprgelemdescParam[cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
+                --cParams; /* Invoke(lcid) supplies the [lcid] parameter, so its hidden from DISPPARAMS */
+        }
+
+        for(i = 0; i < cParams; ++i) {
             if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
                 return S_OK;
             rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
@@ -6156,10 +6177,10 @@ static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
           /* recursive search */
           ITypeInfo *pTInfo;
           HRESULT result;
-          result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
+          result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
           if(SUCCEEDED(result))
 	  {
-            result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
+            result=ITypeInfoImpl_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames, dispinterface);
             ITypeInfo_Release(pTInfo);
             return result;
           }
@@ -6175,6 +6196,25 @@ static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
     return S_OK;
 }
 
+/* ITypeInfo_GetNames
+ *
+ * Retrieves the variable with the specified member ID (or the name of the
+ * property or method and its parameters) that correspond to the specified
+ * function ID.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
+        BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
+{
+    ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
+    TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
+
+    if(!rgBstrNames)
+        return E_INVALIDARG;
+
+    return ITypeInfoImpl_GetNames((ITypeInfo *)iface,
+        memid, rgBstrNames, cMaxNames, pcNames,
+        This->typeattr.typekind == TKIND_DISPATCH);
+}
 
 /* ITypeInfo::GetRefTypeOfImplType
  *




More information about the wine-devel mailing list