diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
index 244e5a7..dae45e9 100644
--- a/.idea/dictionaries/project.xml
+++ b/.idea/dictionaries/project.xml
@@ -6,6 +6,8 @@
ajaxgetdlclist
dlmopen
dlopen
+ dlsym
+ endfor
indicies
inlinentd
isteamapps
@@ -16,10 +18,15 @@
koality
koaloader
libgtk
+ libsteam
+ memcpy
phnt
polyhook
+ rtld
simplecpp
+ steamapi
steamapps
+ steamclient
wstr
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9a2af2a..5ebb97f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -20,4 +20,5 @@
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/linux_exports_generator__64_.xml b/.idea/runConfigurations/linux_exports_generator__64_.xml
index 4c9d705..fb84d06 100644
--- a/.idea/runConfigurations/linux_exports_generator__64_.xml
+++ b/.idea/runConfigurations/linux_exports_generator__64_.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/runConfigurations/steamworks_downloader__prompt_.xml b/.idea/runConfigurations/steamworks_downloader__prompt_.xml
index a774a35..75bb294 100644
--- a/.idea/runConfigurations/steamworks_downloader__prompt_.xml
+++ b/.idea/runConfigurations/steamworks_downloader__prompt_.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/runConfigurations/windows_exports_generator__64_.xml b/.idea/runConfigurations/windows_exports_generator__64_.xml
index e4b4d6d..5d96401 100644
--- a/.idea/runConfigurations/windows_exports_generator__64_.xml
+++ b/.idea/runConfigurations/windows_exports_generator__64_.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/KoalaBox b/KoalaBox
index ba3171f..c59f49a 160000
--- a/KoalaBox
+++ b/KoalaBox
@@ -1 +1 @@
-Subproject commit ba3171fd28a60b8599930b07b02cf77674411726
+Subproject commit c59f49ac00c0433b42e6cd33c56ff616b48d8f8e
diff --git a/README.md b/README.md
index 96acaf6..2589d48 100644
--- a/README.md
+++ b/README.md
@@ -316,9 +316,10 @@ This project makes use of the following open source projects:
- [microsoft/wil](https://github.com/microsoft/wil)
- [p-ranav/glob](https://github.com/p-ranav/glob)
- [pantor/inja](https://github.com/pantor/inja)
+- [jarro2783/cxxopts](https://github.com/jarro2783/cxxopts)
+- [serge1/ELFIO](https://github.com/serge1/ELFIO)
- [bshoshany/thread-pool](https://github.com/bshoshany/thread-pool)
- [batterycenter/embed](https://github.com/batterycenter/embed)
-- [serge1/ELFIO](https://github.com/serge1/ELFIO)
## 📄 License
diff --git a/README.template.md b/README.template.md
index 9017faa..89a6684 100644
--- a/README.template.md
+++ b/README.template.md
@@ -54,6 +54,5 @@ They will be added to the list of missing DLC IDs to facilitate config-less oper
{% block extra_oss_libs %}
- [bshoshany/thread-pool](https://github.com/bshoshany/thread-pool)
- [batterycenter/embed](https://github.com/batterycenter/embed)
-- [serge1/ELFIO](https://github.com/serge1/ELFIO)
{% endblock %}
{% endblock %}
\ No newline at end of file
diff --git a/src/smoke_api/smoke_api.cpp b/src/smoke_api/smoke_api.cpp
index 6e578af..05e2a79 100644
--- a/src/smoke_api/smoke_api.cpp
+++ b/src/smoke_api/smoke_api.cpp
@@ -1,22 +1,25 @@
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "smoke_api.hpp"
-
+#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// static
#include "smoke_api/config.hpp"
#include "smoke_api/steamclient/steamclient.hpp"
+
+#include "smoke_api.hpp"
#include "steam_api/steam_interfaces.hpp"
#include "steam_api/virtuals/steam_api_virtuals.hpp"
@@ -73,8 +76,8 @@ namespace {
return versions;
}
- void warn_if_late_injection(const std::string& steamclient_version) {
#ifdef KB_WIN
+ void warn_if_late_injection(const std::string& steamclient_version) {
if(kb::util::is_wine_env()) {
return;
}
@@ -86,8 +89,8 @@ namespace {
"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
}
+#endif
// ReSharper disable once CppDFAConstantFunctionResult
bool on_steamclient_loaded(void* steamclient_handle) {
@@ -107,7 +110,9 @@ namespace {
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
warn_if_late_injection(steamclient_version);
+#endif
steam_interfaces::hook_steamclient_interface(steamclient_handle, steamclient_version);
} else {
@@ -120,7 +125,9 @@ namespace {
}
void init_lib_monitor() {
+#if defined(KB_WIN) || defined(KB_64)
kb::lib_monitor::init_listener({{STEAMCLIENT_DLL, on_steamclient_loaded}});
+#endif
}
std::optional get_app_id_from_env() noexcept {
@@ -168,12 +175,49 @@ namespace {
return std::nullopt;
}
+
+ void init_hook_mode(void* self_module_handle) {
+ is_hook_mode = true;
+#ifdef KB_LINUX
+ // Because we got injected via LD_PRELOAD,
+ // Linux loader will resolve all SteamAPI exports in unlocker instead of original library.
+ // Hence, we need to patch the stubs even in hook mode.
+
+ const std::string lib_name = STEAM_API_MODULE ".so";
+ for(const auto& lib_path : glob::rglob({"./" + lib_name, "**/" + lib_name})) {
+ if(const auto lib_bitness = kb::lib::get_bitness(lib_path)) {
+ if(static_cast(*lib_bitness) == kb::platform::bitness) {
+ if(const auto lib_handle = kb::lib::load_library(lib_path)) {
+ LOG_INFO("Found original library: {}", kb::path::to_str(lib_path));
+
+ original_steamapi_handle = *lib_handle;
+ proxy_exports::init(self_module_handle, original_steamapi_handle);
+ return;
+ }
+ }
+ }
+ }
+
+ if(!original_steamapi_handle) {
+ kb::util::panic("Failed to find original " + lib_name);
+ }
+#endif
+ }
+
+ void init_proxy_mode(void* self_module_handle) {
+ is_hook_mode = true;
+
+ original_steamapi_handle = kb::lib::load_original_library(kb::paths::get_self_dir(), STEAM_API_MODULE);
+#ifdef KB_LINUX
+ proxy_exports::init(self_module_handle, original_steamapi_handle);
+#endif
+ }
}
namespace smoke_api {
- void init(void* module_handle) {
+ void init(void* self_module_handle) {
try {
- kb::globals::init_globals(module_handle, PROJECT_NAME);
+ kb::globals::init_globals(self_module_handle, PROJECT_NAME);
config::instance = kb::config::parse();
@@ -189,8 +233,8 @@ namespace smoke_api {
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);
- LOG_DEBUG("Self name: '{}'", kb::path::to_str(kb::lib::get_fs_path(module_handle).filename()));
+ LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::platform::bitness);
+ LOG_DEBUG("Self name: '{}'", kb::path::to_str(kb::lib::get_fs_path(self_module_handle).filename()));
#ifdef KB_WIN
kb::win::check_self_duplicates();
@@ -199,25 +243,16 @@ namespace smoke_api {
// We need to hook functions in either mode
kb::hook::init(true);
- if(kb::hook::is_hook_mode(module_handle, STEAM_API_MODULE)) {
+ if(kb::hook::is_hook_mode(self_module_handle, STEAM_API_MODULE)) {
LOG_INFO("Detected hook mode");
-
- is_hook_mode = true;
- init_lib_monitor();
+ init_hook_mode(self_module_handle);
} else {
LOG_INFO("Detected proxy mode");
-
- is_hook_mode = true;
- init_lib_monitor();
-
- const auto self_path = kb::paths::get_self_dir();
- original_steamapi_handle = kb::lib::load_original_library(self_path, STEAM_API_MODULE);
-
-#ifdef KB_LINUX
- proxy_exports::init(module_handle, original_steamapi_handle);
-#endif
+ init_proxy_mode(self_module_handle);
}
+ init_lib_monitor();
+
LOG_INFO("Initialization complete");
} catch(const std::exception& e) {
kb::util::panic(std::format("Initialization error: {}", e.what()));
diff --git a/src/smoke_api/smoke_api.hpp b/src/smoke_api/smoke_api.hpp
index ba02708..696c10f 100644
--- a/src/smoke_api/smoke_api.hpp
+++ b/src/smoke_api/smoke_api.hpp
@@ -8,7 +8,7 @@
#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec(dllexport) TYPE __cdecl
namespace smoke_api {
- void init(void* module_handle);
+ void init(void* self_module_handle);
void shutdown();
AppId_t get_app_id();