Added ReloadConfig

This commit is contained in:
acidicoala
2023-01-11 01:35:14 +03:00
parent 30f1076261
commit edd785cfcf
21 changed files with 184 additions and 128 deletions

View File

@@ -87,6 +87,7 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 4)
src/koalageddon/steamclient/client_apps.cpp src/koalageddon/steamclient/client_apps.cpp
src/koalageddon/steamclient/client_inventory.cpp src/koalageddon/steamclient/client_inventory.cpp
src/koalageddon/steamclient/client_user.cpp src/koalageddon/steamclient/client_user.cpp
src/koalageddon/steamclient/client_utils.cpp
src/koalageddon/steamclient/steamclient.cpp src/koalageddon/steamclient/steamclient.cpp
src/koalageddon/steamclient/steamclient.hpp src/koalageddon/steamclient/steamclient.hpp
) )

View File

@@ -4,6 +4,10 @@
"unlock_family_sharing": true, "unlock_family_sharing": true,
"default_app_status": "unlocked", "default_app_status": "unlocked",
"override_app_status": { "override_app_status": {
"1234": "original",
"4321": "unlocked"
},
"override_dlc_status": {
"1234": "original", "1234": "original",
"4321": "unlocked", "4321": "unlocked",
"5678": "locked" "5678": "locked"

View File

@@ -94,11 +94,6 @@ enum EUserHasLicenseForAppResult {
k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated
}; };
class ISteamClient;
class ISteamApps;
class ISteamUser;
class ISteamInventory;
// These aliases exist solely to increase code readability // These aliases exist solely to increase code readability
using AppIdKey = String; using AppIdKey = String;

View File

@@ -9,7 +9,6 @@
#include <koalabox/logger.hpp> #include <koalabox/logger.hpp>
namespace koalageddon { namespace koalageddon {
const void* client_app_manager_interface = nullptr;
KoalageddonConfig config; // NOLINT(cert-err58-cpp) KoalageddonConfig config; // NOLINT(cert-err58-cpp)
@@ -56,6 +55,8 @@ namespace koalageddon {
} }
void init() { void init() {
// TODO: Load cached koalageddon config by default
std::thread( std::thread(
[]() { []() {
const auto kg_config_source = init_koalageddon_config(); const auto kg_config_source = init_koalageddon_config();

View File

@@ -26,9 +26,6 @@ namespace koalageddon {
) )
}; };
/// We need this interface in other IClient* functions in order to query original DLC status
extern const void* client_app_manager_interface;
extern KoalageddonConfig config; extern KoalageddonConfig config;
void init(); void init();

View File

@@ -1,5 +1,4 @@
#include <steam_impl/steam_apps.hpp> #include <steam_impl/steam_apps.hpp>
#include <koalageddon/koalageddon.hpp>
#include <koalageddon/steamclient/steamclient.hpp> #include <koalageddon/steamclient/steamclient.hpp>
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) { VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
@@ -32,8 +31,9 @@ VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
); );
}, },
[&](AppId_t dlc_id) { [&](AppId_t dlc_id) {
if (koalageddon::client_app_manager_interface) { const auto* app_manager_interface = koalageddon::steamclient::interface_name_to_address_map["IClientAppManager"];
IClientAppManager_IsAppDlcInstalled(koalageddon::client_app_manager_interface, EDX, appID, dlc_id); if (app_manager_interface) {
IClientAppManager_IsAppDlcInstalled(app_manager_interface, EDX, appID, dlc_id);
return true; return true;
} }

View File

@@ -1,10 +1,14 @@
#include <koalageddon/steamclient/steamclient.hpp> #include <koalageddon/steamclient/steamclient.hpp>
#include <steam_impl/steam_apps.hpp> #include <steam_impl/steam_apps.hpp>
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t app_id)) { VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) {
return steam_apps::IsDlcUnlocked(__func__, 0, app_id, [&]() { const auto* utils_interface = koalageddon::steamclient::interface_name_to_address_map["IClientUtils"];
const auto app_id = utils_interface ? IClientUtils_GetAppID(utils_interface, EDX) : 0;
return steam_apps::IsDlcUnlocked(__func__, app_id, dlc_id, [&]() {
GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp) GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp)
return IClientUser_BIsSubscribedApp_o(ARGS(app_id)); return IClientUser_BIsSubscribedApp_o(ARGS(dlc_id));
}); });
} }

View File

@@ -0,0 +1,7 @@
#include <koalageddon/steamclient/steamclient.hpp>
VIRTUAL(AppId_t) IClientUtils_GetAppID(PARAMS()) {
GET_ORIGINAL_HOOKED_FUNCTION(IClientUtils_GetAppID)
return IClientUtils_GetAppID_o(ARGS());
}

View File

@@ -10,6 +10,8 @@
namespace koalageddon::steamclient { namespace koalageddon::steamclient {
using namespace koalabox; using namespace koalabox;
Map<String, void*> interface_name_to_address_map; // NOLINT(cert-err58-cpp)
struct InstructionContext { struct InstructionContext {
std::optional<ZydisRegister> base_register; std::optional<ZydisRegister> base_register;
std::optional<String> function_name; std::optional<String> function_name;
@@ -24,6 +26,14 @@ namespace koalageddon::steamclient {
ZydisDecoder decoder = {}; ZydisDecoder decoder = {};
ZydisFormatter formatter = {}; ZydisFormatter formatter = {};
void construct_ordinal_map( // NOLINT(misc-no-recursion)
const String& target_interface,
Map<String, uint32_t>& map,
uintptr_t start_address,
Set<uintptr_t>& visited_addresses,
InstructionContext context
);
#define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \ #define HOOK_FUNCTION(INTERFACE, FUNC) hook::swap_virtual_func_or_throw( \
globals::address_map, \ globals::address_map, \
interface, \ interface, \
@@ -34,18 +44,20 @@ namespace koalageddon::steamclient {
#define SELECTOR_IMPLEMENTATION(INTERFACE, FUNC_BODY) \ #define SELECTOR_IMPLEMENTATION(INTERFACE, FUNC_BODY) \
DLL_EXPORT(void) INTERFACE##_Selector( \ DLL_EXPORT(void) INTERFACE##_Selector( \
const void* interface, \ void* interface, \
const void* arg2, \ void* arg2, \
const void* arg3, \ void* arg3, \
const void* arg4 \ void* arg4 \
) { \ ) { \
CALL_ONCE(FUNC_BODY) \ CALL_ONCE({ \
interface_name_to_address_map[#INTERFACE] = interface; \
[&]()FUNC_BODY(); \
}) \
GET_ORIGINAL_HOOKED_FUNCTION(INTERFACE##_Selector) \ GET_ORIGINAL_HOOKED_FUNCTION(INTERFACE##_Selector) \
INTERFACE##_Selector_o(interface, arg2, arg3, arg4); \ INTERFACE##_Selector_o(interface, arg2, arg3, arg4); \
} }
SELECTOR_IMPLEMENTATION(IClientAppManager, { SELECTOR_IMPLEMENTATION(IClientAppManager, {
koalageddon::client_app_manager_interface = interface;
HOOK_FUNCTION(IClientAppManager, IsAppDlcInstalled) HOOK_FUNCTION(IClientAppManager, IsAppDlcInstalled)
}) })
@@ -69,6 +81,36 @@ namespace koalageddon::steamclient {
HOOK_FUNCTION(IClientUser, BIsSubscribedApp) HOOK_FUNCTION(IClientUser, BIsSubscribedApp)
}) })
SELECTOR_IMPLEMENTATION(IClientUtils, {
HOOK_FUNCTION(IClientUtils, GetAppID)
})
#define CONSTRUCT_ORDINAL_MAP(INTERFACE) \
Set<uintptr_t> nested_visited_addresses; \
construct_ordinal_map( \
#INTERFACE, \
ordinal_map[#INTERFACE], \
function_selector_address, \
nested_visited_addresses, \
{} \
);
#define DETOUR_SELECTOR(INTERFACE) \
if(interface_name == #INTERFACE){ \
CONSTRUCT_ORDINAL_MAP(INTERFACE) \
DETOUR_ADDRESS(INTERFACE##_Selector, function_selector_address) \
}
void detour_interface_selector(const String& interface_name, uintptr_t function_selector_address) {
LOG_DEBUG("Detected interface: '{}'", interface_name)
DETOUR_SELECTOR(IClientAppManager)
DETOUR_SELECTOR(IClientApps)
DETOUR_SELECTOR(IClientInventory)
DETOUR_SELECTOR(IClientUser)
DETOUR_SELECTOR(IClientUtils)
}
uintptr_t get_absolute_address(ZydisDecodedInstruction instruction, uintptr_t address) { uintptr_t get_absolute_address(ZydisDecodedInstruction instruction, uintptr_t address) {
const auto operand = instruction.operands[0]; const auto operand = instruction.operands[0];
@@ -86,9 +128,9 @@ namespace koalageddon::steamclient {
const auto& operand = instruction.operands[0]; const auto& operand = instruction.operands[0];
return instruction.mnemonic == ZYDIS_MNEMONIC_PUSH && return instruction.mnemonic == ZYDIS_MNEMONIC_PUSH &&
operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE && operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
operand.visibility == ZYDIS_OPERAND_VISIBILITY_EXPLICIT && operand.visibility == ZYDIS_OPERAND_VISIBILITY_EXPLICIT &&
operand.encoding == ZYDIS_OPERAND_ENCODING_SIMM16_32_32; operand.encoding == ZYDIS_OPERAND_ENCODING_SIMM16_32_32;
} }
std::optional<String> get_string_argument(const ZydisDecodedInstruction& instruction) { std::optional<String> get_string_argument(const ZydisDecodedInstruction& instruction) {
@@ -142,9 +184,9 @@ namespace koalageddon::steamclient {
const auto is_mov_base_esp = [](const ZydisDecodedInstruction& instruction) { const auto is_mov_base_esp = [](const ZydisDecodedInstruction& instruction) {
return instruction.mnemonic == ZYDIS_MNEMONIC_MOV && return instruction.mnemonic == ZYDIS_MNEMONIC_MOV &&
instruction.operand_count == 2 && instruction.operand_count == 2 &&
instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instruction.operands[1].reg.value == ZYDIS_REGISTER_ESP; instruction.operands[1].reg.value == ZYDIS_REGISTER_ESP;
}; };
// Initialize with a dummy previous instruction // Initialize with a dummy previous instruction
@@ -169,8 +211,8 @@ namespace koalageddon::steamclient {
// Save base register // Save base register
context.base_register = instruction.operands[0].reg.value; context.base_register = instruction.operands[0].reg.value;
} else if (is_push_immediate(last_instruction) && } else if (is_push_immediate(last_instruction) &&
is_push_immediate(instruction) && is_push_immediate(instruction) &&
!context.function_name) { !context.function_name) {
// The very first 2 consecutive pushes indicate interface and function names. // The very first 2 consecutive pushes indicate interface and function names.
// However, subsequent pushes may contain irrelevant strings. // However, subsequent pushes may contain irrelevant strings.
const auto push_string_1 = get_string_argument(last_instruction); const auto push_string_1 = get_string_argument(last_instruction);
@@ -183,7 +225,7 @@ namespace koalageddon::steamclient {
context.function_name = push_string_1; context.function_name = push_string_1;
} }
if (map.contains(*context.function_name)) { if (context.function_name && map.contains(*context.function_name)) {
// Bail early to avoid duplicate work // Bail early to avoid duplicate work
return; return;
} }
@@ -199,7 +241,7 @@ namespace koalageddon::steamclient {
// But not continue forward, in order to avoid duplicate processing // But not continue forward, in order to avoid duplicate processing
return; return;
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP && } else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) { instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) {
// On unconditional jump we should recurse as well // On unconditional jump we should recurse as well
const auto jump_destination = get_absolute_address(instruction, current_address); const auto jump_destination = get_absolute_address(instruction, current_address);
@@ -304,22 +346,6 @@ namespace koalageddon::steamclient {
return std::nullopt; return std::nullopt;
} }
#define CONSTRUCT_ORDINAL_MAP(INTERFACE) \
Set<uintptr_t> nested_visited_addresses; \
construct_ordinal_map( \
#INTERFACE, \
ordinal_map[#INTERFACE], \
function_selector_address, \
nested_visited_addresses, \
{} \
);
#define DETOUR_SELECTOR(INTERFACE) \
if(interface_name == #INTERFACE){ \
CONSTRUCT_ORDINAL_MAP(INTERFACE) \
DETOUR_ADDRESS(INTERFACE##_Selector, function_selector_address) \
}
void process_interface_selector( // NOLINT(misc-no-recursion) void process_interface_selector( // NOLINT(misc-no-recursion)
const uintptr_t start_address, const uintptr_t start_address,
Set<uintptr_t>& visited_addresses Set<uintptr_t>& visited_addresses
@@ -360,12 +386,7 @@ namespace koalageddon::steamclient {
if (interface_name_opt) { if (interface_name_opt) {
const auto& interface_name = *interface_name_opt; const auto& interface_name = *interface_name_opt;
LOG_DEBUG("Detected interface: '{}'", interface_name) detour_interface_selector(interface_name, function_selector_address);
DETOUR_SELECTOR(IClientAppManager)
DETOUR_SELECTOR(IClientApps)
DETOUR_SELECTOR(IClientInventory)
DETOUR_SELECTOR(IClientUser)
} }
} else if (instruction.meta.category == ZYDIS_CATEGORY_COND_BR) { } else if (instruction.meta.category == ZYDIS_CATEGORY_COND_BR) {
const auto jump_taken_destination = get_absolute_address(instruction, current_address); const auto jump_taken_destination = get_absolute_address(instruction, current_address);
@@ -386,9 +407,9 @@ namespace koalageddon::steamclient {
LOG_TRACE("Breaking recursion due to unconditional branch") LOG_TRACE("Breaking recursion due to unconditional branch")
return; return;
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP && } else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
operand.type == ZYDIS_OPERAND_TYPE_MEMORY && operand.type == ZYDIS_OPERAND_TYPE_MEMORY &&
operand.mem.scale == sizeof(uintptr_t) && operand.mem.scale == sizeof(uintptr_t) &&
operand.mem.disp.has_displacement operand.mem.disp.has_displacement
) { ) {
// Special handling for jump tables. Guaranteed to be present in the interface selector. // Special handling for jump tables. Guaranteed to be present in the interface selector.
const auto* table = (uintptr_t*) operand.mem.disp.value; const auto* table = (uintptr_t*) operand.mem.disp.value;
@@ -433,4 +454,5 @@ namespace koalageddon::steamclient {
Set<uintptr_t> visited_addresses; Set<uintptr_t> visited_addresses;
process_interface_selector(interface_selector_address, visited_addresses); process_interface_selector(interface_selector_address, visited_addresses);
} }
} }

View File

@@ -26,8 +26,14 @@ VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint
// IClientUser // IClientUser
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t)); VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t));
// IClientUtils
VIRTUAL(AppId_t) IClientUtils_GetAppID(PARAMS());
namespace koalageddon::steamclient { namespace koalageddon::steamclient {
/// We need this interface in other IClient* functions in order to call other functions
extern Map<String, void*> interface_name_to_address_map;
void process_client_engine(uintptr_t interface); void process_client_engine(uintptr_t interface);
} }

View File

@@ -13,25 +13,34 @@ namespace smoke_api::config {
if (exists(path)) { if (exists(path)) {
try { try {
instance = Json::parse(koalabox::io::read_file(path)).get<Config>(); const auto config_str = koalabox::io::read_file(path);
LOG_DEBUG("Parsing config:\n{}", config_str)
instance = Json::parse(config_str).get<Config>();
} catch (const Exception& e) { } catch (const Exception& e) {
koalabox::util::panic("Error parsing config: {}", e.what()); const auto message = fmt::format("Error parsing config file: {}", e.what());
koalabox::util::error_box("SmokeAPI Error", message);
} }
} }
} }
bool is_dlc_unlocked(AppId_t app_id, AppId_t dlc_id, const Function<bool()>& original_function) { Vector<DLC> get_extra_dlcs(AppId_t app_id) {
const auto app_id_str = std::to_string(app_id); return DLC::get_dlcs_from_apps(instance.extra_dlcs, app_id);
const auto dlc_id_str = std::to_string(dlc_id); }
bool is_dlc_unlocked(AppId_t app_id, AppId_t dlc_id, const Function<bool()>& original_function) {
auto status = instance.default_app_status; auto status = instance.default_app_status;
const auto app_id_str = std::to_string(app_id);
if (instance.override_app_status.contains(app_id_str)) { if (instance.override_app_status.contains(app_id_str)) {
status = instance.override_app_status[app_id_str]; status = instance.override_app_status[app_id_str];
} }
if (instance.override_app_status.contains(dlc_id_str)) { const auto dlc_id_str = std::to_string(dlc_id);
status = instance.override_app_status[dlc_id_str]; if (instance.override_dlc_status.contains(dlc_id_str)) {
status = instance.override_dlc_status[dlc_id_str];
} }
bool is_unlocked; bool is_unlocked;
@@ -47,15 +56,18 @@ namespace smoke_api::config {
is_unlocked = original_function(); is_unlocked = original_function();
break; break;
} }
LOG_TRACE( LOG_TRACE(
"App ID: {}, DLC ID: {}, Status: {}, Original: {}, Is Unlocked: {}", "App ID: {}, DLC ID: {}, Status: {}, Original: {}, Unlocked: {}",
app_id_str, dlc_id_str, Json(status).dump(), original_function(), is_unlocked app_id_str, dlc_id_str, Json(status).dump(), original_function(), is_unlocked
) )
return is_unlocked; return is_unlocked;
} }
Vector<DLC> get_extra_dlcs(AppId_t app_id) { DLL_EXPORT(void) ReloadConfig() {
return DLC::get_dlcs_from_apps(instance.extra_dlcs, app_id); LOG_INFO("Reloading config")
init();
} }
} }

View File

@@ -25,6 +25,7 @@ namespace smoke_api::config {
bool unlock_family_sharing = true; bool unlock_family_sharing = true;
AppStatus default_app_status = AppStatus::UNLOCKED; AppStatus default_app_status = AppStatus::UNLOCKED;
Map<String, AppStatus> override_app_status; Map<String, AppStatus> override_app_status;
Map<String, AppStatus> override_dlc_status;
AppDlcNameMap extra_dlcs; AppDlcNameMap extra_dlcs;
bool auto_inject_inventory = true; bool auto_inject_inventory = true;
Vector<uint32_t> extra_inventory_items; Vector<uint32_t> extra_inventory_items;
@@ -38,6 +39,7 @@ namespace smoke_api::config {
unlock_family_sharing, unlock_family_sharing,
default_app_status, default_app_status,
override_app_status, override_app_status,
override_dlc_status,
extra_dlcs, extra_dlcs,
auto_inject_inventory, auto_inject_inventory,
extra_inventory_items, extra_inventory_items,
@@ -49,7 +51,7 @@ namespace smoke_api::config {
void init(); void init();
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const Function<bool()>& original_function);
Vector<DLC> get_extra_dlcs(AppId_t app_id); Vector<DLC> get_extra_dlcs(AppId_t app_id);
bool is_dlc_unlocked(uint32_t app_id, uint32_t dlc_id, const Function<bool()>& original_function);
} }

View File

@@ -128,4 +128,5 @@ namespace smoke_api {
LOG_ERROR("Shutdown error: {}", ex.what()) LOG_ERROR("Shutdown error: {}", ex.what())
} }
} }
} }

View File

@@ -3,26 +3,27 @@
#include <core/types.hpp> #include <core/types.hpp>
// Flat // Flat
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(ISteamApps*, AppId_t); DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void*, AppId_t);
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(ISteamApps*, AppId_t); DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void*, AppId_t);
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps*); DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void*);
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(ISteamApps*, int, AppId_t*, bool*, char*, int); DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(void*, int, AppId_t*, bool*, char*, int);
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(ISteamUser*, CSteamID, AppId_t);
DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(ISteamClient*, HSteamUser, HSteamPipe, const char*); DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(void*, HSteamUser, HSteamPipe, const char*);
DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(ISteamInventory*, SteamInventoryResult_t);
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems( DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(void*, SteamInventoryResult_t);
ISteamInventory*, SteamInventoryResult_t, SteamItemDetails_t*, uint32_t* DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(void*, SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*);
);
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
ISteamInventory*, SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t* void*, SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*
); );
DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(ISteamInventory*, SteamInventoryResult_t, CSteamID); DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(void*, SteamInventoryResult_t, CSteamID);
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(ISteamInventory*, SteamInventoryResult_t*); DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(void*, SteamInventoryResult_t*);
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
ISteamInventory*, SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t void*, SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t
); );
DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(ISteamInventory*, SteamInventoryResult_t, void*, uint32_t*); DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(void*, SteamInventoryResult_t, void*, uint32_t*);
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(ISteamInventory*, SteamItemDef_t*, uint32_t*); DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(void*, SteamItemDef_t*, uint32_t*);
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(void*, CSteamID, AppId_t);
// Internal // Internal
DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser, const char*); DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser, const char*);

View File

@@ -3,30 +3,31 @@
#include <steam_impl/steam_client.hpp> #include <steam_impl/steam_client.hpp>
#include <steam_impl/steam_inventory.hpp> #include <steam_impl/steam_inventory.hpp>
#include <steam_impl/steam_user.hpp> #include <steam_impl/steam_user.hpp>
#include <steam_impl/steam_impl.hpp>
// ISteamApps // ISteamApps
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(ISteamApps* self, AppId_t appID) { DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) {
return steam_apps::IsDlcUnlocked( return steam_apps::IsDlcUnlocked(
__func__, 0, appID, [&]() { __func__, 0, dlcID, [&]() {
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp) GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp)
return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, appID); return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, dlcID);
} }
); );
} }
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(ISteamApps* self, AppId_t appID) { DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, AppId_t dlcID) {
return steam_apps::IsDlcUnlocked( return steam_apps::IsDlcUnlocked(
__func__, 0, appID, [&]() { __func__, 0, dlcID, [&]() {
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled) GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled)
return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, appID); return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, dlcID);
} }
); );
} }
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps* self) { DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void* self) {
return steam_apps::GetDLCCount( return steam_apps::GetDLCCount(
__func__, 0, [&]() { __func__, 0, [&]() {
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount) GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount)
@@ -37,7 +38,7 @@ DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps* self) {
} }
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex( DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
ISteamApps* self, void* self,
int iDLC, int iDLC,
AppId_t* pDlcID, AppId_t* pDlcID,
bool* pbAvailable, bool* pbAvailable,
@@ -59,26 +60,10 @@ DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(
); );
} }
// ISteamUser
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(
ISteamUser* self,
CSteamID steamID,
AppId_t appID
) {
return steam_user::UserHasLicenseForApp(
__func__, appID, [&]() {
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, appID);
}
);
}
// ISteamClient // ISteamClient
DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface( DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(
ISteamClient* self, void* self,
HSteamUser hSteamUser, HSteamUser hSteamUser,
HSteamPipe hSteamPipe, HSteamPipe hSteamPipe,
const char* pchVersion const char* pchVersion
@@ -95,7 +80,7 @@ DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(
// ISteamInventory // ISteamInventory
DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus( DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(
ISteamInventory* self, void* self,
SteamInventoryResult_t resultHandle SteamInventoryResult_t resultHandle
) { ) {
return steam_inventory::GetResultStatus( return steam_inventory::GetResultStatus(
@@ -108,7 +93,7 @@ DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
ISteamInventory* self, void* self,
SteamInventoryResult_t resultHandle, SteamInventoryResult_t resultHandle,
SteamItemDetails_t* pOutItemsArray, SteamItemDetails_t* pOutItemsArray,
uint32_t* punOutItemsArraySize uint32_t* punOutItemsArraySize
@@ -129,7 +114,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
ISteamInventory* self, void* self,
SteamInventoryResult_t resultHandle, SteamInventoryResult_t resultHandle,
uint32_t unItemIndex, uint32_t unItemIndex,
const char* pchPropertyName, const char* pchPropertyName,
@@ -148,7 +133,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID( DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(
ISteamInventory* self, void* self,
SteamInventoryResult_t resultHandle, SteamInventoryResult_t resultHandle,
CSteamID steamIDExpected CSteamID steamIDExpected
) { ) {
@@ -162,7 +147,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(
ISteamInventory* self, void* self,
SteamInventoryResult_t* pResultHandle SteamInventoryResult_t* pResultHandle
) { ) {
return steam_inventory::GetAllItems( return steam_inventory::GetAllItems(
@@ -175,7 +160,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
ISteamInventory* self, void* self,
SteamInventoryResult_t* pResultHandle, SteamInventoryResult_t* pResultHandle,
const SteamItemInstanceID_t* pInstanceIDs, const SteamItemInstanceID_t* pInstanceIDs,
uint32_t unCountInstanceIDs uint32_t unCountInstanceIDs
@@ -190,7 +175,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult( DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(
ISteamInventory* self, void* self,
SteamInventoryResult_t resultHandle, SteamInventoryResult_t resultHandle,
void* pOutBuffer, void* pOutBuffer,
uint32_t* punOutBufferSize uint32_t* punOutBufferSize
@@ -205,7 +190,7 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(
} }
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs( DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
ISteamInventory* self, void* self,
SteamItemDef_t* pItemDefIDs, SteamItemDef_t* pItemDefIDs,
uint32_t* punItemDefIDsArraySize uint32_t* punItemDefIDsArraySize
) { ) {
@@ -217,3 +202,19 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
} }
); );
} }
// ISteamUser
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(
void* self,
CSteamID steamID,
AppId_t dlcID
) {
return steam_user::UserHasLicenseForApp(
__func__, steam_impl::get_app_id_or_throw(), dlcID, [&]() {
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, dlcID);
}
);
}

View File

@@ -1,12 +1,13 @@
#include <steam_api_virtuals/steam_api_virtuals.hpp> #include <steam_api_virtuals/steam_api_virtuals.hpp>
#include <steam_impl/steam_user.hpp> #include <steam_impl/steam_user.hpp>
#include <steam_impl/steam_impl.hpp>
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t appID)) { VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t dlcID)) {
return steam_user::UserHasLicenseForApp( return steam_user::UserHasLicenseForApp(
__func__, appID, [&]() { __func__, steam_impl::get_app_id_or_throw(), dlcID, [&]() {
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp) GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, appID)); return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, dlcID));
} }
); );
} }

View File

@@ -193,4 +193,5 @@ namespace steam_apps {
return false; return false;
} }
} }
} }

View File

@@ -16,7 +16,6 @@ namespace steam_inventory {
return status; return status;
} }
// TODO: investigate if we can get app id in koalageddon mode
bool GetResultItems( bool GetResultItems(
const String& function_name, const String& function_name,
const SteamInventoryResult_t resultHandle, const SteamInventoryResult_t resultHandle,

View File

@@ -6,23 +6,24 @@ namespace steam_user {
EUserHasLicenseForAppResult UserHasLicenseForApp( EUserHasLicenseForAppResult UserHasLicenseForApp(
const String& function_name, const String& function_name,
AppId_t appID, AppId_t appId,
AppId_t dlcId,
const Function<EUserHasLicenseForAppResult()>& original_function const Function<EUserHasLicenseForAppResult()>& original_function
) { ) {
const auto result = original_function(); const auto result = original_function();
if (result == k_EUserHasLicenseResultNoAuth) { if (result == k_EUserHasLicenseResultNoAuth) {
LOG_WARN("{} -> App ID: {:>8}, Result: NoAuth", function_name, appID) LOG_WARN("{} -> App ID: {:>8}, Result: NoAuth", function_name, dlcId)
return result; return result;
} }
const auto has_license = smoke_api::config::is_dlc_unlocked( const auto has_license = smoke_api::config::is_dlc_unlocked(
0, appID, [&]() { appId, dlcId, [&]() {
return result == k_EUserHasLicenseResultHasLicense; return result == k_EUserHasLicenseResultHasLicense;
} }
); );
LOG_INFO("{} -> App ID: {:>8}, HasLicense: {}", function_name, appID, has_license) LOG_INFO("{} -> App ID: {:>8}, HasLicense: {}", function_name, dlcId, has_license)
return has_license return has_license
? k_EUserHasLicenseResultHasLicense ? k_EUserHasLicenseResultHasLicense

View File

@@ -1,13 +1,13 @@
#pragma once #pragma once
#include <core/types.hpp> #include <core/types.hpp>
#include <koalabox/core.hpp>
namespace steam_user { namespace steam_user {
EUserHasLicenseForAppResult UserHasLicenseForApp( EUserHasLicenseForAppResult UserHasLicenseForApp(
const String& function_name, const String& function_name,
AppId_t appID, AppId_t appId,
AppId_t dlcId,
const Function<EUserHasLicenseForAppResult()>& original_function const Function<EUserHasLicenseForAppResult()>& original_function
); );