From 8c5e69672000cad5956b8bc78b70c3e5cadbbb34 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 16 Jun 2022 12:12:36 +0200 Subject: [PATCH] Fix threading issues --- src/client/component/arxan.cpp | 5 + src/client/component/scheduler.cpp | 2 +- src/client/component/splash.cpp | 107 ++++++++++++++++------ src/client/component/splash.hpp | 6 ++ src/client/loader/component_interface.hpp | 5 + src/client/loader/component_loader.cpp | 9 +- 6 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 src/client/component/splash.hpp diff --git a/src/client/component/arxan.cpp b/src/client/component/arxan.cpp index f6e7f420..47cfc3a9 100644 --- a/src/client/component/arxan.cpp +++ b/src/client/component/arxan.cpp @@ -870,6 +870,11 @@ namespace arxan open_process_hook.clear(); } + int priority() override + { + return 9999; + } + private: uint8_t window_text_buffer_[15]{}; }; diff --git a/src/client/component/scheduler.cpp b/src/client/component/scheduler.cpp index f7c693dd..47bda262 100644 --- a/src/client/component/scheduler.cpp +++ b/src/client/component/scheduler.cpp @@ -150,7 +150,7 @@ namespace scheduler class component final : public component_interface { public: - void post_unpack() override + void pre_start() override { thread = utils::thread::create_named_thread("Async Scheduler", []() { diff --git a/src/client/component/splash.cpp b/src/client/component/splash.cpp index 85f86f5b..b4a35a99 100644 --- a/src/client/component/splash.cpp +++ b/src/client/component/splash.cpp @@ -1,5 +1,6 @@ #include #include "loader/component_loader.hpp" +#include "splash.hpp" #include "resource.hpp" #include @@ -35,33 +36,23 @@ namespace splash : image_(load_splash_image()) { enable_dpi_awareness(); - this->show(); + this->window_thread_ = std::thread([this] + { + this->draw(); + }); } - void pre_start() override + ~component() { - this->draw_frame(); + if (this->window_thread_.joinable()) + { + this->window_thread_.detach(); + } } void pre_destroy() override { this->destroy(); - - MSG msg; - while (this->window_ && IsWindow(this->window_)) - { - if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - else - { - std::this_thread::sleep_for(1ms); - } - } - - this->window_ = nullptr; } void post_unpack() override @@ -69,30 +60,77 @@ namespace splash this->destroy(); } - private: - HWND window_{}; - HANDLE image_{}; - - void draw_frame() const + void hide() const { - MSG msg{}; - while (this->window_ && PeekMessageW(&msg, nullptr, NULL, NULL, PM_REMOVE)) + if (this->window_ && IsWindow(this->window_)) { - TranslateMessage(&msg); - DispatchMessageW(&msg); + ShowWindow(this->window_, SW_HIDE); + UpdateWindow(this->window_); } } - void destroy() const + private: + std::atomic_bool join_safe_{false}; + HWND window_{}; + HANDLE image_{}; + std::thread window_thread_{}; + + void destroy() { if (this->window_ && IsWindow(this->window_)) { ShowWindow(this->window_, SW_HIDE); DestroyWindow(this->window_); - UnregisterClassA("Black Ops III Splash Screen", utils::nt::library{}); + this->window_ = nullptr; + if (this->window_thread_.joinable()) + { + this->window_thread_.join(); + } + + this->window_ = nullptr; } } + void draw() + { + this->show(); + while (this->draw_frame()) + { + std::this_thread::sleep_for(1ms); + } + + this->window_ = nullptr; + UnregisterClassA("Black Ops III Splash Screen", utils::nt::library{}); + } + + bool draw_frame() const + { + if (!this->window_) + { + return false; + } + + MSG msg{}; + bool success = true; + + while (PeekMessageW(&msg, nullptr, NULL, NULL, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (msg.message == WM_DESTROY && msg.hwnd == this->window_) + { + PostQuitMessage(0); + } + + if (msg.message == WM_QUIT) + { + success = false; + } + } + return success; + } + void show() { WNDCLASSA wnd_class; @@ -158,6 +196,15 @@ namespace splash } } }; + + void hide() + { + auto* splash_component = component_loader::get(); + if (splash_component) + { + splash_component->hide(); + } + } } REGISTER_COMPONENT(splash::component) diff --git a/src/client/component/splash.hpp b/src/client/component/splash.hpp new file mode 100644 index 00000000..330ae8cd --- /dev/null +++ b/src/client/component/splash.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace splash +{ + void hide(); +} diff --git a/src/client/loader/component_interface.hpp b/src/client/loader/component_interface.hpp index 43642a10..3fa612d6 100644 --- a/src/client/loader/component_interface.hpp +++ b/src/client/loader/component_interface.hpp @@ -21,4 +21,9 @@ public: { return true; } + + virtual int priority() + { + return 0; + } }; diff --git a/src/client/loader/component_loader.cpp b/src/client/loader/component_loader.cpp index 0bba4f4d..94cb35a5 100644 --- a/src/client/loader/component_loader.cpp +++ b/src/client/loader/component_loader.cpp @@ -5,7 +5,14 @@ void component_loader::register_component(std::unique_ptr&& component_) { - get_components().push_back(std::move(component_)); + auto& components = get_components(); + components.push_back(std::move(component_)); + + std::ranges::stable_sort(components, [](const std::unique_ptr& a, + const std::unique_ptr& b) + { + return a->priority() > b->priority(); + }); } bool component_loader::pre_start()