Refactor the component system
This commit is contained in:
parent
13be8f3894
commit
ef39098e28
@ -757,9 +757,9 @@ namespace arxan
|
|||||||
//restore_debug_functions();
|
//restore_debug_functions();
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority() override
|
component_priority priority() const override
|
||||||
{
|
{
|
||||||
return 9999;
|
return component_priority::arxan;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -444,7 +444,7 @@ namespace demonware
|
|||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void pre_load() override
|
component()
|
||||||
{
|
{
|
||||||
udp_servers.create<stun_server>("stun.us.demonware.net");
|
udp_servers.create<stun_server>("stun.us.demonware.net");
|
||||||
udp_servers.create<stun_server>("stun.eu.demonware.net");
|
udp_servers.create<stun_server>("stun.eu.demonware.net");
|
||||||
|
@ -196,7 +196,7 @@ namespace exception
|
|||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void pre_load() override
|
component()
|
||||||
{
|
{
|
||||||
main_thread_id = GetCurrentThreadId();
|
main_thread_id = GetCurrentThreadId();
|
||||||
SetUnhandledExceptionFilter(exception_filter);
|
SetUnhandledExceptionFilter(exception_filter);
|
||||||
|
@ -10,7 +10,9 @@ namespace splash
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
HWND window{};
|
HWND window{};
|
||||||
|
HANDLE image{};
|
||||||
std::thread window_thread{};
|
std::thread window_thread{};
|
||||||
|
std::atomic_bool join_safe{false};
|
||||||
|
|
||||||
HANDLE load_splash_image()
|
HANDLE load_splash_image()
|
||||||
{
|
{
|
||||||
@ -51,53 +53,73 @@ namespace splash
|
|||||||
window_thread.detach();
|
window_thread.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class component final : public component_interface
|
void show()
|
||||||
{
|
|
||||||
public:
|
|
||||||
void pre_load() override
|
|
||||||
{
|
{
|
||||||
this->image_ = load_splash_image();
|
WNDCLASSA wnd_class;
|
||||||
|
|
||||||
enable_dpi_awareness();
|
const auto self = utils::nt::library::get_by_address(load_splash_image);
|
||||||
window_thread = std::thread([this]
|
|
||||||
{
|
|
||||||
this->draw();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void pre_destroy() override
|
wnd_class.style = CS_DROPSHADOW;
|
||||||
{
|
wnd_class.cbClsExtra = 0;
|
||||||
destroy_window();
|
wnd_class.cbWndExtra = 0;
|
||||||
if (window_thread.joinable())
|
wnd_class.lpszMenuName = nullptr;
|
||||||
|
wnd_class.lpfnWndProc = DefWindowProcA;
|
||||||
|
wnd_class.hInstance = self;
|
||||||
|
wnd_class.hIcon = LoadIconA(self, MAKEINTRESOURCEA(ID_ICON));
|
||||||
|
wnd_class.hCursor = LoadCursorA(nullptr, IDC_APPSTARTING);
|
||||||
|
wnd_class.hbrBackground = reinterpret_cast<HBRUSH>(6);
|
||||||
|
wnd_class.lpszClassName = "Black Ops III Splash Screen";
|
||||||
|
|
||||||
|
if (RegisterClassA(&wnd_class))
|
||||||
{
|
{
|
||||||
window_thread.detach();
|
const auto x_pixels = GetSystemMetrics(SM_CXFULLSCREEN);
|
||||||
|
const auto y_pixels = GetSystemMetrics(SM_CYFULLSCREEN);
|
||||||
|
|
||||||
|
if (image)
|
||||||
|
{
|
||||||
|
window = CreateWindowExA(WS_EX_APPWINDOW, "Black Ops III Splash Screen", "BOIII",
|
||||||
|
WS_POPUP | WS_SYSMENU,
|
||||||
|
(x_pixels - 320) / 2, (y_pixels - 100) / 2, 320, 100, nullptr,
|
||||||
|
nullptr,
|
||||||
|
self, nullptr);
|
||||||
|
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
auto* const image_window = CreateWindowExA(0, "Static", nullptr, WS_CHILD | WS_VISIBLE | 0xEu,
|
||||||
|
0, 0,
|
||||||
|
320, 100, window, nullptr, self, nullptr);
|
||||||
|
if (image_window)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
SendMessageA(image_window, 0x172u, 0, reinterpret_cast<LPARAM>(image));
|
||||||
|
GetWindowRect(image_window, &rect);
|
||||||
|
|
||||||
|
const int width = rect.right - rect.left;
|
||||||
|
rect.left = (x_pixels - width) / 2;
|
||||||
|
|
||||||
|
const int height = rect.bottom - rect.top;
|
||||||
|
rect.top = (y_pixels - height) / 2;
|
||||||
|
|
||||||
|
rect.right = rect.left + width;
|
||||||
|
rect.bottom = rect.top + height;
|
||||||
|
AdjustWindowRect(&rect, WS_CHILD | WS_VISIBLE | 0xEu, 0);
|
||||||
|
SetWindowPos(window, nullptr, rect.left, rect.top, rect.right - rect.left,
|
||||||
|
rect.bottom - rect.top, SWP_NOZORDER);
|
||||||
|
|
||||||
|
SetWindowRgn(window,
|
||||||
|
CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, 15,
|
||||||
|
15), TRUE);
|
||||||
|
|
||||||
|
ShowWindow(window, SW_SHOW);
|
||||||
|
UpdateWindow(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void post_unpack() override
|
bool draw_frame()
|
||||||
{
|
|
||||||
destroy_window();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::atomic_bool join_safe_{false};
|
|
||||||
HANDLE image_{};
|
|
||||||
|
|
||||||
void draw()
|
|
||||||
{
|
|
||||||
this->show();
|
|
||||||
while (this->draw_frame())
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(1ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
window = nullptr;
|
|
||||||
UnregisterClassA("Black Ops III Splash Screen", utils::nt::library{});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool draw_frame() const
|
|
||||||
{
|
{
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
@ -125,69 +147,45 @@ namespace splash
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void show()
|
void draw()
|
||||||
{
|
{
|
||||||
WNDCLASSA wnd_class;
|
show();
|
||||||
|
while (draw_frame())
|
||||||
const auto self = utils::nt::library::get_by_address(load_splash_image);
|
|
||||||
|
|
||||||
wnd_class.style = CS_DROPSHADOW;
|
|
||||||
wnd_class.cbClsExtra = 0;
|
|
||||||
wnd_class.cbWndExtra = 0;
|
|
||||||
wnd_class.lpszMenuName = nullptr;
|
|
||||||
wnd_class.lpfnWndProc = DefWindowProcA;
|
|
||||||
wnd_class.hInstance = self;
|
|
||||||
wnd_class.hIcon = LoadIconA(self, MAKEINTRESOURCEA(ID_ICON));
|
|
||||||
wnd_class.hCursor = LoadCursorA(nullptr, IDC_APPSTARTING);
|
|
||||||
wnd_class.hbrBackground = reinterpret_cast<HBRUSH>(6);
|
|
||||||
wnd_class.lpszClassName = "Black Ops III Splash Screen";
|
|
||||||
|
|
||||||
if (RegisterClassA(&wnd_class))
|
|
||||||
{
|
{
|
||||||
const auto x_pixels = GetSystemMetrics(SM_CXFULLSCREEN);
|
std::this_thread::sleep_for(1ms);
|
||||||
const auto y_pixels = GetSystemMetrics(SM_CYFULLSCREEN);
|
|
||||||
|
|
||||||
if (image_)
|
|
||||||
{
|
|
||||||
window = CreateWindowExA(WS_EX_APPWINDOW, "Black Ops III Splash Screen", "BOIII",
|
|
||||||
WS_POPUP | WS_SYSMENU,
|
|
||||||
(x_pixels - 320) / 2, (y_pixels - 100) / 2, 320, 100, nullptr,
|
|
||||||
nullptr,
|
|
||||||
self, nullptr);
|
|
||||||
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
auto* const image_window = CreateWindowExA(0, "Static", nullptr, WS_CHILD | WS_VISIBLE | 0xEu,
|
|
||||||
0, 0,
|
|
||||||
320, 100, window, nullptr, self, nullptr);
|
|
||||||
if (image_window)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
SendMessageA(image_window, 0x172u, 0, reinterpret_cast<LPARAM>(image_));
|
|
||||||
GetWindowRect(image_window, &rect);
|
|
||||||
|
|
||||||
const int width = rect.right - rect.left;
|
|
||||||
rect.left = (x_pixels - width) / 2;
|
|
||||||
|
|
||||||
const int height = rect.bottom - rect.top;
|
|
||||||
rect.top = (y_pixels - height) / 2;
|
|
||||||
|
|
||||||
rect.right = rect.left + width;
|
|
||||||
rect.bottom = rect.top + height;
|
|
||||||
AdjustWindowRect(&rect, WS_CHILD | WS_VISIBLE | 0xEu, 0);
|
|
||||||
SetWindowPos(window, nullptr, rect.left, rect.top, rect.right - rect.left,
|
|
||||||
rect.bottom - rect.top, SWP_NOZORDER);
|
|
||||||
|
|
||||||
SetWindowRgn(window,
|
|
||||||
CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, 15,
|
|
||||||
15), TRUE);
|
|
||||||
|
|
||||||
ShowWindow(window, SW_SHOW);
|
|
||||||
UpdateWindow(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window = nullptr;
|
||||||
|
UnregisterClassA("Black Ops III Splash Screen", utils::nt::library{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
component()
|
||||||
|
{
|
||||||
|
enable_dpi_awareness();
|
||||||
|
|
||||||
|
image = load_splash_image();
|
||||||
|
window_thread = std::thread([this]
|
||||||
|
{
|
||||||
|
draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void pre_destroy() override
|
||||||
|
{
|
||||||
|
destroy_window();
|
||||||
|
if (window_thread.joinable())
|
||||||
|
{
|
||||||
|
window_thread.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
destroy_window();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,9 +235,9 @@ namespace steam_proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority() override
|
component_priority priority() const override
|
||||||
{
|
{
|
||||||
return 998; // Run after the updater
|
return component_priority::steam_proxy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ namespace updater
|
|||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void pre_load() override
|
component()
|
||||||
{
|
{
|
||||||
cleanup_update();
|
cleanup_update();
|
||||||
|
|
||||||
@ -150,9 +150,9 @@ namespace updater
|
|||||||
join();
|
join();
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority() override
|
component_priority priority() const override
|
||||||
{
|
{
|
||||||
return 999;
|
return component_priority::updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
enum class component_priority
|
||||||
|
{
|
||||||
|
min = 0,
|
||||||
|
// must run after the updater
|
||||||
|
steam_proxy,
|
||||||
|
updater,
|
||||||
|
// must have the highest priority
|
||||||
|
arxan,
|
||||||
|
};
|
||||||
|
|
||||||
class component_interface
|
class component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~component_interface() = default;
|
virtual ~component_interface() = default;
|
||||||
|
|
||||||
virtual void pre_load()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void post_load()
|
virtual void post_load()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -21,13 +27,8 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_supported()
|
virtual component_priority priority() const
|
||||||
{
|
{
|
||||||
return true;
|
return component_priority::min;
|
||||||
}
|
|
||||||
|
|
||||||
virtual int priority()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,166 +3,165 @@
|
|||||||
|
|
||||||
#include <utils/nt.hpp>
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
void component_loader::register_component(std::unique_ptr<component_interface>&& component_)
|
namespace component_loader
|
||||||
{
|
{
|
||||||
auto& components = get_components();
|
namespace
|
||||||
components.push_back(std::move(component_));
|
|
||||||
|
|
||||||
std::ranges::stable_sort(components, [](const std::unique_ptr<component_interface>& a,
|
|
||||||
const std::unique_ptr<component_interface>& b)
|
|
||||||
{
|
{
|
||||||
return a->priority() > b->priority();
|
std::vector<std::unique_ptr<component_interface>>& get_components()
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool component_loader::pre_load()
|
|
||||||
{
|
|
||||||
static auto res = []
|
|
||||||
{
|
|
||||||
clean();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
for (const auto& component_ : get_components())
|
using component_vector = std::vector<std::unique_ptr<component_interface>>;
|
||||||
|
using component_vector_container = std::unique_ptr<component_vector, std::function<void(component_vector*)>>
|
||||||
|
;
|
||||||
|
|
||||||
|
static component_vector_container components(new component_vector,
|
||||||
|
[](const component_vector* component_vector)
|
||||||
|
{
|
||||||
|
pre_destroy();
|
||||||
|
delete component_vector;
|
||||||
|
});
|
||||||
|
|
||||||
|
return *components;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<registration_functor>& get_registration_functors()
|
||||||
|
{
|
||||||
|
static std::vector<registration_functor> functors;
|
||||||
|
return functors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate_component(std::unique_ptr<component_interface> component)
|
||||||
|
{
|
||||||
|
auto& components = get_components();
|
||||||
|
components.push_back(std::move(component));
|
||||||
|
|
||||||
|
std::ranges::stable_sort(components, [](const std::unique_ptr<component_interface>& a,
|
||||||
|
const std::unique_ptr<component_interface>& b)
|
||||||
{
|
{
|
||||||
component_->pre_load();
|
return a->priority() > b->priority();
|
||||||
}
|
});
|
||||||
}
|
|
||||||
catch (premature_shutdown_trigger&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool component_loader::post_load()
|
|
||||||
{
|
|
||||||
static auto res = []
|
|
||||||
{
|
|
||||||
clean();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (const auto& component_ : get_components())
|
|
||||||
{
|
|
||||||
component_->post_load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (premature_shutdown_trigger&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void component_loader::post_unpack()
|
|
||||||
{
|
|
||||||
static auto res = []
|
|
||||||
{
|
|
||||||
clean();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (const auto& component_ : get_components())
|
|
||||||
{
|
|
||||||
component_->post_unpack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
TerminateProcess(GetCurrentProcess(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void component_loader::pre_destroy()
|
|
||||||
{
|
|
||||||
static auto res = []
|
|
||||||
{
|
|
||||||
clean();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (const auto& component_ : get_components())
|
|
||||||
{
|
|
||||||
component_->pre_destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
TerminateProcess(GetCurrentProcess(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void component_loader::clean()
|
|
||||||
{
|
|
||||||
auto& components = get_components();
|
|
||||||
for (auto i = components.begin(); i != components.end();)
|
|
||||||
{
|
|
||||||
if (!(*i)->is_supported())
|
|
||||||
{
|
|
||||||
(*i)->pre_destroy();
|
|
||||||
i = components.erase(i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void component_loader::trigger_premature_shutdown()
|
void register_component(registration_functor functor)
|
||||||
{
|
|
||||||
throw premature_shutdown_trigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<component_interface>>& component_loader::get_components()
|
|
||||||
{
|
|
||||||
using component_vector = std::vector<std::unique_ptr<component_interface>>;
|
|
||||||
using component_vector_container = std::unique_ptr<component_vector, std::function<void(component_vector*)>>;
|
|
||||||
|
|
||||||
static component_vector_container components(new component_vector, [](const component_vector* component_vector)
|
|
||||||
{
|
{
|
||||||
pre_destroy();
|
if (!get_components().empty())
|
||||||
delete component_vector;
|
{
|
||||||
});
|
throw std::runtime_error("Registration is too late");
|
||||||
|
}
|
||||||
|
|
||||||
return *components;
|
get_registration_functors().push_back(std::move(functor));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool activate()
|
||||||
|
{
|
||||||
|
static auto res = []
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (auto& functor : get_registration_functors())
|
||||||
|
{
|
||||||
|
activate_component(functor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (premature_shutdown_trigger&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool post_load()
|
||||||
|
{
|
||||||
|
static auto res = []
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (const auto& component : get_components())
|
||||||
|
{
|
||||||
|
component->post_load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (premature_shutdown_trigger&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void post_unpack()
|
||||||
|
{
|
||||||
|
static auto res = []
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (const auto& component : get_components())
|
||||||
|
{
|
||||||
|
component->post_unpack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
TerminateProcess(GetCurrentProcess(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pre_destroy()
|
||||||
|
{
|
||||||
|
static auto res = []
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (const auto& component : get_components())
|
||||||
|
{
|
||||||
|
component->pre_destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, e.what(), "Error", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
TerminateProcess(GetCurrentProcess(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void trigger_premature_shutdown()
|
||||||
|
{
|
||||||
|
throw premature_shutdown_trigger();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get_base()
|
size_t get_base()
|
||||||
@ -170,7 +169,7 @@ size_t get_base()
|
|||||||
static auto base = []
|
static auto base = []
|
||||||
{
|
{
|
||||||
const utils::nt::library host{};
|
const utils::nt::library host{};
|
||||||
if(!host || host == utils::nt::library::get_by_address(get_base))
|
if (!host || host == utils::nt::library::get_by_address(get_base))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Invalid host application");
|
throw std::runtime_error("Invalid host application");
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "component_interface.hpp"
|
#include "component_interface.hpp"
|
||||||
|
|
||||||
class component_loader final
|
namespace component_loader
|
||||||
{
|
{
|
||||||
public:
|
using registration_functor = std::function<std::unique_ptr<component_interface>()>;
|
||||||
|
|
||||||
|
void register_component(registration_functor functor);
|
||||||
|
|
||||||
|
bool activate();
|
||||||
|
bool post_load();
|
||||||
|
void post_unpack();
|
||||||
|
void pre_destroy();
|
||||||
|
|
||||||
|
[[noreturn]] void trigger_premature_shutdown();
|
||||||
|
|
||||||
class premature_shutdown_trigger final : public std::exception
|
class premature_shutdown_trigger final : public std::exception
|
||||||
{
|
{
|
||||||
[[nodiscard]] const char* what() const noexcept override
|
[[nodiscard]] const char* what() const noexcept override
|
||||||
@ -20,36 +30,12 @@ public:
|
|||||||
public:
|
public:
|
||||||
installer()
|
installer()
|
||||||
{
|
{
|
||||||
register_component(std::make_unique<T>());
|
register_component([]
|
||||||
|
{
|
||||||
|
return std::make_unique<T>();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static T* get()
|
|
||||||
{
|
|
||||||
for (const auto& component_ : get_components())
|
|
||||||
{
|
|
||||||
if (typeid(*component_.get()) == typeid(T))
|
|
||||||
{
|
|
||||||
return reinterpret_cast<T*>(component_.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void register_component(std::unique_ptr<component_interface>&& component);
|
|
||||||
|
|
||||||
static bool pre_load();
|
|
||||||
static bool post_load();
|
|
||||||
static void post_unpack();
|
|
||||||
static void pre_destroy();
|
|
||||||
static void clean();
|
|
||||||
|
|
||||||
static void trigger_premature_shutdown();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::vector<std::unique_ptr<component_interface>>& get_components();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REGISTER_COMPONENT(name) \
|
#define REGISTER_COMPONENT(name) \
|
||||||
|
@ -183,7 +183,7 @@ namespace
|
|||||||
{
|
{
|
||||||
remove_crash_file();
|
remove_crash_file();
|
||||||
|
|
||||||
if (!component_loader::pre_load())
|
if (!component_loader::activate())
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user