From f1bcb6604f06d3082dbca76a0c78e09e69dd7ebe Mon Sep 17 00:00:00 2001 From: mjk Date: Sat, 20 Mar 2021 14:30:22 +0000 Subject: [PATCH] rewrite InitApartment and protect callers from (the rest of the) exceptions Initializing COM by calling `winrt::init_apartment()` would always cause stack unwinding *in practice*, which is suboptimal at best, and even using `apartment_type::single_threaded` still would require exception filtering *just in case*. --- .../api/include/gobject/winrt.h | 2 +- .../api/src/gobject/winrt.cpp | 32 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/plugins/windows-notification/api/include/gobject/winrt.h b/plugins/windows-notification/api/include/gobject/winrt.h index 10c4feef..bb2ce728 100644 --- a/plugins/windows-notification/api/include/gobject/winrt.h +++ b/plugins/windows-notification/api/include/gobject/winrt.h @@ -15,7 +15,7 @@ #define NOEXCEPT #endif -EXTERN gboolean winrt_InitApartment(); +EXTERN gboolean winrt_InitApartment() NOEXCEPT; EXTERN char* winrt_windows_ui_notifications_toast_notification_manager_GetTemplateContent(winrtWindowsUINotificationsToastTemplateType type) NOEXCEPT; #undef EXTERN diff --git a/plugins/windows-notification/api/src/gobject/winrt.cpp b/plugins/windows-notification/api/src/gobject/winrt.cpp index d3d1e302..d123dc08 100644 --- a/plugins/windows-notification/api/src/gobject/winrt.cpp +++ b/plugins/windows-notification/api/src/gobject/winrt.cpp @@ -1,28 +1,26 @@ -#include #include "gobject/winrt-private.h" #include "converter.hpp" #include "ginvoke.hpp" -gboolean winrt_InitApartment() +#include + +static void ImplInitApartment() { - try + const auto res = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (FAILED(res)) { - winrt::init_apartment(); - return true; + if (res == RPC_E_CHANGED_MODE) // seems harmless + g_info("attempted to change COM apartment mode of thread %" PRIu32, + ::GetCurrentThreadId()); + else + winrt::throw_hresult(res); } - catch(const winrt::hresult_error& e) - { - auto message = wsview_to_char(e.message()); - std::cerr << message << '\n'; - g_free(message); - if (e.code() == -2147417850 /* RPC_E_CHANGED_MODE */) // harmless - { - return true; - } - } - - return false; +} + +gboolean winrt_InitApartment() noexcept +{ + return g_try_invoke0(ImplInitApartment).has_value(); } static char* ImplGetTemplateContent(winrtWindowsUINotificationsToastTemplateType type)