-- v21: wintypes: Add stubs for IKeyValuePair<HSTRING, IInspectable *>. wintypes: Add stubs for IIterator<IKeyValuePair<HSTRING, IInspectable *>>. wintypes: Add stubs for IMapView<HSTRING, IInspectable *>. wintypes: Add stubs for IMap<HSTRING, IInspectable *>, IObservableMap<HSTRING, IInspectable *>, IIterable<IKeyValuePair<HSTRING, IInspectable *>> to PropertySet implementation. wintypes: Add stub for Windows.Foundation.Collections.PropertySet. wintypes/test: Add conformance tests for Windows.Foundation.Collections.PropertySet. include: Add Windows.Foundation.Collections.PropertySet runtime class.
From: Vibhav Pant vibhavp@gmail.com
--- include/windows.foundation.idl | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 9e3b656d8a3..c6c4c491236 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -57,6 +57,20 @@ namespace Windows.Foundation.Collections { { }
+ [ + activatable(Windows.Foundation.FoundationContract, 1.0), + contract(Windows.Foundation.FoundationContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass PropertySet + { + [default] interface Windows.Foundation.Collections.IPropertySet; + interface Windows.Foundation.Collections.IObservableMap<HSTRING, IInspectable *>; + interface Windows.Foundation.Collections.IMap<HSTRING, IInspectable *>; + interface Windows.Foundation.Collections.IIterable<Windows.Foundation.Collections.IKeyValuePair<HSTRING, IInspectable *> *>; + } + [ activatable(Windows.Foundation.FoundationContract, 1.0), contract(Windows.Foundation.FoundationContract, 1.0),
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/tests/Makefile.in | 1 + dlls/wintypes/tests/propertyset.c | 583 ++++++++++++++++++++++++++ dlls/wintypes/tests/wintypes.c | 2 + dlls/wintypes/tests/wintypes_test.idl | 10 + 4 files changed, 596 insertions(+) create mode 100644 dlls/wintypes/tests/propertyset.c
diff --git a/dlls/wintypes/tests/Makefile.in b/dlls/wintypes/tests/Makefile.in index c5ae17c4694..afb4fd4a7f5 100644 --- a/dlls/wintypes/tests/Makefile.in +++ b/dlls/wintypes/tests/Makefile.in @@ -2,5 +2,6 @@ TESTDLL = wintypes.dll IMPORTS = wintypes combase uuid
SOURCES = \ + propertyset.c \ wintypes.c \ wintypes_test.idl diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c new file mode 100644 index 00000000000..3dbf95940f3 --- /dev/null +++ b/dlls/wintypes/tests/propertyset.c @@ -0,0 +1,583 @@ +/* + * 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 "winstring.h" +#include "roapi.h" +#include "ole2.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#include "wintypes_test.h" + +#include "wine/test.h" + +static const WCHAR *class_name = RuntimeClass_Windows_Foundation_Collections_PropertySet; +static const struct DateTime datetime_value = {0x12345678abcdef}; +static const struct TimeSpan timespan_value = {0x12345678abcdef}; +static const struct Point point_value = {1, 2}; +static const struct Size size_value = {1, 2}; +static const struct Rect rect_value = {1, 2, 3, 4}; + +#define DEFINE_IUNKNOWN_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } +#define DEFINE_IUNKNOWN( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IUNKNOWN_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, \ + &impl->base_iface ) + +struct propset_changed_event_handler +{ + IWinePropertySetChangedEventHandler IWinePropertySetChangedEventHandler_iface; + IMapChangedEventHandler_HSTRING_IInspectable IMapChangedEventHandler_HSTRING_IInspectable_iface; + + CollectionChange expected; + + LONG invoked; + LONG ref; +}; + +static inline struct propset_changed_event_handler * +impl_from_IWinePropertySetChangedEventHandler( IWinePropertySetChangedEventHandler *iface ) +{ + return CONTAINING_RECORD( iface, struct propset_changed_event_handler, + IWinePropertySetChangedEventHandler_iface ); +} + +static HRESULT STDMETHODCALLTYPE propset_changed_event_handler_QueryInterface( + IWinePropertySetChangedEventHandler *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IWinePropertySetChangedEventHandler )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + if (IsEqualGUID( iid, &IID_IMapChangedEventHandler_HSTRING_IInspectable )) + { + struct propset_changed_event_handler *impl = + impl_from_IWinePropertySetChangedEventHandler( iface ); + *out = &impl->IMapChangedEventHandler_HSTRING_IInspectable_iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE +propset_changed_event_handler_AddRef( IWinePropertySetChangedEventHandler *iface ) +{ + struct propset_changed_event_handler *impl = + impl_from_IWinePropertySetChangedEventHandler( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG STDMETHODCALLTYPE +propset_changed_event_handler_Release( IWinePropertySetChangedEventHandler *iface ) +{ + struct propset_changed_event_handler *impl = + impl_from_IWinePropertySetChangedEventHandler( iface ); + ULONG ref; + + ref = InterlockedDecrement( &impl->ref ); + if (!ref) + free( impl ); + return ref; +} + +static HRESULT STDMETHODCALLTYPE propset_changed_event_handler_get_TimesInvoked( + IWinePropertySetChangedEventHandler *iface, ULONG *times ) +{ + struct propset_changed_event_handler *impl = + impl_from_IWinePropertySetChangedEventHandler( iface ); + *times = impl->invoked; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE propset_changed_event_handler_Reset( IWinePropertySetChangedEventHandler *iface ) +{ + struct propset_changed_event_handler *impl = + impl_from_IWinePropertySetChangedEventHandler( iface ); + InterlockedExchange( &impl->invoked, 0 ); + return S_OK; +} + +const static IWinePropertySetChangedEventHandlerVtbl propset_changed_event_handler_vtbl = +{ + /* IUnknown */ + propset_changed_event_handler_QueryInterface, + propset_changed_event_handler_AddRef, + propset_changed_event_handler_Release, + /* IWinePropertySetChangedEventHandlerVtbl */ + propset_changed_event_handler_get_TimesInvoked, + propset_changed_event_handler_Reset, +}; + +DEFINE_IUNKNOWN( map_changed_event_handler, IMapChangedEventHandler_HSTRING_IInspectable, + struct propset_changed_event_handler, + IWinePropertySetChangedEventHandler_iface ); + +static HRESULT STDMETHODCALLTYPE map_changed_event_handler_Invoke( + IMapChangedEventHandler_HSTRING_IInspectable *iface, IObservableMap_HSTRING_IInspectable *map, + IMapChangedEventArgs_HSTRING *event_args ) +{ + struct propset_changed_event_handler *impl; + CollectionChange got; + HRESULT hr; + HSTRING key; + + impl = impl_from_IMapChangedEventHandler_HSTRING_IInspectable( iface ); + hr = IMapChangedEventArgs_HSTRING_get_CollectionChanged( event_args, &got ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + hr = IMapChangedEventArgs_HSTRING_get_Key( event_args, &key ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + if (impl->expected == got) + InterlockedIncrement( &impl->invoked ); + return S_OK; +} + +const static IMapChangedEventHandler_HSTRING_IInspectableVtbl map_changed_event_handler_vtbl = +{ + /* IUnknown */ + map_changed_event_handler_QueryInterface, + map_changed_event_handler_AddRef, + map_changed_event_handler_Release, + /* IMapChangedEventHandler<HSTRING, IInspectable*> */ + map_changed_event_handler_Invoke, +}; + +HRESULT propertyset_changed_event_handler_create( CollectionChange change, + IMapChangedEventHandler_HSTRING_IInspectable **out ) +{ + struct propset_changed_event_handler *impl; + + impl = calloc( 1, sizeof( *impl ) ); + if (!impl) + return E_OUTOFMEMORY; + impl->IWinePropertySetChangedEventHandler_iface.lpVtbl = &propset_changed_event_handler_vtbl; + impl->IMapChangedEventHandler_HSTRING_IInspectable_iface.lpVtbl = + &map_changed_event_handler_vtbl; + impl->expected = change; + impl->ref = 1; + + *out = &impl->IMapChangedEventHandler_HSTRING_IInspectable_iface; + return S_OK; +} + +static void test_IPropertySet(void) +{ + IActivationFactory *factory; + IInspectable *inspectable; + IPropertyValueStatics *statics; + IPropertySet *propset; + IMap_HSTRING_IInspectable *map; + IMapView_HSTRING_IInspectable *map_view, *first_view = NULL, *second_view = NULL; + IIterable_IKeyValuePair_HSTRING_IInspectable *iterable; + IIterator_IKeyValuePair_HSTRING_IInspectable *iterator; + IMapChangedEventHandler_HSTRING_IInspectable *handler_inserted = NULL, *handler_changed = NULL, + *handler_removed = NULL, *handler_reset = NULL; + EventRegistrationToken token_inserted = {0}, token_changed = {0}, token_removed = {0}, + token_reset = {0}; + IObservableMap_HSTRING_IInspectable *observable_map; + unsigned int size, prev_size; + boolean valid; + HRESULT hr; + HSTRING name; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + + hr = WindowsCreateString( class_name, wcslen( class_name ), &name ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + hr = RoGetActivationFactory( name, &IID_IActivationFactory, (void **)&factory ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), + "RoGetActivationFactory failed, hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", + wine_dbgstr_w( class_name ) ); + WindowsDeleteString( name ); + RoUninitialize(); + return; + } + WindowsDeleteString( name ); + class_name = RuntimeClass_Windows_Foundation_PropertyValue; + hr = WindowsCreateString( class_name, wcslen( class_name ), &name ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + hr = RoGetActivationFactory( name, &IID_IPropertyValueStatics, (void **)&statics ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), + "RoGetActivationFactory failed, hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", + wine_dbgstr_w( class_name ) ); + WindowsDeleteString( name ); + RoUninitialize(); + return; + } + WindowsDeleteString( name ); + + hr = IActivationFactory_ActivateInstance( factory, &inspectable ); + IActivationFactory_Release( factory ); + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + if (FAILED( hr )) + { + skip("could not activate PropertySet instance.\n"); + IPropertyValueStatics_Release( statics ); + RoUninitialize(); + return; + } + + hr = IInspectable_QueryInterface( inspectable, &IID_IPropertySet, (void **)&propset ); + IInspectable_Release( inspectable ); + todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + if (FAILED( hr )) + { + IPropertyValueStatics_Release( statics ); + RoUninitialize(); + return; + } + + hr = IPropertySet_QueryInterface( propset, &IID_IMap_HSTRING_IInspectable, (void **)&map ); + todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + if (FAILED( hr )) + { + IPropertyValueStatics_Release( statics ); + RoUninitialize(); + return; + } + + hr = IPropertySet_QueryInterface( propset, &IID_IObservableMap_HSTRING_IInspectable, + (void *)&observable_map ); + IPropertySet_Release(propset); + todo_wine ok(SUCCEEDED(hr), "QueryInterface failed, got %#lx\n", hr); + +#define EVENT_HANDLER_CREATE(t, c) \ + do \ + { \ + hr = propertyset_changed_event_handler_create( (c), &handler_##t); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr); \ + if (FAILED( hr )) break; \ + hr = IObservableMap_HSTRING_IInspectable_add_MapChanged( observable_map, \ + handler_##t, \ + &token_##t ); \ + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr); \ + } while(0) + + if (SUCCEEDED( hr )) + { + EVENT_HANDLER_CREATE( inserted, CollectionChange_ItemInserted ); + EVENT_HANDLER_CREATE( changed, CollectionChange_ItemChanged ); + EVENT_HANDLER_CREATE( removed, CollectionChange_ItemRemoved ); + EVENT_HANDLER_CREATE( reset, CollectionChange_Reset ); + } + else + skip( "could not obtain an IObservableMap<HSTRING, IInspectable *> instance.\n" ); + +#define TEST_MAP_VALUES \ + MAP_TEST( Boolean, 1, boolean ); \ + MAP_TEST( UInt16, 0xdead, UINT16 ); \ + MAP_TEST( Int16, 0xdead, INT16 ); \ + MAP_TEST( UInt32, 0xdeadbeef, UINT32 ); \ + MAP_TEST( Int32, 0xdeadbeef, INT32 ); \ + MAP_TEST( UInt64, 0xdeadbeefdeadbeef, UINT64 ); \ + MAP_TEST( Int64, 0xdeadbeefdeadbeef, INT64 ); \ + MAP_TEST( Single, 1.5, FLOAT ); \ + MAP_TEST( Double, 2.5, DOUBLE ); \ + MAP_TEST( DateTime, datetime_value, struct DateTime ); \ + MAP_TEST( TimeSpan, timespan_value, struct TimeSpan ); \ + MAP_TEST( Point, point_value, struct Point ); \ + MAP_TEST( Size, size_value, struct Size ); \ + MAP_TEST( Rect, rect_value, struct Rect ); \ + MAP_TEST( Guid, IID_IPropertyValue, GUID ) + +#define STR_(a) L###a +#define STR(a) STR_(a) +#define MAP_TEST( t, v, ct ) \ + do \ + { \ + HSTRING key; \ + IInspectable *value; \ + boolean replace; \ + const static WCHAR *str = STR( t ); \ + unsigned int cur_size; \ + ct data_val; \ + memset( &data_val, 0, sizeof( ct ) ); \ + hr = WindowsCreateString( str, wcslen( str ), &key ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED( hr )) break; \ + hr = IPropertyValueStatics_Create##t( statics, data_val, &value ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED( hr )) \ + { \ + WindowsDeleteString( key ); \ + break; \ + } \ + hr = IMap_HSTRING_IInspectable_Insert( map, key, value, &replace ); \ + IInspectable_Release( value ); \ + todo_wine ok( SUCCEEDED( hr ), "Insert failed, got %#lx\n", hr ); \ + if (SUCCEEDED( hr )) ok( !replace, "%d != 0\n", replace ); \ + hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); \ + todo_wine ok( SUCCEEDED( hr ), "get_Size failed, got %#lx\n", hr ); \ + if (SUCCEEDED( hr )) ok( size == prev_size + 1, "%u != %u\n", size, prev_size + 1 ); \ + prev_size = cur_size = size; \ + hr = IPropertyValueStatics_Create##t( statics, ( v ), &value ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED( hr )) \ + { \ + WindowsDeleteString( key ); \ + break; \ + } \ + hr = IMap_HSTRING_IInspectable_Insert( map, key, value, &replace ); \ + IInspectable_Release( value ); \ + todo_wine ok( SUCCEEDED( hr ), "Insert failed, got %#lx\n", hr ); \ + todo_wine ok( replace, "%d is not non-zero\n", replace ); \ + hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); \ + todo_wine ok( SUCCEEDED( hr ), "get_Size failed, got %#lx\n", hr); \ + if (SUCCEEDED( hr )) ok( size == cur_size, "%u != %u\n", size, cur_size ); \ + } while (0) + + prev_size = 0; + TEST_MAP_VALUES; + +#define TEST_EVENT_HANDLER(t, v) \ + do \ + { \ + IWinePropertySetChangedEventHandler *handler; \ + ULONG invoked; \ + if (!(handler_##t) || !(token_##t.value)) break; \ + hr = IUnknown_QueryInterface( (handler_##t), \ + &IID_IWinePropertySetChangedEventHandler, \ + (void **)&handler ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED(hr)) break; \ + hr = IWinePropertySetChangedEventHandler_get_TimesInvoked( handler, &invoked ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr); \ + todo_wine ok( invoked == (v), "%lu != %lu\n", invoked, (ULONG)(v)); \ + hr = IWinePropertySetChangedEventHandler_Reset( handler ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + } while(0); + + TEST_EVENT_HANDLER( inserted, 15 ); + TEST_EVENT_HANDLER( changed, 15 ); + + hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); + todo_wine ok( SUCCEEDED( hr ), "get_Size failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) ok( size == 15, "%u != 15\n", size ); + hr = IMap_HSTRING_IInspectable_Clear( map ); + todo_wine ok( SUCCEEDED( hr ), "Clear failed, got %#lx\n", hr ); + TEST_EVENT_HANDLER( reset, 1 ); + hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); + todo_wine ok( SUCCEEDED( hr ), "get_Size failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) ok( size == 0, "%u != 0\n", size ); + + prev_size = 0; + TEST_MAP_VALUES; + + hr = IMap_HSTRING_IInspectable_QueryInterface( + map, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&iterable ); + todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) + { + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + + size = 15; + valid = 1; + while (valid) + { + + IKeyValuePair_HSTRING_IInspectable *kvpair; + HSTRING key; + IInspectable *value; + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iterator, &kvpair ); + todo_wine ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); + hr = IKeyValuePair_HSTRING_IInspectable_get_Key( kvpair, &key ); + todo_wine ok( SUCCEEDED( hr ), "get_Key failed, got %#lx\n", hr ); + WindowsDeleteString( key ); + hr = IKeyValuePair_HSTRING_IInspectable_get_Value( kvpair, &value ); + todo_wine ok( SUCCEEDED( hr ), "get_Value failed, got %#lx\n", hr ); + IInspectable_Release( value ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iterator, &valid ); + todo_wine ok( SUCCEEDED( hr ), "MoveNext failed, got %#lx\n", hr ); + size--; + } + todo_wine ok( size == 0, "%d != 0\n", size ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_HasCurrent( iterator, &valid ); + todo_wine ok( SUCCEEDED( hr ), "get_HasCurrent failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) ok( !valid, "%d is non-zero\n", valid ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + } + else + skip( "Could not obtain IIterable<IKeyValuePair<HSTRING, IInspectable *>> instance.\n"); + +#undef MAP_TEST +#define MAP_TEST(t, v, ct) \ + MAP_TEST_(PropertyType_##t, IPropertyValue_Get##t, IMap, map, STR(t), v, ct) + +#define MAP_TEST_( pt, pg, mi, m, k, v, ct ) \ + do \ + { \ + const static WCHAR *str = (k); \ + HSTRING key; \ + IInspectable *inspect; \ + IPropertyValue *value; \ + PropertyType type; \ + boolean exists; \ + ct data_expect = (v); \ + ct data_got; \ + hr = WindowsCreateString( str, wcslen( str ), &key ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED( hr )) break; \ + hr = mi##_HSTRING_IInspectable_HasKey( (m), key, &exists ); \ + todo_wine ok( SUCCEEDED( hr ), "HasKey failed, got %#lx\n", hr ); \ + todo_wine ok( exists, "expected map to have key %s\n", debugstr_w( str ) ); \ + hr = mi##_HSTRING_IInspectable_Lookup( (m), key, &inspect ); \ + WindowsDeleteString( key ); \ + todo_wine ok( SUCCEEDED( hr ), "Lookup failed, got %#lx\n", hr ); \ + if (FAILED( hr )) break; \ + hr = IInspectable_QueryInterface( inspect, &IID_IPropertyValue, (void **)&value ); \ + IInspectable_Release( inspect ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + IPropertyValue_get_Type( value, &type ); \ + ok( type == (pt), "%d != %d\n", type, (pt) ); \ + hr = (pg)( value, &data_got ); \ + ok( !memcmp( &data_expect, &data_got, sizeof( ct ) ), "Got unexpected value.\n" ); \ + IPropertyValue_Release( value ); \ + } while (0) + + TEST_MAP_VALUES; + +#undef MAP_TEST +#define MAP_TEST(t, v, ct) \ + MAP_TEST_(PropertyType_##t, IPropertyValue_Get##t, IMapView, map_view, STR(t), v, ct) + + hr = IMap_HSTRING_IInspectable_GetView( map, &map_view ); + todo_wine ok( SUCCEEDED( hr ), "GetView failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) + { + TEST_MAP_VALUES; + + hr = IMapView_HSTRING_IInspectable_QueryInterface( + map_view, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&iterable ); + todo_wine ok( SUCCEEDED( hr ), "QuerInterface failed, got %#lx\n", hr ); + if (iterable) + { + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + size = 15; + valid = 1; + while (valid && iterator) + { + + IKeyValuePair_HSTRING_IInspectable *kvpair; + HSTRING key; + IInspectable *value; + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iterator, &kvpair ); + todo_wine ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); + if (FAILED( hr )) break; + hr = IKeyValuePair_HSTRING_IInspectable_get_Key( kvpair, &key ); + todo_wine ok( SUCCEEDED( hr ), "get_Key failed, got %#lx\n", hr ); + WindowsDeleteString( key ); + hr = IKeyValuePair_HSTRING_IInspectable_get_Value( kvpair, &value ); + todo_wine ok( SUCCEEDED( hr ), "get_Value failed, got %#lx\n", hr ); + IInspectable_Release( value ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iterator, &valid ); + todo_wine ok( SUCCEEDED( hr ), "MoveNext failed, got %#lx\n", hr ); + size--; + } + todo_wine ok( size == 0, "%d != 0\n", size ); + if (iterator) + { + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_HasCurrent( iterator, &valid ); + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + if (SUCCEEDED( hr )) ok( !valid, "%d is non-zero\n", valid ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + } + } + + hr = IMapView_HSTRING_IInspectable_Split( map_view, &first_view, &second_view ); + todo_wine ok( SUCCEEDED( hr ), "Split failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) + ok( !first_view && !second_view, "Expected %p and %p to be NULL\n", first_view, + second_view ); + IMapView_HSTRING_IInspectable_Release( map_view ); + } + +#undef MAP_TEST +#undef MAP_TEST_ +#define MAP_TEST(t, v, ct) MAP_TEST_(STR(t)) +#define MAP_TEST_( k ) \ + do \ + { \ + const static WCHAR *str = ( k ); \ + HSTRING key; \ + IInspectable *inspect; \ + boolean exists; \ + hr = WindowsCreateString( str, wcslen( str ), &key ); \ + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (FAILED( hr )) break; \ + hr = IMap_HSTRING_IInspectable_Remove( map, key ); \ + todo_wine ok( SUCCEEDED( hr ), "Remove failed, got %#lx\n", hr ); \ + hr = IMap_HSTRING_IInspectable_HasKey( map, key, &exists ); \ + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \ + if (SUCCEEDED( hr )) ok( !exists, "expected map to not have key %s\n", debugstr_w( str ) ); \ + hr = IMap_HSTRING_IInspectable_Lookup( map, key, &inspect ); \ + WindowsDeleteString( key ); \ + todo_wine ok( hr == E_BOUNDS, "got %#lx != %#lx\n", hr, E_BOUNDS ); \ + } while (0) + + TEST_MAP_VALUES; + TEST_EVENT_HANDLER( removed, 15 ); + hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); + todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + if (SUCCEEDED( hr )) ok( size == 0, "%u != 0\n", size ); + + IObservableMap_HSTRING_IInspectable_Release( observable_map ); + IMap_HSTRING_IInspectable_Release( map ); + IPropertyValueStatics_Release( statics ); + RoUninitialize(); +} + +START_TEST(propertyset) +{ + test_IPropertySet(); +} diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index cb24dee77cf..4a70c184ef8 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -28,7 +28,9 @@ #include "rometadataresolution.h"
#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections #define WIDL_using_Windows_Foundation_Metadata +#include "windows.foundation.collections.h" #include "windows.foundation.metadata.h" #include "wintypes_test.h"
diff --git a/dlls/wintypes/tests/wintypes_test.idl b/dlls/wintypes/tests/wintypes_test.idl index 33cfbed210b..2180604d304 100644 --- a/dlls/wintypes/tests/wintypes_test.idl +++ b/dlls/wintypes/tests/wintypes_test.idl @@ -26,4 +26,14 @@ import "windows.foundation.idl";
declare { interface Windows.Foundation.IReference<HSTRING>; + interface Windows.Foundation.Collections.MapChangedEventHandler<HSTRING, IInspectable*>; } + +[ + uuid(7e860ccf-d9d0-4fbb-87a9-aa6c26f7f6ec) +] +interface IWinePropertySetChangedEventHandler : IUnknown + requires Windows.Foundation.Collections.MapChangedEventHandler<HSTRING, IInspectable *> { + [propget] HRESULT TimesInvoked([out, retval] ULONG *times); + HRESULT Reset(); +};
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/Makefile.in | 1 + dlls/wintypes/main.c | 32 ++++++- dlls/wintypes/propertyset.c | 136 +++++++++++++++++++++++++++++ dlls/wintypes/tests/propertyset.c | 4 +- dlls/wintypes/wintypes_private.idl | 2 + 5 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 dlls/wintypes/propertyset.c
diff --git a/dlls/wintypes/Makefile.in b/dlls/wintypes/Makefile.in index b8958cdcd15..baba92dd6e3 100644 --- a/dlls/wintypes/Makefile.in +++ b/dlls/wintypes/Makefile.in @@ -5,4 +5,5 @@ IMPORTS = combase SOURCES = \ classes.idl \ main.c \ + propertyset.c \ wintypes_private.idl diff --git a/dlls/wintypes/main.c b/dlls/wintypes/main.c index ac4214b486f..44606e57bd4 100644 --- a/dlls/wintypes/main.c +++ b/dlls/wintypes/main.c @@ -31,6 +31,7 @@
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Metadata +#define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.metadata.h" #include "wintypes_private.h"
@@ -60,6 +61,7 @@ static BOOLEAN is_api_contract_present( const HSTRING hname, unsigned int versio struct wintypes { IActivationFactory IActivationFactory_iface; + IActivationFactory IPropertySet_IActivationFactory_iface; IApiInformationStatics IApiInformationStatics_iface; IPropertyValueStatics IPropertyValueStatics_iface; LONG ref; @@ -150,6 +152,13 @@ static HRESULT STDMETHODCALLTYPE wintypes_ActivateInstance(IActivationFactory *i return E_NOTIMPL; }
+static HRESULT STDMETHODCALLTYPE propertyset_factory_ActivateInstance(IActivationFactory *iface, + IInspectable **instance) +{ + TRACE("iface %p, instance %p\n", iface, instance); + return propertyset_create((IPropertySet **)instance); +} + static const struct IActivationFactoryVtbl activation_factory_vtbl = { wintypes_QueryInterface, @@ -163,6 +172,19 @@ static const struct IActivationFactoryVtbl activation_factory_vtbl = wintypes_ActivateInstance, };
+static const struct IActivationFactoryVtbl propertyset_factory_vtbl = +{ + wintypes_QueryInterface, + wintypes_AddRef, + wintypes_Release, + /* IInspectable methods */ + wintypes_GetIids, + wintypes_GetRuntimeClassName, + wintypes_GetTrustLevel, + /* IActivationFactory methods */ + propertyset_factory_ActivateInstance, +}; + DEFINE_IINSPECTABLE(api_information_statics, IApiInformationStatics, struct wintypes, IActivationFactory_iface)
static HRESULT STDMETHODCALLTYPE api_information_statics_IsTypePresent( @@ -1200,6 +1222,7 @@ static const struct IPropertyValueStaticsVtbl property_value_statics_vtbl = static struct wintypes wintypes = { {&activation_factory_vtbl}, + {&propertyset_factory_vtbl}, {&api_information_statics_vtbl}, {&property_value_statics_vtbl}, 1 @@ -1213,8 +1236,15 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) { + const WCHAR *name; + TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory); - *factory = &wintypes.IActivationFactory_iface; + name = WindowsGetStringRawBuffer(classid, NULL); + + if (!wcscmp(name, RuntimeClass_Windows_Foundation_Collections_PropertySet)) + *factory = &wintypes.IPropertySet_IActivationFactory_iface; + else + *factory = &wintypes.IActivationFactory_iface; IUnknown_AddRef(*factory); return S_OK; } diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c new file mode 100644 index 00000000000..74c5b37be1f --- /dev/null +++ b/dlls/wintypes/propertyset.c @@ -0,0 +1,136 @@ +/* + * 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 <winstring.h> +#include <objbase.h> + +#include <wine/debug.h> + +#include <activation.h> + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "wintypes_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL( wintypes ); + +struct propertyset +{ + IPropertySet IPropertySet_iface; + + LONG ref; +}; + +static inline struct propertyset * +impl_from_IPropertySet( IPropertySet *iface ) +{ + return CONTAINING_RECORD( iface, struct propertyset, IPropertySet_iface ); +} + +static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface, REFIID iid, + void **out ) +{ + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + *out = NULL; + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IPropertySet )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE propertyset_AddRef( IPropertySet *iface ) +{ + struct propertyset *impl; + + TRACE( "(%p)\n", iface ); + + impl = impl_from_IPropertySet( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG STDMETHODCALLTYPE propertyset_Release( IPropertySet *iface ) +{ + struct propertyset *impl; + ULONG ref; + + TRACE( "(%p)\n", iface ); + + impl = impl_from_IPropertySet( iface ); + ref = InterlockedDecrement( &impl->ref ); + + if (!ref) + free( impl ); + return ref; +} + +static HRESULT STDMETHODCALLTYPE propertyset_GetIids( IPropertySet *iface, ULONG *iid_count, + IID **iids ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_GetRuntimeClassName( IPropertySet *iface, + HSTRING *class_name ) +{ + FIXME( "(%p, %p) stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_GetTrustLevel( IPropertySet *iface, + TrustLevel *trust_level ) +{ + FIXME( "(%p, %p) stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +const static IPropertySetVtbl propertyset_vtbl = +{ + /* IUnknown */ + propertyset_QueryInterface, + propertyset_AddRef, + propertyset_Release, + /* IInspectable */ + propertyset_GetIids, + propertyset_GetRuntimeClassName, + propertyset_GetTrustLevel, +}; + +HRESULT propertyset_create( IPropertySet **iface ) +{ + struct propertyset *impl; + + impl = calloc( 1, sizeof( *impl ) ); + if (!impl) + return E_OUTOFMEMORY; + + impl->IPropertySet_iface.lpVtbl = &propertyset_vtbl; + impl->ref = 1; + + *iface = &impl->IPropertySet_iface; + return S_OK; +} diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c index 3dbf95940f3..95a23462977 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -255,7 +255,7 @@ static void test_IPropertySet(void)
hr = IActivationFactory_ActivateInstance( factory, &inspectable ); IActivationFactory_Release( factory ); - todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); if (FAILED( hr )) { skip("could not activate PropertySet instance.\n"); @@ -266,7 +266,7 @@ static void test_IPropertySet(void)
hr = IInspectable_QueryInterface( inspectable, &IID_IPropertySet, (void **)&propset ); IInspectable_Release( inspectable ); - todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); if (FAILED( hr )) { IPropertyValueStatics_Release( statics ); diff --git a/dlls/wintypes/wintypes_private.idl b/dlls/wintypes/wintypes_private.idl index b0d7b7d2241..fea76193c2c 100644 --- a/dlls/wintypes/wintypes_private.idl +++ b/dlls/wintypes/wintypes_private.idl @@ -66,3 +66,5 @@ cpp_quote(" }")
cpp_quote("#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \") cpp_quote(" DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface )") + +cpp_quote("HRESULT propertyset_create(IPropertySet **);")
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/propertyset.c | 169 +++++++++++++++++++++++++++++- dlls/wintypes/tests/propertyset.c | 6 +- 2 files changed, 171 insertions(+), 4 deletions(-)
diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index 74c5b37be1f..ccbe30010fd 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -33,6 +33,9 @@ WINE_DEFAULT_DEBUG_CHANNEL( wintypes ); 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;
LONG ref; }; @@ -46,8 +49,11 @@ impl_from_IPropertySet( IPropertySet *iface ) static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface, REFIID iid, void **out ) { + struct propertyset *impl; + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out );
+ impl = impl_from_IPropertySet( iface ); *out = NULL; if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IInspectable ) || @@ -57,6 +63,24 @@ static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface IUnknown_AddRef( iface ); return S_OK; } + if (IsEqualGUID( iid, &IID_IObservableMap_HSTRING_IInspectable )) + { + *out = &impl->IObservableMap_HSTRING_IInspectable_iface; + IUnknown_AddRef( iface ); + return S_OK; + } + if (IsEqualGUID( iid, &IID_IMap_HSTRING_IInspectable )) + { + *out = &impl->IMap_HSTRING_IInspectable_iface; + IUnknown_AddRef( iface ); + return S_OK; + } + if (IsEqualGUID( iid, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable )) + { + *out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + IUnknown_AddRef( iface ); + return S_OK; + }
FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); return E_NOINTERFACE; @@ -84,6 +108,7 @@ static ULONG STDMETHODCALLTYPE propertyset_Release( IPropertySet *iface )
if (!ref) free( impl ); + return ref; }
@@ -120,6 +145,144 @@ const static IPropertySetVtbl propertyset_vtbl = propertyset_GetTrustLevel, };
+DEFINE_IINSPECTABLE( propertyset_IObservableMap, IObservableMap_HSTRING_IInspectable, + struct propertyset, IPropertySet_iface ); + +static HRESULT STDMETHODCALLTYPE propertyset_IObservableMap_add_MapChanged( + IObservableMap_HSTRING_IInspectable *iface, + IMapChangedEventHandler_HSTRING_IInspectable *handler, EventRegistrationToken *token ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_IObservableMap_remove_MapChanged( + IObservableMap_HSTRING_IInspectable *iface, EventRegistrationToken token ) +{ + FIXME( "(%p, %I64d)stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +const static IObservableMap_HSTRING_IInspectableVtbl propertyset_IObservableMap_vtbl = +{ + /* IUnknown */ + propertyset_IObservableMap_QueryInterface, + propertyset_IObservableMap_AddRef, + propertyset_IObservableMap_Release, + /* IInspectable */ + propertyset_IObservableMap_GetIids, + propertyset_IObservableMap_GetRuntimeClassName, + propertyset_IObservableMap_GetTrustLevel, + /* IObservableMap<HSTRING, IInspectable*> */ + propertyset_IObservableMap_add_MapChanged, + propertyset_IObservableMap_remove_MapChanged, +}; + +DEFINE_IINSPECTABLE( propertyset_IMap, IMap_HSTRING_IInspectable, struct propertyset, + IPropertySet_iface ); + +static HRESULT STDMETHODCALLTYPE propertyset_Lookup( IMap_HSTRING_IInspectable *iface, + HSTRING key, + IInspectable **value ) +{ + FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), value ); + *value = NULL; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +propertyset_get_size( IMap_HSTRING_IInspectable *iface, UINT32 *size ) +{ + FIXME( "(%p, %p) stub!\n", iface, size ); + *size = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_HasKey( IMap_HSTRING_IInspectable *iface, + HSTRING key, boolean *exists ) +{ + FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), exists ); + *exists = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_GetView( + IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **view ) +{ + FIXME( "(%p, %p) stub!\n", iface, view ); + *view = NULL; + return E_NOTIMPL; +} + +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 ); + *replaced = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_Remove( IMap_HSTRING_IInspectable *iface, + HSTRING key ) +{ + FIXME( "(%p, %s) stub!\n", iface, debugstr_hstring( key ) ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_Clear( IMap_HSTRING_IInspectable *iface ) +{ + FIXME( "(%p) stub!\n", iface ); + return E_NOTIMPL; +} + +const static IMap_HSTRING_IInspectableVtbl propertyset_IMap_vtbl = +{ + /* IUnknown */ + propertyset_IMap_QueryInterface, + propertyset_IMap_AddRef, + propertyset_IMap_Release, + /* IInspectable */ + propertyset_IMap_GetIids, + propertyset_IMap_GetRuntimeClassName, + propertyset_IMap_GetTrustLevel, + /* IMap<HSTRING, IInspectable*> */ + propertyset_Lookup, + propertyset_get_size, + propertyset_HasKey, + propertyset_GetView, + propertyset_Insert, + propertyset_Remove, + propertyset_Clear, +}; + +DEFINE_IINSPECTABLE_( iterable_kvpair_HSTRING_IInspectable, + IIterable_IKeyValuePair_HSTRING_IInspectable, struct propertyset, + impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable, + IIterable_IKeyValuePair_HSTRING_IInspectable_iface, + &impl->IMap_HSTRING_IInspectable_iface ); + +static HRESULT STDMETHODCALLTYPE +iterable_kvpair_HSTRING_IInspectable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, + IIterator_IKeyValuePair_HSTRING_IInspectable **iter ) +{ + return E_NOTIMPL; +} + +const static IIterable_IKeyValuePair_HSTRING_IInspectableVtbl iterable_kvpair_HSTRING_IInspectable_vtbl = +{ + /* IUnknown */ + iterable_kvpair_HSTRING_IInspectable_QueryInterface, + iterable_kvpair_HSTRING_IInspectable_AddRef, + iterable_kvpair_HSTRING_IInspectable_Release, + /* IInspectable */ + iterable_kvpair_HSTRING_IInspectable_GetIids, + iterable_kvpair_HSTRING_IInspectable_GetRuntimeClassName, + iterable_kvpair_HSTRING_IInspectable_GetTrustLevel, + /* IIterable<IKeyValuePair<HSTRING, IInspectable*>> */ + iterable_kvpair_HSTRING_IInspectable_First +}; + HRESULT propertyset_create( IPropertySet **iface ) { struct propertyset *impl; @@ -129,8 +292,12 @@ HRESULT propertyset_create( IPropertySet **iface ) return E_OUTOFMEMORY;
impl->IPropertySet_iface.lpVtbl = &propertyset_vtbl; - impl->ref = 1; + 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;
+ impl->ref = 1; *iface = &impl->IPropertySet_iface; return S_OK; } diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c index 95a23462977..d2587c4f5a7 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -275,7 +275,7 @@ static void test_IPropertySet(void) }
hr = IPropertySet_QueryInterface( propset, &IID_IMap_HSTRING_IInspectable, (void **)&map ); - todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); if (FAILED( hr )) { IPropertyValueStatics_Release( statics ); @@ -286,7 +286,7 @@ static void test_IPropertySet(void) hr = IPropertySet_QueryInterface( propset, &IID_IObservableMap_HSTRING_IInspectable, (void *)&observable_map ); IPropertySet_Release(propset); - todo_wine ok(SUCCEEDED(hr), "QueryInterface failed, got %#lx\n", hr); + ok(SUCCEEDED(hr), "QueryInterface failed, got %#lx\n", hr);
#define EVENT_HANDLER_CREATE(t, c) \ do \ @@ -412,7 +412,7 @@ static void test_IPropertySet(void)
hr = IMap_HSTRING_IInspectable_QueryInterface( map, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&iterable ); - todo_wine ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "QueryInterface failed, got %#lx\n", hr ); if (SUCCEEDED( hr )) { hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator );
From: Vibhav Pant vibhavp@gmail.com
Implement GetView() for Windows.Foundation.Collections.PropertySet using an instance of this stub. --- dlls/wintypes/propertyset.c | 187 +++++++++++++++++++++++++++++- dlls/wintypes/tests/propertyset.c | 4 +- 2 files changed, 187 insertions(+), 4 deletions(-)
diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index ccbe30010fd..00736812730 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -30,6 +30,176 @@
WINE_DEFAULT_DEBUG_CHANNEL( wintypes );
+struct mapview_HSTRING_IInspectable +{ + IMapView_HSTRING_IInspectable IMapView_HSTRING_IInspectable_iface; + IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + + LONG ref; +}; + +static inline struct mapview_HSTRING_IInspectable * +impl_from_IMapView_HSTRING_IInspectable( IMapView_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct mapview_HSTRING_IInspectable, + IMapView_HSTRING_IInspectable_iface ); +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_QueryInterface( + IMapView_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + *out = NULL; + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IMapView_HSTRING_IInspectable )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + if (IsEqualGUID( iid, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable )) + { + struct mapview_HSTRING_IInspectable *impl = + impl_from_IMapView_HSTRING_IInspectable( iface ); + *out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + IUnknown_AddRef( iface ); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE +mapview_HSTRING_IInspectable_AddRef( IMapView_HSTRING_IInspectable *iface ) +{ + struct mapview_HSTRING_IInspectable *impl; + + TRACE( "(%p)\n", iface ); + impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG STDMETHODCALLTYPE +mapview_HSTRING_IInspectable_Release( IMapView_HSTRING_IInspectable *iface ) +{ + struct mapview_HSTRING_IInspectable *impl; + ULONG ref; + + TRACE( "(%p)\n", iface ); + impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + ref = InterlockedDecrement( &impl->ref ); + if (!ref) + { + free( impl ); + } + + return ref; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_GetIids( + IMapView_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_GetRuntimeClassName( + IMapView_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "(%p, %p) stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_GetTrustLevel( + IMapView_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "(%p, %p) stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +mapview_HSTRING_IInspectable_get_Size( IMapView_HSTRING_IInspectable *iface, UINT32 *size ) +{ + FIXME( "(%p, %p) stub!\n", iface, size ); + *size = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_HaKey( + IMapView_HSTRING_IInspectable *iface, HSTRING key, boolean *exists ) +{ + FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), exists ); + *exists = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_Lookup( + IMapView_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) +{ + FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), value ); + *value = NULL; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE mapview_HSTRING_IInspectable_Split( + IMapView_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **first, + IMapView_HSTRING_IInspectable **second ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, first, second ); + *first = NULL; + *second = NULL; + return E_NOTIMPL; +} + +const static IMapView_HSTRING_IInspectableVtbl mapview_HSTRING_IInspectable_vtbl = +{ + /* IUnknown */ + mapview_HSTRING_IInspectable_QueryInterface, + mapview_HSTRING_IInspectable_AddRef, + mapview_HSTRING_IInspectable_Release, + /* IInspectable */ + mapview_HSTRING_IInspectable_GetIids, + mapview_HSTRING_IInspectable_GetRuntimeClassName, + mapview_HSTRING_IInspectable_GetTrustLevel, + /* IMapView<HSTRING, IInspectable*> */ + mapview_HSTRING_IInspectable_Lookup, + mapview_HSTRING_IInspectable_get_Size, + mapview_HSTRING_IInspectable_HaKey, + mapview_HSTRING_IInspectable_Split, +}; + +DEFINE_IINSPECTABLE_( mapview_iterable_kvpair_HSTRING_IInspectable, + IIterable_IKeyValuePair_HSTRING_IInspectable, + struct mapview_HSTRING_IInspectable, + mapview_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable, + IIterable_IKeyValuePair_HSTRING_IInspectable_iface, + &impl->IMapView_HSTRING_IInspectable_iface ); + +static HRESULT STDMETHODCALLTYPE mapview_iterable_kvpair_HSTRING_IInspectable_First( + IIterable_IKeyValuePair_HSTRING_IInspectable *iface, + IIterator_IKeyValuePair_HSTRING_IInspectable **iter ) +{ + FIXME( "(%p, %p) stub!\n", iface, iter ); + return E_NOTIMPL; +} + +const static IIterable_IKeyValuePair_HSTRING_IInspectableVtbl + mapview_iterable_kvpair_HSTRING_IInspectable_vtbl = +{ + /* IUnknown */ + mapview_iterable_kvpair_HSTRING_IInspectable_QueryInterface, + mapview_iterable_kvpair_HSTRING_IInspectable_AddRef, + mapview_iterable_kvpair_HSTRING_IInspectable_Release, + /* IInspectable */ + mapview_iterable_kvpair_HSTRING_IInspectable_GetIids, + mapview_iterable_kvpair_HSTRING_IInspectable_GetRuntimeClassName, + mapview_iterable_kvpair_HSTRING_IInspectable_GetTrustLevel, + /* IIterable<IKeyValuePair<HSTRING, IInspectable*>> */ + mapview_iterable_kvpair_HSTRING_IInspectable_First +}; + struct propertyset { IPropertySet IPropertySet_iface; @@ -209,9 +379,22 @@ static HRESULT STDMETHODCALLTYPE propertyset_HasKey( IMap_HSTRING_IInspectable * static HRESULT STDMETHODCALLTYPE propertyset_GetView( IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **view ) { - FIXME( "(%p, %p) stub!\n", iface, view ); + struct mapview_HSTRING_IInspectable *view_impl; + + FIXME( "(%p, %p) semi-stub!\n", iface, view ); *view = NULL; - return E_NOTIMPL; + view_impl = calloc( 1, sizeof( *view_impl ) ); + if (!view_impl) + return E_OUTOFMEMORY; + + view_impl->IMapView_HSTRING_IInspectable_iface.lpVtbl = &mapview_HSTRING_IInspectable_vtbl; + view_impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = + &mapview_iterable_kvpair_HSTRING_IInspectable_vtbl; + + view_impl->ref = 1; + *view = &view_impl->IMapView_HSTRING_IInspectable_iface; + + return S_OK; }
static HRESULT STDMETHODCALLTYPE propertyset_Insert( IMap_HSTRING_IInspectable *iface, diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c index d2587c4f5a7..fd00e7dd8c8 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -490,14 +490,14 @@ static void test_IPropertySet(void) MAP_TEST_(PropertyType_##t, IPropertyValue_Get##t, IMapView, map_view, STR(t), v, ct)
hr = IMap_HSTRING_IInspectable_GetView( map, &map_view ); - todo_wine ok( SUCCEEDED( hr ), "GetView failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "GetView failed, got %#lx\n", hr ); if (SUCCEEDED( hr )) { TEST_MAP_VALUES;
hr = IMapView_HSTRING_IInspectable_QueryInterface( map_view, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&iterable ); - todo_wine ok( SUCCEEDED( hr ), "QuerInterface failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "QuerInterface failed, got %#lx\n", hr ); if (iterable) { hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/propertyset.c | 172 +++++++++++++++++++++++++++++- dlls/wintypes/tests/propertyset.c | 2 +- 2 files changed, 170 insertions(+), 4 deletions(-)
diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index 00736812730..343fe597cf6 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -30,6 +30,171 @@
WINE_DEFAULT_DEBUG_CHANNEL( wintypes );
+struct iterator_kvpair_HSTRING_IInspectable +{ + IIterator_IKeyValuePair_HSTRING_IInspectable iface; + + LONG ref; +}; + +static inline struct iterator_kvpair_HSTRING_IInspectable * +impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator_kvpair_HSTRING_IInspectable, iface ); +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_QueryInterface( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + *out = NULL; + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IIterator_IKeyValuePair_HSTRING_IInspectable )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE +iterator_kvpair_HSTRING_IInspectable_AddRef( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct iterator_kvpair_HSTRING_IInspectable *impl; + + TRACE( "(%p)\n", iface ); + impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG STDMETHODCALLTYPE +iterator_kvpair_HSTRING_IInspectable_Release( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct iterator_kvpair_HSTRING_IInspectable *impl; + ULONG ref; + + TRACE( "(%p)\n", iface ); + impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + ref = InterlockedDecrement( &impl->ref ); + if (!ref) + free( impl ); + + return ref; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_GetIids( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_GetRuntimeClassName( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "(%p, %p) stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_GetTrustLevel( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "(%p, %p) stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +iterator_kvpair_HSTRING_IInspectable_get_Current( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, + IKeyValuePair_HSTRING_IInspectable **kvpair ) +{ + FIXME( "(%p, %p) stub!\n", iface, kvpair ); + *kvpair = NULL; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_HasCurrent( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *exists ) +{ + FIXME( "(%p, %p) stub!\n", iface, exists ); + *exists = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_MoveNext( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *valid ) +{ + FIXME( "(%p, %p) stub!\n", iface, valid ); + *valid = 0; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_GetMany( + IIterator_IKeyValuePair_HSTRING_IInspectable *iface, UINT32 count, + IKeyValuePair_HSTRING_IInspectable **items, UINT32 *value ) +{ + boolean end = 0; + HRESULT hr; + + TRACE( "(%p, %u, %p, %p)\n", iface, count, items, value ); + + for (*value = 0; *value < count && !end; *value += 1) + { + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iface, &items[*value] ); + if (FAILED( hr )) + { + *value += 1; + return hr; + } + + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iface, &end ); + if (FAILED( hr )) + { + *value += 1; + return hr; + } + } + + return S_OK; +} + +const static IIterator_IKeyValuePair_HSTRING_IInspectableVtbl iterator_kvpair_HSTRING_IInspectable_vtbl = +{ + /* IUnknown */ + iterator_kvpair_HSTRING_IInspectable_QueryInterface, + iterator_kvpair_HSTRING_IInspectable_AddRef, + iterator_kvpair_HSTRING_IInspectable_Release, + /* IInspectable */ + iterator_kvpair_HSTRING_IInspectable_GetIids, + iterator_kvpair_HSTRING_IInspectable_GetRuntimeClassName, + iterator_kvpair_HSTRING_IInspectable_GetTrustLevel, + /* IIterator<IKeyValuePair<HSTRING,IInspectable*>> */ + iterator_kvpair_HSTRING_IInspectable_get_Current, + iterator_kvpair_HSTRING_IInspectable_HasCurrent, + iterator_kvpair_HSTRING_IInspectable_MoveNext, + iterator_kvpair_HSTRING_IInspectable_GetMany, +}; + +static HRESULT +iterator_kvpair_HSTRING_IInspectable_create( IIterator_IKeyValuePair_HSTRING_IInspectable **iface ) +{ + struct iterator_kvpair_HSTRING_IInspectable *impl_iter; + + TRACE( "(%p)\n", iface ); + + impl_iter = calloc( 1, sizeof( *impl_iter ) ); + if (!impl_iter) + return E_OUTOFMEMORY; + + impl_iter->iface.lpVtbl = &iterator_kvpair_HSTRING_IInspectable_vtbl; + impl_iter->ref = 1; + *iface = &impl_iter->iface; + return S_OK; +} + struct mapview_HSTRING_IInspectable { IMapView_HSTRING_IInspectable IMapView_HSTRING_IInspectable_iface; @@ -181,8 +346,8 @@ static HRESULT STDMETHODCALLTYPE mapview_iterable_kvpair_HSTRING_IInspectable_Fi IIterable_IKeyValuePair_HSTRING_IInspectable *iface, IIterator_IKeyValuePair_HSTRING_IInspectable **iter ) { - FIXME( "(%p, %p) stub!\n", iface, iter ); - return E_NOTIMPL; + FIXME( "(%p, %p) semi-stub!\n", iface, iter ); + return iterator_kvpair_HSTRING_IInspectable_create( iter ); }
const static IIterable_IKeyValuePair_HSTRING_IInspectableVtbl @@ -449,7 +614,8 @@ static HRESULT STDMETHODCALLTYPE iterable_kvpair_HSTRING_IInspectable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, IIterator_IKeyValuePair_HSTRING_IInspectable **iter ) { - return E_NOTIMPL; + FIXME( "(%p, %p) semi-stub!\n", iface, iter ); + return iterator_kvpair_HSTRING_IInspectable_create( iter ); }
const static IIterable_IKeyValuePair_HSTRING_IInspectableVtbl iterable_kvpair_HSTRING_IInspectable_vtbl = diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c index fd00e7dd8c8..6268a211ead 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -502,7 +502,7 @@ static void test_IPropertySet(void) { hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); - todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "got %#lx\n", hr ); size = 15; valid = 1; while (valid && iterator)
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/propertyset.c | 126 +++++++++++++++++++++++++++++- dlls/wintypes/tests/propertyset.c | 12 +-- 2 files changed, 130 insertions(+), 8 deletions(-)
diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index 343fe597cf6..d60ed5f264e 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -30,6 +30,127 @@
WINE_DEFAULT_DEBUG_CHANNEL( wintypes );
+struct kvpair +{ + IKeyValuePair_HSTRING_IInspectable iface; + + LONG ref; +}; + +static inline struct kvpair * +impl_from_IKeyValuePair_HSTRING_IInspectable( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct kvpair, iface ); +} + +static HRESULT STDMETHODCALLTYPE kvpair_QueryInterface( IKeyValuePair_HSTRING_IInspectable *iface, + REFIID iid, void **out ) +{ + TRACE( "(%p, %p, %p)\n", iface, debugstr_guid( iid ), out ); + *out = NULL; + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IKeyValuePair_HSTRING_IInspectable )) + { + *out = iface; + IUnknown_AddRef( iface ); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE kvpair_AddRef( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct kvpair *impl; + + TRACE( "(%p)\n", iface ); + + impl = impl_from_IKeyValuePair_HSTRING_IInspectable( iface ); + return InterlockedIncrement( &impl->ref ); +} + +static ULONG STDMETHODCALLTYPE kvpair_Release( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct kvpair *impl; + ULONG ref; + + TRACE( "(%p)\n", iface ); + + impl = impl_from_IKeyValuePair_HSTRING_IInspectable( iface ); + ref = InterlockedDecrement( &impl->ref ); + if (!ref) + free( impl ); + + return ref; +} + +static HRESULT STDMETHODCALLTYPE kvpair_GetIIDs( IKeyValuePair_HSTRING_IInspectable *iface, + ULONG *iid_count, IID **iids ) +{ + FIXME( "(%p, %p, %p) stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +kvpair_GetRuntimeClassName( IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "(%p, %p) stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE kvpair_GetTrustLevel( IKeyValuePair_HSTRING_IInspectable *iface, + TrustLevel *trust_level ) +{ + FIXME( "(%p, %p) stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE kvpair_get_Key( IKeyValuePair_HSTRING_IInspectable *iface, + HSTRING *key ) +{ + FIXME( "(%p, %p) stub!\n", iface, key ); + *key = NULL; + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE kvpair_get_Value( IKeyValuePair_HSTRING_IInspectable *iface, + IInspectable **value ) +{ + FIXME( "(%p, %p) stub!\n", iface, value ); + *value = NULL; + return E_NOTIMPL; +} + +const static IKeyValuePair_HSTRING_IInspectableVtbl kvpair_vtbl = +{ + kvpair_QueryInterface, + kvpair_AddRef, + kvpair_Release, + kvpair_GetIIDs, + kvpair_GetRuntimeClassName, + kvpair_GetTrustLevel, + kvpair_get_Key, + kvpair_get_Value, +}; + +static HRESULT kvpair_create( IKeyValuePair_HSTRING_IInspectable **kvpair ) +{ + struct kvpair *impl; + + TRACE( "(%p)\n", kvpair ); + + *kvpair = NULL; + impl = calloc( 1, sizeof( *impl ) ); + if (!impl) + return E_OUTOFMEMORY; + + impl->iface.lpVtbl = &kvpair_vtbl; + impl->ref = 1; + *kvpair = &impl->iface; + return S_OK; +} + struct iterator_kvpair_HSTRING_IInspectable { IIterator_IKeyValuePair_HSTRING_IInspectable iface; @@ -111,9 +232,8 @@ static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_get_Current( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, IKeyValuePair_HSTRING_IInspectable **kvpair ) { - FIXME( "(%p, %p) stub!\n", iface, kvpair ); - *kvpair = NULL; - return E_NOTIMPL; + FIXME( "(%p, %p) semi-stub!\n", iface, kvpair ); + return kvpair_create( kvpair ); }
static HRESULT STDMETHODCALLTYPE iterator_kvpair_HSTRING_IInspectable_HasCurrent( diff --git a/dlls/wintypes/tests/propertyset.c b/dlls/wintypes/tests/propertyset.c index 6268a211ead..531c3a9b142 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -425,18 +425,19 @@ static void test_IPropertySet(void) {
IKeyValuePair_HSTRING_IInspectable *kvpair; - HSTRING key; + HSTRING key = NULL; IInspectable *value; hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iterator, &kvpair ); - todo_wine ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); hr = IKeyValuePair_HSTRING_IInspectable_get_Key( kvpair, &key ); todo_wine ok( SUCCEEDED( hr ), "get_Key failed, got %#lx\n", hr ); WindowsDeleteString( key ); hr = IKeyValuePair_HSTRING_IInspectable_get_Value( kvpair, &value ); todo_wine ok( SUCCEEDED( hr ), "get_Value failed, got %#lx\n", hr ); - IInspectable_Release( value ); + if (SUCCEEDED( hr )) IInspectable_Release( value ); hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iterator, &valid ); todo_wine ok( SUCCEEDED( hr ), "MoveNext failed, got %#lx\n", hr ); + if (FAILED( hr )) break; size--; } todo_wine ok( size == 0, "%d != 0\n", size ); @@ -512,16 +513,17 @@ static void test_IPropertySet(void) HSTRING key; IInspectable *value; hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iterator, &kvpair ); - todo_wine ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); + ok( SUCCEEDED( hr ), "get_Current failed, got %#lx\n", hr ); if (FAILED( hr )) break; hr = IKeyValuePair_HSTRING_IInspectable_get_Key( kvpair, &key ); todo_wine ok( SUCCEEDED( hr ), "get_Key failed, got %#lx\n", hr ); WindowsDeleteString( key ); hr = IKeyValuePair_HSTRING_IInspectable_get_Value( kvpair, &value ); todo_wine ok( SUCCEEDED( hr ), "get_Value failed, got %#lx\n", hr ); - IInspectable_Release( value ); + if (SUCCEEDED( hr )) IInspectable_Release( value ); hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iterator, &valid ); todo_wine ok( SUCCEEDED( hr ), "MoveNext failed, got %#lx\n", hr ); + if (FAILED( hr )) break; size--; } todo_wine ok( size == 0, "%d != 0\n", size );
On Wed Nov 6 10:02:22 2024 +0000, Zhiyi Zhang wrote:
wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"Boolean" wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"UInt16" wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"Int16" wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"UInt32" wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"Int32" wintypes:propertyset propertyset.c:497 Test succeeded inside todo block: expected map to have key L"Single"
You need to remove todo_wine for these tests that succeed after implementation. Otherwise, CI will report failures.
This was due to `HasKey` not setting `replaced` to 0, just returning `E_NOTIMPL`. Should be fixed now.
Zhiyi Zhang (@zhiyi) commented about include/windows.foundation.idl:
namespace Windows.Foundation.Collections { interface IPropertySet;
there should be a line of `runtimeclass PropertySet;` here; See other .idl files for example.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/wintypes_test.idl:
declare { interface Windows.Foundation.IReference<HSTRING>;
- interface Windows.Foundation.Collections.MapChangedEventHandler<HSTRING, IInspectable*>;
Please add a space before the asterisk.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- struct propset_changed_event_handler *impl =
impl_from_IWinePropertySetChangedEventHandler( iface );
- ULONG ref;
- ref = InterlockedDecrement( &impl->ref );
- if (!ref)
free( impl );
- return ref;
+}
+static HRESULT STDMETHODCALLTYPE propset_changed_event_handler_get_TimesInvoked(
- IWinePropertySetChangedEventHandler *iface, ULONG *times )
+{
- struct propset_changed_event_handler *impl =
impl_from_IWinePropertySetChangedEventHandler( iface );
- *times = impl->invoked;
What's the purpose of IWinePropertySetChangedEventHandler? just to access `invoked`?
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/wintypes_test.idl:
declare { interface Windows.Foundation.IReference<HSTRING>;
- interface Windows.Foundation.Collections.MapChangedEventHandler<HSTRING, IInspectable*>;
}
+[
- uuid(7e860ccf-d9d0-4fbb-87a9-aa6c26f7f6ec)
+] +interface IWinePropertySetChangedEventHandler : IUnknown
- requires Windows.Foundation.Collections.MapChangedEventHandler<HSTRING, IInspectable *> {
Let's move the left curly brace to a new line.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
+#define COBJMACROS +#include "winstring.h" +#include "roapi.h" +#include "ole2.h"
+#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#include "wintypes_test.h"
+#include "wine/test.h"
+static const WCHAR *class_name = RuntimeClass_Windows_Foundation_Collections_PropertySet;
Let's keep these inside the test_IPropertySet()
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
+#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#include "wintypes_test.h"
+#include "wine/test.h"
+static const WCHAR *class_name = RuntimeClass_Windows_Foundation_Collections_PropertySet; +static const struct DateTime datetime_value = {0x12345678abcdef}; +static const struct TimeSpan timespan_value = {0x12345678abcdef}; +static const struct Point point_value = {1, 2}; +static const struct Size size_value = {1, 2}; +static const struct Rect rect_value = {1, 2, 3, 4};
+#define DEFINE_IUNKNOWN_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \
Is this macro gonna be used multiple times?
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- *out = &impl->IMapChangedEventHandler_HSTRING_IInspectable_iface;
- return S_OK;
+}
+static void test_IPropertySet(void) +{
- IActivationFactory *factory;
- IInspectable *inspectable;
- IPropertyValueStatics *statics;
- IPropertySet *propset;
- IMap_HSTRING_IInspectable *map;
- IMapView_HSTRING_IInspectable *map_view, *first_view = NULL, *second_view = NULL;
- IIterable_IKeyValuePair_HSTRING_IInspectable *iterable;
- IIterator_IKeyValuePair_HSTRING_IInspectable *iterator;
- IMapChangedEventHandler_HSTRING_IInspectable *handler_inserted = NULL, *handler_changed = NULL,
Let's put them on the same line. Or if it's too long (usually at 100 or 120 characters), start at a new line and specify the type again. We usually don't type the variables like this.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/wintypes.c:
#include "rometadataresolution.h"
#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections #define WIDL_using_Windows_Foundation_Metadata +#include "windows.foundation.collections.h" #include "windows.foundation.metadata.h"
Why do you need to change this file?
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
hr = IMap_HSTRING_IInspectable_Insert( map, key, value, &replace ); \
IInspectable_Release( value ); \
todo_wine ok( SUCCEEDED( hr ), "Insert failed, got %#lx\n", hr ); \
if (SUCCEEDED( hr )) ok( !replace, "%d != 0\n", replace ); \
hr = IMap_HSTRING_IInspectable_get_Size( map, &size ); \
todo_wine ok( SUCCEEDED( hr ), "get_Size failed, got %#lx\n", hr ); \
if (SUCCEEDED( hr )) ok( size == prev_size + 1, "%u != %u\n", size, prev_size + 1 ); \
prev_size = cur_size = size; \
hr = IPropertyValueStatics_Create##t( statics, ( v ), &value ); \
ok( SUCCEEDED( hr ), "got %#lx\n", hr ); \
if (FAILED( hr )) \
{ \
WindowsDeleteString( key ); \
break; \
} \
hr = IMap_HSTRING_IInspectable_Insert( map, key, value, &replace ); \
This patch is too long. Please see if you can simplify or separate it.
On Wed Nov 6 10:11:05 2024 +0000, Zhiyi Zhang wrote:
This patch is too long. Please see if you can simplify or separate it.
I'll move most of the map operation tests to another MR, since the corresponding functionality isn't really added here.