This MR adds a very basic implementation of `IPropertyDescription` for system defined properties (i.e, the ones in <propkey.h>). This is needed to support the [`Properties`](https://learn.microsoft.com/en-us/uwp/api/windows.devices.enumeration.device...) method for `IDeviceInformation` in Windows.Devices.Enumeration (!6874).
-- v10: propsys: Implement IPropertyDescription for several known system properties. propsys: Add IPropertyDescription stub for system defined properties. propsys/tests: Add conformance tests for PSGetNameFromPropertyKey. propsys: Add stubs for PSGetNameFromPropertyKey. propsys: Add stubs for PropertySystem.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/tests/propsys.c | 110 +++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+)
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 749704eb9c2..b2bb7bfd2bd 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -32,6 +32,7 @@ #include "propsys.h" #include "propvarutil.h" #include "strsafe.h" +#include "propkey.h" #include "wine/test.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); @@ -56,6 +57,13 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line) ok_(__FILE__,line)(rc == ref, "expected refcount %ld, got %ld\n", ref, rc); }
+static inline const char *debugstr_propkey(const PROPERTYKEY *key) +{ + if (!key) + return "(null)"; + return wine_dbg_sprintf("{%s,%04lx}", wine_dbgstr_guid(&key->fmtid), key->pid); +} + static void test_PSStringFromPropertyKey(void) { static const WCHAR fillerW[] = {'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X', @@ -2949,6 +2957,106 @@ void test_PropVariantGetStringElem(void) PropVariantClear(&propvar); }
+static void test_PropertyDescription_(int line, const PROPERTYKEY *expect_key, const WCHAR *expect_name, VARTYPE expect_type, + IPropertyDescription *desc) +{ + HRESULT hr; + PROPERTYKEY key; + VARTYPE type; + WCHAR *name; + + hr = IPropertyDescription_GetPropertyKey(desc, &key); + ok_(__FILE__, line)(SUCCEEDED(hr), "got %#lx\n", hr); + ok_(__FILE__, line)(!memcmp(&key, expect_key, sizeof(key)), "%s != %s\n", debugstr_propkey(&key), + debugstr_propkey(expect_key)); + hr = IPropertyDescription_GetCanonicalName(desc, &name); + ok_(__FILE__, line)(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + ok_(__FILE__, line)(!wcscmp(name, expect_name), "%s != %s\n", debugstr_w(name), debugstr_w(expect_name)); + CoTaskMemFree(name); + } + hr = IPropertyDescription_GetPropertyType(desc, &type); + ok_(__FILE__, line)(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + ok_(__FILE__, line)(type == expect_type, "%s != !%s\n", debugstr_vt(type), debugstr_vt(expect_type)); +} +#define test_PropertyDescription(k,n,t,d) test_PropertyDescription_(__LINE__, k, n, t, d) + +static void test_PropertySystem(void) +{ + const static struct + { + const PROPERTYKEY *key; + const WCHAR *name; + VARTYPE type; + } system_props[] = { + {&PKEY_ItemNameDisplay, L"System.ItemNameDisplay", VT_LPWSTR}, + {&PKEY_Devices_ContainerId, L"System.Devices.ContainerId", VT_CLSID}, + {&PKEY_Devices_InterfaceClassGuid, L"System.Devices.InterfaceClassGuid", VT_CLSID}, + {&PKEY_Devices_HardwareIds, L"System.Devices.HardwareIds", VT_VECTOR | VT_LPWSTR}, + {&PKEY_Devices_ClassGuid, L"System.Devices.ClassGuid", VT_CLSID} + }; + IPropertySystem *system; + HRESULT hr; + IPropertyDescription *desc; + SIZE_T i; + + CoInitialize(NULL); + hr = CoCreateInstance(&CLSID_PropertySystem, NULL, CLSCTX_INPROC_SERVER, &IID_IPropertySystem, (void **)&system); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (FAILED(hr)) + { + skip("Could not create IPropertySystem instance.\n"); + CoUninitialize(); + return; + } + + for(i = 0; i < ARRAY_SIZE(system_props); i++) + { + IPropertyDescription *desc; + winetest_push_context("system_props %d", (int)i); + + hr = IPropertySystem_GetPropertyDescription(system, system_props[i].key, &IID_IPropertyDescription, (void **)&desc); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); + IPropertyDescription_Release(desc); + } + hr = PSGetPropertyDescription(system_props[i].key, &IID_IPropertyDescription, (void **)&desc); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); + IPropertyDescription_Release(desc); + } + + hr = IPropertySystem_GetPropertyDescriptionByName(system, system_props[i].name, &IID_IPropertyDescription, (void **)&desc); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); + IPropertyDescription_Release(desc); + } + hr = PSGetPropertyDescription(system_props[i].key, &IID_IPropertyDescription, (void **)&desc); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); + IPropertyDescription_Release(desc); + } + + winetest_pop_context(); + } + + hr = IPropertySystem_GetPropertyDescriptionByName(system, L"Non.Existent.Property.Name", &IID_IPropertyDescription, (void **)&desc); + todo_wine ok(hr == TYPE_E_ELEMENTNOTFOUND, "%#lx != %#lx\n", hr, TYPE_E_ELEMENTNOTFOUND); + + IPropertySystem_Release(system); + CoUninitialize(); +} + START_TEST(propsys) { test_InitPropVariantFromGUIDAsString(); @@ -2981,4 +3089,6 @@ START_TEST(propsys) test_VariantToPropVariant(); test_PropVariantToVariant(); test_PropVariantGetStringElem(); + + test_PropertySystem(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/tests/propsys.c | 8 ++++++++ include/propsys.idl | 1 + 2 files changed, 9 insertions(+)
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index b2bb7bfd2bd..5371e42df6a 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -3015,6 +3015,8 @@ static void test_PropertySystem(void) for(i = 0; i < ARRAY_SIZE(system_props); i++) { IPropertyDescription *desc; + PROPERTYKEY key; + winetest_push_context("system_props %d", (int)i);
hr = IPropertySystem_GetPropertyDescription(system, system_props[i].key, &IID_IPropertyDescription, (void **)&desc); @@ -3032,6 +3034,12 @@ static void test_PropertySystem(void) IPropertyDescription_Release(desc); }
+ hr = PSGetPropertyKeyFromName(system_props[i].name, &key); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + ok(!memcmp(&key, system_props[i].key, sizeof(key)), "%s != %s\n", debugstr_propkey(&key), + debugstr_propkey(system_props[i].key)); + hr = IPropertySystem_GetPropertyDescriptionByName(system, system_props[i].name, &IID_IPropertyDescription, (void **)&desc); todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) diff --git a/include/propsys.idl b/include/propsys.idl index 9dc93caf15d..5627b23dbcd 100644 --- a/include/propsys.idl +++ b/include/propsys.idl @@ -808,6 +808,7 @@ cpp_quote("#define PKEYSTR_MAX (GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX)") cpp_quote("PSSTDAPI PSCreateMemoryPropertyStore(REFIID,void **);") cpp_quote("PSSTDAPI PSCreatePropertyStoreFromObject(IUnknown*,DWORD,REFIID,void **);") cpp_quote("PSSTDAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") +cpp_quote("PSSTDAPI PSGetPropertyKeyFromName(PCWSTR,PROPERTYKEY *);") cpp_quote("PSSTDAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);") cpp_quote("PSSTDAPI PSGetPropertyDescription(REFPROPERTYKEY,REFIID,void **);") cpp_quote("PSSTDAPI PSGetPropertyDescriptionListFromString(LPCWSTR,REFIID,void **);")
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/tests/propsys.c | 3 +++ include/propsys.idl | 1 + 2 files changed, 4 insertions(+)
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 5371e42df6a..8224249d6df 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -3002,6 +3002,9 @@ static void test_PropertySystem(void) IPropertyDescription *desc; SIZE_T i;
+ hr = PSGetPropertySystem(&IID_IPropertySystem, (void **)&system); + todo_wine ok(hr == CO_E_NOTINITIALIZED, "got %#lx != %#lx", hr, CO_E_NOTINITIALIZED); + CoInitialize(NULL); hr = CoCreateInstance(&CLSID_PropertySystem, NULL, CLSCTX_INPROC_SERVER, &IID_IPropertySystem, (void **)&system); todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); diff --git a/include/propsys.idl b/include/propsys.idl index 5627b23dbcd..24ffd00c2d3 100644 --- a/include/propsys.idl +++ b/include/propsys.idl @@ -807,6 +807,7 @@ cpp_quote("#define PKEYSTR_MAX (GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX)")
cpp_quote("PSSTDAPI PSCreateMemoryPropertyStore(REFIID,void **);") cpp_quote("PSSTDAPI PSCreatePropertyStoreFromObject(IUnknown*,DWORD,REFIID,void **);") +cpp_quote("PSSTDAPI PSGetPropertySystem(REFIID, void**);") cpp_quote("PSSTDAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") cpp_quote("PSSTDAPI PSGetPropertyKeyFromName(PCWSTR,PROPERTYKEY *);") cpp_quote("PSSTDAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);")
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/propsys_classes.idl | 6 ++ dlls/propsys/propsys_main.c | 107 +++++++++++++++++++++++++++---- dlls/propsys/propsys_private.h | 7 ++ dlls/propsys/tests/propsys.c | 5 +- 4 files changed, 110 insertions(+), 15 deletions(-)
diff --git a/dlls/propsys/propsys_classes.idl b/dlls/propsys/propsys_classes.idl index 02555a37d26..c6e1821ecbc 100644 --- a/dlls/propsys/propsys_classes.idl +++ b/dlls/propsys/propsys_classes.idl @@ -26,3 +26,9 @@ uuid(9a02e012-6303-4e1e-b9a1-630f802592c5) ] coclass InMemoryPropertyStore { interface IPropertyStoreCache; } + +[ + threading(both), + uuid(b8967f85-58ae-4f46-9fb2-5d7904798f4b) +] +coclass PropertySystem { interface IPropertySystem; } diff --git a/dlls/propsys/propsys_main.c b/dlls/propsys/propsys_main.c index 6e87b3d3579..407fde90482 100644 --- a/dlls/propsys/propsys_main.c +++ b/dlls/propsys/propsys_main.c @@ -92,19 +92,71 @@ static const IClassFactoryVtbl InMemoryPropertyStoreFactoryVtbl = {
static IClassFactory InMemoryPropertyStoreFactory = { &InMemoryPropertyStoreFactoryVtbl };
+struct property_system +{ + IPropertySystem IPropertySystem_iface; + LONG ref; +}; + +static const IPropertySystemVtbl propsysvtbl; + +static HRESULT WINAPI propsys_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + struct property_system *propsys_impl; + HRESULT hr; + + TRACE("%p, %p, %s, %p\n", iface, outer, debugstr_guid(iid), out); + + *out = NULL; + if (outer) + return CLASS_E_NOAGGREGATION; + + propsys_impl = calloc(1, sizeof(*propsys_impl)); + if (!propsys_impl) + return E_OUTOFMEMORY; + + propsys_impl->IPropertySystem_iface.lpVtbl = &propsysvtbl; + propsys_impl->ref = 1; + hr = IPropertySystem_QueryInterface(&propsys_impl->IPropertySystem_iface, iid, out); + IPropertySystem_Release(&propsys_impl->IPropertySystem_iface); + return hr; +} + +static const IClassFactoryVtbl PropertySystemFactoryVtbl = +{ + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + propsys_factory_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory PropertySystemFactory = { &PropertySystemFactoryVtbl }; + HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { if(IsEqualGUID(&CLSID_InMemoryPropertyStore, rclsid)) { TRACE("(CLSID_InMemoryPropertyStore %s %p)\n", debugstr_guid(riid), ppv); return IClassFactory_QueryInterface(&InMemoryPropertyStoreFactory, riid, ppv); } + if (IsEqualGUID(&CLSID_PropertySystem, rclsid)) + { + TRACE("(CLSID_PropertySystem %s %p)\n", debugstr_guid(riid), ppv); + return IClassFactory_QueryInterface(&PropertySystemFactory, riid, ppv); + }
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; }
+static inline struct property_system *impl_from_IPropertySystem( IPropertySystem *iface ) +{ + return CONTAINING_RECORD( iface, struct property_system, IPropertySystem_iface ); +} + static HRESULT WINAPI propsys_QueryInterface(IPropertySystem *iface, REFIID riid, void **obj) { + TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), obj); *obj = NULL;
if (IsEqualIID(riid, &IID_IPropertySystem) || IsEqualIID(riid, &IID_IUnknown)) { @@ -119,24 +171,33 @@ static HRESULT WINAPI propsys_QueryInterface(IPropertySystem *iface, REFIID riid
static ULONG WINAPI propsys_AddRef(IPropertySystem *iface) { - return 2; + struct property_system *impl = impl_from_IPropertySystem(iface); + return InterlockedIncrement(&impl->ref); }
static ULONG WINAPI propsys_Release(IPropertySystem *iface) { - return 1; + struct property_system *impl; + ULONG ref; + + impl = impl_from_IPropertySystem(iface); + ref = InterlockedDecrement(&impl->ref); + if (!ref) + free(impl); + return ref; }
static HRESULT WINAPI propsys_GetPropertyDescription(IPropertySystem *iface, REFPROPERTYKEY propkey, REFIID riid, void **ppv) { - return PSGetPropertyDescription(propkey, riid, ppv); + FIXME("(%p, %s, %s, %p): stub\n", iface, debugstr_propkey(propkey), debugstr_guid(riid), ppv); + return E_NOTIMPL; }
static HRESULT WINAPI propsys_GetPropertyDescriptionByName(IPropertySystem *iface, LPCWSTR canonical_name, REFIID riid, void **ppv) { - FIXME("%s %s %p: stub\n", debugstr_w(canonical_name), debugstr_guid(riid), ppv); + FIXME("(%p, %s, %s, %p): stub\n", iface, debugstr_w(canonical_name), debugstr_guid(riid), ppv); return E_NOTIMPL; }
@@ -199,11 +260,9 @@ static const IPropertySystemVtbl propsysvtbl = { propsys_RefreshPropertySchema };
-static IPropertySystem propsys = { &propsysvtbl }; - HRESULT WINAPI PSGetPropertySystem(REFIID riid, void **obj) { - return IPropertySystem_QueryInterface(&propsys, riid, obj); + return CoCreateInstance(&CLSID_PropertySystem, NULL, CLSCTX_INPROC_SERVER, riid, obj); }
HRESULT WINAPI PSRegisterPropertySchema(PCWSTR path) @@ -216,14 +275,22 @@ HRESULT WINAPI PSRegisterPropertySchema(PCWSTR path) HRESULT WINAPI PSUnregisterPropertySchema(PCWSTR path) { FIXME("%s stub\n", debugstr_w(path)); - return E_NOTIMPL; }
HRESULT WINAPI PSGetPropertyDescription(REFPROPERTYKEY propkey, REFIID riid, void **ppv) { - FIXME("%p, %p, %p\n", propkey, riid, ppv); - return E_NOTIMPL; + HRESULT hr; + IPropertySystem *system; + + TRACE("%p, %p, %p\n", propkey, riid, ppv); + hr = PSGetPropertySystem(&IID_IPropertySystem, (void **)&system); + if (SUCCEEDED(hr)) + { + hr = IPropertySystem_GetPropertyDescription(system, propkey, riid, ppv); + IPropertySystem_Release(system); + } + return hr; }
HRESULT WINAPI PSGetPropertyDescriptionListFromString(LPCWSTR proplist, REFIID riid, void **ppv) @@ -234,8 +301,24 @@ HRESULT WINAPI PSGetPropertyDescriptionListFromString(LPCWSTR proplist, REFIID r
HRESULT WINAPI PSGetPropertyKeyFromName(PCWSTR name, PROPERTYKEY *key) { - FIXME("%s, %p\n", debugstr_w(name), key); - return E_NOTIMPL; + HRESULT hr; + IPropertySystem *system; + + TRACE("%s, %p\n", debugstr_w(name), debugstr_propkey(key)); + hr = PSGetPropertySystem(&IID_IPropertySystem, (void **)&system); + if (SUCCEEDED(hr)) + { + IPropertyDescription *desc; + hr = IPropertySystem_GetPropertyDescriptionByName(system, name, &IID_IPropertyDescription, (void *)&desc); + if (SUCCEEDED(hr)) + { + hr = IPropertyDescription_GetPropertyKey(desc, key); + IPropertyDescription_Release(desc); + } + IPropertySystem_Release(system); + } + + return hr; }
HRESULT WINAPI PSRefreshPropertySchema(void) diff --git a/dlls/propsys/propsys_private.h b/dlls/propsys/propsys_private.h index ab5b0fe255c..0d2d0fb4556 100644 --- a/dlls/propsys/propsys_private.h +++ b/dlls/propsys/propsys_private.h @@ -19,3 +19,10 @@ */
HRESULT PropertyStore_CreateInstance(IUnknown *outer, REFIID riid, void **ppv); + +static inline const char *debugstr_propkey(const PROPERTYKEY *key) +{ + if (!key) + return "(null)"; + return wine_dbg_sprintf("{%s,%04lx}", wine_dbgstr_guid(&key->fmtid), key->pid); +} diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 8224249d6df..25d7c984281 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -457,7 +457,6 @@ static void test_PSRefreshPropertySchema(void) HRESULT ret;
ret = PSRefreshPropertySchema(); - todo_wine ok(ret == CO_E_NOTINITIALIZED, "Expected PSRefreshPropertySchema to return CO_E_NOTINITIALIZED, got 0x%08lx\n", ret);
@@ -3003,11 +3002,11 @@ static void test_PropertySystem(void) SIZE_T i;
hr = PSGetPropertySystem(&IID_IPropertySystem, (void **)&system); - todo_wine ok(hr == CO_E_NOTINITIALIZED, "got %#lx != %#lx", hr, CO_E_NOTINITIALIZED); + ok(hr == CO_E_NOTINITIALIZED, "got %#lx != %#lx", hr, CO_E_NOTINITIALIZED);
CoInitialize(NULL); hr = CoCreateInstance(&CLSID_PropertySystem, NULL, CLSCTX_INPROC_SERVER, &IID_IPropertySystem, (void **)&system); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (FAILED(hr)) { skip("Could not create IPropertySystem instance.\n");
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/propsys.spec | 2 +- dlls/propsys/propsys_main.c | 15 +++++++++++++++ include/propsys.idl | 1 + 3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec index 6a1a313f93b..fbaf3b575e5 100644 --- a/dlls/propsys/propsys.spec +++ b/dlls/propsys/propsys.spec @@ -77,7 +77,7 @@ @ stub PSFormatPropertyValue @ stub PSGetItemPropertyHandler @ stub PSGetItemPropertyHandlerWithCreateObject -@ stub PSGetNameFromPropertyKey +@ stdcall PSGetNameFromPropertyKey(ptr ptr) @ stub PSGetNamedPropertyFromPropertyStorage @ stdcall PSGetPropertyDescription(ptr ptr ptr) @ stub PSGetPropertyDescriptionByName diff --git a/dlls/propsys/propsys_main.c b/dlls/propsys/propsys_main.c index 407fde90482..6453e1b4a26 100644 --- a/dlls/propsys/propsys_main.c +++ b/dlls/propsys/propsys_main.c @@ -299,6 +299,21 @@ HRESULT WINAPI PSGetPropertyDescriptionListFromString(LPCWSTR proplist, REFIID r return E_NOTIMPL; }
+HRESULT WINAPI PSGetNameFromPropertyKey(REFPROPERTYKEY key, LPWSTR *name) +{ + HRESULT hr; + IPropertyDescription *desc; + + TRACE("(%s, %p)\n", debugstr_propkey(key), name); + hr = PSGetPropertyDescription(key, &IID_IPropertyDescription, (void *)&desc); + if (SUCCEEDED(hr)) + { + hr = IPropertyDescription_GetCanonicalName(desc, name); + IPropertyDescription_Release(desc); + } + return hr; +} + HRESULT WINAPI PSGetPropertyKeyFromName(PCWSTR name, PROPERTYKEY *key) { HRESULT hr; diff --git a/include/propsys.idl b/include/propsys.idl index 24ffd00c2d3..1cfcaf338da 100644 --- a/include/propsys.idl +++ b/include/propsys.idl @@ -810,6 +810,7 @@ cpp_quote("PSSTDAPI PSCreatePropertyStoreFromObject(IUnknown*,DWORD,REFIID,void cpp_quote("PSSTDAPI PSGetPropertySystem(REFIID, void**);") cpp_quote("PSSTDAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") cpp_quote("PSSTDAPI PSGetPropertyKeyFromName(PCWSTR,PROPERTYKEY *);") +cpp_quote("PSSTDAPI PSGetNameFromPropertyKey(REFPROPERTYKEY,LPWSTR *);") cpp_quote("PSSTDAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);") cpp_quote("PSSTDAPI PSGetPropertyDescription(REFPROPERTYKEY,REFIID,void **);") cpp_quote("PSSTDAPI PSGetPropertyDescriptionListFromString(LPCWSTR,REFIID,void **);")
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/tests/propsys.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 25d7c984281..52c428f91ce 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -3017,6 +3017,7 @@ static void test_PropertySystem(void) for(i = 0; i < ARRAY_SIZE(system_props); i++) { IPropertyDescription *desc; + LPWSTR name; PROPERTYKEY key;
winetest_push_context("system_props %d", (int)i); @@ -3042,6 +3043,14 @@ static void test_PropertySystem(void) ok(!memcmp(&key, system_props[i].key, sizeof(key)), "%s != %s\n", debugstr_propkey(&key), debugstr_propkey(system_props[i].key));
+ hr = PSGetNameFromPropertyKey(system_props[i].key, &name); + todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + ok(!wcscmp(name, system_props[i].name), "%s != %s\n", debugstr_w(name), debugstr_w(system_props[i].name)); + CoTaskMemFree(name); + } + hr = IPropertySystem_GetPropertyDescriptionByName(system, system_props[i].name, &IID_IPropertyDescription, (void **)&desc); todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr))
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/Makefile.in | 1 + dlls/propsys/propsys_desc.c | 269 +++++++++++++++++++++++++++++++++ dlls/propsys/propsys_main.c | 31 +++- dlls/propsys/propsys_private.h | 2 + 4 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 dlls/propsys/propsys_desc.c
diff --git a/dlls/propsys/Makefile.in b/dlls/propsys/Makefile.in index a8661ca17e9..c8f4eb953a4 100644 --- a/dlls/propsys/Makefile.in +++ b/dlls/propsys/Makefile.in @@ -8,5 +8,6 @@ EXTRADLLFLAGS = -Wb,--prefer-native SOURCES = \ propstore.c \ propsys_classes.idl \ + propsys_desc.c \ propsys_main.c \ propvar.c diff --git a/dlls/propsys/propsys_desc.c b/dlls/propsys/propsys_desc.c new file mode 100644 index 00000000000..91622ebb4df --- /dev/null +++ b/dlls/propsys/propsys_desc.c @@ -0,0 +1,269 @@ +/* + * IPropertyDescription implementation + * + * Copyright 2024 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <propsys.h> +#include <propkey.h> + +#include <wine/debug.h> + +#include "propsys_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL( propsys ); + +struct property_description +{ + IPropertyDescription IPropertyDescription_iface; + LONG ref; +}; + +static inline struct property_description * +impl_from_IPropertyDescription( IPropertyDescription *iface ) +{ + return CONTAINING_RECORD( iface, struct property_description, IPropertyDescription_iface ); +} + +static HRESULT WINAPI propdesc_QueryInterface( IPropertyDescription *iface, REFIID iid, void **out ) +{ + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + *out = NULL; + + if (IsEqualGUID( &IID_IUnknown, iid ) || + IsEqualGUID( &IID_IPropertyDescription, iid )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + FIXME( "%s not implemented\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI propdesc_AddRef( IPropertyDescription *iface ) +{ + struct property_description *impl; + TRACE( "(%p)\n", iface ); + impl = impl_from_IPropertyDescription( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG WINAPI propdesc_Release( IPropertyDescription *iface ) +{ + struct property_description *impl; + ULONG ref; + + TRACE( "(%p)\n", iface ); + + impl = impl_from_IPropertyDescription( iface ); + ref = InterlockedDecrement( &impl->ref ); + if (!ref) + free( impl ); + + return ref; +} + +static HRESULT WINAPI propdesc_GetPropertyKey( IPropertyDescription *iface, PROPERTYKEY *pkey ) +{ + FIXME( "(%p, %p) stub!\n", iface, pkey ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetCanonicalName( IPropertyDescription *iface, LPWSTR *name ) +{ + TRACE( "(%p, %p) stub!\n", iface, name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetPropertyType( IPropertyDescription *iface, VARTYPE *vt ) +{ + FIXME( "(%p, %p) stub!\n", iface, vt ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetDisplayName( IPropertyDescription *iface, LPWSTR *name ) +{ + FIXME( "(%p, %p) semi-stub!\n", iface, name ); + return IPropertyDescription_GetCanonicalName( iface, name ); +} + +static HRESULT WINAPI propdesc_GetEditInvitation( IPropertyDescription *iface, LPWSTR *invite ) +{ + FIXME( "(%p, %p) stub!\n", iface, invite ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetTypeFlags( IPropertyDescription *iface, PROPDESC_TYPE_FLAGS mask, + PROPDESC_TYPE_FLAGS *flags ) +{ + FIXME( "(%p, %#x, %p) stub!\n", iface, mask, flags ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetViewFlags( IPropertyDescription *iface, PROPDESC_VIEW_FLAGS *flags ) +{ + FIXME( "(%p, %p) stub!\n", iface, flags ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetDefaultColumnWidth( IPropertyDescription *iface, UINT *chars ) +{ + FIXME( "(%p, %p) stub!\n", iface, chars ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetDisplayType( IPropertyDescription *iface, PROPDESC_DISPLAYTYPE *type ) +{ + FIXME( "(%p, %p) stub!\n", iface, type ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetColumnState( IPropertyDescription *iface, SHCOLSTATEF *flags ) +{ + FIXME( "(%p, %p) stub!\n", iface, flags ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetGroupingRange( IPropertyDescription *iface, PROPDESC_GROUPING_RANGE *range ) +{ + FIXME( "(%p, %p) stub!\n", iface, range ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetRelativeDescriptionType( IPropertyDescription *iface, + PROPDESC_RELATIVEDESCRIPTION_TYPE *type ) +{ + FIXME( "(%p, %p) stub!\n", iface, type ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetRelativeDescription( IPropertyDescription *iface, REFPROPVARIANT propvar1, + REFPROPVARIANT propvar2, LPWSTR *desc1, LPWSTR *desc2 ) +{ + FIXME( "(%p, %p, %p, %p, %p) stub!\n", iface, propvar1, propvar2, desc1, desc2 ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetSortDescription( IPropertyDescription *iface, PROPDESC_SORTDESCRIPTION *psd ) +{ + FIXME( "(%p, %p) stub!\n", iface, psd ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetSortDescriptionLabel( IPropertyDescription *iface, BOOL descending, LPWSTR *desc ) +{ + FIXME( "(%p, %d, %p) stub!\n", iface, descending, desc ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetAggregationType( IPropertyDescription *iface, PROPDESC_AGGREGATION_TYPE *type ) +{ + FIXME( "(%p, %p) stub!\n", iface, type ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetConditionType( IPropertyDescription *iface, PROPDESC_CONDITION_TYPE *cond_type, + CONDITION_OPERATION *op_default ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, cond_type, op_default ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_GetEnumTypeList( IPropertyDescription *iface, REFIID riid, void **out ) +{ + FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_guid( riid ), out ); + *out = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_CoerceToCanonicalValue( IPropertyDescription *iface, PROPVARIANT *propvar ) +{ + FIXME( "(%p, %p) stub!\n", iface, propvar ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_FormatForDisplay( IPropertyDescription *iface, REFPROPVARIANT propvar, + PROPDESC_FORMAT_FLAGS flags, LPWSTR *display ) +{ + FIXME( "(%p, %p, %#x, %p) stub!\n", iface, propvar, flags, display ); + return E_NOTIMPL; +} + +static HRESULT WINAPI propdesc_IsValueCanonical( IPropertyDescription *iface, REFPROPVARIANT propvar ) +{ + FIXME( "(%p, %p) stub!\n", iface, propvar ); + return E_NOTIMPL; +} + +const static IPropertyDescriptionVtbl property_description_vtbl = +{ + /* IUnknown */ + propdesc_QueryInterface, + propdesc_AddRef, + propdesc_Release, + /* IPropertyDescription */ + propdesc_GetPropertyKey, + propdesc_GetCanonicalName, + propdesc_GetPropertyType, + propdesc_GetDisplayName, + propdesc_GetEditInvitation, + propdesc_GetTypeFlags, + propdesc_GetViewFlags, + propdesc_GetDefaultColumnWidth, + propdesc_GetDisplayType, + propdesc_GetColumnState, + propdesc_GetGroupingRange, + propdesc_GetRelativeDescriptionType, + propdesc_GetRelativeDescription, + propdesc_GetSortDescription, + propdesc_GetSortDescriptionLabel, + propdesc_GetAggregationType, + propdesc_GetConditionType, + propdesc_GetEnumTypeList, + propdesc_CoerceToCanonicalValue, + propdesc_FormatForDisplay, + propdesc_IsValueCanonical +}; + +static HRESULT propdesc_from_system_property( IPropertyDescription **out ) +{ + struct property_description *impl; + + impl = calloc(1, sizeof( *impl )); + if (!impl) + return E_OUTOFMEMORY; + + impl->IPropertyDescription_iface.lpVtbl = &property_description_vtbl; + impl->ref = 1; + + *out = &impl->IPropertyDescription_iface; + return S_OK; +} + +HRESULT propsys_get_system_propdesc_by_name( const WCHAR *name, IPropertyDescription **desc ) +{ + return propdesc_from_system_property( desc ); +} + +HRESULT propsys_get_system_propdesc_by_key( const PROPERTYKEY *key, IPropertyDescription **desc ) +{ + return propdesc_from_system_property( desc ); +} diff --git a/dlls/propsys/propsys_main.c b/dlls/propsys/propsys_main.c index 6453e1b4a26..3045ebbfb5a 100644 --- a/dlls/propsys/propsys_main.c +++ b/dlls/propsys/propsys_main.c @@ -190,15 +190,40 @@ static ULONG WINAPI propsys_Release(IPropertySystem *iface) static HRESULT WINAPI propsys_GetPropertyDescription(IPropertySystem *iface, REFPROPERTYKEY propkey, REFIID riid, void **ppv) { - FIXME("(%p, %s, %s, %p): stub\n", iface, debugstr_propkey(propkey), debugstr_guid(riid), ppv); - return E_NOTIMPL; + HRESULT hr; + IPropertyDescription *desc; + + FIXME("(%p, %s, %s, %p): semi-stub!\n", iface, debugstr_propkey(propkey), debugstr_guid(riid), ppv); + + if (!ppv) + return E_INVALIDARG; + *ppv = NULL; + hr = propsys_get_system_propdesc_by_key( propkey, &desc ); + if (FAILED( hr )) + return hr; + + hr = IPropertyDescription_QueryInterface( desc, riid, ppv ); + IPropertyDescription_Release( desc ); + return hr; }
static HRESULT WINAPI propsys_GetPropertyDescriptionByName(IPropertySystem *iface, LPCWSTR canonical_name, REFIID riid, void **ppv) { + HRESULT hr; + IPropertyDescription *desc; + FIXME("(%p, %s, %s, %p): stub\n", iface, debugstr_w(canonical_name), debugstr_guid(riid), ppv); - return E_NOTIMPL; + + if (!ppv) + return E_INVALIDARG; + *ppv = NULL; + hr = propsys_get_system_propdesc_by_name( canonical_name, &desc ); + if (FAILED( hr )) + return hr; + hr = IPropertyDescription_QueryInterface( desc, riid, ppv ); + IPropertyDescription_Release( desc ); + return hr; }
static HRESULT WINAPI propsys_GetPropertyDescriptionListFromString(IPropertySystem *iface, diff --git a/dlls/propsys/propsys_private.h b/dlls/propsys/propsys_private.h index 0d2d0fb4556..cd38692c499 100644 --- a/dlls/propsys/propsys_private.h +++ b/dlls/propsys/propsys_private.h @@ -20,6 +20,8 @@
HRESULT PropertyStore_CreateInstance(IUnknown *outer, REFIID riid, void **ppv);
+HRESULT propsys_get_system_propdesc_by_name(const WCHAR *name, IPropertyDescription **desc); +HRESULT propsys_get_system_propdesc_by_key(const PROPERTYKEY *key, IPropertyDescription **desc); static inline const char *debugstr_propkey(const PROPERTYKEY *key) { if (!key)
From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/propsys_desc.c | 100 +++++++++++++++++++++++++++++++---- dlls/propsys/tests/propsys.c | 14 ++--- 2 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/dlls/propsys/propsys_desc.c b/dlls/propsys/propsys_desc.c index 91622ebb4df..5ec0b36a24c 100644 --- a/dlls/propsys/propsys_desc.c +++ b/dlls/propsys/propsys_desc.c @@ -32,7 +32,13 @@ WINE_DEFAULT_DEBUG_CHANNEL( propsys ); struct property_description { IPropertyDescription IPropertyDescription_iface; + + PROPERTYKEY key; + VARTYPE type; + PROPDESC_TYPE_FLAGS type_flags; + LONG ref; + WCHAR canonical_name[1]; };
static inline struct property_description * @@ -83,20 +89,35 @@ static ULONG WINAPI propdesc_Release( IPropertyDescription *iface )
static HRESULT WINAPI propdesc_GetPropertyKey( IPropertyDescription *iface, PROPERTYKEY *pkey ) { - FIXME( "(%p, %p) stub!\n", iface, pkey ); - return E_NOTIMPL; + struct property_description *impl; + + TRACE( "(%p, %p)\n", iface, pkey ); + impl = impl_from_IPropertyDescription( iface ); + *pkey = impl->key; + return S_OK; }
static HRESULT WINAPI propdesc_GetCanonicalName( IPropertyDescription *iface, LPWSTR *name ) { - TRACE( "(%p, %p) stub!\n", iface, name ); - return E_NOTIMPL; + struct property_description *impl; + + TRACE( "(%p, %p)\n", iface, name ); + impl = impl_from_IPropertyDescription( iface ); + *name = CoTaskMemAlloc( wcslen( impl->canonical_name ) * sizeof( WCHAR ) ); + if (!*name) + return E_OUTOFMEMORY; + wcscpy( *name, impl->canonical_name ); + return S_OK; }
static HRESULT WINAPI propdesc_GetPropertyType( IPropertyDescription *iface, VARTYPE *vt ) { - FIXME( "(%p, %p) stub!\n", iface, vt ); - return E_NOTIMPL; + struct property_description *impl; + + TRACE( "(%p, %p)\n", iface, vt ); + impl = impl_from_IPropertyDescription( iface ); + *vt = impl->type; + return S_OK; }
static HRESULT WINAPI propdesc_GetDisplayName( IPropertyDescription *iface, LPWSTR *name ) @@ -114,7 +135,11 @@ static HRESULT WINAPI propdesc_GetEditInvitation( IPropertyDescription *iface, L static HRESULT WINAPI propdesc_GetTypeFlags( IPropertyDescription *iface, PROPDESC_TYPE_FLAGS mask, PROPDESC_TYPE_FLAGS *flags ) { - FIXME( "(%p, %#x, %p) stub!\n", iface, mask, flags ); + struct property_description *impl; + + TRACE( "(%p, %#x, %p)\n", iface, mask, flags ); + impl = impl_from_IPropertyDescription( iface ); + *flags = mask & impl->type_flags; return E_NOTIMPL; }
@@ -243,15 +268,52 @@ const static IPropertyDescriptionVtbl property_description_vtbl = propdesc_IsValueCanonical };
-static HRESULT propdesc_from_system_property( IPropertyDescription **out ) +struct system_property_description +{ + const WCHAR *canonical_name; + const PROPERTYKEY *key; + + VARTYPE type; +}; + +/* It may be ideal to construct rb_trees for looking up property descriptions by name and key if this array gets large + * enough. */ +static struct system_property_description system_properties[] = +{ + {L"System.Devices.ContainerId", &PKEY_Devices_ContainerId, VT_CLSID}, + {L"System.Devices.InterfaceClassGuid", &PKEY_Devices_InterfaceClassGuid, VT_CLSID}, + {L"System.Devices.DeviceInstanceId", &PKEY_Devices_DeviceInstanceId, VT_CLSID}, + {L"System.Devices.InterfaceEnabled", &PKEY_Devices_InterfaceEnabled, VT_BOOL}, + {L"System.Devices.ClassGuid", &PKEY_Devices_ClassGuid, VT_CLSID}, + {L"System.Devices.CompatibleIds", &PKEY_Devices_CompatibleIds, VT_VECTOR | VT_LPWSTR}, + {L"System.Devices.DeviceCapabilities", &PKEY_Devices_DeviceCapabilities, VT_UI2}, + {L"System.Devices.DeviceHasProblem", &PKEY_Devices_DeviceHasProblem, VT_BOOL}, + {L"System.Devices.DeviceManufacturer", &PKEY_Devices_DeviceManufacturer, VT_LPWSTR}, + {L"System.Devices.HardwareIds", &PKEY_Devices_HardwareIds, VT_VECTOR | VT_LPWSTR}, + {L"System.Devices.Parent", &PKEY_Devices_Parent, VT_LPWSTR}, + {L"System.ItemNameDisplay", &PKEY_ItemNameDisplay, VT_LPWSTR}, + {L"System.Devices.Category", &PKEY_Devices_Category, VT_VECTOR | VT_LPWSTR}, + {L"System.Devices.CategoryIds", &PKEY_Devices_CategoryIds, VT_VECTOR | VT_LPWSTR}, + {L"System.Devices.CategoryPlural", &PKEY_Devices_CategoryPlural, VT_VECTOR | VT_LPWSTR}, + {L"System.Devices.Connected", &PKEY_Devices_Connected, VT_BOOL}, + {L"System.Devices.GlyphIcon", &PKEY_Devices_GlyphIcon, VT_LPWSTR}, +}; + +static HRESULT propdesc_from_system_property( const struct system_property_description *desc, IPropertyDescription **out ) { struct property_description *impl;
- impl = calloc(1, sizeof( *impl )); + impl = calloc(1, offsetof( struct property_description, canonical_name[wcslen(desc->canonical_name)] )); if (!impl) return E_OUTOFMEMORY;
impl->IPropertyDescription_iface.lpVtbl = &property_description_vtbl; + impl->key = *desc->key; + wcscpy( impl->canonical_name, desc->canonical_name ); + impl->type = desc->type; + impl->type_flags = PDTF_ISINNATE; + if (impl->type & VT_VECTOR) + impl->type_flags |= PDTF_MULTIPLEVALUES; impl->ref = 1;
*out = &impl->IPropertyDescription_iface; @@ -260,10 +322,26 @@ static HRESULT propdesc_from_system_property( IPropertyDescription **out )
HRESULT propsys_get_system_propdesc_by_name( const WCHAR *name, IPropertyDescription **desc ) { - return propdesc_from_system_property( desc ); + SIZE_T i; + + for (i = 0; i < ARRAY_SIZE( system_properties ); i++) + { + if (!wcscmp( name, system_properties[i].canonical_name )) + return propdesc_from_system_property( &system_properties[i], desc ); + } + + return TYPE_E_ELEMENTNOTFOUND; }
HRESULT propsys_get_system_propdesc_by_key( const PROPERTYKEY *key, IPropertyDescription **desc ) { - return propdesc_from_system_property( desc ); + SIZE_T i; + + for (i = 0; i < ARRAY_SIZE( system_properties ); i++) + { + if (!memcmp( key, system_properties[i].key, sizeof( *key ) )) + return propdesc_from_system_property( &system_properties[i], desc ); + } + + return TYPE_E_ELEMENTNOTFOUND; } diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 52c428f91ce..bd5e566b4e0 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -3023,14 +3023,14 @@ static void test_PropertySystem(void) winetest_push_context("system_props %d", (int)i);
hr = IPropertySystem_GetPropertyDescription(system, system_props[i].key, &IID_IPropertyDescription, (void **)&desc); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) { test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); IPropertyDescription_Release(desc); } hr = PSGetPropertyDescription(system_props[i].key, &IID_IPropertyDescription, (void **)&desc); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) { test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); @@ -3038,13 +3038,13 @@ static void test_PropertySystem(void) }
hr = PSGetPropertyKeyFromName(system_props[i].name, &key); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) ok(!memcmp(&key, system_props[i].key, sizeof(key)), "%s != %s\n", debugstr_propkey(&key), debugstr_propkey(system_props[i].key));
hr = PSGetNameFromPropertyKey(system_props[i].key, &name); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) { ok(!wcscmp(name, system_props[i].name), "%s != %s\n", debugstr_w(name), debugstr_w(system_props[i].name)); @@ -3052,14 +3052,14 @@ static void test_PropertySystem(void) }
hr = IPropertySystem_GetPropertyDescriptionByName(system, system_props[i].name, &IID_IPropertyDescription, (void **)&desc); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) { test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); IPropertyDescription_Release(desc); } hr = PSGetPropertyDescription(system_props[i].key, &IID_IPropertyDescription, (void **)&desc); - todo_wine ok(SUCCEEDED(hr), "got %#lx\n", hr); + ok(SUCCEEDED(hr), "got %#lx\n", hr); if (SUCCEEDED(hr)) { test_PropertyDescription(system_props[i].key, system_props[i].name, system_props[i].type, desc); @@ -3070,7 +3070,7 @@ static void test_PropertySystem(void) }
hr = IPropertySystem_GetPropertyDescriptionByName(system, L"Non.Existent.Property.Name", &IID_IPropertyDescription, (void **)&desc); - todo_wine ok(hr == TYPE_E_ELEMENTNOTFOUND, "%#lx != %#lx\n", hr, TYPE_E_ELEMENTNOTFOUND); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "%#lx != %#lx\n", hr, TYPE_E_ELEMENTNOTFOUND);
IPropertySystem_Release(system); CoUninitialize();
On Mon Jun 16 12:20:04 2025 +0000, Nikolay Sivov wrote:
You don't have to implement functions that you're not planning to use.
Removed, thanks.
On Mon Jun 16 12:22:25 2025 +0000, Nikolay Sivov wrote:
Then let's limit this only to changes you're going to need. So PSGetPropertyKeyFromName and PSGetNameFromPropertyKey, and maybe GetPropertyDescription() if you really need it. If you're not sure if propsys is enough for your case, you can always prototype on Windows using setupapi directly + those propsys functions, and see if results are the same as what you get from Devices.Enumeration.
Done. The only changes are to `PSGetPropertyKeyFromName`, `PSGetNameFromPropertyKey`, and a basic implementation for `IPropertyDescription`/`GetPropertyDescription`.