Cleaned up CoInitialize() politics on Windows.
--- a/src/core/windows/SDL_windows.c Thu Aug 04 01:07:13 2011 -0400
+++ b/src/core/windows/SDL_windows.c Wed Aug 03 04:22:47 2011 -0400
@@ -23,6 +23,8 @@
#include "SDL_error.h"
#include "SDL_windows.h"
+#include <objbase.h> /* for CoInitialize/CoUninitialize */
+
/* Sets an error message based on GetLastError() */
void
@@ -37,4 +39,23 @@
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: */
--- a/src/core/windows/SDL_windows.h Thu Aug 04 01:07:13 2011 -0400
+++ b/src/core/windows/SDL_windows.h Wed Aug 03 04:22:47 2011 -0400
@@ -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: */
--- a/src/haptic/windows/SDL_syshaptic.c Thu Aug 04 01:07:13 2011 -0400
+++ b/src/haptic/windows/SDL_syshaptic.c Wed Aug 03 04:22:47 2011 -0400
@@ -68,6 +68,7 @@
/*
* Internal stuff.
*/
+static SDL_bool coinitialized = SDL_FALSE;
static LPDIRECTINPUT dinput = NULL;
@@ -147,15 +148,18 @@
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 @@
/* 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 @@
DIEDFL_FORCEFEEDBACK |
DIEDFL_ATTACHEDONLY);
if (FAILED(ret)) {
+ SDL_SYS_HapticQuit();
DI_SetError("Enumerating DirectInput devices", ret);
return -1;
}
@@ -664,8 +671,15 @@
}
}
- IDirectInput_Release(dinput);
- dinput = NULL;
+ if (dinput != NULL) {
+ IDirectInput_Release(dinput);
+ dinput = NULL;
+ }
+
+ if (coinitialized) {
+ WIN_CoUninitialize();
+ coinitialized = SDL_FALSE;
+ }
}
--- a/src/joystick/windows/SDL_dxjoystick.c Thu Aug 04 01:07:13 2011 -0400
+++ b/src/joystick/windows/SDL_dxjoystick.c Wed Aug 03 04:22:47 2011 -0400
@@ -57,6 +57,7 @@
/* 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 @@
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 @@
/* 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 @@
result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
if (FAILED(result)) {
+ SDL_SYS_JoystickQuit();
SetDIerror("IDirectInput::Initialize", result);
return (-1);
}
@@ -802,8 +808,15 @@
}
}
- IDirectInput_Release(dinput);
- dinput = NULL;
+ if (dinput != NULL) {
+ IDirectInput_Release(dinput);
+ dinput = NULL;
+ }
+
+ if (coinitialized) {
+ WIN_CoUninitialize();
+ coinitialized = SDL_FALSE;
+ }
}
#endif /* SDL_JOYSTICK_DINPUT */
--- a/src/video/windows/SDL_windowskeyboard.c Thu Aug 04 01:07:13 2011 -0400
+++ b/src/video/windows/SDL_windowskeyboard.c Wed Aug 03 04:22:47 2011 -0400
@@ -305,7 +305,7 @@
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 @@
videodata->ime_threadmgr = 0;
}
if (videodata->ime_com_initialized) {
- CoUninitialize();
+ WIN_CoUninitialize();
videodata->ime_com_initialized = SDL_FALSE;
}
IME_DestroyTextures(videodata);