oleaut32:VatCat fixes initialization and conformance test
Benjamin Arai
me at benjaminarai.com
Tue Jul 18 18:44:16 CDT 2006
Changelog:
- Helps address http://bugs.winehq.com/show_bug.cgi?id=3628
- Addresses variant initialization and missing conformance test
issues brought up by Qingdoa Daoo
- Fixes VarCat conformance test failures exposed by Rob Shearman:
"oleaut32: Test the return value of VarCat in the tests."
A test may pass on Windows because it returned without any errors
(S_OK) but on Wine that same test can technically fail but be
misinterpeted as a correct result in Wine if the expected error code
is returned. Temporary variants may be uninitialized before usage in
specific cases causing unexpected results.
-------------- next part --------------
---
dlls/oleaut32/tests/vartest.c | 158 +++++++++++++++++------------------------
dlls/oleaut32/variant.c | 122 ++++++++++++++++++++++----------
2 files changed, 150 insertions(+), 130 deletions(-)
diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index 642bd94..79bbd9e 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -5109,6 +5109,7 @@ static void test_VarCat(void)
TCHAR orig_date_format[128];
VARTYPE leftvt, rightvt, resultvt;
HRESULT hres;
+ HRESULT expected_error_num;
/* Set date format for testing */
lcid = LOCALE_USER_DEFAULT;
@@ -5128,52 +5129,70 @@ static void test_VarCat(void)
for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
{
- BOOL bFail = FALSE;
+
SKIPTESTS(rightvt);
+ expected_error_num = S_OK;
+ resultvt = VT_EMPTY;
if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH ||
- leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN ||
- leftvt == VT_RECORD || rightvt == VT_RECORD ||
- leftvt == VT_CLSID || rightvt == VT_CLSID ||
- leftvt == VT_BSTR_BLOB || rightvt == VT_BSTR_BLOB
- )
- continue;
+ leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN ||
+ leftvt == VT_RECORD || rightvt == VT_RECORD ||
+ leftvt == 15 || rightvt == 15 /* Undefined type */)
+ continue;
- if (leftvt == VT_ERROR || rightvt == VT_ERROR)
- resultvt = VT_EMPTY;
- else if (leftvt == VT_NULL && rightvt == VT_NULL)
+ if (leftvt == VT_NULL && rightvt == VT_NULL)
resultvt = VT_NULL;
+ else if (leftvt == VT_VARIANT && (rightvt == VT_ERROR ||
+ rightvt == VT_DATE || rightvt == VT_DECIMAL))
+ expected_error_num = DISP_E_TYPEMISMATCH;
else if ((leftvt == VT_I2 || leftvt == VT_I4 ||
- leftvt == VT_R4 || leftvt == VT_R8 ||
- leftvt == VT_CY || leftvt == VT_BOOL ||
- leftvt == VT_BSTR || leftvt == VT_I1 ||
- leftvt == VT_UI1 || leftvt == VT_UI2 ||
- leftvt == VT_UI4 || leftvt == VT_I8 ||
- leftvt == VT_UI8 || leftvt == VT_INT ||
- leftvt == VT_UINT || leftvt == VT_EMPTY ||
- leftvt == VT_NULL || leftvt == VT_DECIMAL ||
- leftvt == VT_DATE)
- &&
- (rightvt == VT_I2 || rightvt == VT_I4 ||
- rightvt == VT_R4 || rightvt == VT_R8 ||
- rightvt == VT_CY || rightvt == VT_BOOL ||
- rightvt == VT_BSTR || rightvt == VT_I1 ||
- rightvt == VT_UI1 || rightvt == VT_UI2 ||
- rightvt == VT_UI4 || rightvt == VT_I8 ||
- rightvt == VT_UI8 || rightvt == VT_INT ||
- rightvt == VT_UINT || rightvt == VT_EMPTY ||
- rightvt == VT_NULL || rightvt == VT_DECIMAL ||
- rightvt == VT_DATE))
- {
+ leftvt == VT_R4 || leftvt == VT_R8 ||
+ leftvt == VT_CY || leftvt == VT_BOOL ||
+ leftvt == VT_BSTR || leftvt == VT_I1 ||
+ leftvt == VT_UI1 || leftvt == VT_UI2 ||
+ leftvt == VT_UI4 || leftvt == VT_I8 ||
+ leftvt == VT_UI8 || leftvt == VT_INT ||
+ leftvt == VT_UINT || leftvt == VT_EMPTY ||
+ leftvt == VT_NULL || leftvt == VT_DECIMAL ||
+ leftvt == VT_DATE)
+ &&
+ (rightvt == VT_I2 || rightvt == VT_I4 ||
+ rightvt == VT_R4 || rightvt == VT_R8 ||
+ rightvt == VT_CY || rightvt == VT_BOOL ||
+ rightvt == VT_BSTR || rightvt == VT_I1 ||
+ rightvt == VT_UI1 || rightvt == VT_UI2 ||
+ rightvt == VT_UI4 || rightvt == VT_I8 ||
+ rightvt == VT_UI8 || rightvt == VT_INT ||
+ rightvt == VT_UINT || rightvt == VT_EMPTY ||
+ rightvt == VT_NULL || rightvt == VT_DECIMAL ||
+ rightvt == VT_DATE))
resultvt = VT_BSTR;
- }
+ else if (rightvt == VT_ERROR && leftvt < VT_VOID)
+ expected_error_num = DISP_E_TYPEMISMATCH;
+ else if (leftvt == VT_ERROR && (rightvt == VT_DATE ||
+ rightvt == VT_ERROR || rightvt == VT_DECIMAL))
+ expected_error_num = DISP_E_TYPEMISMATCH;
+ else if (rightvt == VT_DATE || rightvt == VT_ERROR ||
+ rightvt == VT_DECIMAL)
+ expected_error_num = DISP_E_BADVARTYPE;
+ else if (leftvt == VT_ERROR || rightvt == VT_ERROR)
+ expected_error_num = DISP_E_TYPEMISMATCH;
+ else if (leftvt == VT_VARIANT)
+ expected_error_num = DISP_E_TYPEMISMATCH;
+ else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY ||
+ leftvt == VT_NULL || leftvt == VT_I2 ||
+ leftvt == VT_I4 || leftvt == VT_R4 ||
+ leftvt == VT_R8 || leftvt == VT_CY ||
+ leftvt == VT_DATE || leftvt == VT_BSTR ||
+ leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
+ leftvt == VT_I1 || leftvt == VT_UI1 ||
+ leftvt == VT_UI2 || leftvt == VT_UI4 ||
+ leftvt == VT_I8 || leftvt == VT_UI8 ||
+ leftvt == VT_INT || leftvt == VT_UINT
+ ))
+ expected_error_num = DISP_E_TYPEMISMATCH;
else
- resultvt = VT_EMPTY;
-
- if (leftvt == VT_ERROR || rightvt == VT_ERROR)
- {
- bFail = TRUE;
- }
+ expected_error_num = DISP_E_BADVARTYPE;
V_VT(&left) = leftvt;
V_VT(&right) = rightvt;
@@ -5192,57 +5211,16 @@ static void test_VarCat(void)
VarDecFromR8(0.0, &V_DECIMAL(&right));
hres = VarCat(&left, &right, &result);
- if (bFail) {
- /* Determine the error code for the vt combination */
- HRESULT expected_error_num = S_OK;
- if (rightvt == VT_ERROR && leftvt <= VT_VOID)
- expected_error_num = DISP_E_TYPEMISMATCH;
- else if (leftvt == VT_ERROR && (rightvt == VT_DATE ||
- rightvt == VT_ERROR || rightvt == VT_DECIMAL))
- expected_error_num = DISP_E_TYPEMISMATCH;
- else if (rightvt == VT_DATE || rightvt == VT_ERROR ||
- rightvt == VT_DECIMAL)
- expected_error_num = DISP_E_BADVARTYPE;
- else if (leftvt == VT_ERROR || rightvt == VT_ERROR)
- expected_error_num = DISP_E_TYPEMISMATCH;
-
- ok(hres == DISP_E_BADVARTYPE || hres == E_INVALIDARG ||
- hres == DISP_E_TYPEMISMATCH,
- "VarCat: %d, %d: Expected failure 0x%lX, got 0x%lX\n",
- leftvt, rightvt, expected_error_num, hres);
- }
- else
- {
- ok(V_VT(&result) == resultvt,
- "VarCat: %d, %d: expected vt %d, got vt %d\n",
- leftvt, rightvt, resultvt, V_VT(&result));
- if (hres != S_OK)
- {
- HRESULT expected_error_num;
- if (leftvt == VT_VARIANT && rightvt == VT_ERROR)
- expected_error_num = DISP_E_BADVARTYPE;
- else if (leftvt == VT_VARIANT)
- expected_error_num = DISP_E_TYPEMISMATCH;
- else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY ||
- leftvt == VT_NULL || leftvt == VT_I2 ||
- leftvt == VT_I4 || leftvt == VT_R4 ||
- leftvt == VT_R8 || leftvt == VT_CY ||
- leftvt == VT_DATE || leftvt == VT_BSTR ||
- leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
- leftvt == VT_I1 || leftvt == VT_UI1 ||
- leftvt == VT_UI2 || leftvt == VT_UI4 ||
- leftvt == VT_I8 || leftvt == VT_UI8 ||
- leftvt == VT_INT || leftvt == VT_UINT
- ))
- expected_error_num = DISP_E_TYPEMISMATCH;
- else
- expected_error_num = DISP_E_BADVARTYPE;
- ok(hres == expected_error_num,
- "VarCat: %d, %d: Expected failure 0x%lX, got 0x%lX\n",
- leftvt, rightvt, expected_error_num, hres);
- }
- }
+ /* Determine the error code for the vt combination */
+ ok(hres == expected_error_num,
+ "VarCat: %d, %d returned error, 0x%lX expected 0x%lX.\n",
+ leftvt, rightvt, expected_error_num, hres);
+
+ /* Check types are correct */
+ ok(V_VT(&result) == resultvt,
+ "VarCat: %d, %d: expected vt %d, got vt %d\n",
+ leftvt, rightvt, resultvt, V_VT(&result));
VariantClear(&left);
VariantClear(&right);
@@ -5272,9 +5250,7 @@ static void test_VarCat(void)
V_VT(&left) = VT_ERROR;
V_VT(&right) = VT_BSTR;
hres = VarCat(&left,&right,&result);
- todo_wine {
ok(hres == DISP_E_TYPEMISMATCH, "VarCat should have returned DISP_E_TYPEMISMATCH instead of 0x%08lx\n", hres);
- }
ok(V_VT(&result) == VT_EMPTY,
"VarCat: VT_ERROR concat with VT_BSTR should have returned VT_EMPTY\n");
@@ -5285,9 +5261,7 @@ static void test_VarCat(void)
V_VT(&left) = VT_BSTR;
V_VT(&right) = VT_ERROR;
hres = VarCat(&left,&right,&result);
- todo_wine {
ok(hres == DISP_E_TYPEMISMATCH, "VarCat should have returned DISP_E_TYPEMISMATCH instead of 0x%08lx\n", hres);
- }
ok(V_VT(&result) == VT_EMPTY,
"VarCat: VT_BSTR concat with VT_ERROR should have returned VT_EMPTY\n");
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 2de8550..c3691b6 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -2444,60 +2444,97 @@ VarNumFromParseNum_DecOverflow:
*/
HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
{
- VARTYPE leftvt,rightvt;
+ VARTYPE leftvt,rightvt,resultvt;
HRESULT hres;
static const WCHAR str_true[] = {'T','r','u','e','\0'};
static const WCHAR str_false[] = {'F','a','l','s','e','\0'};
+ static const WCHAR sz_empty[] = {'\0'};
leftvt = V_VT(left);
rightvt = V_VT(right);
TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), out);
- /* Null and Null simply return Null */
+ /* when both left and right are NULL the result is NULL */
if (leftvt == VT_NULL && rightvt == VT_NULL)
{
V_VT(out) = VT_NULL;
return S_OK;
}
- /* VT_ERROR with any other value should return VT_NULL */
- else if (V_VT(left) == VT_ERROR || V_VT(right) == VT_ERROR)
+ hres = S_OK;
+ resultvt = VT_EMPTY;
+
+ /* There are many special case for errors and return types */
+ if (leftvt == VT_VARIANT && (rightvt == VT_ERROR ||
+ rightvt == VT_DATE || rightvt == VT_DECIMAL))
+ hres = DISP_E_TYPEMISMATCH;
+ else if ((leftvt == VT_I2 || leftvt == VT_I4 ||
+ leftvt == VT_R4 || leftvt == VT_R8 ||
+ leftvt == VT_CY || leftvt == VT_BOOL ||
+ leftvt == VT_BSTR || leftvt == VT_I1 ||
+ leftvt == VT_UI1 || leftvt == VT_UI2 ||
+ leftvt == VT_UI4 || leftvt == VT_I8 ||
+ leftvt == VT_UI8 || leftvt == VT_INT ||
+ leftvt == VT_UINT || leftvt == VT_EMPTY ||
+ leftvt == VT_NULL || leftvt == VT_DECIMAL ||
+ leftvt == VT_DATE)
+ &&
+ (rightvt == VT_I2 || rightvt == VT_I4 ||
+ rightvt == VT_R4 || rightvt == VT_R8 ||
+ rightvt == VT_CY || rightvt == VT_BOOL ||
+ rightvt == VT_BSTR || rightvt == VT_I1 ||
+ rightvt == VT_UI1 || rightvt == VT_UI2 ||
+ rightvt == VT_UI4 || rightvt == VT_I8 ||
+ rightvt == VT_UI8 || rightvt == VT_INT ||
+ rightvt == VT_UINT || rightvt == VT_EMPTY ||
+ rightvt == VT_NULL || rightvt == VT_DECIMAL ||
+ rightvt == VT_DATE))
+ resultvt = VT_BSTR;
+ else if (rightvt == VT_ERROR && leftvt < VT_VOID)
+ hres = DISP_E_TYPEMISMATCH;
+ else if (leftvt == VT_ERROR && (rightvt == VT_DATE ||
+ rightvt == VT_ERROR || rightvt == VT_DECIMAL))
+ hres = DISP_E_TYPEMISMATCH;
+ else if (rightvt == VT_DATE || rightvt == VT_ERROR ||
+ rightvt == VT_DECIMAL)
+ hres = DISP_E_BADVARTYPE;
+ else if (leftvt == VT_ERROR || rightvt == VT_ERROR)
+ hres = DISP_E_TYPEMISMATCH;
+ else if (leftvt == VT_VARIANT)
+ hres = DISP_E_TYPEMISMATCH;
+ else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY ||
+ leftvt == VT_NULL || leftvt == VT_I2 ||
+ leftvt == VT_I4 || leftvt == VT_R4 ||
+ leftvt == VT_R8 || leftvt == VT_CY ||
+ leftvt == VT_DATE || leftvt == VT_BSTR ||
+ leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
+ leftvt == VT_I1 || leftvt == VT_UI1 ||
+ leftvt == VT_UI2 || leftvt == VT_UI4 ||
+ leftvt == VT_I8 || leftvt == VT_UI8 ||
+ leftvt == VT_INT || leftvt == VT_UINT))
+ hres = DISP_E_TYPEMISMATCH;
+ else
+ hres = DISP_E_BADVARTYPE;
+
+ /* if resutl type is not S_OK, then no need to go further */
+ if (hres != S_OK)
{
- V_VT(out) = VT_EMPTY;
- return DISP_E_BADVARTYPE;
+ V_VT(out) = resultvt;
+ return hres;
}
-
- /* Concat all type that match conformance test */
- if ((leftvt == VT_I2 || leftvt == VT_I4 ||
- leftvt == VT_R4 || leftvt == VT_R8 ||
- leftvt == VT_CY || leftvt == VT_BOOL ||
- leftvt == VT_BSTR || leftvt == VT_I1 ||
- leftvt == VT_UI1 || leftvt == VT_UI2 ||
- leftvt == VT_UI4 || leftvt == VT_I8 ||
- leftvt == VT_UI8 || leftvt == VT_INT ||
- leftvt == VT_UINT || leftvt == VT_EMPTY ||
- leftvt == VT_NULL || leftvt == VT_DATE ||
- leftvt == VT_DECIMAL)
- &&
- (rightvt == VT_I2 || rightvt == VT_I4 ||
- rightvt == VT_R4 || rightvt == VT_R8 ||
- rightvt == VT_CY || rightvt == VT_BOOL ||
- rightvt == VT_BSTR || rightvt == VT_I1 ||
- rightvt == VT_UI1 || rightvt == VT_UI2 ||
- rightvt == VT_UI4 || rightvt == VT_I8 ||
- rightvt == VT_UI8 || rightvt == VT_INT ||
- rightvt == VT_UINT || rightvt == VT_EMPTY ||
- rightvt == VT_NULL || rightvt == VT_DATE ||
- rightvt == VT_DECIMAL))
+ /* Else proceed with formatting inputs to strings */
+ else
{
VARIANT bstrvar_left, bstrvar_right;
V_VT(out) = VT_BSTR;
+ VariantInit(&bstrvar_left);
+ VariantInit(&bstrvar_right);
+
/* Convert left side variant to string */
if (leftvt != VT_BSTR)
{
- VariantInit(&bstrvar_left);
if (leftvt == VT_BOOL)
{
/* Bools are handled as True/False strings instead of 0/-1 as in MSDN */
@@ -2507,6 +2544,12 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
else
V_BSTR(&bstrvar_left) = SysAllocString(str_false);
}
+ /* Fill with empty string for later concat with right side */
+ else if (leftvt == VT_NULL)
+ {
+ V_VT(&bstrvar_left) = VT_BSTR;
+ V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
+ }
else
{
hres = VariantChangeTypeEx(&bstrvar_left,left,0,0,VT_BSTR);
@@ -2523,8 +2566,8 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
rightvt == VT_UI2 || rightvt == VT_UI4 ||
rightvt == VT_I8 || rightvt == VT_UI8 ||
rightvt == VT_INT || rightvt == VT_UINT))
- return DISP_E_BADVARTYPE;
- return hres;
+ return DISP_E_TYPEMISMATCH;
+ return DISP_E_TYPEMISMATCH;
}
}
}
@@ -2532,7 +2575,6 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
/* convert right side variant to string */
if (rightvt != VT_BSTR)
{
- VariantInit(&bstrvar_right);
if (rightvt == VT_BOOL)
{
/* Bools are handled as True/False strings instead of 0/-1 as in MSDN */
@@ -2542,6 +2584,12 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
else
V_BSTR(&bstrvar_right) = SysAllocString(str_false);
}
+ /* Fill with empty string for later concat with right side */
+ else if (rightvt == VT_NULL)
+ {
+ V_VT(&bstrvar_right) = VT_BSTR;
+ V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
+ }
else
{
hres = VariantChangeTypeEx(&bstrvar_right,right,0,0,VT_BSTR);
@@ -2558,8 +2606,8 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
leftvt == VT_UI2 || leftvt == VT_UI4 ||
leftvt == VT_I8 || leftvt == VT_UI8 ||
leftvt == VT_INT || leftvt == VT_UINT))
- return DISP_E_BADVARTYPE;
- return hres;
+ return DISP_E_TYPEMISMATCH;
+ return DISP_E_TYPEMISMATCH;
}
}
}
@@ -2578,11 +2626,9 @@ HRESULT WINAPI VarCat(LPVARIANT left, LP
VariantClear(&bstrvar_right);
return S_OK;
}
-
- V_VT(out) = VT_EMPTY;
- return S_OK;
}
+
/* Wrapper around VariantChangeTypeEx() which permits changing a
variant with VT_RESERVED flag set. Needed by VarCmp. */
static HRESULT _VarChangeTypeExWrap (VARIANTARG* pvargDest,
--
1.4.0
More information about the wine-patches
mailing list