diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c index a271c5092a1..d8a6ebf8cbd 100644 --- a/dlls/oleaut32/tests/vartest.c +++ b/dlls/oleaut32/tests/vartest.c @@ -6093,7 +6093,7 @@ static void test_VarCat(void) SET_EXPECT(dispatch_invoke); hres = VarCat(&left, &right, &result); - todo_wine ok(hres == S_OK, "got 0x%08x\n", hres); + ok(hres == S_OK, "got 0x%08x\n", hres); ok(V_VT(&result) == VT_BSTR, "got %d\n", V_VT(&result)); ok(SysStringLen(V_BSTR(&result)) == 0, "got %d\n", SysStringLen(V_BSTR(&result))); CHECK_CALLED(dispatch_invoke); @@ -6108,7 +6108,7 @@ static void test_VarCat(void) SET_EXPECT(dispatch_invoke); hres = VarCat(&left, &right, &result); - todo_wine ok(hres == S_OK, "got 0x%08x\n", hres); + ok(hres == S_OK, "got 0x%08x\n", hres); ok(V_VT(&result) == VT_BSTR, "got %d\n", V_VT(&result)); ok(SysStringLen(V_BSTR(&result)) == 0, "got %d\n", SysStringLen(V_BSTR(&result))); CHECK_CALLED(dispatch_invoke); @@ -6140,7 +6140,21 @@ static void test_VarCat(void) SET_EXPECT(dispatch_invoke); hres = VarCat(&left, &right, &result); - todo_wine ok(hres == E_OUTOFMEMORY, "got 0x%08x\n", hres); + ok(hres == E_OUTOFMEMORY, "got 0x%08x\n", hres); + CHECK_CALLED(dispatch_invoke); + + VariantClear(&left); + VariantClear(&right); + VariantClear(&result); + + init_test_dispatch(VT_NULL, &dispatch); + dispatch.result = DISP_E_TYPEMISMATCH; + V_VT(&right) = VT_DISPATCH; + V_DISPATCH(&right) = &dispatch.IDispatch_iface; + + SET_EXPECT(dispatch_invoke); + hres = VarCat(&left, &right, &result); + ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hres); CHECK_CALLED(dispatch_invoke); VariantClear(&left); diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index 2dcded5989c..ee203d7c729 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -515,6 +515,22 @@ static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYP return DISP_E_TYPEMISMATCH; } +static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue) +{ + HRESULT hres; + static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 }; + + if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) { + if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH; + hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL, + LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue, + NULL, NULL); + } else { + hres = DISP_E_TYPEMISMATCH; + } + return hres; +} + /****************************************************************************** * Check if a variants type is valid. */ @@ -2503,7 +2519,7 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) { VARTYPE leftvt,rightvt,resultvt; HRESULT hres; - static const WCHAR sz_empty[] = {'\0'}; + leftvt = V_VT(left); rightvt = V_VT(right); @@ -2581,64 +2597,79 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) else { VARIANT bstrvar_left, bstrvar_right; + VARIANT *tmp; + VARIANT fetched; + V_VT(out) = VT_BSTR; VariantInit(&bstrvar_left); VariantInit(&bstrvar_right); + VariantInit(&fetched); /* Convert left side variant to string */ if (leftvt != VT_BSTR) { - /* Fill with empty string for later concat with right side */ - if (leftvt == VT_NULL) + tmp = left; + + if(leftvt == VT_DISPATCH) + { + hres = VARIANT_FetchDispatchValue(left, &fetched); + if(FAILED(hres)) + goto failed; + + tmp = &fetched; + } + + hres = VariantChangeTypeEx(&bstrvar_left,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR); + VariantClear(&fetched); + if (hres == DISP_E_TYPEMISMATCH) { V_VT(&bstrvar_left) = VT_BSTR; - V_BSTR(&bstrvar_left) = SysAllocString(sz_empty); - } - else - { - hres = VariantChangeTypeEx(&bstrvar_left,left,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR); - if (hres != S_OK) { - VariantClear(&bstrvar_left); - VariantClear(&bstrvar_right); - return hres; - } + V_BSTR(&bstrvar_left) = SysAllocStringLen(NULL, 0); } + else if(hres != S_OK) + goto failed; } /* convert right side variant to string */ if (rightvt != VT_BSTR) { - /* Fill with empty string for later concat with right side */ - if (rightvt == VT_NULL) + tmp = right; + + if(rightvt == VT_DISPATCH) + { + hres = VARIANT_FetchDispatchValue(right, &fetched); + if(FAILED(hres)) + goto failed; + + tmp = &fetched; + } + + hres = VariantChangeTypeEx(&bstrvar_right,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR); + VariantClear(&fetched); + if (hres == DISP_E_TYPEMISMATCH) { V_VT(&bstrvar_right) = VT_BSTR; - V_BSTR(&bstrvar_right) = SysAllocString(sz_empty); - } - else - { - hres = VariantChangeTypeEx(&bstrvar_right,right,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR); - if (hres != S_OK) { - VariantClear(&bstrvar_left); - VariantClear(&bstrvar_right); - return hres; - } + V_BSTR(&bstrvar_right) = SysAllocStringLen(NULL, 0); } + else if(hres != S_OK) + goto failed; } /* Concat the resulting strings together */ if (leftvt == VT_BSTR && rightvt == VT_BSTR) - VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out)); + hres = VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out)); else if (leftvt != VT_BSTR && rightvt != VT_BSTR) - VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out)); + hres = VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out)); else if (leftvt != VT_BSTR && rightvt == VT_BSTR) - VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out)); + hres = VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out)); else if (leftvt == VT_BSTR && rightvt != VT_BSTR) - VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out)); + hres = VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out)); +failed: VariantClear(&bstrvar_left); VariantClear(&bstrvar_right); - return S_OK; + return hres; } } @@ -2865,22 +2896,6 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags) #undef _VARCMP } -static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue) -{ - HRESULT hres; - static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 }; - - if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) { - if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH; - hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue, - NULL, NULL); - } else { - hres = DISP_E_TYPEMISMATCH; - } - return hres; -} - /********************************************************************** * VarAnd [OLEAUT32.142] *