oleaut: Fix the order of parameters passed into DispCallFunc.

This commit is contained in:
Robert Shearman 2006-01-30 14:55:57 +01:00 committed by Alexandre Julliard
parent b94ceeeb7c
commit be13d154c6
1 changed files with 41 additions and 30 deletions

View File

@ -5101,10 +5101,9 @@ static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc,
*|CC_MPWCDECL *|CC_MPWCDECL
*|CC_MPWPASCAL *|CC_MPWPASCAL
* *
* BUGS * The rgpvarg array contains the parameters, but in the opposite order to
* Native accepts arguments in the reverse order. I.e. the first item in the * what is usually assumed. The first parameter in rgpvarg is the last
* prgpvarg array is the last argument in the C/C++ declaration of the * parameter in the function call and vice-versa.
* function to be called.
*/ */
HRESULT WINAPI HRESULT WINAPI
DispCallFunc( DispCallFunc(
@ -5138,10 +5137,11 @@ DispCallFunc(
argspos++; argspos++;
} }
for (i=0;i<cActuals;i++) for (i = cActuals - 1; i >= 0; i--)
{ {
VARIANT *arg = prgpvarg[i]; VARIANT *arg = prgpvarg[i];
TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]); TRACE("Storing arg %d from left (%d as %d)\n", cActuals - 1 - i,
V_VT(arg), prgvt[i]);
memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD)); memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
argspos += _argsize(prgvt[i]); argspos += _argsize(prgvt[i]);
} }
@ -5228,8 +5228,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
hres = S_OK; hres = S_OK;
for (i = 0; i < func_desc->cParams; i++) for (i = 0; i < func_desc->cParams; i++)
{ {
UINT varindex = func_desc->cParams - 1 - i;
TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]); hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[varindex]);
if (FAILED(hres)) if (FAILED(hres))
goto func_fail; goto func_fail;
} }
@ -5238,6 +5239,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
for (i = 0; i < func_desc->cParams; i++) for (i = 0; i < func_desc->cParams; i++)
{ {
USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
UINT varindex = func_desc->cParams - 1 - i;
if (wParamFlags & PARAMFLAG_FRETVAL) if (wParamFlags & PARAMFLAG_FRETVAL)
{ {
@ -5247,9 +5249,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
if (i == func_desc->cParams - 1) if (i == func_desc->cParams - 1)
{ {
VARIANTARG *arg; VARIANTARG *arg;
arg = prgpvarg[i] = &rgvarg[i]; arg = prgpvarg[varindex] = &rgvarg[varindex];
memset(arg, 0, sizeof(*arg)); memset(arg, 0, sizeof(*arg));
V_VT(arg) = rgvt[i]; V_VT(arg) = rgvt[varindex];
memset(&retval, 0, sizeof(retval)); memset(&retval, 0, sizeof(retval));
V_BYREF(arg) = &retval; V_BYREF(arg) = &retval;
} }
@ -5263,35 +5265,38 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
else if (i < pDispParams->cArgs) else if (i < pDispParams->cArgs)
{ {
VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i]; VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
V_VT(&rgvarg[i]) = V_VT(src_arg); V_VT(&rgvarg[varindex]) = V_VT(src_arg);
dump_Variant(src_arg); dump_Variant(src_arg);
/* FIXME: this doesn't work for VT_BYREF arguments if /* FIXME: this doesn't work for VT_BYREF arguments if
* they are not the same type as in the paramdesc */ * they are not the same type as in the paramdesc */
if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) if ((rgvt[varindex] & VT_BYREF) && !V_ISBYREF(src_arg))
{ {
VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
V_VT(&missing_arg[i]) = V_VT(src_arg); V_VT(&missing_arg[varindex]) = V_VT(src_arg);
hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); hres = VariantChangeType(&missing_arg[varindex],
V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); src_arg, 0,
rgvt[varindex] & ~VT_BYREF);
V_BYREF(&rgvarg[varindex]) = &V_NONE(&missing_arg[varindex]);
} }
else else
hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); hres = VariantChangeType(&rgvarg[varindex], src_arg,
0, rgvt[varindex]);
if (FAILED(hres)) if (FAILED(hres))
{ {
ERR("failed to convert param %d to %s%s from %s%s\n", i, ERR("failed to convert param %d to %s%s from %s%s\n", i,
debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]), debugstr_vt(rgvt[varindex]), debugstr_vf(rgvt[varindex]),
debugstr_VT(src_arg), debugstr_VF(src_arg)); debugstr_VT(src_arg), debugstr_VF(src_arg));
break; break;
} }
V_VT(&rgvarg[i]) = rgvt[i]; V_VT(&rgvarg[varindex]) = rgvt[varindex];
prgpvarg[i] = &rgvarg[i]; prgpvarg[varindex] = &rgvarg[varindex];
} }
else if (wParamFlags & PARAMFLAG_FOPT) else if (wParamFlags & PARAMFLAG_FOPT)
{ {
VARIANTARG *arg; VARIANTARG *arg;
arg = prgpvarg[i] = &rgvarg[i]; arg = prgpvarg[varindex] = &rgvarg[varindex];
if (wParamFlags & PARAMFLAG_FHASDEFAULT) if (wParamFlags & PARAMFLAG_FHASDEFAULT)
{ {
hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
@ -5302,7 +5307,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
{ {
VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
V_VT(arg) = VT_VARIANT | VT_BYREF; V_VT(arg) = VT_VARIANT | VT_BYREF;
V_VARIANTREF(arg) = &missing_arg[i]; V_VARIANTREF(arg) = &missing_arg[varindex];
V_VT(V_VARIANTREF(arg)) = VT_ERROR; V_VT(V_VARIANTREF(arg)) = VT_ERROR;
V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND; V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
} }
@ -5331,38 +5336,44 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
for (i = 0; i < func_desc->cParams; i++) for (i = 0; i < func_desc->cParams; i++)
{ {
UINT varindex = func_desc->cParams - 1 - i;
USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
if (wParamFlags & PARAMFLAG_FRETVAL) if (wParamFlags & PARAMFLAG_FRETVAL)
{ {
if (TRACE_ON(ole)) if (TRACE_ON(ole))
{ {
TRACE("[retval] value: "); TRACE("[retval] value: ");
dump_Variant(prgpvarg[i]); dump_Variant(prgpvarg[varindex]);
} }
if (pVarResult) if (pVarResult)
{
/* deref return value */ /* deref return value */
hres = VariantCopyInd(pVarResult, prgpvarg[i]); hres = VariantCopyInd(pVarResult, prgpvarg[varindex]);
TRACE("derefed [retval] value: ");
dump_Variant(pVarResult);
}
/* free data stored in varresult. Note that /* free data stored in varresult. Note that
* VariantClear doesn't do what we want because we are * VariantClear doesn't do what we want because we are
* working with byref types. */ * working with byref types. */
/* FIXME: clear safearrays, bstrs, records and /* FIXME: clear safearrays, bstrs, records and
* variants here too */ * variants here too */
if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) || if ((V_VT(prgpvarg[varindex]) == (VT_UNKNOWN | VT_BYREF)) ||
(V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF))) (V_VT(prgpvarg[varindex]) == (VT_DISPATCH | VT_BYREF)))
{ {
if(*V_UNKNOWNREF(prgpvarg[i])) if(*V_UNKNOWNREF(prgpvarg[varindex]))
IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i])); IUnknown_Release(*V_UNKNOWNREF(prgpvarg[varindex]));
} }
break; break;
} }
else if (i < pDispParams->cArgs)
if (i < pDispParams->cArgs)
{ {
if (wParamFlags & PARAMFLAG_FOUT) if (wParamFlags & PARAMFLAG_FOUT)
{ {
hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i], hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i],
&rgvarg[i], 0, &rgvarg[varindex], 0,
V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i])); V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
if (FAILED(hres)) if (FAILED(hres))
{ {
@ -5371,12 +5382,12 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
break; break;
} }
} }
VariantClear(&rgvarg[i]); VariantClear(&rgvarg[varindex]);
} }
else if (wParamFlags & PARAMFLAG_FOPT) else if (wParamFlags & PARAMFLAG_FOPT)
{ {
if (wParamFlags & PARAMFLAG_FHASDEFAULT) if (wParamFlags & PARAMFLAG_FHASDEFAULT)
VariantClear(&rgvarg[i]); VariantClear(&rgvarg[varindex]);
} }
} }