Misha Koshelev : oleaut32: Add support for vararg functions in ITypeInfo:: Invoke.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 7 07:20:23 CDT 2007


Module: wine
Branch: master
Commit: 428ed94fa9f75c2036953352b50c217aa925479a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=428ed94fa9f75c2036953352b50c217aa925479a

Author: Misha Koshelev <mk144210 at bcm.edu>
Date:   Wed Jun  6 15:50:32 2007 -0500

oleaut32: Add support for vararg functions in ITypeInfo::Invoke.

---

 dlls/oleaut32/tests/tmarshal.c |    4 +-
 dlls/oleaut32/typelib.c        |   71 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c
index 05624e9..cc2632f 100644
--- a/dlls/oleaut32/tests/tmarshal.c
+++ b/dlls/oleaut32/tests/tmarshal.c
@@ -1007,14 +1007,14 @@ static void test_typelibmarshal(void)
     dispparams.rgdispidNamedArgs = NULL;
     dispparams.rgvarg = vararg;
     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
-    todo_wine ok_ole_success(hr, ITypeInfo_Invoke);
+    ok_ole_success(hr, ITypeInfo_Invoke);
 
     /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
     dispidNamed = 0;
     dispparams.cNamedArgs = 1;
     dispparams.rgdispidNamedArgs = &dispidNamed;
     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
-    todo_wine ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
+    ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
     dispidNamed = DISPID_PROPERTYPUT;
 
     /* call Error */
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 6bf9dfd..1558593 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -5594,6 +5594,13 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                 rgdispidNamedArgs++;
             }
 
+            if (func_desc->cParamsOpt < 0 && cNamedArgs)
+            {
+                ERR("functions with the vararg attribute do not support named arguments\n");
+                hres = DISP_E_NONAMEDARGS;
+                goto func_fail;
+            }
+
             for (i = 0; i < func_desc->cParams; i++)
             {
                 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
@@ -5674,6 +5681,36 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         }
                         V_VT(&rgvarg[i]) = rgvt[i];
                     }
+                    else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
+                    {
+                        SAFEARRAY *a;
+                        SAFEARRAYBOUND bound;
+                        VARIANT *v;
+                        LONG j;
+                        bound.lLbound = 0;
+                        bound.cElements = pDispParams->cArgs-i;
+                        if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
+                        {
+                            ERR("SafeArrayCreate failed\n");
+                            break;
+                        }
+                        hres = SafeArrayAccessData(a, (LPVOID)&v);
+                        if (hres != S_OK)
+                        {
+                            ERR("SafeArrayAccessData failed with %x\n", hres);
+                            break;
+                        }
+                        for (j = 0; j < bound.cElements; j++)
+                            VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
+                        hres = SafeArrayUnaccessData(a);
+                        if (hres != S_OK)
+                        {
+                            ERR("SafeArrayUnaccessData failed with %x\n", hres);
+                            break;
+                        }
+                        V_ARRAY(&rgvarg[i]) = a;
+                        V_VT(&rgvarg[i]) = rgvt[i];
+                    }
                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
                     {
                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
@@ -5740,12 +5777,6 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                 }
             }
             if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
-            if (func_desc->cParamsOpt < 0)
-            {
-                FIXME("Does not support safearray optional parameters\n");
-                hres = DISP_E_BADPARAMCOUNT;
-                goto func_fail; /* FIXME: we don't free changed types here */
-            }
 
             /* VT_VOID is a special case for return types, so it is not
              * handled in the general function */
@@ -5809,6 +5840,34 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                             break;
                         }
                     }
+                    else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
+                             func_desc->cParamsOpt < 0 &&
+                             i == func_desc->cParams-1)
+                    {
+                        SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
+                        LONG j, ubound;
+                        VARIANT *v;
+                        hres = SafeArrayGetUBound(a, 1, &ubound);
+                        if (hres != S_OK)
+                        {
+                            ERR("SafeArrayGetUBound failed with %x\n", hres);
+                            break;
+                        }
+                        hres = SafeArrayAccessData(a, (LPVOID)&v);
+                        if (hres != S_OK)
+                        {
+                            ERR("SafeArrayAccessData failed with %x\n", hres);
+                            break;
+                        }
+                        for (j = 0; j <= ubound; j++)
+                            VariantClear(&v[j]);
+                        hres = SafeArrayUnaccessData(a);
+                        if (hres != S_OK)
+                        {
+                            ERR("SafeArrayUnaccessData failed with %x\n", hres);
+                            break;
+                        }
+                    }
                     VariantClear(&rgvarg[i]);
                 }
                 else if (wParamFlags & PARAMFLAG_FOPT)




More information about the wine-cvs mailing list