From: Vibhav Pant vibhavp@gmail.com
--- dlls/propsys/propsys_main.c | 118 +++++++++++++++++++++++++++++++---- dlls/propsys/tests/propsys.c | 14 ++--- 2 files changed, 113 insertions(+), 19 deletions(-)
diff --git a/dlls/propsys/propsys_main.c b/dlls/propsys/propsys_main.c index 643673c19d8..67131e37dea 100644 --- a/dlls/propsys/propsys_main.c +++ b/dlls/propsys/propsys_main.c @@ -28,6 +28,7 @@ #include "objbase.h" #include "rpcproxy.h" #include "propsys.h" +#include "propkey.h" #include "wine/debug.h"
#include "propsys_private.h" @@ -154,7 +155,8 @@ static ULONG WINAPI propsys_Release(IPropertySystem *iface) return 1; }
-static HRESULT propdesc_from_system_property( IPropertyDescription **out ); +static HRESULT propdesc_get_by_name( const WCHAR *name, IPropertyDescription **desc ); +static HRESULT propdesc_get_by_key( const PROPERTYKEY *key, IPropertyDescription **desc );
static HRESULT WINAPI propsys_GetPropertyDescription(IPropertySystem *iface, REFPROPERTYKEY propkey, REFIID riid, void **ppv) @@ -167,7 +169,7 @@ static HRESULT WINAPI propsys_GetPropertyDescription(IPropertySystem *iface, if (!ppv) return E_INVALIDARG; *ppv = NULL; - hr = propdesc_from_system_property( &desc ); + hr = propdesc_get_by_key( propkey, &desc ); if (FAILED( hr )) return hr;
@@ -187,7 +189,7 @@ static HRESULT WINAPI propsys_GetPropertyDescriptionByName(IPropertySystem *ifac if (!ppv) return E_INVALIDARG; *ppv = NULL; - hr = propdesc_from_system_property( &desc ); + hr = propdesc_get_by_name( canonical_name, &desc ); if (FAILED( hr )) return hr; hr = IPropertyDescription_QueryInterface( desc, riid, ppv ); @@ -572,6 +574,12 @@ HRESULT WINAPI PSCreateMemoryPropertyStore(REFIID riid, void **ppv) struct property_description { IPropertyDescription IPropertyDescription_iface; + + WCHAR *canonical_name; + PROPERTYKEY key; + VARTYPE type; + PROPDESC_TYPE_FLAGS type_flags; + LONG ref; };
@@ -613,27 +621,42 @@ static ULONG WINAPI propdesc_Release( IPropertyDescription *iface ) TRACE( "(%p)\n", iface ); ref = InterlockedDecrement( &propdesc->ref ); if (!ref) + { + free( propdesc->canonical_name ); free( propdesc ); + }
return ref; }
static HRESULT WINAPI propdesc_GetPropertyKey( IPropertyDescription *iface, PROPERTYKEY *pkey ) { - FIXME( "(%p, %p) stub!\n", iface, pkey ); - return E_NOTIMPL; + struct property_description *propdesc = impl_from_IPropertyDescription( iface ); + + TRACE( "(%p, %p)\n", iface, pkey ); + *pkey = propdesc->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 *propdesc = impl_from_IPropertyDescription( iface ); + + TRACE( "(%p, %p)\n", iface, name ); + *name = CoTaskMemAlloc( (wcslen( propdesc->canonical_name ) + 1) * sizeof( WCHAR ) ); + if (!*name) + return E_OUTOFMEMORY; + wcscpy( *name, propdesc->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 *propdesc = impl_from_IPropertyDescription( iface ); + + TRACE( "(%p, %p)\n", iface, vt ); + *vt = propdesc->type; + return S_OK; }
static HRESULT WINAPI propdesc_GetDisplayName( IPropertyDescription *iface, LPWSTR *name ) @@ -651,7 +674,10 @@ 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 *propdesc = impl_from_IPropertyDescription( iface ); + + TRACE( "(%p, %#x, %p)\n", iface, mask, flags ); + *flags = mask & propdesc->type_flags; return E_NOTIMPL; }
@@ -780,16 +806,84 @@ 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 *propdesc;
- if (!(propdesc = calloc( 1, sizeof( *propdesc ) ))) + propdesc = calloc( 1, sizeof( *propdesc ) ); + if (!propdesc) return E_OUTOFMEMORY;
propdesc->IPropertyDescription_iface.lpVtbl = &property_description_vtbl; + if (!(propdesc->canonical_name = wcsdup( desc->canonical_name ))) + { + free( propdesc ); + return E_OUTOFMEMORY; + } + propdesc->key = *desc->key; + propdesc->type = desc->type; + propdesc->type_flags = PDTF_ISINNATE; + if (propdesc->type & VT_VECTOR) + propdesc->type_flags |= PDTF_MULTIPLEVALUES; propdesc->ref = 1;
*out = &propdesc->IPropertyDescription_iface; return S_OK; } + +static HRESULT propdesc_get_by_name( const WCHAR *name, IPropertyDescription **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; +} + +static HRESULT propdesc_get_by_key( const PROPERTYKEY *key, IPropertyDescription **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 921e612da5d..7048e0e8f14 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -3020,14 +3020,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); @@ -3035,13 +3035,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)); @@ -3049,14 +3049,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); @@ -3067,7 +3067,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();