From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/propertyset.c | 69 +++++++++++++++++++++++++++++++++- dlls/wintypes/tests/wintypes.c | 8 ---- 2 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index ad4d54a9cfb..0b2afdff8af 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -24,14 +24,42 @@
#include "private.h"
+#include <wine/rbtree.h> + WINE_DEFAULT_DEBUG_CHANNEL( wintypes );
+struct map_entry +{ + struct rb_entry entry; + HSTRING key; + IInspectable *value; +}; + +static int map_entry_compare( const void *key, const struct rb_entry *entry ) +{ + INT32 order; + + WindowsCompareStringOrdinal( (HSTRING)key, (HSTRING)RB_ENTRY_VALUE( entry, struct map_entry, entry )->key, &order ); + return order; +} + +static void map_entry_destroy( struct rb_entry *entry, void *data ) +{ + struct map_entry *map_entry = RB_ENTRY_VALUE( entry, struct map_entry, entry ); + + WindowsDeleteString( map_entry->key ); + IInspectable_Release( map_entry->value ); + free( entry ); +} + struct propertyset { IPropertySet IPropertySet_iface; IObservableMap_HSTRING_IInspectable IObservableMap_HSTRING_IInspectable_iface; IMap_HSTRING_IInspectable IMap_HSTRING_IInspectable_iface; IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + SRWLOCK lock; + struct rb_tree entries; /* Guarded by lock */ LONG ref; };
@@ -97,7 +125,10 @@ static ULONG STDMETHODCALLTYPE propertyset_Release( IPropertySet *iface )
ref = InterlockedDecrement( &impl->ref ); if (!ref) + { + rb_destroy( &impl->entries, map_entry_destroy, NULL ); free( impl ); + } return ref; }
@@ -191,8 +222,40 @@ static HRESULT STDMETHODCALLTYPE propertyset_GetView( IMap_HSTRING_IInspectable
static HRESULT STDMETHODCALLTYPE propertyset_Insert( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable *value, boolean *replaced ) { - FIXME( "(%p, %s, %p, %p) stub!\n", iface, debugstr_hstring( key ), value, replaced ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + struct map_entry *map_entry; + struct rb_entry *entry; + HRESULT hr = S_OK; + + TRACE( "(%p, %s, %p, %p)\n", iface, debugstr_hstring( key ), value, replaced ); + + *replaced = FALSE; + AcquireSRWLockExclusive( &impl->lock ); + if (!(entry = rb_get( &impl->entries, key ))) + { + if (!(map_entry = calloc( 1, sizeof( *map_entry ) ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + if (FAILED(hr = WindowsDuplicateString( key, &map_entry->key ))) + { + free( map_entry ); + goto done; + } + rb_put( &impl->entries, key, &map_entry->entry ); + } + else + { + map_entry = RB_ENTRY_VALUE( entry, struct map_entry, entry ); + IInspectable_Release( map_entry->value ); + *replaced = TRUE; + } + map_entry->value = value; + IInspectable_AddRef( value ); +done: + ReleaseSRWLockExclusive( &impl->lock ); + return hr; }
static HRESULT STDMETHODCALLTYPE propertyset_Remove( IMap_HSTRING_IInspectable *iface, HSTRING key ) @@ -327,6 +390,8 @@ static HRESULT STDMETHODCALLTYPE factory_ActivateInstance( IActivationFactory *i impl->IObservableMap_HSTRING_IInspectable_iface.lpVtbl = &propertyset_IObservableMap_vtbl; impl->IMap_HSTRING_IInspectable_iface.lpVtbl = &propertyset_IMap_vtbl; impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &iterable_kvpair_HSTRING_IInspectable_vtbl; + InitializeSRWLock( &impl->lock ); + rb_init( &impl->entries, map_entry_compare ); impl->ref = 1; *instance = (IInspectable *)&impl->IPropertySet_iface; return S_OK; diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 0d8d80ac372..9e1d81404fe 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -1327,9 +1327,7 @@ static void test_IPropertySet(void) ok( hr == S_OK, "CreateUInt32 failed, got %#lx\n", hr ); boolean = TRUE; hr = IMap_HSTRING_IInspectable_Insert( map, NULL, val1, &boolean ); - todo_wine ok( hr == S_OK, "Insert failed, got %#lx\n", hr ); - todo_wine ok( !boolean, "Got boolean %d.\n", boolean );
hr = IPropertyValueStatics_CreateUInt32( propval_statics, 0xc0decafe, &val2 ); @@ -1337,9 +1335,7 @@ static void test_IPropertySet(void) boolean = FALSE; hr = IMap_HSTRING_IInspectable_Insert( map, NULL, val2, &boolean ); IInspectable_Release( val2 ); - todo_wine ok( boolean, "Got boolean %d.\n", boolean ); - todo_wine ok( hr == S_OK, "Insert failed, got %#lx\n", hr ); boolean = FALSE; hr = IMap_HSTRING_IInspectable_HasKey( map, NULL, &boolean ); @@ -1372,9 +1368,7 @@ static void test_IPropertySet(void) ok( hr == E_BOUNDS, "Got hr %#lx\n", hr ); hr = IMap_HSTRING_IInspectable_Insert( map, key1, val1, &boolean ); IInspectable_Release( val1 ); - todo_wine ok( hr == S_OK, "Insert failed, got %#lx\n", hr ); - todo_wine ok( !boolean, "Got boolean %d.\n", boolean ); boolean = FALSE; hr = IMap_HSTRING_IInspectable_HasKey( map, key1, &boolean ); @@ -1413,9 +1407,7 @@ static void test_IPropertySet(void) boolean = TRUE; hr = IMap_HSTRING_IInspectable_Insert( map, key2, val3, &boolean ); IInspectable_Release( val3 ); - todo_wine ok( hr == S_OK, "Insert failed, got %#lx\n", hr ); - todo_wine ok( !boolean, "Got boolean %d.\n", boolean ); boolean = FALSE; hr = IMap_HSTRING_IInspectable_HasKey( map, key2, &boolean );