From 428ed94fa9f75c2036953352b50c217aa925479a Mon Sep 17 00:00:00 2001 From: Misha Koshelev Date: Wed, 6 Jun 2007 15:50:32 -0500 Subject: [PATCH] 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 05624e9880..cc2632fe58 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 6bf9dfd5fe..15585933c9 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)