From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/mmdevapi/tests/Makefile.in | 2 +- dlls/mmdevapi/tests/propstore.c | 175 +++++++++++++++++++++++++++++++- 2 files changed, 175 insertions(+), 2 deletions(-)
diff --git a/dlls/mmdevapi/tests/Makefile.in b/dlls/mmdevapi/tests/Makefile.in index d7408be1bbf..dc515833ce1 100644 --- a/dlls/mmdevapi/tests/Makefile.in +++ b/dlls/mmdevapi/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mmdevapi.dll -IMPORTS = ole32 version user32 advapi32 winmm +IMPORTS = ole32 version user32 advapi32 winmm oleaut32 propsys
SOURCES = \ capture.c \ diff --git a/dlls/mmdevapi/tests/propstore.c b/dlls/mmdevapi/tests/propstore.c index b333a556567..88496375dd8 100644 --- a/dlls/mmdevapi/tests/propstore.c +++ b/dlls/mmdevapi/tests/propstore.c @@ -31,6 +31,7 @@ #include "ks.h" #include "ksmedia.h" #include "mmreg.h" +#include "propvarutil.h"
static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *);
@@ -133,19 +134,150 @@ static void test_getat(IPropertyStore *store) ok(found_desc, "DEVPKEY_Device_DeviceDesc not found\n"); }
+static const VARIANT_BOOL vt_bool_vals[] = { VARIANT_TRUE, VARIANT_FALSE }; +static const GUID vt_clsid_vals[] = { { 1 }, { 2 } }; +static const BYTE vt_blob_val[] = { 1, 2, 3, 4, 5, 6 }; +static const WCHAR vt_bstr_val[] = L"Test1"; + +static ULONG set_propvariant_for_vt(PROPVARIANT *pv, VARTYPE vt, const void *val, DWORD size) +{ + ULONG elems = 1; + + PropVariantInit(pv); + pv->vt = vt; + switch (vt) + { + case VT_BOOL: + pv->boolVal = ((const VARIANT_BOOL *)val)[0]; + break; + + case VT_BOOL | VT_VECTOR: + pv->cabool.cElems = size / sizeof(*pv->cabool.pElems); + pv->cabool.pElems = CoTaskMemAlloc(size); + memcpy(pv->cabool.pElems, val, size); + elems = pv->cabool.cElems; + break; + + case VT_CLSID: + pv->puuid = CoTaskMemAlloc(sizeof(*pv->puuid)); + *pv->puuid = ((const GUID *)val)[0]; + break; + + case VT_CLSID | VT_VECTOR: + pv->cauuid.cElems = size / sizeof(*pv->cauuid.pElems); + pv->cauuid.pElems = CoTaskMemAlloc(size); + memcpy(pv->cauuid.pElems, val, size); + elems = pv->cauuid.cElems; + break; + + case VT_BSTR: + pv->bstrVal = SysAllocString((const WCHAR *)val); + break; + + case VT_BLOB: + pv->blob.cbSize = size; + pv->blob.pBlobData = CoTaskMemAlloc(size); + memcpy(pv->blob.pBlobData, val, size); + break; + } + + return elems; +} + +static BOOL compare_propvariant(PROPVARIANT *pv, PROPVARIANT *pv2) +{ + unsigned int i; + + if (pv->vt != pv2->vt) + return FALSE; + + switch (pv->vt) + { + case VT_BSTR: + case VT_CLSID: + return !PropVariantCompareEx(pv, pv2, 0, 0); + + case VT_BOOL: + return pv->boolVal == pv2->boolVal; + + case VT_BOOL | VT_VECTOR: + if (pv->cabool.cElems != pv2->cabool.cElems) + return FALSE; + + for (i = 0; i < pv->cabool.cElems; i++) + { + if (pv->cabool.pElems[i] != pv2->cabool.pElems[i]) + return FALSE; + } + return TRUE; + + case VT_CLSID | VT_VECTOR: + if (pv->cauuid.cElems != pv2->cauuid.cElems) + return FALSE; + + for (i = 0; i < pv->cauuid.cElems; i++) + { + if (memcmp(&pv->cauuid.pElems[i], &pv2->cauuid.pElems[i], sizeof(*pv->cauuid.pElems))) + return FALSE; + } + return TRUE; + + case VT_BLOB: + if (pv->blob.cbSize != pv2->blob.cbSize) + return FALSE; + + return !memcmp(pv->blob.pBlobData, pv2->blob.pBlobData, pv->blob.cbSize); + } + + return FALSE; +} + +struct reg_serialized { + VARTYPE vt; + WORD unk; /* Seems like mostly uninitialized memory... */ + ULONG elems; + BYTE data[]; +}; + static void test_setvalue_on_wow64(IPropertyStore *store) { - PROPVARIANT pv; + static const struct + { + VARTYPE vt; + const void *data; + DWORD data_size; + + HRESULT expected_hr; + DWORD expected_reg_type; + DWORD expected_size; + BOOL todo_hr; + BOOL todo_data; + } propvar_tests[] = + { + { VT_BOOL, vt_bool_vals, sizeof(vt_bool_vals[0]), S_OK, REG_BINARY, 0xa, TRUE, TRUE }, + { VT_BOOL | VT_VECTOR, vt_bool_vals, sizeof(vt_bool_vals), S_OK, REG_BINARY, 0xc, TRUE, TRUE }, + { VT_CLSID, vt_clsid_vals, sizeof(vt_clsid_vals[0]), S_OK, REG_BINARY, 0x18, TRUE, TRUE }, + { VT_CLSID | VT_VECTOR, vt_clsid_vals, sizeof(vt_clsid_vals), S_OK, REG_BINARY, 0x28, TRUE, TRUE }, + { VT_BSTR, vt_bstr_val, sizeof(vt_bstr_val), S_OK, REG_BINARY, 0x14, TRUE, TRUE }, + { VT_BLOB, vt_blob_val, sizeof(vt_blob_val), S_OK, REG_BINARY, 0xe, .todo_data = TRUE }, + }; + PROPVARIANT pv, pv2; HRESULT hr; LONG ret; WCHAR *guidW; HKEY root, props, devkey; DWORD type, regval, size; + unsigned int i; + BYTE buf[256];
static const PROPERTYKEY PKEY_Bogus = { {0x1da5d803, 0xd492, 0x4edd, {0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x00}}, 0x7f }; + static const PROPERTYKEY PKEY_Bogus2 = { + {0x1da5d803, 0xd492, 0x4edd, {0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x00}}, 0x80 + }; static const WCHAR bogusW[] = L"{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F00},127"; + static const WCHAR bogus2W[] = L"{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F00},128";
PropVariantInit(&pv);
@@ -189,6 +321,47 @@ static void test_setvalue_on_wow64(IPropertyStore *store) ok(type == REG_DWORD, "Got wrong value type: %lu\n", type); ok(regval == 0xAB, "Got wrong value: 0x%lx\n", regval);
+ for (i = 0; i < ARRAY_SIZE(propvar_tests); i++) + { + struct reg_serialized *reg_val; + ULONG expected_elems; + + winetest_push_context("Test %u", i); + + expected_elems = set_propvariant_for_vt(&pv, propvar_tests[i].vt, propvar_tests[i].data, propvar_tests[i].data_size); + hr = IPropertyStore_SetValue(store, &PKEY_Bogus2, &pv); + todo_wine_if(propvar_tests[i].todo_hr) ok(hr == propvar_tests[i].expected_hr, "Unexpected hr %#lx.\n", hr); + if (FAILED(hr)) + { + winetest_pop_context(); + PropVariantClear(&pv); + continue; + } + + ret = RegQueryValueExW(props, bogus2W, NULL, &type, NULL, &size); + ok(ret == ERROR_SUCCESS, "Couldn't get bogus propertykey value: %lu.\n", ret); + ok(type == propvar_tests[i].expected_reg_type, "Unexpected registry value type %lu.\n", type); + todo_wine_if(propvar_tests[i].todo_data) ok(size >= propvar_tests[i].expected_size, "Unexpected registry value size 0x%lx.\n", size); + + ret = RegQueryValueExW(props, bogus2W, NULL, &type, buf, &size); + ok(ret == ERROR_SUCCESS, "Couldn't get bogus propertykey value: %lu.\n", ret); + reg_val = (struct reg_serialized *)buf; + todo_wine_if(propvar_tests[i].todo_data) + ok(reg_val->vt == propvar_tests[i].vt, "Unexpected vt: %#x.\n", reg_val->vt); + todo_wine_if(propvar_tests[i].todo_data) + ok(reg_val->elems == expected_elems, "Unexpected elems: %lu.\n", reg_val->elems); + todo_wine_if(propvar_tests[i].todo_data) + ok(!memcmp(reg_val->data, propvar_tests[i].data, propvar_tests[i].data_size), "Unexpected data.\n"); + + hr = IPropertyStore_GetValue(store, &PKEY_Bogus2, &pv2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(compare_propvariant(&pv, &pv2), "Propvariant mismatch.\n"); + + PropVariantClear(&pv); + PropVariantClear(&pv2); + winetest_pop_context(); + } + RegCloseKey(props); RegCloseKey(devkey); RegCloseKey(root);