From: Ziqing Hui zhui@codeweavers.com
--- dlls/propsys/propsys.spec | 4 ++-- dlls/propsys/propvar.c | 10 ++++++++++ include/propvarutil.h | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec index 20615dd3aed..e6f2853b2a0 100644 --- a/dlls/propsys/propsys.spec +++ b/dlls/propsys/propsys.spec @@ -150,7 +150,7 @@ @ stub PropVariantToUInt64Vector @ stub PropVariantToUInt64VectorAlloc @ stub PropVariantToUInt64WithDefault -@ stub PropVariantToVariant +@ stdcall PropVariantToVariant(ptr ptr) @ stub StgDeserializePropVariant @ stub StgSerializePropVariant @ stub VariantCompare @@ -188,7 +188,7 @@ @ stub VariantToInt64Array @ stub VariantToInt64ArrayAlloc @ stub VariantToInt64WithDefault -@ stub VariantToPropVariant +@ stdcall VariantToPropVariant(ptr ptr) @ stub VariantToStrRet @ stdcall VariantToString(ptr ptr long) @ stub VariantToStringAlloc diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index 8702d31561f..038222daafd 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -1025,3 +1025,13 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2
return res; } + +HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var) +{ + return E_NOTIMPL; +} + +HRESULT WINAPI VariantToPropVariant(const VARIANT *var, PROPVARIANT *propvar) +{ + return E_NOTIMPL; +} diff --git a/include/propvarutil.h b/include/propvarutil.h index 8bbe0c8fd15..29c0bf7796b 100644 --- a/include/propvarutil.h +++ b/include/propvarutil.h @@ -110,6 +110,9 @@ PSSTDAPI VariantToString(REFVARIANT var, PWSTR ret, UINT cch);
PSSTDAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret);
+PSSTDAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var); +PSSTDAPI VariantToPropVariant(const VARIANT* var, PROPVARIANT* propvar); + #ifdef __cplusplus
HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/propsys/tests/propsys.c | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+)
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 04816864080..fded4b13879 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -2322,6 +2322,91 @@ static void test_VariantToString(void) VariantClear(&v); }
+#define check_VariantToPropVariant(var, propvar, type, member, value, format) do \ +{ \ + V_VT(&(var)) = VT_##type; \ + V_##type(&(var)) = (value); \ + hr = VariantToPropVariant(&(var), &(propvar)); \ + ok_(__FILE__, __LINE__)(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); \ + ok_(__FILE__, __LINE__)((propvar).vt == VT_##type, "Unexpected propvar.vt %d.\n", (propvar).vt); \ + ok_(__FILE__, __LINE__)((propvar).member == (value), \ + "Unexpected propvar."#member" "format".\n", (propvar).member); \ +} while (0) + +static void test_VariantToPropVariant(void) +{ + PROPVARIANT propvar; + VARIANT var; + HRESULT hr; + + VariantInit(&var); + PropVariantInit(&propvar); + + hr = VariantToPropVariant(NULL, &propvar); + todo_wine + ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr); + hr = VariantToPropVariant(&var, NULL); + todo_wine + ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr); + + V_VT(&var) = 0xdead; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == DISP_E_BADVARTYPE, "VariantToPropVariant returned %#lx.\n", hr); + V_VT(&var) = VT_ILLEGAL; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == TYPE_E_TYPEMISMATCH, "VariantToPropVariant returned %#lx.\n", hr); + V_VT(&var) = VT_CLSID; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == DISP_E_BADVARTYPE, "VariantToPropVariant returned %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "Unexpected propvar.vt %d.\n", propvar.vt); + + todo_wine + { + V_VT(&var) = VT_NULL; + hr = VariantToPropVariant(&var, &propvar); + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ok(propvar.vt == VT_NULL, "Unexpected propvar.vt %d.\n", propvar.vt); + + check_VariantToPropVariant(var, propvar, I1, cVal, -123, "%c"); + check_VariantToPropVariant(var, propvar, I2, iVal, -456, "%d"); + check_VariantToPropVariant(var, propvar, I4, lVal, -789, "%ld"); + check_VariantToPropVariant(var, propvar, I8, hVal.QuadPart, -101112, "%I64d"); + + check_VariantToPropVariant(var, propvar, UI1, bVal, 0xcd, "%#x"); + check_VariantToPropVariant(var, propvar, UI2, uiVal, 0xdead, "%#x"); + check_VariantToPropVariant(var, propvar, UI4, ulVal, 0xdeadbeef, "%#lx"); + check_VariantToPropVariant(var, propvar, UI8, uhVal.QuadPart, 0xdeadbeefdeadbeef, "%I64x"); + + check_VariantToPropVariant(var, propvar, BOOL, boolVal, TRUE, "%d"); + + check_VariantToPropVariant(var, propvar, R4, fltVal, 0.123f, "%f"); + check_VariantToPropVariant(var, propvar, R8, dblVal, 0.456f, "%f"); + } + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"test"); + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + if (hr == S_OK) + { + ok(propvar.vt == VT_BSTR, "Unexpected propvar.vt %d.\n", propvar.vt); + ok(propvar.bstrVal != V_BSTR(&var), "Got same string pointer.\n"); + ok(!wcscmp(propvar.bstrVal, V_BSTR(&var)), "Unexpected propvar.bstrVal %s.\n", debugstr_w(propvar.bstrVal)); + } + + PropVariantClear(&propvar); + VariantClear(&var); +} + START_TEST(propsys) { test_InitPropVariantFromGUIDAsString(); @@ -2350,4 +2435,5 @@ START_TEST(propsys) test_PSCreatePropertyStoreFromObject(); test_VariantToStringWithDefault(); test_VariantToString(); + test_VariantToPropVariant(); }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/propsys/propvar.c | 81 +++++++++++++++++++++++++++++++++++- dlls/propsys/tests/propsys.c | 11 ----- 2 files changed, 80 insertions(+), 12 deletions(-)
diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index 038222daafd..6500926380f 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -36,6 +36,26 @@
WINE_DEFAULT_DEBUG_CHANNEL(propsys);
+static HRESULT VARIANT_ValidateType(VARTYPE vt) +{ + VARTYPE vtExtra = vt & (VT_VECTOR | VT_ARRAY | VT_BYREF | VT_RESERVED); + + vt &= VT_TYPEMASK; + + if (!(vtExtra & (VT_VECTOR | VT_RESERVED))) + { + if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID) + { + if ((vtExtra & (VT_BYREF | VT_ARRAY)) && vt <= VT_NULL) + return DISP_E_BADVARTYPE; + if (vt != (VARTYPE)15) + return S_OK; + } + } + + return DISP_E_BADVARTYPE; +} + static HRESULT PROPVAR_ConvertFILETIME(const FILETIME *ft, PROPVARIANT *ppropvarDest, VARTYPE vt) { SYSTEMTIME time; @@ -1033,5 +1053,64 @@ HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var)
HRESULT WINAPI VariantToPropVariant(const VARIANT *var, PROPVARIANT *propvar) { - return E_NOTIMPL; + HRESULT hr; + + TRACE("var %p, propvar %p, var->vt %04x.\n", var, propvar, var->vt); + + if (!var || !propvar) + return E_INVALIDARG; + + if (FAILED(hr = VARIANT_ValidateType(var->vt))) + return hr; + + PropVariantInit(propvar); + propvar->vt = var->vt; + + switch (var->vt) + { + case VT_EMPTY: + case VT_NULL: + break; + case VT_I1: + propvar->cVal = V_I1(var); + break; + case VT_I2: + propvar->iVal = V_I2(var); + break; + case VT_I4: + propvar->lVal = V_I4(var); + break; + case VT_I8: + propvar->hVal.QuadPart = V_I8(var); + break; + case VT_UI1: + propvar->bVal = V_UI1(var); + break; + case VT_UI2: + propvar->uiVal = V_UI2(var); + break; + case VT_UI4: + propvar->ulVal = V_UI4(var); + break; + case VT_UI8: + propvar->uhVal.QuadPart = V_UI8(var); + break; + case VT_BOOL: + propvar->boolVal = V_BOOL(var); + break; + case VT_R4: + propvar->fltVal = V_R4(var); + break; + case VT_R8: + propvar->dblVal = V_R8(var); + break; + case VT_BSTR: + propvar->bstrVal = SysAllocString(V_BSTR(var)); + break; + default: + FIXME("Unsupported type %d.\n", var->vt); + return E_INVALIDARG; + } + + return S_OK; } diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index fded4b13879..fa0badef653 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -2343,15 +2343,12 @@ static void test_VariantToPropVariant(void) PropVariantInit(&propvar);
hr = VariantToPropVariant(NULL, &propvar); - todo_wine ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr); hr = VariantToPropVariant(&var, NULL); - todo_wine ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr);
V_VT(&var) = 0xdead; hr = VariantToPropVariant(&var, &propvar); - todo_wine ok(hr == DISP_E_BADVARTYPE, "VariantToPropVariant returned %#lx.\n", hr); V_VT(&var) = VT_ILLEGAL; hr = VariantToPropVariant(&var, &propvar); @@ -2364,12 +2361,9 @@ static void test_VariantToPropVariant(void)
V_VT(&var) = VT_EMPTY; hr = VariantToPropVariant(&var, &propvar); - todo_wine ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); ok(propvar.vt == VT_EMPTY, "Unexpected propvar.vt %d.\n", propvar.vt);
- todo_wine - { V_VT(&var) = VT_NULL; hr = VariantToPropVariant(&var, &propvar); ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); @@ -2389,19 +2383,14 @@ static void test_VariantToPropVariant(void)
check_VariantToPropVariant(var, propvar, R4, fltVal, 0.123f, "%f"); check_VariantToPropVariant(var, propvar, R8, dblVal, 0.456f, "%f"); - }
V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"test"); hr = VariantToPropVariant(&var, &propvar); - todo_wine ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); - if (hr == S_OK) - { ok(propvar.vt == VT_BSTR, "Unexpected propvar.vt %d.\n", propvar.vt); ok(propvar.bstrVal != V_BSTR(&var), "Got same string pointer.\n"); ok(!wcscmp(propvar.bstrVal, V_BSTR(&var)), "Unexpected propvar.bstrVal %s.\n", debugstr_w(propvar.bstrVal)); - }
PropVariantClear(&propvar); VariantClear(&var);
I don't know why build-clang fails.
Dmitry Timoshkov (@dmitry) commented about dlls/propsys/propvar.c:
WINE_DEFAULT_DEBUG_CHANNEL(propsys);
+static HRESULT VARIANT_ValidateType(VARTYPE vt) +{
- VARTYPE vtExtra = vt & (VT_VECTOR | VT_ARRAY | VT_BYREF | VT_RESERVED);
- vt &= VT_TYPEMASK;
- if (!(vtExtra & (VT_VECTOR | VT_RESERVED)))
Looks like a typo. Shouldn't 'if' use 'vt' instead? vtExtra should be removed then.
On Fri Jul 19 08:21:43 2024 +0000, Dmitry Timoshkov wrote:
Looks like a typo. Shouldn't 'if' use 'vt' instead? vtExtra should be removed then.
I copied it from oleaut32/variant.c, I didn't look into it myself. But it looks good to me.
On Sat Jul 20 02:48:05 2024 +0000, Ziqing Hui wrote:
I copied it from oleaut32/variant.c, I didn't look into it myself. But it looks good to me.
Sorry for the noise, false alarm.
@huw should I assign this to you or someone else?