Cleaned up CoInitialize() politics on Windows.
authorRyan C. Gordon
Wed, 03 Aug 2011 04:22:47 -0400
changeset 559117beb16fa838
parent 5590 db152c9f31c3
child 5592 2e88d0742f4d
Cleaned up CoInitialize() politics on Windows.
src/core/windows/SDL_windows.c
src/core/windows/SDL_windows.h
src/haptic/windows/SDL_syshaptic.c
src/joystick/windows/SDL_dxjoystick.c
src/video/windows/SDL_windowskeyboard.c
     1.1 --- a/src/core/windows/SDL_windows.c	Thu Aug 04 01:07:13 2011 -0400
     1.2 +++ b/src/core/windows/SDL_windows.c	Wed Aug 03 04:22:47 2011 -0400
     1.3 @@ -23,6 +23,8 @@
     1.4  #include "SDL_error.h"
     1.5  #include "SDL_windows.h"
     1.6  
     1.7 +#include <objbase.h>  /* for CoInitialize/CoUninitialize */
     1.8 +
     1.9  
    1.10  /* Sets an error message based on GetLastError() */
    1.11  void
    1.12 @@ -37,4 +39,23 @@
    1.13      SDL_free(message);
    1.14  }
    1.15  
    1.16 +HRESULT
    1.17 +WIN_CoInitialize(void)
    1.18 +{
    1.19 +    /* S_FALSE means success, but someone else already initialized. */
    1.20 +    /* You still need to call CoUninitialize in this case! */
    1.21 +    const HRESULT hr = CoInitialize(NULL);
    1.22 +    if ((hr == S_OK) || (hr == S_FALSE)) {
    1.23 +        return S_OK;
    1.24 +    }
    1.25 +
    1.26 +    return hr;
    1.27 +}
    1.28 +
    1.29 +void
    1.30 +WIN_CoUninitialize(void)
    1.31 +{
    1.32 +    CoUninitialize();
    1.33 +}
    1.34 +
    1.35  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/core/windows/SDL_windows.h	Thu Aug 04 01:07:13 2011 -0400
     2.2 +++ b/src/core/windows/SDL_windows.h	Wed Aug 03 04:22:47 2011 -0400
     2.3 @@ -47,6 +47,10 @@
     2.4  /* Sets an error message based on GetLastError() */
     2.5  extern void WIN_SetError(const char *prefix);
     2.6  
     2.7 +/* Wrap up the oddities of CoInitialize() into a common function. */
     2.8 +extern HRESULT WIN_CoInitialize(void);
     2.9 +extern void WIN_CoUninitialize(void);
    2.10 +
    2.11  #endif /* _INCLUDED_WINDOWS_H */
    2.12  
    2.13  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/haptic/windows/SDL_syshaptic.c	Thu Aug 04 01:07:13 2011 -0400
     3.2 +++ b/src/haptic/windows/SDL_syshaptic.c	Wed Aug 03 04:22:47 2011 -0400
     3.3 @@ -68,6 +68,7 @@
     3.4  /*
     3.5   * Internal stuff.
     3.6   */
     3.7 +static SDL_bool coinitialized = SDL_FALSE;
     3.8  static LPDIRECTINPUT dinput = NULL;
     3.9  
    3.10  
    3.11 @@ -147,15 +148,18 @@
    3.12  
    3.13      SDL_numhaptics = 0;
    3.14  
    3.15 -    ret = CoInitialize(NULL);
    3.16 +    ret = WIN_CoInitialize();
    3.17      if (FAILED(ret)) {
    3.18          DI_SetError("Coinitialize", ret);
    3.19          return -1;
    3.20      }
    3.21  
    3.22 +    coinitialized = SDL_TRUE;
    3.23 +
    3.24      ret = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
    3.25                             &IID_IDirectInput, (LPVOID) & dinput);
    3.26      if (FAILED(ret)) {
    3.27 +        SDL_SYS_HapticQuit();
    3.28          DI_SetError("CoCreateInstance", ret);
    3.29          return -1;
    3.30      }
    3.31 @@ -163,12 +167,14 @@
    3.32      /* Because we used CoCreateInstance, we need to Initialize it, first. */
    3.33      instance = GetModuleHandle(NULL);
    3.34      if (instance == NULL) {
    3.35 +        SDL_SYS_HapticQuit();
    3.36          SDL_SetError("GetModuleHandle() failed with error code %d.",
    3.37                       GetLastError());
    3.38          return -1;
    3.39      }
    3.40      ret = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
    3.41      if (FAILED(ret)) {
    3.42 +        SDL_SYS_HapticQuit();
    3.43          DI_SetError("Initializing DirectInput device", ret);
    3.44          return -1;
    3.45      }
    3.46 @@ -181,6 +187,7 @@
    3.47                                     DIEDFL_FORCEFEEDBACK |
    3.48                                     DIEDFL_ATTACHEDONLY);
    3.49      if (FAILED(ret)) {
    3.50 +        SDL_SYS_HapticQuit();
    3.51          DI_SetError("Enumerating DirectInput devices", ret);
    3.52          return -1;
    3.53      }
    3.54 @@ -664,8 +671,15 @@
    3.55          }
    3.56      }
    3.57  
    3.58 -    IDirectInput_Release(dinput);
    3.59 -    dinput = NULL;
    3.60 +    if (dinput != NULL) {
    3.61 +        IDirectInput_Release(dinput);
    3.62 +        dinput = NULL;
    3.63 +    }
    3.64 +
    3.65 +    if (coinitialized) {
    3.66 +        WIN_CoUninitialize();
    3.67 +        coinitialized = SDL_FALSE;
    3.68 +    }
    3.69  }
    3.70  
    3.71  
     4.1 --- a/src/joystick/windows/SDL_dxjoystick.c	Thu Aug 04 01:07:13 2011 -0400
     4.2 +++ b/src/joystick/windows/SDL_dxjoystick.c	Wed Aug 03 04:22:47 2011 -0400
     4.3 @@ -57,6 +57,7 @@
     4.4  
     4.5  
     4.6  /* local variables */
     4.7 +static SDL_bool coinitialized = SDL_FALSE;
     4.8  static LPDIRECTINPUT dinput = NULL;
     4.9  extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
    4.10                                         LPDIRECTINPUT * ppDI,
    4.11 @@ -284,16 +285,19 @@
    4.12  
    4.13      SYS_NumJoysticks = 0;
    4.14  
    4.15 -    result = CoInitialize(NULL);
    4.16 +    result = WIN_CoInitialize();
    4.17      if (FAILED(result)) {
    4.18          SetDIerror("CoInitialize", result);
    4.19          return (-1);
    4.20      }
    4.21  
    4.22 +    coinitialized = SDL_TRUE;
    4.23 +
    4.24      result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
    4.25                                &IID_IDirectInput, (LPVOID)&dinput);
    4.26  
    4.27      if (FAILED(result)) {
    4.28 +        SDL_SYS_JoystickQuit();
    4.29          SetDIerror("CoCreateInstance", result);
    4.30          return (-1);
    4.31      }
    4.32 @@ -301,6 +305,7 @@
    4.33      /* Because we used CoCreateInstance, we need to Initialize it, first. */
    4.34      instance = GetModuleHandle(NULL);
    4.35      if (instance == NULL) {
    4.36 +        SDL_SYS_JoystickQuit();
    4.37          SDL_SetError("GetModuleHandle() failed with error code %d.",
    4.38                       GetLastError());
    4.39          return (-1);
    4.40 @@ -308,6 +313,7 @@
    4.41      result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
    4.42  
    4.43      if (FAILED(result)) {
    4.44 +        SDL_SYS_JoystickQuit();
    4.45          SetDIerror("IDirectInput::Initialize", result);
    4.46          return (-1);
    4.47      }
    4.48 @@ -802,8 +808,15 @@
    4.49          }
    4.50      }
    4.51  
    4.52 -    IDirectInput_Release(dinput);
    4.53 -    dinput = NULL;
    4.54 +    if (dinput != NULL) {
    4.55 +        IDirectInput_Release(dinput);
    4.56 +        dinput = NULL;
    4.57 +    }
    4.58 +
    4.59 +    if (coinitialized) {
    4.60 +        WIN_CoUninitialize();
    4.61 +        coinitialized = SDL_FALSE;
    4.62 +    }
    4.63  }
    4.64  
    4.65  #endif /* SDL_JOYSTICK_DINPUT */
     5.1 --- a/src/video/windows/SDL_windowskeyboard.c	Thu Aug 04 01:07:13 2011 -0400
     5.2 +++ b/src/video/windows/SDL_windowskeyboard.c	Wed Aug 03 04:22:47 2011 -0400
     5.3 @@ -305,7 +305,7 @@
     5.4          return;
     5.5  
     5.6      videodata->ime_hwnd_main = hwnd;
     5.7 -    if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
     5.8 +    if (SUCCEEDED(WIN_CoInitialize())) {
     5.9          videodata->ime_com_initialized = SDL_TRUE;
    5.10          CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr);
    5.11      }
    5.12 @@ -389,7 +389,7 @@
    5.13          videodata->ime_threadmgr = 0;
    5.14      }
    5.15      if (videodata->ime_com_initialized) {
    5.16 -        CoUninitialize();
    5.17 +        WIN_CoUninitialize();
    5.18          videodata->ime_com_initialized = SDL_FALSE;
    5.19      }
    5.20      IME_DestroyTextures(videodata);