Sync with KoalaBox

This commit is contained in:
acidicoala
2025-09-19 02:14:17 +05:00
parent 3544436df7
commit a7b95fc907
16 changed files with 366 additions and 556 deletions

View File

@@ -2,12 +2,11 @@
#include <set>
#include <koalabox/config.hpp>
#include <koalabox/dll_monitor.hpp>
#include <koalabox/lib_monitor.hpp>
#include <koalabox/globals.hpp>
#include <koalabox/hook.hpp>
#include <koalabox/loader.hpp>
#include <koalabox/logger.hpp>
#include <koalabox/module.hpp>
#include <koalabox/lib.hpp>
#include <koalabox/path.hpp>
#include <koalabox/paths.hpp>
#include <koalabox/util.hpp>
@@ -41,17 +40,16 @@
namespace {
namespace kb = koalabox;
void* steamapi_handle = nullptr;
const kb::dll_monitor::callback_context_t* dll_monitor_context = nullptr;
void* original_steamapi_handle = nullptr;
std::set<std::string> find_steamclient_versions() {
std::set<std::string> find_steamclient_versions(void* steamapi_handle) {
if(!steamapi_handle) {
kb::util::panic("Invalid state. steamapi_handle is null.");
}
std::set<std::string> versions;
const auto rdata_section = kb::module::get_section_or_throw(steamapi_handle, kb::module::CONST_STR_SECTION);
const auto rdata_section = kb::lib::get_section_or_throw(steamapi_handle, kb::lib::CONST_STR_SECTION);
const auto rdata = rdata_section.to_string();
const std::regex pattern(R"(SteamClient\d{3})");
@@ -65,26 +63,36 @@ namespace {
return versions;
}
bool on_steamclient_loaded(const HMODULE steamclient_handle) {
void warn_if_late_injection(const std::string& steamclient_version) {
#ifdef KB_WIN
if(kb::util::is_wine_env()) {
return;
}
LOG_WARN(
"'{}' was already initialized. SmokeAPI might not work as expected.", steamclient_version
);
LOG_WARN(
"Probable cause: SmokeAPI was injected too late. If possible, try injecting it earlier."
);
LOG_WARN("NOTE: You can safely ignore this warning if running under Proton or native Linux");
#endif
}
bool on_steamclient_loaded(void* steamclient_handle) {
static const auto CreateInterface$ = KB_MOD_GET_FUNC(steamclient_handle, CreateInterface);
auto* steamapi_handle = original_steamapi_handle
? original_steamapi_handle
: kb::lib::get_library_handle(STEAM_API_MODULE);
if(steamapi_handle) {
// SteamAPI might have been initialized.
// Hence, we need to query SteamClient interfaces and hook them if needed.
const auto steamclient_versions = find_steamclient_versions();
const auto steamclient_versions = find_steamclient_versions(steamapi_handle);
for(const auto& steamclient_version : steamclient_versions) {
if(CreateInterface$(steamclient_version.c_str(), nullptr)) {
#ifdef KB_WIN
if(!kb::util::is_wine_env()) {
LOG_WARN(
"'{}' was already initialized. SmokeAPI might not work as expected.", steamclient_version
);
LOG_WARN(
"Probable cause: SmokeAPI was injected too late. If possible, try injecting it earlier."
);
LOG_WARN("NOTE: You can safely ignore this warning if running under Proton or native Linux");
}
#endif
warn_if_late_injection(steamclient_version);
steam_interfaces::hook_steamclient_interface(steamclient_handle, steamclient_version);
} else {
LOG_INFO("'{}' has not been initialized. Waiting for initialization.", steamclient_version);
@@ -94,16 +102,11 @@ namespace {
KB_HOOK_DETOUR_MODULE(CreateInterface, steamclient_handle);
// TODO: There is an implicit lifetime dependency here and potential for leaks.
// This mechanism requires rework.
// DLL monitor will have destroyed it.
dll_monitor_context = nullptr;
return true;
}
void start_dll_listener() {
dll_monitor_context = kb::dll_monitor::init_listener(
void init_lib_monitor() {
kb::lib_monitor::init_listener(
{{STEAMCLIENT_DLL, on_steamclient_loaded}}
);
}
@@ -123,7 +126,7 @@ namespace smoke_api {
LOG_INFO("{} v{} | Built at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__);
LOG_DEBUG("Parsed config:\n{}", nlohmann::ordered_json(config::instance).dump(2));
const auto exe_path = kb::module::get_fs_path(nullptr);
const auto exe_path = kb::lib::get_fs_path(nullptr);
const auto exe_name = kb::path::to_str(exe_path.filename());
LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::util::BITNESS);
@@ -135,14 +138,14 @@ namespace smoke_api {
if(kb::hook::is_hook_mode(module_handle, STEAM_API_MODULE)) {
LOG_INFO("Detected hook mode");
start_dll_listener();
init_lib_monitor();
} else {
LOG_INFO("Detected proxy mode");
start_dll_listener();
init_lib_monitor();
const auto self_path = kb::paths::get_self_dir();
steamapi_handle = kb::loader::load_original_library(
original_steamapi_handle = kb::lib::load_original_library(
self_path,
STEAM_API_MODULE
);
@@ -156,12 +159,14 @@ namespace smoke_api {
void shutdown() {
try {
if(steamapi_handle != nullptr) {
kb::module::unload_library(steamapi_handle);
steamapi_handle = nullptr;
if(original_steamapi_handle != nullptr) {
kb::lib::unload_library(original_steamapi_handle);
original_steamapi_handle = nullptr;
}
kb::dll_monitor::shutdown_listener(dll_monitor_context);
if(kb::lib_monitor::is_initialized()) {
kb::lib_monitor::shutdown_listener();
}
// TODO: Unhook everything

View File

@@ -6,15 +6,17 @@
namespace steam_client {
void* GetGenericInterface(
const std::string& function_name,
const std::string& interface_version,
const char* interface_version, // This can be null
const std::function<void*()>& original_function
) noexcept {
try {
auto* const interface = original_function();
LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface);
if(interface_version) {
LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface);
steam_interfaces::hook_virtuals(interface, interface_version);
steam_interfaces::hook_virtuals(interface, interface_version);
}
return interface;
} catch(const std::exception& e) {

View File

@@ -5,7 +5,7 @@
namespace steam_client {
void* GetGenericInterface(
const std::string& function_name,
const std::string& interface_version,
const char* interface_version,
const std::function<void*()>& original_function
) noexcept;
}

View File

@@ -7,7 +7,7 @@
#include "steam_api/steam_interfaces.hpp"
#include "koalabox/module.hpp"
#include "koalabox/lib.hpp"
#include "smoke_api/smoke_api.hpp"
#include "smoke_api/steamclient/steamclient.hpp"
#include "virtuals/steam_api_virtuals.hpp"
@@ -196,7 +196,7 @@ namespace steam_interfaces {
}
void hook_steamclient_interface(
const HMODULE steamclient_handle,
void* steamclient_handle,
const std::string& steam_client_interface_version
) noexcept {
try {
@@ -209,7 +209,6 @@ namespace steam_interfaces {
// Map virtual hook map to a set of keys
const auto prefixes = std::views::keys(virtual_hook_map) | std::ranges::to<std::set>();
const auto CreateInterface$ = KB_MOD_GET_FUNC(steamclient_handle, CreateInterface);
const auto* const THIS = CreateInterface$(steam_client_interface_version.c_str(), nullptr);
hook_virtuals(THIS, steam_client_interface_version);

View File

@@ -12,7 +12,7 @@ namespace steam_interfaces {
* such as in the case of late injection.
*/
void hook_steamclient_interface(
HMODULE steamclient_handle,
void* steamclient_handle,
const std::string& steam_client_interface_version
) noexcept;
}