From 7cf57ffba46cd2e4c6581eb405532d737c5d949d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 3 Aug 2011 04:22:47 -0400 Subject: [PATCH] Cleaned up CoInitialize() politics on Windows. --- src/core/windows/SDL_windows.c | 21 +++++++++++++++++++++ src/core/windows/SDL_windows.h | 4 ++++ src/haptic/windows/SDL_syshaptic.c | 20 +++++++++++++++++--- src/joystick/windows/SDL_dxjoystick.c | 19 ++++++++++++++++--- src/video/windows/SDL_windowskeyboard.c | 4 ++-- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index f154bebc5..275ec4469 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -23,6 +23,8 @@ #include "SDL_error.h" #include "SDL_windows.h" +#include /* for CoInitialize/CoUninitialize */ + /* Sets an error message based on GetLastError() */ void @@ -37,4 +39,23 @@ WIN_SetError(const char *prefix) SDL_free(message); } +HRESULT +WIN_CoInitialize(void) +{ + /* S_FALSE means success, but someone else already initialized. */ + /* You still need to call CoUninitialize in this case! */ + const HRESULT hr = CoInitialize(NULL); + if ((hr == S_OK) || (hr == S_FALSE)) { + return S_OK; + } + + return hr; +} + +void +WIN_CoUninitialize(void) +{ + CoUninitialize(); +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 194c8a176..604370ba4 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -47,6 +47,10 @@ /* Sets an error message based on GetLastError() */ extern void WIN_SetError(const char *prefix); +/* Wrap up the oddities of CoInitialize() into a common function. */ +extern HRESULT WIN_CoInitialize(void); +extern void WIN_CoUninitialize(void); + #endif /* _INCLUDED_WINDOWS_H */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/haptic/windows/SDL_syshaptic.c b/src/haptic/windows/SDL_syshaptic.c index 6209257cb..79a9ab9b1 100644 --- a/src/haptic/windows/SDL_syshaptic.c +++ b/src/haptic/windows/SDL_syshaptic.c @@ -68,6 +68,7 @@ struct haptic_hweffect /* * Internal stuff. */ +static SDL_bool coinitialized = SDL_FALSE; static LPDIRECTINPUT dinput = NULL; @@ -147,15 +148,18 @@ SDL_SYS_HapticInit(void) SDL_numhaptics = 0; - ret = CoInitialize(NULL); + ret = WIN_CoInitialize(); if (FAILED(ret)) { DI_SetError("Coinitialize", ret); return -1; } + coinitialized = SDL_TRUE; + ret = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, (LPVOID) & dinput); if (FAILED(ret)) { + SDL_SYS_HapticQuit(); DI_SetError("CoCreateInstance", ret); return -1; } @@ -163,12 +167,14 @@ SDL_SYS_HapticInit(void) /* Because we used CoCreateInstance, we need to Initialize it, first. */ instance = GetModuleHandle(NULL); if (instance == NULL) { + SDL_SYS_HapticQuit(); SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError()); return -1; } ret = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION); if (FAILED(ret)) { + SDL_SYS_HapticQuit(); DI_SetError("Initializing DirectInput device", ret); return -1; } @@ -181,6 +187,7 @@ SDL_SYS_HapticInit(void) DIEDFL_FORCEFEEDBACK | DIEDFL_ATTACHEDONLY); if (FAILED(ret)) { + SDL_SYS_HapticQuit(); DI_SetError("Enumerating DirectInput devices", ret); return -1; } @@ -664,8 +671,15 @@ SDL_SYS_HapticQuit(void) } } - IDirectInput_Release(dinput); - dinput = NULL; + if (dinput != NULL) { + IDirectInput_Release(dinput); + dinput = NULL; + } + + if (coinitialized) { + WIN_CoUninitialize(); + coinitialized = SDL_FALSE; + } } diff --git a/src/joystick/windows/SDL_dxjoystick.c b/src/joystick/windows/SDL_dxjoystick.c index 8799511b4..6d9b44ff8 100644 --- a/src/joystick/windows/SDL_dxjoystick.c +++ b/src/joystick/windows/SDL_dxjoystick.c @@ -57,6 +57,7 @@ extern HWND SDL_HelperWindow; /* local variables */ +static SDL_bool coinitialized = SDL_FALSE; static LPDIRECTINPUT dinput = NULL; extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT * ppDI, @@ -284,16 +285,19 @@ SDL_SYS_JoystickInit(void) SYS_NumJoysticks = 0; - result = CoInitialize(NULL); + result = WIN_CoInitialize(); if (FAILED(result)) { SetDIerror("CoInitialize", result); return (-1); } + coinitialized = SDL_TRUE; + result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, (LPVOID)&dinput); if (FAILED(result)) { + SDL_SYS_JoystickQuit(); SetDIerror("CoCreateInstance", result); return (-1); } @@ -301,6 +305,7 @@ SDL_SYS_JoystickInit(void) /* Because we used CoCreateInstance, we need to Initialize it, first. */ instance = GetModuleHandle(NULL); if (instance == NULL) { + SDL_SYS_JoystickQuit(); SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError()); return (-1); @@ -308,6 +313,7 @@ SDL_SYS_JoystickInit(void) result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION); if (FAILED(result)) { + SDL_SYS_JoystickQuit(); SetDIerror("IDirectInput::Initialize", result); return (-1); } @@ -802,8 +808,15 @@ SDL_SYS_JoystickQuit(void) } } - IDirectInput_Release(dinput); - dinput = NULL; + if (dinput != NULL) { + IDirectInput_Release(dinput); + dinput = NULL; + } + + if (coinitialized) { + WIN_CoUninitialize(); + coinitialized = SDL_FALSE; + } } #endif /* SDL_JOYSTICK_DINPUT */ diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 43b1416c1..ca03e529b 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -305,7 +305,7 @@ IME_Init(SDL_VideoData *videodata, HWND hwnd) return; videodata->ime_hwnd_main = hwnd; - if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { + if (SUCCEEDED(WIN_CoInitialize())) { videodata->ime_com_initialized = SDL_TRUE; CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr); } @@ -389,7 +389,7 @@ IME_Quit(SDL_VideoData *videodata) videodata->ime_threadmgr = 0; } if (videodata->ime_com_initialized) { - CoUninitialize(); + WIN_CoUninitialize(); videodata->ime_com_initialized = SDL_FALSE; } IME_DestroyTextures(videodata);