From: Rémi Bernon rbernon@codeweavers.com
--- dlls/wintypes/Makefile.in | 1 + dlls/wintypes/map.c | 638 ++++++++++++++++++++++++++++ dlls/wintypes/private.h | 50 +++ dlls/wintypes/propertyset.c | 656 ++++++++++++++++++++++++----- dlls/wintypes/tests/wintypes.c | 30 +- dlls/wintypes/wintypes_private.idl | 39 -- 6 files changed, 1256 insertions(+), 158 deletions(-) create mode 100644 dlls/wintypes/map.c
diff --git a/dlls/wintypes/Makefile.in b/dlls/wintypes/Makefile.in index fd370133cf8..883d02f8b83 100644 --- a/dlls/wintypes/Makefile.in +++ b/dlls/wintypes/Makefile.in @@ -6,6 +6,7 @@ SOURCES = \ buffer.c \ classes.idl \ main.c \ + map.c \ propertyset.c \ storage.c \ wintypes_private.idl diff --git a/dlls/wintypes/map.c b/dlls/wintypes/map.c new file mode 100644 index 00000000000..e49e933274a --- /dev/null +++ b/dlls/wintypes/map.c @@ -0,0 +1,638 @@ +/* + * Copyright 2025 Rémi Bernon for CodeWeavers + * + * 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 <wine/debug.h> + +#include "private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(combase); + +struct pair +{ + IKeyValuePair_HSTRING_IInspectable IKeyValuePair_HSTRING_IInspectable_iface; + const GUID *iid; + LONG ref; +}; + +static struct pair *impl_from_IKeyValuePair_HSTRING_IInspectable( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct pair, IKeyValuePair_HSTRING_IInspectable_iface ); +} + +static HRESULT WINAPI pair_QueryInterface( IKeyValuePair_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + struct pair *impl = impl_from_IKeyValuePair_HSTRING_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iid )) + { + IInspectable_AddRef( (*out = &impl->IKeyValuePair_HSTRING_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI pair_AddRef( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct pair *impl = impl_from_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI pair_Release( IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct pair *impl = impl_from_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI pair_GetIids( IKeyValuePair_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI pair_GetRuntimeClassName( IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI pair_GetTrustLevel( IKeyValuePair_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI pair_get_Key( IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI pair_get_Value( IKeyValuePair_HSTRING_IInspectable *iface, IInspectable **value ) +{ + TRACE( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const IKeyValuePair_HSTRING_IInspectableVtbl pair_vtbl = +{ + pair_QueryInterface, + pair_AddRef, + pair_Release, + /* IInspectable methods */ + pair_GetIids, + pair_GetRuntimeClassName, + pair_GetTrustLevel, + /* IKeyValuePair<HSTRING,IInspectable*> methods */ + pair_get_Key, + pair_get_Value, +}; + +static HRESULT pair_create( const GUID *iid, IKeyValuePair_HSTRING_IInspectable **out ) +{ + struct pair *pair; + + if (!(pair = calloc(1, sizeof(*pair)))) return E_OUTOFMEMORY; + pair->IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &pair_vtbl; + pair->iid = iid; + pair->ref = 1; + + return S_OK; +} + +struct map_view +{ + IMapView_HSTRING_IInspectable IMapView_HSTRING_IInspectable_iface; + IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + struct map_iids iids; + LONG ref; +}; + +static struct map_view *impl_from_IMapView_HSTRING_IInspectable( IMapView_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct map_view, IMapView_HSTRING_IInspectable_iface ); +} + +struct iterator +{ + IIterator_IKeyValuePair_HSTRING_IInspectable IIterator_IKeyValuePair_HSTRING_IInspectable_iface; + const GUID *iid; + LONG ref; + + IMapView_HSTRING_IInspectable *view; +}; + +static struct iterator *impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator, IIterator_IKeyValuePair_HSTRING_IInspectable_iface ); +} + +static HRESULT WINAPI iterator_QueryInterface( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + struct iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iid )) + { + IInspectable_AddRef( (*out = &impl->IIterator_IKeyValuePair_HSTRING_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI iterator_AddRef( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI iterator_Release( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IMapView_HSTRING_IInspectable_Release( impl->view ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI iterator_GetIids( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetRuntimeClassName( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetTrustLevel( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_get_Current( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, IKeyValuePair_HSTRING_IInspectable **value ) +{ + struct iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + struct map_view *view = impl_from_IMapView_HSTRING_IInspectable( impl->view ); + FIXME( "iface %p, value %p stub!\n", iface, value ); + return pair_create( view->iids.pair, value ); +} + +static HRESULT WINAPI iterator_get_HasCurrent( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *value ) +{ + TRACE( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_MoveNext( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetMany( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, UINT32 items_size, + IKeyValuePair_HSTRING_IInspectable **items, UINT *count ) +{ + FIXME( "iface %p, items_size %u, items %p, count %p stub!\n", iface, items_size, items, count ); + return E_NOTIMPL; +} + +static const IIterator_IKeyValuePair_HSTRING_IInspectableVtbl iterator_vtbl = +{ + iterator_QueryInterface, + iterator_AddRef, + iterator_Release, + /* IInspectable methods */ + iterator_GetIids, + iterator_GetRuntimeClassName, + iterator_GetTrustLevel, + /* IIterator<IInspectable*> methods */ + iterator_get_Current, + iterator_get_HasCurrent, + iterator_MoveNext, + iterator_GetMany, +}; + +static HRESULT WINAPI map_view_QueryInterface( IMapView_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + struct map_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iids.view )) + { + IInspectable_AddRef( (*out = &impl->IMapView_HSTRING_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI map_view_AddRef( IMapView_HSTRING_IInspectable *iface ) +{ + struct map_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI map_view_Release( IMapView_HSTRING_IInspectable *iface ) +{ + struct map_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI map_view_GetIids( IMapView_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_GetRuntimeClassName( IMapView_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_GetTrustLevel( IMapView_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_Lookup( IMapView_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) +{ + FIXME( "iface %p, key %s, value %p stub!\n", iface, debugstr_hstring( key ), value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_get_Size( IMapView_HSTRING_IInspectable *iface, UINT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_HasKey( IMapView_HSTRING_IInspectable *iface, HSTRING key, boolean *found ) +{ + FIXME( "iface %p, key %s, found %p stub!\n", iface, debugstr_hstring( key ), found ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_view_Split( IMapView_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **first, + IMapView_HSTRING_IInspectable **second ) +{ + FIXME( "iface %p, first %p, second %p stub!\n", iface, first, second ); + return E_NOTIMPL; +} + +static const struct IMapView_HSTRING_IInspectableVtbl map_view_vtbl = +{ + map_view_QueryInterface, + map_view_AddRef, + map_view_Release, + /* IInspectable methods */ + map_view_GetIids, + map_view_GetRuntimeClassName, + map_view_GetTrustLevel, + /* IMapView_HSTRING<IInspectable*> methods */ + map_view_Lookup, + map_view_get_Size, + map_view_HasKey, + map_view_Split, +}; + +DEFINE_IINSPECTABLE_( iterable_view, IIterable_IKeyValuePair_HSTRING_IInspectable, struct map_view, view_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable, + IIterable_IKeyValuePair_HSTRING_IInspectable_iface, &impl->IMapView_HSTRING_IInspectable_iface ) + +static HRESULT WINAPI iterable_view_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, IIterator_IKeyValuePair_HSTRING_IInspectable **value ) +{ + struct map_view *impl = view_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable( iface ); + struct iterator *iter; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!(iter = calloc( 1, sizeof(struct iterator) ))) return E_OUTOFMEMORY; + iter->IIterator_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &iterator_vtbl; + iter->iid = impl->iids.iterator; + iter->ref = 1; + + IMapView_HSTRING_IInspectable_AddRef( (iter->view = &impl->IMapView_HSTRING_IInspectable_iface) ); + *value = &iter->IIterator_IKeyValuePair_HSTRING_IInspectable_iface; + return S_OK; +} + +static const struct IIterable_IKeyValuePair_HSTRING_IInspectableVtbl iterable_view_vtbl = +{ + iterable_view_QueryInterface, + iterable_view_AddRef, + iterable_view_Release, + /* IInspectable methods */ + iterable_view_GetIids, + iterable_view_GetRuntimeClassName, + iterable_view_GetTrustLevel, + /* IIterable<T> methods */ + iterable_view_First, +}; + +static HRESULT map_view_create( const struct map_iids *iids, IMapView_HSTRING_IInspectable **out ) +{ + struct map_view *view; + + if (!(view = calloc( 1, sizeof(*view) ))) return E_OUTOFMEMORY; + view->IMapView_HSTRING_IInspectable_iface.lpVtbl = &map_view_vtbl; + view->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &iterable_view_vtbl; + view->iids = *iids; + view->ref = 1; + + *out = &view->IMapView_HSTRING_IInspectable_iface; + return S_OK; +} + +struct map +{ + IInspectable IInspectable_iface; + IMap_HSTRING_IInspectable IMap_HSTRING_IInspectable_iface; + IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + IInspectable *IInspectable_outer; + struct map_iids iids; + LONG ref; +}; + +static struct map *impl_from_IInspectable( IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct map, IInspectable_iface ); +} + +static HRESULT WINAPI map_inner_QueryInterface( IInspectable *iface, REFIID iid, void **out ) +{ + struct map *impl = impl_from_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject )) + { + IInspectable_AddRef( (*out = &impl->IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.map )) + { + IInspectable_AddRef( (*out = &impl->IMap_HSTRING_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI map_inner_AddRef( IInspectable *iface ) +{ + struct map *impl = impl_from_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI map_inner_Release( IInspectable *iface ) +{ + struct map *impl = impl_from_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IMap_HSTRING_IInspectable_Clear( &impl->IMap_HSTRING_IInspectable_iface ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI map_inner_GetIids( IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_inner_GetRuntimeClassName( IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_inner_GetTrustLevel( IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +const static IInspectableVtbl map_inner_vtbl = +{ + /* IUnknown */ + map_inner_QueryInterface, + map_inner_AddRef, + map_inner_Release, + /* IInspectable */ + map_inner_GetIids, + map_inner_GetRuntimeClassName, + map_inner_GetTrustLevel, +}; + +DEFINE_IINSPECTABLE_OUTER( map, IMap_HSTRING_IInspectable, struct map, IInspectable_outer ) + +static HRESULT WINAPI map_Lookup( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) +{ + FIXME( "iface %p, key %s, value %p stub!\n", iface, debugstr_hstring( key ), value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_get_Size( IMap_HSTRING_IInspectable *iface, UINT32 *size ) +{ + FIXME( "iface %p, size %p stub!\n", iface, size ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_HasKey( IMap_HSTRING_IInspectable *iface, HSTRING key, boolean *exists ) +{ + FIXME( "iface %p, key %s, exists %p stub!\n", iface, debugstr_hstring( key ), exists ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_GetView( IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **value ) +{ + struct map *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + TRACE( "iface %p, value %p.\n", iface, value ); + return map_view_create( &impl->iids, value ); +} + +static HRESULT WINAPI map_Insert( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable *value, boolean *replaced ) +{ + FIXME( "iface %p, key %p, value %p, replaced %p stub!\n", iface, key, value, replaced ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_Remove( IMap_HSTRING_IInspectable *iface, HSTRING key ) +{ + FIXME( "iface %p, key %s stub!\n", iface, debugstr_hstring( key ) ); + return E_NOTIMPL; +} + +static HRESULT WINAPI map_Clear( IMap_HSTRING_IInspectable *iface ) +{ + FIXME( "iface %p stub!\n", iface ); + return E_NOTIMPL; +} + +const static IMap_HSTRING_IInspectableVtbl map_vtbl = +{ + /* IUnknown */ + map_QueryInterface, + map_AddRef, + map_Release, + /* IInspectable */ + map_GetIids, + map_GetRuntimeClassName, + map_GetTrustLevel, + /* IMap<HSTRING, IInspectable *> */ + map_Lookup, + map_get_Size, + map_HasKey, + map_GetView, + map_Insert, + map_Remove, + map_Clear, +}; + +DEFINE_IINSPECTABLE_OUTER( iterable, IIterable_IKeyValuePair_HSTRING_IInspectable, struct map, IInspectable_outer ) + +static HRESULT WINAPI iterable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, IIterator_IKeyValuePair_HSTRING_IInspectable **value ) +{ + struct map *impl = impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable( iface ); + IIterable_IKeyValuePair_HSTRING_IInspectable *iterable; + IMapView_HSTRING_IInspectable *view; + HRESULT hr; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (FAILED(hr = IMap_HSTRING_IInspectable_GetView( &impl->IMap_HSTRING_IInspectable_iface, &view ))) return hr; + + hr = IMapView_HSTRING_IInspectable_QueryInterface( view, impl->iids.iterable, (void **)&iterable ); + IMapView_HSTRING_IInspectable_Release( view ); + if (FAILED(hr)) return hr; + + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, value ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); + return hr; +} + +static const struct IIterable_IKeyValuePair_HSTRING_IInspectableVtbl iterable_vtbl = +{ + iterable_QueryInterface, + iterable_AddRef, + iterable_Release, + /* IInspectable methods */ + iterable_GetIids, + iterable_GetRuntimeClassName, + iterable_GetTrustLevel, + /* IIterable<T> methods */ + iterable_First, +}; + +HRESULT map_create( const struct map_iids *iids, IInspectable *outer, void **out ) +{ + struct map *impl; + + TRACE( "iid %s, out %p.\n", debugstr_guid( iids->map ), out ); + + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IInspectable_iface.lpVtbl = &map_inner_vtbl; + impl->IMap_HSTRING_IInspectable_iface.lpVtbl = &map_vtbl; + impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &iterable_vtbl; + impl->IInspectable_outer = outer ? outer : (IInspectable *)&impl->IInspectable_iface; + impl->iids = *iids; + impl->ref = 1; + + *out = &impl->IInspectable_iface; + TRACE( "created %p\n", *out ); + return S_OK; +} diff --git a/dlls/wintypes/private.h b/dlls/wintypes/private.h index fe9e8cb951c..898b68c441b 100644 --- a/dlls/wintypes/private.h +++ b/dlls/wintypes/private.h @@ -39,6 +39,56 @@ #include "windows.storage.streams.h" #include "wintypes_private.h"
+struct map_iids +{ + const GUID *map; + const GUID *view; + const GUID *iterable; + const GUID *iterator; + const GUID *pair; +}; +extern HRESULT map_create( const struct map_iids *iids, IInspectable *outer, void **out ); + extern IActivationFactory *data_writer_activation_factory; extern IActivationFactory *buffer_activation_factory; extern IActivationFactory *property_set_factory; + +#define DEFINE_IINSPECTABLE_( 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) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) +#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface ) diff --git a/dlls/wintypes/propertyset.c b/dlls/wintypes/propertyset.c index 6a0ccc30c2b..52f345766ce 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -32,6 +32,9 @@ struct propertyset IObservableMap_HSTRING_IInspectable IObservableMap_HSTRING_IInspectable_iface; IMap_HSTRING_IInspectable IMap_HSTRING_IInspectable_iface; IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + SRWLOCK lock; + IMap_HSTRING_IInspectable *map; /* Guarded by lock */ + IIterable_IKeyValuePair_HSTRING_IInspectable *iterable; /* Guarded by lock */ LONG ref; };
@@ -40,6 +43,356 @@ static inline struct propertyset *impl_from_IPropertySet( IPropertySet *iface ) return CONTAINING_RECORD( iface, struct propertyset, IPropertySet_iface ); }
+struct propertyset_view +{ + IMapView_HSTRING_IInspectable IMapView_HSTRING_IInspectable_iface; + IIterable_IKeyValuePair_HSTRING_IInspectable IIterable_IKeyValuePair_HSTRING_IInspectable_iface; + struct propertyset *set; + IMapView_HSTRING_IInspectable *view; + IIterable_IKeyValuePair_HSTRING_IInspectable *view_iterable; + LONG ref; +}; + +static inline struct propertyset_view *impl_from_IMapView_HSTRING_IInspectable( IMapView_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct propertyset_view, IMapView_HSTRING_IInspectable_iface ); +} + +struct propertyset_iterator +{ + IIterator_IKeyValuePair_HSTRING_IInspectable IIterator_IKeyValuePair_HSTRING_IInspectable_iface; + struct propertyset *set; + IIterator_IKeyValuePair_HSTRING_IInspectable *iterator; + LONG ref; +}; + +static inline struct propertyset_iterator *impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct propertyset_iterator, IIterator_IKeyValuePair_HSTRING_IInspectable_iface ); +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_QueryInterface( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IIterator_IKeyValuePair_HSTRING_IInspectable )) + { + IIterator_IKeyValuePair_HSTRING_IInspectable_AddRef(( *out = &impl->IIterator_IKeyValuePair_HSTRING_IInspectable_iface )); + return S_OK; + } + + *out = NULL; + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return S_OK; +} + +static ULONG STDMETHODCALLTYPE propertyset_iterator_AddRef( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG STDMETHODCALLTYPE propertyset_iterator_Release( IIterator_IKeyValuePair_HSTRING_IInspectable *iface ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( impl->iterator ); + IPropertySet_Release( &impl->set->IPropertySet_iface ); + free( impl ); + } + return ref; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_GetIids( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_GetRuntimeClassName( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_GetTrustLevel( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_get_Current( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, + IKeyValuePair_HSTRING_IInspectable **value ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, value %p\n", iface, value ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( impl->iterator, value ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_get_HasCurrent( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *value ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, value %p\n", iface, value ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_HasCurrent( impl->iterator, value ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_MoveNext( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, boolean *value ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + HRESULT hr = S_OK; + + TRACE( "iface %p, value %p\n", iface, value ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( impl->iterator, value ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_iterator_GetMany( IIterator_IKeyValuePair_HSTRING_IInspectable *iface, UINT32 items_size, + IKeyValuePair_HSTRING_IInspectable **items, UINT *count ) +{ + struct propertyset_iterator *impl = impl_from_IIterator_IKeyValuePair_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, items_size %u, items %p, count %p\n", iface, items_size, items, count ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_GetMany( impl->iterator, items_size, items, count ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static const IIterator_IKeyValuePair_HSTRING_IInspectableVtbl propertyset_IIterator_vtbl = +{ + /* IUnknown */ + propertyset_iterator_QueryInterface, + propertyset_iterator_AddRef, + propertyset_iterator_Release, + /* IInspectable */ + propertyset_iterator_GetIids, + propertyset_iterator_GetRuntimeClassName, + propertyset_iterator_GetTrustLevel, + /* IIterable*/ + propertyset_iterator_get_Current, + propertyset_iterator_get_HasCurrent, + propertyset_iterator_MoveNext, + propertyset_iterator_GetMany +}; + +static HRESULT create_propertyset_iterator( struct propertyset *set, IIterable_IKeyValuePair_HSTRING_IInspectable *iterable, + IIterator_IKeyValuePair_HSTRING_IInspectable **out ) +{ + struct propertyset_iterator *impl; + HRESULT hr; + + *out = NULL; + if (!(impl = calloc( 1, sizeof( *impl )))) return E_OUTOFMEMORY; + + impl->IIterator_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &propertyset_IIterator_vtbl; + impl->ref = 1; + impl->set = set; + IPropertySet_AddRef( &set->IPropertySet_iface ); + AcquireSRWLockShared( &set->lock ); + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &impl->iterator ); + ReleaseSRWLockShared( &set->lock ); + if (FAILED(hr)) + { + IPropertySet_Release( &set->IPropertySet_iface ); + free( impl ); + return hr; + } + *out = &impl->IIterator_IKeyValuePair_HSTRING_IInspectable_iface; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_QueryInterface( IMapView_HSTRING_IInspectable *iface, REFIID iid, void **out ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + + TRACE( "(%p, %s, %p)\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IMapView_HSTRING_IInspectable )) + { + IMapView_HSTRING_IInspectable_AddRef(( *out = &impl->IMapView_HSTRING_IInspectable_iface )); + return S_OK; + } + if (IsEqualGUID( iid, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable )) + { + IIterable_IKeyValuePair_HSTRING_IInspectable_AddRef(( *out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface )); + return S_OK; + } + + *out = NULL; + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return S_OK; +} + +static ULONG STDMETHODCALLTYPE propertyset_view_AddRef( IMapView_HSTRING_IInspectable *iface ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG STDMETHODCALLTYPE propertyset_view_Release( IMapView_HSTRING_IInspectable *iface ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IMapView_HSTRING_IInspectable_Release( impl->view ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( impl->view_iterable ); + IPropertySet_Release( &impl->set->IPropertySet_iface ); + free( impl ); + } + return ref; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_GetIids( IMapView_HSTRING_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_GetRuntimeClassName( IMapView_HSTRING_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_GetTrustLevel( IMapView_HSTRING_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_Lookup( IMapView_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, key %s, value %p\n", iface, debugstr_hstring( key ), value ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IMapView_HSTRING_IInspectable_Lookup( impl->view, key, value ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_get_Size( IMapView_HSTRING_IInspectable *iface, UINT32 *value ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + HRESULT hr = S_OK; + + TRACE( "iface %p, value %p\n", iface, value ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IMapView_HSTRING_IInspectable_get_Size( impl->view, value ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_HasKey( IMapView_HSTRING_IInspectable *iface, HSTRING key, boolean *found ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, key %s, found %p\n", iface, debugstr_hstring( key ), found ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IMapView_HSTRING_IInspectable_HasKey( impl->view, key, found ); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +static HRESULT STDMETHODCALLTYPE propertyset_view_Split( IMapView_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **first, + IMapView_HSTRING_IInspectable **second ) +{ + struct propertyset_view *impl = impl_from_IMapView_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, first %p, second %p\n", iface, first, second ); + + AcquireSRWLockShared( &impl->set->lock ); + hr = IMapView_HSTRING_IInspectable_Split( impl->view, first, second); + ReleaseSRWLockShared( &impl->set->lock ); + return hr; +} + +DEFINE_IINSPECTABLE_( propertyset_view_iterable, IIterable_IKeyValuePair_HSTRING_IInspectable, struct propertyset_view, + view_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable, IIterable_IKeyValuePair_HSTRING_IInspectable_iface, + &impl->IMapView_HSTRING_IInspectable_iface ); + +static HRESULT STDMETHODCALLTYPE propertyset_view_iterable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, + IIterator_IKeyValuePair_HSTRING_IInspectable **value ) +{ + struct propertyset_view *impl = view_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable( iface ); + TRACE( "iface %p, value %p\n", iface, value ); + return create_propertyset_iterator( impl->set, impl->view_iterable, value ); +} + +static const struct IIterable_IKeyValuePair_HSTRING_IInspectableVtbl propertyset_view_IIterable_vtbl = +{ + /* IUnknown */ + propertyset_view_iterable_QueryInterface, + propertyset_view_iterable_AddRef, + propertyset_view_iterable_Release, + /* IInspectable */ + propertyset_view_iterable_GetIids, + propertyset_view_iterable_GetRuntimeClassName, + propertyset_view_iterable_GetTrustLevel, + /* IIterable_HSTRING_IInspectable */ + propertyset_view_iterable_First +}; + +static const IMapView_HSTRING_IInspectableVtbl propertyset_view_vtbl = +{ + /* IUnknown */ + propertyset_view_QueryInterface, + propertyset_view_AddRef, + propertyset_view_Release, + /* IMapView_HSTRING_IInspectable */ + propertyset_view_GetIids, + propertyset_view_GetRuntimeClassName, + propertyset_view_GetTrustLevel, + propertyset_view_Lookup, + propertyset_view_get_Size, + propertyset_view_HasKey, + propertyset_view_Split, +}; + static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface, REFIID iid, void **out ) { struct propertyset *impl = impl_from_IPropertySet( iface ); @@ -48,6 +401,7 @@ static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface
*out = NULL; if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IAgileObject ) || IsEqualGUID( iid, &IID_IInspectable ) || IsEqualGUID( iid, &IID_IPropertySet )) { @@ -64,13 +418,13 @@ static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface else if (IsEqualGUID( iid, &IID_IMap_HSTRING_IInspectable )) { *out = &impl->IMap_HSTRING_IInspectable_iface; - IUnknown_AddRef( (IUnknown *)iface ); + IUnknown_AddRef( (IUnknown *)*out ); return S_OK; } else if (IsEqualGUID( iid, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable )) { *out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface; - IUnknown_AddRef( (IUnknown *)iface ); + IUnknown_AddRef( (IUnknown *)*out ); return S_OK; }
@@ -81,22 +435,25 @@ static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface static ULONG STDMETHODCALLTYPE propertyset_AddRef( IPropertySet *iface ) { struct propertyset *impl = impl_from_IPropertySet( iface ); - - TRACE( "(%p)\n", iface ); - - return InterlockedIncrement( &impl->ref ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; }
static ULONG STDMETHODCALLTYPE propertyset_Release( IPropertySet *iface ) { struct propertyset *impl = impl_from_IPropertySet( iface ); - ULONG ref; + ULONG ref = InterlockedDecrement( &impl->ref );
- TRACE( "(%p)\n", iface ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
- ref = InterlockedDecrement( &impl->ref ); if (!ref) + { + IMap_HSTRING_IInspectable_Release( impl->map ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( impl->iterable ); free( impl ); + } + return ref; }
@@ -118,137 +475,209 @@ static HRESULT STDMETHODCALLTYPE propertyset_GetTrustLevel( IPropertySet *iface, return E_NOTIMPL; }
-static const IPropertySetVtbl propertyset_vtbl = +DEFINE_IINSPECTABLE_( propertyset_map, IMap_HSTRING_IInspectable, struct propertyset, impl_from_IMap_HSTRING_IInspectable, IMap_HSTRING_IInspectable_iface, + &impl->IPropertySet_iface ) + +static HRESULT STDMETHODCALLTYPE propertyset_map_Lookup( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) { - /* IUnknown */ - propertyset_QueryInterface, - propertyset_AddRef, - propertyset_Release, - /* IInspectable */ - propertyset_GetIids, - propertyset_GetRuntimeClassName, - propertyset_GetTrustLevel, -}; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr;
-DEFINE_IINSPECTABLE( propertyset_IObservableMap, IObservableMap_HSTRING_IInspectable, struct propertyset, IPropertySet_iface ); + TRACE( "iface %p, key %s, value %p\n", iface, debugstr_hstring( key ), value );
-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; + AcquireSRWLockShared( &impl->lock ); + hr = IMap_HSTRING_IInspectable_Lookup( impl->map, key, value ); + ReleaseSRWLockShared( &impl->lock ); + return hr; }
-static HRESULT STDMETHODCALLTYPE propertyset_IObservableMap_remove_MapChanged( IObservableMap_HSTRING_IInspectable *iface, EventRegistrationToken token ) +static HRESULT STDMETHODCALLTYPE propertyset_map_get_Size( IMap_HSTRING_IInspectable *iface, UINT32 *size ) { - FIXME( "(%p, %I64d) stub!\n", iface, token.value ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, size %p\n", iface, size ); + + AcquireSRWLockShared( &impl->lock ); + hr = IMap_HSTRING_IInspectable_get_Size( impl->map, size ); + ReleaseSRWLockShared( &impl->lock ); + return hr; }
-const static IObservableMap_HSTRING_IInspectableVtbl propertyset_IObservableMap_vtbl = +static HRESULT STDMETHODCALLTYPE propertyset_map_HasKey( IMap_HSTRING_IInspectable *iface, HSTRING key, boolean *exists ) { - /* 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, -}; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr;
-DEFINE_IINSPECTABLE( propertyset_IMap, IMap_HSTRING_IInspectable, struct propertyset, - IPropertySet_iface ); + TRACE( "iface %p, key %s, exists %p\n", iface, debugstr_hstring( key ), exists );
-static HRESULT STDMETHODCALLTYPE propertyset_Lookup( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable **value ) -{ - FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), value ); - return E_NOTIMPL; + AcquireSRWLockShared( &impl->lock ); + hr = IMap_HSTRING_IInspectable_HasKey( impl->map, key, exists ); + ReleaseSRWLockShared( &impl->lock ); + return hr; }
-static HRESULT STDMETHODCALLTYPE propertyset_get_Size( IMap_HSTRING_IInspectable *iface, UINT32 *size ) +static HRESULT STDMETHODCALLTYPE propertyset_map_GetView( IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **value ) { - FIXME( "(%p, %p) stub!\n", iface, size ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + struct propertyset_view *view; + HRESULT hr; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!(view = calloc( 1, sizeof(*view) ))) return E_OUTOFMEMORY; + view->IMapView_HSTRING_IInspectable_iface.lpVtbl = &propertyset_view_vtbl; + view->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &propertyset_view_IIterable_vtbl; + view->ref = 1; + view->set = impl; + IPropertySet_AddRef( &view->set->IPropertySet_iface ); + AcquireSRWLockShared( &impl->lock ); + hr = IMap_HSTRING_IInspectable_GetView( impl->map, &view->view ); + ReleaseSRWLockShared( &impl->lock ); + if (FAILED(hr)) + { + IPropertySet_Release( &view->set->IPropertySet_iface ); + free( view ); + return hr; + } + hr = IMapView_HSTRING_IInspectable_QueryInterface( view->view, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&view->view_iterable ); + if (FAILED(hr)) + { + IMapView_HSTRING_IInspectable_Release( view->view ); + IPropertySet_Release( &view->set->IPropertySet_iface ); + free( view ); + return hr; + } + *value = &view->IMapView_HSTRING_IInspectable_iface; + return S_OK; }
-static HRESULT STDMETHODCALLTYPE propertyset_HasKey( IMap_HSTRING_IInspectable *iface, HSTRING key, boolean *exists ) +static HRESULT STDMETHODCALLTYPE propertymap_map_Insert( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable *value, boolean *replaced ) { - FIXME( "(%p, %s, %p) stub!\n", iface, debugstr_hstring( key ), exists ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, key %p, value %p, replaced %p\n", iface, key, value, replaced ); + + AcquireSRWLockExclusive( &impl->lock ); + hr = IMap_HSTRING_IInspectable_Insert( impl->map, key, value, replaced ); + ReleaseSRWLockExclusive( &impl->lock ); + return hr; }
-static HRESULT STDMETHODCALLTYPE propertyset_GetView( IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **view ) +static HRESULT STDMETHODCALLTYPE propertyset_map_Remove( IMap_HSTRING_IInspectable *iface, HSTRING key ) { - FIXME( "(%p, %p) stub!\n", iface, view ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p, key %s\n", iface, debugstr_hstring( key ) ); + + AcquireSRWLockExclusive( &impl->lock ); + hr = IMap_HSTRING_IInspectable_Remove( impl->map, key ); + ReleaseSRWLockExclusive( &impl->lock ); + return hr; }
-static HRESULT STDMETHODCALLTYPE propertyset_Insert( IMap_HSTRING_IInspectable *iface, HSTRING key, IInspectable *value, boolean *replaced ) +static HRESULT STDMETHODCALLTYPE propertyset_map_Clear( IMap_HSTRING_IInspectable *iface ) { - FIXME( "(%p, %s, %p, %p) stub!\n", iface, debugstr_hstring( key ), value, replaced ); - return E_NOTIMPL; + struct propertyset *impl = impl_from_IMap_HSTRING_IInspectable( iface ); + HRESULT hr; + + TRACE( "iface %p\n", iface ); + + AcquireSRWLockExclusive( &impl->lock ); + hr = IMap_HSTRING_IInspectable_Clear( impl->map ); + ReleaseSRWLockExclusive( &impl->lock ); + return hr; }
-static HRESULT STDMETHODCALLTYPE propertyset_Remove( IMap_HSTRING_IInspectable *iface, HSTRING key ) +static const IMap_HSTRING_IInspectableVtbl propertyset_IMap_vtbl = { - FIXME( "(%p, %s) stub!\n", iface, debugstr_hstring( key ) ); - return E_NOTIMPL; -} + /* IUnknown */ + propertyset_map_QueryInterface, + propertyset_map_AddRef, + propertyset_map_Release, + /* IInspectable */ + propertyset_map_GetIids, + propertyset_map_GetRuntimeClassName, + propertyset_map_GetTrustLevel, + /* IMap_HSTRING_IInspectable */ + propertyset_map_Lookup, + propertyset_map_get_Size, + propertyset_map_HasKey, + propertyset_map_GetView, + propertymap_map_Insert, + propertyset_map_Remove, + propertyset_map_Clear +}; + +DEFINE_IINSPECTABLE_( propertyset_map_iterable, IIterable_IKeyValuePair_HSTRING_IInspectable, struct propertyset, + map_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable, IIterable_IKeyValuePair_HSTRING_IInspectable_iface, + &impl->IPropertySet_iface )
-static HRESULT STDMETHODCALLTYPE propertyset_Clear( IMap_HSTRING_IInspectable *iface ) +static HRESULT STDMETHODCALLTYPE propertyset_map_iterable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, + IIterator_IKeyValuePair_HSTRING_IInspectable **value ) { - FIXME( "(%p) stub!\n", iface ); - return E_NOTIMPL; + struct propertyset *impl = map_impl_from_IIterable_IKeyValuePair_HSTRING_IInspectable( iface ); + TRACE( "iface %p, value %p\n", iface, value ); + return create_propertyset_iterator( impl, impl->iterable, value ); }
-const static IMap_HSTRING_IInspectableVtbl propertyset_IMap_vtbl = +static const IIterable_IKeyValuePair_HSTRING_IInspectableVtbl propertyset_IIterable_vtbl = { /* IUnknown */ - propertyset_IMap_QueryInterface, - propertyset_IMap_AddRef, - propertyset_IMap_Release, + propertyset_map_iterable_QueryInterface, + propertyset_map_iterable_AddRef, + propertyset_map_iterable_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, + propertyset_map_iterable_GetIids, + propertyset_map_iterable_GetRuntimeClassName, + propertyset_map_iterable_GetTrustLevel, + /* IIterable_IKeyValuePair_HSTRING_IInspectable */ + propertyset_map_iterable_First, };
-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 const IPropertySetVtbl propertyset_vtbl = +{ + /* IUnknown */ + propertyset_QueryInterface, + propertyset_AddRef, + propertyset_Release, + /* IInspectable */ + propertyset_GetIids, + propertyset_GetRuntimeClassName, + 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 iterable_kvpair_HSTRING_IInspectable_First( IIterable_IKeyValuePair_HSTRING_IInspectable *iface, - IIterator_IKeyValuePair_HSTRING_IInspectable **iter ) +static HRESULT STDMETHODCALLTYPE propertyset_IObservableMap_remove_MapChanged( IObservableMap_HSTRING_IInspectable *iface, EventRegistrationToken token ) { - FIXME( "(%p, %p) stub!\n", iface, iter ); + FIXME( "(%p, %I64d) stub!\n", iface, token.value ); return E_NOTIMPL; }
-const static IIterable_IKeyValuePair_HSTRING_IInspectableVtbl iterable_kvpair_HSTRING_IInspectable_vtbl = +const static IObservableMap_HSTRING_IInspectableVtbl propertyset_IObservableMap_vtbl = { /* IUnknown */ - iterable_kvpair_HSTRING_IInspectable_QueryInterface, - iterable_kvpair_HSTRING_IInspectable_AddRef, - iterable_kvpair_HSTRING_IInspectable_Release, + propertyset_IObservableMap_QueryInterface, + propertyset_IObservableMap_AddRef, + propertyset_IObservableMap_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 + propertyset_IObservableMap_GetIids, + propertyset_IObservableMap_GetRuntimeClassName, + propertyset_IObservableMap_GetTrustLevel, + /* IObservableMap<HSTRING, IInspectable*> */ + propertyset_IObservableMap_add_MapChanged, + propertyset_IObservableMap_remove_MapChanged, };
struct propertyset_factory @@ -314,7 +743,18 @@ static HRESULT STDMETHODCALLTYPE factory_GetTrustLevel( IActivationFactory *ifac
static HRESULT STDMETHODCALLTYPE factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) { + static const struct map_iids iids = + { + .map = &IID_IMap_HSTRING_IInspectable, + .view = &IID_IMapView_HSTRING_IInspectable, + .iterable = &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, + .iterator = &IID_IIterator_IKeyValuePair_HSTRING_IInspectable, + .pair = &IID_IKeyValuePair_HSTRING_IInspectable, + }; + struct propertyset *impl; + IInspectable *map; + HRESULT hr;
TRACE( "(%p, %p)\n", iface, instance );
@@ -325,8 +765,28 @@ static HRESULT STDMETHODCALLTYPE factory_ActivateInstance( IActivationFactory *i impl->IPropertySet_iface.lpVtbl = &propertyset_vtbl; 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->IIterable_IKeyValuePair_HSTRING_IInspectable_iface.lpVtbl = &propertyset_IIterable_vtbl; impl->ref = 1; + InitializeSRWLock( &impl->lock ); + + if (FAILED(hr = map_create( &iids, NULL, (void **)&map ))) + { + free( impl ); + return hr; + } + hr = IInspectable_QueryInterface( map, &IID_IMap_HSTRING_IInspectable, (void **)&impl->map ); + IInspectable_Release( map ); + if (FAILED( hr )) + { + free( impl ); + return hr; + } + if (FAILED(hr = IMap_HSTRING_IInspectable_QueryInterface( impl->map, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&impl->iterable ))) + { + IMap_HSTRING_IInspectable_Release( impl->map ); + free( impl ); + return hr; + } *instance = (IInspectable *)&impl->IPropertySet_iface; return S_OK; } diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 81e7d65a494..8a54a6b2d17 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -1443,32 +1443,20 @@ static void test_IPropertySet(void) (void **)&iterable ); ok( hr == S_OK, "QueryInterface failed, got %#lx\n", hr ); hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); - todo_wine ok( hr == S_OK, "got %#lx\n", hr ); - if (SUCCEEDED( hr )) - IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable );
hr = IMap_HSTRING_IInspectable_GetView( map, &map_view ); - todo_wine ok( hr == S_OK, "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( hr == S_OK, "QueryInterface failed, got %#lx\n", hr ); - if (SUCCEEDED( hr )) - { - hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); - todo_wine - ok( hr == S_OK, "got %#lx\n", hr ); - if (SUCCEEDED( hr )) - IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); - IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); - } - IMapView_HSTRING_IInspectable_Release( map_view ); - } + hr = IMapView_HSTRING_IInspectable_QueryInterface( map_view, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, + (void **)&iterable ); + ok( hr == S_OK, "QueryInterface failed, got %#lx\n", hr ); + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); + ok( hr == S_OK, "got %#lx\n", hr ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); + IMapView_HSTRING_IInspectable_Release( map_view ); IMap_HSTRING_IInspectable_Release( map ); IPropertyValueStatics_Release( propval_statics ); done: diff --git a/dlls/wintypes/wintypes_private.idl b/dlls/wintypes/wintypes_private.idl index b0d7b7d2241..33cfbed210b 100644 --- a/dlls/wintypes/wintypes_private.idl +++ b/dlls/wintypes/wintypes_private.idl @@ -27,42 +27,3 @@ import "windows.foundation.idl"; declare { interface Windows.Foundation.IReference<HSTRING>; } - -cpp_quote("#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \") -cpp_quote(" static inline impl_type *impl_from( iface_type *iface ) \") -cpp_quote(" { \") -cpp_quote(" return CONTAINING_RECORD( iface, impl_type, iface_mem ); \") -cpp_quote(" } \") -cpp_quote(" static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \") -cpp_quote(" } \") -cpp_quote(" static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_AddRef( (IInspectable *)(expr) ); \") -cpp_quote(" } \") -cpp_quote(" static ULONG WINAPI pfx##_Release( iface_type *iface ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_Release( (IInspectable *)(expr) ); \") -cpp_quote(" } \") -cpp_quote(" static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \") -cpp_quote(" } \") -cpp_quote(" static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \") -cpp_quote(" } \") -cpp_quote(" static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \") -cpp_quote(" { \") -cpp_quote(" impl_type *impl = impl_from( iface ); \") -cpp_quote(" return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \") -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 )")