Commit e171b58a authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

windows.gaming.input: Instantiate the WineGameControllerProvider runtimeclass.

parent 8b288980
MODULE = windows.gaming.input.dll
IMPORTS = combase uuid user32 setupapi hid
IMPORTS = combase uuid user32 dinput8 setupapi hid
C_SRCS = \
controller.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 );
......
......@@ -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 );
}
......@@ -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 ) \
{ \
......
......@@ -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 );
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment