-- v25: 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 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 9e3b656d8a3..8f11da943f3 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -30,6 +30,8 @@ import "windows.foundation.collections.idl"; namespace Windows.Foundation.Collections { interface IPropertySet;
+ runtimeclass PropertySet; + declare { interface Windows.Foundation.Collections.IKeyValuePair<HSTRING, HSTRING>; interface Windows.Foundation.Collections.IKeyValuePair<HSTRING, IInspectable *>; @@ -57,6 +59,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 | 153 ++++++++++++++++++++++++++++++ 2 files changed, 154 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..aff3aee465b --- /dev/null +++ b/dlls/wintypes/tests/propertyset.c @@ -0,0 +1,153 @@ +/* + * 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" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#include "wintypes_test.h" + +#include "wine/test.h" + +static void test_IPropertySet(void) +{ + static const WCHAR *class_name = RuntimeClass_Windows_Foundation_Collections_PropertySet; + IActivationFactory *factory; + IInspectable *inspectable; + IPropertyValueStatics *statics; + IPropertySet *propset; + IMap_HSTRING_IInspectable *map; + IMapView_HSTRING_IInspectable *map_view; + IIterable_IKeyValuePair_HSTRING_IInspectable *iterable; + IIterator_IKeyValuePair_HSTRING_IInspectable *iterator; + IObservableMap_HSTRING_IInspectable *observable_map; + 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); + + 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 ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + } + else + skip( "Could not obtain IIterable<IKeyValuePair<HSTRING, IInspectable *>> instance.\n"); + + hr = IMap_HSTRING_IInspectable_GetView( map, &map_view ); + todo_wine ok( SUCCEEDED( hr ), "GetView failed, got %#lx\n", hr ); + if (SUCCEEDED( hr )) + { + 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 ); + if (iterator) + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + + } + } + + IObservableMap_HSTRING_IInspectable_Release( observable_map ); + IMap_HSTRING_IInspectable_Release( map ); + IPropertyValueStatics_Release( statics ); + RoUninitialize(); +} + +START_TEST(propertyset) +{ + test_IPropertySet(); +}
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 aff3aee465b..fca885a0303 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -77,7 +77,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"); @@ -88,7 +88,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 fca885a0303..9b8235192a6 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -97,7 +97,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 ); @@ -108,11 +108,11 @@ 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);
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 9b8235192a6..b91cc0ed46d 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -124,12 +124,12 @@ static void test_IPropertySet(void) skip( "Could not obtain IIterable<IKeyValuePair<HSTRING, IInspectable *>> instance.\n");
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 )) { 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 +++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 3 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 =
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/propertyset.c | 126 +++++++++++++++++++++++++++++- dlls/wintypes/tests/propertyset.c | 2 +- 2 files changed, 124 insertions(+), 4 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 b91cc0ed46d..9106884bd99 100644 --- a/dlls/wintypes/tests/propertyset.c +++ b/dlls/wintypes/tests/propertyset.c @@ -134,7 +134,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 ); if (iterator) IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149510
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000029D00EE, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
On Wed Nov 6 13:48:51 2024 +0000, Zhiyi Zhang wrote:
Why do you need to change this file?
Removed these for now.
@zhiyi I have slimmed down the tests to only testing basic interface methods. I'll expand them in future MRs, is this better?
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
+/*
- Copyright 2024 Vibhav Pant
Add a `s` at the end of `test`. "wintypes/test: ... " -> "wintypes/tests: ... "
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- 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"
+#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#include "wintypes_test.h"
I think you can delete `#include "wintypes_test.h"`, wintypes_test.h only contains Windows.Foundation.IReference<HSTRING> and you're not using it.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- 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 );
I don't see this IPropertyValueStatics actually used anywhere. This is probably just a leftover from copy-pasting existing tests. Please remove them. Also, this suggests that you should thoroughly review your code before submitting it.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator );
IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable );
todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr );
if (iterator)
IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator );
}
- }
- IObservableMap_HSTRING_IInspectable_Release( observable_map );
- IMap_HSTRING_IInspectable_Release( map );
- IPropertyValueStatics_Release( statics );
- RoUninitialize();
+}
+START_TEST(propertyset)
I think you can put the tests in the existing wintypes.c.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- hr = IMap_HSTRING_IInspectable_GetView( map, &map_view );
- todo_wine ok( SUCCEEDED( hr ), "GetView failed, got %#lx\n", hr );
- if (SUCCEEDED( hr ))
- {
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 );
if (iterator)
IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator );
Please remove this empty line.
Zhiyi Zhang (@zhiyi) commented about dlls/wintypes/tests/propertyset.c:
- IMap_HSTRING_IInspectable *map;
- IMapView_HSTRING_IInspectable *map_view;
- IIterable_IKeyValuePair_HSTRING_IInspectable *iterable;
- IIterator_IKeyValuePair_HSTRING_IInspectable *iterator;
- IObservableMap_HSTRING_IInspectable *observable_map;
- 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 );
You can call WindowsDeleteString() here so you don't need to call it when RoGetActivationFactory() fails.
Rémi Bernon (@rbernon) commented about dlls/wintypes/main.c:
HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) {
- const WCHAR *name;
- TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
- name = WindowsGetStringRawBuffer(classid, NULL);
- if (!wcscmp(name, RuntimeClass_Windows_Foundation_Collections_PropertySet))
*factory = &wintypes.IPropertySet_IActivationFactory_iface;
- else *factory = &wintypes.IActivationFactory_iface;
Fwiw I don't think we should mix factories like that, unless proved otherwise each class has its own static factory. It would be better to keep them separate, using separate sources as in most of the other places we have WinRT classes implemented now. Keeping consistent patterns will make future refactor/code factorization much easier.
On Tue Nov 12 09:59:50 2024 +0000, Zhiyi Zhang wrote:
I think you can put the tests in the existing wintypes.c.
These tests a lot larger in the next MR, including a bunch of new helper functions for testing `IObservableMap`, that is why I made a new file for them.
On Tue Nov 12 09:59:50 2024 +0000, Zhiyi Zhang wrote:
I don't see this IPropertyValueStatics actually used anywhere. This is probably just a leftover from copy-pasting existing tests. Please remove them. Also, this suggests that you should thoroughly review your code before submitting it.
The statics are used in tests for the methods `Insert` and `Lookup`. They were left over after I split the conformance tests commits into two MRs. Removed them for now.