Module: wine Branch: refs/heads/master Commit: be13d154c64581f3aa6b9e6ada8c72dd79bf3001 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=be13d154c64581f3aa6b9e6a...
Author: Robert Shearman rob@codeweavers.com Date: Mon Jan 30 14:55:57 2006 +0100
oleaut: Fix the order of parameters passed into DispCallFunc.
---
dlls/oleaut32/typelib.c | 71 +++++++++++++++++++++++++++-------------------- 1 files changed, 41 insertions(+), 30 deletions(-)
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 64ae776..2dbbd34 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -5101,10 +5101,9 @@ static HRESULT typedescvt_to_variantvt(I *|CC_MPWCDECL *|CC_MPWPASCAL * - * BUGS - * Native accepts arguments in the reverse order. I.e. the first item in the - * prgpvarg array is the last argument in the C/C++ declaration of the - * function to be called. + * The rgpvarg array contains the parameters, but in the opposite order to + * what is usually assumed. The first parameter in rgpvarg is the last + * parameter in the function call and vice-versa. */ HRESULT WINAPI DispCallFunc( @@ -5138,10 +5137,11 @@ DispCallFunc( argspos++; }
- for (i=0;i<cActuals;i++) + for (i = cActuals - 1; i >= 0; 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)); argspos += _argsize(prgvt[i]); } @@ -5228,8 +5228,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke hres = S_OK; for (i = 0; i < func_desc->cParams; i++) { + UINT varindex = func_desc->cParams - 1 - i; 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)) goto func_fail; } @@ -5238,6 +5239,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke for (i = 0; i < func_desc->cParams; i++) { USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; + UINT varindex = func_desc->cParams - 1 - i;
if (wParamFlags & PARAMFLAG_FRETVAL) { @@ -5247,9 +5249,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke if (i == func_desc->cParams - 1) { VARIANTARG *arg; - arg = prgpvarg[i] = &rgvarg[i]; + arg = prgpvarg[varindex] = &rgvarg[varindex]; memset(arg, 0, sizeof(*arg)); - V_VT(arg) = rgvt[i]; + V_VT(arg) = rgvt[varindex]; memset(&retval, 0, sizeof(retval)); V_BYREF(arg) = &retval; } @@ -5263,35 +5265,38 @@ static HRESULT WINAPI ITypeInfo_fnInvoke else if (i < pDispParams->cArgs) { 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);
/* FIXME: this doesn't work for VT_BYREF arguments if * 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); - V_VT(&missing_arg[i]) = V_VT(src_arg); - hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); - V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); + V_VT(&missing_arg[varindex]) = V_VT(src_arg); + hres = VariantChangeType(&missing_arg[varindex], + src_arg, 0, + rgvt[varindex] & ~VT_BYREF); + V_BYREF(&rgvarg[varindex]) = &V_NONE(&missing_arg[varindex]); } else - hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); + hres = VariantChangeType(&rgvarg[varindex], src_arg, + 0, rgvt[varindex]);
if (FAILED(hres)) { 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)); break; } - V_VT(&rgvarg[i]) = rgvt[i]; - prgpvarg[i] = &rgvarg[i]; + V_VT(&rgvarg[varindex]) = rgvt[varindex]; + prgpvarg[varindex] = &rgvarg[varindex]; } else if (wParamFlags & PARAMFLAG_FOPT) { VARIANTARG *arg; - arg = prgpvarg[i] = &rgvarg[i]; + arg = prgpvarg[varindex] = &rgvarg[varindex]; if (wParamFlags & PARAMFLAG_FHASDEFAULT) { 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); 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_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND; } @@ -5331,38 +5336,44 @@ static HRESULT WINAPI ITypeInfo_fnInvoke
for (i = 0; i < func_desc->cParams; i++) { + UINT varindex = func_desc->cParams - 1 - i; USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; if (wParamFlags & PARAMFLAG_FRETVAL) { if (TRACE_ON(ole)) { TRACE("[retval] value: "); - dump_Variant(prgpvarg[i]); + dump_Variant(prgpvarg[varindex]); }
if (pVarResult) + { /* 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 * VariantClear doesn't do what we want because we are * working with byref types. */ /* FIXME: clear safearrays, bstrs, records and * variants here too */ - if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) || - (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF))) + if ((V_VT(prgpvarg[varindex]) == (VT_UNKNOWN | VT_BYREF)) || + (V_VT(prgpvarg[varindex]) == (VT_DISPATCH | VT_BYREF))) { - if(*V_UNKNOWNREF(prgpvarg[i])) - IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i])); + if(*V_UNKNOWNREF(prgpvarg[varindex])) + IUnknown_Release(*V_UNKNOWNREF(prgpvarg[varindex])); } break; } - else if (i < pDispParams->cArgs) + + if (i < pDispParams->cArgs) { if (wParamFlags & PARAMFLAG_FOUT) { hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i], - &rgvarg[i], 0, + &rgvarg[varindex], 0, V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i])); if (FAILED(hres)) { @@ -5371,12 +5382,12 @@ static HRESULT WINAPI ITypeInfo_fnInvoke break; } } - VariantClear(&rgvarg[i]); + VariantClear(&rgvarg[varindex]); } else if (wParamFlags & PARAMFLAG_FOPT) { if (wParamFlags & PARAMFLAG_FHASDEFAULT) - VariantClear(&rgvarg[i]); + VariantClear(&rgvarg[varindex]); } }