[PATCH 4/4] windows.gaming.input: Instantiate the WineGameControllerProvider runtimeclass.
Rémi Bernon
rbernon at codeweavers.com
Fri Mar 4 03:05:10 CST 2022
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/windows.gaming.input/Makefile.in | 2 +-
dlls/windows.gaming.input/main.c | 2 +-
dlls/windows.gaming.input/manager.c | 10 ++
dlls/windows.gaming.input/private.h | 4 +
dlls/windows.gaming.input/provider.c | 222 +++++++++++++++++++++++++-
5 files changed, 236 insertions(+), 4 deletions(-)
diff --git a/dlls/windows.gaming.input/Makefile.in b/dlls/windows.gaming.input/Makefile.in
index 1a3cdb364f2..93d167f61e9 100644
--- a/dlls/windows.gaming.input/Makefile.in
+++ b/dlls/windows.gaming.input/Makefile.in
@@ -1,5 +1,5 @@
MODULE = windows.gaming.input.dll
-IMPORTS = combase uuid user32 setupapi hid
+IMPORTS = combase uuid user32 dinput8 setupapi hid
C_SRCS = \
controller.c \
diff --git a/dlls/windows.gaming.input/main.c b/dlls/windows.gaming.input/main.c
index 0fc23cea5bf..03d47e1ce2f 100644
--- a/dlls/windows.gaming.input/main.c
+++ b/dlls/windows.gaming.input/main.c
@@ -38,7 +38,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(input);
-static HINSTANCE windows_gaming_input;
+HINSTANCE windows_gaming_input;
DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x47,0x67,0x50,0xc5,0xe1,0xa6 );
diff --git a/dlls/windows.gaming.input/manager.c b/dlls/windows.gaming.input/manager.c
index 61f639b8e7e..e6366256fe7 100644
--- a/dlls/windows.gaming.input/manager.c
+++ b/dlls/windows.gaming.input/manager.c
@@ -199,3 +199,13 @@ static struct manager_statics manager_statics =
};
IActivationFactory *manager_factory = &manager_statics.IActivationFactory_iface;
+
+void manager_on_provider_created( IGameControllerProvider *provider )
+{
+ FIXME( "provider %p stub!\n", provider );
+}
+
+void manager_on_provider_removed( IGameControllerProvider *provider )
+{
+ FIXME( "provider %p stub!\n", provider );
+}
diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h
index 87a3f677d8c..a0bd45b3f20 100644
--- a/dlls/windows.gaming.input/private.h
+++ b/dlls/windows.gaming.input/private.h
@@ -35,6 +35,7 @@
#define WIDL_using_Windows_Gaming_Input_Custom
#include "windows.gaming.input.custom.h"
+extern HINSTANCE windows_gaming_input;
extern IActivationFactory *controller_factory;
extern IActivationFactory *gamepad_factory;
extern IActivationFactory *manager_factory;
@@ -44,6 +45,9 @@ extern HRESULT vector_create( REFIID iid, REFIID view_iid, void **out );
extern void provider_create( const WCHAR *device_path );
extern void provider_remove( const WCHAR *device_path );
+extern void manager_on_provider_created( IGameControllerProvider *provider );
+extern void manager_on_provider_removed( IGameControllerProvider *provider );
+
#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \
static inline impl_type *impl_from_##iface_type( iface_type *iface ) \
{ \
diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c
index 710349eb75f..9ab9682f221 100644
--- a/dlls/windows.gaming.input/provider.c
+++ b/dlls/windows.gaming.input/provider.c
@@ -20,18 +20,236 @@
#include "private.h"
#include "initguid.h"
+#include "dinput.h"
#include "provider.h"
#include "wine/debug.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(input);
+DEFINE_GUID( device_path_guid, 0x00000000, 0x0000, 0x0000, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf8 );
+
+static CRITICAL_SECTION provider_cs;
+static CRITICAL_SECTION_DEBUG provider_cs_debug =
+{
+ 0, 0, &provider_cs,
+ { &provider_cs_debug.ProcessLocksList, &provider_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": provider_cs") }
+};
+static CRITICAL_SECTION provider_cs = { &provider_cs_debug, -1, 0, 0, 0, 0 };
+
+static struct list provider_list = LIST_INIT( provider_list );
+
+struct provider
+{
+ IWineGameControllerProvider IWineGameControllerProvider_iface;
+ IGameControllerProvider IGameControllerProvider_iface;
+ LONG ref;
+
+ IDirectInputDevice8W *dinput_device;
+ WCHAR device_path[MAX_PATH];
+ struct list entry;
+};
+
+static inline struct provider *impl_from_IWineGameControllerProvider( IWineGameControllerProvider *iface )
+{
+ return CONTAINING_RECORD( iface, struct provider, IWineGameControllerProvider_iface );
+}
+
+static HRESULT WINAPI wine_provider_QueryInterface( IWineGameControllerProvider *iface, REFIID iid, void **out )
+{
+ struct provider *impl = impl_from_IWineGameControllerProvider( 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_IWineGameControllerProvider ))
+ {
+ IInspectable_AddRef( (*out = &impl->IWineGameControllerProvider_iface) );
+ return S_OK;
+ }
+
+ if (IsEqualGUID( iid, &IID_IGameControllerProvider ))
+ {
+ IInspectable_AddRef( (*out = &impl->IGameControllerProvider_iface) );
+ return S_OK;
+ }
+
+ FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI wine_provider_AddRef( IWineGameControllerProvider *iface )
+{
+ struct provider *impl = impl_from_IWineGameControllerProvider( iface );
+ ULONG ref = InterlockedIncrement( &impl->ref );
+ TRACE( "iface %p increasing refcount to %lu.\n", iface, ref );
+ return ref;
+}
+
+static ULONG WINAPI wine_provider_Release( IWineGameControllerProvider *iface )
+{
+ struct provider *impl = impl_from_IWineGameControllerProvider( iface );
+ ULONG ref = InterlockedDecrement( &impl->ref );
+
+ TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
+
+ if (!ref)
+ {
+ IDirectInputDevice8_Release( impl->dinput_device );
+ free( impl );
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI wine_provider_GetIids( IWineGameControllerProvider *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 wine_provider_GetRuntimeClassName( IWineGameControllerProvider *iface, HSTRING *class_name )
+{
+ FIXME( "iface %p, class_name %p stub!\n", iface, class_name );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI wine_provider_GetTrustLevel( IWineGameControllerProvider *iface, TrustLevel *trust_level )
+{
+ FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level );
+ return E_NOTIMPL;
+}
+
+static const struct IWineGameControllerProviderVtbl wine_provider_vtbl =
+{
+ wine_provider_QueryInterface,
+ wine_provider_AddRef,
+ wine_provider_Release,
+ /* IInspectable methods */
+ wine_provider_GetIids,
+ wine_provider_GetRuntimeClassName,
+ wine_provider_GetTrustLevel,
+};
+
+DEFINE_IINSPECTABLE( game_provider, IGameControllerProvider, struct provider, IWineGameControllerProvider_iface )
+
+static HRESULT WINAPI game_provider_get_FirmwareVersionInfo( IGameControllerProvider *iface, GameControllerVersionInfo *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI game_provider_get_HardwareProductId( IGameControllerProvider *iface, UINT16 *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI game_provider_get_HardwareVendorId( IGameControllerProvider *iface, UINT16 *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI game_provider_get_HardwareVersionInfo( IGameControllerProvider *iface, GameControllerVersionInfo *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI game_provider_get_IsConnected( IGameControllerProvider *iface, boolean *value )
+{
+ FIXME( "iface %p, value %p stub!\n", iface, value );
+ return E_NOTIMPL;
+}
+
+static const struct IGameControllerProviderVtbl game_provider_vtbl =
+{
+ game_provider_QueryInterface,
+ game_provider_AddRef,
+ game_provider_Release,
+ /* IInspectable methods */
+ game_provider_GetIids,
+ game_provider_GetRuntimeClassName,
+ game_provider_GetTrustLevel,
+ /* IGameControllerProvider methods */
+ game_provider_get_FirmwareVersionInfo,
+ game_provider_get_HardwareProductId,
+ game_provider_get_HardwareVendorId,
+ game_provider_get_HardwareVersionInfo,
+ game_provider_get_IsConnected,
+};
+
void provider_create( const WCHAR *device_path )
{
- FIXME( "device_path %s stub!\n", debugstr_w( device_path ) );
+ IDirectInputDevice8W *dinput_device;
+ IGameControllerProvider *provider;
+ struct provider *impl, *entry;
+ GUID guid = device_path_guid;
+ IDirectInput8W *dinput;
+ BOOL found = FALSE;
+ const WCHAR *tmp;
+ HRESULT hr;
+
+ if (wcsnicmp( device_path, L"\\\\?\\HID#", 8 )) return;
+ if ((tmp = wcschr( device_path + 8, '#' )) && !wcsnicmp( tmp - 6, L"&IG_", 4 )) return;
+
+ TRACE( "device_path %s\n", debugstr_w( device_path ) );
+
+ *(const WCHAR **)&guid = device_path;
+ if (FAILED(DirectInput8Create( windows_gaming_input, DIRECTINPUT_VERSION, &IID_IDirectInput8W,
+ (void **)&dinput, NULL ))) return;
+ hr = IDirectInput8_CreateDevice( dinput, &guid, &dinput_device, NULL );
+ IDirectInput8_Release( dinput );
+ if (FAILED(hr)) return;
+
+ if (!(impl = calloc( 1, sizeof(*impl) ))) goto done;
+ impl->IWineGameControllerProvider_iface.lpVtbl = &wine_provider_vtbl;
+ impl->IGameControllerProvider_iface.lpVtbl = &game_provider_vtbl;
+ IDirectInputDevice_AddRef( dinput_device );
+ impl->dinput_device = dinput_device;
+ impl->ref = 1;
+
+ wcscpy( impl->device_path, device_path );
+ list_init( &impl->entry );
+ provider = &impl->IGameControllerProvider_iface;
+ TRACE( "created WineGameControllerProvider %p\n", provider );
+
+ EnterCriticalSection( &provider_cs );
+ LIST_FOR_EACH_ENTRY( entry, &provider_list, struct provider, entry )
+ if ((found = !wcscmp( entry->device_path, device_path ))) break;
+ if (!found) list_add_tail( &provider_list, &impl->entry );
+ LeaveCriticalSection( &provider_cs );
+
+ if (found) IGameControllerProvider_Release( provider );
+ else manager_on_provider_created( provider );
+done:
+ IDirectInputDevice_Release( dinput_device );
}
void provider_remove( const WCHAR *device_path )
{
- FIXME( "device_path %s stub!\n", debugstr_w( device_path ) );
+ IGameControllerProvider *provider;
+ struct provider *entry;
+ BOOL found = FALSE;
+
+ TRACE( "device_path %s\n", debugstr_w( device_path ) );
+
+ EnterCriticalSection( &provider_cs );
+ LIST_FOR_EACH_ENTRY( entry, &provider_list, struct provider, entry )
+ if ((found = !wcscmp( entry->device_path, device_path ))) break;
+ if (found) list_remove( &entry->entry );
+ LeaveCriticalSection( &provider_cs );
+
+ if (found)
+ {
+ provider = &entry->IGameControllerProvider_iface;
+ manager_on_provider_removed( provider );
+ IGameControllerProvider_Release( provider );
+ }
}
--
2.34.1
More information about the wine-devel
mailing list