[4/5] propsys: Implement prop variant integer conversions with tests.

Vincent Povirk madewokherd at gmail.com
Thu Sep 13 17:27:32 CDT 2012


-------------- next part --------------
From 7764559ef81974a0fa8c3cb0b73623c9ce19537c Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Thu, 13 Sep 2012 16:10:35 -0500
Subject: [PATCH 4/5] propsys: Implement prop variant integer conversions with
 tests.

---
 dlls/propsys/propsys.spec    |   12 ++--
 dlls/propsys/propvar.c       |  141 ++++++++++++++++++++++++++++++++++++++++++
 dlls/propsys/tests/propsys.c |  126 +++++++++++++++++++++++++++++++++++++
 include/propvarutil.h        |    6 ++
 4 files changed, 279 insertions(+), 6 deletions(-)

diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec
index fefc5f0..15386d7 100644
--- a/dlls/propsys/propsys.spec
+++ b/dlls/propsys/propsys.spec
@@ -120,15 +120,15 @@
 @ stub PropVariantToFileTimeVector
 @ stub PropVariantToFileTimeVectorAlloc
 @ stdcall PropVariantToGUID(ptr ptr)
-@ stub PropVariantToInt16
+@ stdcall PropVariantToInt16(ptr ptr)
 @ stub PropVariantToInt16Vector
 @ stub PropVariantToInt16VectorAlloc
 @ stub PropVariantToInt16WithDefault
-@ stub PropVariantToInt32
+@ stdcall PropVariantToInt32(ptr ptr)
 @ stub PropVariantToInt32Vector
 @ stub PropVariantToInt32VectorAlloc
 @ stub PropVariantToInt32WithDefault
-@ stub PropVariantToInt64
+@ stdcall PropVariantToInt64(ptr ptr)
 @ stub PropVariantToInt64Vector
 @ stub PropVariantToInt64VectorAlloc
 @ stub PropVariantToInt64WithDefault
@@ -138,15 +138,15 @@
 @ stub PropVariantToStringVector
 @ stub PropVariantToStringVectorAlloc
 @ stub PropVariantToStringWithDefault
-@ stub PropVariantToUInt16
+@ stdcall PropVariantToUInt16(ptr ptr)
 @ stub PropVariantToUInt16Vector
 @ stub PropVariantToUInt16VectorAlloc
 @ stub PropVariantToUInt16WithDefault
-@ stub PropVariantToUInt32
+@ stdcall PropVariantToUInt32(ptr ptr)
 @ stub PropVariantToUInt32Vector
 @ stub PropVariantToUInt32VectorAlloc
 @ stub PropVariantToUInt32WithDefault
-@ stub PropVariantToUInt64
+@ stdcall PropVariantToUInt64(ptr ptr)
 @ stub PropVariantToUInt64Vector
 @ stub PropVariantToUInt64VectorAlloc
 @ stub PropVariantToUInt64WithDefault
diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c
index bbfe8ca..28100a0 100644
--- a/dlls/propsys/propvar.c
+++ b/dlls/propsys/propvar.c
@@ -68,6 +68,147 @@ static HRESULT PROPVAR_ConvertFILETIME(PROPVARIANT *ppropvarDest,
     return E_FAIL;
 }
 
+static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits,
+    int dest_signed, LONGLONG *res)
+{
+    int src_signed;
+
+    switch (pv->vt)
+    {
+    case VT_I1:
+        src_signed = 1;
+        *res = pv->u.cVal;
+        break;
+    case VT_UI1:
+        src_signed = 0;
+        *res = pv->u.bVal;
+        break;
+    case VT_I2:
+        src_signed = 1;
+        *res = pv->u.iVal;
+        break;
+    case VT_UI2:
+        src_signed = 0;
+        *res = pv->u.uiVal;
+        break;
+    case VT_I4:
+        src_signed = 1;
+        *res = pv->u.lVal;
+        break;
+    case VT_UI4:
+        src_signed = 0;
+        *res = pv->u.ulVal;
+        break;
+    case VT_I8:
+        src_signed = 1;
+        *res = pv->u.hVal.QuadPart;
+        break;
+    case VT_UI8:
+        src_signed = 0;
+        *res = pv->u.uhVal.QuadPart;
+        break;
+    case VT_EMPTY:
+        src_signed = 0;
+        *res = 0;
+        break;
+    default:
+        FIXME("unhandled vt %d\n", pv->vt);
+        return E_NOTIMPL;
+    }
+
+    if (*res < 0 && src_signed != dest_signed)
+        return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+
+    if (dest_bits < 64)
+    {
+        if (dest_signed)
+        {
+            if (*res >= ((LONGLONG)1 << (dest_bits-1)) ||
+                *res < ((LONGLONG)-1 << (dest_bits-1)))
+                return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+        }
+        else
+        {
+            if ((ULONGLONG)(*res) >= ((ULONGLONG)1 << dest_bits))
+                return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+        }
+    }
+
+    return S_OK;
+}
+
+HRESULT WINAPI PropVariantToInt16(REFPROPVARIANT propvarIn, SHORT *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 16, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (SHORT)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToInt32(REFPROPVARIANT propvarIn, LONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 32, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (LONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 64, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (LONGLONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt16(REFPROPVARIANT propvarIn, USHORT *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 16, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (USHORT)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 32, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (ULONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 64, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (ULONGLONG)res;
+    return hr;
+}
+
 /******************************************************************
  *  PropVariantChangeType   (PROPSYS.@)
  */
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c
index 789eee8..c9df1c9 100644
--- a/dlls/propsys/tests/propsys.c
+++ b/dlls/propsys/tests/propsys.c
@@ -753,6 +753,131 @@ static void test_PropVariantCompare(void)
     SysFreeString(str_b.u.bstrVal);
 }
 
+static inline const char* debugstr_longlong(ULONGLONG ll)
+{
+    static char string[17];
+    if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
+        sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
+    else
+        sprintf(string, "%lx", (unsigned long)ll);
+    return string;
+}
+
+static void test_intconversions(void)
+{
+    PROPVARIANT propvar;
+    SHORT sval;
+    USHORT usval;
+    LONG lval;
+    ULONG ulval;
+    LONGLONG llval;
+    ULONGLONG ullval;
+    HRESULT hr;
+
+    PropVariantClear(&propvar);
+
+    propvar.vt = VT_I8;
+    propvar.u.hVal.QuadPart = (LONGLONG)1 << 63;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == (LONGLONG)1 << 63, "got wrong value %s\n", debugstr_longlong(llval));
+
+    hr = PropVariantToUInt64(&propvar, &ullval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToInt32(&propvar, &lval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToUInt32(&propvar, &ulval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToInt16(&propvar, &sval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToUInt16(&propvar, &usval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    propvar.vt = VT_UI8;
+    propvar.u.uhVal.QuadPart = 5;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == 5, "got wrong value %s\n", debugstr_longlong(llval));
+
+    hr = PropVariantToUInt64(&propvar, &ullval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(ullval == 5, "got wrong value %s\n", debugstr_longlong(ullval));
+
+    hr = PropVariantToInt32(&propvar, &lval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(lval == 5, "got wrong value %d\n", lval);
+
+    hr = PropVariantToUInt32(&propvar, &ulval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(ulval == 5, "got wrong value %d\n", ulval);
+
+    hr = PropVariantToInt16(&propvar, &sval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(sval == 5, "got wrong value %d\n", sval);
+
+    hr = PropVariantToUInt16(&propvar, &usval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(usval == 5, "got wrong value %d\n", usval);
+
+    propvar.vt = VT_I8;
+    propvar.u.hVal.QuadPart = -5;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == -5, "got wrong value %s\n", debugstr_longlong(llval));
+
+    hr = PropVariantToUInt64(&propvar, &ullval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToInt32(&propvar, &lval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(lval == -5, "got wrong value %d\n", lval);
+
+    hr = PropVariantToUInt32(&propvar, &ulval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    hr = PropVariantToInt16(&propvar, &sval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(sval == -5, "got wrong value %d\n", sval);
+
+    hr = PropVariantToUInt16(&propvar, &usval);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
+
+    propvar.vt = VT_UI4;
+    propvar.u.ulVal = 6;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == 6, "got wrong value %s\n", debugstr_longlong(llval));
+
+    propvar.vt = VT_I4;
+    propvar.u.lVal = -6;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == -6, "got wrong value %s\n", debugstr_longlong(llval));
+
+    propvar.vt = VT_UI2;
+    propvar.u.uiVal = 7;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == 7, "got wrong value %s\n", debugstr_longlong(llval));
+
+    propvar.vt = VT_I2;
+    propvar.u.iVal = -7;
+
+    hr = PropVariantToInt64(&propvar, &llval);
+    ok(hr == S_OK, "hr=%x\n", hr);
+    ok(llval == -7, "got wrong value %s\n", debugstr_longlong(llval));
+}
+
 START_TEST(propsys)
 {
     test_PSStringFromPropertyKey();
@@ -762,4 +887,5 @@ START_TEST(propsys)
     test_InitPropVariantFromBuffer();
     test_PropVariantToGUID();
     test_PropVariantCompare();
+    test_intconversions();
 }
diff --git a/include/propvarutil.h b/include/propvarutil.h
index 94a80b4..4618efe 100644
--- a/include/propvarutil.h
+++ b/include/propvarutil.h
@@ -70,6 +70,12 @@ HRESULT WINAPI VariantToGUID(const VARIANT *pvar, GUID *guid);
 INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2,
                                 PROPVAR_COMPARE_UNIT uint, PROPVAR_COMPARE_FLAGS flags);
 
+HRESULT WINAPI PropVariantToInt16(REFPROPVARIANT propvarIn, SHORT *ret);
+HRESULT WINAPI PropVariantToInt32(REFPROPVARIANT propvarIn, LONG *ret);
+HRESULT WINAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret);
+HRESULT WINAPI PropVariantToUInt16(REFPROPVARIANT propvarIn, USHORT *ret);
+HRESULT WINAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret);
+HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret);
 
 #ifdef __cplusplus
 
-- 
1.7.9.5


More information about the wine-patches mailing list