[PATCH] oleaut32: Improve support for IDispatch in VarCat
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Tue Jun 13 17:35:06 CDT 2017
v3: Use worker function to get the value from Dispatch.
v4: Use SysStringLen() for empty string.
We cannot use VariantChangeTypeEx to convert the IDispatch type
since it always returns DISP_E_TYPEMISMATCH when the Invoke fails.
Fixes https://bugs.winehq.org/show_bug.cgi?id=27106
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
dlls/oleaut32/tests/vartest.c | 20 ++++++--
dlls/oleaut32/variant.c | 103 ++++++++++++++++++++++++------------------
2 files changed, 76 insertions(+), 47 deletions(-)
diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index a271c5092a..d8a6ebf8cb 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 2dcded5989..ee203d7c72 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)
{
- V_VT(&bstrvar_left) = VT_BSTR;
- V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
+ hres = VARIANT_FetchDispatchValue(left, &fetched);
+ if(FAILED(hres))
+ goto failed;
+
+ tmp = &fetched;
}
- else
+
+ hres = VariantChangeTypeEx(&bstrvar_left,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
+ VariantClear(&fetched);
+ if (hres == DISP_E_TYPEMISMATCH)
{
- 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_VT(&bstrvar_left) = VT_BSTR;
+ 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)
{
- V_VT(&bstrvar_right) = VT_BSTR;
- V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
+ hres = VARIANT_FetchDispatchValue(right, &fetched);
+ if(FAILED(hres))
+ goto failed;
+
+ tmp = &fetched;
}
- else
+
+ hres = VariantChangeTypeEx(&bstrvar_right,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
+ VariantClear(&fetched);
+ if (hres == DISP_E_TYPEMISMATCH)
{
- 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_VT(&bstrvar_right) = VT_BSTR;
+ 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]
*
--
2.11.0
More information about the wine-patches
mailing list