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