From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com> --- dlls/gameinput/gameinput.c | 575 ++++++++++++++++++++++++++++++++++++- 1 file changed, 573 insertions(+), 2 deletions(-) diff --git a/dlls/gameinput/gameinput.c b/dlls/gameinput/gameinput.c index c3923bf2efc..4452cb22eb3 100644 --- a/dlls/gameinput/gameinput.c +++ b/dlls/gameinput/gameinput.c @@ -23,17 +23,588 @@ #include "windef.h" #include "winbase.h" +#include "initguid.h" #include "gameinput.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ginput); -HRESULT WINAPI GameInputCreate( v0_IGameInput **out ) +struct game_input +{ + v0_IGameInput v0_IGameInput_iface; + v1_IGameInput v1_IGameInput_iface; + v2_IGameInput v2_IGameInput_iface; + + LONG ref; +}; + +/* Global */ +static struct game_input *gameinput = NULL; + +static inline struct game_input *impl_from_v0_IGameInput( v0_IGameInput *iface ) +{ + return CONTAINING_RECORD( iface, struct game_input, v0_IGameInput_iface ); +} + +static inline struct game_input *impl_from_v1_IGameInput( v1_IGameInput *iface ) +{ + return CONTAINING_RECORD( iface, struct game_input, v1_IGameInput_iface ); +} + +static inline struct game_input *impl_from_v2_IGameInput( v2_IGameInput *iface ) +{ + return CONTAINING_RECORD( iface, struct game_input, v2_IGameInput_iface ); +} + +static HRESULT WINAPI game_input_QueryInterface( v0_IGameInput *iface, REFIID iid, void **out ) +{ + struct game_input *impl = impl_from_v0_IGameInput( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + *out = NULL; + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_v0_IGameInput )) + *out = &impl->v0_IGameInput_iface; + else if (IsEqualGUID( iid, &IID_v1_IGameInput )) + *out = &impl->v1_IGameInput_iface; + else if (IsEqualGUID( iid, &IID_v2_IGameInput )) + *out = &impl->v2_IGameInput_iface; + + if (!*out) + { + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; + } + + v0_IGameInput_AddRef( iface ); + return S_OK; +} + +static ULONG WINAPI game_input_AddRef( v0_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v0_IGameInput( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI game_input_Release( v0_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v0_IGameInput( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + if (!ref) + { + gameinput = NULL; + free(impl); + } + return ref; +} + +static uint64_t WINAPI game_input_GetCurrentTimestamp( v0_IGameInput *iface ) +{ + FIXME( "iface %p, stub GetCurrentTimestamp.\n", iface ); + return 0; +} + +static HRESULT WINAPI game_input_GetCurrentReading( v0_IGameInput *iface, GameInputKind kind, + v0_IGameInputDevice *device, v0_IGameInputReading **reading ) +{ + FIXME( "iface %p GetCurrentReading kind=%d device=%p reading=%p\n", iface, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_GetNextReading( v0_IGameInput *iface, v0_IGameInputReading *reference, + GameInputKind kind, v0_IGameInputDevice *device, + v0_IGameInputReading **reading ) +{ + FIXME( "iface %p GetNextReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_GetPreviousReading( v0_IGameInput *iface, v0_IGameInputReading *reference, + GameInputKind kind, v0_IGameInputDevice *device, + v0_IGameInputReading **reading ) +{ + FIXME( "iface %p GetPreviousReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_GetTemporalReading( v0_IGameInput *iface, uint64_t timestamp, + v0_IGameInputDevice *device, v0_IGameInputReading **reading ) +{ + FIXME( "iface %p GetTemporalReading timestamp=%llu device=%p reading=%p\n", iface, timestamp, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_RegisterReadingCallback( v0_IGameInput *iface, v0_IGameInputDevice *device, + GameInputKind kind, float threshold, void *context, + v0_GameInputReadingCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterReadingCallback device=%p kind=%d threshold=%f callback=%p token=%p\n", + iface, device, kind, threshold, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_RegisterDeviceCallback( v0_IGameInput *iface, v0_IGameInputDevice *device, + GameInputKind kind, GameInputDeviceStatus filter, + GameInputEnumerationKind enum_kind, void *context, + v0_GameInputDeviceCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterDeviceCallback device=%p kind=%d filter=%d enum_kind=%d callback=%p token=%p\n", + iface, device, kind, filter, enum_kind, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_RegisterSystemButtonCallback( v0_IGameInput *iface, v0_IGameInputDevice *device, + GameInputSystemButtons filter, void *context, + v0_GameInputSystemButtonCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterSystemButtonCallback device=%p filter=%u callback=%p token=%p\n", + iface, device, filter, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_RegisterKeyboardLayoutCallback( v0_IGameInput *iface, v0_IGameInputDevice *device, + void *context, v0_GameInputKeyboardLayoutCallback callback, + GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterKeyboardLayoutCallback device=%p callback=%p token=%p\n", + iface, device, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static void WINAPI game_input_StopCallback( v0_IGameInput *iface, GameInputCallbackToken token ) +{ + FIXME( "iface %p StopCallback token=%llu\n", iface, token ); + /* no-op stub */ +} + +static bool WINAPI game_input_UnregisterCallback( v0_IGameInput *iface, GameInputCallbackToken token, uint64_t timeout_ms ) +{ + FIXME( "iface %p UnregisterCallback token=%llu timeout_ms=%llu\n", iface, token, timeout_ms ); + return false; +} + +static HRESULT WINAPI game_input_CreateDispatcher( v0_IGameInput *iface, IGameInputDispatcher **dispatcher ) +{ + FIXME( "iface %p CreateDispatcher dispatcher=%p\n", iface, dispatcher ); + if (dispatcher) *dispatcher = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_CreateAggregateDevice( v0_IGameInput *iface, GameInputKind kind, v0_IGameInputDevice **device ) +{ + FIXME( "iface %p CreateAggregateDevice kind=%d device=%p\n", iface, kind, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_FindDeviceFromId( v0_IGameInput *iface, const APP_LOCAL_DEVICE_ID *value, v0_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromId value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_FindDeviceFromObject( v0_IGameInput *iface, IUnknown *value, v0_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromObject unknown=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_FindDeviceFromPlatformHandle( v0_IGameInput *iface, HANDLE value, v0_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromPlatformHandle handle=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_FindDeviceFromPlatformString( v0_IGameInput *iface, const WCHAR *value, v0_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromPlatformString value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input_EnableOemDeviceSupport( v0_IGameInput *iface, uint16_t vid, uint16_t pid, + uint8_t iface_num, uint8_t collection ) +{ + FIXME( "iface %p EnableOemDeviceSupport vid=0x%04x pid=0x%04x iface=%u collection=%u\n", + iface, vid, pid, iface_num, collection ); + return E_NOTIMPL; +} + +static void WINAPI game_input_SetFocusPolicy( v0_IGameInput *iface, GameInputFocusPolicy policy ) +{ + FIXME( "iface %p SetFocusPolicy policy=%d\n", iface, policy ); +} + +static const struct v0_IGameInputVtbl game_input_vtbl = +{ + /* IUnknown methods */ + game_input_QueryInterface, + game_input_AddRef, + game_input_Release, + /* v0_IGameInput methods */ + game_input_GetCurrentTimestamp, + game_input_GetCurrentReading, + game_input_GetNextReading, + game_input_GetPreviousReading, + game_input_GetTemporalReading, + game_input_RegisterReadingCallback, + game_input_RegisterDeviceCallback, + game_input_RegisterSystemButtonCallback, + game_input_RegisterKeyboardLayoutCallback, + game_input_StopCallback, + game_input_UnregisterCallback, + game_input_CreateDispatcher, + game_input_CreateAggregateDevice, + game_input_FindDeviceFromId, + game_input_FindDeviceFromObject, + game_input_FindDeviceFromPlatformHandle, + game_input_FindDeviceFromPlatformString, + game_input_EnableOemDeviceSupport, + game_input_SetFocusPolicy +}; + + +static HRESULT WINAPI game_input1_QueryInterface( v1_IGameInput *iface, REFIID iid, void **out ) +{ + struct game_input *impl = impl_from_v1_IGameInput( iface ); + return v0_IGameInput_QueryInterface( &impl->v0_IGameInput_iface, iid, out ); +} + +static ULONG WINAPI game_input1_AddRef( v1_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v1_IGameInput( iface ); + return v0_IGameInput_AddRef( &impl->v0_IGameInput_iface); +} + +static ULONG WINAPI game_input1_Release( v1_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v1_IGameInput( iface ); + return v0_IGameInput_Release( &impl->v0_IGameInput_iface); +}; + +static uint64_t WINAPI game_input1_GetCurrentTimestamp( v1_IGameInput *iface ) +{ + TRACE( "iface %p, stub GetCurrentTimestamp.\n", iface ); + return 0; +} + +static HRESULT WINAPI game_input1_GetCurrentReading( v1_IGameInput *iface, GameInputKind kind, + v1_IGameInputDevice *device, v1_IGameInputReading **reading ) +{ + FIXME( "iface %p GetCurrentReading kind=%d device=%p =%p\n", iface, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_GetNextReading( v1_IGameInput *iface, v1_IGameInputReading *reference, + GameInputKind kind, v1_IGameInputDevice *device, + v1_IGameInputReading **reading ) +{ + FIXME( "iface %p GetNextReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_GetPreviousReading( v1_IGameInput *iface, v1_IGameInputReading *reference, + GameInputKind kind, v1_IGameInputDevice *device, + v1_IGameInputReading **reading ) +{ + FIXME( "iface %p GetPreviousReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_RegisterReadingCallback( v1_IGameInput *iface, v1_IGameInputDevice *device, + GameInputKind kind, void *context, + v1_GameInputReadingCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterReadingCallback device=%p kind=%d callback=%p token=%p\n", + iface, device, kind, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_RegisterDeviceCallback( v1_IGameInput *iface, v1_IGameInputDevice *device, + GameInputKind kind, GameInputDeviceStatus filter, + GameInputEnumerationKind enum_kind, void *context, + v1_GameInputDeviceCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterDeviceCallback device=%p kind=%d filter=%d enum_kind=%d callback=%p token=%p\n", + iface, device, kind, filter, enum_kind, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_RegisterSystemButtonCallback( v1_IGameInput *iface, v1_IGameInputDevice *device, + GameInputSystemButtons filter, void *context, + v1_GameInputSystemButtonCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterSystemButtonCallback device=%p filter=%u callback=%p token=%p\n", + iface, device, filter, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_RegisterKeyboardLayoutCallback( v1_IGameInput *iface, v1_IGameInputDevice *device, + void *context, v1_GameInputKeyboardLayoutCallback callback, + GameInputCallbackToken *token ) { - FIXME( "out %p, stub!\n", out ); + FIXME( "iface %p RegisterKeyboardLayoutCallback device=%p callback=%p token=%p\n", + iface, device, callback, token ); + if (token) *token = (GameInputCallbackToken)0; return E_NOTIMPL; } +static void WINAPI game_input1_StopCallback( v1_IGameInput *iface, GameInputCallbackToken token ) +{ + FIXME( "iface %p StopCallback token=%llu\n", iface, token ); +} + +static bool WINAPI game_input1_UnregisterCallback( v1_IGameInput *iface, GameInputCallbackToken token ) +{ + FIXME( "iface %p UnregisterCallback token=%llu\n", iface, token ); + return false; +} + +static HRESULT WINAPI game_input1_CreateDispatcher( v1_IGameInput *iface, IGameInputDispatcher **dispatcher ) +{ + FIXME( "iface %p CreateDispatcher dispatcher=%p\n", iface, dispatcher ); + if (dispatcher) *dispatcher = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_FindDeviceFromId( v1_IGameInput *iface, const APP_LOCAL_DEVICE_ID *value, v1_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromId value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input1_FindDeviceFromPlatformString( v1_IGameInput *iface, const WCHAR *value, v1_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromPlatformString value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static void WINAPI game_input1_SetFocusPolicy( v1_IGameInput *iface, GameInputFocusPolicy policy ) +{ + FIXME( "iface %p SetFocusPolicy policy=%d\n", iface, policy ); +} + +static const struct v1_IGameInputVtbl game_input1_vtbl = +{ + /* IUnknown methods */ + game_input1_QueryInterface, + game_input1_AddRef, + game_input1_Release, + /* v0_IGameInput methods */ + game_input1_GetCurrentTimestamp, + game_input1_GetCurrentReading, + game_input1_GetNextReading, + game_input1_GetPreviousReading, + game_input1_RegisterReadingCallback, + game_input1_RegisterDeviceCallback, + game_input1_RegisterSystemButtonCallback, + game_input1_RegisterKeyboardLayoutCallback, + game_input1_StopCallback, + game_input1_UnregisterCallback, + game_input1_CreateDispatcher, + game_input1_FindDeviceFromId, + game_input1_FindDeviceFromPlatformString, + game_input1_SetFocusPolicy +}; + +static HRESULT WINAPI game_input2_QueryInterface( v2_IGameInput *iface, REFIID iid, void **out ) +{ + struct game_input *impl = impl_from_v2_IGameInput( iface ); + return v0_IGameInput_QueryInterface( &impl->v0_IGameInput_iface, iid, out ); +} + +static ULONG WINAPI game_input2_AddRef( v2_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v2_IGameInput( iface ); + return v0_IGameInput_AddRef( &impl->v0_IGameInput_iface); +} + +static ULONG WINAPI game_input2_Release( v2_IGameInput *iface ) +{ + struct game_input *impl = impl_from_v2_IGameInput( iface ); + return v0_IGameInput_Release( &impl->v0_IGameInput_iface); +}; + +static uint64_t WINAPI game_input2_GetCurrentTimestamp( v2_IGameInput *iface ) +{ + TRACE( "iface %p, stub GetCurrentTimestamp.\n", iface ); + return 0; +} + +static HRESULT WINAPI game_input2_GetCurrentReading( v2_IGameInput *iface, GameInputKind kind, + v2_IGameInputDevice *device, v2_IGameInputReading **reading ) +{ + FIXME( "iface %p kind %d device %p reading %p\n", iface, kind, device, reading ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_GetNextReading( v2_IGameInput *iface, v2_IGameInputReading *reference, + GameInputKind kind, v2_IGameInputDevice *device, + v2_IGameInputReading **reading ) +{ + FIXME( "iface %p GetNextReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_GetPreviousReading( v2_IGameInput *iface, v2_IGameInputReading *reference, + GameInputKind kind, v2_IGameInputDevice *device, + v2_IGameInputReading **reading ) +{ + FIXME( "iface %p GetPreviousReading reference=%p kind=%d device=%p reading=%p\n", iface, reference, kind, device, reading ); + if (reading) *reading = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_RegisterReadingCallback( v2_IGameInput *iface, v2_IGameInputDevice *device, + GameInputKind kind, void *context, + v2_GameInputReadingCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterReadingCallback device=%p kind=%d callback=%p token=%p\n", + iface, device, kind, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_RegisterDeviceCallback( v2_IGameInput *iface, v2_IGameInputDevice *device, + GameInputKind kind, GameInputDeviceStatus filter, + GameInputEnumerationKind enum_kind, void *context, + v2_GameInputDeviceCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p, device %p, kind %#x, filter %#x, enum_kind %d, context %p, callback %p, token %p semi-stub!\n", iface, device, kind, filter, enum_kind, context, callback, token ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_RegisterSystemButtonCallback( v2_IGameInput *iface, v2_IGameInputDevice *device, + GameInputSystemButtons filter, void *context, + v2_GameInputSystemButtonCallback callback, GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterSystemButtonCallback device=%p filter=%u callback=%p token=%p\n", + iface, device, filter, callback, token ); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_RegisterKeyboardLayoutCallback( v2_IGameInput *iface, v2_IGameInputDevice *device, + void *context, v2_GameInputKeyboardLayoutCallback callback, + GameInputCallbackToken *token ) +{ + FIXME( "iface %p RegisterKeyboardLayoutCallback device=%p callback=%p token=%p\n", + iface, device, callback, token); + if (token) *token = (GameInputCallbackToken)0; + return E_NOTIMPL; +} + +static void WINAPI game_input2_StopCallback( v2_IGameInput *iface, GameInputCallbackToken token ) +{ + FIXME( "iface %p StopCallback token=%llu\n", iface, token ); +} + +static bool WINAPI game_input2_UnregisterCallback( v2_IGameInput *iface, GameInputCallbackToken token ) +{ + FIXME( "iface %p UnregisterCallback token=%llu\n", iface, token ); + return TRUE; +} + +static HRESULT WINAPI game_input2_CreateDispatcher( v2_IGameInput *iface, IGameInputDispatcher **dispatcher ) +{ + FIXME( "iface %p CreateDispatcher dispatcher=%p\n", iface, dispatcher ); + if (dispatcher) *dispatcher = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_FindDeviceFromId( v2_IGameInput *iface, const APP_LOCAL_DEVICE_ID *value, v2_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromId value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI game_input2_FindDeviceFromPlatformString( v2_IGameInput *iface, const WCHAR *value, v2_IGameInputDevice **device ) +{ + FIXME( "iface %p FindDeviceFromPlatformString value=%p device=%p\n", iface, value, device ); + if (device) *device = NULL; + return E_NOTIMPL; +} + +static void WINAPI game_input2_SetFocusPolicy( v2_IGameInput *iface, GameInputFocusPolicy policy ) +{ + FIXME( "iface %p SetFocusPolicy policy=%d\n", iface, policy ); +} + +static const struct v2_IGameInputVtbl game_input2_vtbl = +{ + /* IUnknown methods */ + game_input2_QueryInterface, + game_input2_AddRef, + game_input2_Release, + /* v0_IGameInput methods */ + game_input2_GetCurrentTimestamp, + game_input2_GetCurrentReading, + game_input2_GetNextReading, + game_input2_GetPreviousReading, + game_input2_RegisterReadingCallback, + game_input2_RegisterDeviceCallback, + game_input2_RegisterSystemButtonCallback, + game_input2_RegisterKeyboardLayoutCallback, + game_input2_StopCallback, + game_input2_UnregisterCallback, + game_input2_CreateDispatcher, + game_input2_FindDeviceFromId, + game_input2_FindDeviceFromPlatformString, + game_input2_SetFocusPolicy +}; + +HRESULT WINAPI GameInputCreate( v0_IGameInput **out ) +{ + TRACE( "out %p\n", out ); + + if (gameinput) + { + v0_IGameInput_AddRef( &gameinput->v0_IGameInput_iface ); + *out = &gameinput->v0_IGameInput_iface; + return S_OK; + } + + if (!(gameinput = calloc( 1, sizeof(*gameinput) ))) + return E_OUTOFMEMORY; + + gameinput->v0_IGameInput_iface.lpVtbl = &game_input_vtbl; + gameinput->v1_IGameInput_iface.lpVtbl = &game_input1_vtbl; + gameinput->v2_IGameInput_iface.lpVtbl = &game_input2_vtbl; + gameinput->ref = 1; + + *out = &gameinput->v0_IGameInput_iface; + + return S_OK; +} + HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) { FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10258