Commit 8fa65eea authored by Ryan C. Gordon's avatar Ryan C. Gordon

Cleaned up CoInitialize() politics on Windows.

parent 0dea877a
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_windows.h" #include "SDL_windows.h"
#include <objbase.h> /* for CoInitialize/CoUninitialize */
/* Sets an error message based on GetLastError() */ /* Sets an error message based on GetLastError() */
void void
...@@ -37,4 +39,23 @@ WIN_SetError(const char *prefix) ...@@ -37,4 +39,23 @@ WIN_SetError(const char *prefix)
SDL_free(message); 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: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -47,6 +47,10 @@ ...@@ -47,6 +47,10 @@
/* Sets an error message based on GetLastError() */ /* Sets an error message based on GetLastError() */
extern void WIN_SetError(const char *prefix); 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 */ #endif /* _INCLUDED_WINDOWS_H */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -68,6 +68,7 @@ struct haptic_hweffect ...@@ -68,6 +68,7 @@ struct haptic_hweffect
/* /*
* Internal stuff. * Internal stuff.
*/ */
static SDL_bool coinitialized = SDL_FALSE;
static LPDIRECTINPUT dinput = NULL; static LPDIRECTINPUT dinput = NULL;
...@@ -147,15 +148,18 @@ SDL_SYS_HapticInit(void) ...@@ -147,15 +148,18 @@ SDL_SYS_HapticInit(void)
SDL_numhaptics = 0; SDL_numhaptics = 0;
ret = CoInitialize(NULL); ret = WIN_CoInitialize();
if (FAILED(ret)) { if (FAILED(ret)) {
DI_SetError("Coinitialize", ret); DI_SetError("Coinitialize", ret);
return -1; return -1;
} }
coinitialized = SDL_TRUE;
ret = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, ret = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectInput, (LPVOID) & dinput); &IID_IDirectInput, (LPVOID) & dinput);
if (FAILED(ret)) { if (FAILED(ret)) {
SDL_SYS_HapticQuit();
DI_SetError("CoCreateInstance", ret); DI_SetError("CoCreateInstance", ret);
return -1; return -1;
} }
...@@ -163,12 +167,14 @@ SDL_SYS_HapticInit(void) ...@@ -163,12 +167,14 @@ SDL_SYS_HapticInit(void)
/* Because we used CoCreateInstance, we need to Initialize it, first. */ /* Because we used CoCreateInstance, we need to Initialize it, first. */
instance = GetModuleHandle(NULL); instance = GetModuleHandle(NULL);
if (instance == NULL) { if (instance == NULL) {
SDL_SYS_HapticQuit();
SDL_SetError("GetModuleHandle() failed with error code %d.", SDL_SetError("GetModuleHandle() failed with error code %d.",
GetLastError()); GetLastError());
return -1; return -1;
} }
ret = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION); ret = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
if (FAILED(ret)) { if (FAILED(ret)) {
SDL_SYS_HapticQuit();
DI_SetError("Initializing DirectInput device", ret); DI_SetError("Initializing DirectInput device", ret);
return -1; return -1;
} }
...@@ -181,6 +187,7 @@ SDL_SYS_HapticInit(void) ...@@ -181,6 +187,7 @@ SDL_SYS_HapticInit(void)
DIEDFL_FORCEFEEDBACK | DIEDFL_FORCEFEEDBACK |
DIEDFL_ATTACHEDONLY); DIEDFL_ATTACHEDONLY);
if (FAILED(ret)) { if (FAILED(ret)) {
SDL_SYS_HapticQuit();
DI_SetError("Enumerating DirectInput devices", ret); DI_SetError("Enumerating DirectInput devices", ret);
return -1; return -1;
} }
...@@ -664,8 +671,15 @@ SDL_SYS_HapticQuit(void) ...@@ -664,8 +671,15 @@ SDL_SYS_HapticQuit(void)
} }
} }
IDirectInput_Release(dinput); if (dinput != NULL) {
dinput = NULL; IDirectInput_Release(dinput);
dinput = NULL;
}
if (coinitialized) {
WIN_CoUninitialize();
coinitialized = SDL_FALSE;
}
} }
......
...@@ -57,6 +57,7 @@ extern HWND SDL_HelperWindow; ...@@ -57,6 +57,7 @@ extern HWND SDL_HelperWindow;
/* local variables */ /* local variables */
static SDL_bool coinitialized = SDL_FALSE;
static LPDIRECTINPUT dinput = NULL; static LPDIRECTINPUT dinput = NULL;
extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion, extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
LPDIRECTINPUT * ppDI, LPDIRECTINPUT * ppDI,
...@@ -284,16 +285,19 @@ SDL_SYS_JoystickInit(void) ...@@ -284,16 +285,19 @@ SDL_SYS_JoystickInit(void)
SYS_NumJoysticks = 0; SYS_NumJoysticks = 0;
result = CoInitialize(NULL); result = WIN_CoInitialize();
if (FAILED(result)) { if (FAILED(result)) {
SetDIerror("CoInitialize", result); SetDIerror("CoInitialize", result);
return (-1); return (-1);
} }
coinitialized = SDL_TRUE;
result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectInput, (LPVOID)&dinput); &IID_IDirectInput, (LPVOID)&dinput);
if (FAILED(result)) { if (FAILED(result)) {
SDL_SYS_JoystickQuit();
SetDIerror("CoCreateInstance", result); SetDIerror("CoCreateInstance", result);
return (-1); return (-1);
} }
...@@ -301,6 +305,7 @@ SDL_SYS_JoystickInit(void) ...@@ -301,6 +305,7 @@ SDL_SYS_JoystickInit(void)
/* Because we used CoCreateInstance, we need to Initialize it, first. */ /* Because we used CoCreateInstance, we need to Initialize it, first. */
instance = GetModuleHandle(NULL); instance = GetModuleHandle(NULL);
if (instance == NULL) { if (instance == NULL) {
SDL_SYS_JoystickQuit();
SDL_SetError("GetModuleHandle() failed with error code %d.", SDL_SetError("GetModuleHandle() failed with error code %d.",
GetLastError()); GetLastError());
return (-1); return (-1);
...@@ -308,6 +313,7 @@ SDL_SYS_JoystickInit(void) ...@@ -308,6 +313,7 @@ SDL_SYS_JoystickInit(void)
result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION); result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
if (FAILED(result)) { if (FAILED(result)) {
SDL_SYS_JoystickQuit();
SetDIerror("IDirectInput::Initialize", result); SetDIerror("IDirectInput::Initialize", result);
return (-1); return (-1);
} }
...@@ -802,8 +808,15 @@ SDL_SYS_JoystickQuit(void) ...@@ -802,8 +808,15 @@ SDL_SYS_JoystickQuit(void)
} }
} }
IDirectInput_Release(dinput); if (dinput != NULL) {
dinput = NULL; IDirectInput_Release(dinput);
dinput = NULL;
}
if (coinitialized) {
WIN_CoUninitialize();
coinitialized = SDL_FALSE;
}
} }
#endif /* SDL_JOYSTICK_DINPUT */ #endif /* SDL_JOYSTICK_DINPUT */
......
...@@ -305,7 +305,7 @@ IME_Init(SDL_VideoData *videodata, HWND hwnd) ...@@ -305,7 +305,7 @@ IME_Init(SDL_VideoData *videodata, HWND hwnd)
return; return;
videodata->ime_hwnd_main = hwnd; videodata->ime_hwnd_main = hwnd;
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { if (SUCCEEDED(WIN_CoInitialize())) {
videodata->ime_com_initialized = SDL_TRUE; videodata->ime_com_initialized = SDL_TRUE;
CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr); CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr);
} }
...@@ -389,7 +389,7 @@ IME_Quit(SDL_VideoData *videodata) ...@@ -389,7 +389,7 @@ IME_Quit(SDL_VideoData *videodata)
videodata->ime_threadmgr = 0; videodata->ime_threadmgr = 0;
} }
if (videodata->ime_com_initialized) { if (videodata->ime_com_initialized) {
CoUninitialize(); WIN_CoUninitialize();
videodata->ime_com_initialized = SDL_FALSE; videodata->ime_com_initialized = SDL_FALSE;
} }
IME_DestroyTextures(videodata); IME_DestroyTextures(videodata);
......
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