[PATCH 1/5] windows.gaming.input: Instantiate IGameController(BatteryInfo) stub from providers.
Rémi Bernon
rbernon at codeweavers.com
Tue Mar 8 03:55:22 CST 2022
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
Not completely sure what was wrong with this patch but I've split it
to avoid having non executed code and to leave the detail of COM
aggregation for later.
dlls/windows.gaming.input/manager.c | 265 +++++++++++++++++++++++++++-
dlls/windows.gaming.input/private.h | 1 +
2 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.gaming.input/manager.c b/dlls/windows.gaming.input/manager.c
index e6366256fe7..15388f7df5d 100644
--- a/dlls/windows.gaming.input/manager.c
+++ b/dlls/windows.gaming.input/manager.c
@@ -18,12 +18,209 @@
*/
#include "private.h"
+#include "provider.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(input);
+static CRITICAL_SECTION manager_cs;
+static CRITICAL_SECTION_DEBUG manager_cs_debug =
+{
+ 0, 0, &manager_cs,
+ { &manager_cs_debug.ProcessLocksList, &manager_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": manager_cs") }
+};
+static CRITICAL_SECTION manager_cs = { &manager_cs_debug, -1, 0, 0, 0, 0 };
+
+static struct list controller_list = LIST_INIT( controller_list );
+
+struct controller
+{
+ IGameController IGameController_iface;
+ IGameControllerBatteryInfo IGameControllerBatteryInfo_iface;
+ LONG ref;
+
+ struct list entry;
+ IGameControllerProvider *provider;
+ ICustomGameControllerFactory *factory;
+};
+
+static inline struct controller *impl_from_IGameController( IGameController *iface )
+{
+ return CONTAINING_RECORD( iface, struct controller, IGameController_iface );
+}
+
+static HRESULT WINAPI controller_QueryInterface( IGameController *iface, REFIID iid, void **out )
+{
+ struct controller *impl = impl_from_IGameController( 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, &IID_IGameController ))
+ {
+ IInspectable_AddRef( (*out = &impl->IGameController_iface) );
+ return S_OK;
+ }
+
+ if (IsEqualGUID( iid, &IID_IGameControllerBatteryInfo ))
+ {
+ IInspectable_AddRef( (*out = &impl->IGameControllerBatteryInfo_iface) );
+ return S_OK;
+ }
+
+ FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI controller_AddRef( IGameController *iface )
+{
+ struct controller *impl = impl_from_IGameController( iface );
+ ULONG ref = InterlockedIncrement( &impl->ref );
+ TRACE( "iface %p increasing refcount to %lu.\n", iface, ref );
+ return ref;
+}
+
+static ULONG WINAPI controller_Release( IGameController *iface )
+{
+ struct controller *impl = impl_from_IGameController( iface );
+ ULONG ref = InterlockedDecrement( &impl->ref );
+
+ TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
+
+ if (!ref)
+ {
+ ICustomGameControllerFactory_Release( impl->factory );
+ IGameControllerProvider_Release( impl->provider );
+ free( impl );
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI controller_GetIids( IGameController *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 controller_GetRuntimeClassName( IGameController *iface, HSTRING *class_name )
+{
+ FIXME( "iface %p, class_name %p stub!\n", iface, class_name );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_GetTrustLevel( IGameController *iface, TrustLevel *trust_level )
+{
+ FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_add_HeadsetConnected( IGameController *iface, ITypedEventHandler_IGameController_Headset *handler,
+ EventRegistrationToken *token )
+{
+ FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_remove_HeadsetConnected( IGameController *iface, EventRegistrationToken token )
+{
+ FIXME( "iface %p, token %I64x stub!\n", iface, token.value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_add_HeadsetDisconnected( IGameController *iface, ITypedEventHandler_IGameController_Headset *handler,
+ EventRegistrationToken *token )
+{
+ FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_remove_HeadsetDisconnected( IGameController *iface, EventRegistrationToken token )
+{
+ FIXME( "iface %p, token %I64x stub!\n", iface, token.value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_add_UserChanged( IGameController *iface,
+ ITypedEventHandler_IGameController_UserChangedEventArgs *handler,
+ EventRegistrationToken *token )
+{
+ FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_remove_UserChanged( IGameController *iface, EventRegistrationToken token )
+{
+ FIXME( "iface %p, token %I64x stub!\n", iface, token.value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_get_Headset( IGameController *iface, IHeadset **value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_get_IsWireless( IGameController *iface, boolean *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI controller_get_User( IGameController *iface, __x_ABI_CWindows_CSystem_CIUser **value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static const struct IGameControllerVtbl controller_vtbl =
+{
+ controller_QueryInterface,
+ controller_AddRef,
+ controller_Release,
+ /* IInspectable methods */
+ controller_GetIids,
+ controller_GetRuntimeClassName,
+ controller_GetTrustLevel,
+ /* IGameController methods */
+ controller_add_HeadsetConnected,
+ controller_remove_HeadsetConnected,
+ controller_add_HeadsetDisconnected,
+ controller_remove_HeadsetDisconnected,
+ controller_add_UserChanged,
+ controller_remove_UserChanged,
+ controller_get_Headset,
+ controller_get_IsWireless,
+ controller_get_User,
+};
+
+DEFINE_IINSPECTABLE( battery, IGameControllerBatteryInfo, struct controller, IGameController_iface )
+
+static HRESULT WINAPI battery_TryGetBatteryReport( IGameControllerBatteryInfo *iface, IBatteryReport **value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static const struct IGameControllerBatteryInfoVtbl battery_vtbl =
+{
+ battery_QueryInterface,
+ battery_AddRef,
+ battery_Release,
+ /* IInspectable methods */
+ battery_GetIids,
+ battery_GetRuntimeClassName,
+ battery_GetTrustLevel,
+ /* IGameControllerBatteryInfo methods */
+ battery_TryGetBatteryReport,
+};
+
struct manager_statics
{
IActivationFactory IActivationFactory_iface;
@@ -200,12 +397,76 @@ static struct manager_statics manager_statics =
IActivationFactory *manager_factory = &manager_statics.IActivationFactory_iface;
+static HRESULT controller_create( ICustomGameControllerFactory *factory, IGameControllerProvider *provider,
+ struct controller **out )
+{
+ struct controller *impl;
+
+ if (!(impl = malloc(sizeof(*impl)))) return E_OUTOFMEMORY;
+ impl->IGameController_iface.lpVtbl = &controller_vtbl;
+ impl->IGameControllerBatteryInfo_iface.lpVtbl = &battery_vtbl;
+ impl->ref = 1;
+
+ ICustomGameControllerFactory_AddRef( (impl->factory = factory) );
+ IGameControllerProvider_AddRef( (impl->provider = provider) );
+
+ *out = impl;
+ return S_OK;
+}
+
void manager_on_provider_created( IGameControllerProvider *provider )
{
- FIXME( "provider %p stub!\n", provider );
+ struct list *entry, *next, *list;
+ struct controller *controller;
+ HRESULT hr;
+
+ TRACE( "provider %p\n", provider );
+
+ EnterCriticalSection( &manager_cs );
+
+ if (list_empty( &controller_list )) list = &controller_list;
+ else list = list_tail( &controller_list );
+
+ if (SUCCEEDED(controller_create( controller_factory, provider, &controller )))
+ list_add_tail( &controller_list, &controller->entry );
+
+ LIST_FOR_EACH_SAFE( entry, next, list )
+ {
+ controller = LIST_ENTRY( entry, struct controller, entry );
+ hr = ICustomGameControllerFactory_OnGameControllerAdded( controller->factory,
+ &controller->IGameController_iface );
+ if (FAILED(hr))
+ {
+ list_remove( &controller->entry );
+ IGameController_Release( &controller->IGameController_iface );
+ }
+ if (next == &controller_list) break;
+ }
+
+ LeaveCriticalSection( &manager_cs );
}
void manager_on_provider_removed( IGameControllerProvider *provider )
{
- FIXME( "provider %p stub!\n", provider );
+ struct controller *controller, *next;
+
+ TRACE( "provider %p\n", provider );
+
+ EnterCriticalSection( &manager_cs );
+
+ LIST_FOR_EACH_ENTRY( controller, &controller_list, struct controller, entry )
+ {
+ if (controller->provider != provider) continue;
+ ICustomGameControllerFactory_OnGameControllerRemoved( controller->factory,
+ &controller->IGameController_iface );
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE( controller, next, &controller_list, struct controller, entry )
+ {
+ if (controller->provider != provider) continue;
+ list_remove( &controller->entry );
+ IGameController_Release( &controller->IGameController_iface );
+ }
+
+ LeaveCriticalSection( &manager_cs );
}
diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h
index 24d0609aa7e..27dbdb8416c 100644
--- a/dlls/windows.gaming.input/private.h
+++ b/dlls/windows.gaming.input/private.h
@@ -31,6 +31,7 @@
#define WIDL_using_Windows_Foundation
#define WIDL_using_Windows_Foundation_Collections
#include "windows.foundation.h"
+#define WIDL_using_Windows_Devices_Power
#define WIDL_using_Windows_Gaming_Input
#define WIDL_using_Windows_Gaming_Input_Custom
#include "windows.gaming.input.custom.h"
--
2.35.1
More information about the wine-devel
mailing list