Robert Shearman : oleaut: Fix the order of parameters passed into DispCallFunc.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jan 30 08:04:07 CST 2006


Module: wine
Branch: refs/heads/master
Commit: be13d154c64581f3aa6b9e6ada8c72dd79bf3001
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=be13d154c64581f3aa6b9e6ada8c72dd79bf3001

Author: Robert Shearman <rob at 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]);
                 }
             }
 




More information about the wine-cvs mailing list