Reworked hooking

This commit is contained in:
acidicoala
2025-08-28 22:25:11 +05:00
parent 6432eb3ec9
commit 09e1187ab0
19 changed files with 129 additions and 120 deletions

View File

@@ -35,6 +35,8 @@ set(SMOKE_API_STATIC_SOURCES
set(SMOKE_API_SOURCES set(SMOKE_API_SOURCES
${SMOKE_API_STATIC_SOURCES} ${SMOKE_API_STATIC_SOURCES}
src/smoke_api/smoke_api.cpp
src/smoke_api/smoke_api.hpp
src/steam_api/exports/steam_api.cpp src/steam_api/exports/steam_api.cpp
src/steam_api/exports/steam_api.hpp src/steam_api/exports/steam_api.hpp
src/steam_api/exports/steam_api_unversioned.cpp src/steam_api/exports/steam_api_unversioned.cpp
@@ -51,29 +53,30 @@ set(SMOKE_API_SOURCES
src/steam_api/steam_interface.hpp src/steam_api/steam_interface.hpp
src/steamclient/steamclient.cpp src/steamclient/steamclient.cpp
src/main.cpp src/main.cpp
src/smoke_api.cpp
src/smoke_api.hpp
) )
### SmokeAPI interface ### SmokeAPI interface
add_library(SmokeAPI_interface INTERFACE) add_library(SmokeAPI_common INTERFACE)
add_library(SmokeAPI::common ALIAS SmokeAPI_common)
target_include_directories(SmokeAPI_interface INTERFACE target_include_directories(SmokeAPI_common INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/static>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/static>"
) )
target_link_libraries(SmokeAPI_interface INTERFACE KoalaBox $<TARGET_OBJECTS:KoalaBox>) target_link_libraries(SmokeAPI_common INTERFACE KoalaBox $<TARGET_OBJECTS:KoalaBox>)
### Static SmokeAPI ### Static SmokeAPI
add_library(SmokeAPI_static STATIC ${SMOKE_API_STATIC_SOURCES}) add_library(SmokeAPI_static STATIC ${SMOKE_API_STATIC_SOURCES})
target_link_libraries(SmokeAPI_static PUBLIC SmokeAPI_interface) add_library(SmokeAPI::static ALIAS SmokeAPI_static)
target_link_libraries(SmokeAPI_static PUBLIC SmokeAPI::common)
### Shared SmokeAPI ### Shared SmokeAPI
add_library(SmokeAPI SHARED ${SMOKE_API_SOURCES}) add_library(SmokeAPI SHARED ${SMOKE_API_SOURCES})
target_link_libraries(SmokeAPI PUBLIC SmokeAPI_interface) target_link_libraries(SmokeAPI PUBLIC SmokeAPI::common)
set_target_properties(SmokeAPI PROPERTIES RUNTIME_OUTPUT_NAME ${STEAMAPI_DLL}) set_target_properties(SmokeAPI PROPERTIES RUNTIME_OUTPUT_NAME ${STEAMAPI_DLL})
configure_version_resource( configure_version_resource(
TARGET SmokeAPI TARGET SmokeAPI

View File

@@ -1,4 +1,4 @@
#include "smoke_api.hpp" #include "smoke_api/smoke_api.hpp"
// This header will be populated at build time // This header will be populated at build time
#include "linker_exports_for_steam_api.h" #include "linker_exports_for_steam_api.h"

View File

@@ -79,11 +79,9 @@ namespace smoke_api {
kb::logger::init_file_logger(kb::paths::get_log_path()); kb::logger::init_file_logger(kb::paths::get_log_path());
} }
// This kind of timestamp is reliable only for CI builds, as it will reflect the LOG_INFO("{} v{} | Built at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__);
// compilation time stamp only when this file gets recompiled.
LOG_INFO("{} v{} | Compiled at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__);
LOG_DEBUG("Parsed config:\n{}", nlohmann::json(config::instance).dump(2)); LOG_DEBUG("Parsed config:\n{}", nlohmann::ordered_json(config::instance).dump(2));
const auto exe_path = kb::win::get_module_path(nullptr); const auto exe_path = kb::win::get_module_path(nullptr);
const auto exe_name = kb::path::to_str(exe_path.filename()); const auto exe_name = kb::path::to_str(exe_path.filename());

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <koalabox/hook.hpp> #include <koalabox/win.hpp>
constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION";
constexpr auto STEAM_CLIENT = "SteamClient"; constexpr auto STEAM_CLIENT = "SteamClient";
@@ -13,21 +13,6 @@ constexpr auto STEAM_GAME_SERVER = "SteamGameServer";
// so any name changes here must be reflected there as well. // so any name changes here must be reflected there as well.
#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec(dllexport) TYPE __cdecl #define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec(dllexport) TYPE __cdecl
// These macros are meant to be used for callbacks that should return original result
#define MODULE_CALL(FUNC, ...) \
static const auto _##FUNC = KB_HOOK_GET_MODULE_FN(smoke_api::steamapi_module, FUNC); \
return _##FUNC(__VA_ARGS__)
#define MODULE_CALL_CLOSURE(FUNC, ...) \
[&] { MODULE_CALL(FUNC, __VA_ARGS__); }
#define AUTO_CALL(FUNC, ...) \
static const auto _##FUNC = smoke_api::hook_mode \
? KB_HOOK_GET_HOOKED_FN(FUNC) \
: KB_HOOK_GET_MODULE_FN(smoke_api::steamapi_module, FUNC); \
return _##FUNC(__VA_ARGS__)
namespace smoke_api { namespace smoke_api {
extern HMODULE steamapi_module; extern HMODULE steamapi_module;

View File

@@ -1,8 +1,14 @@
#include <koalabox/logger.hpp> #include <koalabox/logger.hpp>
#include "steam_api/exports/steam_api.hpp" #include "steam_api/exports/steam_api.hpp"
#include "smoke_api.hpp"
#include "smoke_api/config.hpp" #include "smoke_api/config.hpp"
#include "smoke_api/smoke_api.hpp"
#define AUTO_CALL(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__)
DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const AppId_t unOwnAppID) { DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const AppId_t unOwnAppID) {
LOG_INFO("{} -> unOwnAppID: {}", __func__, unOwnAppID); LOG_INFO("{} -> unOwnAppID: {}", __func__, unOwnAppID);

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "smoke_api.hpp" #include "smoke_api/smoke_api.hpp"
#include "smoke_api/types.hpp" #include "smoke_api/types.hpp"
DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID); DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(AppId_t unOwnAppID);

View File

@@ -1,10 +1,10 @@
#include <regex>
#include <map> #include <map>
#include <regex>
#include <koalabox/logger.hpp> #include <koalabox/logger.hpp>
#include <koalabox/win.hpp> #include <koalabox/win.hpp>
#include "smoke_api.hpp" #include "smoke_api/smoke_api.hpp"
#include "steam_api/steam_client.hpp" #include "steam_api/steam_client.hpp"
namespace { namespace {
@@ -20,7 +20,10 @@ namespace {
) { ) {
static std::map<std::string, std::string> version_map; static std::map<std::string, std::string> version_map;
if(not version_map.contains(version_prefix)) { if(version_map.contains(version_prefix)) {
return version_map.at(version_prefix);
}
try { try {
const auto section = kb::win::get_pe_section_or_throw( const auto section = kb::win::get_pe_section_or_throw(
smoke_api::steamapi_module, smoke_api::steamapi_module,
@@ -34,10 +37,9 @@ namespace {
const std::regex regex(version_prefix + "\\d{3}"); const std::regex regex(version_prefix + "\\d{3}");
if(std::smatch match; std::regex_search(rdata, match, regex)) { if(std::smatch match; std::regex_search(rdata, match, regex)) {
version_map[version_prefix] = match[0]; version_map[version_prefix] = match[0];
return version_map[version_prefix]; } else {
}
throw std::runtime_error(std::format("No match found for '{}'", version_prefix)); throw std::runtime_error(std::format("No match found for '{}'", version_prefix));
}
} catch(const std::exception& ex) { } catch(const std::exception& ex) {
LOG_ERROR( LOG_ERROR(
"Failed to get versioned interface: {}." "Failed to get versioned interface: {}."
@@ -48,14 +50,19 @@ namespace {
version_map[version_prefix] = version_prefix + fallback; version_map[version_prefix] = version_prefix + fallback;
} }
}
return version_map[version_prefix]; return version_map.at(version_prefix);
} }
} }
// TODO: Do we really need to proxy them? // TODO: Do we really need to proxy them?
#define MODULE_CALL_CLOSURE(FUNC, ...) \
[&] { \
static const auto _##FUNC = KB_WIN_GET_PROC(smoke_api::steamapi_module, FUNC); \
return _##FUNC(__VA_ARGS__); \
}
DLL_EXPORT(void*) SteamApps() { DLL_EXPORT(void*) SteamApps() {
static auto version = get_versioned_interface(STEAM_APPS, "002"); static auto version = get_versioned_interface(STEAM_APPS, "002");

View File

@@ -8,17 +8,17 @@
#include <koalabox/win.hpp> #include <koalabox/win.hpp>
#include "steam_api/steam_interface.hpp" #include "steam_api/steam_interface.hpp"
#include "smoke_api.hpp" #include "smoke_api/smoke_api.hpp"
#include "virtuals/steam_api_virtuals.hpp" #include "virtuals/steam_api_virtuals.hpp"
namespace { namespace {
struct interface_entry { struct interface_entry {
// function_name must match the function identifier to be able to call original functions // function_name must match the function identifier to be able to call original functions
std::string function_name; // e.g. "ISteamClient_GetISteamApps" std::string function_name; // e.g. "ISteamClient_GetISteamApps"
uintptr_t function_address; // e.g. ISteamClient_GetISteamApps void* function_address; // e.g. ISteamClient_GetISteamApps
}; };
struct interface_data { struct interface_data { // NOLINT(*-exception-escape)
std::string fallback_version; // e.g. "SteamClient021" std::string fallback_version; // e.g. "SteamClient021"
std::map<std::string, interface_entry> entry_map; std::map<std::string, interface_entry> entry_map;
// e.g. {ENTRY(ISteamClient, GetISteamApps), ...} // e.g. {ENTRY(ISteamClient, GetISteamApps), ...}
@@ -28,7 +28,7 @@ namespace {
#define ENTRY(INTERFACE, FUNC) \ #define ENTRY(INTERFACE, FUNC) \
{ \ { \
#FUNC, { \ #FUNC, { \
#INTERFACE "_" #FUNC, reinterpret_cast<uintptr_t>(INTERFACE##_##FUNC) \ #INTERFACE "_" #FUNC, reinterpret_cast<void*>(INTERFACE##_##FUNC) \
} \ } \
} }
@@ -137,6 +137,10 @@ namespace steam_interface {
} }
} }
/**
* @param interface Pointer to the interface
* @param version_string Example: 'SteamClient020'
*/
void hook_virtuals(void* interface, const std::string& version_string) { void hook_virtuals(void* interface, const std::string& version_string) {
if(interface == nullptr) { if(interface == nullptr) {
// Game has tried to use an interface before initializing steam api // Game has tried to use an interface before initializing steam api
@@ -160,11 +164,16 @@ namespace steam_interface {
static const auto virtual_hook_map = get_virtual_hook_map(); static const auto virtual_hook_map = get_virtual_hook_map();
for(const auto& [prefix, data] : virtual_hook_map) { for(const auto& [prefix, data] : virtual_hook_map) {
if(version_string.starts_with(prefix)) { if(not version_string.starts_with(prefix)) {
continue;
}
const auto& lookup = find_lookup(version_string, data.fallback_version); const auto& lookup = find_lookup(version_string, data.fallback_version);
for(const auto& [function, entry] : data.entry_map) { for(const auto& [function, entry] : data.entry_map) {
if(lookup.contains(function)) { if(not lookup.contains(function)) {
continue;
}
kb::hook::swap_virtual_func( kb::hook::swap_virtual_func(
interface, interface,
entry.function_name, entry.function_name,
@@ -172,10 +181,8 @@ namespace steam_interface {
entry.function_address entry.function_address
); );
} }
}
break; break;
} }
} }
} }
}

View File

@@ -9,7 +9,7 @@ VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(const AppId_t dlc_id)) noexcept
__func__, __func__,
steam_interface::get_app_id(), steam_interface::get_app_id(),
dlc_id, dlc_id,
HOOKED_CALL_CLOSURE(ISteamApps_BIsSubscribedApp, ARGS(dlc_id)) SWAPPED_CALL_CLOSURE(ISteamApps_BIsSubscribedApp, ARGS(dlc_id))
); );
} }
@@ -18,7 +18,7 @@ VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(const AppId_t dlc_id)) noexcept
__func__, __func__,
steam_interface::get_app_id(), steam_interface::get_app_id(),
dlc_id, dlc_id,
HOOKED_CALL_CLOSURE(ISteamApps_BIsDlcInstalled, ARGS(dlc_id)) SWAPPED_CALL_CLOSURE(ISteamApps_BIsDlcInstalled, ARGS(dlc_id))
); );
} }
@@ -26,7 +26,7 @@ VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) noexcept {
return smoke_api::steam_apps::GetDLCCount( return smoke_api::steam_apps::GetDLCCount(
__func__, __func__,
steam_interface::get_app_id(), steam_interface::get_app_id(),
HOOKED_CALL_CLOSURE(ISteamApps_GetDLCCount, ARGS()) SWAPPED_CALL_CLOSURE(ISteamApps_GetDLCCount, ARGS())
); );
} }
@@ -47,11 +47,11 @@ VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(
pbAvailable, pbAvailable,
pchName, pchName,
cchNameBufferSize, cchNameBufferSize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamApps_BGetDLCDataByIndex, ISteamApps_BGetDLCDataByIndex,
ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize) ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize)
), ),
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamApps_BIsSubscribedApp, ISteamApps_BIsSubscribedApp,
ARGS(*p_dlc_id) ARGS(*p_dlc_id)
) )

View File

@@ -13,7 +13,7 @@ VIRTUAL(void*) ISteamClient_GetISteamApps(
return steam_client::GetGenericInterface( return steam_client::GetGenericInterface(
__func__, __func__,
version, version,
HOOKED_CALL_CLOSURE(ISteamClient_GetISteamApps, ARGS(hSteamUser, hSteamPipe, version)) SWAPPED_CALL_CLOSURE(ISteamClient_GetISteamApps, ARGS(hSteamUser, hSteamPipe, version))
); );
} }
@@ -27,7 +27,7 @@ VIRTUAL(void*) ISteamClient_GetISteamUser(
return steam_client::GetGenericInterface( return steam_client::GetGenericInterface(
__func__, __func__,
version, version,
HOOKED_CALL_CLOSURE(ISteamClient_GetISteamUser, ARGS(hSteamUser, hSteamPipe, version)) SWAPPED_CALL_CLOSURE(ISteamClient_GetISteamUser, ARGS(hSteamUser, hSteamPipe, version))
); );
} }
@@ -41,7 +41,7 @@ VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(
return steam_client::GetGenericInterface( return steam_client::GetGenericInterface(
__func__, __func__,
pchVersion, pchVersion,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamClient_GetISteamGenericInterface, ISteamClient_GetISteamGenericInterface,
ARGS(hSteamUser, hSteamPipe, pchVersion) ARGS(hSteamUser, hSteamPipe, pchVersion)
) )
@@ -58,7 +58,7 @@ VIRTUAL(void*) ISteamClient_GetISteamInventory(
return steam_client::GetGenericInterface( return steam_client::GetGenericInterface(
__func__, __func__,
pchVersion, pchVersion,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamClient_GetISteamInventory, ISteamClient_GetISteamInventory,
ARGS(hSteamUser, hSteamPipe, pchVersion) ARGS(hSteamUser, hSteamPipe, pchVersion)
) )

View File

@@ -11,6 +11,6 @@ VIRTUAL(EUserHasLicenseForAppResult) ISteamGameServer_UserHasLicenseForApp(
__func__, __func__,
steam_interface::get_app_id(), steam_interface::get_app_id(),
dlc_id, dlc_id,
HOOKED_CALL_CLOSURE(ISteamGameServer_UserHasLicenseForApp, ARGS(steamID, dlc_id)) SWAPPED_CALL_CLOSURE(ISteamGameServer_UserHasLicenseForApp, ARGS(steamID, dlc_id))
); );
} }

View File

@@ -16,7 +16,7 @@ VIRTUAL(bool) ISteamHTTP_GetHTTPResponseBodyData(
hRequest, hRequest,
pBodyDataBuffer, pBodyDataBuffer,
unBufferSize, unBufferSize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamHTTP_GetHTTPResponseBodyData, ISteamHTTP_GetHTTPResponseBodyData,
ARGS(hRequest, pBodyDataBuffer, unBufferSize) ARGS(hRequest, pBodyDataBuffer, unBufferSize)
) )
@@ -37,7 +37,7 @@ VIRTUAL(bool) ISteamHTTP_GetHTTPStreamingResponseBodyData(
cOffset, cOffset,
pBodyDataBuffer, pBodyDataBuffer,
unBufferSize, unBufferSize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamHTTP_GetHTTPStreamingResponseBodyData, ISteamHTTP_GetHTTPStreamingResponseBodyData,
ARGS(hRequest, cOffset, pBodyDataBuffer, unBufferSize) ARGS(hRequest, cOffset, pBodyDataBuffer, unBufferSize)
) )
@@ -58,7 +58,7 @@ VIRTUAL(bool) ISteamHTTP_SetHTTPRequestRawPostBody(
pchContentType, pchContentType,
pubBody, pubBody,
unBodyLen, unBodyLen,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamHTTP_SetHTTPRequestRawPostBody, ISteamHTTP_SetHTTPRequestRawPostBody,
ARGS(hRequest, pchContentType, pubBody, unBodyLen) ARGS(hRequest, pchContentType, pubBody, unBodyLen)
) )

View File

@@ -7,7 +7,7 @@ VIRTUAL(EResult) ISteamInventory_GetResultStatus(
return smoke_api::steam_inventory::GetResultStatus( return smoke_api::steam_inventory::GetResultStatus(
__func__, __func__,
resultHandle, resultHandle,
HOOKED_CALL_CLOSURE(ISteamInventory_GetResultStatus, ARGS(resultHandle)) SWAPPED_CALL_CLOSURE(ISteamInventory_GetResultStatus, ARGS(resultHandle))
); );
} }
@@ -23,12 +23,13 @@ VIRTUAL(bool) ISteamInventory_GetResultItems(
resultHandle, resultHandle,
pOutItemsArray, pOutItemsArray,
punOutItemsArraySize, punOutItemsArraySize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamInventory_GetResultItems, ISteamInventory_GetResultItems,
ARGS(resultHandle, pOutItemsArray, punOutItemsArraySize) ARGS(resultHandle, pOutItemsArray, punOutItemsArraySize)
), ),
[&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) {
HOOKED_CALL( SWAPPED_CALL(
THIS,
ISteamInventory_GetItemDefinitionIDs, ISteamInventory_GetItemDefinitionIDs,
ARGS(pItemDefIDs, punItemDefIDsArraySize) ARGS(pItemDefIDs, punItemDefIDsArraySize)
); );
@@ -52,7 +53,7 @@ VIRTUAL(bool) ISteamInventory_GetResultItemProperty(
pchPropertyName, pchPropertyName,
pchValueBuffer, pchValueBuffer,
punValueBufferSizeOut, punValueBufferSizeOut,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamInventory_GetResultItemProperty, ISteamInventory_GetResultItemProperty,
ARGS( ARGS(
resultHandle, resultHandle,
@@ -69,7 +70,7 @@ VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResult
return smoke_api::steam_inventory::GetAllItems( return smoke_api::steam_inventory::GetAllItems(
__func__, __func__,
pResultHandle, pResultHandle,
HOOKED_CALL_CLOSURE(ISteamInventory_GetAllItems, ARGS(pResultHandle)) SWAPPED_CALL_CLOSURE(ISteamInventory_GetAllItems, ARGS(pResultHandle))
); );
} }
@@ -85,7 +86,7 @@ VIRTUAL(bool) ISteamInventory_GetItemsByID(
pResultHandle, pResultHandle,
pInstanceIDs, pInstanceIDs,
unCountInstanceIDs, unCountInstanceIDs,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamInventory_GetItemsByID, ISteamInventory_GetItemsByID,
ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs) ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs)
) )
@@ -104,7 +105,7 @@ VIRTUAL(bool) ISteamInventory_SerializeResult(
resultHandle, resultHandle,
pOutBuffer, pOutBuffer,
punOutBufferSize, punOutBufferSize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamInventory_SerializeResult, ISteamInventory_SerializeResult,
ARGS(resultHandle, pOutBuffer, punOutBufferSize) ARGS(resultHandle, pOutBuffer, punOutBufferSize)
) )
@@ -121,7 +122,7 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(
__func__, __func__,
pItemDefIDs, pItemDefIDs,
punItemDefIDsArraySize, punItemDefIDsArraySize,
HOOKED_CALL_CLOSURE( SWAPPED_CALL_CLOSURE(
ISteamInventory_GetItemDefinitionIDs, ISteamInventory_GetItemDefinitionIDs,
ARGS(pItemDefIDs, punItemDefIDsArraySize) ARGS(pItemDefIDs, punItemDefIDsArraySize)
) )
@@ -135,6 +136,6 @@ VIRTUAL(bool) ISteamInventory_CheckResultSteamID(
__func__, __func__,
resultHandle, resultHandle,
steamIDExpected, steamIDExpected,
HOOKED_CALL_CLOSURE(ISteamInventory_CheckResultSteamID, ARGS(resultHandle, steamIDExpected)) SWAPPED_CALL_CLOSURE(ISteamInventory_CheckResultSteamID, ARGS(resultHandle, steamIDExpected))
); );
} }

View File

@@ -11,6 +11,6 @@ VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(
__func__, __func__,
steam_interface::get_app_id(), steam_interface::get_app_id(),
dlc_id, dlc_id,
HOOKED_CALL_CLOSURE(ISteamUser_UserHasLicenseForApp, ARGS(steamID, dlc_id)) SWAPPED_CALL_CLOSURE(ISteamUser_UserHasLicenseForApp, ARGS(steamID, dlc_id))
); );
} }

View File

@@ -1,8 +1,10 @@
#include "smoke_api/steamclient/steamclient.hpp" #include <koalabox/hook.hpp>
#include "../smoke_api.hpp"
#include "smoke_api/types.hpp"
#include "../steam_api/steam_client.hpp" #include "smoke_api/steamclient/steamclient.hpp"
#include "smoke_api/smoke_api.hpp"
#include "smoke_api/types.hpp"
#include "steam_api/steam_client.hpp"
/** /**
* SmokeAPI implementation * SmokeAPI implementation
@@ -11,6 +13,9 @@ C_DECL(void*) CreateInterface(const char* interface_version, int* out_result) {
return steam_client::GetGenericInterface( return steam_client::GetGenericInterface(
__func__, __func__,
interface_version, interface_version,
HOOKED_CALL_CLOSURE(CreateInterface, interface_version, out_result) [&] {
static const auto CreateInterface$ = KB_HOOK_GET_HOOKED_FN(CreateInterface);
return CreateInterface$(interface_version, out_result);
}
); );
} }

View File

@@ -37,6 +37,7 @@ namespace smoke_api::config {
Config, Config,
$version, $version,
logging, logging,
log_steam_http,
default_app_status, default_app_status,
override_app_status, override_app_status,
override_dlc_status, override_dlc_status,

View File

@@ -4,9 +4,9 @@ std::vector<DLC> DLC::get_dlcs_from_apps(const AppDlcNameMap& apps, const AppId_
std::vector<DLC> dlcs; std::vector<DLC> dlcs;
if(const auto app_id_str = std::to_string(app_id); apps.contains(app_id_str)) { if(const auto app_id_str = std::to_string(app_id); apps.contains(app_id_str)) {
const auto& app = apps.at(app_id_str); const auto& [app_dlcs] = apps.at(app_id_str);
for(auto const& [id, name] : app.dlcs) { for(auto const& [id, name] : app_dlcs) {
dlcs.emplace_back(id, name); dlcs.emplace_back(id, name);
} }
} }

View File

@@ -13,16 +13,12 @@
// These macros are meant to be used for callbacks that should return original result // These macros are meant to be used for callbacks that should return original result
#define HOOKED_CALL(FUNC, ...) \ #define SWAPPED_CALL(CLASS, FUNC, ...) \
static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(FUNC); \ const auto _##FUNC = KB_HOOK_GET_SWAPPED_FN(CLASS, FUNC); \
return _##FUNC(__VA_ARGS__) return _##FUNC(__VA_ARGS__)
#define HOOKED_CALL_CLOSURE(FUNC, ...) \ #define SWAPPED_CALL_CLOSURE(FUNC, ...) \
[&] { HOOKED_CALL(FUNC, __VA_ARGS__); } [&] { SWAPPED_CALL(THIS, FUNC, __VA_ARGS__); }
#define HOOKED_CALL_RESULT(FUNC, ...) \
static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(FUNC); \
const auto result = _##FUNC(__VA_ARGS__)
/** /**
* By default, virtual functions are declared with __thiscall * By default, virtual functions are declared with __thiscall