mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2025-12-05 21:15:39 -05:00
Refactored for latest Koalabox
This commit is contained in:
4
.idea/cmake.xml
generated
4
.idea/cmake.xml
generated
@@ -2,8 +2,8 @@
|
||||
<project version="4">
|
||||
<component name="CMakeSharedSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug [32] (Template: copy and set the 32-bit toolchain)" ENABLED="false" GENERATION_DIR="build/32/debug" CONFIG_NAME="Debug" GENERATION_OPTIONS="-G "Visual Studio 17 2022" -A Win32" />
|
||||
<configuration PROFILE_NAME="Debug [64] (Template: copy and set the 64-bit toolchain)" ENABLED="false" GENERATION_DIR="build/64/debug" CONFIG_NAME="Debug" GENERATION_OPTIONS="-G "Visual Studio 17 2022" -A x64" />
|
||||
<configuration PROFILE_NAME="Debug [32] (Template: copy and set the 32-bit toolchain)" ENABLED="false" GENERATION_DIR="build/32" CONFIG_NAME="Debug" GENERATION_OPTIONS="-G "Visual Studio 17 2022" -A Win32" />
|
||||
<configuration PROFILE_NAME="Debug [64] (Template: copy and set the 64-bit toolchain)" ENABLED="false" GENERATION_DIR="build/64" CONFIG_NAME="Debug" GENERATION_OPTIONS="-G "Visual Studio 17 2022" -A x64" />
|
||||
</configurations>
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/codeStyles/Project.xml
generated
1
.idea/codeStyles/Project.xml
generated
@@ -9,6 +9,7 @@
|
||||
</Markdown>
|
||||
<Objective-C>
|
||||
<option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" />
|
||||
<option name="FUNCTION_CALL_ARGUMENTS_ALIGN_MULTILINE" value="false" />
|
||||
<option name="FUNCTION_CALL_ARGUMENTS_NEW_LINE_AFTER_LPAR" value="true" />
|
||||
<option name="FUNCTION_CALL_ARGUMENTS_NEW_LINE_BEFORE_RPAR" value="true" />
|
||||
<option name="SPACE_BEFORE_POINTER_IN_DECLARATION" value="false" />
|
||||
|
||||
@@ -44,6 +44,7 @@ set(
|
||||
src/core/macros.hpp
|
||||
src/core/paths.cpp
|
||||
src/core/paths.hpp
|
||||
src/core/steam_types.hpp
|
||||
src/smoke_api/smoke_api.cpp
|
||||
src/smoke_api/smoke_api.hpp
|
||||
src/steam_api_exports/steam_api_flat.cpp
|
||||
@@ -63,7 +64,6 @@ set(
|
||||
src/steam_impl/steam_user.hpp
|
||||
src/steam_functions/steam_functions.cpp
|
||||
src/steam_functions/steam_functions.hpp
|
||||
src/steam_types/steam_types.hpp
|
||||
src/steamclient_exports/steamclient.cpp
|
||||
src/main.cpp
|
||||
${GENERATED_LINKER_EXPORTS}
|
||||
@@ -76,7 +76,9 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
src/koalageddon/koalageddon.hpp
|
||||
src/koalageddon/koalageddon.cpp
|
||||
src/koalageddon/vstdlib.cpp
|
||||
src/koalageddon/vstdlib.hpp
|
||||
src/koalageddon/steamclient.cpp
|
||||
src/koalageddon/steamclient.hpp
|
||||
src/steamclient_virtuals/client_app_manager.cpp
|
||||
src/steamclient_virtuals/client_apps.cpp
|
||||
src/steamclient_virtuals/client_inventory.cpp
|
||||
|
||||
2
KoalaBox
2
KoalaBox
Submodule KoalaBox updated: a258e92cce...15d5cfc2e5
@@ -1,11 +1,14 @@
|
||||
#include <core/cache.hpp>
|
||||
#include <core/paths.hpp>
|
||||
#include <koalabox/io.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
namespace cache {
|
||||
|
||||
|
||||
Cache read_cache_from_disk() {
|
||||
try {
|
||||
const auto cache_string = io::read_file(paths::get_cache_path());
|
||||
const auto cache_string = koalabox::io::read_file(paths::get_cache_path());
|
||||
|
||||
if (cache_string.empty()) {
|
||||
return {};
|
||||
@@ -13,7 +16,7 @@ namespace cache {
|
||||
|
||||
return nlohmann::json::parse(cache_string).get<Cache>();
|
||||
} catch (const Exception& e) {
|
||||
logger->warn("{} -> Failed to read cache from disk: {}", __func__, e.what());
|
||||
LOG_WARN("{} -> Failed to read cache from disk: {}", __func__, e.what())
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -23,9 +26,9 @@ namespace cache {
|
||||
try {
|
||||
const auto cache_string = nlohmann::json(cache).dump(2);
|
||||
|
||||
io::write_file(paths::get_cache_path(), cache_string);
|
||||
koalabox::io::write_file(paths::get_cache_path(), cache_string);
|
||||
} catch (const Exception& e) {
|
||||
logger->error("{} -> Failed to write cache to disk: {}", __func__, e.what());
|
||||
LOG_ERROR("{} -> Failed to write cache to disk: {}", __func__, e.what())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +55,7 @@ namespace cache {
|
||||
}
|
||||
|
||||
void save_dlc_ids(AppId_t app_id, const Vector<AppId_t>& dlc_ids) {
|
||||
logger->debug("{} -> Caching DLC IDs for the app: {}", __func__, app_id);
|
||||
LOG_DEBUG("{} -> Caching DLC IDs for the app: {}", __func__, app_id)
|
||||
|
||||
auto cache = read_cache_from_disk();
|
||||
|
||||
@@ -68,7 +71,7 @@ namespace cache {
|
||||
}
|
||||
|
||||
void save_koalageddon_config(const koalageddon::KoalageddonConfig& config) {
|
||||
logger->debug("{} -> Caching koalageddon config", __func__);
|
||||
LOG_DEBUG("{} -> Caching koalageddon config", __func__)
|
||||
|
||||
auto cache = read_cache_from_disk();
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <steam_types/steam_types.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
|
||||
/**
|
||||
* This namespace contains utility functions for reading from and writing to cache file on disk.
|
||||
* All functions are intended to be safe to call, i.e. they should not throw exceptions.
|
||||
*/
|
||||
namespace cache {
|
||||
using namespace koalabox;
|
||||
|
||||
struct App {
|
||||
Vector<AppId_t> dlc_ids;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace config {
|
||||
|
||||
// TODO: Reloading via export
|
||||
void init() {
|
||||
instance = config_parser::parse<Config>(paths::get_config_path());
|
||||
instance = koalabox::config_parser::parse<Config>(paths::get_config_path());
|
||||
}
|
||||
|
||||
AppStatus get_app_status(uint32_t app_id) {
|
||||
@@ -36,7 +36,7 @@ namespace config {
|
||||
return instance.default_dlc_status;
|
||||
}
|
||||
|
||||
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const std::function<bool()>& original_function) {
|
||||
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const Function<bool()>& original_function) {
|
||||
const auto app_status = config::get_app_status(app_id);
|
||||
const auto dlc_status = config::get_dlc_status(dlc_id);
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace config {
|
||||
using namespace koalabox;
|
||||
|
||||
enum class AppStatus {
|
||||
LOCKED,
|
||||
UNLOCKED,
|
||||
@@ -67,5 +64,5 @@ namespace config {
|
||||
|
||||
AppStatus get_app_status(uint32_t app_id);
|
||||
DlcStatus get_dlc_status(uint32_t dlc_id);
|
||||
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const std::function<bool()>& original_function);
|
||||
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const Function<bool()>& original_function);
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace globals {
|
||||
HMODULE steamapi_module = nullptr;
|
||||
HMODULE vstdlib_module = nullptr;
|
||||
HMODULE steamclient_module = nullptr;
|
||||
Map<String, FunctionAddress> address_map;
|
||||
Map<String, uintptr_t> address_map; // NOLINT(cert-err58-cpp)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace globals {
|
||||
using namespace koalabox;
|
||||
|
||||
extern HMODULE smokeapi_handle;
|
||||
extern HMODULE steamclient_module;
|
||||
extern HMODULE steamapi_module;
|
||||
extern HMODULE vstdlib_module;
|
||||
extern Map<String, FunctionAddress> address_map;
|
||||
extern Map<String, uintptr_t> address_map;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,39 @@
|
||||
#include <core/globals.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
|
||||
/**
|
||||
* By default, virtual functions are declared with __thiscall
|
||||
* convention, which is normal since they are class members.
|
||||
* But it presents an issue for us, since we cannot pass *this
|
||||
* pointer as a function argument. This is because *this
|
||||
* pointer is passed via register ECX in __thiscall
|
||||
* convention. Hence, to resolve this issue we declare our
|
||||
* hooked functions with __fastcall convention, to trick
|
||||
* the compiler into reading ECX & EDX registers as 1st
|
||||
* and 2nd function arguments respectively. Similarly, __fastcall
|
||||
* makes the compiler push the first argument into the ECX register,
|
||||
* which mimics the __thiscall calling convention. Register EDX
|
||||
* is not used anywhere in this case, but we still pass it along
|
||||
* to conform to the __fastcall convention. This all applies
|
||||
* to the x86 architecture.
|
||||
*
|
||||
* In x86-64 however, there is only one calling convention,
|
||||
* so __fastcall is simply ignored. However, RDX in this case
|
||||
* will store the 1st actual argument to the function, so we
|
||||
* have to omit it from the function signature.
|
||||
*
|
||||
* The macros below implement the above-mentioned considerations.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
#define PARAMS(...) void* RCX, ##__VA_ARGS__
|
||||
#define ARGS(...) RCX, ##__VA_ARGS__
|
||||
#define THIS RCX
|
||||
#else
|
||||
#define PARAMS(...) void* ECX, void* EDX, ##__VA_ARGS__
|
||||
#define ARGS(...) ECX, EDX, ##__VA_ARGS__
|
||||
#define THIS ECX
|
||||
#endif
|
||||
|
||||
// Names beginning with $ designate macros that are not meant to be used directly by the sources consuming this file
|
||||
|
||||
#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec( dllexport ) TYPE __cdecl
|
||||
@@ -14,11 +47,12 @@
|
||||
#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \
|
||||
static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC);
|
||||
|
||||
#define $DETOUR(FUNC, MODULE_HANDLE) \
|
||||
koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, #FUNC, reinterpret_cast<FunctionAddress>(FUNC));
|
||||
|
||||
#define DETOUR_ADDRESS(FUNC, ADDRESS) \
|
||||
koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast<FunctionAddress>(FUNC));
|
||||
koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast<uintptr_t>(FUNC));
|
||||
|
||||
#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, globals::steamclient_module)
|
||||
#define DETOUR_VSTDLIB(FUNC) $DETOUR(FUNC, globals::vstdlib_module)
|
||||
#define $DETOUR(FUNC, NAME, MODULE_HANDLE) \
|
||||
koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, NAME, reinterpret_cast<uintptr_t>(FUNC));
|
||||
|
||||
#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, #FUNC, globals::steamclient_module)
|
||||
#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include <koalabox/loader.hpp>
|
||||
#include <core/paths.hpp>
|
||||
#include <core/globals.hpp>
|
||||
#include <koalabox/loader.hpp>
|
||||
|
||||
namespace paths {
|
||||
|
||||
Path get_self_path() {
|
||||
static const auto path = loader::get_module_dir(globals::smokeapi_handle);
|
||||
static const auto path = koalabox::loader::get_module_dir(globals::smokeapi_handle);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -22,4 +23,5 @@ namespace paths {
|
||||
static const auto path = get_self_path() / "SmokeAPI.log.log";
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace paths {
|
||||
using namespace koalabox;
|
||||
|
||||
/**
|
||||
* @return An std::path instance representing the directory containing this DLL
|
||||
@@ -13,4 +11,5 @@ namespace paths {
|
||||
Path get_config_path();
|
||||
Path get_cache_path();
|
||||
Path get_log_path();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
typedef uint32_t SteamInventoryResult_t;
|
||||
typedef uint64_t SteamItemInstanceID_t;
|
||||
typedef uint32_t SteamItemDef_t;
|
||||
typedef uint32_t AppId_t;
|
||||
typedef uint32_t HSteamPipe;
|
||||
typedef uint32_t HSteamUser;
|
||||
typedef uint64_t CSteamID;
|
||||
#include <cstdint>
|
||||
|
||||
using AppId_t = uint32_t;
|
||||
using SteamInventoryResult_t = uint32_t;
|
||||
using SteamItemInstanceID_t = uint64_t;
|
||||
using SteamItemDef_t = uint32_t;
|
||||
using HSteamPipe = uint32_t;
|
||||
using HSteamUser = uint32_t;
|
||||
using CSteamID = uint64_t;
|
||||
using EResult = uint32_t;
|
||||
|
||||
struct SteamItemDetails_t {
|
||||
SteamItemInstanceID_t m_itemId;
|
||||
@@ -22,4 +25,10 @@ enum EUserHasLicenseForAppResult {
|
||||
k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated
|
||||
};
|
||||
|
||||
typedef uint32_t EResult;
|
||||
class ISteamClient;
|
||||
|
||||
class ISteamApps;
|
||||
|
||||
class ISteamUser;
|
||||
|
||||
class ISteamInventory;
|
||||
@@ -1,13 +1,19 @@
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <koalageddon/vstdlib.hpp>
|
||||
#include <build_config.h>
|
||||
#include <core/cache.hpp>
|
||||
#include <core/config.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/dll_monitor.hpp>
|
||||
#include <koalabox/http_client.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/patcher.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
|
||||
namespace koalageddon {
|
||||
using namespace koalabox;
|
||||
|
||||
KoalageddonConfig config; // NOLINT(cert-err58-cpp)
|
||||
|
||||
/**
|
||||
@@ -21,7 +27,7 @@ namespace koalageddon {
|
||||
|
||||
return "local config override";
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Failed to get local koalageddon config: {}", ex.what());
|
||||
LOG_ERROR("Failed to get local koalageddon config: {}", ex.what())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +40,7 @@ namespace koalageddon {
|
||||
|
||||
return "GitHub repository";
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Failed to get remote koalageddon config: {}", ex.what());
|
||||
LOG_ERROR("Failed to get remote koalageddon config: {}", ex.what())
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -44,7 +50,7 @@ namespace koalageddon {
|
||||
|
||||
return "disk cache";
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Failed to get cached koalageddon config: {}", ex.what());
|
||||
LOG_ERROR("Failed to get cached koalageddon config: {}", ex.what())
|
||||
}
|
||||
|
||||
// Finally, fallback on the default config
|
||||
@@ -53,35 +59,41 @@ namespace koalageddon {
|
||||
}
|
||||
|
||||
void init() {
|
||||
std::thread([]() {
|
||||
const auto kg_config_source = init_koalageddon_config();
|
||||
logger->info("Loaded Koalageddon config from the {}", kg_config_source);
|
||||
}).detach();
|
||||
|
||||
dll_monitor::init({VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& module_handle, const String& name) {
|
||||
try {
|
||||
if (util::strings_are_equal(name, VSTDLIB_DLL)) {
|
||||
// VStdLib DLL handles Family Sharing functions
|
||||
|
||||
globals::vstdlib_module = module_handle;
|
||||
|
||||
if (config::instance.unlock_family_sharing) {
|
||||
DETOUR_VSTDLIB(Coroutine_Create)
|
||||
}
|
||||
} else if (util::strings_are_equal(name, STEAMCLIENT_DLL)) {
|
||||
// SteamClient DLL handles unlocking functions
|
||||
|
||||
globals::steamclient_module = module_handle;
|
||||
|
||||
DETOUR_STEAMCLIENT(CreateInterface)
|
||||
}
|
||||
|
||||
if (globals::vstdlib_module != nullptr && globals::steamclient_module != nullptr) {
|
||||
dll_monitor::shutdown();
|
||||
}
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Koalageddon mode dll monitor init error. Module: '{}', Message: {}", name, ex.what());
|
||||
std::thread(
|
||||
[]() {
|
||||
const auto kg_config_source = init_koalageddon_config();
|
||||
LOG_INFO("Loaded Koalageddon config from the {}", kg_config_source)
|
||||
}
|
||||
});
|
||||
).detach();
|
||||
|
||||
dll_monitor::init(
|
||||
{VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& module_handle, const String& name) {
|
||||
try {
|
||||
if (util::strings_are_equal(name, VSTDLIB_DLL)) {
|
||||
// VStdLib DLL handles Family Sharing functions
|
||||
|
||||
globals::vstdlib_module = module_handle;
|
||||
|
||||
if (config::instance.unlock_family_sharing) {
|
||||
DETOUR_VSTDLIB(Coroutine_Create)
|
||||
}
|
||||
} else if (util::strings_are_equal(name, STEAMCLIENT_DLL)) {
|
||||
// SteamClient DLL handles unlocking functions
|
||||
|
||||
globals::steamclient_module = module_handle;
|
||||
|
||||
DETOUR_STEAMCLIENT(CreateInterface)
|
||||
}
|
||||
|
||||
if (globals::vstdlib_module != nullptr && globals::steamclient_module != nullptr) {
|
||||
dll_monitor::shutdown();
|
||||
}
|
||||
} catch (const Exception& ex) {
|
||||
LOG_ERROR(
|
||||
"Koalageddon mode dll monitor process_interface_selector error. Module: '{}', Message: {}",
|
||||
name, ex.what())
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace koalageddon {
|
||||
using namespace koalabox;
|
||||
|
||||
// Offset values are interpreted according to pointer arithmetic rules, i.e.
|
||||
// 1 unit offset represents 4 and 8 bytes in 32-bit and 64-bit architectures respectively.
|
||||
struct KoalageddonConfig {
|
||||
@@ -37,7 +34,4 @@ namespace koalageddon {
|
||||
|
||||
void init();
|
||||
|
||||
namespace steamclient {
|
||||
void init(uintptr_t interface_selector_address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,117 +1,83 @@
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/patcher.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <Zydis/Zydis.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
|
||||
namespace koalageddon::steamclient {
|
||||
using namespace koalabox;
|
||||
|
||||
struct InstructionContext {
|
||||
std::optional<ZydisRegister> base_register;
|
||||
std::optional<String> function_name;
|
||||
};
|
||||
|
||||
// map<interface name, map<function name, function ordinal>>
|
||||
Map<String, Map<String, uint32_t>> ordinal_map; // NOLINT(cert-err58-cpp)
|
||||
|
||||
const auto MAX_INSTRUCTION_SIZE = 15;
|
||||
|
||||
|
||||
// TODO: Refactor into Koalabox
|
||||
ZydisDecoder decoder = {};
|
||||
ZydisFormatter formatter = {};
|
||||
|
||||
#define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \
|
||||
globals::address_map, \
|
||||
interface, \
|
||||
#INTERFACE"_"#FUNC, \
|
||||
ordinal_map[#INTERFACE][#FUNC], \
|
||||
reinterpret_cast<uintptr_t>(INTERFACE##_##FUNC) \
|
||||
#define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \
|
||||
globals::address_map, \
|
||||
interface, \
|
||||
#INTERFACE"_"#FUNC, \
|
||||
ordinal_map[#INTERFACE][#FUNC], \
|
||||
reinterpret_cast<uintptr_t>(INTERFACE##_##FUNC) \
|
||||
);
|
||||
|
||||
DLL_EXPORT(void) IClientAppManager_Selector(
|
||||
const void* interface,
|
||||
const void* arg2,
|
||||
const void* arg3,
|
||||
const void* arg4
|
||||
) {
|
||||
static std::once_flag flag;
|
||||
std::call_once(
|
||||
flag, [&]() {
|
||||
HOOK_FUNCTION(IClientAppManager, IsAppDlcInstalled)
|
||||
}
|
||||
);
|
||||
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_Selector)
|
||||
IClientAppManager_Selector_o(interface, arg2, arg3, arg4);
|
||||
#define SELECTOR_IMPLEMENTATION(INTERFACE, FUNC_BODY) \
|
||||
DLL_EXPORT(void) INTERFACE##_Selector( \
|
||||
const void* interface, \
|
||||
const void* arg2, \
|
||||
const void* arg3, \
|
||||
const void* arg4 \
|
||||
) { \
|
||||
CALL_ONCE(FUNC_BODY) \
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(INTERFACE##_Selector) \
|
||||
INTERFACE##_Selector_o(interface, arg2, arg3, arg4); \
|
||||
}
|
||||
|
||||
DLL_EXPORT(void) IClientApps_Selector(
|
||||
const void* interface,
|
||||
const void* arg2,
|
||||
const void* arg3,
|
||||
const void* arg4
|
||||
) {
|
||||
static std::once_flag flag;
|
||||
std::call_once(
|
||||
flag, [&]() {
|
||||
HOOK_FUNCTION(IClientApps, GetDLCCount)
|
||||
HOOK_FUNCTION(IClientApps, BGetDLCDataByIndex)
|
||||
}
|
||||
);
|
||||
SELECTOR_IMPLEMENTATION(IClientAppManager, {
|
||||
HOOK_FUNCTION(IClientAppManager, IsAppDlcInstalled)
|
||||
})
|
||||
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_Selector)
|
||||
IClientApps_Selector_o(interface, arg2, arg3, arg4);
|
||||
}
|
||||
SELECTOR_IMPLEMENTATION(IClientApps, {
|
||||
HOOK_FUNCTION(IClientApps, GetDLCCount)
|
||||
HOOK_FUNCTION(IClientApps, BGetDLCDataByIndex)
|
||||
})
|
||||
|
||||
DLL_EXPORT(void) IClientInventory_Selector(
|
||||
const void* interface,
|
||||
const void* arg2,
|
||||
const void* arg3,
|
||||
const void* arg4
|
||||
) {
|
||||
static std::once_flag flag;
|
||||
std::call_once(
|
||||
flag, [&]() {
|
||||
HOOK_FUNCTION(IClientInventory, GetResultStatus)
|
||||
HOOK_FUNCTION(IClientInventory, GetResultItems)
|
||||
HOOK_FUNCTION(IClientInventory, GetResultItemProperty)
|
||||
HOOK_FUNCTION(IClientInventory, CheckResultSteamID)
|
||||
HOOK_FUNCTION(IClientInventory, GetAllItems)
|
||||
HOOK_FUNCTION(IClientInventory, GetItemsByID)
|
||||
HOOK_FUNCTION(IClientInventory, SerializeResult)
|
||||
HOOK_FUNCTION(IClientInventory, GetItemDefinitionIDs)
|
||||
}
|
||||
);
|
||||
SELECTOR_IMPLEMENTATION(IClientInventory, {
|
||||
HOOK_FUNCTION(IClientInventory, GetResultStatus)
|
||||
HOOK_FUNCTION(IClientInventory, GetResultItems)
|
||||
HOOK_FUNCTION(IClientInventory, GetResultItemProperty)
|
||||
HOOK_FUNCTION(IClientInventory, CheckResultSteamID)
|
||||
HOOK_FUNCTION(IClientInventory, GetAllItems)
|
||||
HOOK_FUNCTION(IClientInventory, GetItemsByID)
|
||||
HOOK_FUNCTION(IClientInventory, SerializeResult)
|
||||
HOOK_FUNCTION(IClientInventory, GetItemDefinitionIDs)
|
||||
})
|
||||
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_Selector)
|
||||
IClientInventory_Selector_o(interface, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
DLL_EXPORT(void) IClientUser_Selector(
|
||||
const void* interface,
|
||||
const void* arg2,
|
||||
const void* arg3,
|
||||
const void* arg4
|
||||
) {
|
||||
static std::once_flag flag;
|
||||
std::call_once(
|
||||
flag, [&]() {
|
||||
HOOK_FUNCTION(IClientUser, BIsSubscribedApp)
|
||||
}
|
||||
);
|
||||
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_Selector)
|
||||
IClientUser_Selector_o(interface, arg2, arg3, arg4);
|
||||
}
|
||||
SELECTOR_IMPLEMENTATION(IClientUser, {
|
||||
HOOK_FUNCTION(IClientUser, BIsSubscribedApp)
|
||||
})
|
||||
|
||||
uintptr_t get_absolute_address(ZydisDecodedInstruction instruction, uintptr_t address) {
|
||||
const auto op = instruction.operands[0];
|
||||
const auto operand = instruction.operands[0];
|
||||
|
||||
if (op.imm.is_relative) {
|
||||
if (operand.imm.is_relative) {
|
||||
ZyanU64 absolute_address;
|
||||
ZydisCalcAbsoluteAddress(&instruction, &op, address, &absolute_address);
|
||||
ZydisCalcAbsoluteAddress(&instruction, &operand, address, &absolute_address);
|
||||
|
||||
return absolute_address;
|
||||
}
|
||||
|
||||
return (uintptr_t) op.imm.value.u;
|
||||
return (uintptr_t) operand.imm.value.u;
|
||||
}
|
||||
|
||||
bool is_push_immediate(const ZydisDecodedInstruction& instruction) {
|
||||
@@ -153,11 +119,6 @@ namespace koalageddon::steamclient {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
struct InstructionContext {
|
||||
std::optional<ZydisRegister> base_register;
|
||||
std::optional<String> function_name;
|
||||
};
|
||||
|
||||
void construct_ordinal_map( // NOLINT(misc-no-recursion)
|
||||
const String& target_interface,
|
||||
Map<String, uint32_t>& map,
|
||||
@@ -189,15 +150,13 @@ namespace koalageddon::steamclient {
|
||||
|
||||
auto current_address = (uintptr_t) start_address;
|
||||
ZydisDecodedInstruction instruction{};
|
||||
while (ZYAN_SUCCESS(
|
||||
ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
)
|
||||
)) {
|
||||
TRACE(
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
))) {
|
||||
LOG_TRACE(
|
||||
"{} -> Visiting {} | {}",
|
||||
__func__, (void*) current_address, *get_instruction_string(instruction, current_address)
|
||||
)
|
||||
@@ -296,10 +255,10 @@ namespace koalageddon::steamclient {
|
||||
if (offset && is_derived_from_base_reg) {
|
||||
const auto ordinal = *offset / sizeof(uintptr_t);
|
||||
|
||||
logger->debug(
|
||||
LOG_DEBUG(
|
||||
"{} -> Found function ordinal {}::{}@{}",
|
||||
__func__, target_interface, *context.function_name, ordinal
|
||||
);
|
||||
)
|
||||
|
||||
map[*context.function_name] = ordinal;
|
||||
break;
|
||||
@@ -320,14 +279,12 @@ namespace koalageddon::steamclient {
|
||||
std::optional<String> find_interface_name(uintptr_t selector_address) {
|
||||
auto current_address = selector_address;
|
||||
ZydisDecodedInstruction instruction{};
|
||||
while (ZYAN_SUCCESS(
|
||||
ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
)
|
||||
)) {
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
))) {
|
||||
const auto debug_str = get_instruction_string(instruction, current_address);
|
||||
|
||||
if (is_push_immediate(instruction)) {
|
||||
@@ -343,7 +300,7 @@ namespace koalageddon::steamclient {
|
||||
current_address += instruction.length;
|
||||
}
|
||||
|
||||
// logger->warn("Failed to find any interface names at {}", (void*) selector_address);
|
||||
// LOG_WARN("Failed to find any interface names at {}", (void*) selector_address);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -368,26 +325,24 @@ namespace koalageddon::steamclient {
|
||||
const uintptr_t start_address,
|
||||
Set<uintptr_t>& visited_addresses
|
||||
) {
|
||||
TRACE("{} -> start_address: {}", __func__, (void*) start_address)
|
||||
LOG_TRACE("{} -> start_address: {}", __func__, (void*) start_address)
|
||||
|
||||
if (visited_addresses.contains(start_address)) {
|
||||
TRACE("{} -> Breaking recursion due to visited address", __func__)
|
||||
LOG_TRACE("{} -> Breaking recursion due to visited address", __func__)
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_address = start_address;
|
||||
|
||||
ZydisDecodedInstruction instruction{};
|
||||
while (ZYAN_SUCCESS(
|
||||
ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
)
|
||||
)) {
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
|
||||
&decoder,
|
||||
(void*) current_address,
|
||||
MAX_INSTRUCTION_SIZE,
|
||||
&instruction
|
||||
))) {
|
||||
visited_addresses.insert(current_address);
|
||||
TRACE(
|
||||
LOG_TRACE(
|
||||
"{} -> Visiting {} | {}",
|
||||
__func__, (void*) current_address, *get_instruction_string(instruction, current_address)
|
||||
)
|
||||
@@ -397,7 +352,7 @@ namespace koalageddon::steamclient {
|
||||
if (instruction.mnemonic == ZYDIS_MNEMONIC_CALL &&
|
||||
operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE
|
||||
) {
|
||||
TRACE("{} -> Found call instruction at {}", __func__, (void*) current_address)
|
||||
LOG_TRACE("{} -> Found call instruction at {}", __func__, (void*) current_address)
|
||||
|
||||
const auto function_selector_address = get_absolute_address(instruction, current_address);
|
||||
|
||||
@@ -406,7 +361,7 @@ namespace koalageddon::steamclient {
|
||||
if (interface_name_opt) {
|
||||
const auto& interface_name = *interface_name_opt;
|
||||
|
||||
logger->debug("Detected interface: '{}'", interface_name);
|
||||
LOG_DEBUG("Detected interface: '{}'", interface_name)
|
||||
|
||||
DETOUR_SELECTOR(IClientAppManager)
|
||||
DETOUR_SELECTOR(IClientApps)
|
||||
@@ -420,7 +375,7 @@ namespace koalageddon::steamclient {
|
||||
process_interface_selector(jump_taken_destination, visited_addresses);
|
||||
process_interface_selector(jump_not_taken_destination, visited_addresses);
|
||||
|
||||
TRACE("breaking recursion due to conditional branch")
|
||||
LOG_TRACE("breaking recursion due to conditional branch")
|
||||
return;
|
||||
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
|
||||
operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE
|
||||
@@ -429,7 +384,7 @@ namespace koalageddon::steamclient {
|
||||
|
||||
process_interface_selector(jump_destination, visited_addresses);
|
||||
|
||||
TRACE("breaking recursion due to unconditional branch")
|
||||
LOG_TRACE("breaking recursion due to unconditional branch")
|
||||
return;
|
||||
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
|
||||
operand.type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||
@@ -448,7 +403,7 @@ namespace koalageddon::steamclient {
|
||||
|
||||
return;
|
||||
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_RET) {
|
||||
TRACE("{} -> Breaking recursion due to return instruction", __func__)
|
||||
LOG_TRACE("{} -> Breaking recursion due to return instruction", __func__)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -456,14 +411,23 @@ namespace koalageddon::steamclient {
|
||||
}
|
||||
}
|
||||
|
||||
void init(const uintptr_t interface_selector_address) {
|
||||
void process_client_engine(uintptr_t interface) {
|
||||
const auto* steam_client_internal = ((uintptr_t***) interface)[
|
||||
koalageddon::config.client_engine_steam_client_internal_ordinal
|
||||
];
|
||||
const auto interface_selector_address = (*steam_client_internal)[
|
||||
koalageddon::config.steam_client_internal_interface_selector_ordinal
|
||||
];
|
||||
|
||||
LOG_DEBUG("Found interface selector at: {}", (void*) interface_selector_address);
|
||||
|
||||
if (ZYAN_FAILED(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LEGACY_32, ZYDIS_ADDRESS_WIDTH_32))) {
|
||||
logger->error("Failed to initialize zydis decoder");
|
||||
LOG_ERROR("Failed to initialize zydis decoder")
|
||||
return;
|
||||
}
|
||||
|
||||
if (ZYAN_FAILED(ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL))) {
|
||||
logger->error("Failed to initialize zydis formatter");
|
||||
LOG_ERROR("Failed to initialize zydis formatter")
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
6
src/koalageddon/steamclient.hpp
Normal file
6
src/koalageddon/steamclient.hpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace koalageddon::steamclient {
|
||||
|
||||
void process_client_engine(uintptr_t interface);
|
||||
}
|
||||
@@ -1,88 +1,70 @@
|
||||
#include <koalageddon/vstdlib.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
using namespace koalageddon;
|
||||
using namespace koalabox;
|
||||
|
||||
VIRTUAL(bool) SharedLicensesLockStatus(PARAMS(void* arg)) { // NOLINT(misc-unused-parameters)
|
||||
logger->debug("{} -> instance: {}, arg: {}", __func__, fmt::ptr(THIS), fmt::ptr(arg));
|
||||
return true;
|
||||
}
|
||||
namespace koalageddon::vstdlib {
|
||||
using namespace koalabox;
|
||||
|
||||
VIRTUAL(bool) SharedLibraryStopPlaying(PARAMS(void* arg)) { // NOLINT(misc-unused-parameters)
|
||||
logger->debug("{} -> instance: {}, arg: {}", __func__, fmt::ptr(THIS), fmt::ptr(arg));
|
||||
return true;
|
||||
}
|
||||
|
||||
struct CallbackData {
|
||||
FunctionAddress get_callback_intercept_address() {
|
||||
return reinterpret_cast<FunctionAddress*>(this)[koalageddon::config.vstdlib_callback_interceptor_address_offset];
|
||||
VIRTUAL(bool) SharedLicensesLockStatus(PARAMS(void* arg)) {
|
||||
LOG_DEBUG("{} -> ecx: {}, edx: {}, arg: {}", __func__, ARGS(arg))
|
||||
return true;
|
||||
}
|
||||
|
||||
FunctionAddress get_callback_address() {
|
||||
return reinterpret_cast<FunctionAddress*>(this)[koalageddon::config.vstdlib_callback_address_offset];
|
||||
}
|
||||
};
|
||||
|
||||
struct CoroutineData {
|
||||
CallbackData* get_callback_data() {
|
||||
return reinterpret_cast<CallbackData**>(this)[koalageddon::config.vstdlib_callback_data_offset];
|
||||
VIRTUAL(bool) SharedLibraryStopPlaying(PARAMS(void* arg)) {
|
||||
LOG_DEBUG("{} -> ecx: {}, edx: {}, arg: {}", __func__, ARGS(arg))
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* get_callback_name() {
|
||||
return reinterpret_cast<const char**>(this)[koalageddon::config.vstdlib_callback_name_offset];
|
||||
}
|
||||
};
|
||||
VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** name_ptr)) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(VStdLib_Callback_Interceptor)
|
||||
VStdLib_Callback_Interceptor_o(ARGS(name_ptr));
|
||||
|
||||
VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** p_name)) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(VStdLib_Callback_Interceptor)
|
||||
static auto lock_status_hooked = false;
|
||||
static auto stop_playing_hooked = false;
|
||||
|
||||
VStdLib_Callback_Interceptor_o(ARGS(p_name));
|
||||
if (lock_status_hooked && stop_playing_hooked) {
|
||||
return;
|
||||
}
|
||||
|
||||
static auto lock_status_hooked = false;
|
||||
static auto stop_playing_hooked = false;
|
||||
auto* const data = (CoroutineData*) THIS;
|
||||
|
||||
if (lock_status_hooked && stop_playing_hooked) {
|
||||
return;
|
||||
}
|
||||
if (data && data->get_callback_name()) {
|
||||
const auto name = String(data->get_callback_name());
|
||||
LOG_TRACE("{} -> instance: {}, name: '{}'", __func__, fmt::ptr(THIS), name)
|
||||
|
||||
auto* const data = (CoroutineData*) THIS;
|
||||
|
||||
if (data && data->get_callback_name()) {
|
||||
const auto name = String(data->get_callback_name());
|
||||
TRACE("{} -> instance: {}, name: '{}'", __func__, fmt::ptr(THIS), name)
|
||||
|
||||
|
||||
if (name == "SharedLicensesLockStatus" && !lock_status_hooked) {
|
||||
DETOUR_ADDRESS(SharedLicensesLockStatus, data->get_callback_data()->get_callback_address())
|
||||
lock_status_hooked = true;
|
||||
} else if (name == "SharedLibraryStopPlaying" && !stop_playing_hooked) {
|
||||
DETOUR_ADDRESS(SharedLibraryStopPlaying, data->get_callback_data()->get_callback_address())
|
||||
stop_playing_hooked = true;
|
||||
if (name == "SharedLicensesLockStatus" && !lock_status_hooked) {
|
||||
DETOUR_ADDRESS(SharedLicensesLockStatus, data->get_callback_data()->get_callback_address())
|
||||
lock_status_hooked = true;
|
||||
} else if (name == "SharedLibraryStopPlaying" && !stop_playing_hooked) {
|
||||
DETOUR_ADDRESS(SharedLibraryStopPlaying, data->get_callback_data()->get_callback_address())
|
||||
stop_playing_hooked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initially, callback data passed into this function is not complete,
|
||||
* hence we must hook an interface method that sets the callback name.
|
||||
*/
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(Coroutine_Create)
|
||||
|
||||
const auto result = Coroutine_Create_o(callback_address, data);
|
||||
|
||||
// Coroutine callback appears to be always the same
|
||||
static std::once_flag flag;
|
||||
std::call_once(
|
||||
flag, [&]() {
|
||||
logger->debug("Coroutine_Create -> callback: {}, data: {}", callback_address, fmt::ptr(data));
|
||||
|
||||
DETOUR_ADDRESS(VStdLib_Callback_Interceptor, data->get_callback_data()->get_callback_intercept_address())
|
||||
}
|
||||
);
|
||||
|
||||
return result;
|
||||
|
||||
/**
|
||||
* Initially, callback data passed into this function is not complete,
|
||||
* hence we must hook an interface method that sets the callback name.
|
||||
*/
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(Coroutine_Create)
|
||||
|
||||
const auto result = Coroutine_Create_o(callback_address, data);
|
||||
|
||||
// Coroutine callback appears to be always the same
|
||||
CALL_ONCE({
|
||||
LOG_DEBUG("Coroutine_Create -> callback: {}, data: {}", callback_address, fmt::ptr(data));
|
||||
|
||||
DETOUR_ADDRESS(
|
||||
VStdLib_Callback_Interceptor,
|
||||
data->get_callback_data()->get_callback_intercept_address()
|
||||
)
|
||||
})
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
29
src/koalageddon/vstdlib.hpp
Normal file
29
src/koalageddon/vstdlib.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <core/macros.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
|
||||
namespace koalageddon::vstdlib {
|
||||
|
||||
struct CallbackData {
|
||||
uintptr_t get_callback_intercept_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[koalageddon::config.vstdlib_callback_interceptor_address_offset];
|
||||
}
|
||||
|
||||
uintptr_t get_callback_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[koalageddon::config.vstdlib_callback_address_offset];
|
||||
}
|
||||
};
|
||||
|
||||
struct CoroutineData {
|
||||
CallbackData* get_callback_data() {
|
||||
return reinterpret_cast<CallbackData**>(this)[koalageddon::config.vstdlib_callback_data_offset];
|
||||
}
|
||||
|
||||
const char* get_callback_name() {
|
||||
return reinterpret_cast<const char**>(this)[koalageddon::config.vstdlib_callback_name_offset];
|
||||
}
|
||||
};
|
||||
|
||||
typedef uint32_t HCoroutine;
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/config_parser.hpp>
|
||||
#include <koalabox/dll_monitor.hpp>
|
||||
#include <koalabox/file_logger.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/loader.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
@@ -20,21 +20,23 @@ namespace smoke_api {
|
||||
using namespace koalabox;
|
||||
|
||||
void init_proxy_mode() {
|
||||
logger->info("🔀 Detected proxy mode");
|
||||
LOG_INFO("🔀 Detected proxy mode")
|
||||
|
||||
globals::steamapi_module = loader::load_original_library(paths::get_self_path(), STEAMAPI_DLL);
|
||||
}
|
||||
|
||||
void init_hook_mode() {
|
||||
logger->info("🪝 Detected hook mode");
|
||||
LOG_INFO("🪝 Detected hook mode")
|
||||
|
||||
dll_monitor::init(STEAMCLIENT_DLL, [](const HMODULE& library) {
|
||||
globals::steamclient_module = library;
|
||||
dll_monitor::init(
|
||||
STEAMCLIENT_DLL, [](const HMODULE& library) {
|
||||
globals::steamclient_module = library;
|
||||
|
||||
DETOUR_STEAMCLIENT(CreateInterface)
|
||||
DETOUR_STEAMCLIENT(CreateInterface)
|
||||
|
||||
dll_monitor::shutdown();
|
||||
});
|
||||
dll_monitor::shutdown();
|
||||
}
|
||||
);
|
||||
|
||||
// Hooking steam_api has shown itself to be less desirable than steamclient
|
||||
// for the reasons outlined below:
|
||||
@@ -80,41 +82,35 @@ namespace smoke_api {
|
||||
|
||||
globals::smokeapi_handle = module_handle;
|
||||
|
||||
koalabox::project_name = PROJECT_NAME;
|
||||
|
||||
config::init();
|
||||
|
||||
if (config::instance.logging) {
|
||||
logger::init_file_logger(paths::get_log_path());
|
||||
}
|
||||
|
||||
LOG_INFO("🐨 {} v{}", PROJECT_NAME, PROJECT_VERSION)
|
||||
|
||||
const auto exe_path = Path(win_util::get_module_file_name_or_throw(nullptr));
|
||||
const auto exe_name = exe_path.filename().string();
|
||||
const auto exe_bitness = util::is_x64() ? 64 : 32;
|
||||
|
||||
if (config::instance.logging) {
|
||||
logger = file_logger::create(paths::get_log_path());
|
||||
}
|
||||
|
||||
logger->info("🐨 {} v{}", PROJECT_NAME, PROJECT_VERSION);
|
||||
|
||||
logger->debug(R"(Process name: "{}" [{}-bit])", exe_name, exe_bitness);
|
||||
LOG_DEBUG(R"(Process name: "{}" [{}-bit])", exe_name, exe_bitness)
|
||||
|
||||
if (hook::is_hook_mode(globals::smokeapi_handle, STEAMAPI_DLL)) {
|
||||
hook::init(true);
|
||||
|
||||
#ifdef _WIN64
|
||||
init_hook_mode();
|
||||
#else
|
||||
// TODO: Check if it's steam from valve
|
||||
if (is_valve_steam(exe_name)) {
|
||||
logger->info("🐨💥 Detected Koalageddon mode");
|
||||
|
||||
#ifndef _WIN64
|
||||
LOG_INFO("🐨💥 Detected Koalageddon mode")
|
||||
koalageddon::init();
|
||||
#endif
|
||||
} else {
|
||||
init_hook_mode();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
init_proxy_mode();
|
||||
}
|
||||
logger->info("🚀 Initialization complete");
|
||||
LOG_INFO("🚀 Initialization complete")
|
||||
} catch (const Exception& ex) {
|
||||
util::panic(fmt::format("Initialization error: {}", ex.what()));
|
||||
}
|
||||
@@ -126,9 +122,9 @@ namespace smoke_api {
|
||||
win_util::free_library(globals::steamapi_module);
|
||||
}
|
||||
|
||||
logger->info("💀 Shutdown complete");
|
||||
LOG_INFO("💀 Shutdown complete")
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Shutdown error: {}", ex.what());
|
||||
LOG_ERROR("Shutdown error: {}", ex.what())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,43 @@
|
||||
#include <core/macros.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
#include <steam_impl/steam_user.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
using namespace koalabox;
|
||||
|
||||
// ISteamApps
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(ISteamApps* self, AppId_t appID) {
|
||||
return steam_apps::IsDlcUnlocked(__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp)
|
||||
return steam_apps::IsDlcUnlocked(
|
||||
__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp)
|
||||
|
||||
return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, appID);
|
||||
});
|
||||
return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, appID);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(ISteamApps* self, AppId_t appID) {
|
||||
return steam_apps::IsDlcUnlocked(__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled)
|
||||
return steam_apps::IsDlcUnlocked(
|
||||
__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled)
|
||||
|
||||
return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, appID);
|
||||
});
|
||||
return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, appID);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps* self) {
|
||||
return steam_apps::GetDLCCount(__func__, 0, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount)
|
||||
return steam_apps::GetDLCCount(
|
||||
__func__, 0, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount)
|
||||
|
||||
return SteamAPI_ISteamApps_GetDLCCount_o(self);
|
||||
});
|
||||
return SteamAPI_ISteamApps_GetDLCCount_o(self);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
|
||||
@@ -40,13 +48,15 @@ DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
|
||||
char* pchName,
|
||||
int cchNameBufferSize
|
||||
) {
|
||||
return steam_apps::GetDLCDataByIndex(__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BGetDLCDataByIndex)
|
||||
return steam_apps::GetDLCDataByIndex(
|
||||
__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BGetDLCDataByIndex)
|
||||
|
||||
return SteamAPI_ISteamApps_BGetDLCDataByIndex_o(
|
||||
self, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize
|
||||
);
|
||||
});
|
||||
return SteamAPI_ISteamApps_BGetDLCDataByIndex_o(
|
||||
self, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ISteamUser
|
||||
@@ -56,11 +66,13 @@ DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp
|
||||
CSteamID steamID,
|
||||
AppId_t appID
|
||||
) {
|
||||
return steam_user::UserHasLicenseForApp(__func__, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
|
||||
return steam_user::UserHasLicenseForApp(
|
||||
__func__, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
|
||||
|
||||
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, appID);
|
||||
});
|
||||
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, appID);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ISteamClient
|
||||
@@ -71,11 +83,13 @@ DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(
|
||||
HSteamPipe hSteamPipe,
|
||||
const char* pchVersion
|
||||
) {
|
||||
return steam_client::GetGenericInterface(__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamClient_GetISteamGenericInterface)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamClient_GetISteamGenericInterface)
|
||||
|
||||
return SteamAPI_ISteamClient_GetISteamGenericInterface_o(self, hSteamUser, hSteamPipe, pchVersion);
|
||||
});
|
||||
return SteamAPI_ISteamClient_GetISteamGenericInterface_o(self, hSteamUser, hSteamPipe, pchVersion);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ISteamInventory
|
||||
@@ -84,11 +98,13 @@ DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(
|
||||
ISteamInventory* self,
|
||||
SteamInventoryResult_t resultHandle
|
||||
) {
|
||||
return steam_inventory::GetResultStatus(__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetResultStatus)
|
||||
return steam_inventory::GetResultStatus(
|
||||
__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetResultStatus)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetResultStatus_o(self, resultHandle);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_GetResultStatus_o(self, resultHandle);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
|
||||
@@ -136,22 +152,26 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(
|
||||
SteamInventoryResult_t resultHandle,
|
||||
CSteamID steamIDExpected
|
||||
) {
|
||||
return steam_inventory::CheckResultSteamID(__func__, resultHandle, steamIDExpected, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_CheckResultSteamID)
|
||||
return steam_inventory::CheckResultSteamID(
|
||||
__func__, resultHandle, steamIDExpected, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_CheckResultSteamID)
|
||||
|
||||
return SteamAPI_ISteamInventory_CheckResultSteamID_o(self, resultHandle, steamIDExpected);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_CheckResultSteamID_o(self, resultHandle, steamIDExpected);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(
|
||||
ISteamInventory* self,
|
||||
SteamInventoryResult_t* pResultHandle
|
||||
) {
|
||||
return steam_inventory::GetAllItems(__func__, pResultHandle, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetAllItems)
|
||||
return steam_inventory::GetAllItems(
|
||||
__func__, pResultHandle, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetAllItems)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetAllItems_o(self, pResultHandle);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_GetAllItems_o(self, pResultHandle);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
|
||||
@@ -160,11 +180,13 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
|
||||
const SteamItemInstanceID_t* pInstanceIDs,
|
||||
uint32_t unCountInstanceIDs
|
||||
) {
|
||||
return steam_inventory::GetItemsByID(__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemsByID)
|
||||
return steam_inventory::GetItemsByID(
|
||||
__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemsByID)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetItemsByID_o(self, pResultHandle, pInstanceIDs, unCountInstanceIDs);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_GetItemsByID_o(self, pResultHandle, pInstanceIDs, unCountInstanceIDs);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(
|
||||
@@ -173,11 +195,13 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(
|
||||
void* pOutBuffer,
|
||||
uint32_t* punOutBufferSize
|
||||
) {
|
||||
return steam_inventory::SerializeResult(__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_SerializeResult)
|
||||
return steam_inventory::SerializeResult(
|
||||
__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_SerializeResult)
|
||||
|
||||
return SteamAPI_ISteamInventory_SerializeResult_o(self, resultHandle, pOutBuffer, punOutBufferSize);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_SerializeResult_o(self, resultHandle, pOutBuffer, punOutBufferSize);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
|
||||
@@ -185,9 +209,11 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
|
||||
SteamItemDef_t* pItemDefIDs,
|
||||
uint32_t* punItemDefIDsArraySize
|
||||
) {
|
||||
return steam_inventory::GetItemDefinitionIDs(__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
|
||||
return steam_inventory::GetItemDefinitionIDs(
|
||||
__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o(self, pItemDefIDs, punItemDefIDsArraySize);
|
||||
});
|
||||
return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o(self, pItemDefIDs, punItemDefIDsArraySize);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
#include <core/macros.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
|
||||
using namespace koalabox;
|
||||
|
||||
DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser hSteamUser, const char* version) {
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInternal_FindOrCreateUserInterface)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInternal_FindOrCreateUserInterface)
|
||||
|
||||
return SteamInternal_FindOrCreateUserInterface_o(hSteamUser, version);
|
||||
});
|
||||
return SteamInternal_FindOrCreateUserInterface_o(hSteamUser, version);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(void*) SteamInternal_CreateInterface(const char* version) {
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInternal_CreateInterface)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInternal_CreateInterface)
|
||||
|
||||
return SteamInternal_CreateInterface_o(version);
|
||||
});
|
||||
return SteamInternal_CreateInterface_o(version);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
#include <core/macros.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
|
||||
#include <koalabox/util.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <regex>
|
||||
|
||||
using namespace smoke_api;
|
||||
using namespace steam_functions;
|
||||
using namespace koalabox;
|
||||
|
||||
/**
|
||||
* Searches the `.rdata` section of the original dll for the full interface version string
|
||||
@@ -28,10 +28,10 @@ String get_versioned_interface(const String& version_prefix, const String& fallb
|
||||
|
||||
throw util::exception("No match found for '{}'", version_prefix);
|
||||
} catch (const Exception& ex) {
|
||||
logger->error(
|
||||
LOG_ERROR(
|
||||
"Failed to get versioned interface: {}."
|
||||
"Falling back to version {}", ex.what(), fallback
|
||||
);
|
||||
)
|
||||
|
||||
version_map[version_prefix] = version_prefix + fallback;
|
||||
}
|
||||
@@ -41,41 +41,49 @@ String get_versioned_interface(const String& version_prefix, const String& fallb
|
||||
}
|
||||
|
||||
DLL_EXPORT(void*) SteamClient() {
|
||||
static auto version = get_versioned_interface(STEAM_CLIENT, "006");
|
||||
static auto version = get_versioned_interface(steam_functions::STEAM_CLIENT, "006");
|
||||
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamClient)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamClient)
|
||||
|
||||
return SteamClient_o();
|
||||
});
|
||||
return SteamClient_o();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(void*) SteamApps() {
|
||||
static auto version = get_versioned_interface(STEAM_APPS, "002");
|
||||
static auto version = get_versioned_interface(steam_functions::STEAM_APPS, "002");
|
||||
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamApps)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamApps)
|
||||
|
||||
return SteamApps_o();
|
||||
});
|
||||
return SteamApps_o();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(void*) SteamUser() {
|
||||
static auto version = get_versioned_interface(STEAM_USER, "012");
|
||||
static auto version = get_versioned_interface(steam_functions::STEAM_USER, "012");
|
||||
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamUser)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamUser)
|
||||
|
||||
return SteamUser_o();
|
||||
});
|
||||
return SteamUser_o();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(void*) SteamInventory() {
|
||||
static auto version = get_versioned_interface(STEAM_INVENTORY, "001");
|
||||
static auto version = get_versioned_interface(steam_functions::STEAM_INVENTORY, "001");
|
||||
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInventory)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInventory)
|
||||
|
||||
return SteamInventory_o();
|
||||
});
|
||||
return SteamInventory_o();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,34 @@
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <core/macros.hpp>
|
||||
|
||||
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t appID)) { // NOLINT(misc-unused-parameters)
|
||||
return steam_apps::IsDlcUnlocked(__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsSubscribedApp)
|
||||
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t appID)) {
|
||||
return steam_apps::IsDlcUnlocked(
|
||||
__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsSubscribedApp)
|
||||
|
||||
return ISteamApps_BIsSubscribedApp_o(ARGS(appID));
|
||||
});
|
||||
return ISteamApps_BIsSubscribedApp_o(ARGS(appID));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t appID)) { // NOLINT(misc-unused-parameters)
|
||||
return steam_apps::IsDlcUnlocked(__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsDlcInstalled)
|
||||
VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t appID)) {
|
||||
return steam_apps::IsDlcUnlocked(
|
||||
__func__, 0, appID, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(ISteamApps_BIsDlcInstalled)
|
||||
|
||||
return ISteamApps_BIsDlcInstalled_o(ARGS(appID));
|
||||
});
|
||||
return ISteamApps_BIsDlcInstalled_o(ARGS(appID));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_GetDLCCount)
|
||||
|
||||
return steam_apps::GetDLCCount(__func__, 0, [&]() {
|
||||
|
||||
return ISteamApps_GetDLCCount_o(ARGS());
|
||||
});
|
||||
return steam_apps::GetDLCCount(
|
||||
__func__, 0, [&]() {
|
||||
return ISteamApps_GetDLCCount_o(ARGS());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(
|
||||
@@ -34,11 +40,13 @@ VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(
|
||||
int cchNameBufferSize
|
||||
)
|
||||
) {
|
||||
return steam_apps::GetDLCDataByIndex(__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex)
|
||||
return steam_apps::GetDLCDataByIndex(
|
||||
__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex)
|
||||
|
||||
return ISteamApps_BGetDLCDataByIndex_o(
|
||||
ARGS(iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize)
|
||||
);
|
||||
});
|
||||
return ISteamApps_BGetDLCDataByIndex_o(
|
||||
ARGS(iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
VIRTUAL(void*) ISteamClient_GetISteamApps(
|
||||
PARAMS(
|
||||
@@ -10,11 +8,13 @@ VIRTUAL(void*) ISteamClient_GetISteamApps(
|
||||
const char* version
|
||||
)
|
||||
) {
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps)
|
||||
|
||||
return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||
});
|
||||
return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(void*) ISteamClient_GetISteamUser(
|
||||
@@ -24,11 +24,13 @@ VIRTUAL(void*) ISteamClient_GetISteamUser(
|
||||
const char* version
|
||||
)
|
||||
) {
|
||||
return steam_client::GetGenericInterface(__func__, version, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, version, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser)
|
||||
|
||||
return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||
});
|
||||
return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
|
||||
@@ -38,11 +40,13 @@ VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
|
||||
const char* pchVersion
|
||||
)
|
||||
) {
|
||||
return steam_client::GetGenericInterface(__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface)
|
||||
|
||||
return ISteamClient_GetISteamGenericInterface_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||
});
|
||||
return ISteamClient_GetISteamGenericInterface_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(void*) ISteamClient_GetISteamInventory(
|
||||
@@ -52,9 +56,11 @@ VIRTUAL(void*) ISteamClient_GetISteamInventory(
|
||||
const char* pchVersion
|
||||
)
|
||||
) {
|
||||
return steam_client::GetGenericInterface(__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, pchVersion, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory)
|
||||
|
||||
return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||
});
|
||||
return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
|
||||
return steam_inventory::GetResultStatus(__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultStatus)
|
||||
return steam_inventory::GetResultStatus(
|
||||
__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultStatus)
|
||||
|
||||
return ISteamInventory_GetResultStatus_o(ARGS(resultHandle));
|
||||
});
|
||||
return ISteamInventory_GetResultStatus_o(ARGS(resultHandle));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamInventory_GetResultItems(
|
||||
@@ -18,7 +18,6 @@ VIRTUAL(bool) ISteamInventory_GetResultItems(
|
||||
uint32_t * punOutItemsArraySize
|
||||
)
|
||||
) {
|
||||
|
||||
return steam_inventory::GetResultItems(
|
||||
__func__, resultHandle, pOutItemsArray, punOutItemsArraySize,
|
||||
[&]() {
|
||||
@@ -60,19 +59,23 @@ VIRTUAL(bool) ISteamInventory_CheckResultSteamID(
|
||||
CSteamID steamIDExpected
|
||||
)
|
||||
) {
|
||||
return steam_inventory::CheckResultSteamID(__func__, resultHandle, steamIDExpected, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_CheckResultSteamID)
|
||||
return steam_inventory::CheckResultSteamID(
|
||||
__func__, resultHandle, steamIDExpected, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_CheckResultSteamID)
|
||||
|
||||
return ISteamInventory_CheckResultSteamID_o(ARGS(resultHandle, steamIDExpected));
|
||||
});
|
||||
return ISteamInventory_CheckResultSteamID_o(ARGS(resultHandle, steamIDExpected));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) {
|
||||
return steam_inventory::GetAllItems(__func__, pResultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetAllItems)
|
||||
return steam_inventory::GetAllItems(
|
||||
__func__, pResultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetAllItems)
|
||||
|
||||
return ISteamInventory_GetAllItems_o(ARGS(pResultHandle));
|
||||
});
|
||||
return ISteamInventory_GetAllItems_o(ARGS(pResultHandle));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamInventory_GetItemsByID(
|
||||
@@ -82,11 +85,13 @@ VIRTUAL(bool) ISteamInventory_GetItemsByID(
|
||||
uint32_t unCountInstanceIDs
|
||||
)
|
||||
) {
|
||||
return steam_inventory::GetItemsByID(__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemsByID)
|
||||
return steam_inventory::GetItemsByID(
|
||||
__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemsByID)
|
||||
|
||||
return ISteamInventory_GetItemsByID_o(ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs));
|
||||
});
|
||||
return ISteamInventory_GetItemsByID_o(ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamInventory_SerializeResult(
|
||||
@@ -96,11 +101,13 @@ VIRTUAL(bool) ISteamInventory_SerializeResult(
|
||||
uint32_t * punOutBufferSize
|
||||
)
|
||||
) {
|
||||
return steam_inventory::SerializeResult(__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_SerializeResult)
|
||||
return steam_inventory::SerializeResult(
|
||||
__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_SerializeResult)
|
||||
|
||||
return ISteamInventory_SerializeResult_o(ARGS(resultHandle, pOutBuffer, punOutBufferSize));
|
||||
});
|
||||
return ISteamInventory_SerializeResult_o(ARGS(resultHandle, pOutBuffer, punOutBufferSize));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(
|
||||
@@ -109,9 +116,11 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(
|
||||
uint32_t * punItemDefIDsArraySize
|
||||
)
|
||||
) {
|
||||
return steam_inventory::GetItemDefinitionIDs(__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs)
|
||||
return steam_inventory::GetItemDefinitionIDs(
|
||||
__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs)
|
||||
|
||||
return ISteamInventory_GetItemDefinitionIDs_o(ARGS(pItemDefIDs, punItemDefIDsArraySize));
|
||||
});
|
||||
return ISteamInventory_GetItemDefinitionIDs_o(ARGS(pItemDefIDs, punItemDefIDsArraySize));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <steam_impl/steam_user.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t appID)) {
|
||||
return steam_user::UserHasLicenseForApp(__func__, appID, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
|
||||
return steam_user::UserHasLicenseForApp(
|
||||
__func__, appID, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
|
||||
|
||||
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, appID));
|
||||
});
|
||||
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, appID));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalageddon/steamclient.hpp>
|
||||
#include <build_config.h>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <polyhook2/Misc.hpp>
|
||||
|
||||
namespace steam_functions {
|
||||
@@ -82,20 +84,20 @@ namespace steam_functions {
|
||||
int min_version,
|
||||
int max_version
|
||||
) {
|
||||
logger->debug("Hooking interface '{}'", version_string);
|
||||
LOG_DEBUG("Hooking interface '{}'", version_string)
|
||||
|
||||
try {
|
||||
const auto version_number = stoi(version_string.substr(prefix.length()));
|
||||
|
||||
if (version_number < min_version) {
|
||||
logger->warn("Legacy version of {}: {}", version_string, version_number);
|
||||
LOG_WARN("Legacy version of {}: {}", version_string, version_number)
|
||||
}
|
||||
|
||||
if (version_number > max_version) {
|
||||
logger->warn(
|
||||
LOG_WARN(
|
||||
"Unsupported new version of {}: {}. Fallback version {} will be used",
|
||||
version_string, version_number, max_version
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return version_number;
|
||||
@@ -118,19 +120,19 @@ namespace steam_functions {
|
||||
util::panic("Invalid interface version ({}) for function {}", interface_version, function_name);
|
||||
}
|
||||
|
||||
#define HOOK(MAP, FUNC) \
|
||||
#define HOOK_VIRTUALS(MAP, FUNC) \
|
||||
hook::swap_virtual_func( \
|
||||
globals::address_map, \
|
||||
interface, \
|
||||
#FUNC, \
|
||||
get_ordinal(MAP, #FUNC, version_number), \
|
||||
(FunctionAddress) (FUNC) \
|
||||
reinterpret_cast<uintptr_t>(FUNC) \
|
||||
);
|
||||
|
||||
#define HOOK_STEAM_CLIENT(FUNC) HOOK(steam_client_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_APPS(FUNC) HOOK(steam_apps_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_USER(FUNC) HOOK(steam_user_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_INVENTORY(FUNC) HOOK(steam_inventory_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_CLIENT(FUNC) HOOK_VIRTUALS(steam_client_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_APPS(FUNC) HOOK_VIRTUALS(steam_apps_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_USER(FUNC) HOOK_VIRTUALS(steam_user_ordinal_map, FUNC)
|
||||
#define HOOK_STEAM_INVENTORY(FUNC) HOOK_VIRTUALS(steam_inventory_ordinal_map, FUNC)
|
||||
|
||||
void hook_virtuals(void* interface, const String& version_string) {
|
||||
if (interface == nullptr) {
|
||||
@@ -138,17 +140,15 @@ namespace steam_functions {
|
||||
return;
|
||||
}
|
||||
|
||||
static Set<std::pair<void*, String>> hooked_interfaces;
|
||||
static Set<void*> hooked_interfaces;
|
||||
|
||||
const auto interface_pair = std::pair{interface, version_string};
|
||||
|
||||
if (hooked_interfaces.contains(interface_pair)) {
|
||||
if (hooked_interfaces.contains(interface)) {
|
||||
// This interface is already hooked. Skipping it.
|
||||
return;
|
||||
}
|
||||
|
||||
static std::mutex section;
|
||||
const std::lock_guard<std::mutex> guard(section);
|
||||
static Mutex section;
|
||||
const MutexLockGuard guard(section);
|
||||
|
||||
if (version_string.starts_with(STEAM_CLIENT)) {
|
||||
const auto version_number = extract_version_number(version_string, STEAM_CLIENT, 6, 20);
|
||||
@@ -196,22 +196,12 @@ namespace steam_functions {
|
||||
}
|
||||
} else if (version_string.starts_with(CLIENT_ENGINE)) {
|
||||
// Koalageddon mode
|
||||
|
||||
const auto* steam_client_internal = ((uintptr_t***) interface)[
|
||||
koalageddon::config.client_engine_steam_client_internal_ordinal
|
||||
];
|
||||
const auto interface_selector_address = (*steam_client_internal)[
|
||||
koalageddon::config.steam_client_internal_interface_selector_ordinal
|
||||
];
|
||||
|
||||
logger->debug("Found interface selector at: {}", (void*) interface_selector_address);
|
||||
|
||||
koalageddon::steamclient::init(interface_selector_address);
|
||||
koalageddon::steamclient::process_client_engine(reinterpret_cast<uintptr_t>(interface));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
hooked_interfaces.insert(interface_pair);
|
||||
hooked_interfaces.insert(interface);
|
||||
}
|
||||
|
||||
HSteamPipe get_steam_pipe_or_throw() {
|
||||
@@ -249,7 +239,7 @@ namespace steam_functions {
|
||||
return function(ARGS(args...));
|
||||
}
|
||||
|
||||
uint32_t get_app_id_or_throw() {
|
||||
AppId_t get_app_id_or_throw() {
|
||||
// Get CreateInterface
|
||||
const auto& steam_client_module = win_util::get_module_handle_or_throw(STEAMCLIENT_DLL);
|
||||
auto* CreateInterface_address = (void*) win_util::get_proc_address_or_throw(
|
||||
|
||||
@@ -1,46 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <steam_types/steam_types.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
/**
|
||||
* By default, virtual functions are declared with __thiscall
|
||||
* convention, which is normal since they are class members.
|
||||
* But it presents an issue for us, since we cannot pass *this
|
||||
* pointer as a function argument. This is because *this
|
||||
* pointer is passed via register ECX in __thiscall
|
||||
* convention. Hence, to resolve this issue we declare our
|
||||
* hooked functions with __fastcall convention, to trick
|
||||
* the compiler into reading ECX & EDX registers as 1st
|
||||
* and 2nd function arguments respectively. Similarly, __fastcall
|
||||
* makes the compiler push the first argument into the ECX register,
|
||||
* which mimics the __thiscall calling convention. Register EDX
|
||||
* is not used anywhere in this case, but we still pass it along
|
||||
* to conform to the __fastcall convention. This all applies
|
||||
* to the x86 architecture.
|
||||
*
|
||||
* In x86-64 however, there is only one calling convention,
|
||||
* so __fastcall is simply ignored. However, RDX in this case
|
||||
* will store the 1st actual argument to the function, so we
|
||||
* have to omit it from the function signature.
|
||||
*
|
||||
* The macros below implement the above-mentioned considerations.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
#define PARAMS(...) void* RCX, ##__VA_ARGS__
|
||||
#define ARGS(...) RCX, ##__VA_ARGS__
|
||||
#define THIS RCX
|
||||
#else
|
||||
#define PARAMS(...) void* ECX, void* EDX, ##__VA_ARGS__
|
||||
#define ARGS(...) ECX, EDX, ##__VA_ARGS__
|
||||
#define THIS ECX
|
||||
#endif
|
||||
|
||||
class ISteamClient;
|
||||
class ISteamApps;
|
||||
class ISteamUser;
|
||||
class ISteamInventory;
|
||||
|
||||
// TODO: Refactor into multiple headers
|
||||
|
||||
@@ -60,7 +23,7 @@ VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*,
|
||||
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t));
|
||||
|
||||
// ISteamInventory
|
||||
VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(uint32_t));
|
||||
VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t));
|
||||
VIRTUAL(bool) ISteamInventory_GetResultItems(PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*));
|
||||
VIRTUAL(bool) ISteamInventory_GetResultItemProperty(
|
||||
PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*)
|
||||
@@ -127,9 +90,6 @@ VIRTUAL(bool) IClientInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, cons
|
||||
VIRTUAL(bool) IClientInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t, uint32_t *));
|
||||
VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t, uint32_t *));
|
||||
|
||||
typedef uint32_t HCoroutine;
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, struct CoroutineData* data);
|
||||
|
||||
namespace steam_functions {
|
||||
using namespace koalabox;
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <cpr/cpr.h>
|
||||
#include <koalabox/io.hpp>
|
||||
#include <koalabox/http_client.hpp>
|
||||
#include <core/cache.hpp>
|
||||
#include <core/config.hpp>
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
|
||||
namespace steam_apps {
|
||||
using namespace smoke_api;
|
||||
using namespace koalabox;
|
||||
|
||||
/// Steamworks may max GetDLCCount value at 64, depending on how much unowned DLCs the user has.
|
||||
/// Despite this limit, some games with more than 64 DLCs still keep using this method.
|
||||
@@ -27,9 +29,9 @@ namespace steam_apps {
|
||||
try {
|
||||
app_id = steam_functions::get_app_id_or_throw();
|
||||
// TODO: Check what it returns in koalageddon mode
|
||||
logger->info("Detected App ID: {}", app_id);
|
||||
LOG_INFO("Detected App ID: {}", app_id)
|
||||
} catch (const Exception& ex) {
|
||||
logger->error("Failed to get app ID: {}", ex.what());
|
||||
LOG_ERROR("Failed to get app ID: {}", ex.what())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +56,7 @@ namespace steam_apps {
|
||||
dlcs.emplace_back(std::stoi(app_id));
|
||||
}
|
||||
} catch (const Exception& e) {
|
||||
logger->error("Failed to fetch dlc list from steam api: {}", e.what());
|
||||
LOG_ERROR("Failed to fetch dlc list from steam api: {}", e.what())
|
||||
total_success = false;
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ namespace steam_apps {
|
||||
dlcs = json[app_id_str].get<decltype(dlcs)>();
|
||||
}
|
||||
} catch (const Exception& e) {
|
||||
logger->error("Failed to fetch extra dlc list from github api: {}", e.what());
|
||||
LOG_ERROR("Failed to fetch extra dlc list from github api: {}", e.what())
|
||||
total_success = false;
|
||||
}
|
||||
|
||||
@@ -110,34 +112,34 @@ namespace steam_apps {
|
||||
const String& function_name,
|
||||
AppId_t app_id,
|
||||
AppId_t dlc_id,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
try {
|
||||
const auto unlocked = config::is_dlc_unlocked(app_id, dlc_id, original_function);
|
||||
|
||||
logger->info("{} -> {}DLC ID: {}, Unlocked: {}", function_name, get_app_id_log(app_id), dlc_id, unlocked);
|
||||
LOG_INFO("{} -> {}DLC ID: {}, Unlocked: {}", function_name, get_app_id_log(app_id), dlc_id, unlocked)
|
||||
|
||||
return unlocked;
|
||||
} catch (const Exception& e) {
|
||||
logger->error("{} -> Uncaught exception: {}", function_name, e.what());
|
||||
LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int GetDLCCount(const String& function_name, const AppId_t app_id, const std::function<int()>& original_function) {
|
||||
int GetDLCCount(const String& function_name, const AppId_t app_id, const Function<int()>& original_function) {
|
||||
try {
|
||||
const auto total_count = [&](int count) {
|
||||
logger->info("{} -> Responding with DLC count: {}", function_name, count);
|
||||
LOG_INFO("{} -> Responding with DLC count: {}", function_name, count)
|
||||
return count;
|
||||
};
|
||||
|
||||
if (app_id != 0) {
|
||||
logger->debug("{} -> App ID: {}", function_name, app_id);
|
||||
LOG_DEBUG("{} -> App ID: {}", function_name, app_id)
|
||||
}
|
||||
|
||||
const auto original_count = original_function();
|
||||
original_dlc_count_map[app_id] = original_count;
|
||||
logger->debug("{} -> Original DLC count: {}", function_name, original_count);
|
||||
LOG_DEBUG("{} -> Original DLC count: {}", function_name, original_count)
|
||||
|
||||
if (original_count < MAX_DLC) {
|
||||
return total_count(original_count);
|
||||
@@ -146,7 +148,7 @@ namespace steam_apps {
|
||||
// We need to fetch DLC IDs from all possible sources at this point
|
||||
|
||||
const auto injected_count = static_cast<int>(config::instance.extra_dlc_ids.size());
|
||||
logger->debug("{} -> Injected DLC count: {}", function_name, injected_count);
|
||||
LOG_DEBUG("{} -> Injected DLC count: {}", function_name, injected_count)
|
||||
|
||||
// Maintain a list of app_ids for which we have already fetched and cached DLC IDs
|
||||
static Set<AppId_t> cached_apps;
|
||||
@@ -154,7 +156,7 @@ namespace steam_apps {
|
||||
static std::mutex mutex;
|
||||
const std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
logger->debug("Game has {} or more DLCs. Fetching DLCs from remote sources.", MAX_DLC);
|
||||
LOG_DEBUG("Game has {} or more DLCs. Fetching DLCs from remote sources.", MAX_DLC)
|
||||
|
||||
if (fetch_and_cache_dlcs(app_id)) {
|
||||
cached_apps.insert(app_id);
|
||||
@@ -162,11 +164,11 @@ namespace steam_apps {
|
||||
}
|
||||
|
||||
const auto cached_count = static_cast<int>(cached_dlcs.size());
|
||||
logger->debug("{} -> Cached DLC count: {}", function_name, cached_count);
|
||||
LOG_DEBUG("{} -> Cached DLC count: {}", function_name, cached_count)
|
||||
|
||||
return total_count(injected_count + cached_count);
|
||||
} catch (const Exception& e) {
|
||||
logger->error("{} -> Uncaught exception: {}", function_name, e.what());
|
||||
LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -179,14 +181,14 @@ namespace steam_apps {
|
||||
bool* pbAvailable,
|
||||
char* pchName,
|
||||
int cchNameBufferSize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
try {
|
||||
const auto print_dlc_info = [&](const String& tag) {
|
||||
logger->info(
|
||||
LOG_INFO(
|
||||
"{} -> [{}] {}index: {}, DLC ID: {}, available: {}, name: '{}'",
|
||||
function_name, tag, get_app_id_log(app_id), iDLC, *pDlcId, *pbAvailable, pchName
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
const auto inject_dlc = [&](const String& tag, const Vector<AppId_t>& dlc_ids, const int index) {
|
||||
@@ -224,7 +226,7 @@ namespace steam_apps {
|
||||
*pbAvailable = config::is_dlc_unlocked(app_id, *pDlcId, [&]() { return *pbAvailable; });
|
||||
print_dlc_info("original");
|
||||
} else {
|
||||
logger->warn("{} -> original call failed for index: {}", function_name, iDLC);
|
||||
LOG_WARN("{} -> original call failed for index: {}", function_name, iDLC)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -236,7 +238,7 @@ namespace steam_apps {
|
||||
// [injected-dlc-0, injected-dlc-1, ..., cached-dlc-0, cached-dlc-1, ...]
|
||||
|
||||
if (iDLC < 0) {
|
||||
logger->warn("{} -> Out of bounds DLC index: {}", function_name, iDLC);
|
||||
LOG_WARN("{} -> Out of bounds DLC index: {}", function_name, iDLC)
|
||||
}
|
||||
|
||||
const int local_dlc_count = static_cast<int>(config::instance.extra_dlc_ids.size());
|
||||
@@ -250,14 +252,14 @@ namespace steam_apps {
|
||||
return inject_dlc("memory cache", cached_dlcs, adjusted_index);
|
||||
}
|
||||
|
||||
logger->error(
|
||||
LOG_ERROR(
|
||||
"{} -> Out of bounds DLC index: {}, local dlc count: {}, cached dlc count: {}",
|
||||
function_name, iDLC, local_dlc_count, cached_dlc_count
|
||||
);
|
||||
)
|
||||
|
||||
return false;
|
||||
} catch (const Exception& e) {
|
||||
logger->error("{} -> Uncaught exception: {}", function_name, e.what());
|
||||
LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace steam_apps {
|
||||
using namespace koalabox;
|
||||
|
||||
bool IsDlcUnlocked(
|
||||
const String& function_name,
|
||||
AppId_t app_id,
|
||||
AppId_t dlc_id,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
int GetDLCCount(
|
||||
const String& function_name,
|
||||
AppId_t app_id,
|
||||
const std::function<int()>& original_function
|
||||
const Function<int()>& original_function
|
||||
);
|
||||
|
||||
bool GetDLCDataByIndex(
|
||||
@@ -24,7 +24,7 @@ namespace steam_apps {
|
||||
bool* pbAvailable,
|
||||
char* pchName,
|
||||
int cchNameBufferSize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
namespace steam_client {
|
||||
|
||||
void* GetGenericInterface(
|
||||
const String& function_name,
|
||||
const String& interface_version,
|
||||
const std::function<void*()>& original_function
|
||||
const Function<void*()>& original_function
|
||||
) {
|
||||
logger->debug("{} -> Version: '{}'", function_name, interface_version);
|
||||
|
||||
auto* const interface = original_function();
|
||||
|
||||
logger->debug("{} -> Result: {}", function_name, fmt::ptr(interface));
|
||||
LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface)
|
||||
|
||||
steam_functions::hook_virtuals(interface, interface_version);
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace steam_client {
|
||||
using namespace koalabox;
|
||||
|
||||
void* GetGenericInterface(
|
||||
const String& function_name,
|
||||
const String& interface_version,
|
||||
const std::function<void*()>& original_function
|
||||
const Function<void*()>& original_function
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
#include <core/config.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
namespace steam_inventory {
|
||||
|
||||
EResult GetResultStatus(
|
||||
const String& function_name,
|
||||
const SteamInventoryResult_t resultHandle,
|
||||
const std::function<EResult()>& original_function
|
||||
const Function<EResult()>& original_function
|
||||
) {
|
||||
const auto status = original_function();
|
||||
|
||||
logger->debug("{} -> handle: {}, status: {}", function_name, resultHandle, (int) status);
|
||||
LOG_DEBUG("{} -> handle: {}, status: {}", function_name, resultHandle, (int) status)
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -20,8 +21,8 @@ namespace steam_inventory {
|
||||
const SteamInventoryResult_t resultHandle,
|
||||
SteamItemDetails_t* pOutItemsArray,
|
||||
uint32_t* punOutItemsArraySize,
|
||||
const std::function<bool()>& original_function,
|
||||
const std::function<bool(SteamItemDef_t*, uint32_t*)>& get_item_definition_ids
|
||||
const Function<bool()>& original_function,
|
||||
const Function<bool(SteamItemDef_t*, uint32_t*)>& get_item_definition_ids
|
||||
) {
|
||||
static std::mutex section;
|
||||
const std::lock_guard<std::mutex> guard(section);
|
||||
@@ -29,26 +30,26 @@ namespace steam_inventory {
|
||||
const auto success = original_function();
|
||||
|
||||
auto print_item = [](const String& tag, const SteamItemDetails_t& item) {
|
||||
logger->debug(
|
||||
LOG_DEBUG(
|
||||
" [{}] definitionId: {}, itemId: {}, quantity: {}, flags: {}",
|
||||
tag, item.m_iDefinition, item.m_itemId, item.m_unQuantity, item.m_unFlags
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
if (not success) {
|
||||
logger->debug("{} -> original result is false", function_name);
|
||||
LOG_DEBUG("{} -> original result is false", function_name)
|
||||
return success;
|
||||
}
|
||||
|
||||
if (punOutItemsArraySize == nullptr) {
|
||||
logger->error("{} -> arraySize pointer is null", function_name);
|
||||
LOG_ERROR("{} -> arraySize pointer is null", function_name)
|
||||
return success;
|
||||
}
|
||||
|
||||
logger->debug(
|
||||
LOG_DEBUG(
|
||||
"{} -> handle: {}, pOutItemsArray: {}, arraySize: {}",
|
||||
function_name, resultHandle, fmt::ptr(pOutItemsArray), *punOutItemsArraySize
|
||||
);
|
||||
)
|
||||
|
||||
static uint32_t original_count = 0;
|
||||
const auto injected_count = config::instance.extra_inventory_items.size();
|
||||
@@ -56,14 +57,13 @@ namespace steam_inventory {
|
||||
// Automatically get inventory items from steam
|
||||
static Vector<SteamItemDef_t> auto_inventory_items;
|
||||
if (config::instance.auto_inject_inventory) {
|
||||
static std::once_flag flag;
|
||||
std::call_once(flag, [&]() {
|
||||
CALL_ONCE({
|
||||
uint32_t count = 0;
|
||||
if (get_item_definition_ids(nullptr, &count)) {
|
||||
auto_inventory_items.resize(count);
|
||||
get_item_definition_ids(auto_inventory_items.data(), &count);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const auto auto_injected_count = auto_inventory_items.size();
|
||||
@@ -72,10 +72,10 @@ namespace steam_inventory {
|
||||
// If pOutItemsArray is NULL then we must set the array size.
|
||||
original_count = *punOutItemsArraySize;
|
||||
*punOutItemsArraySize += auto_injected_count + injected_count;
|
||||
logger->debug(
|
||||
LOG_DEBUG(
|
||||
"{} -> Original count: {}, Total count: {}",
|
||||
function_name, original_count, *punOutItemsArraySize
|
||||
);
|
||||
)
|
||||
} else {
|
||||
// Otherwise, we modify the array
|
||||
for (int i = 0; i < original_count; i++) {
|
||||
@@ -120,7 +120,7 @@ namespace steam_inventory {
|
||||
const char* pchPropertyName,
|
||||
char* pchValueBuffer,
|
||||
const uint32_t* punValueBufferSizeOut,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto common_info = fmt::format(
|
||||
"{} -> Handle: {}, Index: {}, Name: '{}'", function_name, resultHandle, unItemIndex, pchPropertyName
|
||||
@@ -129,11 +129,11 @@ namespace steam_inventory {
|
||||
const auto success = original_function();
|
||||
|
||||
if (!success) {
|
||||
logger->warn("{}, Result is false", common_info);
|
||||
LOG_WARN("{}, Result is false", common_info)
|
||||
return false;
|
||||
}
|
||||
|
||||
logger->debug("{}, Buffer: '{}'", common_info, String(pchValueBuffer, *punValueBufferSizeOut - 1));
|
||||
LOG_DEBUG("{}, Buffer: '{}'", common_info, String(pchValueBuffer, *punValueBufferSizeOut - 1))
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -141,11 +141,11 @@ namespace steam_inventory {
|
||||
bool GetAllItems(
|
||||
const String& function_name,
|
||||
const SteamInventoryResult_t* pResultHandle,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto success = original_function();
|
||||
|
||||
logger->debug("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle));
|
||||
LOG_DEBUG("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle))
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -156,15 +156,15 @@ namespace steam_inventory {
|
||||
SteamInventoryResult_t* pResultHandle,
|
||||
const SteamItemInstanceID_t* pInstanceIDs,
|
||||
const uint32_t unCountInstanceIDs,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto success = original_function();
|
||||
|
||||
logger->debug("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle));
|
||||
LOG_DEBUG("{} -> Handle: {}", function_name, fmt::ptr(pResultHandle))
|
||||
|
||||
if (success && pInstanceIDs != nullptr) {
|
||||
for (int i = 0; i < unCountInstanceIDs; i++) {
|
||||
logger->debug(" Index: {}, ItemId: {}", i, pInstanceIDs[i]);
|
||||
LOG_DEBUG(" Index: {}, ItemId: {}", i, pInstanceIDs[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,15 +176,15 @@ namespace steam_inventory {
|
||||
SteamInventoryResult_t resultHandle,
|
||||
void* pOutBuffer,
|
||||
uint32_t* punOutBufferSize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto success = original_function();
|
||||
|
||||
if (pOutBuffer != nullptr) {
|
||||
String buffer((char*) pOutBuffer, *punOutBufferSize);
|
||||
logger->debug("{} -> Handle: {}, Buffer: '{}'", function_name, resultHandle, buffer);
|
||||
LOG_DEBUG("{} -> Handle: {}, Buffer: '{}'", function_name, resultHandle, buffer)
|
||||
} else {
|
||||
logger->debug("{} -> Handle: {}, Size: '{}'", function_name, resultHandle, *punOutBufferSize);
|
||||
LOG_DEBUG("{} -> Handle: {}, Size: '{}'", function_name, resultHandle, *punOutBufferSize)
|
||||
}
|
||||
|
||||
return success;
|
||||
@@ -194,23 +194,23 @@ namespace steam_inventory {
|
||||
const String& function_name,
|
||||
const SteamItemDef_t* pItemDefIDs,
|
||||
uint32_t* punItemDefIDsArraySize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto success = original_function();
|
||||
|
||||
if (!success) {
|
||||
logger->warn("{} -> Result is false", function_name);
|
||||
LOG_WARN("{} -> Result is false", function_name)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (punItemDefIDsArraySize) {
|
||||
logger->debug("{} -> Size: {}", function_name, *punItemDefIDsArraySize);
|
||||
LOG_DEBUG("{} -> Size: {}", function_name, *punItemDefIDsArraySize)
|
||||
}
|
||||
|
||||
if (pItemDefIDs) { // Definitions were copied
|
||||
for (int i = 0; i < *punItemDefIDsArraySize; i++) {
|
||||
const auto& def = pItemDefIDs[i];
|
||||
logger->debug(" Index: {}, ID: {}", i, def);
|
||||
LOG_DEBUG(" Index: {}, ID: {}", i, def)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,14 +221,14 @@ namespace steam_inventory {
|
||||
const String& function_name,
|
||||
SteamInventoryResult_t resultHandle,
|
||||
CSteamID steamIDExpected,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
) {
|
||||
const auto result = original_function();
|
||||
|
||||
logger->debug(
|
||||
LOG_DEBUG(
|
||||
"{} -> handle: {}, steamID: {}, original result: {}",
|
||||
function_name, resultHandle, steamIDExpected, result
|
||||
);
|
||||
)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace steam_inventory {
|
||||
using namespace koalabox;
|
||||
|
||||
EResult GetResultStatus(
|
||||
const String& function_name,
|
||||
SteamInventoryResult_t resultHandle,
|
||||
const std::function<EResult()>& original_function
|
||||
const Function<EResult()>& original_function
|
||||
);
|
||||
|
||||
bool GetResultItems(
|
||||
@@ -15,8 +14,8 @@ namespace steam_inventory {
|
||||
SteamInventoryResult_t resultHandle,
|
||||
SteamItemDetails_t* pOutItemsArray,
|
||||
uint32_t* punOutItemsArraySize,
|
||||
const std::function<bool()>& original_function,
|
||||
const std::function<bool(SteamItemDef_t*, uint32_t*)>& get_item_definition_ids
|
||||
const Function<bool()>& original_function,
|
||||
const Function<bool(SteamItemDef_t*, uint32_t*)>& get_item_definition_ids
|
||||
);
|
||||
|
||||
bool GetResultItemProperty(
|
||||
@@ -26,13 +25,13 @@ namespace steam_inventory {
|
||||
const char* pchPropertyName,
|
||||
char* pchValueBuffer,
|
||||
const uint32_t* punValueBufferSizeOut,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
bool GetAllItems(
|
||||
const String& function_name,
|
||||
const SteamInventoryResult_t* pResultHandle,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
bool GetItemsByID(
|
||||
@@ -40,7 +39,7 @@ namespace steam_inventory {
|
||||
SteamInventoryResult_t* pResultHandle,
|
||||
const SteamItemInstanceID_t* pInstanceIDs,
|
||||
uint32_t unCountInstanceIDs,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
bool SerializeResult(
|
||||
@@ -48,14 +47,14 @@ namespace steam_inventory {
|
||||
SteamInventoryResult_t resultHandle,
|
||||
void* pOutBuffer,
|
||||
uint32_t* punOutBufferSize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
bool GetItemDefinitionIDs(
|
||||
const String& function_name,
|
||||
const SteamItemDef_t* pItemDefIDs,
|
||||
uint32_t* punItemDefIDsArraySize,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
|
||||
|
||||
@@ -63,6 +62,6 @@ namespace steam_inventory {
|
||||
const String& function_name,
|
||||
SteamInventoryResult_t resultHandle,
|
||||
CSteamID steamIDExpected,
|
||||
const std::function<bool()>& original_function
|
||||
const Function<bool()>& original_function
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
#include <steam_impl/steam_user.hpp>
|
||||
#include <core/config.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
namespace steam_user {
|
||||
|
||||
EUserHasLicenseForAppResult UserHasLicenseForApp(
|
||||
const String& function_name,
|
||||
AppId_t appID,
|
||||
const std::function<EUserHasLicenseForAppResult()>& original_function
|
||||
const Function<EUserHasLicenseForAppResult()>& original_function
|
||||
) {
|
||||
const auto result = original_function();
|
||||
|
||||
if (result == k_EUserHasLicenseResultNoAuth) {
|
||||
logger->warn("{} -> App ID: {}, Result: NoAuth", function_name, appID);
|
||||
LOG_WARN("{} -> App ID: {}, Result: NoAuth", function_name, appID)
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto has_license = config::is_dlc_unlocked(0, appID, [&]() {
|
||||
return result == k_EUserHasLicenseResultHasLicense;
|
||||
});
|
||||
const auto has_license = config::is_dlc_unlocked(
|
||||
0, appID, [&]() {
|
||||
return result == k_EUserHasLicenseResultHasLicense;
|
||||
}
|
||||
);
|
||||
|
||||
logger->info("{} -> App ID: {}, HasLicense: {}", function_name, appID, has_license);
|
||||
LOG_INFO("{} -> App ID: {}, HasLicense: {}", function_name, appID, has_license)
|
||||
|
||||
return has_license
|
||||
? k_EUserHasLicenseResultHasLicense
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#include <koalabox/koalabox.hpp>
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <koalabox/types.hpp>
|
||||
|
||||
namespace steam_user {
|
||||
using namespace koalabox;
|
||||
|
||||
EUserHasLicenseForAppResult UserHasLicenseForApp(
|
||||
const String& function_name,
|
||||
AppId_t appID,
|
||||
const std::function<EUserHasLicenseForAppResult()>& original_function
|
||||
const Function<EUserHasLicenseForAppResult()>& original_function
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include <core/macros.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result) {
|
||||
return steam_client::GetGenericInterface(__func__, interface_string, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(CreateInterface)
|
||||
return steam_client::GetGenericInterface(
|
||||
__func__, interface_string, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(CreateInterface)
|
||||
|
||||
return CreateInterface_o(interface_string, out_result);
|
||||
});
|
||||
return CreateInterface_o(interface_string, out_result);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
|
||||
VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) {
|
||||
return steam_apps::IsDlcUnlocked(__func__, app_id, dlc_id, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_IsAppDlcInstalled)
|
||||
return steam_apps::IsDlcUnlocked(
|
||||
__func__, app_id, dlc_id, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_IsAppDlcInstalled)
|
||||
|
||||
return IClientAppManager_IsAppDlcInstalled_o(ARGS(app_id, dlc_id));
|
||||
});
|
||||
return IClientAppManager_IsAppDlcInstalled_o(ARGS(app_id, dlc_id));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
|
||||
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
|
||||
return steam_apps::GetDLCCount(__func__, appId, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_GetDLCCount)
|
||||
return steam_apps::GetDLCCount(
|
||||
__func__, appId, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_GetDLCCount)
|
||||
|
||||
return IClientApps_GetDLCCount_o(ARGS(appId));
|
||||
});
|
||||
return IClientApps_GetDLCCount_o(ARGS(appId));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
||||
@@ -21,11 +22,13 @@ VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
||||
int cchNameBufferSize
|
||||
)
|
||||
) {
|
||||
return steam_apps::GetDLCDataByIndex(__func__, appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_BGetDLCDataByIndex)
|
||||
return steam_apps::GetDLCDataByIndex(
|
||||
__func__, appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_BGetDLCDataByIndex)
|
||||
|
||||
return IClientApps_BGetDLCDataByIndex_o(
|
||||
ARGS(appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize)
|
||||
);
|
||||
});
|
||||
return IClientApps_BGetDLCDataByIndex_o(
|
||||
ARGS(appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <core/steam_types.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
#include <steam_functions/steam_functions.hpp>
|
||||
|
||||
VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
|
||||
return steam_inventory::GetResultStatus(__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetResultStatus)
|
||||
return steam_inventory::GetResultStatus(
|
||||
__func__, resultHandle, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetResultStatus)
|
||||
|
||||
return IClientInventory_GetResultStatus_o(ARGS(resultHandle));
|
||||
});
|
||||
return IClientInventory_GetResultStatus_o(ARGS(resultHandle));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
VIRTUAL(bool) IClientInventory_GetResultItems(
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <smoke_api/smoke_api.hpp>
|
||||
#include <core/macros.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
using namespace smoke_api;
|
||||
|
||||
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t app_id)) {
|
||||
return steam_apps::IsDlcUnlocked(__func__, 0, app_id, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp)
|
||||
|
||||
Reference in New Issue
Block a user