From 83d6df449cead5df428725a7a5343629922122e6 Mon Sep 17 00:00:00 2001 From: acidicoala <67734819+acidicoala@users.noreply.github.com> Date: Sun, 24 Aug 2025 19:29:54 +0500 Subject: [PATCH] Fixed unicode paths --- CMakeLists.txt | 15 +++---- KoalaBox | 2 +- src/smoke_api.cpp | 42 ++++++++++++------- src/smoke_api.hpp | 8 ++++ src/steam_api/exports/steam_api.cpp | 11 ++--- src/steam_api/exports/steam_api.hpp | 8 ++++ .../exports/steam_api_unversioned.cpp | 4 +- src/steam_api/steam_interface.cpp | 4 +- tools/CMakeLists.txt | 6 +-- tools/steamworks_downloader.cpp | 5 ++- tools/steamworks_parser.cpp | 36 +++++++--------- 11 files changed, 80 insertions(+), 61 deletions(-) create mode 100644 src/steam_api/exports/steam_api.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b1fef4..3b8eaba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(SMOKE_API_STATIC_SOURCES set(SMOKE_API_SOURCES ${SMOKE_API_STATIC_SOURCES} src/steam_api/exports/steam_api.cpp + src/steam_api/exports/steam_api.hpp src/steam_api/exports/steam_api_flat.cpp src/steam_api/exports/steam_api_internal.cpp src/steam_api/exports/steam_api_unversioned.cpp @@ -56,11 +57,6 @@ set(SMOKE_API_SOURCES add_library(SmokeAPI_interface INTERFACE) -# There is a weird MSVC bug where c++23 features are not enabled in x64 builds, -# while they are available in x86. I've no idea what causes this discrepancy, -# but manually setting the MSVC compiler option fixes this issue. -#target_compile_options(SmokeAPI_interface PUBLIC /std:c++latest) - target_include_directories(SmokeAPI_interface INTERFACE "$" ) @@ -71,17 +67,19 @@ target_link_libraries(SmokeAPI_interface INTERFACE KoalaBox $ #include #include +#include #include +#include #include -#include +#include #include "build_config.h" #include "smoke_api.hpp" #include "smoke_api/config.hpp" #include "smoke_api/steamclient/steamclient.hpp" +#include "steam_api/exports/steam_api.hpp" // Hooking steam_api has shown itself to be less desirable than steamclient // for the reasons outlined below: @@ -51,7 +54,7 @@ namespace { void init_proxy_mode() { LOG_INFO("Detected proxy mode"); - const auto self_path = kb::paths::get_self_path(); + const auto self_path = kb::paths::get_self_dir(); smoke_api::steamapi_module = kb::loader::load_original_library(self_path, STEAMAPI_DLL); } @@ -60,16 +63,26 @@ namespace { kb::hook::init(true); + const std::vector target_libraries{STEAMCLIENT_DLL, STEAMAPI_DLL}; kb::dll_monitor::init_listener( - STEAMCLIENT_DLL, - [](const HMODULE& steamclient_module) { - kb::hook::detour_or_warn( - steamclient_module, - "CreateInterface", - reinterpret_cast(CreateInterface) - ); + target_libraries, + [&](const HMODULE& module_handle, const std::string& library_name) { + static auto hook_count = 0U; - kb::dll_monitor::shutdown_listener(); + if(kb::str::eq(library_name, STEAMCLIENT_DLL)) { + KB_HOOK_DETOUR_MODULE(CreateInterface, module_handle); + + hook_count++; + } else if(kb::str::eq(library_name, STEAMAPI_DLL)) { + KB_HOOK_DETOUR_MODULE(SteamAPI_RestartAppIfNecessary, module_handle); + KB_HOOK_DETOUR_MODULE(SteamAPI_Shutdown, module_handle); + + hook_count++; + } + + if(hook_count == target_libraries.size()) { + kb::dll_monitor::shutdown_listener(); + } } ); } @@ -77,9 +90,9 @@ namespace { namespace smoke_api { HMODULE steamapi_module = nullptr; + bool hook_mode = false; void init(const HMODULE module_handle) { - // FIXME: IMPORTANT! Non ascii paths in directories will result in init errors try { kb::globals::init_globals(module_handle, PROJECT_NAME); @@ -93,14 +106,15 @@ namespace smoke_api { // compilation time stamp only when this file gets recompiled. LOG_INFO("{} v{} | Compiled at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__); - const fs::path exe_path = kb::win_util::get_module_file_name_or_throw(nullptr); - const auto exe_name = exe_path.filename().string(); + const auto exe_path = kb::win::get_module_path(nullptr); + const auto exe_name = kb::path::to_str(exe_path.filename()); LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::util::BITNESS); override_app_id(); if(kb::hook::is_hook_mode(module_handle, STEAMAPI_DLL)) { + hook_mode = true; init_hook_mode(); } else { init_proxy_mode(); @@ -115,7 +129,7 @@ namespace smoke_api { void shutdown() { try { if(steamapi_module != nullptr) { - kb::win_util::free_library(steamapi_module); + kb::win::free_library(steamapi_module); steamapi_module = nullptr; } diff --git a/src/smoke_api.hpp b/src/smoke_api.hpp index d8fe394..70666a7 100644 --- a/src/smoke_api.hpp +++ b/src/smoke_api.hpp @@ -20,9 +20,17 @@ constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; #define MODULE_CALL_CLOSURE(FUNC, ...) \ [&] { MODULE_CALL(FUNC, __VA_ARGS__); } +#define AUTO_CALL(FUNC, ...) \ + static const auto _##FUNC = smoke_api::hook_mode \ + ? KB_HOOK_GET_HOOKED_FN(FUNC) \ + : KB_HOOK_GET_MODULE_FN(smoke_api::steamapi_module, FUNC); \ + return _##FUNC(__VA_ARGS__) + namespace smoke_api { extern HMODULE steamapi_module; + extern bool hook_mode; + void init(HMODULE module_handle); void shutdown(); diff --git a/src/steam_api/exports/steam_api.cpp b/src/steam_api/exports/steam_api.cpp index 61aec23..9a5ae3e 100644 --- a/src/steam_api/exports/steam_api.cpp +++ b/src/steam_api/exports/steam_api.cpp @@ -1,23 +1,20 @@ #include +#include "steam_api/exports/steam_api.hpp" #include "smoke_api.hpp" #include "smoke_api/config.hpp" -// TODO: Support in hook mode -DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const uint32_t unOwnAppID) { +DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const AppId_t unOwnAppID) { if(smoke_api::config::instance.override_app_id != 0) { LOG_DEBUG("{} -> {}. Preventing app restart", unOwnAppID, __func__); return false; } - // Note: Assumes proxy mode only - MODULE_CALL(SteamAPI_RestartAppIfNecessary, unOwnAppID); + AUTO_CALL(SteamAPI_RestartAppIfNecessary, unOwnAppID); } -// TODO: Support in hook mode DLL_EXPORT(void) SteamAPI_Shutdown() { LOG_INFO("{} -> Game requested shutdown", __func__); - // Note: Assumes proxy mode only - MODULE_CALL(SteamAPI_Shutdown); + AUTO_CALL(SteamAPI_Shutdown); } diff --git a/src/steam_api/exports/steam_api.hpp b/src/steam_api/exports/steam_api.hpp new file mode 100644 index 0000000..9171fd9 --- /dev/null +++ b/src/steam_api/exports/steam_api.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "smoke_api.hpp" +#include "smoke_api/types.hpp" + +DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID); + +DLL_EXPORT(void) SteamAPI_Shutdown(); diff --git a/src/steam_api/exports/steam_api_unversioned.cpp b/src/steam_api/exports/steam_api_unversioned.cpp index d45456b..0f1926a 100644 --- a/src/steam_api/exports/steam_api_unversioned.cpp +++ b/src/steam_api/exports/steam_api_unversioned.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include "smoke_api.hpp" #include "steam_api/steam_client.hpp" @@ -23,7 +23,7 @@ namespace { if(not version_map.contains(version_prefix)) { try { - const std::string rdata = kb::win_util::get_pe_section_data_or_throw( + const std::string rdata = kb::win::get_pe_section_data_or_throw( smoke_api::steamapi_module, ".rdata" ); diff --git a/src/steam_api/steam_interface.cpp b/src/steam_api/steam_interface.cpp index aaf64ca..3ab85c5 100644 --- a/src/steam_api/steam_interface.cpp +++ b/src/steam_api/steam_interface.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "smoke_api.hpp" #include "virtuals/steam_api_virtuals.hpp" @@ -113,7 +113,7 @@ namespace steam_interface { namespace kb = koalabox; AppId_t get_app_id_or_throw() { - const auto app_id_str = kb::win_util::get_env_var("SteamAppId"); + const auto app_id_str = kb::win::get_env_var("SteamAppId"); return std::stoi(app_id_str); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 7143c08..f98c425 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -17,11 +17,7 @@ target_include_directories(BS_thread_pool INTERFACE ${BS_thread_pool_SOURCE_DIR} ### Steamworks Downloader executable add_executable(steamworks_downloader steamworks_downloader.cpp) -target_link_libraries(steamworks_downloader PRIVATE - KoalaBox - cpr # HTTP client - miniz # ZIP library TODO: Use koalabox instead -) +target_link_libraries(steamworks_downloader PRIVATE KoalaBox) ### Steamworks Parser executable diff --git a/tools/steamworks_downloader.cpp b/tools/steamworks_downloader.cpp index 0cc5449..42a9e08 100644 --- a/tools/steamworks_downloader.cpp +++ b/tools/steamworks_downloader.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -91,10 +92,12 @@ int wmain(const int argc, const wchar_t** argv) { // NOLINT(*-use-internal-linka const auto steamworks_dir = std::filesystem::current_path() / "steamworks"; + // Special case. If there is a directory with a bunch of SDKs downloaded, + // then we can just provide it as a single argument if(argc == 2) { if(const auto cdn_dir = kb::str::to_str(argv[1]); fs::is_directory(cdn_dir)) { for(const auto& entry : fs::directory_iterator(cdn_dir)) { - const auto filename = entry.path().filename().string(); + const auto filename = kb::path::to_str(entry.path().filename()); const std::regex re(R"(steamworks_sdk_(.+)\.zip)"); if(std::smatch match; std::regex_match(filename, match, re)) { diff --git a/tools/steamworks_parser.cpp b/tools/steamworks_parser.cpp index c16e1ec..a5168e3 100644 --- a/tools/steamworks_parser.cpp +++ b/tools/steamworks_parser.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include namespace { namespace fs = std::filesystem; @@ -123,8 +123,7 @@ namespace { static std::mutex section; if(not interface_version.empty() - ) - { + ) { const std::lock_guard lock(section); lookup[interface_version] = current_lookup; } @@ -150,13 +149,14 @@ namespace { BS::thread_pool<>& pool ) { const auto headers_dir = sdk_path / "headers\\steam"; + const auto headers_dir_str = kb::path::to_str(headers_dir); if(not fs::exists(headers_dir)) { - LOG_WARN("Warning: SDK missing 'headers' directory: {}", headers_dir.string()); + LOG_WARN("Warning: SDK missing 'headers/steam' directory: {}", headers_dir_str); return; } - LOG_INFO("Parsing SDK: {}", headers_dir.string()); + LOG_INFO("Parsing SDK: {}", headers_dir_str); // Go over each file in headers directory for(const auto& entry : fs::directory_iterator(headers_dir)) { @@ -164,7 +164,7 @@ namespace { const auto task = pool.submit_task( [&, header_path] { try { - LOG_DEBUG("Parsing header: {}", header_path.string()); + LOG_DEBUG("Parsing header: {}", kb::path::to_str(header_path)); const auto processed_header = manually_preprocess_header(header_path); parse_header(processed_header, lookup); @@ -193,21 +193,14 @@ namespace { // Go over each steamworks sdk version for(const auto& entry : fs::directory_iterator(steamworks_dir)) { - if(not - entry.is_directory() - ) - { + if(not entry.is_directory()) { continue; } - if(not - sdk_filter.empty() - and - not sdk_filter - . - contains(entry.path().filename().string()) - ) - { + if( + not sdk_filter.empty() and + not sdk_filter.contains(kb::path::to_str(entry.path().filename())) + ) { continue; } @@ -222,7 +215,10 @@ namespace { std::ofstream lookup_output(interface_lookup_path); lookup_output << std::setw(4) << lookup; - LOG_INFO("Interface lookup generated at: {}", fs::absolute(interface_lookup_path).string()); + LOG_INFO( + "Interface lookup generated at: {}", + kb::path::to_str(fs::absolute(interface_lookup_path)) + ); } } @@ -259,4 +255,4 @@ int wmain(const int argc, const wchar_t* argv[]) { // NOLINT(*-use-internal-link LOG_CRITICAL("Error: {}", e.what()); return 1; } -} \ No newline at end of file +}