From e3b1d818afb85343e8d53360e58a63d2f2616f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Wed, 9 Mar 2022 09:48:00 +0100 Subject: [PATCH] windows.gaming.input: Implement IIterable and IIterator interfaces. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the generic vector implementation. Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/windows.gaming.input/controller.c | 11 +- dlls/windows.gaming.input/gamepad.c | 11 +- dlls/windows.gaming.input/private.h | 9 +- dlls/windows.gaming.input/vector.c | 243 +++++++++++++++++++++++-- include/windows.gaming.input.idl | 8 +- 5 files changed, 259 insertions(+), 23 deletions(-) diff --git a/dlls/windows.gaming.input/controller.c b/dlls/windows.gaming.input/controller.c index 9b08528b01b..9fb1b1a69a2 100644 --- a/dlls/windows.gaming.input/controller.c +++ b/dlls/windows.gaming.input/controller.c @@ -381,14 +381,19 @@ static HRESULT WINAPI statics_remove_RawGameControllerRemoved( IRawGameControlle static HRESULT WINAPI statics_get_RawGameControllers( IRawGameControllerStatics *iface, IVectorView_RawGameController **value ) { - static const GUID *view_iid = &IID_IVectorView_RawGameController; - static const GUID *iid = &IID_IVector_RawGameController; + static const struct vector_iids iids = + { + .vector = &IID_IVector_RawGameController, + .view = &IID_IVectorView_RawGameController, + .iterable = &IID_IIterable_RawGameController, + .iterator = &IID_IIterator_RawGameController, + }; IVector_RawGameController *controllers; HRESULT hr; TRACE( "iface %p, value %p.\n", iface, value ); - if (SUCCEEDED(hr = vector_create( iid, view_iid, (void **)&controllers ))) + if (SUCCEEDED(hr = vector_create( &iids, (void **)&controllers ))) { hr = IVector_RawGameController_GetView( controllers, value ); IVector_RawGameController_Release( controllers ); diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c index 3fdf852ac1f..172ca74e3f6 100644 --- a/dlls/windows.gaming.input/gamepad.c +++ b/dlls/windows.gaming.input/gamepad.c @@ -341,14 +341,19 @@ static HRESULT WINAPI statics_remove_GamepadRemoved( IGamepadStatics *iface, Eve static HRESULT WINAPI statics_get_Gamepads( IGamepadStatics *iface, IVectorView_Gamepad **value ) { - static const GUID *view_iid = &IID_IVectorView_Gamepad; - static const GUID *iid = &IID_IVector_Gamepad; + static const struct vector_iids iids = + { + .vector = &IID_IVector_Gamepad, + .view = &IID_IVectorView_Gamepad, + .iterable = &IID_IIterable_Gamepad, + .iterator = &IID_IIterator_Gamepad, + }; IVector_Gamepad *gamepads; HRESULT hr; TRACE( "iface %p, value %p.\n", iface, value ); - if (SUCCEEDED(hr = vector_create( iid, view_iid, (void **)&gamepads ))) + if (SUCCEEDED(hr = vector_create( &iids, (void **)&gamepads ))) { hr = IVector_Gamepad_GetView( gamepads, value ); IVector_Gamepad_Release( gamepads ); diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h index e3da45621b4..5d5f48d12e7 100644 --- a/dlls/windows.gaming.input/private.h +++ b/dlls/windows.gaming.input/private.h @@ -41,7 +41,14 @@ extern ICustomGameControllerFactory *controller_factory; extern ICustomGameControllerFactory *gamepad_factory; extern IGameControllerFactoryManagerStatics2 *manager_factory; -extern HRESULT vector_create( REFIID iid, REFIID view_iid, void **out ); +struct vector_iids +{ + const GUID *vector; + const GUID *view; + const GUID *iterable; + const GUID *iterator; +}; +extern HRESULT vector_create( const struct vector_iids *iids, void **out ); extern void provider_create( const WCHAR *device_path ); extern void provider_remove( const WCHAR *device_path ); diff --git a/dlls/windows.gaming.input/vector.c b/dlls/windows.gaming.input/vector.c index 441c13dab4c..10dac5a5547 100644 --- a/dlls/windows.gaming.input/vector.c +++ b/dlls/windows.gaming.input/vector.c @@ -23,10 +23,144 @@ WINE_DEFAULT_DEBUG_CHANNEL(combase); +struct iterator +{ + IIterator_IInspectable IIterator_IInspectable_iface; + const GUID *iid; + LONG ref; + + IVectorView_IInspectable *view; + UINT32 index; + UINT32 size; +}; + +static inline struct iterator *impl_from_IIterator_IInspectable( IIterator_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator, IIterator_IInspectable_iface ); +} + +static HRESULT WINAPI iterator_QueryInterface( IIterator_IInspectable *iface, REFIID iid, void **out ) +{ + struct iterator *impl = impl_from_IIterator_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_IInspectable_iface) ); + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI iterator_AddRef( IIterator_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_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_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IVectorView_IInspectable_Release( impl->view ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI iterator_GetIids( IIterator_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_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_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_IInspectable *iface, IInspectable **value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + return IVectorView_IInspectable_GetAt( impl->view, impl->index, value ); +} + +static HRESULT WINAPI iterator_get_HasCurrent( IIterator_IInspectable *iface, BOOL *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + *value = impl->index < impl->size; + return S_OK; +} + +static HRESULT WINAPI iterator_MoveNext( IIterator_IInspectable *iface, BOOL *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + if ((*value = impl->index < impl->size)) impl->index++; + return S_OK; +} + +static HRESULT WINAPI iterator_GetMany( IIterator_IInspectable *iface, UINT32 items_size, + IInspectable **items, UINT *count ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + return IVectorView_IInspectable_GetMany( impl->view, impl->index, items_size, items, count ); +} + +static const IIterator_IInspectableVtbl iterator_vtbl = +{ + iterator_QueryInterface, + iterator_AddRef, + iterator_Release, + /* IInspectable methods */ + iterator_GetIids, + iterator_GetRuntimeClassName, + iterator_GetTrustLevel, + /* IIterator methods */ + iterator_get_Current, + iterator_get_HasCurrent, + iterator_MoveNext, + iterator_GetMany, +}; + struct vector_view { IVectorView_IInspectable IVectorView_IInspectable_iface; - const GUID *iid; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; LONG ref; UINT32 size; @@ -47,10 +181,15 @@ static HRESULT WINAPI vector_view_QueryInterface( IVectorView_IInspectable *ifac if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IInspectable ) || IsEqualGUID( iid, &IID_IAgileObject ) || - IsEqualGUID( iid, impl->iid )) + IsEqualGUID( iid, impl->iids.view )) { - IUnknown_AddRef( iface ); - *out = iface; + IInspectable_AddRef( (*out = &impl->IVectorView_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); return S_OK; } @@ -176,11 +315,46 @@ static const struct IVectorView_IInspectableVtbl vector_view_vtbl = vector_view_GetMany, }; +DEFINE_IINSPECTABLE_( iterable_view, IIterable_IInspectable, struct vector_view, view_impl_from_IIterable_IInspectable, + IIterable_IInspectable_iface, &impl->IVectorView_IInspectable_iface ) + +static HRESULT WINAPI iterable_view_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector_view *impl = view_impl_from_IIterable_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_IInspectable_iface.lpVtbl = &iterator_vtbl; + iter->iid = impl->iids.iterator; + iter->ref = 1; + + IVectorView_IInspectable_AddRef( (iter->view = &impl->IVectorView_IInspectable_iface) ); + iter->size = impl->size; + + *value = &iter->IIterator_IInspectable_iface; + return S_OK; +} + +static const struct IIterable_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 methods */ + iterable_view_First, +}; + struct vector { IVector_IInspectable IVector_IInspectable_iface; - const GUID *iid; - const GUID *view_iid; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; LONG ref; UINT32 size; @@ -202,10 +376,15 @@ static HRESULT WINAPI vector_QueryInterface( IVector_IInspectable *iface, REFIID if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IInspectable ) || IsEqualGUID( iid, &IID_IAgileObject ) || - IsEqualGUID( iid, impl->iid )) + IsEqualGUID( iid, impl->iids.vector )) { - IUnknown_AddRef( iface ); - *out = iface; + IInspectable_AddRef( (*out = &impl->IVector_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); return S_OK; } @@ -287,7 +466,8 @@ static HRESULT WINAPI vector_GetView( IVector_IInspectable *iface, IVectorView_I if (!(view = calloc( 1, offsetof( struct vector_view, elements[impl->size] ) ))) return E_OUTOFMEMORY; view->IVectorView_IInspectable_iface.lpVtbl = &vector_view_vtbl; - view->iid = impl->view_iid; + view->IIterable_IInspectable_iface.lpVtbl = &iterable_view_vtbl; + view->iids = impl->iids; view->ref = 1; for (i = 0; i < impl->size; ++i) IInspectable_AddRef( (view->elements[view->size++] = impl->elements[i]) ); @@ -446,16 +626,51 @@ static const struct IVector_IInspectableVtbl vector_vtbl = vector_ReplaceAll, }; -HRESULT vector_create( REFIID iid, REFIID view_iid, void **out ) +DEFINE_IINSPECTABLE( iterable, IIterable_IInspectable, struct vector, IVector_IInspectable_iface ) + +static HRESULT WINAPI iterable_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector *impl = impl_from_IIterable_IInspectable( iface ); + IIterable_IInspectable *iterable; + IVectorView_IInspectable *view; + HRESULT hr; + + TRACE("\n"); + + if (FAILED(hr = IVector_IInspectable_GetView( &impl->IVector_IInspectable_iface, &view ))) return hr; + + hr = IVectorView_IInspectable_QueryInterface( view, impl->iids.iterable, (void **)&iterable ); + IVectorView_IInspectable_Release( view ); + if (FAILED(hr)) return hr; + + hr = IIterable_IInspectable_First( iterable, value ); + IIterable_IInspectable_Release( iterable ); + return hr; +} + +static const struct IIterable_IInspectableVtbl iterable_vtbl = +{ + iterable_QueryInterface, + iterable_AddRef, + iterable_Release, + /* IInspectable methods */ + iterable_GetIids, + iterable_GetRuntimeClassName, + iterable_GetTrustLevel, + /* IIterable methods */ + iterable_First, +}; + +HRESULT vector_create( const struct vector_iids *iids, void **out ) { struct vector *impl; - TRACE( "iid %s, out %p.\n", debugstr_guid( iid ), out ); + TRACE( "iid %s, out %p.\n", debugstr_guid( iids->vector ), out ); if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; impl->IVector_IInspectable_iface.lpVtbl = &vector_vtbl; - impl->iid = iid; - impl->view_iid = view_iid; + impl->IIterable_IInspectable_iface.lpVtbl = &iterable_vtbl; + impl->iids = *iids; impl->ref = 1; *out = &impl->IVector_IInspectable_iface; diff --git a/include/windows.gaming.input.idl b/include/windows.gaming.input.idl index 5bf94f78820..4e9bb6e2465 100644 --- a/include/windows.gaming.input.idl +++ b/include/windows.gaming.input.idl @@ -56,8 +56,12 @@ namespace Windows.Gaming.Input { interface Windows.Foundation.EventHandler; interface Windows.Foundation.TypedEventHandler; interface Windows.Foundation.TypedEventHandler; - interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IIterator; + interface Windows.Foundation.Collections.IIterable; + interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IIterator; + interface Windows.Foundation.Collections.IIterable; interface Windows.Foundation.Collections.IVectorView; interface Windows.Foundation.Collections.IVector; }