mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2026-01-24 21:42:53 -05:00
Added init functions and hook fallback
This commit is contained in:
@@ -54,6 +54,10 @@ namespace {
|
||||
if(kb::str::eq(library_name, STEAMCLIENT_DLL)) {
|
||||
KB_HOOK_DETOUR_MODULE(CreateInterface, module_handle);
|
||||
} else if(kb::str::eq(library_name, STEAMAPI_DLL)) {
|
||||
KB_HOOK_DETOUR_MODULE(SteamAPI_Init, module_handle);
|
||||
KB_HOOK_DETOUR_MODULE(SteamAPI_InitSafe, module_handle);
|
||||
KB_HOOK_DETOUR_MODULE(SteamAPI_InitFlat, module_handle);
|
||||
KB_HOOK_DETOUR_MODULE(SteamInternal_SteamAPI_Init, module_handle);
|
||||
KB_HOOK_DETOUR_MODULE(SteamAPI_RestartAppIfNecessary, module_handle);
|
||||
KB_HOOK_DETOUR_MODULE(SteamAPI_Shutdown, module_handle);
|
||||
|
||||
@@ -98,8 +102,8 @@ namespace smoke_api {
|
||||
}
|
||||
|
||||
LOG_INFO("Initialization complete");
|
||||
} catch(const std::exception& ex) {
|
||||
kb::util::panic(fmt::format("Initialization error: {}", ex.what()));
|
||||
} catch(const std::exception& e) {
|
||||
kb::util::panic(fmt::format("Initialization error: {}", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,22 +4,93 @@
|
||||
#include "smoke_api/config.hpp"
|
||||
#include "smoke_api/smoke_api.hpp"
|
||||
|
||||
#define AUTO_CALL(FUNC, ...) \
|
||||
#define AUTO_CALL_RETURN(FUNC, ...) \
|
||||
static const auto _##FUNC = smoke_api::hook_mode \
|
||||
? KB_HOOK_GET_HOOKED_FN(FUNC) \
|
||||
: KB_WIN_GET_PROC(smoke_api::steamapi_module, FUNC); \
|
||||
return _##FUNC(__VA_ARGS__)
|
||||
|
||||
#define AUTO_CALL_RESULT(FUNC, ...) \
|
||||
static const auto _##FUNC = smoke_api::hook_mode \
|
||||
? KB_HOOK_GET_HOOKED_FN(FUNC) \
|
||||
: KB_WIN_GET_PROC(smoke_api::steamapi_module, FUNC); \
|
||||
const auto result = _##FUNC(__VA_ARGS__)
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_Init() {
|
||||
LOG_INFO(__func__);
|
||||
|
||||
AUTO_CALL_RESULT(SteamAPI_Init);
|
||||
|
||||
LOG_INFO("{} -> result: {}", __func__, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_InitSafe() {
|
||||
LOG_INFO(__func__);
|
||||
|
||||
AUTO_CALL_RESULT(SteamAPI_InitSafe);
|
||||
|
||||
LOG_INFO("{} -> result: {}", __func__, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DLL_EXPORT(ESteamAPIInitResult) SteamAPI_InitFlat(const SteamErrMsg* pOutErrMsg) {
|
||||
LOG_INFO(__func__);
|
||||
|
||||
AUTO_CALL_RESULT(SteamAPI_InitFlat, pOutErrMsg);
|
||||
|
||||
const auto error_message = pOutErrMsg && *pOutErrMsg
|
||||
? std::string_view(*pOutErrMsg)
|
||||
: "";
|
||||
|
||||
LOG_INFO(
|
||||
"{} -> result: {}, error_message: {}",
|
||||
__func__,
|
||||
result,
|
||||
error_message
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DLL_EXPORT(ESteamAPIInitResult) SteamInternal_SteamAPI_Init(
|
||||
const char* pszInternalCheckInterfaceVersions,
|
||||
const SteamErrMsg* pOutErrMsg
|
||||
) {
|
||||
LOG_INFO(__func__);
|
||||
|
||||
AUTO_CALL_RESULT(SteamInternal_SteamAPI_Init, pszInternalCheckInterfaceVersions, pOutErrMsg);
|
||||
|
||||
const auto error_message = pOutErrMsg && *pOutErrMsg
|
||||
? std::string_view(*pOutErrMsg)
|
||||
: "";
|
||||
|
||||
LOG_INFO(
|
||||
"{} -> pszInternalCheckInterfaceVersions: {}, result: {}, error_message: {}",
|
||||
__func__,
|
||||
pszInternalCheckInterfaceVersions,
|
||||
result,
|
||||
error_message
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const AppId_t unOwnAppID) {
|
||||
LOG_INFO("{} -> unOwnAppID: {}", __func__, unOwnAppID);
|
||||
LOG_INFO(__func__);
|
||||
|
||||
AUTO_CALL_RESULT(SteamAPI_RestartAppIfNecessary, unOwnAppID);
|
||||
|
||||
LOG_INFO("{} -> unOwnAppID: {}, result: {}", __func__, unOwnAppID, result);
|
||||
|
||||
// Restart can be suppressed if needed
|
||||
|
||||
AUTO_CALL(SteamAPI_RestartAppIfNecessary, unOwnAppID);
|
||||
return result;
|
||||
}
|
||||
|
||||
DLL_EXPORT(void) SteamAPI_Shutdown() {
|
||||
LOG_INFO("{} -> Game requested shutdown", __func__);
|
||||
|
||||
AUTO_CALL(SteamAPI_Shutdown);
|
||||
AUTO_CALL_RETURN(SteamAPI_Shutdown);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
#include "smoke_api/smoke_api.hpp"
|
||||
#include "smoke_api/types.hpp"
|
||||
|
||||
using ESteamAPIInitResult = uint32_t;
|
||||
using SteamErrMsg = char[1024];
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_Init();
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_InitSafe();
|
||||
|
||||
DLL_EXPORT(ESteamAPIInitResult) SteamAPI_InitFlat(const SteamErrMsg* pOutErrMsg);
|
||||
|
||||
DLL_EXPORT(ESteamAPIInitResult) SteamInternal_SteamAPI_Init(
|
||||
const char* pszInternalCheckInterfaceVersions,
|
||||
const SteamErrMsg* pOutErrMsg
|
||||
);
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID);
|
||||
|
||||
DLL_EXPORT(void) SteamAPI_Shutdown();
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace steam_client {
|
||||
try {
|
||||
auto* const interface = original_function();
|
||||
|
||||
LOG_DEBUG("'{}' -> '{}' @ {}", function_name, interface_version, interface);
|
||||
LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface);
|
||||
|
||||
steam_interface::hook_virtuals(interface, interface_version);
|
||||
|
||||
return interface;
|
||||
} catch(const std::exception& e) {
|
||||
LOG_ERROR("'{}' -> Error: '{}' @ {}", function_name, interface_version, e.what());
|
||||
LOG_ERROR("{} -> Error: '{}' @ {}", function_name, interface_version, e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace {
|
||||
void* function_address; // e.g. ISteamClient_GetISteamApps
|
||||
};
|
||||
|
||||
// TODO: Split fallback into low and high versions
|
||||
struct interface_data { // NOLINT(*-exception-escape)
|
||||
std::string fallback_version; // e.g. "SteamClient021"
|
||||
std::map<std::string, interface_entry> entry_map;
|
||||
@@ -153,12 +154,13 @@ namespace steam_interface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param interface Pointer to the interface
|
||||
* @param interface_ptr Pointer to the interface
|
||||
* @param version_string Example: 'SteamClient020'
|
||||
*/
|
||||
void hook_virtuals(void* interface, const std::string& version_string) {
|
||||
if(interface == nullptr) {
|
||||
void hook_virtuals(void* interface_ptr, const std::string& version_string) {
|
||||
if(interface_ptr == nullptr) {
|
||||
// Game has tried to use an interface before initializing steam api
|
||||
// This does happen in practice.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,21 +169,28 @@ namespace steam_interface {
|
||||
|
||||
static std::set<void*> processed_interfaces;
|
||||
|
||||
if(processed_interfaces.contains(interface)) {
|
||||
if(processed_interfaces.contains(interface_ptr)) {
|
||||
LOG_DEBUG(
|
||||
"Interface '{}' @ {} has already been processed.",
|
||||
version_string,
|
||||
interface
|
||||
interface_ptr
|
||||
);
|
||||
return;
|
||||
}
|
||||
processed_interfaces.insert(interface);
|
||||
processed_interfaces.insert(interface_ptr);
|
||||
|
||||
static const auto virtual_hook_map = get_virtual_hook_map();
|
||||
for(const auto& [prefix, data] : virtual_hook_map) {
|
||||
if(not version_string.starts_with(prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_INFO(
|
||||
"Processing '{}' @ {} found in virtual hook map",
|
||||
version_string,
|
||||
interface_ptr
|
||||
);
|
||||
|
||||
const auto& lookup = find_lookup(version_string, data.fallback_version);
|
||||
|
||||
for(const auto& [function, entry] : data.entry_map) {
|
||||
@@ -190,7 +199,7 @@ namespace steam_interface {
|
||||
}
|
||||
|
||||
kb::hook::swap_virtual_func(
|
||||
interface,
|
||||
interface_ptr,
|
||||
entry.function_name,
|
||||
lookup.at(function),
|
||||
entry.function_address
|
||||
|
||||
@@ -6,5 +6,5 @@ namespace steam_interface {
|
||||
AppId_t get_app_id_or_throw();
|
||||
AppId_t get_app_id();
|
||||
|
||||
void hook_virtuals(void* interface, const std::string& version_string);
|
||||
void hook_virtuals(void* interface_ptr, const std::string& version_string);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user