oleaut32: Improve support for IDispatch in VarCat.

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alistair Leslie-Hughes 2017-06-13 22:35:06 +00:00 committed by Alexandre Julliard
parent 66b65474d1
commit 538e46adea
2 changed files with 78 additions and 49 deletions

View File

@ -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);

View File

@ -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]
*