[PATCH 0/5] MR10196: Implement VariantCompare.
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- include/propvarutil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/propvarutil.h b/include/propvarutil.h index 003a4f761a8..dae95152b08 100644 --- a/include/propvarutil.h +++ b/include/propvarutil.h @@ -118,6 +118,7 @@ PSSTDAPI PropVariantToString(REFPROPVARIANT propvarIn, PWSTR ret, UINT cch); PSSTDAPI_(PCWSTR) PropVariantToStringWithDefault(REFPROPVARIANT propvarIn, LPCWSTR pszDefault); PSSTDAPI_(PCWSTR) VariantToStringWithDefault(const VARIANT *pvar, LPCWSTR pszDefault); PSSTDAPI VariantToString(REFVARIANT var, PWSTR ret, UINT cch); +PSSTDAPI_(INT) VariantCompare(REFVARIANT var1, REFVARIANT var2); PSSTDAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/propsys/tests/propsys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 17c9e87d7ef..ffd9f9277fc 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -732,7 +732,10 @@ static void test_PropVariantCompareEx(void) PropVariantInit(&i4_largeneg); PropVariantInit(&i4_2); PropVariantInit(&str_2); + PropVariantInit(&str_02); PropVariantInit(&str_b); + PropVariantInit(&ui4); + PropVariantInit(&ui4_large); empty.vt = VT_EMPTY; null.vt = VT_NULL; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/propsys/propsys.spec | 2 +- dlls/propsys/propvar.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec index 28245452f6f..670f7282041 100644 --- a/dlls/propsys/propsys.spec +++ b/dlls/propsys/propsys.spec @@ -153,7 +153,7 @@ @ stdcall PropVariantToVariant(ptr ptr) @ stub StgDeserializePropVariant @ stub StgSerializePropVariant -@ stub VariantCompare +@ stdcall VariantCompare(ptr ptr) @ stub VariantGetBooleanElem @ stub VariantGetDoubleElem @ stub VariantGetElementCount diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index 7a1ee5fd876..f01ca59af69 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -1164,6 +1164,12 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 return res; } +INT WINAPI VariantCompare(REFVARIANT refvar1, REFVARIANT refvar2) +{ + FIXME("%s %s: stub!\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); + return 0; +} + HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var) { HRESULT hr = S_OK; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/propsys/tests/propsys.c | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index ffd9f9277fc..7517f0f16ba 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -980,6 +980,205 @@ static void test_PropVariantCompareEx(void) SysFreeString(str_b.bstrVal); } +static void test_VariantCompare(void) +{ + VARIANT empty, null, emptyarray, i2_0, i2_2, i4_large, i4_largeneg, i4_2, str_2, str_02, str_b; + VARIANT r4_0, r4_2, r8_0, r8_2; + VARIANT ui4, ui4_large; + INT res; + static const WCHAR str_2W[] = {'2', 0}; + static const WCHAR str_02W[] = {'0', '2', 0}; + static const WCHAR str_bW[] = {'b', 0}; + SAFEARRAY emptysafearray; + + VariantInit(&empty); + VariantInit(&null); + VariantInit(&emptyarray); + VariantInit(&i2_0); + VariantInit(&i2_2); + VariantInit(&i4_large); + VariantInit(&i4_largeneg); + VariantInit(&i4_2); + VariantInit(&ui4); + VariantInit(&ui4_large); + VariantInit(&str_2); + VariantInit(&str_02); + VariantInit(&str_b); + + empty.vt = VT_EMPTY; + null.vt = VT_NULL; + emptyarray.vt = VT_ARRAY | VT_I4; + emptyarray.parray = &emptysafearray; + emptysafearray.cDims = 1; + emptysafearray.fFeatures = FADF_FIXEDSIZE; + emptysafearray.cbElements = 4; + emptysafearray.cLocks = 0; + emptysafearray.pvData = NULL; + emptysafearray.rgsabound[0].cElements = 0; + emptysafearray.rgsabound[0].lLbound = 0; + i2_0.vt = VT_I2; + i2_0.iVal = 0; + i2_2.vt = VT_I2; + i2_2.iVal = 2; + i4_large.vt = VT_I4; + i4_large.lVal = 65536; + i4_largeneg.vt = VT_I4; + i4_largeneg.lVal = -65536; + i4_2.vt = VT_I4; + i4_2.lVal = 2; + ui4.vt = VT_UI4; + ui4.ulVal = 2; + ui4_large.vt = VT_UI4; + ui4_large.ulVal = 65536; + str_2.vt = VT_BSTR; + str_2.bstrVal = SysAllocString(str_2W); + str_02.vt = VT_BSTR; + str_02.bstrVal = SysAllocString(str_02W); + str_b.vt = VT_BSTR; + str_b.bstrVal = SysAllocString(str_bW); + r4_0.vt = VT_R4; + r4_0.fltVal = 0.0f; + r4_2.vt = VT_R4; + r4_2.fltVal = 2.0f; + r8_0.vt = VT_R8; + r8_0.dblVal = 0.0; + r8_2.vt = VT_R8; + r8_2.dblVal = 2.0; + + /* don't test NULL values, this segfaults on native */ + + res = VariantCompare(&empty, &empty); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&empty, &null); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&null, &emptyarray); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&empty, &i2_0); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&null, &i2_0); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&i2_0, &null); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i2_0, &empty); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i2_2, &i2_0); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i2_0, &i2_2); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&ui4, &ui4_large); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&ui4_large, &ui4); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i2_0, &i4_large); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare( &i4_large, &i2_0); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i2_0, &i4_largeneg); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i4_largeneg, &i2_0); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&i4_large, &i2_0); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i4_largeneg, &i2_0); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&i2_2, &i4_2); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&i2_2, &str_2); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&i2_2, &str_02); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&str_2, &i2_2); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&str_02, &i2_2); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&str_02, &str_2); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&str_02, &str_b); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&str_2, &str_02); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&i4_large, &str_b); + todo_wine + ok(res == -1, "res=%i\n", res); + + /* VT_R4/VT_R8 */ + res = VariantCompare(&r4_0, &r8_0); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&r4_0, &r4_0); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&r4_0, &r4_2); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&r4_2, &r4_0); + todo_wine + ok(res == 1, "res=%i\n", res); + + res = VariantCompare(&r8_0, &r8_0); + ok(res == 0, "res=%i\n", res); + + res = VariantCompare(&r8_0, &r8_2); + todo_wine + ok(res == -1, "res=%i\n", res); + + res = VariantCompare(&r8_2, &r8_0); + todo_wine + ok(res == 1, "res=%i\n", res); + + SysFreeString(str_2.bstrVal); + SysFreeString(str_02.bstrVal); + SysFreeString(str_b.bstrVal); +} + static void test_intconversions(void) { PROPVARIANT propvar; @@ -3249,6 +3448,7 @@ START_TEST(propsys) test_VariantToStringWithDefault(); test_VariantToString(); test_VariantToPropVariant(); + test_VariantCompare(); test_PropVariantToVariant(); test_PropVariantGetStringElem(); test_PropVariantToFileTime(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/propsys/propvar.c | 62 ++++++++++++++++++++++++++++++++++-- dlls/propsys/tests/propsys.c | 27 ---------------- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index f01ca59af69..b61f65b4512 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -1164,12 +1164,70 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 return res; } -INT WINAPI VariantCompare(REFVARIANT refvar1, REFVARIANT refvar2) +static inline size_t data_size(unsigned vt) { - FIXME("%s %s: stub!\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); + switch (vt) + { + case VT_I1: + case VT_UI1: return sizeof(BYTE); + case VT_I2: + case VT_UI2: return sizeof(SHORT); + case VT_INT: + case VT_UINT: + case VT_I4: + case VT_UI4: return sizeof(LONG); + case VT_I8: + case VT_UI8: return sizeof(LONGLONG); + case VT_R4: return sizeof(float); + case VT_R8: return sizeof(double); + case VT_DATE: return sizeof(DATE); + case VT_BOOL: return sizeof(VARIANT_BOOL); + case VT_DISPATCH: + case VT_UNKNOWN: + case VT_BSTR: return sizeof(void*); + case VT_CY: return sizeof(CY); + case VT_ERROR: return sizeof(SCODE); + default: WARN("Unexpected variant type %u\n", vt); + } return 0; } +INT WINAPI VariantCompare(REFVARIANT refvar1, REFVARIANT refvar2) +{ + static const unsigned mask_sint = VTBIT_I1 | VTBIT_I2 | VTBIT_I4 | VTBIT_I8; + static const unsigned mask_uint = VTBIT_UI1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8; + static const unsigned mask_int = mask_sint | mask_uint; + static const unsigned mask_float = VTBIT_R4 | VTBIT_R8; + unsigned mask = (1u << refvar1->vt) | (1 << refvar2->vt); + PROPVARIANT prop_var1, prop_var2; + BOOL tst1 = refvar1->vt == VT_EMPTY || refvar1->vt == VT_NULL; + BOOL tst2 = refvar2->vt == VT_EMPTY || refvar2->vt == VT_NULL; + int ret; + + TRACE("%s %s!\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); + + if (tst1 && tst2) return 0; + if (tst1) return -1; + if (tst2) return +1; + + ret = refvar1->vt - refvar2->vt; + if ((ret == 0 || !(mask & ~mask_int) || !(mask & ~mask_float)) && + VariantToPropVariant(refvar1, &prop_var1) == S_OK && + VariantToPropVariant(refvar2, &prop_var2) == S_OK) + { + /* as PropVariantCompareEx coerces prop_var2 into prop_var1's type, + * use the largest variant as first argument + */ + if (data_size(prop_var1.vt) >= data_size(prop_var2.vt)) + ret = PropVariantCompareEx(&prop_var1, &prop_var2, 0, 0); + else + ret = -PropVariantCompareEx(&prop_var2, &prop_var1, 0, 0); + if (prop_var1.vt == VT_BSTR) SysFreeString(prop_var1.bstrVal); + if (prop_var2.vt == VT_BSTR) SysFreeString(prop_var2.bstrVal); + } + return ret < 0 ? -1 : (ret > 0 ? +1 : 0); +} + HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var) { HRESULT hr = S_OK; diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 7517f0f16ba..677174a6d57 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -1054,98 +1054,75 @@ static void test_VariantCompare(void) ok(res == 0, "res=%i\n", res); res = VariantCompare(&null, &emptyarray); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&empty, &i2_0); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&null, &i2_0); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&i2_0, &null); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_0, &empty); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_2, &i2_0); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_0, &i2_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&ui4, &ui4_large); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&ui4_large, &ui4); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_0, &i4_large); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare( &i4_large, &i2_0); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_0, &i4_largeneg); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i4_largeneg, &i2_0); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&i4_large, &i2_0); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i4_largeneg, &i2_0); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&i2_2, &i4_2); ok(res == 0, "res=%i\n", res); res = VariantCompare(&i2_2, &str_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&i2_2, &str_02); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&str_2, &i2_2); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&str_02, &i2_2); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&str_02, &str_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&str_02, &str_b); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&str_2, &str_02); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i4_large, &str_b); - todo_wine ok(res == -1, "res=%i\n", res); /* VT_R4/VT_R8 */ @@ -1156,22 +1133,18 @@ static void test_VariantCompare(void) ok(res == 0, "res=%i\n", res); res = VariantCompare(&r4_0, &r4_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&r4_2, &r4_0); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&r8_0, &r8_0); ok(res == 0, "res=%i\n", res); res = VariantCompare(&r8_0, &r8_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&r8_2, &r8_0); - todo_wine ok(res == 1, "res=%i\n", res); SysFreeString(str_2.bstrVal); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
Please add tests for comparing integers and floats (and fix the implementation). Here's an example of a test that currently fails: ```c res = VariantCompare(&r4_2, &i2_2); ok(res == 0, "res=%i\n", res); ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10196#note_130595
participants (3)
-
Eric Pouech -
eric pouech (@epo) -
Piotr Caban (@piotr)