diff --git a/.clang-tidy b/.clang-tidy index ee63016..a72f9af 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -69,4 +69,5 @@ misc-*, -readability-named-parameter, -readability-function-cognitive-complexity, -*-include-cleaner, --*-lambda-function-name' \ No newline at end of file +-*-lambda-function-name, +-*-err58-cpp' \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcadb2c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text eol=lf diff --git a/.gitignore b/.gitignore index 42afabf..796b96d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/build \ No newline at end of file +/build diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b8eaba..124024e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(SMOKE_API_SOURCES src/steam_api/exports/steam_api_unversioned.cpp src/steam_api/virtuals/isteamapps.cpp src/steam_api/virtuals/isteamclient.cpp + src/steam_api/virtuals/isteamgameserver.cpp src/steam_api/virtuals/isteaminventory.cpp src/steam_api/virtuals/isteamuser.cpp src/steam_api/virtuals/steam_api_virtuals.hpp @@ -82,6 +83,7 @@ target_include_directories(SmokeAPI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_BINARY_DIR}") +## https://github.com/batterycenter/embed CPMAddPackage( URI "gh:batterycenter/embed@1.2.19" OPTIONS "B_PRODUCTION_MODE ON" diff --git a/KoalaBox b/KoalaBox index 76510ed..ece1caf 160000 --- a/KoalaBox +++ b/KoalaBox @@ -1 +1 @@ -Subproject commit 76510ed1c7fef42dcc8f048ba0cf1b65b1a0315b +Subproject commit ece1cafc758d26656af11390f34c7b257686518d diff --git a/README.adoc b/README.adoc index 6cf2723..d7bd513 100644 --- a/README.adoc +++ b/README.adoc @@ -73,21 +73,21 @@ SmokeAPI supports 2 installation modes: hook mode and proxy mode. |=== - Try installing the unlocker in hook mode first. If it doesn't work, try installing it in proxy mode. -==== 🪝 Hook mode +=== 🪝 Hook mode . Download the latest SmokeAPI release zip from {smokeapi_release}. . From SmokeAPI archive unpack `steam_api.dll` or `steam_api64.dll`, depending on the game bitness, rename it to `version.dll`, and place it next to the game exe file. -==== 🪝 Hook mode (Alternative) +=== 🪝 Hook mode (Alternative) -If a game doesn't load `version.dll`, you can use one of the {koaloader} DLLs that the game does in fact load. For example, assuming that the game loads `d3d9.dll`: +If a game doesn't load `version.dll`, you can use one of the {koaloader} DLLs that the game does in fact load. +For example, assuming that the game loads `winmm.dll`: . Download the latest Koaloader release zip from https://github.com/acidicoala/Koaloader/releases/latest[Koaloader Releases]. -. From Koaloader archive unpack `d3d9.dll` from `d3d9-32` or `d3d9-64`, depending on the game bitness, and place it next to the game exe file. +. From Koaloader archive unpack `winmm.dll` from `winmm-32` or `winmm-64`, depending on the game bitness, and place it next to the game exe file. . Download the latest SmokeAPI release zip from {smokeapi_release}. . From SmokeAPI archive unpack `steam_api.dll` or `steam_api64.dll`, depending on the game bitness, rename it to `SmokeAPI.dll`, and place it next to the game exe file. @@ -265,9 +265,15 @@ For example: .\build.ps1 64 Release ---- +== 🐞 Known issues + +* Crashes on startup in Project Winter in hook mode (proxy mode works fine). + == 📚 Open-Source libraries -TODO +* https://github.com/batterycenter/embed[batterycenter/embed] +* https://github.com/bshoshany/thread-pool[bshoshany/thread-pool] +* + https://github.com/acidicoala/Koalabox?tab=readme-ov-file#-open-source-libraries[libraries used by KoalaBox] == 📄 License diff --git a/res/SmokeAPI.config.json b/res/SmokeAPI.config.json index 621f546..f0c374e 100644 --- a/res/SmokeAPI.config.json +++ b/res/SmokeAPI.config.json @@ -3,7 +3,6 @@ "$version": 3, "logging": true, "default_app_status": "unlocked", - "override_app_id": 0, "override_app_status": {}, "override_dlc_status": {}, "auto_inject_inventory": true, diff --git a/res/SmokeAPI.schema.json b/res/SmokeAPI.schema.json index a9386ec..ac3367f 100644 --- a/res/SmokeAPI.schema.json +++ b/res/SmokeAPI.schema.json @@ -5,6 +5,10 @@ "type": "object", "additionalProperties": false, "properties": { + "$schema": { + "type": "string", + "description": "The URI of the JSON Schema used to validate this config." + }, "$version": { "type": "integer", "minimum": 0, @@ -21,12 +25,6 @@ "default": "unlocked", "$ref": "#/$defs/AppStatus" }, - "override_app_id": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "Overrides the current app ID (0 means no override)." - }, "override_app_status": { "type": "object", "default": {}, @@ -113,6 +111,7 @@ }, "examples": [ { + "$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/heads/master/res/SmokeAPI.schema.json", "$version": 3, "logging": true, "default_app_status": "unlocked", diff --git a/res/steamworks/132/headers/steam/isteamclient.h b/res/steamworks/132/headers/steam/isteamclient.h index 796d72d..84d4195 100644 --- a/res/steamworks/132/headers/steam/isteamclient.h +++ b/res/steamworks/132/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/133b/headers/steam/isteamclient.h b/res/steamworks/133b/headers/steam/isteamclient.h index 796d72d..84d4195 100644 --- a/res/steamworks/133b/headers/steam/isteamclient.h +++ b/res/steamworks/133b/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/134/headers/steam/isteamclient.h b/res/steamworks/134/headers/steam/isteamclient.h index 796d72d..84d4195 100644 --- a/res/steamworks/134/headers/steam/isteamclient.h +++ b/res/steamworks/134/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/135/headers/steam/isteamclient.h b/res/steamworks/135/headers/steam/isteamclient.h index 796d72d..84d4195 100644 --- a/res/steamworks/135/headers/steam/isteamclient.h +++ b/res/steamworks/135/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/135a/headers/steam/isteamclient.h b/res/steamworks/135a/headers/steam/isteamclient.h index 796d72d..84d4195 100644 --- a/res/steamworks/135a/headers/steam/isteamclient.h +++ b/res/steamworks/135a/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/136/headers/steam/isteamclient.h b/res/steamworks/136/headers/steam/isteamclient.h index 6dc72fe..c361f8c 100644 --- a/res/steamworks/136/headers/steam/isteamclient.h +++ b/res/steamworks/136/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/137/headers/steam/isteamclient.h b/res/steamworks/137/headers/steam/isteamclient.h index 45d707d..632b373 100644 --- a/res/steamworks/137/headers/steam/isteamclient.h +++ b/res/steamworks/137/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/138a/headers/steam/isteamclient.h b/res/steamworks/138a/headers/steam/isteamclient.h index 45d707d..632b373 100644 --- a/res/steamworks/138a/headers/steam/isteamclient.h +++ b/res/steamworks/138a/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/139/headers/steam/isteamclient.h b/res/steamworks/139/headers/steam/isteamclient.h index f007c63..a446a5d 100644 --- a/res/steamworks/139/headers/steam/isteamclient.h +++ b/res/steamworks/139/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/140/headers/steam/isteamclient.h b/res/steamworks/140/headers/steam/isteamclient.h index f007c63..a446a5d 100644 --- a/res/steamworks/140/headers/steam/isteamclient.h +++ b/res/steamworks/140/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/141/headers/steam/isteamclient.h b/res/steamworks/141/headers/steam/isteamclient.h index 0ac7a67..176b607 100644 --- a/res/steamworks/141/headers/steam/isteamclient.h +++ b/res/steamworks/141/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/142/headers/steam/isteamclient.h b/res/steamworks/142/headers/steam/isteamclient.h index af8828d..5b0286a 100644 --- a/res/steamworks/142/headers/steam/isteamclient.h +++ b/res/steamworks/142/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. diff --git a/res/steamworks/143/headers/steam/isteamclient.h b/res/steamworks/143/headers/steam/isteamclient.h index 72115b9..c3185b5 100644 --- a/res/steamworks/143/headers/steam/isteamclient.h +++ b/res/steamworks/143/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/144/headers/steam/isteamclient.h b/res/steamworks/144/headers/steam/isteamclient.h index 72115b9..c3185b5 100644 --- a/res/steamworks/144/headers/steam/isteamclient.h +++ b/res/steamworks/144/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/145/headers/steam/isteamclient.h b/res/steamworks/145/headers/steam/isteamclient.h index 72115b9..c3185b5 100644 --- a/res/steamworks/145/headers/steam/isteamclient.h +++ b/res/steamworks/145/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/146/headers/steam/isteamclient.h b/res/steamworks/146/headers/steam/isteamclient.h index d37961d..aca9934 100644 --- a/res/steamworks/146/headers/steam/isteamclient.h +++ b/res/steamworks/146/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/147/headers/steam/isteamclient.h b/res/steamworks/147/headers/steam/isteamclient.h index fe7a1e7..eeb77bc 100644 --- a/res/steamworks/147/headers/steam/isteamclient.h +++ b/res/steamworks/147/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/148a/headers/steam/isteamclient.h b/res/steamworks/148a/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/148a/headers/steam/isteamclient.h +++ b/res/steamworks/148a/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/149/headers/steam/isteamclient.h b/res/steamworks/149/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/149/headers/steam/isteamclient.h +++ b/res/steamworks/149/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/150/headers/steam/isteamclient.h b/res/steamworks/150/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/150/headers/steam/isteamclient.h +++ b/res/steamworks/150/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/151/headers/steam/isteamclient.h b/res/steamworks/151/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/151/headers/steam/isteamclient.h +++ b/res/steamworks/151/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/152/headers/steam/isteamclient.h b/res/steamworks/152/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/152/headers/steam/isteamclient.h +++ b/res/steamworks/152/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/153a/headers/steam/isteamclient.h b/res/steamworks/153a/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/153a/headers/steam/isteamclient.h +++ b/res/steamworks/153a/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/154/headers/steam/isteamclient.h b/res/steamworks/154/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/154/headers/steam/isteamclient.h +++ b/res/steamworks/154/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/155/headers/steam/isteamclient.h b/res/steamworks/155/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/155/headers/steam/isteamclient.h +++ b/res/steamworks/155/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/156/headers/steam/isteamclient.h b/res/steamworks/156/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/156/headers/steam/isteamclient.h +++ b/res/steamworks/156/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/157/headers/steam/isteamclient.h b/res/steamworks/157/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/157/headers/steam/isteamclient.h +++ b/res/steamworks/157/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/158a/headers/steam/isteamclient.h b/res/steamworks/158a/headers/steam/isteamclient.h index 8cd4589..3278780 100644 --- a/res/steamworks/158a/headers/steam/isteamclient.h +++ b/res/steamworks/158a/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/159/headers/steam/isteamclient.h b/res/steamworks/159/headers/steam/isteamclient.h index e457e87..ce9946c 100644 --- a/res/steamworks/159/headers/steam/isteamclient.h +++ b/res/steamworks/159/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/160/headers/steam/isteamclient.h b/res/steamworks/160/headers/steam/isteamclient.h index e457e87..ce9946c 100644 --- a/res/steamworks/160/headers/steam/isteamclient.h +++ b/res/steamworks/160/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/161/headers/steam/isteamclient.h b/res/steamworks/161/headers/steam/isteamclient.h index e457e87..ce9946c 100644 --- a/res/steamworks/161/headers/steam/isteamclient.h +++ b/res/steamworks/161/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/res/steamworks/162/headers/steam/isteamclient.h b/res/steamworks/162/headers/steam/isteamclient.h index e457e87..ce9946c 100644 --- a/res/steamworks/162/headers/steam/isteamclient.h +++ b/res/steamworks/162/headers/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright Valve Corporation, All rights reserved. ==================== +//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal low-level access to Steamworks interfaces. // diff --git a/src/smoke_api.cpp b/src/smoke_api.cpp index d4910cf..c8a4873 100644 --- a/src/smoke_api.cpp +++ b/src/smoke_api.cpp @@ -37,19 +37,6 @@ namespace { namespace kb = koalabox; - namespace fs = std::filesystem; - - void override_app_id() { - const auto override_app_id = smoke_api::config::instance.override_app_id; - if(override_app_id == 0) { - return; - } - - spdlog::default_logger_raw(); - LOG_DEBUG("Overriding app id to {}", override_app_id); - - SetEnvironmentVariable(TEXT("SteamAppId"), std::to_wstring(override_app_id).c_str()); - } void init_proxy_mode() { LOG_INFO("Detected proxy mode"); @@ -61,27 +48,14 @@ namespace { void init_hook_mode() { LOG_INFO("Detected hook mode"); - kb::hook::init(true); - - const std::vector target_libraries{STEAMCLIENT_DLL, STEAMAPI_DLL}; kb::dll_monitor::init_listener( - target_libraries, + {STEAMCLIENT_DLL, STEAMAPI_DLL}, [&](const HMODULE& module_handle, const std::string& library_name) { - static auto hook_count = 0U; - 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(); } } ); @@ -111,7 +85,8 @@ namespace smoke_api { LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::util::BITNESS); - override_app_id(); + // We need to hook functions in either mode + kb::hook::init(true); if(kb::hook::is_hook_mode(module_handle, STEAMAPI_DLL)) { hook_mode = true; diff --git a/src/smoke_api.hpp b/src/smoke_api.hpp index 70666a7..d80a1b8 100644 --- a/src/smoke_api.hpp +++ b/src/smoke_api.hpp @@ -6,6 +6,7 @@ constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; constexpr auto STEAM_CLIENT = "SteamClient"; constexpr auto STEAM_USER = "SteamUser"; constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; +constexpr auto STEAM_GAME_SERVER = "SteamGameServer"; // IMPORTANT: DLL_EXPORT is hardcoded in exports_generator.cpp, // so any name changes here must be reflected there as well. diff --git a/src/steam_api/exports/steam_api.cpp b/src/steam_api/exports/steam_api.cpp index 9a5ae3e..c4d9edf 100644 --- a/src/steam_api/exports/steam_api.cpp +++ b/src/steam_api/exports/steam_api.cpp @@ -5,10 +5,9 @@ #include "smoke_api/config.hpp" 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; - } + LOG_INFO("{} -> unOwnAppID: {}", __func__, unOwnAppID); + + // Restart can be suppressed if needed AUTO_CALL(SteamAPI_RestartAppIfNecessary, unOwnAppID); } diff --git a/src/steam_api/exports/steam_api_flat.cpp b/src/steam_api/exports/steam_api_flat.cpp index 52969e2..541ebc3 100644 --- a/src/steam_api/exports/steam_api_flat.cpp +++ b/src/steam_api/exports/steam_api_flat.cpp @@ -9,7 +9,7 @@ // ISteamApps -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) { +DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, const AppId_t dlcID) { try { return smoke_api::steam_apps::IsDlcUnlocked( __func__, @@ -23,7 +23,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) } } -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, AppId_t dlcID) { +DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, const AppId_t dlcID) { try { return smoke_api::steam_apps::IsDlcUnlocked( __func__, @@ -294,3 +294,28 @@ DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp return k_EUserHasLicenseResultDoesNotHaveLicense; } } + +// ISteamGameServer + +DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamGameServer_UserHasLicenseForApp( + void* self, + const CSteamID steamID, + const AppId_t dlcID +) { + try { + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + steam_interface::get_app_id(), + dlcID, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamGameServer_UserHasLicenseForApp, + self, + steamID, + dlcID + ) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return k_EUserHasLicenseResultDoesNotHaveLicense; + } +} diff --git a/src/steam_api/exports/steam_api_unversioned.cpp b/src/steam_api/exports/steam_api_unversioned.cpp index 0f1926a..f83e248 100644 --- a/src/steam_api/exports/steam_api_unversioned.cpp +++ b/src/steam_api/exports/steam_api_unversioned.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include "smoke_api.hpp" @@ -34,7 +33,7 @@ namespace { return version_map[version_prefix]; } - throw kb::util::exception("No match found for '{}'", version_prefix); + throw std::runtime_error(std::format("No match found for '{}'", version_prefix)); } catch(const std::exception& ex) { LOG_ERROR( "Failed to get versioned interface: {}." diff --git a/src/steam_api/steam_interface.cpp b/src/steam_api/steam_interface.cpp index 3ab85c5..17d425e 100644 --- a/src/steam_api/steam_interface.cpp +++ b/src/steam_api/steam_interface.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include "smoke_api.hpp" @@ -67,17 +66,11 @@ namespace { } }, { - STEAM_INVENTORY, + STEAM_GAME_SERVER, interface_data{ - .fallback_version = "STEAMINVENTORY_INTERFACE_V003", + .fallback_version = "SteamGameServer015", .entry_map = { - ENTRY(ISteamInventory, GetResultStatus), - ENTRY(ISteamInventory, GetResultItems), - ENTRY(ISteamInventory, CheckResultSteamID), - ENTRY(ISteamInventory, GetAllItems), - ENTRY(ISteamInventory, GetItemsByID), - ENTRY(ISteamInventory, SerializeResult), - ENTRY(ISteamInventory, GetItemDefinitionIDs), + ENTRY(ISteamGameServer, UserHasLicenseForApp), } } }, diff --git a/src/steam_api/virtuals/isteamapps.cpp b/src/steam_api/virtuals/isteamapps.cpp index 4d78f79..e9905bc 100644 --- a/src/steam_api/virtuals/isteamapps.cpp +++ b/src/steam_api/virtuals/isteamapps.cpp @@ -1,6 +1,5 @@ #include -#include "smoke_api.hpp" #include "smoke_api/interfaces/steam_apps.hpp" #include "steam_api/steam_interface.hpp" #include "steam_api/virtuals/steam_api_virtuals.hpp" diff --git a/src/steam_api/virtuals/isteamclient.cpp b/src/steam_api/virtuals/isteamclient.cpp index dfdf51a..4bc6aff 100644 --- a/src/steam_api/virtuals/isteamclient.cpp +++ b/src/steam_api/virtuals/isteamclient.cpp @@ -1,6 +1,5 @@ #include -#include "smoke_api.hpp" #include "steam_api/steam_client.hpp" #include "steam_api/virtuals/steam_api_virtuals.hpp" diff --git a/src/steam_api/virtuals/isteamgameserver.cpp b/src/steam_api/virtuals/isteamgameserver.cpp new file mode 100644 index 0000000..32af7a8 --- /dev/null +++ b/src/steam_api/virtuals/isteamgameserver.cpp @@ -0,0 +1,21 @@ +#include + +#include "smoke_api/interfaces/steam_user.hpp" +#include "steam_api/steam_interface.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(EUserHasLicenseForAppResult) ISteamGameServer_UserHasLicenseForApp( + PARAMS(const CSteamID steamID, const AppId_t dlc_id) +) { + try { + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamGameServer_UserHasLicenseForApp, ARGS(steamID, dlc_id)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return k_EUserHasLicenseResultDoesNotHaveLicense; + } +} diff --git a/src/steam_api/virtuals/isteaminventory.cpp b/src/steam_api/virtuals/isteaminventory.cpp index 806e646..d1c32b2 100644 --- a/src/steam_api/virtuals/isteaminventory.cpp +++ b/src/steam_api/virtuals/isteaminventory.cpp @@ -1,4 +1,3 @@ -#include "smoke_api.hpp" #include "smoke_api/interfaces/steam_inventory.hpp" #include "steam_api/virtuals/steam_api_virtuals.hpp" @@ -130,7 +129,7 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( } VIRTUAL(bool) ISteamInventory_CheckResultSteamID( - PARAMS(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) + PARAMS(const SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) ) { return smoke_api::steam_inventory::CheckResultSteamID( __func__, diff --git a/src/steam_api/virtuals/isteamuser.cpp b/src/steam_api/virtuals/isteamuser.cpp index 1b68b83..a15412d 100644 --- a/src/steam_api/virtuals/isteamuser.cpp +++ b/src/steam_api/virtuals/isteamuser.cpp @@ -1,6 +1,5 @@ #include -#include "smoke_api.hpp" #include "smoke_api/interfaces/steam_user.hpp" #include "steam_api/steam_interface.hpp" #include "steam_api/virtuals/steam_api_virtuals.hpp" diff --git a/src/steam_api/virtuals/steam_api_virtuals.hpp b/src/steam_api/virtuals/steam_api_virtuals.hpp index 264b431..8a2338f 100644 --- a/src/steam_api/virtuals/steam_api_virtuals.hpp +++ b/src/steam_api/virtuals/steam_api_virtuals.hpp @@ -33,3 +33,8 @@ VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, // ISteamUser VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t)); + +// ISteamGameServer +VIRTUAL(EUserHasLicenseForAppResult) ISteamGameServer_UserHasLicenseForApp( + PARAMS(CSteamID, AppId_t) +); diff --git a/static/smoke_api/api.cpp b/static/smoke_api/api.cpp index 411996b..d7bca64 100644 --- a/static/smoke_api/api.cpp +++ b/static/smoke_api/api.cpp @@ -32,7 +32,7 @@ namespace smoke_api::api { std::optional> fetch_dlcs_from_steam(const AppId_t app_id) { try { - // TODO: Communicate directly with Steam servers. + // TODO: Communicate directly with Steam servers? // ref.: https://github.com/SteamRE/SteamKit const auto url = std::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id); diff --git a/static/smoke_api/cache.cpp b/static/smoke_api/cache.cpp index d565ea7..2b8d138 100644 --- a/static/smoke_api/cache.cpp +++ b/static/smoke_api/cache.cpp @@ -32,6 +32,9 @@ namespace smoke_api::cache { } bool save_dlcs(AppId_t app_id, const std::vector& dlcs) noexcept { + static std::mutex section; + const std::lock_guard lock(section); + try { LOG_DEBUG("Caching DLC IDs for the app: {}", app_id); diff --git a/static/smoke_api/config.cpp b/static/smoke_api/config.cpp index a7d8b10..75b16f7 100644 --- a/static/smoke_api/config.cpp +++ b/static/smoke_api/config.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "smoke_api/config.hpp" @@ -40,6 +39,7 @@ namespace smoke_api::config { break; case AppStatus::ORIGINAL: case AppStatus::UNDEFINED: + default: is_unlocked = original_function(); break; } diff --git a/static/smoke_api/config.hpp b/static/smoke_api/config.hpp index 5a357ca..c73bfb6 100644 --- a/static/smoke_api/config.hpp +++ b/static/smoke_api/config.hpp @@ -14,10 +14,10 @@ namespace smoke_api::config { AppStatus, // @formatter:off { - {AppStatus::UNDEFINED, nullptr}, - {AppStatus::ORIGINAL, "original"}, - {AppStatus::UNLOCKED, "unlocked"}, - {AppStatus::LOCKED, "locked"}, + { AppStatus::UNDEFINED, nullptr }, + { AppStatus::ORIGINAL, "original" }, + { AppStatus::UNLOCKED, "unlocked" }, + { AppStatus::LOCKED, "locked" }, } // @formatter:on ) @@ -26,7 +26,6 @@ namespace smoke_api::config { uint32_t $version = 3; bool logging = false; AppStatus default_app_status = AppStatus::UNLOCKED; - uint32_t override_app_id = 0; std::map override_app_status; std::map override_dlc_status; AppDlcNameMap extra_dlcs; @@ -35,11 +34,9 @@ namespace smoke_api::config { NLOHMANN_DEFINE_TYPE_INTRUSIVE( Config, - // NOLINT(misc-const-correctness) $version, logging, default_app_status, - override_app_id, override_app_status, override_dlc_status, extra_dlcs, diff --git a/static/smoke_api/interfaces/steam_apps.cpp b/static/smoke_api/interfaces/steam_apps.cpp index 9cc1f17..9fedfc3 100644 --- a/static/smoke_api/interfaces/steam_apps.cpp +++ b/static/smoke_api/interfaces/steam_apps.cpp @@ -1,7 +1,6 @@ #include #include -#include #include "smoke_api/interfaces/steam_apps.hpp" #include "smoke_api/api.hpp" @@ -88,7 +87,7 @@ namespace smoke_api::steam_apps { const std::function& original_function ) { try { - const auto unlocked = smoke_api::config::is_dlc_unlocked( + const auto unlocked = config::is_dlc_unlocked( app_id, dlc_id, original_function @@ -172,10 +171,10 @@ namespace smoke_api::steam_apps { ); }; - const auto inject_dlc = [&](const DLC& dlc) { + const auto output_dlc = [&](const DLC& dlc) { // Fill the output pointers *pDlcId = dlc.get_id(); - *pbAvailable = smoke_api::config::is_dlc_unlocked( + *pbAvailable = config::is_dlc_unlocked( app_id, *pDlcId, [&] { @@ -192,7 +191,7 @@ namespace smoke_api::steam_apps { const auto& dlcs = app_dlcs[app_id]; if(iDLC >= 0 && iDLC < dlcs.size()) { - inject_dlc(dlcs[iDLC]); + output_dlc(dlcs[iDLC]); print_dlc_info("injected"); return true; } @@ -204,7 +203,7 @@ namespace smoke_api::steam_apps { const auto success = original_function(); if(success) { - *pbAvailable = smoke_api::config::is_dlc_unlocked( + *pbAvailable = config::is_dlc_unlocked( app_id, *pDlcId, [&] { diff --git a/static/smoke_api/interfaces/steam_inventory.cpp b/static/smoke_api/interfaces/steam_inventory.cpp index 320beda..1e121a5 100644 --- a/static/smoke_api/interfaces/steam_inventory.cpp +++ b/static/smoke_api/interfaces/steam_inventory.cpp @@ -59,7 +59,7 @@ namespace smoke_api::steam_inventory { "{} -> handle: {}, pOutItemsArray: {}, arraySize: {}", function_name, resultHandle, - fmt::ptr(pOutItemsArray), + reinterpret_cast(pOutItemsArray), *punOutItemsArraySize ); @@ -140,26 +140,32 @@ namespace smoke_api::steam_inventory { const uint32_t* punValueBufferSizeOut, const std::function& original_function ) { - const auto common_info = fmt::format( + LOG_DEBUG( "{} -> Handle: {}, Index: {}, Name: '{}'", function_name, resultHandle, unItemIndex, - pchPropertyName + // can be empty, in which case steam responds with property list in csv format + pchPropertyName ? pchPropertyName : "nullptr" ); const auto success = original_function(); if(!success) { - LOG_WARN("{}, Result is false", common_info); + LOG_WARN("{} -> Result is false", function_name); return false; } - LOG_DEBUG( - "{}, Buffer: '{}'", - common_info, - std::string(pchValueBuffer, *punValueBufferSizeOut - 1) - ); + if( + pchValueBuffer && *pchValueBuffer && + punValueBufferSizeOut && *punValueBufferSizeOut > 0 + ) { + LOG_DEBUG( + R"({} -> Buffer: "{}")", + function_name, + std::string(pchValueBuffer, *punValueBufferSizeOut - 1) + ); + } return success; } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index f98c425..1f9f34d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -4,6 +4,7 @@ project(smoke-api-tools LANGUAGES CXX) ### Thread pool library +## https://github.com/bshoshany/thread-pool CPMAddPackage( NAME BS_thread_pool GITHUB_REPOSITORY bshoshany/thread-pool