oleaut32: ITypeInfo_fnInvoke behavior on PARAMFLAG_FOPT without
PARAMFLAG_FHASDEFAULT
Robert Shearman
rob at codeweavers.com
Mon Nov 6 04:27:20 CST 2006
a_villacis at palosanto.com wrote:
> 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
>
>
I don't believe this is fix is correct. See the tests not included in
Wine yet here:
http://www.winehq.org/pipermail/wine-patches/2006-August/029511.html
In particular, this code:
> +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;
> +}
--
Rob Shearman
More information about the wine-devel
mailing list