Fixed crashes in new joystick code

This commit is contained in:
Sam Lantinga 2012-11-28 11:52:38 -08:00
parent 732f28216b
commit 556c764047
2 changed files with 50 additions and 30 deletions

View file

@ -30,7 +30,8 @@
#include "../events/SDL_events_c.h" #include "../events/SDL_events_c.h"
#endif #endif
SDL_Joystick *SDL_joysticks = NULL; static SDL_Joystick *SDL_joysticks = NULL;
static SDL_Joystick *SDL_updating_joystick = NULL;
int int
SDL_JoystickInit(void) SDL_JoystickInit(void)
@ -386,6 +387,10 @@ SDL_JoystickClose(SDL_Joystick * joystick)
return; return;
} }
if (joystick == SDL_updating_joystick) {
return;
}
SDL_SYS_JoystickClose(joystick); SDL_SYS_JoystickClose(joystick);
joysticklist = SDL_joysticks; joysticklist = SDL_joysticks;
@ -432,6 +437,9 @@ SDL_JoystickClose(SDL_Joystick * joystick)
void void
SDL_JoystickQuit(void) SDL_JoystickQuit(void)
{ {
/* Make sure we're not getting called in the middle of updating joysticks */
SDL_assert(!SDL_updating_joystick);
/* Stop the event polling */ /* Stop the event polling */
while ( SDL_joysticks ) while ( SDL_joysticks )
{ {
@ -588,6 +596,8 @@ SDL_JoystickUpdate(void)
*/ */
joysticknext = joystick->next; joysticknext = joystick->next;
SDL_updating_joystick = joystick;
SDL_SYS_JoystickUpdate( joystick ); SDL_SYS_JoystickUpdate( joystick );
if ( joystick->closed && joystick->uncentered ) if ( joystick->closed && joystick->uncentered )
@ -595,7 +605,7 @@ SDL_JoystickUpdate(void)
int i; int i;
joystick->uncentered = 0; joystick->uncentered = 0;
// Tell the app that everything is centered/unpressed... /* Tell the app that everything is centered/unpressed... */
for (i = 0; i < joystick->naxes; i++) for (i = 0; i < joystick->naxes; i++)
SDL_PrivateJoystickAxis(joystick, i, 0); SDL_PrivateJoystickAxis(joystick, i, 0);
@ -604,6 +614,14 @@ SDL_JoystickUpdate(void)
for (i = 0; i < joystick->nhats; i++) for (i = 0; i < joystick->nhats; i++)
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
}
SDL_updating_joystick = NULL;
/* If the joystick was closed while updating, free it here */
if ( joystick->ref_count <= 0 ) {
SDL_JoystickClose(joystick);
} }
joystick = joysticknext; joystick = joysticknext;

View file

@ -498,24 +498,6 @@ LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM w
} }
/* helper func to create a hidden, message only window for the joystick detect thread
*/
HWND CreateHiddenJoystickDetectWindow() {
WNDCLASSEX wincl;
HWND hMessageWindow = 0;
SDL_memset( &wincl, 0x0, sizeof(wincl) );
wincl.hInstance = GetModuleHandle( NULL );
wincl.lpszClassName = L"Message";
wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; // This function is called by windows
wincl.cbSize = sizeof (WNDCLASSEX);
if (!RegisterClassEx (&wincl))
return 0;
hMessageWindow = (HWND)CreateWindowEx( 0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
return hMessageWindow;
}
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \ DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
0xC0, 0x4F, 0xB9, 0x51, 0xED); 0xC0, 0x4F, 0xB9, 0x51, 0xED);
@ -529,12 +511,26 @@ SDL_JoystickThread(void *_data)
HDEVNOTIFY hNotify = 0; HDEVNOTIFY hNotify = 0;
DEV_BROADCAST_DEVICEINTERFACE dbh; DEV_BROADCAST_DEVICEINTERFACE dbh;
SDL_bool bOpenedXInputDevices[4]; SDL_bool bOpenedXInputDevices[4];
WNDCLASSEX wincl;
SDL_memset( bOpenedXInputDevices, 0x0, sizeof(bOpenedXInputDevices) ); SDL_memset( bOpenedXInputDevices, 0x0, sizeof(bOpenedXInputDevices) );
result = WIN_CoInitialize(); result = WIN_CoInitialize();
messageWindow = CreateHiddenJoystickDetectWindow(); SDL_memset( &wincl, 0x0, sizeof(wincl) );
wincl.hInstance = GetModuleHandle( NULL );
wincl.lpszClassName = L"Message";
wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; // This function is called by windows
wincl.cbSize = sizeof (WNDCLASSEX);
if (!RegisterClassEx (&wincl))
{
SDL_SetError("Failed to create register class for joystick autodetect.",
GetLastError());
return -1;
}
messageWindow = (HWND)CreateWindowEx( 0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
if ( !messageWindow ) if ( !messageWindow )
{ {
SDL_SetError("Failed to create message window for joystick autodetect.", SDL_SetError("Failed to create message window for joystick autodetect.",
@ -611,6 +607,8 @@ SDL_JoystickThread(void *_data)
if ( messageWindow ) if ( messageWindow )
DestroyWindow( messageWindow ); DestroyWindow( messageWindow );
UnregisterClass( wincl.lpszClassName, wincl.hInstance );
messageWindow = 0; messageWindow = 0;
WIN_CoUninitialize(); WIN_CoUninitialize();
return 1; return 1;
@ -720,22 +718,25 @@ static BOOL CALLBACK
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{ {
JoyStick_DeviceData *pNewJoystick; JoyStick_DeviceData *pNewJoystick;
JoyStick_DeviceData *pPrevJoystick = NULL;
SDL_bool bXInputDevice; SDL_bool bXInputDevice;
pNewJoystick = *(JoyStick_DeviceData **)pContext; pNewJoystick = *(JoyStick_DeviceData **)pContext;
while ( pNewJoystick ) while ( pNewJoystick )
{ {
if ( !SDL_memcmp( &pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance) ) ) if ( !SDL_memcmp( &pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance) ) )
{ {
if ( SYS_Joystick )
{
pNewJoystick->pNext = SYS_Joystick;
}
SYS_Joystick = pNewJoystick;
/* if we are replacing the front of the list then update it */ /* if we are replacing the front of the list then update it */
if ( pNewJoystick == *(JoyStick_DeviceData **)pContext ) if ( pNewJoystick == *(JoyStick_DeviceData **)pContext )
{ {
*(JoyStick_DeviceData **)pContext = pNewJoystick->pNext; *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
} }
else if ( pPrevJoystick )
{
pPrevJoystick->pNext = pNewJoystick->pNext;
}
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance; s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
s_iNewGUID++; s_iNewGUID++;
@ -745,6 +746,7 @@ static BOOL CALLBACK
return DIENUM_STOP; return DIENUM_STOP;
} }
pPrevJoystick = pNewJoystick;
pNewJoystick = pNewJoystick->pNext; pNewJoystick = pNewJoystick->pNext;
} }
@ -756,17 +758,17 @@ static BOOL CALLBACK
if ( bXInputDevice ) if ( bXInputDevice )
{ {
SDL_memset(&(pNewJoystick->dxdevice), 0x0,
sizeof(DIDEVICEINSTANCE));
pNewJoystick->bXInputDevice = SDL_TRUE; pNewJoystick->bXInputDevice = SDL_TRUE;
pNewJoystick->XInputUserId = INVALID_XINPUT_USERID; pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
} }
else else
{ {
pNewJoystick->bXInputDevice = SDL_FALSE; pNewJoystick->bXInputDevice = SDL_FALSE;
}
SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance, SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
sizeof(DIDEVICEINSTANCE)); sizeof(DIDEVICEINSTANCE));
}
pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName); pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
pNewJoystick->send_add_event = 1; pNewJoystick->send_add_event = 1;
pNewJoystick->nInstanceID = ++s_nInstanceID; pNewJoystick->nInstanceID = ++s_nInstanceID;