[PATCH v3 0/4] MR10196: Implement VariantCompare.
-- v3: propsys: Implement VariantCompare(). propsys/tests: Add tests for VariantCompare(). propsys: Add stub for VariantCompare(). include: Add definition for VariantCompare in propvarutil.h https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
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/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 | 423 +++++++++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 17c9e87d7ef..f5dc843ca0a 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -34,6 +34,8 @@ #include "strsafe.h" #include "propkey.h" #include "wine/test.h" +#include "intsafe.h" +#include "float.h" DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); DEFINE_GUID(dummy_guid, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe); @@ -977,6 +979,426 @@ static void test_PropVariantCompareEx(void) SysFreeString(str_b.bstrVal); } +static void test_VariantCompare(void) +{ + VARIANT emptyarray; + VARIANT var1, var2; + INT res; + BSTR bstr_def = SysAllocString(L"66"); /* must match C_DEF value below */ + BSTR bstr_0def = SysAllocString(L"066"); + BSTR bstr_bbb = SysAllocString(L"bbb"); + SAFEARRAY emptysafearray; + + ok(bstr_def && bstr_0def && bstr_bbb, "Allocation failed\n"); + VariantInit(&emptyarray); + + 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; + + VariantInit(&var1); + VariantInit(&var2); +#define VARINIT(var,vt,val) V_VT(var) = VT_ ## vt; V_ ## vt(var) = (val) +#define VARCMP_(pvar1,pvar2,exp) res = VariantCompare(pvar1, pvar2); \ + todo_wine_if(exp) ok(res == (exp), "res=%d while expecting %d\n", res, (exp)) +#define VARCMP(vt1,val1,vt2,val2,exp) \ + { VARINIT(&var1,vt1,(val1)); \ + VARINIT(&var2,vt2,(val2)); \ + VARCMP_(&var1,&var2,(exp)); } + + /* default values, that should be usable for all integral & float types */ +#define C_DEF (2*33) +#define C_SBLW (-33) +#define C_UBLW (33) +#define C_ABV (3*33) + + var1.vt = VT_EMPTY; var2.vt = VT_EMPTY; + VARCMP_(&var1, &var2,0); + var1.vt = VT_EMPTY; var2.vt = VT_NULL; + VARCMP_(&var1, &var2,0); + var1.vt = VT_NULL; var2.vt = VT_EMPTY; + VARCMP_(&var1, &var2,0); + var1.vt = VT_NULL; var2.vt = VT_NULL; + VARCMP_(&var1, &var2,0); + + VARINIT(&var2,I4,C_DEF); + var1.vt = VT_EMPTY; + VARCMP_(&var1, &var2,-1); + var1.vt = VT_NULL; + VARCMP_(&var1, &var2,-1); + VARCMP_(&emptyarray,&var2,0); + + VARINIT(&var1,I4,C_DEF); + var2.vt = VT_EMPTY; + VARCMP_(&var1, &var2,1); + var2.vt = VT_NULL; + VARCMP_(&var1, &var2,1); + VARCMP_(&var1,&emptyarray,0); + + /* regular values */ + VARCMP(I1,C_DEF,I1,C_DEF,0); + VARCMP(I1,C_DEF,I1,C_SBLW,1); + VARCMP(I1,C_SBLW,I1,C_DEF,-1); + VARCMP(I1,C_DEF,I1,C_ABV,-1); + VARCMP(I1,C_ABV,I1,C_DEF,1); + + /* default + limits / limits */ + VARCMP(I1,C_DEF,I1,INT8_MIN,1); + VARCMP(I1,C_DEF,I1,INT8_MAX,-1); + VARCMP(I1,INT8_MIN,I1,C_DEF,-1); + VARCMP(I1,INT8_MAX,I1,C_DEF,1); + + VARCMP(I1,INT8_MIN,I1,INT8_MAX,-1); + VARCMP(I1,INT8_MAX,I1,INT8_MIN,1); + + /* limit / beyond limit in larger integer */ + VARCMP(I1,INT8_MIN,I2,INT8_MIN-1,0); + VARCMP(I1,INT8_MIN,I4,INT8_MIN-1,0); + VARCMP(I1,INT8_MIN,I8,INT8_MIN-1,0); + VARCMP(I1,INT8_MIN,R4,INT8_MIN-1,0); + VARCMP(I1,INT8_MIN,R8,INT8_MIN-1,0); + VARCMP(I2,INT8_MIN-1,I1,INT8_MIN,0); + VARCMP(I1,INT8_MAX,I2,INT8_MAX+1,0); + VARCMP(I1,INT8_MAX,I4,INT8_MAX+1,0); + VARCMP(I1,INT8_MAX,I8,INT8_MAX+1,0); + VARCMP(I1,INT8_MAX,R4,INT8_MAX+1,0); + VARCMP(I1,INT8_MAX,R8,INT8_MAX+1,0); + VARCMP(I2,INT8_MAX+1,I1,INT8_MAX,0); + + /* regular values */ + VARCMP(I2,C_DEF,I2,C_DEF,0); + VARCMP(I2,C_DEF,I2,C_SBLW,1); + VARCMP(I2,C_SBLW,I2,C_DEF,-1); + VARCMP(I2,C_DEF,I2,C_ABV,-1); + VARCMP(I2,C_ABV,I2,C_DEF,1); + + /* default + limits / limits */ + VARCMP(I2,C_DEF,I2,INT16_MIN,1); + VARCMP(I2,C_DEF,I2,INT16_MAX,-1); + VARCMP(I2,INT16_MIN,I2,C_DEF,-1); + VARCMP(I2,INT16_MAX,I2,C_DEF,1); + + VARCMP(I2,INT16_MIN,I2,INT16_MAX,-1); + VARCMP(I2,INT16_MAX,I2,INT16_MIN,1); + + /* limit / beyond limit in larger integer */ + VARCMP(I2,INT16_MIN,I4,INT16_MIN-1,1); + VARCMP(I4,INT16_MIN-1,I2,INT16_MIN,-1); + + VARCMP(I2,INT16_MAX,I4,INT16_MAX+1,-1); + VARCMP(I4,INT16_MAX+1,I2,INT16_MAX,1); + + /* regular values */ + VARCMP(I4,C_DEF,I4,C_DEF,0); + VARCMP(I4,C_DEF,I4,C_SBLW,1); + VARCMP(I4,C_SBLW,I4,C_DEF,-1); + VARCMP(I4,C_DEF,I4,C_ABV,-1); + VARCMP(I4,C_ABV,I4,C_DEF,1); + + /* default + limits / limits */ + VARCMP(I4,C_DEF,I4,INT32_MIN,1); + VARCMP(I4,C_DEF,I4,INT32_MAX,-1); + VARCMP(I4,INT32_MIN,I4,C_DEF,-1); + VARCMP(I4,INT32_MAX,I4,C_DEF,1); + + VARCMP(I4,INT32_MIN,I4,INT32_MAX,-1); + VARCMP(I4,INT32_MAX,I4,INT32_MIN,1); + + /* limit / beyond limit in larger integer */ + VARCMP(I4,INT32_MIN,I8,(LONG64)INT32_MIN-1,1); + VARCMP(I8,(LONG64)INT32_MIN-1,I4,INT32_MIN,-1); + + VARCMP(I4,INT32_MAX,I8,(LONG64)INT32_MAX+1,-1); + VARCMP(I8,(LONG64)INT32_MAX+1,I4,INT32_MAX,1); + + /* regular values */ + VARCMP(I8,C_DEF,I8,C_DEF,0); + VARCMP(I8,C_DEF,I8,C_SBLW,1); + VARCMP(I8,C_SBLW,I8,C_DEF,-1); + VARCMP(I8,C_DEF,I8,C_ABV,-1); + VARCMP(I8,C_ABV,I8,C_DEF,1); + + /* default + limits / limits */ + VARCMP(I8,C_DEF,I8,INT64_MIN,1); + VARCMP(I8,C_DEF,I8,INT64_MAX,-1); + VARCMP(I8,INT64_MIN,I8,C_DEF,-1); + VARCMP(I8,INT64_MAX,I8,C_DEF,1); + + VARCMP(I8,INT64_MIN,I8,INT64_MAX,-1); + VARCMP(I8,INT64_MAX,I8,INT64_MIN,1); + + /* regular values */ + VARCMP(R4,C_DEF,R4,C_DEF,0); + VARCMP(R4,C_DEF,R4,C_SBLW,1); + VARCMP(R4,C_SBLW,R4,C_DEF,-1); + VARCMP(R4,C_DEF,R4,C_ABV,-1); + VARCMP(R4,C_ABV,R4,C_DEF,1); + + /* default + limits / limits */ + VARCMP(R4,C_DEF,R4,-FLT_MAX,1); + VARCMP(R4,C_DEF,R4,FLT_MAX,-1); + VARCMP(R4,-FLT_MAX,R4,C_DEF,-1); + VARCMP(R4,FLT_MAX,R4,C_DEF,1); + + VARCMP(R4,-FLT_MAX,R4,FLT_MAX,-1); + VARCMP(R4,FLT_MAX,R4,-FLT_MAX,1); + + /* limit / beyond limit in larger float */ + VARCMP(R4,-FLT_MAX,R8,-2.*FLT_MAX,1); + VARCMP(R8,-2.*FLT_MAX,R4,-FLT_MAX,-1); + + VARCMP(R4,FLT_MAX,R8,2.*FLT_MAX,-1); + VARCMP(R8,2.*FLT_MAX,R4,FLT_MAX,1); + + /* regular values */ + VARCMP(R8,C_DEF,R8,C_DEF,0); + VARCMP(R8,C_DEF,R8,C_SBLW,1); + VARCMP(R8,C_SBLW,R8,C_DEF,-1); + VARCMP(R8,C_DEF,R8,C_ABV,-1); + VARCMP(R8,C_ABV,R8,C_DEF,1); + + /* default + limits / limits */ + VARCMP(R8,C_DEF,R8,-DBL_MAX,1); + VARCMP(R8,C_DEF,R8,DBL_MAX,-1); + VARCMP(R8,-DBL_MAX,R8,C_DEF,-1); + VARCMP(R8,DBL_MAX,R8,C_DEF,1); + + VARCMP(R8,-DBL_MAX,R8,DBL_MAX,-1); + VARCMP(R8,DBL_MAX,R8,-DBL_MAX,1); + + /* some more int <> float tests */ + VARCMP(I4,C_DEF,R4,C_DEF,0); + VARCMP(I4,C_DEF,R4,C_SBLW,1); + VARCMP(I4,C_SBLW,R4,C_DEF,-1); + VARCMP(I4,C_DEF,R4,C_ABV,-1); + VARCMP(I4,C_ABV,R4,C_DEF,1); + + VARCMP(R4,C_DEF,I4,C_DEF,0); + VARCMP(R4,C_DEF,I4,C_SBLW,1); + VARCMP(R4,C_SBLW,I4,C_DEF,-1); + VARCMP(R4,C_DEF,I4,C_ABV,-1); + VARCMP(I4,C_ABV,R4,C_DEF,1); + + VARCMP(I4,C_DEF,R8,C_DEF,0); + VARCMP(I4,C_DEF,R8,C_SBLW,1); + VARCMP(I4,C_SBLW,R8,C_DEF,-1); + VARCMP(I4,C_DEF,R8,C_ABV,-1); + VARCMP(I4,C_ABV,R8,C_DEF,1); + + VARCMP(R8,C_DEF,I4,C_DEF,0); + VARCMP(R8,C_DEF,I4,C_SBLW,1); + VARCMP(R8,C_SBLW,I4,C_DEF,-1); + VARCMP(R8,C_DEF,I4,C_ABV,-1); + VARCMP(R8,C_ABV,I4,C_DEF,1); + + VARCMP(I4,C_DEF,R4,C_DEF+.1f,-1); + VARCMP(R4,C_DEF+.1f,I4,C_DEF,1); + VARCMP(I4,C_DEF,R8,C_DEF+.1,-1); + VARCMP(R8,C_DEF+.1,I4,C_DEF,1); + + /* regular values */ + VARCMP(UI1,C_DEF,UI1,C_DEF,0); + VARCMP(UI1,C_DEF,UI1,C_UBLW,1); + VARCMP(UI1,C_UBLW,UI1,C_DEF,-1); + VARCMP(UI1,C_DEF,UI1,C_ABV,-1); + VARCMP(UI1,C_ABV,UI1,C_DEF,1); + + /* default + limits / limits */ + VARCMP(UI1,C_DEF,UI1,0,1); + VARCMP(UI1,C_DEF,UI1,UINT8_MAX,-1); + VARCMP(UI1,0,UI1,C_DEF,-1); + VARCMP(UI1,UINT8_MAX,UI1,C_DEF,1); + + VARCMP(UI1,0,UI1,UINT8_MAX,-1); + VARCMP(UI1,UINT8_MAX,UI1,0,1); + + /* limit / beyond limit in larger integer */ + VARCMP(UI1,0,R4,-1,1); + VARCMP(UI1,0,R8,-1,1); + VARCMP(UI1,UINT8_MAX,UI2,UINT8_MAX+1,-1); + VARCMP(UI1,UINT8_MAX,UI4,UINT8_MAX+1,-1); + VARCMP(UI1,UINT8_MAX,UI8,UINT8_MAX+1,-1); + VARCMP(UI1,UINT8_MAX,R4,UINT8_MAX+1,-1); + VARCMP(UI1,UINT8_MAX,R8,UINT8_MAX+1,-1); + VARCMP(UI2,UINT8_MAX+1,UI1,UINT8_MAX,1); + + /* regular values */ + VARCMP(UI2,C_DEF,UI2,C_DEF,0); + VARCMP(UI2,C_DEF,UI2,C_UBLW,1); + VARCMP(UI2,C_UBLW,UI2,C_DEF,-1); + VARCMP(UI2,C_DEF,UI2,C_ABV,-1); + VARCMP(UI2,C_ABV,UI2,C_DEF,1); + + /* default + limits / limits */ + VARCMP(UI2,C_DEF,UI2,0,1); + VARCMP(UI2,C_DEF,UI2,UINT16_MAX,-1); + VARCMP(UI2,0,UI2,C_DEF,-1); + VARCMP(UI2,UINT16_MAX,UI2,C_DEF,1); + + VARCMP(UI2,0,UI2,UINT16_MAX,-1); + VARCMP(UI2,UINT16_MAX,UI2,0,1); + + /* limit / beyond limit in larger integer */ + VARCMP(UI2,UINT16_MAX,UI4,UINT16_MAX+1,-1); + VARCMP(UI4,UINT16_MAX+1,UI2,UINT16_MAX,1); + + /* regular values */ + VARCMP(UI4,C_DEF,UI4,C_DEF,0); + VARCMP(UI4,C_DEF,UI4,C_UBLW,1); + VARCMP(UI4,C_UBLW,UI4,C_DEF,-1); + VARCMP(UI4,C_DEF,UI4,C_ABV,-1); + VARCMP(UI4,C_ABV,UI4,C_DEF,1); + + /* default + limits / limits */ + VARCMP(UI4,C_DEF,UI4,0,1); + VARCMP(UI4,C_DEF,UI4,UINT32_MAX,-1); + VARCMP(UI4,0,UI4,C_DEF,-1); + VARCMP(UI4,UINT32_MAX,UI4,C_DEF,1); + + VARCMP(UI4,0,UI4,UINT32_MAX,-1); + VARCMP(UI4,UINT32_MAX,UI4,0,1); + + /* limit / beyond limit in larger integer */ + VARCMP(UI4,UINT32_MAX,UI8,(LONG64)UINT32_MAX+1,-1); + VARCMP(UI8,(LONG64)UINT32_MAX+1,UI4,UINT32_MAX,1); + + /* regular values */ + VARCMP(UI8,C_DEF,UI8,C_DEF,0); + VARCMP(UI8,C_DEF,UI8,C_UBLW,1); + VARCMP(UI8,C_UBLW,UI8,C_DEF,-1); + VARCMP(UI8,C_DEF,UI8,C_ABV,-1); + VARCMP(UI8,C_ABV,UI8,C_DEF,1); + + /* default + limits / limits */ + VARCMP(UI8,C_DEF,UI8,0,1); + VARCMP(UI8,C_DEF,UI8,UINT64_MAX,-1); + VARCMP(UI8,0,UI8,C_DEF,-1); + VARCMP(UI8,UINT64_MAX,UI8,C_DEF,1); + + VARCMP(UI8,0,UI8,UINT64_MAX,-1); + VARCMP(UI8,UINT64_MAX,UI8,0,1); + + /* regular values */ + VARCMP(R4,C_DEF,R4,C_DEF,0); + VARCMP(R4,C_DEF,R4,C_UBLW,1); + VARCMP(R4,C_UBLW,R4,C_DEF,-1); + VARCMP(R4,C_DEF,R4,C_ABV,-1); + VARCMP(R4,C_ABV,R4,C_DEF,1); + + /* default + limits / limits */ + VARCMP(R4,C_DEF,R4,-FLT_MAX,1); + VARCMP(R4,C_DEF,R4,FLT_MAX,-1); + VARCMP(R4,-FLT_MAX,R4,C_DEF,-1); + VARCMP(R4,FLT_MAX,R4,C_DEF,1); + + VARCMP(R4,-FLT_MAX,R4,FLT_MAX,-1); + VARCMP(R4,FLT_MAX,R4,-FLT_MAX,1); + + /* limit / beyond limit in larger float */ + VARCMP(R4,-FLT_MAX,R8,-2.*FLT_MAX,1); + VARCMP(R8,-2.*FLT_MAX,R4,-FLT_MAX,-1); + + VARCMP(R4,FLT_MAX,R8,2.*FLT_MAX,-1); + VARCMP(R8,2.*FLT_MAX,R4,FLT_MAX,1); + + /* regular values */ + VARCMP(R8,C_DEF,R8,C_DEF,0); + VARCMP(R8,C_DEF,R8,C_UBLW,1); + VARCMP(R8,C_UBLW,R8,C_DEF,-1); + VARCMP(R8,C_DEF,R8,C_ABV,-1); + VARCMP(R8,C_ABV,R8,C_DEF,1); + + /* default + limits / limits */ + VARCMP(R8,C_DEF,R8,-DBL_MAX,1); + VARCMP(R8,C_DEF,R8,DBL_MAX,-1); + VARCMP(R8,-DBL_MAX,R8,C_DEF,-1); + VARCMP(R8,DBL_MAX,R8,C_DEF,1); + + VARCMP(R8,-DBL_MAX,R8,DBL_MAX,-1); + VARCMP(R8,DBL_MAX,R8,-DBL_MAX,1); + + /* some more int <> float tests */ + VARCMP(UI4,C_DEF,R4,C_DEF,0); + VARCMP(UI4,C_DEF,R4,C_UBLW,0); + VARCMP(UI4,C_UBLW,R4,C_DEF,0); + VARCMP(UI4,C_DEF,R4,C_ABV,0); + VARCMP(UI4,C_ABV,R4,C_DEF,0); + + VARCMP(R4,C_DEF,UI4,C_DEF,0); + VARCMP(R4,C_DEF,UI4,C_UBLW,0); + VARCMP(R4,C_UBLW,UI4,C_DEF,0); + VARCMP(R4,C_DEF,UI4,C_ABV,0); + VARCMP(R4,C_ABV,UI4,C_DEF,0); + /* UI2 and UI8 return 0 */ + + VARCMP(UI4,C_DEF,R8,C_DEF,0); + VARCMP(UI4,C_DEF,R8,C_UBLW,1); + VARCMP(UI4,C_UBLW,R8,C_DEF,-1); + VARCMP(UI4,C_DEF,R8,C_ABV,-1); + VARCMP(UI4,C_ABV,R8,C_DEF,1); + + VARCMP(R8,C_DEF,UI4,C_DEF,0); + VARCMP(R8,C_DEF,UI4,C_UBLW,1); + VARCMP(R8,C_UBLW,UI4,C_DEF,-1); + VARCMP(R8,C_DEF,UI4,C_ABV,-1); + VARCMP(R8,C_ABV,UI4,C_DEF,1); + + VARCMP(UI4,C_DEF,R4,C_DEF+.1f,0); + VARCMP(R4,C_DEF+.1f,UI4,C_DEF,0); + VARCMP(UI4,C_DEF,R8,C_DEF+.1,-1); + VARCMP(R8,C_DEF+.1,UI4,C_DEF,1); + + /* signed / unsigned comparisons */ + VARCMP(I1,C_SBLW,UI1,C_DEF,0); + VARCMP(UI1,C_DEF,I1,C_SBLW,0); + VARCMP(UI1,C_DEF,I2,C_SBLW,1); + VARCMP(UI1,C_DEF,I4,C_SBLW,1); + VARCMP(UI1,C_DEF,I8,C_SBLW,1); + VARCMP(UI1,C_DEF,R4,C_SBLW,1); + VARCMP(UI1,C_DEF,R8,C_SBLW,1); + VARCMP(UI1,C_DEF,I1,C_UBLW,0); + + VARCMP(I8,INT64_MAX,UI8,UINT64_MAX,-1); + VARCMP(I8,INT64_MIN,UI8,0,-1); + VARCMP(I8,INT64_MIN,UI8,(ULONG64)INT_MAX+1,-1); + VARCMP(UI8,(ULONG64)INT_MAX+1,I8,INT64_MIN,1); + VARCMP(UI8,UINT64_MAX,I8,INT64_MAX,1); + VARCMP(UI8,0,I8,INT64_MIN,1); + + /* string string comparisons */ + VARCMP(BSTR,bstr_def,BSTR,bstr_0def,1); + VARCMP(BSTR,bstr_0def,BSTR,bstr_def,-1); + VARCMP(BSTR,bstr_def,BSTR,bstr_bbb,-1); + VARCMP(BSTR,bstr_bbb,BSTR,bstr_def,1); + + /* integer / string comparisons */ + VARCMP(I2,C_DEF,BSTR,bstr_def,-1); + VARCMP(BSTR,bstr_def,I2,C_DEF,1); + VARCMP(I2,C_DEF,BSTR,bstr_0def,-1); + VARCMP(BSTR,bstr_0def,I2,C_DEF,1); + VARCMP(I2,C_DEF,BSTR,bstr_bbb,-1); + VARCMP(BSTR,bstr_bbb,I2,C_DEF,1); + +#undef VARCMP +#undef VARCMP_ +#undef VARINIT + +#undef C_DEF +#undef C_SBLW +#undef C_UBLW +#undef C_ABV + + SysFreeString(bstr_def); + SysFreeString(bstr_0def); + SysFreeString(bstr_bbb); +} + static void test_intconversions(void) { PROPVARIANT propvar; @@ -3246,6 +3668,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 | 97 +++++++++++++++++++++++++++++++++++- dlls/propsys/tests/propsys.c | 2 +- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index f01ca59af69..a1de99b01f5 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -31,6 +31,7 @@ #include "shlobj.h" #include "propvarutil.h" #include "strsafe.h" +#include "intsafe.h" #include "wine/debug.h" @@ -1164,9 +1165,103 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 return res; } +static inline BOOL is_variant_empty(REFVARIANT var) +{ + return var->vt == VT_EMPTY || var->vt == VT_NULL; +} + +static BOOL convert_variant(REFVARIANT src, VARIANT *dest) +{ + switch (src->vt) + { + case VT_I1: dest->vt = VT_I8; V_I8(dest) = V_I1(src); break; + case VT_I2: dest->vt = VT_I8; V_I8(dest) = V_I2(src); break; + case VT_I4: dest->vt = VT_I8; V_I8(dest) = V_I4(src); break; + case VT_I8: dest->vt = VT_I8; V_I8(dest) = V_I8(src); break; + + case VT_UI1: dest->vt = VT_UI8; V_UI8(dest) = V_UI1(src); break; + case VT_UI2: dest->vt = VT_UI8; V_UI8(dest) = V_UI2(src); break; + case VT_UI4: dest->vt = VT_UI8; V_UI8(dest) = V_UI4(src); break; + case VT_UI8: dest->vt = VT_UI8; V_UI8(dest) = V_UI8(src); break; + + case VT_R4: dest->vt = VT_R8; V_R8(dest) = V_R4(src); break; + case VT_R8: dest->vt = VT_R8; V_R8(dest) = V_R8(src); break; + + default: return FALSE; + } + return TRUE; + +} + INT WINAPI VariantCompare(REFVARIANT refvar1, REFVARIANT refvar2) { - FIXME("%s %s: stub!\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); + VARIANT v1, v2; + BOOL convert1, convert2; + + TRACE("(%s %s)\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); + + if (is_variant_empty(refvar1)) + return is_variant_empty(refvar2) ? 0 : -1; + if (is_variant_empty(refvar2)) return 1; + + /* dunno why... */ + if (refvar1->vt != refvar2->vt && (refvar1->vt == VT_I1 || refvar2->vt == VT_I1)) + return 0; + /* dunno why these two return always 0 (but UI1 doesn't, nor R8)... */ + if ((refvar1->vt == VT_UI2 || refvar1->vt == VT_UI4 || refvar1->vt == VT_UI8) && refvar2->vt == VT_R4) + return 0; + if (refvar1->vt == VT_R4 && (refvar2->vt == VT_UI2 || refvar2->vt == VT_UI4 || refvar2->vt == VT_UI8)) + return 0; + + convert1 = convert_variant(refvar1, &v1); + convert2 = convert_variant(refvar2, &v2); + if (convert1 && convert2) /* handle numeric comparisons */ + { +#define SPACESHIP_CMP(a, b) ((a) == (b) ? 0 : ((a) < (b) ? -1 : 1)) + if (v1.vt == VT_I8 && v2.vt == VT_I8) + return SPACESHIP_CMP(V_I8(&v1), V_I8(&v2)); + if (v1.vt == VT_UI8 && v2.vt == VT_UI8) + return SPACESHIP_CMP(V_UI8(&v1), V_UI8(&v2)); + if (v1.vt == VT_R8 && v2.vt == VT_R8) + return SPACESHIP_CMP(V_R8(&v1), V_R8(&v2)); + if (v1.vt == VT_I8 && v2.vt == VT_UI8) + { + if (V_I8(&v1) < 0) return -1; + if (V_UI8(&v2) > (ULONG64)INT64_MAX) return -1; + return SPACESHIP_CMP((ULONG64)V_I8(&v1), V_UI8(&v2)); + } + if (v1.vt == VT_UI8 && v2.vt == VT_I8) + { + if (V_I8(&v2) < 0) return 1; + if (V_UI8(&v1) > (ULONG64)INT64_MAX) return 1; + return SPACESHIP_CMP(V_UI8(&v1), (ULONG64)V_I8(&v2)); + } + if (v1.vt == VT_R8 && v2.vt == VT_I8) + return SPACESHIP_CMP(V_R8(&v1), (double)V_I8(&v2)); + if (v1.vt == VT_R8 && v2.vt == VT_UI8) + return SPACESHIP_CMP(V_R8(&v1), (double)V_UI8(&v2)); + if (v1.vt == VT_I8 && v2.vt == VT_R8) + return SPACESHIP_CMP((double)V_I8(&v1), V_R8(&v2)); + if (v1.vt == VT_UI8 && v2.vt == VT_R8) + return SPACESHIP_CMP((double)V_UI8(&v1), V_R8(&v2)); + /* should not be reached */ +#undef SPACESHIP_CMP + } + if (refvar1->vt == refvar2->vt) + { + if (refvar1->vt == VT_BSTR) + return lstrcmpW(V_BSTR(refvar1), V_BSTR(refvar2)); + } + else + { + /* this doesn't make a lot of sense either */ + if (convert1 && refvar2->vt == VT_BSTR) + return -1; + if (refvar1->vt == VT_BSTR && convert2) + return 1; + } + /* potentially other cases here */ + FIXME("Case not handled %s <=> %s\n", debugstr_variant(refvar1), debugstr_variant(refvar2)); return 0; } diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index f5dc843ca0a..fa21349bb8b 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -1006,7 +1006,7 @@ static void test_VariantCompare(void) VariantInit(&var2); #define VARINIT(var,vt,val) V_VT(var) = VT_ ## vt; V_ ## vt(var) = (val) #define VARCMP_(pvar1,pvar2,exp) res = VariantCompare(pvar1, pvar2); \ - todo_wine_if(exp) ok(res == (exp), "res=%d while expecting %d\n", res, (exp)) + ok(res == (exp), "res=%d while expecting %d\n", res, (exp)) #define VARCMP(vt1,val1,vt2,val2,exp) \ { VARINIT(&var1,vt1,(val1)); \ VARINIT(&var2,vt2,(val2)); \ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10196
for the V3: 1) I dropped using PropVariantCompareEx as the underlying helper for VariantCompare, and implemented needed things directly. Rationale: - VariantCompare is (from the tests) antisymetric (VariantCompare(v1,v2)==-VariantCompare(v2,v1)), while PropVariantCompareEx isn't (it always coerces v2 into v1's type) - it saves us a couple of (PROP)VARIANT copies - there are a lot of things behaving differently (eg Prop comparison converts betwen numeric & strings, while VariantCompare doesn't; VariantCompare properly compares all cases of signed/unsigned args, while PropVariantCompare only succeeds when second arg can be converted to first's type...) 2) there are a bunch of new tests, some can look redundant; but given some of the outcome (eg unsigned int + float), it ended up covering a great deal of the possible cases 3) I moved changes to PropVariantCompareEx outside of this MR (things are no longer related). I'll send it after this one is merged. 4) code for VariantCompare passes all the tests (and should be ok for all numeric types and BSTR), but I couldn't figure out a nicer way to implement behavior for some some of the results. The quote of MSDN for this function reads
This function does not support the comparison of different VARIANT types. If the types named in var1 and var2 are different, the results are undefined and should be ignored. Calling applications should ensure that they are comparing two of the same type before they call this function. The PropVariantChangeType function can be used to convert the two structures to the same type.
(side note: PropVariantChangeType doesn't apply to VARIANT) on one hand tests show that VariantCompare does the conversions between the numeric types (integers & floats), but on the other hand that some results are "strange" (ie BSTR\<\>numeric return -1/1, indepentantly of values of the args vs eg ARRAY) this would require much more tests to get perhaps a better understanding. for now I'd rather keep it as is (and extend it if needed, there should be a FIXME for the not handled cases) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10196#note_130869
participants (2)
-
Eric Pouech -
eric pouech (@epo)