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