[PATCH v2 03/15] propsys: Extend PropVariantCompareEx()

Jonas Kümmerlin rgcjonas at gmail.com
Sat Jul 18 11:26:42 CDT 2015


PropVariantCompareEx() now supports all integer types, vectors of most things
and other types we plan to implement in the serialization routines.

The new comparisons aid future test cases for the (de)serialization routines.
---
 dlls/propsys/propvar.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++---
 include/propidl.idl    |   4 +
 include/propvarutil.h  |   5 +
 3 files changed, 322 insertions(+), 18 deletions(-)

diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c
index 1a4d9d1..ae3fd2f 100644
--- a/dlls/propsys/propvar.c
+++ b/dlls/propsys/propvar.c
@@ -614,7 +614,17 @@ static BOOL isemptyornull(const PROPVARIANT *propvar)
         }
         return i == propvar->u.parray->cDims;
     }
-    /* FIXME: vectors, byrefs, errors? */
+    if ((propvar->vt & VT_VECTOR) == VT_VECTOR)
+    {
+        /* all vector structs are equal */
+        return !propvar->u.cac.cElems || !propvar->u.cac.pElems;
+    }
+    if ((propvar->vt & VT_BYREF) == VT_BYREF)
+    {
+        /* all pointers are equal */
+        return !propvar->u.punkVal;
+    }
+    /* FIXME: errors? */
     return FALSE;
 }
 
@@ -658,36 +668,321 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2
     else \
         res = 0; \
     } while (0)
+#define CMP_INT_VECTOR(var) do { \
+    if (propvar1->u.var.cElems > propvar2_converted->u.var.cElems) \
+    { res = 1; } \
+    else if (propvar1->u.var.cElems < propvar2_converted->u.var.cElems) \
+    { res = -1; } \
+    else \
+    { \
+        ULONG i; \
+        res = 0; \
+        for (i = 0; i < propvar1->u.var.cElems; ++i) \
+        { \
+            if (propvar1->u.var.pElems[i] > propvar2_converted->u.var.pElems[i]) \
+            { \
+                res = 1; \
+                break; \
+            } \
+            else if (propvar1->u.var.pElems[i] < propvar2_converted->u.var.pElems[i]) \
+            { \
+                res = -1; \
+                break; \
+            } \
+        } \
+    } \
+    }  while(0)
+
+#define INT_CASE(vtype, svar, vecvar) \
+    case vtype: \
+        CMP_INT_VALUE(svar); \
+        break; \
+    case VT_VECTOR|vtype: \
+        CMP_INT_VECTOR(vecvar); \
+        break; \
 
     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:
+    INT_CASE(VT_I1, cVal, cac)
+    INT_CASE(VT_UI1, bVal, caub)
+    INT_CASE(VT_I2, iVal, cai)
+    INT_CASE(VT_UI2, uiVal, caui)
+    INT_CASE(VT_I4, lVal, cal)
+    INT_CASE(VT_UI4, ulVal, caul)
+    INT_CASE(VT_BOOL, boolVal, cabool)
+    INT_CASE(VT_R4, fltVal, caflt)
+    INT_CASE(VT_R8, dblVal, cadbl)
+    INT_CASE(VT_DATE, date, cadate) /* DATE == double */
+    INT_CASE(VT_ERROR, scode, cascode) /* == ULONG */
+    case VT_INT: /* does not appear as vector */
         CMP_INT_VALUE(lVal);
         break;
-    case VT_UI4:
-        CMP_INT_VALUE(uiVal);
+    case VT_UINT: /* does not appear as vector */
+        CMP_INT_VALUE(ulVal);
         break;
     case VT_I8:
         CMP_INT_VALUE(hVal.QuadPart);
         break;
+    case VT_VECTOR|VT_I8:
+        if (propvar1->u.cah.cElems > propvar2_converted->u.cah.cElems)
+            res = 1;
+        else if (propvar1->u.cah.cElems < propvar2_converted->u.cah.cElems)
+            res = -1;
+        else
+        {
+            ULONG i;
+            res = 0;
+            for (i = 0; i < propvar1->u.cah.cElems; ++i)
+            {
+                if (propvar1->u.cah.pElems[i].QuadPart > propvar2_converted->u.cah.pElems[i].QuadPart)
+                {
+                    res = 1;
+                    break;
+                }
+                else if (propvar1->u.cah.pElems[i].QuadPart < propvar2_converted->u.cah.pElems[i].QuadPart)
+                {
+                    res = -1;
+                    break;
+                }
+            }
+        }
+        break;
     case VT_UI8:
         CMP_INT_VALUE(uhVal.QuadPart);
         break;
-    case VT_BSTR:
+    case VT_VECTOR|VT_UI8:
+        if (propvar1->u.cauh.cElems > propvar2_converted->u.cauh.cElems)
+            res = 1;
+        else if (propvar1->u.cauh.cElems < propvar2_converted->u.cauh.cElems)
+            res = -1;
+        else
+        {
+            ULONG i;
+            res = 0;
+            for (i = 0; i < propvar1->u.cauh.cElems; ++i)
+            {
+                if (propvar1->u.cauh.pElems[i].QuadPart > propvar2_converted->u.cauh.pElems[i].QuadPart)
+                {
+                    res = 1;
+                    break;
+                }
+                else if (propvar1->u.cauh.pElems[i].QuadPart < propvar2_converted->u.cauh.pElems[i].QuadPart)
+                {
+                    res = -1;
+                    break;
+                }
+            }
+        }
+        break;
+    case VT_FILETIME:
+    {
+        CMP_INT_VALUE(filetime.dwHighDateTime);
+        if (res == 0)
+            CMP_INT_VALUE(filetime.dwLowDateTime);
+
+        break;
+    }
+    case VT_VECTOR|VT_FILETIME:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(cafiletime.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.cafiletime.cElems; ++i)
+        {
+            CMP_INT_VALUE(cafiletime.pElems[i].dwHighDateTime);
+            if (res)
+                break;
+
+            CMP_INT_VALUE(cafiletime.pElems[i].dwLowDateTime);
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_LPSTR:
+        res = lstrcmpA(propvar1->u.pszVal, propvar2_converted->u.pszVal);
+        break;
+    case VT_VECTOR|VT_LPSTR:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(calpstr.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.calpstr.cElems; ++i)
+        {
+            /* FIXME: Use string flags. */
+            res = lstrcmpA(propvar1->u.calpstr.pElems[i], propvar2_converted->u.calpstr.pElems[i]);
+
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_BSTR:   /* BSTR and LPWSTR are NOT EQUAL in general, but here */
+    case VT_LPWSTR:
         /* FIXME: Use string flags. */
-        res = lstrcmpW(propvar1->u.bstrVal, propvar2->u.bstrVal);
+        res = lstrcmpW(propvar1->u.bstrVal, propvar2_converted->u.bstrVal);
+        break;
+    case VT_VECTOR|VT_BSTR:
+    case VT_VECTOR|VT_LPWSTR:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(calpwstr.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.calpwstr.cElems; ++i)
+        {
+            /* FIXME: Use string flags. */
+            res = lstrcmpW(propvar1->u.calpwstr.pElems[i], propvar2_converted->u.calpwstr.pElems[i]);
+
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_CLSID:
+        /* IsEqualUUID only compares for equality :( */
+        CMP_INT_VALUE(puuid->Data1);
+        if (res)
+            break;
+
+        CMP_INT_VALUE(puuid->Data2);
+        if (res)
+            break;
+
+        CMP_INT_VALUE(puuid->Data3);
+        if (res)
+            break;
+
+        res = memcmp(propvar1->u.puuid->Data4, propvar2_converted->u.puuid->Data4, 8);
+        break;
+    case VT_VECTOR|VT_CLSID:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(cauuid.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.cauuid.cElems; ++i)
+        {
+            CMP_INT_VALUE(cauuid.pElems[i].Data1);
+            if (res)
+                break;
+
+            CMP_INT_VALUE(cauuid.pElems[i].Data2);
+            if (res)
+                break;
+
+            CMP_INT_VALUE(cauuid.pElems[i].Data3);
+            if (res)
+                break;
+
+            res = memcmp(propvar1->u.cauuid.pElems[i].Data4,
+                         propvar2_converted->u.cauuid.pElems[i].Data4,
+                         8);
+
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_CF:
+        CMP_INT_VALUE(pclipdata->cbSize);
+        if (res)
+            break;
+
+        CMP_INT_VALUE(pclipdata->ulClipFmt);
+        if (res)
+            break;
+
+        res = memcmp(propvar1->u.pclipdata->pClipData,
+                     propvar2_converted->u.pclipdata->pClipData,
+                     propvar1->u.pclipdata->cbSize - 4);
+        break;
+    case VT_VECTOR|VT_CF:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(caclipdata.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.caclipdata.cElems; ++i)
+        {
+            CMP_INT_VALUE(caclipdata.pElems[i].cbSize);
+            if (res)
+                break;
+
+            CMP_INT_VALUE(caclipdata.pElems[i].ulClipFmt);
+            if (res)
+                break;
+
+            res = memcmp(propvar1->u.caclipdata.pElems[i].pClipData,
+                         propvar2_converted->u.caclipdata.pElems[i].pClipData,
+                         propvar1->u.caclipdata.pElems[i].cbSize - 4);
+
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_VECTOR|VT_VARIANT:
+    {
+        ULONG i;
+
+        CMP_INT_VALUE(capropvar.cElems);
+        if (res)
+            break;
+
+        for (i = 0; i < propvar1->u.capropvar.cElems; ++i)
+        {
+            res = PropVariantCompareEx(&propvar1->u.capropvar.pElems[i],
+                                       &propvar2_converted->u.capropvar.pElems[i],
+                                       unit, flags);
+
+            if (res)
+                break;
+        }
+        break;
+    }
+    case VT_DECIMAL:
+    {
+        HRESULT hr;
+        DECIMAL dec1 = *(DECIMAL*)propvar1;
+        DECIMAL dec2 = *(DECIMAL*)propvar2_converted;
+        dec1.wReserved = 0;
+        dec2.wReserved = 0;
+
+        hr = VarDecCmp(&dec1, &dec2);
+        if (hr == VARCMP_LT)
+            res = -1;
+        else if (hr == VARCMP_GT)
+            res = 1;
+        else if (hr == VARCMP_EQ)
+            res = 0;
+        else
+        {
+            WARN("Comparing DECIMALS: hr=%08x\n", (unsigned)hr);
+            res = -1;
+        }
+        break;
+    }
+    case VT_BLOB:
+        CMP_INT_VALUE(blob.cbSize);
+        if (res)
+            break;
+
+        res = memcmp(propvar1->u.blob.pBlobData,
+                     propvar2_converted->u.blob.pBlobData,
+                     propvar1->u.blob.cbSize);
         break;
     default:
         FIXME("vartype %d not handled\n", propvar1->vt);
diff --git a/include/propidl.idl b/include/propidl.idl
index fbe80d8..2fb8370 100644
--- a/include/propidl.idl
+++ b/include/propidl.idl
@@ -85,6 +85,7 @@ interface IPropertyStorage : IUnknown
       type *pElems; \
     } name
 
+  TYPEDEF_CA(char, CAC);
   TYPEDEF_CA(unsigned char, CAUB);
   TYPEDEF_CA(short, CAI);
   TYPEDEF_CA(USHORT, CAUI);
@@ -137,10 +138,13 @@ interface IPropertyStorage : IUnknown
     [case(VT_CF)]                         CLIPDATA *pclipdata;
     [case(VT_STREAM, VT_STREAMED_OBJECT)] IStream *pStream;
     [case(VT_STORAGE, VT_STORED_OBJECT)]  IStorage *pStorage;
+    [case(VT_DISPATCH)]                   IDispatch *pdispVal;
+    [case(VT_UNKNOWN)]                    IUnknown *punkVal;
     [case(VT_BSTR)]                       BSTR bstrVal;
     [case(VT_BSTR_BLOB)]                  BSTRBLOB bstrblobVal;
     [case(VT_LPSTR)]                      LPSTR pszVal;
     [case(VT_LPWSTR)]                     LPWSTR pwszVal;
+    [case(VT_I1|VT_VECTOR)]               CAC cac;
     [case(VT_UI1|VT_VECTOR)]              CAUB caub;
     [case(VT_I2|VT_VECTOR)]               CAI cai;
     [case(VT_UI2|VT_VECTOR)]              CAUI caui;
diff --git a/include/propvarutil.h b/include/propvarutil.h
index 1efa248..b0a1731 100644
--- a/include/propvarutil.h
+++ b/include/propvarutil.h
@@ -175,6 +175,11 @@ static inline HRESULT InitPropVariantFromUInt64(ULONGLONG val, PROPVARIANT *ppro
     return S_OK;
 }
 
+static inline INT PropVariantCompare(REFPROPVARIANT v1, REFPROPVARIANT v2)
+{
+    return PropVariantCompareEx(v1, v2, PVCU_DEFAULT, PVCF_DEFAULT);
+}
+
 #undef PROPVARIANT_U
 
 #endif
-- 
2.4.3




More information about the wine-devel mailing list