In a tax app written in Visual Basic/ADO, I found the following problem:
In dlls/oleaut32/typelib.c, in function ITypeInfo_fnInvoke(), the
following code is found (around line 5569).
VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer,
func_desc->cParams);
V_VT(arg) = VT_VARIANT | VT_BYREF;
V_VARIANTREF(arg) = &missing_arg[i];
V_VT(V_VARIANTREF(arg)) = VT_ERROR;
V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
This code runs when a parameter is found that has the PARAMFLAG_FIN and
PARAMFLAG_FOPT flags, but not the PARAMFLAG_FHASDEFAULT flag. As far
as I
understand, this code is supposed to supply a variant that might hold an
output value. However, in the Append method of the Fields object within
the Recordset object of Microsoft ADODB 2.7, the following
declaration is
found:
trace:ole:ITypeInfo_fnInvoke invoking:
L"Append"(5)
parm0: L"Name"
parm1: L"Type"
parm2: L"DefinedSize"
parm3: L"Attrib"
parm4: L"FieldValue"
memid is 00000003
Param 0:
tdesc.vartype 8 (VT_BSTR)
u.paramdesc.wParamFlags PARAMFLAG_FIN
u.paramdesc.lpex (nil)
Param 1:
tdesc.vartype 29 (VT_USERDEFINED ref = 2bc)
u.paramdesc.wParamFlags PARAMFLAG_FIN
u.paramdesc.lpex (nil)
Param 2:
tdesc.vartype 29 (VT_USERDEFINED ref = 1c84)
u.paramdesc.wParamFlags PARAMFLAG_FIN PARAMFLAG_FOPT
PARAMFLAG_FHASDEFAULT
u.paramdesc.lpex 0x199868
Param 3:
tdesc.vartype 29 (VT_USERDEFINED ref = 320)
u.paramdesc.wParamFlags PARAMFLAG_FIN PARAMFLAG_FOPT
PARAMFLAG_FHASDEFAULT
u.paramdesc.lpex 0x1998d0
Param 4:
tdesc.vartype 12 (VT_VARIANT)
u.paramdesc.wParamFlags PARAMFLAG_FIN PARAMFLAG_FOPT
u.paramdesc.lpex (nil)
funckind: 1 (pure virtual)
invkind: 1 (func)
callconv: 4 (stdcall)
oVft: 52
cParamsOpt: 1
wFlags: 0
elemdescFunc (return value type):
tdesc.vartype 25 (VT_HRESULT)
u.paramdesc.wParamFlags PARAMFLAGS_NONE
u.paramdesc.lpex (nil)
helpstring: (null)
entry (ordinal): 0x0000
The implementation of the method in Microsoft ADODB 2.7 last parameter
(FieldValue) absolutely refuses to accept a VT_VARIANT | VT_BYREF
variant.
This result is not dependent of the type of variant pointed to by the
first-level variant - changing VT_ERROR to VT_EMPTY has no effect.
Only by
passing a VT_EMPTY instead of a VT_VARIANT | VT_BYREF can the
application
proceed normally. All oleaut32 tests still pass. Please comment if
this is
an appropriate fix for this issue.
Changelog:
* (PARAMFLAG_FIN | PARAMFLAG_FOPT) & ~PARAMFLAG_FHASDEFAULT should
result
in a default parameter of VT_EMPTY, not a VT_VARIANT | VT_BYREF in
ITypeInfo_fnInvoke
+HRESULT WINAPI Widget_DoSomething(
+ IWidget __RPC_FAR * iface,
+ /* [in] */ double number,
+ /* [out] */ BSTR *str1,
+ /* [defaultvalue][in] */ BSTR str2,
+ /* [optional][in] */ VARIANT __RPC_FAR *opt)
+{
+ static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
+ trace("DoSomething()\n");
+
+ ok(number == 3.141, "number(%f) != 3.141\n", number);
+ ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
+ ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead
of 0x%x\n", V_VT(opt));
+ ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be
DISP_E_PARAMNOTFOUND instead of 0x%08lx\n", V_ERROR(opt));
+ *str1 = SysAllocString(szString);
+
+ return S_FALSE;
+}