From 576e4406219a08d26be6eb8de6003c5a7aa652f8 Mon Sep 17 00:00:00 2001 From: George Tokmaji Date: Sat, 28 Jan 2023 14:15:55 +0100 Subject: [PATCH] Use RAII for COM initialization --- cmake/filelists/EngineWin32.txt | 1 + src/C4Com.h | 55 +++++++++++++++++++++++++++++++++ src/C4WinMain.cpp | 7 +++-- src/StdWindow.h | 8 ++--- 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 src/C4Com.h diff --git a/cmake/filelists/EngineWin32.txt b/cmake/filelists/EngineWin32.txt index 3a731561a..4fc0c1669 100644 --- a/cmake/filelists/EngineWin32.txt +++ b/cmake/filelists/EngineWin32.txt @@ -1,3 +1,4 @@ +src/C4Com.h src/C4CrashHandlerWin32.cpp src/C4FileClasses.cpp src/C4Windows.h diff --git a/src/C4Com.h b/src/C4Com.h new file mode 100644 index 000000000..bb05b8aa3 --- /dev/null +++ b/src/C4Com.h @@ -0,0 +1,55 @@ +/* + * LegacyClonk + * + * Copyright (c) 2023, The LegacyClonk Team and contributors + * + * Distributed under the terms of the ISC license; see accompanying file + * "COPYING" for details. + * + * "Clonk" is a registered trademark of Matthes Bender, used with permission. + * See accompanying file "TRADEMARK" for details. + * + * To redistribute this file separately, substitute the full license texts + * for the above references. + */ + +#pragma once + +#include "C4WinRT.h" + +class C4Com +{ +public: + C4Com() = default; + + explicit C4Com(const winrt::apartment_type apartmentType) + { + MapHResultError(&winrt::init_apartment, apartmentType); + initialized = true; + } + + ~C4Com() + { + if (initialized) + { + winrt::uninit_apartment(); + } + } + + C4Com(const C4Com &) = delete; + C4Com &operator=(const C4Com &) = delete; + + C4Com(C4Com &&other) noexcept + : initialized{std::exchange(other.initialized, false)} + { + } + + C4Com &operator=(C4Com &&other) noexcept + { + initialized = std::exchange(other.initialized, false); + return *this; + } + +private: + bool initialized{false}; +}; diff --git a/src/C4WinMain.cpp b/src/C4WinMain.cpp index 686c85916..e9b9ee01a 100644 --- a/src/C4WinMain.cpp +++ b/src/C4WinMain.cpp @@ -34,6 +34,7 @@ #endif #ifdef WIN32 +#include "C4Com.h" #include "C4WinRT.h" #include #endif @@ -109,9 +110,11 @@ int WINAPI WinMain(HINSTANCE hInst, SetCurrentProcessExplicitAppUserModelID(_CRT_WIDE(STD_APPUSERMODELID)); + C4Com com; + try { - winrt::init_apartment(); + com = C4Com{winrt::apartment_type::multi_threaded}; } catch (const winrt::hresult_error &e) { @@ -119,8 +122,6 @@ int WINAPI WinMain(HINSTANCE hInst, return C4XRV_Failure; } - struct ComUninit { ~ComUninit() { winrt::uninit_apartment(); } } uninit; - // Init application try { diff --git a/src/StdWindow.h b/src/StdWindow.h index 53342e782..283d99cab 100644 --- a/src/StdWindow.h +++ b/src/StdWindow.h @@ -27,6 +27,7 @@ #ifdef _WIN32 const int SEC1_TIMER = 1, SEC1_MSEC = 1000; +#include "C4Com.h" #include "C4WinRT.h" #include @@ -289,16 +290,11 @@ class CStdWindow virtual bool Win32DialogMessageHandling(MSG *msg) { return false; }; private: + C4Com com{winrt::apartment_type::multi_threaded}; DWORD style = WS_OVERLAPPEDWINDOW; DWORD styleEx = 0; winrt::com_ptr taskBarList{nullptr}; - struct ComUnInit - { - ComUnInit() { winrt::init_apartment(); } - ~ComUnInit() { winrt::uninit_apartment(); } - } const comUninit; - #elif defined(USE_X11) protected: