mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2025-12-05 21:15:39 -05:00
Removed steam_api hooking
This commit is contained in:
@@ -75,7 +75,6 @@ SmokeAPI does not require any manual configuration. By default, it uses the most
|
|||||||
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|:-------:|
|
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|:-------:|
|
||||||
| `$version` | A technical field reserved for future use by tools like GUI config editors | Integer | `1` |
|
| `$version` | A technical field reserved for future use by tools like GUI config editors | Integer | `1` |
|
||||||
| `logging` | Toggles generation of `*.log` file | Boolean | `false` |
|
| `logging` | Toggles generation of `*.log` file | Boolean | `false` |
|
||||||
| `hook_steamclient` | When installed in hook mode, this option toggles between hooking steamclient(64).dll and steam_api(64).dll | Boolean | `true` |
|
|
||||||
| `unlock_all` | Toggles whether all DLCs should be unlocked by default | Boolean | `true` |
|
| `unlock_all` | Toggles whether all DLCs should be unlocked by default | Boolean | `true` |
|
||||||
| `override` | When `unlock_all` is `true`, this option serves as a blacklist of DLC IDs, which should remain locked. When `unlock_all` is `false`, this option serves as a whitelist of DLC IDs, which should become unlocked | List of Integers | `[]` |
|
| `override` | When `unlock_all` is `true`, this option serves as a blacklist of DLC IDs, which should remain locked. When `unlock_all` is `false`, this option serves as a whitelist of DLC IDs, which should become unlocked | List of Integers | `[]` |
|
||||||
| `dlc_ids` | When game requests list of all DLCs from Steam and the number of registered DLCs is greater than 64, Steam may not return all of them. In this case, SmokeAPI will fetch all released DLCs from Web API. In some games, however (like Monster Hunter: World), web api also doesn't return all possible DLCs. To address this issue, you can specify the missing DLC IDs¹ in this option. For some games (including MH:W), however, it is not necessary because SmokeAPI will also automatically fetch a [manually maintained list of DLC IDs] that are missing from web api | List of Integers | `[]` |
|
| `dlc_ids` | When game requests list of all DLCs from Steam and the number of registered DLCs is greater than 64, Steam may not return all of them. In this case, SmokeAPI will fetch all released DLCs from Web API. In some games, however (like Monster Hunter: World), web api also doesn't return all possible DLCs. To address this issue, you can specify the missing DLC IDs¹ in this option. For some games (including MH:W), however, it is not necessary because SmokeAPI will also automatically fetch a [manually maintained list of DLC IDs] that are missing from web api | List of Integers | `[]` |
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$version": 1,
|
"$version": 2,
|
||||||
"logging": true,
|
"logging": true,
|
||||||
"hook_steamclient": true,
|
|
||||||
"unlock_all": true,
|
"unlock_all": true,
|
||||||
"override": [],
|
"override": [],
|
||||||
"dlc_ids": [],
|
"dlc_ids": [],
|
||||||
|
|||||||
@@ -24,6 +24,65 @@ namespace smoke_api {
|
|||||||
|
|
||||||
Path self_directory;
|
Path self_directory;
|
||||||
|
|
||||||
|
void init_koalageddon_mode() {
|
||||||
|
#ifndef _WIN64
|
||||||
|
logger->info("🐨 Detected Koalageddon mode 💥");
|
||||||
|
|
||||||
|
dll_monitor::init({VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& library, const String& name) {
|
||||||
|
original_library = library; // TODO: Is this necessary?
|
||||||
|
|
||||||
|
if (name == VSTDLIB_DLL) {
|
||||||
|
// Family Sharing functions
|
||||||
|
DETOUR(Coroutine_Create)
|
||||||
|
} else if (name == STEAMCLIENT_DLL) {
|
||||||
|
// Unlocking functions
|
||||||
|
// TODO: Un-hardcode the pattern
|
||||||
|
const String pattern("55 8B EC 8B ?? ?? ?? ?? ?? 81 EC ?? ?? ?? ?? 53 FF 15");
|
||||||
|
auto Log_Interface_address = (FunctionAddress) patcher::find_pattern_address(
|
||||||
|
win_util::get_module_info(library), "Log_Interface", pattern
|
||||||
|
);
|
||||||
|
if (Log_Interface_address) {
|
||||||
|
DETOUR_EX(Log_Interface, Log_Interface_address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_proxy_mode() {
|
||||||
|
logger->info("🔀 Detected proxy mode");
|
||||||
|
|
||||||
|
original_library = loader::load_original_library(self_directory, ORIGINAL_DLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_hook_mode() {
|
||||||
|
logger->info("🪝 Detected hook mode");
|
||||||
|
|
||||||
|
dll_monitor::init(STEAMCLIENT_DLL, [](const HMODULE& library) {
|
||||||
|
original_library = library;
|
||||||
|
|
||||||
|
DETOUR(CreateInterface)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hooking steam_api has show itself to be less desirable than steamclient
|
||||||
|
// for the reasons outlined below:
|
||||||
|
//
|
||||||
|
// Calling original in flat functions will actually call the hooked functions
|
||||||
|
// because the original function redirects the execution to a function taken
|
||||||
|
// from self pointer, which would have been hooked by SteamInternal_*Interface
|
||||||
|
// functions.
|
||||||
|
//
|
||||||
|
// Furthermore, turns out that many flat functions share the same body,
|
||||||
|
// which looks like the following snippet:
|
||||||
|
//
|
||||||
|
// mov rax, qword ptr ds:[rcx]
|
||||||
|
// jmp qword ptr ds:[rax+immediate]
|
||||||
|
//
|
||||||
|
// This means that we end up inadvertently hooking unintended functions.
|
||||||
|
// Given that hooking steam_api has no apparent benefits, but has inherent flaws,
|
||||||
|
// the support for it has been dropped from this project.
|
||||||
|
}
|
||||||
|
|
||||||
void init(HMODULE self_module) {
|
void init(HMODULE self_module) {
|
||||||
try {
|
try {
|
||||||
DisableThreadLibraryCalls(self_module);
|
DisableThreadLibraryCalls(self_module);
|
||||||
@@ -51,68 +110,13 @@ namespace smoke_api {
|
|||||||
if (is_hook_mode) {
|
if (is_hook_mode) {
|
||||||
hook::init(true);
|
hook::init(true);
|
||||||
|
|
||||||
if (util::strings_are_equal(exe_name, "steam.exe")) {
|
if (util::strings_are_equal(exe_name, "steam.exe") && !util::is_x64()) {
|
||||||
#ifndef _WIN64
|
init_koalageddon_mode();
|
||||||
logger->info("🐨 Detected Koalageddon mode 💥");
|
} else {
|
||||||
|
init_hook_mode();
|
||||||
dll_monitor::init({VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& library, const String& name) {
|
|
||||||
original_library = library; // TODO: Is this necessary?
|
|
||||||
|
|
||||||
if (name == VSTDLIB_DLL) {
|
|
||||||
// Family Sharing functions
|
|
||||||
DETOUR(Coroutine_Create)
|
|
||||||
} else if (name == STEAMCLIENT_DLL) {
|
|
||||||
// Unlocking functions
|
|
||||||
// TODO: Un-hardcode the pattern
|
|
||||||
const String pattern("55 8B EC 8B ?? ?? ?? ?? ?? 81 EC ?? ?? ?? ?? 53 FF 15");
|
|
||||||
auto Log_Interface_address = (FunctionAddress) patcher::find_pattern_address(
|
|
||||||
win_util::get_module_info(library), "Log_Interface", pattern
|
|
||||||
);
|
|
||||||
if (Log_Interface_address) {
|
|
||||||
DETOUR_EX(Log_Interface, Log_Interface_address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
} else if (config.hook_steamclient) { // target steamclient(64).dll
|
|
||||||
logger->info("🪝 Detected hook mode for SteamClient");
|
|
||||||
|
|
||||||
dll_monitor::init(STEAMCLIENT_DLL, [](const HMODULE& library) {
|
|
||||||
original_library = library;
|
|
||||||
|
|
||||||
DETOUR(CreateInterface)
|
|
||||||
});
|
|
||||||
} else { // target steam_api.dll
|
|
||||||
logger->info("🪝 Detected hook mode for Steam_API");
|
|
||||||
|
|
||||||
dll_monitor::init(ORIGINAL_DLL, [](const HMODULE& library) {
|
|
||||||
original_library = library;
|
|
||||||
|
|
||||||
DETOUR(SteamInternal_FindOrCreateUserInterface)
|
|
||||||
DETOUR(SteamInternal_CreateInterface)
|
|
||||||
DETOUR(SteamApps)
|
|
||||||
DETOUR(SteamClient)
|
|
||||||
DETOUR(SteamUser)
|
|
||||||
|
|
||||||
DETOUR(SteamAPI_ISteamApps_BIsSubscribedApp)
|
|
||||||
DETOUR(SteamAPI_ISteamApps_BIsDlcInstalled)
|
|
||||||
DETOUR(SteamAPI_ISteamApps_GetDLCCount)
|
|
||||||
DETOUR(SteamAPI_ISteamApps_BGetDLCDataByIndex)
|
|
||||||
DETOUR(SteamAPI_ISteamClient_GetISteamGenericInterface)
|
|
||||||
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetResultStatus)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetResultItems)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetResultItemProperty)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_CheckResultSteamID)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetAllItems)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetItemsByID)
|
|
||||||
DETOUR(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger->info("🔀 Detected proxy mode for Steam_API");
|
init_proxy_mode();
|
||||||
|
|
||||||
original_library = loader::load_original_library(self_directory, ORIGINAL_DLL);
|
|
||||||
}
|
}
|
||||||
logger->info("🚀 Initialization complete");
|
logger->info("🚀 Initialization complete");
|
||||||
} catch (const Exception& ex) {
|
} catch (const Exception& ex) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ namespace smoke_api {
|
|||||||
struct Config {
|
struct Config {
|
||||||
uint32_t $version = 1;
|
uint32_t $version = 1;
|
||||||
bool logging = false;
|
bool logging = false;
|
||||||
bool hook_steamclient = true;
|
|
||||||
bool unlock_all = true;
|
bool unlock_all = true;
|
||||||
Set<uint32_t> override;
|
Set<uint32_t> override;
|
||||||
Vector<uint32_t> dlc_ids;
|
Vector<uint32_t> dlc_ids;
|
||||||
@@ -35,10 +34,9 @@ namespace smoke_api {
|
|||||||
Vector<uint32_t> inventory_items;
|
Vector<uint32_t> inventory_items;
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||||
Config, $version,
|
Config, $version, // NOLINT(misc-const-correctness)
|
||||||
logging,
|
logging,
|
||||||
unlock_all,
|
unlock_all,
|
||||||
hook_steamclient,
|
|
||||||
override,
|
override,
|
||||||
dlc_ids,
|
dlc_ids,
|
||||||
auto_inject_inventory,
|
auto_inject_inventory,
|
||||||
|
|||||||
@@ -159,18 +159,18 @@ namespace steam_apps {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (app_id) {
|
if (app_id != 0) {
|
||||||
logger->debug("{} -> App ID: {}", function_name, app_id);
|
logger->debug("{} -> App ID: {}", function_name, app_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute count only once // FIXME: This doesn't work in Koalageddon mode
|
// Compute count only once
|
||||||
|
// FIXME: This doesn't work in Koalageddon mode
|
||||||
original_dlc_count = original_function();
|
original_dlc_count = original_function();
|
||||||
logger->debug("{} -> Original DLC count: {}", function_name, original_dlc_count);
|
logger->debug("{} -> Original DLC count: {}", function_name, original_dlc_count);
|
||||||
|
|
||||||
const auto injected_count = static_cast<int>(config.dlc_ids.size());
|
const auto injected_count = static_cast<int>(config.dlc_ids.size());
|
||||||
logger->debug("{} -> Injected DLC count: {}", function_name, injected_count);
|
logger->debug("{} -> Injected DLC count: {}", function_name, injected_count);
|
||||||
|
|
||||||
|
|
||||||
if (original_dlc_count < max_dlc) {
|
if (original_dlc_count < max_dlc) {
|
||||||
return total_count(original_dlc_count + injected_count);
|
return total_count(original_dlc_count + injected_count);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using namespace smoke_api;
|
using namespace smoke_api;
|
||||||
|
|
||||||
|
// TODO: Implement?
|
||||||
VIRTUAL(bool) IClientUser_IsSubscribedApp(PARAMS(AppId_t app_id)) { // NOLINT(misc-unused-parameters)
|
VIRTUAL(bool) IClientUser_IsSubscribedApp(PARAMS(AppId_t app_id)) { // NOLINT(misc-unused-parameters)
|
||||||
return steam_apps::IsDlcUnlocked(__func__, 0, app_id);
|
return steam_apps::IsDlcUnlocked(__func__, 0, app_id);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user