From 5ee8bbe467806ad78061c3450df36eb572422897 Mon Sep 17 00:00:00 2001 From: Roland Winklmeier Date: Mon, 15 Oct 2018 12:13:54 +0200 Subject: [PATCH] Properly initialize and cleanup DirectInput ref T391 --- src/blackinput/win/joystickwindows.cpp | 46 ++++++++++++++++++++------ src/blackinput/win/joystickwindows.h | 1 + 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/blackinput/win/joystickwindows.cpp b/src/blackinput/win/joystickwindows.cpp index 5ede8e32c..574bd4860 100644 --- a/src/blackinput/win/joystickwindows.cpp +++ b/src/blackinput/win/joystickwindows.cpp @@ -152,30 +152,54 @@ namespace BlackInput CJoystickWindows::CJoystickWindows(QObject *parent) : IJoystick(parent) { - // Initialize COM - CoInitializeEx(nullptr, COINIT_MULTITHREADED); - this->createHelperWindow(); + // Initialize COM. + // https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-coinitializeex + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - if (helperWindow) + // RPC_E_CHANGED_MODE: CoInitializeEx was already called by someone else in this thread with a different mode. + if (hr == RPC_E_CHANGED_MODE) { - this->initDirectInput(); - this->enumJoystickDevices(); + CLogMessage(this).debug("CoInitializeEx was already called with a different mode. Trying again."); + hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); } + + // Continue here only if CoInitializeEx was successful + // S_OK: The COM library was initialized successfully on this thread. + // S_FALSE: The COM library is already initialized on this thread. Reference count was incremented. This is not an error. + if (hr == S_OK || hr == S_FALSE) + { + m_coInitializeSucceeded = true; + this->createHelperWindow(); + + if (helperWindow) + { + this->initDirectInput(); + this->enumJoystickDevices(); + } + } + else + { + CLogMessage(this).warning("CoInitializeEx returned error code %1"); + } + } CJoystickWindows::~CJoystickWindows() { + // All DirectInput devices need to be cleaned up before the call to CoUninitialize() + for (CJoystickDevice *joystickDevice : m_joystickDevices) + { + delete joystickDevice; + } m_joystickDevices.clear(); m_directInput.reset(); - CoUninitialize(); + if (m_coInitializeSucceeded) { CoUninitialize(); } destroyHelperWindow(); } void ReleaseDirectInput(IDirectInput8 *obj) { - Q_UNUSED(obj); - //! \todo temp workaround for crash when shutting down T391 - // if (obj) { obj->Release(); } + if (obj) { obj->Release(); } } HRESULT CJoystickWindows::initDirectInput() @@ -277,7 +301,7 @@ namespace BlackInput } else { - device->deleteLater(); + delete device; } } diff --git a/src/blackinput/win/joystickwindows.h b/src/blackinput/win/joystickwindows.h index dd23dbc5a..d338e6e85 100644 --- a/src/blackinput/win/joystickwindows.h +++ b/src/blackinput/win/joystickwindows.h @@ -140,6 +140,7 @@ namespace BlackInput const TCHAR *helperWindowClassName = TEXT("HelperWindow"); const TCHAR *helperWindowName = TEXT("JoystickCatcherWindow"); + bool m_coInitializeSucceeded = false; DirectInput8Ptr m_directInput; //!< DirectInput object QVector m_joystickDevices; //!< Joystick devices