diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index e529b684d..86f733a8d 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -22,6 +22,8 @@ #ifdef SDL_JOYSTICK_WGI +#include "SDL_assert.h" +#include "SDL_atomic.h" #include "SDL_endian.h" #include "SDL_events.h" #include "../SDL_sysjoystick.h" @@ -207,6 +209,11 @@ SDL_IsXInputDevice(Uint16 vendor, Uint16 product) return SDL_FALSE; } +typedef struct RawGameControllerDelegate { + __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *vtbl; + SDL_atomic_t refcount; +} RawGameControllerDelegate; + static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, REFIID riid, void **ppvObject) { if (!ppvObject) { @@ -216,9 +223,10 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInter *ppvObject = NULL; if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) { *ppvObject = This; + __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_AddRef(This); return S_OK; } else if (WIN_IsEqualIID(riid, &IID_IMarshal)) { - // This seems complicated. Let's hope it doesn't happen. + /* This seems complicated. Let's hope it doesn't happen. */ return E_OUTOFMEMORY; } else { return E_NOINTERFACE; @@ -227,12 +235,17 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInter static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_AddRef(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This) { - return 1; + RawGameControllerDelegate *self = (RawGameControllerDelegate *)This; + return SDL_AtomicAdd(&self->refcount, 1) + 1; } static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This) { - return 1; + RawGameControllerDelegate *self = (RawGameControllerDelegate *)This; + int rc = SDL_AtomicAdd(&self->refcount, -1) - 1; + /* Should never free the static delegate objects */ + SDL_assert(rc > 0); + return rc; } static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e) @@ -417,8 +430,9 @@ static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl contr IEventHandler_CRawGameControllerVtbl_Release, IEventHandler_CRawGameControllerVtbl_InvokeAdded }; -static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_added = { - &controller_added_vtbl +static RawGameControllerDelegate controller_added = { + { &controller_added_vtbl }, + { 1 } }; static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_removed_vtbl = { @@ -427,8 +441,9 @@ static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl contr IEventHandler_CRawGameControllerVtbl_Release, IEventHandler_CRawGameControllerVtbl_InvokeRemoved }; -static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_removed = { - &controller_removed_vtbl +static RawGameControllerDelegate controller_removed = { + { &controller_removed_vtbl }, + { 1 } }; static int