diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index 0877801592b..bbfe8ca7082 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -284,10 +284,103 @@ HRESULT WINAPI VariantToGUID(const VARIANT *pvar, GUID *guid) } } +static int isemptyornull(const PROPVARIANT *propvar) +{ + if (propvar->vt == VT_EMPTY || propvar->vt == VT_NULL) + return 1; + if ((propvar->vt & VT_ARRAY) == VT_ARRAY) + { + int i; + for (i=0; iu.parray->cDims; i++) + { + if (propvar->u.parray->rgsabound[i].cElements != 0) + break; + } + return i == propvar->u.parray->cDims; + } + /* FIXME: vectors, byrefs, errors? */ + return 0; +} + INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2, PROPVAR_COMPARE_UNIT unit, PROPVAR_COMPARE_FLAGS flags) { - FIXME("%p,%p,%x,%x\n", propvar1, propvar2, unit, flags); + const PROPVARIANT *propvar2_converted; + PROPVARIANT propvar2_static; + HRESULT hr; + INT res=-1; - return -1; + TRACE("%p,%p,%x,%x\n", propvar1, propvar2, unit, flags); + + if (isemptyornull(propvar1)) + { + if (isemptyornull(propvar2)) + return 0; + return (flags & PVCF_TREATEMPTYASGREATERTHAN) ? 1 : -1; + } + + if (isemptyornull(propvar2)) + return (flags & PVCF_TREATEMPTYASGREATERTHAN) ? -1 : 1; + + if (propvar1->vt != propvar2->vt) + { + hr = PropVariantChangeType(&propvar2_static, propvar2, 0, propvar1->vt); + + if (FAILED(hr)) + return -1; + + propvar2_converted = &propvar2_static; + } + else + propvar2_converted = propvar2; + +#define CMP_INT_VALUE(var) do { \ + if (propvar1->u.var > propvar2_converted->u.var) \ + res = 1; \ + else if (propvar1->u.var < propvar2_converted->u.var) \ + res = -1; \ + else \ + res = 0; \ + } while (0) + + switch (propvar1->vt) + { + case VT_I1: + CMP_INT_VALUE(cVal); + break; + case VT_UI1: + CMP_INT_VALUE(bVal); + break; + case VT_I2: + CMP_INT_VALUE(iVal); + break; + case VT_UI2: + CMP_INT_VALUE(uiVal); + break; + case VT_I4: + CMP_INT_VALUE(lVal); + break; + case VT_UI4: + CMP_INT_VALUE(uiVal); + break; + case VT_I8: + CMP_INT_VALUE(hVal.QuadPart); + break; + case VT_UI8: + CMP_INT_VALUE(uhVal.QuadPart); + break; + case VT_BSTR: + /* FIXME: Use string flags. */ + res = lstrcmpW(propvar1->u.bstrVal, propvar2->u.bstrVal); + break; + default: + FIXME("vartype %d not handled\n", propvar1->vt); + res = -1; + break; + } + + if (propvar2_converted == &propvar2_static) + PropVariantClear(&propvar2_static); + + return res; } diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 92a6668a28a..789eee85038 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -682,28 +682,28 @@ static void test_PropVariantCompare(void) str_b.u.bstrVal = SysAllocString(str_bW); res = PropVariantCompareEx(&empty, &empty, 0, 0); - todo_wine ok(res == 0, "res=%i\n", res); + ok(res == 0, "res=%i\n", res); res = PropVariantCompareEx(&empty, &null, 0, 0); - todo_wine ok(res == 0, "res=%i\n", res); + ok(res == 0, "res=%i\n", res); res = PropVariantCompareEx(&null, &emptyarray, 0, 0); - todo_wine ok(res == 0, "res=%i\n", res); + ok(res == 0, "res=%i\n", res); res = PropVariantCompareEx(&null, &i2_0, 0, 0); ok(res == -1, "res=%i\n", res); res = PropVariantCompareEx(&i2_0, &null, 0, 0); - todo_wine ok(res == 1, "res=%i\n", res); + ok(res == 1, "res=%i\n", res); res = PropVariantCompareEx(&null, &i2_0, 0, PVCF_TREATEMPTYASGREATERTHAN); - todo_wine ok(res == 1, "res=%i\n", res); + ok(res == 1, "res=%i\n", res); res = PropVariantCompareEx(&i2_0, &null, 0, PVCF_TREATEMPTYASGREATERTHAN); ok(res == -1, "res=%i\n", res); res = PropVariantCompareEx(&i2_2, &i2_0, 0, 0); - todo_wine ok(res == 1, "res=%i\n", res); + ok(res == 1, "res=%i\n", res); res = PropVariantCompareEx(&i2_0, &i2_2, 0, 0); ok(res == -1, "res=%i\n", res); @@ -742,6 +742,9 @@ static void test_PropVariantCompare(void) res = PropVariantCompareEx(&str_02, &str_b, 0, 0); ok(res == -1, "res=%i\n", res); + res = PropVariantCompareEx(&str_2, &str_02, 0, 0); + ok(res == 1, "res=%i\n", res); + res = PropVariantCompareEx(&i4_large, &str_b, 0, 0); todo_wine ok(res == -5 /* ??? */, "res=%i\n", res);