From: Eric Pouech <epouech@codeweavers.com> Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- dlls/propsys/propvar.c | 57 ++++++++++++++++++++++++++++++++++-- dlls/propsys/tests/propsys.c | 32 -------------------- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index b5f4099f2c6..0ae8caf21ad 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -647,7 +647,6 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p case VT_UI1: { LONGLONG res; - hr = PROPVAR_ConvertNumber(propvarSrc, 8, FALSE, &res); if (SUCCEEDED(hr)) { @@ -1183,10 +1182,62 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 return res; } +static inline size_t vt_weight(unsigned vt) +{ + 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); + default: return 0; + } +} + INT WINAPI VariantCompare(REFVARIANT refvar1, REFVARIANT refvar2) { - FIXME("%s %s: stub!\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); - return 0; + static const unsigned mask_int = VTBIT_I1 | VTBIT_I2 | VTBIT_I4 | VTBIT_I8 | + VTBIT_UI1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8; + static const unsigned mask_float = VTBIT_R4 | VTBIT_R8; + unsigned mask1 = refvar1->vt < 8 * sizeof(mask1) ? (1u << refvar1->vt) : 0; + unsigned mask2 = refvar2->vt < 8 * sizeof(mask2) ? (1u << refvar2->vt) : 0; + unsigned mask = mask1 | mask2; + 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 || (mask1 && mask2 && !(mask & ~(mask_int | mask_float)))) && + VariantToPropVariant(refvar1, &prop_var1) == S_OK) + { + if (VariantToPropVariant(refvar2, &prop_var2) == S_OK) + { + /* as PropVariantCompareEx coerces prop_var2 into prop_var1's type, + * use the largest integer type if both are integers + */ + BOOL can_swap = mask1 && mask2 && !(mask & ~mask_int); + if (!can_swap || vt_weight(prop_var1.vt) >= vt_weight(prop_var2.vt)) + ret = PropVariantCompareEx(&prop_var1, &prop_var2, 0, 0); + else + ret = -PropVariantCompareEx(&prop_var2, &prop_var1, 0, 0); + if (prop_var2.vt == VT_BSTR) SysFreeString(prop_var2.bstrVal); + } + if (prop_var1.vt == VT_BSTR) SysFreeString(prop_var1.bstrVal); + } + return ret < 0 ? -1 : (ret > 0 ? +1 : 0); } HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var) diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 82fdb59c5e9..a814e92d77f 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -1088,98 +1088,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 */ @@ -1190,43 +1167,34 @@ 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); /* float <> int */ res = VariantCompare(&r4_2, &i4_largeneg); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&r4_2, &i4_large); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&i4_large, &r4_2); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i4_largeneg, &r4_2); - todo_wine ok(res == -1, "res=%i\n", res); res = VariantCompare(&r4_21, &i2_2); - todo_wine ok(res == 1, "res=%i\n", res); res = VariantCompare(&i2_2, &r4_21); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196