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 | 144 ++----- dlls/wintypes/tests/wintypes.c | 30 +- dlls/wintypes/wintypes_private.idl | 39 -- 6 files changed, 730 insertions(+), 172 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..c486ab2f432 100644 --- a/dlls/wintypes/propertyset.c +++ b/dlls/wintypes/propertyset.c @@ -30,9 +30,9 @@ 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; + + IMap_HSTRING_IInspectable *IMap_HSTRING_IInspectable_inner; };
static inline struct propertyset *impl_from_IPropertySet( IPropertySet *iface ) @@ -61,18 +61,9 @@ static HRESULT STDMETHODCALLTYPE propertyset_QueryInterface( IPropertySet *iface IUnknown_AddRef( (IUnknown *)*out ); return S_OK; } - else if (IsEqualGUID( iid, &IID_IMap_HSTRING_IInspectable )) - { - *out = &impl->IMap_HSTRING_IInspectable_iface; - IUnknown_AddRef( (IUnknown *)iface ); - return S_OK; - } - else if (IsEqualGUID( iid, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable )) - { - *out = &impl->IIterable_IKeyValuePair_HSTRING_IInspectable_iface; - IUnknown_AddRef( (IUnknown *)iface ); + + if (SUCCEEDED(IMap_HSTRING_IInspectable_QueryInterface( impl->IMap_HSTRING_IInspectable_inner, iid, out ))) return S_OK; - }
FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); return E_NOINTERFACE; @@ -81,22 +72,26 @@ 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) + { + /* guard against re-entry if inner releases an outer iface */ + InterlockedIncrement( &impl->ref ); + IMap_HSTRING_IInspectable_Release( impl->IMap_HSTRING_IInspectable_inner ); free( impl ); + } + return ref; }
@@ -161,96 +156,6 @@ const static IObservableMap_HSTRING_IInspectableVtbl propertyset_IObservableMap_ 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 ); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE propertyset_get_Size( IMap_HSTRING_IInspectable *iface, UINT32 *size ) -{ - FIXME( "(%p, %p) stub!\n", iface, size ); - 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 ); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE propertyset_GetView( IMap_HSTRING_IInspectable *iface, IMapView_HSTRING_IInspectable **view ) -{ - FIXME( "(%p, %p) stub!\n", iface, view ); - 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 ); - 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 ) -{ - FIXME( "(%p, %p) stub!\n", iface, 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 -}; - struct propertyset_factory { IActivationFactory IActivationFactory_iface; @@ -314,7 +219,17 @@ 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; + HRESULT hr;
TRACE( "(%p, %p)\n", iface, instance );
@@ -324,9 +239,14 @@ 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->ref = 1; + + if (FAILED(hr = map_create( &iids, (IInspectable *)&impl->IPropertySet_iface, (void *)&impl->IMap_HSTRING_IInspectable_inner ))) + { + 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 )")