From dc086e40e09d5c51196fa41817787d231d858f35 Mon Sep 17 00:00:00 2001 From: acidicoala <67734819+acidicoala@users.noreply.github.com> Date: Sat, 23 Aug 2025 13:44:17 +0500 Subject: [PATCH] Split static & shared lib --- .gitmodules | 2 +- CMakeLists.txt | 137 +++--- KoalaBox | 2 +- res/extra_build_config.gen.h | 1 - src/exports/steam_api.cpp | 28 -- src/exports/steam_api_flat.cpp | 395 ------------------ src/exports/steam_api_internal.cpp | 40 -- src/main.cpp | 3 +- src/{smoke_api => }/smoke_api.cpp | 28 +- src/smoke_api.hpp | 36 ++ src/smoke_api/globals.cpp | 4 - src/smoke_api/globals.hpp | 6 - src/smoke_api/smoke_api.hpp | 7 - src/smoke_api/types.hpp | 141 ------- src/steam_api/exports/steam_api.cpp | 23 + src/steam_api/exports/steam_api_flat.cpp | 296 +++++++++++++ src/steam_api/exports/steam_api_internal.cpp | 22 + .../exports/steam_api_unversioned.cpp | 69 +-- .../steam_client.cpp | 3 +- .../steam_client.hpp | 2 +- .../steam_interface.cpp | 32 +- .../steam_interface.hpp | 1 - src/steam_api/virtuals/isteamapps.cpp | 79 ++++ src/steam_api/virtuals/isteamclient.cpp | 87 ++++ src/steam_api/virtuals/isteaminventory.cpp | 144 +++++++ src/steam_api/virtuals/isteamuser.cpp | 23 + src/steam_api/virtuals/steam_api_virtuals.hpp | 70 ++++ src/{exports => steamclient}/steamclient.cpp | 12 +- src/{exports => steamclient}/steamclient.hpp | 2 +- src/virtuals/isteamapps.cpp | 98 ----- src/virtuals/isteamclient.cpp | 106 ----- src/virtuals/isteaminventory.cpp | 166 -------- src/virtuals/isteamuser.cpp | 27 -- src/virtuals/steam_api_virtuals.hpp | 64 --- {src => static}/smoke_api/api.cpp | 14 +- {src => static}/smoke_api/api.hpp | 6 +- {src => static}/smoke_api/cache.cpp | 4 +- {src => static}/smoke_api/cache.hpp | 0 {src => static}/smoke_api/config.cpp | 19 +- {src => static}/smoke_api/config.hpp | 10 +- .../smoke_api/interfaces}/steam_apps.cpp | 26 +- .../smoke_api/interfaces}/steam_apps.hpp | 3 +- .../smoke_api/interfaces}/steam_inventory.cpp | 14 +- .../smoke_api/interfaces}/steam_inventory.hpp | 8 +- .../smoke_api/interfaces}/steam_user.cpp | 12 +- .../smoke_api/interfaces}/steam_user.hpp | 4 +- {src => static}/smoke_api/types.cpp | 7 +- static/smoke_api/types.hpp | 83 ++++ 48 files changed, 1048 insertions(+), 1318 deletions(-) delete mode 100644 src/exports/steam_api.cpp delete mode 100644 src/exports/steam_api_flat.cpp delete mode 100644 src/exports/steam_api_internal.cpp rename src/{smoke_api => }/smoke_api.cpp (84%) create mode 100644 src/smoke_api.hpp delete mode 100644 src/smoke_api/globals.cpp delete mode 100644 src/smoke_api/globals.hpp delete mode 100644 src/smoke_api/smoke_api.hpp delete mode 100644 src/smoke_api/types.hpp create mode 100644 src/steam_api/exports/steam_api.cpp create mode 100644 src/steam_api/exports/steam_api_flat.cpp create mode 100644 src/steam_api/exports/steam_api_internal.cpp rename src/{ => steam_api}/exports/steam_api_unversioned.cpp (60%) rename src/{steam_interface => steam_api}/steam_client.cpp (84%) rename src/{steam_interface => steam_api}/steam_client.hpp (87%) rename src/{steam_interface => steam_api}/steam_interface.cpp (97%) rename src/{steam_interface => steam_api}/steam_interface.hpp (99%) create mode 100644 src/steam_api/virtuals/isteamapps.cpp create mode 100644 src/steam_api/virtuals/isteamclient.cpp create mode 100644 src/steam_api/virtuals/isteaminventory.cpp create mode 100644 src/steam_api/virtuals/isteamuser.cpp create mode 100644 src/steam_api/virtuals/steam_api_virtuals.hpp rename src/{exports => steamclient}/steamclient.cpp (51%) rename src/{exports => steamclient}/steamclient.hpp (58%) delete mode 100644 src/virtuals/isteamapps.cpp delete mode 100644 src/virtuals/isteamclient.cpp delete mode 100644 src/virtuals/isteaminventory.cpp delete mode 100644 src/virtuals/isteamuser.cpp delete mode 100644 src/virtuals/steam_api_virtuals.hpp rename {src => static}/smoke_api/api.cpp (81%) rename {src => static}/smoke_api/api.hpp (75%) rename {src => static}/smoke_api/cache.cpp (96%) rename {src => static}/smoke_api/cache.hpp (100%) rename {src => static}/smoke_api/config.cpp (84%) rename {src => static}/smoke_api/config.hpp (93%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_apps.cpp (91%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_apps.hpp (90%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_inventory.cpp (95%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_inventory.hpp (92%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_user.cpp (85%) rename {src/steam_interface => static/smoke_api/interfaces}/steam_user.hpp (88%) rename {src => static}/smoke_api/types.cpp (81%) create mode 100644 static/smoke_api/types.hpp diff --git a/.gitmodules b/.gitmodules index 5886685..b8ce744 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "KoalaBox"] path = KoalaBox - url = ../../acidicoala/KoalaBox.git + url = ../KoalaBox.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1739026..4bd7aa3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,83 +5,98 @@ project(SmokeAPI VERSION 3.0.0) include(KoalaBox/cmake/KoalaBox.cmake) add_subdirectory(KoalaBox EXCLUDE_FROM_ALL) +add_subdirectory(tools) set_32_and_64(STEAMAPI_DLL steam_api) set_32_and_64(STEAMCLIENT_DLL steamclient) -set_32_and_64(VSTDLIB_DLL vstdlib_s) - -configure_version_resource("Free DLC for everyone ʕ ᵔᴥᵔʔ") - -# Setup linker exports - set_32_and_64(STEAM_API_DLL steam_api.dll steam_api64.dll) -set( - STEAM_API_EXPORTS - src/game_mode/exports/steam_api.cpp - src/game_mode/exports/steam_api_flat.cpp - src/game_mode/exports/steam_api_internal.cpp - src/game_mode/exports/steam_api_unversioned.cpp -) - configure_build_config(extra_build_config) -set( - SMOKE_API_SOURCES - src/exports/steamclient.cpp - src/exports/steamclient.hpp - src/exports/steam_api.cpp - src/exports/steam_api_flat.cpp - src/exports/steam_api_internal.cpp - src/exports/steam_api_unversioned.cpp - src/virtuals/isteamapps.cpp - src/virtuals/isteamclient.cpp - src/virtuals/isteaminventory.cpp - src/virtuals/isteamuser.cpp - src/virtuals/steam_api_virtuals.hpp - src/smoke_api/cache.cpp - src/smoke_api/cache.hpp - src/smoke_api/config.cpp - src/smoke_api/config.hpp - src/smoke_api/smoke_api.cpp - src/smoke_api/smoke_api.hpp - src/smoke_api/api.cpp - src/smoke_api/api.hpp - src/smoke_api/globals.cpp - src/smoke_api/globals.hpp - src/smoke_api/types.cpp - src/smoke_api/types.hpp - src/steam_interface/steam_apps.cpp - src/steam_interface/steam_apps.hpp - src/steam_interface/steam_client.cpp - src/steam_interface/steam_client.hpp - src/steam_interface/steam_interface.cpp - src/steam_interface/steam_interface.hpp - src/steam_interface/steam_inventory.cpp - src/steam_interface/steam_inventory.hpp - src/steam_interface/steam_user.cpp - src/steam_interface/steam_user.hpp - src/main.cpp - ${GENERATED_LINKER_EXPORTS} +set(SMOKE_API_STATIC_SOURCES + static/smoke_api/interfaces/steam_apps.hpp + static/smoke_api/interfaces/steam_apps.cpp + static/smoke_api/interfaces/steam_inventory.hpp + static/smoke_api/interfaces/steam_inventory.cpp + static/smoke_api/interfaces/steam_user.hpp + static/smoke_api/interfaces/steam_user.cpp + static/smoke_api/api.hpp + static/smoke_api/api.cpp + static/smoke_api/cache.hpp + static/smoke_api/cache.cpp + static/smoke_api/config.hpp + static/smoke_api/config.cpp + static/smoke_api/types.hpp + static/smoke_api/types.cpp ) -add_library(SmokeAPI SHARED ${SMOKE_API_SOURCES} ${VERSION_RESOURCE}) +set(SMOKE_API_SOURCES + ${SMOKE_API_STATIC_SOURCES} + src/steam_api/exports/steam_api.cpp + src/steam_api/exports/steam_api_flat.cpp + src/steam_api/exports/steam_api_internal.cpp + src/steam_api/exports/steam_api_unversioned.cpp + src/steam_api/virtuals/isteamapps.cpp + src/steam_api/virtuals/isteamclient.cpp + src/steam_api/virtuals/isteaminventory.cpp + src/steam_api/virtuals/isteamuser.cpp + src/steam_api/virtuals/steam_api_virtuals.hpp + src/steam_api/steam_client.hpp + src/steam_api/steam_client.cpp + src/steam_api/steam_interface.cpp + src/steam_api/steam_interface.hpp + src/steamclient/steamclient.cpp + src/steamclient/steamclient.hpp + src/main.cpp + src/smoke_api.cpp + src/smoke_api.hpp +) + +### SmokeAPI interface + +add_library(SmokeAPI_interface INTERFACE) # There is a weird MSVC bug where c++23 features are not enabled in x64 builds, # while they are available in x86. I've no idea what causes this discrepancy, # but manually setting the MSVC compiler option fixes this issue. -target_compile_options(SmokeAPI PRIVATE /std:c++latest) +#target_compile_options(SmokeAPI_interface PUBLIC /std:c++latest) -target_include_directories(SmokeAPI PUBLIC "$") +target_include_directories(SmokeAPI_interface INTERFACE + "$" +) +target_link_libraries(SmokeAPI_interface INTERFACE KoalaBox $) + + +### Static SmokeAPI + +add_library(SmokeAPI_static STATIC ${SMOKE_API_STATIC_SOURCES}) +target_link_libraries(SmokeAPI_static PUBLIC SmokeAPI_interface) +target_include_directories(SmokeAPI_static PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/static") + +### Shared SmokeAPI + +add_library(SmokeAPI SHARED ${SMOKE_API_SOURCES}) +target_link_libraries(SmokeAPI PUBLIC SmokeAPI_interface) +set_target_properties(SmokeAPI PROPERTIES RUNTIME_OUTPUT_NAME ${STEAMAPI_DLL}) +configure_version_resource(SmokeAPI "Free DLC for everyone ʕ ᵔᴥᵔʔ") +target_include_directories(SmokeAPI PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src" + "${CMAKE_CURRENT_SOURCE_DIR}/static" + "${CMAKE_CURRENT_BINARY_DIR}") + +set(B_PRODUCTION_MODE ON) +CPMAddPackage("gh:batterycenter/embed@1.2.19") +b_embed(SmokeAPI "res/interface_lookup.json") configure_linker_exports( TARGET SmokeAPI HEADER_NAME "linker_exports_for_steam_api" FORWARDED_DLL "${STEAMAPI_DLL}_o" - INPUT_SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/exports" + INPUT_SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/steam_api/exports" DLL_FILES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/res/steamworks/*/binaries/${STEAM_API_DLL}" ) +# TODO: Why not add other compatible DLLs? configure_linker_exports( TARGET SmokeAPI HEADER_NAME "linker_exports_for_version" @@ -89,15 +104,3 @@ configure_linker_exports( INPUT_SOURCES_DIR "" DLL_FILES_GLOB "C:/Windows/System32/version.dll" ) - -configure_output_name(${STEAMAPI_DLL}) - -configure_include_directories() - -target_link_libraries(SmokeAPI PRIVATE KoalaBox) - -set(B_PRODUCTION_MODE ON) -CPMAddPackage("gh:batterycenter/embed@1.2.19") -b_embed(SmokeAPI "res/interface_lookup.json") - -add_subdirectory(tools) diff --git a/KoalaBox b/KoalaBox index 96bb86e..06fa530 160000 --- a/KoalaBox +++ b/KoalaBox @@ -1 +1 @@ -Subproject commit 96bb86e91c0dd1852f1259ef6dcd346d1f8ab3fe +Subproject commit 06fa5304b3fd9e546159f980b2440a808e9ae6a9 diff --git a/res/extra_build_config.gen.h b/res/extra_build_config.gen.h index 6fa6a2c..2a4049f 100644 --- a/res/extra_build_config.gen.h +++ b/res/extra_build_config.gen.h @@ -2,4 +2,3 @@ #define STEAMAPI_DLL "${STEAMAPI_DLL}" #define STEAMCLIENT_DLL "${STEAMCLIENT_DLL}" -#define VSTDLIB_DLL "${VSTDLIB_DLL}" diff --git a/src/exports/steam_api.cpp b/src/exports/steam_api.cpp deleted file mode 100644 index 22a210e..0000000 --- a/src/exports/steam_api.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -#include "smoke_api/config.hpp" -#include "smoke_api/globals.hpp" - -// TODO: Detour in hook mode -DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary -( -const uint32_t unOwnAppID -) - { - if(smoke_api::config::instance.override_app_id != 0) { - LOG_DEBUG("{} -> {}. Preventing app restart", unOwnAppID, __func__); - return false; - } - - return ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_RestartAppIfNecessary)(unOwnAppID); -} - -DLL_EXPORT(void) SteamAPI_Shutdown -( -) - { - LOG_INFO("{} -> Game requested shutdown", __func__); - - ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_Shutdown)(); -} \ No newline at end of file diff --git a/src/exports/steam_api_flat.cpp b/src/exports/steam_api_flat.cpp deleted file mode 100644 index 4a80395..0000000 --- a/src/exports/steam_api_flat.cpp +++ /dev/null @@ -1,395 +0,0 @@ -#include -#include - -#include "smoke_api/types.hpp" -#include "smoke_api/globals.hpp" -#include "steam_interface/steam_apps.hpp" -#include "steam_interface/steam_client.hpp" -#include "steam_interface/steam_interface.hpp" -#include "steam_interface/steam_inventory.hpp" -#include "steam_interface/steam_user.hpp" - -// ISteamApps - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp -( -void *self, AppId_t dlcID -) - { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::IsDlcUnlocked( - __func__, - app_id, - dlcID, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsSubscribedApp) - - return SteamAPI_ISteamApps_BIsSubscribedApp_o(self, dlcID); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled -( -void *self, AppId_t dlcID -) - { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::IsDlcUnlocked( - __func__, - app_id, - dlcID, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BIsDlcInstalled) - - return SteamAPI_ISteamApps_BIsDlcInstalled_o(self, dlcID); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount -( -void* self -) - { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::GetDLCCount( - __func__, - app_id, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_GetDLCCount) - - return SteamAPI_ISteamApps_GetDLCCount_o(self); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return 0; - } -} - -DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex -( - -void *self, - -int iDLC, - AppId_t*pDlcID, - -bool *pbAvailable, - -char *pchName, - -int cchNameBufferSize -) - { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::GetDLCDataByIndex( - __func__, - app_id, - iDLC, - pDlcID, - pbAvailable, - pchName, - cchNameBufferSize, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamApps_BGetDLCDataByIndex) - return SteamAPI_ISteamApps_BGetDLCDataByIndex_o( - self, - iDLC, - pDlcID, - pbAvailable, - pchName, - cchNameBufferSize - ); - }, - [&](AppId_t dlc_id) { - return SteamAPI_ISteamApps_BIsDlcInstalled(self, dlc_id); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} - -// ISteamClient - -DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface -( - -void *self, - HSteamUser hSteamUser, - HSteamPipe hSteamPipe, - -const char* pchVersion -) - { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamClient_GetISteamGenericInterface) - return SteamAPI_ISteamClient_GetISteamGenericInterface_o( - self, - hSteamUser, - hSteamPipe, - pchVersion - ); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} - -// ISteamInventory - -DLL_EXPORT (EResult) SteamAPI_ISteamInventory_GetResultStatus( - void* self, - SteamInventoryResult_t resultHandle - ) { - return steam_inventory::GetResultStatus( - __func__, - resultHandle, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetResultStatus) - - return SteamAPI_ISteamInventory_GetResultStatus_o(self, resultHandle); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs -( - - -void *self, - SteamItemDef_t*pItemDefIDs, - uint32_t*punItemDefIDsArraySize -) - { - return steam_inventory::GetItemDefinitionIDs( - __func__, - pItemDefIDs, - punItemDefIDsArraySize, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs) - - return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o( - self, - pItemDefIDs, - punItemDefIDsArraySize - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems -( - - -void *self, - SteamInventoryResult_t resultHandle, - SteamItemDetails_t*pOutItemsArray, - uint32_t*punOutItemsArraySize -) - { - return steam_inventory::GetResultItems( - __func__, - resultHandle, - pOutItemsArray, - punOutItemsArraySize, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetResultItems) - - return SteamAPI_ISteamInventory_GetResultItems_o( - self, - resultHandle, - pOutItemsArray, - punOutItemsArraySize - ); - }, - [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs) - - return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o( - self, - pItemDefIDs, - punItemDefIDsArraySize - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty -( - -void *self, - SteamInventoryResult_t resultHandle, - uint32_t unItemIndex, - -const char *pchPropertyName, - -char *pchValueBuffer, - uint32_t*punValueBufferSizeOut -) - { - return steam_inventory::GetResultItemProperty( - __func__, - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetResultItemProperty) - - return SteamAPI_ISteamInventory_GetResultItemProperty_o( - self, - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID -( - -void *self, - SteamInventoryResult_t resultHandle, - CSteamID steamIDExpected -) - { - return steam_inventory::CheckResultSteamID( - __func__, - resultHandle, - steamIDExpected, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_CheckResultSteamID) - - return SteamAPI_ISteamInventory_CheckResultSteamID_o( - self, - resultHandle, - steamIDExpected - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems -( - -void *self, - SteamInventoryResult_t*pResultHandle -) - { - return steam_inventory::GetAllItems( - __func__, - pResultHandle, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetAllItems) - - return SteamAPI_ISteamInventory_GetAllItems_o(self, pResultHandle); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID -( - -void *self, - SteamInventoryResult_t*pResultHandle, - -const SteamItemInstanceID_t *pInstanceIDs, - uint32_t unCountInstanceIDs -) - { - return steam_inventory::GetItemsByID( - __func__, - pResultHandle, - pInstanceIDs, - unCountInstanceIDs, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemsByID) - - return SteamAPI_ISteamInventory_GetItemsByID_o( - self, - pResultHandle, - pInstanceIDs, - unCountInstanceIDs - ); - } - ); -} - -DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult -( - -void *self, - SteamInventoryResult_t resultHandle, - -void *pOutBuffer, - uint32_t*punOutBufferSize -) - { - return steam_inventory::SerializeResult( - __func__, - resultHandle, - pOutBuffer, - punOutBufferSize, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_SerializeResult) - - return SteamAPI_ISteamInventory_SerializeResult_o( - self, - resultHandle, - pOutBuffer, - punOutBufferSize - ); - } - ); -} - -// ISteamUser - -DLL_EXPORT (EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp( - void* self, - CSteamID steamID, - AppId_t dlcID - ) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_user::UserHasLicenseForApp( - __func__, - app_id, - dlcID, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp) - - return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, dlcID); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } -} \ No newline at end of file diff --git a/src/exports/steam_api_internal.cpp b/src/exports/steam_api_internal.cpp deleted file mode 100644 index 07421a8..0000000 --- a/src/exports/steam_api_internal.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#include "smoke_api/globals.hpp" -#include "smoke_api/types.hpp" -#include "steam_interface/steam_client.hpp" - -DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface -( - HSteamUser hSteamUser -, -const char* version -) - { - return steam_client::GetGenericInterface( - __func__, - version, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInternal_FindOrCreateUserInterface) - - 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 SteamInternal_CreateInterface_o(version); - } - ); -} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d6cd5df..b625b8d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,10 @@ -#include +#include "smoke_api.hpp" // This header will be populated at build time #include "linker_exports_for_steam_api.h" #include "linker_exports_for_version.h" EXTERN_C [[maybe_unused]] BOOL WINAPI - DllMain(const HMODULE module_handle, const DWORD reason, LPVOID) { if(reason == DLL_PROCESS_ATTACH) { smoke_api::init(module_handle); diff --git a/src/smoke_api/smoke_api.cpp b/src/smoke_api.cpp similarity index 84% rename from src/smoke_api/smoke_api.cpp rename to src/smoke_api.cpp index c3f43dd..f283734 100644 --- a/src/smoke_api/smoke_api.cpp +++ b/src/smoke_api.cpp @@ -10,10 +10,9 @@ #include "build_config.h" -#include "smoke_api/smoke_api.hpp" -#include "exports/steamclient.hpp" +#include "smoke_api.hpp" #include "smoke_api/config.hpp" -#include "smoke_api/globals.hpp" +#include "steamclient/steamclient.hpp" // Hooking steam_api has shown itself to be less desirable than steamclient // for the reasons outlined below: @@ -37,9 +36,6 @@ namespace { namespace kb = koalabox; namespace fs = std::filesystem; -#define DETOUR_STEAMCLIENT(FUNC) \ - kb::hook::detour_or_warn(globals::steamclient_module, #FUNC, reinterpret_cast(FUNC)); - void override_app_id() { const auto override_app_id = smoke_api::config::instance.override_app_id; if(override_app_id == 0) { @@ -56,7 +52,7 @@ namespace { LOG_INFO("Detected proxy mode"); const auto self_path = kb::paths::get_self_path(); - globals::steamapi_module = kb::loader::load_original_library(self_path, STEAMAPI_DLL); + smoke_api::steamapi_module = kb::loader::load_original_library(self_path, STEAMAPI_DLL); } void init_hook_mode() { @@ -66,10 +62,12 @@ namespace { kb::dll_monitor::init_listener( STEAMCLIENT_DLL, - [](const HMODULE& library) { - globals::steamclient_module = library; - - DETOUR_STEAMCLIENT(CreateInterface) + [](const HMODULE& steamclient_module) { + kb::hook::detour_or_warn( + steamclient_module, + "CreateInterface", + reinterpret_cast(CreateInterface) + ); kb::dll_monitor::shutdown_listener(); } @@ -78,6 +76,8 @@ namespace { } namespace smoke_api { + HMODULE steamapi_module = nullptr; + void init(const HMODULE module_handle) { // FIXME: IMPORTANT! Non ascii paths in directories will result in init errors try { @@ -114,9 +114,9 @@ namespace smoke_api { void shutdown() { try { - if(globals::steamapi_module != nullptr) { - kb::win_util::free_library(globals::steamapi_module); - globals::steamapi_module = nullptr; + if(steamapi_module != nullptr) { + kb::win_util::free_library(steamapi_module); + steamapi_module = nullptr; } LOG_INFO("Shutdown complete"); diff --git a/src/smoke_api.hpp b/src/smoke_api.hpp new file mode 100644 index 0000000..91a0e99 --- /dev/null +++ b/src/smoke_api.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; +constexpr auto STEAM_CLIENT = "SteamClient"; +constexpr auto STEAM_USER = "SteamUser"; +constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; + +// IMPORTANT: DLL_EXPORT is hardcoded in exports_generator.cpp, +// so any name changes here must be reflected there as well. +#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 HOOKED_CALL(FUNC, ...) \ + static const auto _##FUNC = KB_HOOK_GET_HOOKED_FN(smoke_api::steamapi_module, FUNC); \ + return _##FUNC(__VA_ARGS__) + +#define HOOKED_CALL_CLOSURE(FUNC, ...) \ + [&] { HOOKED_CALL(FUNC, __VA_ARGS__); } + +namespace smoke_api { + extern HMODULE steamapi_module; + + void init(HMODULE module_handle); + + void shutdown(); +} diff --git a/src/smoke_api/globals.cpp b/src/smoke_api/globals.cpp deleted file mode 100644 index b0927ab..0000000 --- a/src/smoke_api/globals.cpp +++ /dev/null @@ -1,4 +0,0 @@ -namespace globals { - HMODULE steamapi_module = nullptr; - HMODULE steamclient_module = nullptr; -} diff --git a/src/smoke_api/globals.hpp b/src/smoke_api/globals.hpp deleted file mode 100644 index 5e56be1..0000000 --- a/src/smoke_api/globals.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace globals { - extern HMODULE steamclient_module; - extern HMODULE steamapi_module; -} diff --git a/src/smoke_api/smoke_api.hpp b/src/smoke_api/smoke_api.hpp deleted file mode 100644 index 60bbff7..0000000 --- a/src/smoke_api/smoke_api.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace smoke_api { - void init(HMODULE module_handle); - - void shutdown(); -} diff --git a/src/smoke_api/types.hpp b/src/smoke_api/types.hpp deleted file mode 100644 index 5709a41..0000000 --- a/src/smoke_api/types.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -/** - * 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(...) const void *ECX, const 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 - -// IMPORTANT: DLL_EXPORT is hardcoded in exports_generator.cpp, -// so any name changes here must be reflected there as well. -#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec(dllexport) TYPE __cdecl - -#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall -#define C_DECL(TYPE) extern "C" __declspec(noinline) TYPE __cdecl - -// TODO: Replace with direct call -#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \ - static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(#FUNC, FUNC); - -#define ORIGINAL_FUNCTION_STEAMAPI(FUNC) \ - koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC) - -// TODO: Rename to DEFINE_ORIGINAL_FUNCTION_STEAMAPI -#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \ - static const auto FUNC##_o = ORIGINAL_FUNCTION_STEAMAPI(FUNC); - -#define DETOUR_ADDRESS(FUNC, ADDRESS) \ - koalabox::hook::detour_or_warn(ADDRESS, #FUNC, reinterpret_cast(FUNC)); - -#define _DETOUR(FUNC, NAME, MODULE_HANDLE) \ - koalabox::hook::detour_or_warn(MODULE_HANDLE, NAME, reinterpret_cast(FUNC)); - -constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; -constexpr auto STEAM_CLIENT = "SteamClient"; -constexpr auto STEAM_USER = "SteamUser"; -constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; - -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; - uint32_t m_iDefinition; - uint16_t m_unQuantity; - uint16_t m_unFlags; // see ESteamItemFlags -}; - -// results from UserHasLicenseForApp -enum EUserHasLicenseForAppResult { - k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app - k_EUserHasLicenseResultDoesNotHaveLicense = 1, - // User does not have a license for the specified app - k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated -}; - -// These aliases exist solely to increase code readability - -using AppIdKey = std::string; -using DlcIdKey = std::string; -using DlcNameValue = std::string; -using DlcNameMap = std::map; - -struct App { - DlcNameMap dlcs; - - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(App, dlcs) // NOLINT(misc-const-correctness) -}; - -using AppDlcNameMap = std::map; - -class DLC { - // These 2 names must match the property names from Steam API - std::string appid; - std::string name; - -public: - explicit DLC() = default; - - explicit DLC(std::string appid, std::string name) : appid{std::move(appid)}, - name{std::move(name)} {} - - [[nodiscard]] std::string get_id_str() const { - return appid; - } - - [[nodiscard]] uint32_t get_id() const { - return std::stoi(appid); - } - - [[nodiscard]] std::string get_name() const { - return name; - } - - NLOHMANN_DEFINE_TYPE_INTRUSIVE(DLC, appid, name) - - static std::vector get_dlcs_from_apps(const AppDlcNameMap& apps, AppId_t app_id); - - static DlcNameMap get_dlc_map_from_vector(const std::vector& vector); -}; \ No newline at end of file diff --git a/src/steam_api/exports/steam_api.cpp b/src/steam_api/exports/steam_api.cpp new file mode 100644 index 0000000..61aec23 --- /dev/null +++ b/src/steam_api/exports/steam_api.cpp @@ -0,0 +1,23 @@ +#include + +#include "smoke_api.hpp" +#include "smoke_api/config.hpp" + +// TODO: Support in hook mode +DLL_EXPORT(bool) SteamAPI_RestartAppIfNecessary(const uint32_t unOwnAppID) { + if(smoke_api::config::instance.override_app_id != 0) { + LOG_DEBUG("{} -> {}. Preventing app restart", unOwnAppID, __func__); + return false; + } + + // Note: Assumes proxy mode only + MODULE_CALL(SteamAPI_RestartAppIfNecessary, unOwnAppID); +} + +// TODO: Support in hook mode +DLL_EXPORT(void) SteamAPI_Shutdown() { + LOG_INFO("{} -> Game requested shutdown", __func__); + + // Note: Assumes proxy mode only + MODULE_CALL(SteamAPI_Shutdown); +} diff --git a/src/steam_api/exports/steam_api_flat.cpp b/src/steam_api/exports/steam_api_flat.cpp new file mode 100644 index 0000000..52969e2 --- /dev/null +++ b/src/steam_api/exports/steam_api_flat.cpp @@ -0,0 +1,296 @@ +#include + +#include "smoke_api.hpp" +#include "smoke_api/interfaces/steam_apps.hpp" +#include "smoke_api/interfaces/steam_inventory.hpp" +#include "smoke_api/interfaces/steam_user.hpp" +#include "steam_api/steam_client.hpp" +#include "steam_api/steam_interface.hpp" + +// ISteamApps + +DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void* self, AppId_t dlcID) { + try { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlcID, + MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_BIsSubscribedApp, self, dlcID) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} + +DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void* self, AppId_t dlcID) { + try { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlcID, + MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_BIsDlcInstalled, self, dlcID) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} + +DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void* self) { + try { + return smoke_api::steam_apps::GetDLCCount( + __func__, + steam_interface::get_app_id(), + MODULE_CALL_CLOSURE(SteamAPI_ISteamApps_GetDLCCount, self) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return 0; + } +} + +DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex( + void* self, + const int iDLC, + AppId_t* pDlcID, + bool* pbAvailable, + char* pchName, + const int cchNameBufferSize +) { + try { + return smoke_api::steam_apps::GetDLCDataByIndex( + __func__, + steam_interface::get_app_id(), + iDLC, + pDlcID, + pbAvailable, + pchName, + cchNameBufferSize, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamApps_BGetDLCDataByIndex, + self, + iDLC, + pDlcID, + pbAvailable, + pchName, + cchNameBufferSize + ), + [&](const AppId_t dlc_id) { + return SteamAPI_ISteamApps_BIsDlcInstalled(self, dlc_id); + } + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} + +// ISteamClient + +DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface( + void* self, + const HSteamUser hSteamUser, + const HSteamPipe hSteamPipe, + const char* pchVersion +) { + try { + return steam_client::GetGenericInterface( + __func__, + pchVersion, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamClient_GetISteamGenericInterface, + self, + hSteamUser, + hSteamPipe, + pchVersion + ) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return nullptr; + } +} + +// ISteamInventory + +DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus( + void* self, + const SteamInventoryResult_t resultHandle +) { + return smoke_api::steam_inventory::GetResultStatus( + __func__, + resultHandle, + MODULE_CALL_CLOSURE(SteamAPI_ISteamInventory_GetResultStatus, self, resultHandle) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs( + void* self, + SteamItemDef_t* pItemDefIDs, + uint32_t* punItemDefIDsArraySize +) { + return smoke_api::steam_inventory::GetItemDefinitionIDs( + __func__, + pItemDefIDs, + punItemDefIDsArraySize, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_GetItemDefinitionIDs, + self, + pItemDefIDs, + punItemDefIDsArraySize + ) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems( + void* self, + const SteamInventoryResult_t resultHandle, + SteamItemDetails_t* pOutItemsArray, + uint32_t* punOutItemsArraySize +) { + return smoke_api::steam_inventory::GetResultItems( + __func__, + resultHandle, + pOutItemsArray, + punOutItemsArraySize, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_GetResultItems, + self, + resultHandle, + pOutItemsArray, + punOutItemsArraySize + ), + [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { + MODULE_CALL( + SteamAPI_ISteamInventory_GetItemDefinitionIDs, + self, + pItemDefIDs, + punItemDefIDsArraySize + ); + } + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty( + void* self, + const SteamInventoryResult_t resultHandle, + const uint32_t unItemIndex, + const char* pchPropertyName, + char* pchValueBuffer, + uint32_t* punValueBufferSizeOut +) { + return smoke_api::steam_inventory::GetResultItemProperty( + __func__, + resultHandle, + unItemIndex, + pchPropertyName, + pchValueBuffer, + punValueBufferSizeOut, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_GetResultItemProperty, + self, + resultHandle, + unItemIndex, + pchPropertyName, + pchValueBuffer, + punValueBufferSizeOut + ) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID( + void* self, + const SteamInventoryResult_t resultHandle, + const CSteamID steamIDExpected +) { + return smoke_api::steam_inventory::CheckResultSteamID( + __func__, + resultHandle, + steamIDExpected, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_CheckResultSteamID, + self, + resultHandle, + steamIDExpected + ) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems( + void* self, + SteamInventoryResult_t* pResultHandle +) { + return smoke_api::steam_inventory::GetAllItems( + __func__, + pResultHandle, + MODULE_CALL_CLOSURE(SteamAPI_ISteamInventory_GetAllItems, self, pResultHandle) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID( + void* self, + SteamInventoryResult_t* pResultHandle, + const SteamItemInstanceID_t* pInstanceIDs, + const uint32_t unCountInstanceIDs +) { + return smoke_api::steam_inventory::GetItemsByID( + __func__, + pResultHandle, + pInstanceIDs, + unCountInstanceIDs, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_GetItemsByID, + self, + pResultHandle, + pInstanceIDs, + unCountInstanceIDs + ) + ); +} + +DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult( + void* self, + const SteamInventoryResult_t resultHandle, + void* pOutBuffer, + uint32_t* punOutBufferSize +) { + return smoke_api::steam_inventory::SerializeResult( + __func__, + resultHandle, + pOutBuffer, + punOutBufferSize, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamInventory_SerializeResult, + self, + resultHandle, + pOutBuffer, + punOutBufferSize + ) + ); +} + +// ISteamUser + +DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp( + void* self, + const CSteamID steamID, + const AppId_t dlcID +) { + try { + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + steam_interface::get_app_id(), + dlcID, + MODULE_CALL_CLOSURE( + SteamAPI_ISteamUser_UserHasLicenseForApp, + self, + steamID, + dlcID + ) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return k_EUserHasLicenseResultDoesNotHaveLicense; + } +} diff --git a/src/steam_api/exports/steam_api_internal.cpp b/src/steam_api/exports/steam_api_internal.cpp new file mode 100644 index 0000000..964eb6c --- /dev/null +++ b/src/steam_api/exports/steam_api_internal.cpp @@ -0,0 +1,22 @@ +#include "smoke_api.hpp" +#include "smoke_api/types.hpp" +#include "steam_api/steam_client.hpp" + +DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface( + const HSteamUser hSteamUser, + const char* version +) { + return steam_client::GetGenericInterface( + __func__, + version, + MODULE_CALL_CLOSURE(SteamInternal_FindOrCreateUserInterface, hSteamUser, version) + ); +} + +DLL_EXPORT(void*) SteamInternal_CreateInterface(const char* version) { + return steam_client::GetGenericInterface( + __func__, + version, + MODULE_CALL_CLOSURE(SteamInternal_CreateInterface, version) + ); +} diff --git a/src/exports/steam_api_unversioned.cpp b/src/steam_api/exports/steam_api_unversioned.cpp similarity index 60% rename from src/exports/steam_api_unversioned.cpp rename to src/steam_api/exports/steam_api_unversioned.cpp index 387fcb5..d45456b 100644 --- a/src/exports/steam_api_unversioned.cpp +++ b/src/steam_api/exports/steam_api_unversioned.cpp @@ -1,15 +1,16 @@ #include +#include -#include #include #include #include -#include "smoke_api/globals.hpp" -#include "smoke_api/types.hpp" -#include "steam_interface/steam_client.hpp" +#include "smoke_api.hpp" +#include "steam_api/steam_client.hpp" namespace { + namespace kb = koalabox; + /** * Searches the `.rdata` section of the original dll for the full interface version string * Results are cached for performance. @@ -20,24 +21,20 @@ namespace { ) { static std::map version_map; - if(not - version_map.contains(version_prefix) - ) - { + if(not version_map.contains(version_prefix)) { try { - const std::string rdata = koalabox::win_util::get_pe_section_data_or_throw( - globals::steamapi_module, + const std::string rdata = kb::win_util::get_pe_section_data_or_throw( + smoke_api::steamapi_module, ".rdata" ); const std::regex regex(version_prefix + "\\d{3}"); - std::smatch match; - if(std::regex_search(rdata, match, regex)) { + if(std::smatch match; std::regex_search(rdata, match, regex)) { version_map[version_prefix] = match[0]; return version_map[version_prefix]; } - throw koalabox::util::exception("No match found for '{}'", version_prefix); + throw kb::util::exception("No match found for '{}'", version_prefix); } catch(const std::exception& ex) { LOG_ERROR( "Failed to get versioned interface: {}." @@ -54,70 +51,42 @@ namespace { } } -DLL_EXPORT(void*) SteamClient -( -) - { +DLL_EXPORT(void*) SteamClient() { static auto version = get_versioned_interface(STEAM_CLIENT, "006"); return steam_client::GetGenericInterface( __func__, version, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamClient) - - return SteamClient_o(); - } + MODULE_CALL_CLOSURE(SteamClient) ); } -DLL_EXPORT(void*) SteamApps -( -) - { +DLL_EXPORT(void*) SteamApps() { static auto version = get_versioned_interface(STEAM_APPS, "002"); return steam_client::GetGenericInterface( __func__, version, - [&]() { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamApps) - - return SteamApps_o(); - } + MODULE_CALL_CLOSURE(SteamApps) ); } -DLL_EXPORT(void*) SteamUser -( -) - { +DLL_EXPORT(void*) SteamUser() { static auto version = get_versioned_interface(STEAM_USER, "012"); return steam_client::GetGenericInterface( __func__, version, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamUser) - - return SteamUser_o(); - } + MODULE_CALL_CLOSURE(SteamUser) ); } -DLL_EXPORT(void*) SteamInventory -( -) - { +DLL_EXPORT(void*) SteamInventory() { static auto version = get_versioned_interface(STEAM_INVENTORY, "001"); return steam_client::GetGenericInterface( __func__, version, - [&] { - GET_ORIGINAL_FUNCTION_STEAMAPI(SteamInventory) - - return SteamInventory_o(); - } + MODULE_CALL_CLOSURE(SteamInventory) ); -} \ No newline at end of file +} diff --git a/src/steam_interface/steam_client.cpp b/src/steam_api/steam_client.cpp similarity index 84% rename from src/steam_interface/steam_client.cpp rename to src/steam_api/steam_client.cpp index e146d72..5cfafa1 100644 --- a/src/steam_interface/steam_client.cpp +++ b/src/steam_api/steam_client.cpp @@ -1,7 +1,6 @@ #include -#include "steam_interface/steam_client.hpp" -#include "steam_interface/steam_interface.hpp" +#include "steam_api/steam_interface.hpp" namespace steam_client { void* GetGenericInterface( diff --git a/src/steam_interface/steam_client.hpp b/src/steam_api/steam_client.hpp similarity index 87% rename from src/steam_interface/steam_client.hpp rename to src/steam_api/steam_client.hpp index baf03d0..75ae03d 100644 --- a/src/steam_interface/steam_client.hpp +++ b/src/steam_api/steam_client.hpp @@ -1,6 +1,6 @@ #pragma once -#include "smoke_api/types.hpp" +#include namespace steam_client { void* GetGenericInterface( diff --git a/src/steam_interface/steam_interface.cpp b/src/steam_api/steam_interface.cpp similarity index 97% rename from src/steam_interface/steam_interface.cpp rename to src/steam_api/steam_interface.cpp index 0ff871f..aaf64ca 100644 --- a/src/steam_interface/steam_interface.cpp +++ b/src/steam_api/steam_interface.cpp @@ -8,8 +8,7 @@ #include #include -#include "steam_interface/steam_interface.hpp" -#include "exports/steamclient.hpp" +#include "smoke_api.hpp" #include "virtuals/steam_api_virtuals.hpp" namespace { @@ -113,6 +112,21 @@ namespace { namespace steam_interface { namespace kb = koalabox; + AppId_t get_app_id_or_throw() { + const auto app_id_str = kb::win_util::get_env_var("SteamAppId"); + return std::stoi(app_id_str); + } + + AppId_t get_app_id() { + try { + static const auto app_id = get_app_id_or_throw(); + return app_id; + } catch(const std::exception& e) { + LOG_ERROR("Failed to get app id: {}", e.what()); + return 0; + } + } + void hook_virtuals(void* interface, const std::string& version_string) { if(interface == nullptr) { // Game has tried to use an interface before initializing steam api @@ -151,18 +165,4 @@ namespace steam_interface { processed_interfaces.insert(interface); } - - AppId_t get_app_id_or_throw() { - const auto app_id_str = kb::win_util::get_env_var("SteamAppId"); - return std::stoi(app_id_str); - } - - AppId_t get_app_id() { - try { - return get_app_id_or_throw(); - } catch(const std::exception& e) { - LOG_ERROR("Failed to get app id: {}", e.what()); - return 0; - } - } } diff --git a/src/steam_interface/steam_interface.hpp b/src/steam_api/steam_interface.hpp similarity index 99% rename from src/steam_interface/steam_interface.hpp rename to src/steam_api/steam_interface.hpp index 8b58cf3..4e8c5ef 100644 --- a/src/steam_interface/steam_interface.hpp +++ b/src/steam_api/steam_interface.hpp @@ -4,7 +4,6 @@ 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); diff --git a/src/steam_api/virtuals/isteamapps.cpp b/src/steam_api/virtuals/isteamapps.cpp new file mode 100644 index 0000000..4d78f79 --- /dev/null +++ b/src/steam_api/virtuals/isteamapps.cpp @@ -0,0 +1,79 @@ +#include + +#include "smoke_api.hpp" +#include "smoke_api/interfaces/steam_apps.hpp" +#include "steam_api/steam_interface.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(const AppId_t dlc_id)) { + try { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamApps_BIsSubscribedApp, ARGS(dlc_id)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} + +VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(const AppId_t dlc_id)) { + try { + return smoke_api::steam_apps::IsDlcUnlocked( + __func__, + steam_interface::get_app_id(), + dlc_id, + HOOKED_CALL_CLOSURE(ISteamApps_BIsDlcInstalled, ARGS(dlc_id)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} + +VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) { + try { + return smoke_api::steam_apps::GetDLCCount( + __func__, + steam_interface::get_app_id(), + HOOKED_CALL_CLOSURE(ISteamApps_GetDLCCount, ARGS()) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return 0; + } +} + +VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex( + PARAMS( + const int iDLC, + AppId_t* p_dlc_id, + bool* pbAvailable, + char* pchName, + const int cchNameBufferSize + ) +) { + try { + return smoke_api::steam_apps::GetDLCDataByIndex( + __func__, + steam_interface::get_app_id(), + iDLC, + p_dlc_id, + pbAvailable, + pchName, + cchNameBufferSize, + HOOKED_CALL_CLOSURE( + ISteamApps_BGetDLCDataByIndex, + ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize) + ), + [&](const AppId_t dlc_id) { + return ISteamApps_BIsDlcInstalled(ARGS(dlc_id)); + } + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return false; + } +} diff --git a/src/steam_api/virtuals/isteamclient.cpp b/src/steam_api/virtuals/isteamclient.cpp new file mode 100644 index 0000000..dfdf51a --- /dev/null +++ b/src/steam_api/virtuals/isteamclient.cpp @@ -0,0 +1,87 @@ +#include + +#include "smoke_api.hpp" +#include "steam_api/steam_client.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(void*) ISteamClient_GetISteamApps( + PARAMS( + const HSteamUser hSteamUser, + const HSteamPipe hSteamPipe, + const char* version + ) +) { + try { + return steam_client::GetGenericInterface( + __func__, + version, + HOOKED_CALL_CLOSURE(ISteamClient_GetISteamApps, ARGS(hSteamUser, hSteamPipe, version)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return nullptr; + } +} + +VIRTUAL(void*) ISteamClient_GetISteamUser( + PARAMS( + const HSteamUser hSteamUser, + const HSteamPipe hSteamPipe, + const char* version + ) +) { + try { + return steam_client::GetGenericInterface( + __func__, + version, + HOOKED_CALL_CLOSURE(ISteamClient_GetISteamUser, ARGS(hSteamUser, hSteamPipe, version)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return nullptr; + } +} + +VIRTUAL(void*) ISteamClient_GetISteamGenericInterface( + PARAMS( + HSteamUser hSteamUser, + HSteamPipe hSteamPipe, + const char* pchVersion + ) +) { + try { + return steam_client::GetGenericInterface( + __func__, + pchVersion, + HOOKED_CALL_CLOSURE( + ISteamClient_GetISteamGenericInterface, + ARGS(hSteamUser, hSteamPipe, pchVersion) + ) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return nullptr; + } +} + +VIRTUAL(void*) ISteamClient_GetISteamInventory( + PARAMS( + const HSteamUser hSteamUser, + const HSteamPipe hSteamPipe, + const char* pchVersion + ) +) { + try { + return steam_client::GetGenericInterface( + __func__, + pchVersion, + HOOKED_CALL_CLOSURE( + ISteamClient_GetISteamInventory, + ARGS(hSteamUser, hSteamPipe, pchVersion) + ) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return nullptr; + } +} diff --git a/src/steam_api/virtuals/isteaminventory.cpp b/src/steam_api/virtuals/isteaminventory.cpp new file mode 100644 index 0000000..806e646 --- /dev/null +++ b/src/steam_api/virtuals/isteaminventory.cpp @@ -0,0 +1,144 @@ +#include "smoke_api.hpp" +#include "smoke_api/interfaces/steam_inventory.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(EResult) ISteamInventory_GetResultStatus( + PARAMS(const SteamInventoryResult_t resultHandle) +) { + return smoke_api::steam_inventory::GetResultStatus( + __func__, + resultHandle, + HOOKED_CALL_CLOSURE(ISteamInventory_GetResultStatus, ARGS(resultHandle)) + ); +} + +VIRTUAL(bool) ISteamInventory_GetResultItems( + PARAMS( + const SteamInventoryResult_t resultHandle, + SteamItemDetails_t* pOutItemsArray, + uint32_t* punOutItemsArraySize + ) +) { + return smoke_api::steam_inventory::GetResultItems( + __func__, + resultHandle, + pOutItemsArray, + punOutItemsArraySize, + HOOKED_CALL_CLOSURE( + ISteamInventory_GetResultItems, + ARGS(resultHandle, pOutItemsArray, punOutItemsArraySize) + ), + [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { + HOOKED_CALL( + ISteamInventory_GetItemDefinitionIDs, + ARGS(pItemDefIDs, punItemDefIDsArraySize) + ); + } + ); +} + +VIRTUAL(bool) ISteamInventory_GetResultItemProperty( + PARAMS( + const SteamInventoryResult_t resultHandle, + const uint32_t unItemIndex, + const char* pchPropertyName, + char* pchValueBuffer, + uint32_t* punValueBufferSizeOut + ) +) { + return smoke_api::steam_inventory::GetResultItemProperty( + __func__, + resultHandle, + unItemIndex, + pchPropertyName, + pchValueBuffer, + punValueBufferSizeOut, + HOOKED_CALL_CLOSURE( + ISteamInventory_GetResultItemProperty, + ARGS( + resultHandle, + unItemIndex, + pchPropertyName, + pchValueBuffer, + punValueBufferSizeOut + ) + ) + ); +} + +VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) { + return smoke_api::steam_inventory::GetAllItems( + __func__, + pResultHandle, + HOOKED_CALL_CLOSURE(ISteamInventory_GetAllItems, ARGS(pResultHandle)) + ); +} + +VIRTUAL(bool) ISteamInventory_GetItemsByID( + PARAMS( + SteamInventoryResult_t* pResultHandle, + const SteamItemInstanceID_t* pInstanceIDs, + const uint32_t unCountInstanceIDs + ) +) { + return smoke_api::steam_inventory::GetItemsByID( + __func__, + pResultHandle, + pInstanceIDs, + unCountInstanceIDs, + HOOKED_CALL_CLOSURE( + ISteamInventory_GetItemsByID, + ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs) + ) + ); +} + +VIRTUAL(bool) ISteamInventory_SerializeResult( + PARAMS( + const SteamInventoryResult_t resultHandle, + void* pOutBuffer, + uint32_t* punOutBufferSize + ) +) { + return smoke_api::steam_inventory::SerializeResult( + __func__, + resultHandle, + pOutBuffer, + punOutBufferSize, + HOOKED_CALL_CLOSURE( + ISteamInventory_SerializeResult, + ARGS(resultHandle, pOutBuffer, punOutBufferSize) + ) + ); +} + +VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( + PARAMS( + SteamItemDef_t*pItemDefIDs, + uint32_t* punItemDefIDsArraySize + ) +) { + return smoke_api::steam_inventory::GetItemDefinitionIDs( + __func__, + pItemDefIDs, + punItemDefIDsArraySize, + HOOKED_CALL_CLOSURE( + ISteamInventory_GetItemDefinitionIDs, + ARGS(pItemDefIDs, punItemDefIDsArraySize) + ) + ); +} + +VIRTUAL(bool) ISteamInventory_CheckResultSteamID( + PARAMS(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) +) { + return smoke_api::steam_inventory::CheckResultSteamID( + __func__, + resultHandle, + steamIDExpected, + HOOKED_CALL_CLOSURE( + ISteamInventory_CheckResultSteamID, + ARGS(resultHandle, steamIDExpected) + ) + ); +} diff --git a/src/steam_api/virtuals/isteamuser.cpp b/src/steam_api/virtuals/isteamuser.cpp new file mode 100644 index 0000000..1b68b83 --- /dev/null +++ b/src/steam_api/virtuals/isteamuser.cpp @@ -0,0 +1,23 @@ +#include + +#include "smoke_api.hpp" +#include "smoke_api/interfaces/steam_user.hpp" +#include "steam_api/steam_interface.hpp" +#include "steam_api/virtuals/steam_api_virtuals.hpp" + +VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp( + PARAMS(const CSteamID steamID, const AppId_t dlc_id) +) { + try { + static const auto app_id = steam_interface::get_app_id(); + return smoke_api::steam_user::UserHasLicenseForApp( + __func__, + app_id, + dlc_id, + HOOKED_CALL_CLOSURE(ISteamUser_UserHasLicenseForApp, ARGS(steamID, dlc_id)) + ); + } catch(const std::exception& e) { + LOG_ERROR("{} -> Error: {}", __func__, e.what()); + return k_EUserHasLicenseResultDoesNotHaveLicense; + } +} diff --git a/src/steam_api/virtuals/steam_api_virtuals.hpp b/src/steam_api/virtuals/steam_api_virtuals.hpp new file mode 100644 index 0000000..98f91eb --- /dev/null +++ b/src/steam_api/virtuals/steam_api_virtuals.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "smoke_api/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(...) const void *ECX, const void *EDX, __VA_ARGS__ +#define ARGS(...) ECX, EDX, __VA_ARGS__ +#define THIS ECX +#endif + +#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall // NOLINT(*-macro-parentheses) + +// ISteamApps +VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t)); +VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t)); +VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()); +VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*, int)); + +// ISteamClient +VIRTUAL(void*) ISteamClient_GetISteamApps(PARAMS(HSteamUser, HSteamPipe, const char*)); +VIRTUAL(void*) ISteamClient_GetISteamUser(PARAMS(HSteamUser, HSteamPipe, const char*)); +VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(PARAMS(HSteamUser, HSteamPipe, const char*)); +VIRTUAL(void*) ISteamClient_GetISteamInventory(PARAMS(HSteamUser, HSteamPipe, const char*)); + +// ISteamInventory +VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t)); +VIRTUAL(bool) ISteamInventory_GetResultItems( + PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*) // @formatter:off +); // @formatter:on + +VIRTUAL(bool) ISteamInventory_GetResultItemProperty( + PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*) // @formatter:off +); // @formatter:on +VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t*)); +VIRTUAL(bool) ISteamInventory_GetItemsByID( + PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t) +); +VIRTUAL(bool) ISteamInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t*)); +VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t*)); +VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID)); + +// ISteamUser +VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t)); diff --git a/src/exports/steamclient.cpp b/src/steamclient/steamclient.cpp similarity index 51% rename from src/exports/steamclient.cpp rename to src/steamclient/steamclient.cpp index bf5f0f4..b632f65 100644 --- a/src/exports/steamclient.cpp +++ b/src/steamclient/steamclient.cpp @@ -1,17 +1,15 @@ #include -#include "exports/steamclient.hpp" +#include "steamclient.hpp" + +#include "smoke_api.hpp" #include "smoke_api/types.hpp" -#include "steam_interface/steam_client.hpp" +#include "steam_api/steam_client.hpp" C_DECL(void*) CreateInterface(const char* interface_string, int* out_result) { return steam_client::GetGenericInterface( __func__, interface_string, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(CreateInterface) - - return CreateInterface_o(interface_string, out_result); - } + HOOKED_CALL_CLOSURE(CreateInterface, interface_string, out_result) ); } diff --git a/src/exports/steamclient.hpp b/src/steamclient/steamclient.hpp similarity index 58% rename from src/exports/steamclient.hpp rename to src/steamclient/steamclient.hpp index 81d8e43..bb54c16 100644 --- a/src/exports/steamclient.hpp +++ b/src/steamclient/steamclient.hpp @@ -1,5 +1,5 @@ #pragma once -#include "smoke_api/types.hpp" +#define C_DECL(TYPE) extern "C" __declspec(noinline) TYPE __cdecl C_DECL(void*) CreateInterface(const char* interface_string, int* out_result); diff --git a/src/virtuals/isteamapps.cpp b/src/virtuals/isteamapps.cpp deleted file mode 100644 index 6f44a2a..0000000 --- a/src/virtuals/isteamapps.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include - -#include "steam_interface/steam_apps.hpp" -#include "steam_interface/steam_interface.hpp" -#include "virtuals/steam_api_virtuals.hpp" - -VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::IsDlcUnlocked( - __func__, - app_id, - dlc_id, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BIsSubscribedApp) - return ISteamApps_BIsSubscribedApp_o(ARGS(dlc_id)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - - return false; - } -} - -VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t dlc_id)) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::IsDlcUnlocked( - __func__, - app_id, - dlc_id, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BIsDlcInstalled) - return ISteamApps_BIsDlcInstalled_o(ARGS(dlc_id)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - - return false; - } -} - -VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::GetDLCCount( - __func__, - app_id, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_GetDLCCount) - return ISteamApps_GetDLCCount_o(ARGS()); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - - return 0; - } -} - -VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex( - PARAMS( - int iDLC, - AppId_t* p_dlc_id, - bool* pbAvailable, - char* pchName, - int cchNameBufferSize - ) -) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_apps::GetDLCDataByIndex( - __func__, - app_id, - iDLC, - p_dlc_id, - pbAvailable, - pchName, - cchNameBufferSize, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex) - return ISteamApps_BGetDLCDataByIndex_o( - ARGS(iDLC, p_dlc_id, pbAvailable, pchName, cchNameBufferSize) - ); - }, - [&](AppId_t dlc_id) { - return ISteamApps_BIsDlcInstalled(ARGS(dlc_id)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return false; - } -} diff --git a/src/virtuals/isteamclient.cpp b/src/virtuals/isteamclient.cpp deleted file mode 100644 index 0ce74a5..0000000 --- a/src/virtuals/isteamclient.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "steam_interface/steam_client.hpp" -#include "virtuals/steam_api_virtuals.hpp" - -VIRTUAL(void*) ISteamClient_GetISteamApps - -( - PARAMS( - HSteamUser hSteamUser, - HSteamPipe hSteamPipe, - const char* version - ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - version, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps) - return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} - -VIRTUAL(void*) ISteamClient_GetISteamUser - -( - PARAMS( - HSteamUser hSteamUser, - HSteamPipe hSteamPipe, - const char* version - ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - version, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser) - - return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} - -VIRTUAL(void*) ISteamClient_GetISteamGenericInterface - -( - PARAMS( - HSteamUser hSteamUser, - HSteamPipe hSteamPipe, - const char* pchVersion - ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface) - - return ISteamClient_GetISteamGenericInterface_o( - ARGS(hSteamUser, hSteamPipe, pchVersion) - ); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} - -VIRTUAL(void*) ISteamClient_GetISteamInventory - -( - PARAMS( - HSteamUser hSteamUser, - HSteamPipe hSteamPipe, - const char* pchVersion - ) -) { - try { - return steam_client::GetGenericInterface( - __func__, - pchVersion, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory) - - return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return nullptr; - } -} \ No newline at end of file diff --git a/src/virtuals/isteaminventory.cpp b/src/virtuals/isteaminventory.cpp deleted file mode 100644 index 19e32ee..0000000 --- a/src/virtuals/isteaminventory.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include - -#include "steam_interface/steam_inventory.hpp" -#include "virtuals/steam_api_virtuals.hpp" - -VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) { - return steam_inventory::GetResultStatus( - __func__, - resultHandle, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultStatus) - - return ISteamInventory_GetResultStatus_o(ARGS(resultHandle)); - } - ); -} - -VIRTUAL(bool) ISteamInventory_GetResultItems( - PARAMS( - SteamInventoryResult_t resultHandle, - SteamItemDetails_t* pOutItemsArray, - uint32_t* punOutItemsArraySize - ) -) { - return steam_inventory::GetResultItems( - __func__, - resultHandle, - pOutItemsArray, - punOutItemsArraySize, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultItems) - - return ISteamInventory_GetResultItems_o( - ARGS(resultHandle, pOutItemsArray, punOutItemsArraySize) - ); - }, - [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs) - - return ISteamInventory_GetItemDefinitionIDs_o( - ARGS(pItemDefIDs, punItemDefIDsArraySize) - ); - } - ); -} - -VIRTUAL(bool) ISteamInventory_GetResultItemProperty( - PARAMS( - SteamInventoryResult_t resultHandle, - uint32_t unItemIndex, - const char* pchPropertyName, - char* pchValueBuffer, - uint32_t* punValueBufferSizeOut - ) -) { - return steam_inventory::GetResultItemProperty( - __func__, - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultItemProperty) - - return ISteamInventory_GetResultItemProperty_o( - ARGS( - resultHandle, - unItemIndex, - pchPropertyName, - pchValueBuffer, - punValueBufferSizeOut - ) - ); - } - ); -} - -VIRTUAL(bool) ISteamInventory_CheckResultSteamID( - PARAMS(SteamInventoryResult_t resultHandle, CSteamID steamIDExpected) -) { - return steam_inventory::CheckResultSteamID( - __func__, - resultHandle, - steamIDExpected, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_CheckResultSteamID) - - 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 ISteamInventory_GetAllItems_o(ARGS(pResultHandle)); - } - ); -} - -VIRTUAL(bool) ISteamInventory_GetItemsByID( - PARAMS( - SteamInventoryResult_t* pResultHandle, - const SteamItemInstanceID_t* pInstanceIDs, - uint32_t unCountInstanceIDs - ) -) { - return steam_inventory::GetItemsByID( - __func__, - pResultHandle, - pInstanceIDs, - unCountInstanceIDs, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemsByID) - - return ISteamInventory_GetItemsByID_o( - ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs) - ); - } - ); -} - -VIRTUAL(bool) ISteamInventory_SerializeResult( - PARAMS(SteamInventoryResult_t resultHandle, void* pOutBuffer, uint32_t* punOutBufferSize) -) { - return steam_inventory::SerializeResult( - __func__, - resultHandle, - pOutBuffer, - punOutBufferSize, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_SerializeResult) - - return ISteamInventory_SerializeResult_o( - ARGS(resultHandle, pOutBuffer, punOutBufferSize) - ); - } - ); -} - -VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( - PARAMS( - SteamItemDef_t*pItemDefIDs, - uint32_t* punItemDefIDsArraySize - ) -) { - return steam_inventory::GetItemDefinitionIDs( - __func__, - pItemDefIDs, - punItemDefIDsArraySize, - [&] { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs) - - return ISteamInventory_GetItemDefinitionIDs_o( - ARGS(pItemDefIDs, punItemDefIDsArraySize) - ); - } - ); -} diff --git a/src/virtuals/isteamuser.cpp b/src/virtuals/isteamuser.cpp deleted file mode 100644 index 75a0d48..0000000 --- a/src/virtuals/isteamuser.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -#include "steam_interface/steam_interface.hpp" -#include "steam_interface/steam_user.hpp" -#include "virtuals/steam_api_virtuals.hpp" - -VIRTUAL (EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp( - PARAMS(CSteamID steamID, AppId_t dlc_id) - ) { - try { - static const auto app_id = steam_interface::get_app_id(); - return steam_user::UserHasLicenseForApp( - __func__, - app_id, - dlc_id, - [&]() { - GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp) - - return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, dlc_id)); - } - ); - } catch(const std::exception& e) { - LOG_ERROR("{} -> Error: {}", __func__, e.what()); - return k_EUserHasLicenseResultDoesNotHaveLicense; - } -} \ No newline at end of file diff --git a/src/virtuals/steam_api_virtuals.hpp b/src/virtuals/steam_api_virtuals.hpp deleted file mode 100644 index d456d0c..0000000 --- a/src/virtuals/steam_api_virtuals.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include "smoke_api/types.hpp" - -// ISteamApps -VIRTUAL(bool) ISteamApps_BIsSubscribedApp -(PARAMS -(AppId_t) -); -VIRTUAL(bool) ISteamApps_BIsDlcInstalled -(PARAMS -(AppId_t) -); -VIRTUAL(int) ISteamApps_GetDLCCount -(PARAMS()); -VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex -(PARAMS(int, AppId_t*, bool*, char*, int)); - -// ISteamClient -VIRTUAL(void*) ISteamClient_GetISteamApps -(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamUser -(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamGenericInterface -(PARAMS(HSteamUser, HSteamPipe, const char*)); -VIRTUAL(void*) ISteamClient_GetISteamInventory -(PARAMS(HSteamUser, HSteamPipe, const char*)); - -// ISteamInventory -VIRTUAL (EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t)); -VIRTUAL(bool) ISteamInventory_GetResultItems -( - PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*) // @formatter:off -); // @formatter:on - -VIRTUAL(bool) ISteamInventory_GetResultItemProperty -( - PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*) // @formatter:off -); // @formatter:on -VIRTUAL(bool) ISteamInventory_GetAllItems -(PARAMS(SteamInventoryResult_t*)); -VIRTUAL(bool) ISteamInventory_GetItemsByID -( - PARAMS( - SteamInventoryResult_t*, - const SteamItemInstanceID_t*, - uint32_t - ) -); -VIRTUAL(bool) ISteamInventory_SerializeResult -(PARAMS(SteamInventoryResult_t, void*, uint32_t*)); -VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs -(PARAMS(SteamItemDef_t*, uint32_t*)); -VIRTUAL(bool) ISteamInventory_CheckResultSteamID -( - PARAMS -(SteamInventoryResult_t -, -CSteamID -) -); - -// ISteamUser -VIRTUAL (EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t)); \ No newline at end of file diff --git a/src/smoke_api/api.cpp b/static/smoke_api/api.cpp similarity index 81% rename from src/smoke_api/api.cpp rename to static/smoke_api/api.cpp index 7f33522..411996b 100644 --- a/src/smoke_api/api.cpp +++ b/static/smoke_api/api.cpp @@ -4,7 +4,7 @@ #include "smoke_api/api.hpp" #include "smoke_api/types.hpp" -namespace api { +namespace smoke_api::api { struct SteamResponse { uint32_t success = 0; std::vector dlcs; @@ -13,10 +13,10 @@ namespace api { SteamResponse, success, dlcs - ) // NOLINT(misc-const-correctness) + ) }; - std::optional> fetch_dlcs_from_github(AppId_t app_id) noexcept { + std::optional> fetch_dlcs_from_github(const AppId_t app_id) { try { constexpr auto url = "https://raw.githubusercontent.com/" "acidicoala/public-entitlements/main/steam/v2/dlc.json"; @@ -30,12 +30,12 @@ namespace api { } } - std::optional> fetch_dlcs_from_steam(AppId_t app_id) noexcept { + std::optional> fetch_dlcs_from_steam(const AppId_t app_id) { try { // TODO: Communicate directly with Steam servers. // ref.: https://github.com/SteamRE/SteamKit const auto url = - fmt::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id); + std::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id); const auto json = koalabox::http_client::get_json(url); const auto [success, dlcs] = json.get(); @@ -47,7 +47,7 @@ namespace api { return dlcs; } catch(const std::exception& e) { LOG_ERROR("Failed to fetch dlc list from Steam: {}", e.what()); - return std::nullopt; + return {}; } } -} \ No newline at end of file +} diff --git a/src/smoke_api/api.hpp b/static/smoke_api/api.hpp similarity index 75% rename from src/smoke_api/api.hpp rename to static/smoke_api/api.hpp index b699d52..449f60c 100644 --- a/src/smoke_api/api.hpp +++ b/static/smoke_api/api.hpp @@ -2,8 +2,8 @@ #include "smoke_api/types.hpp" -namespace api { - std::optional> fetch_dlcs_from_github(AppId_t app_id) noexcept; +namespace smoke_api::api { + std::optional> fetch_dlcs_from_github(AppId_t app_id); - std::optional> fetch_dlcs_from_steam(AppId_t app_id) noexcept; + std::optional> fetch_dlcs_from_steam(AppId_t app_id); } diff --git a/src/smoke_api/cache.cpp b/static/smoke_api/cache.cpp similarity index 96% rename from src/smoke_api/cache.cpp rename to static/smoke_api/cache.cpp index 2eb5f1c..d565ea7 100644 --- a/src/smoke_api/cache.cpp +++ b/static/smoke_api/cache.cpp @@ -6,7 +6,7 @@ constexpr auto KEY_APPS = "apps"; namespace { - AppDlcNameMap get_cached_apps() noexcept { + AppDlcNameMap get_cached_apps() { try { return koalabox::cache::get(KEY_APPS).get(); } catch(const std::exception& e) { @@ -46,4 +46,4 @@ namespace smoke_api::cache { return false; } } -} \ No newline at end of file +} diff --git a/src/smoke_api/cache.hpp b/static/smoke_api/cache.hpp similarity index 100% rename from src/smoke_api/cache.hpp rename to static/smoke_api/cache.hpp diff --git a/src/smoke_api/config.cpp b/static/smoke_api/config.cpp similarity index 84% rename from src/smoke_api/config.cpp rename to static/smoke_api/config.cpp index 319dbb3..a7d8b10 100644 --- a/src/smoke_api/config.cpp +++ b/static/smoke_api/config.cpp @@ -6,17 +6,15 @@ #include "smoke_api/config.hpp" namespace smoke_api::config { - namespace kb = koalabox; - Config instance; // NOLINT(cert-err58-cpp) - std::vector get_extra_dlcs(const AppId_t app_id) { + std::vector get_extra_dlcs(const uint32_t app_id) { return DLC::get_dlcs_from_apps(instance.extra_dlcs, app_id); } bool is_dlc_unlocked( - AppId_t app_id, - AppId_t dlc_id, + const AppId_t app_id, + const AppId_t dlc_id, const std::function& original_function ) { auto status = instance.default_app_status; @@ -57,13 +55,4 @@ namespace smoke_api::config { return is_unlocked; } - - DLL_EXPORT(void) ReloadConfig - ( - ) - { - LOG_INFO("Reloading config"); - - instance = kb::config::parse(); - } -} \ No newline at end of file +} diff --git a/src/smoke_api/config.hpp b/static/smoke_api/config.hpp similarity index 93% rename from src/smoke_api/config.hpp rename to static/smoke_api/config.hpp index e7d24af..4c4fdf1 100644 --- a/src/smoke_api/config.hpp +++ b/static/smoke_api/config.hpp @@ -53,12 +53,8 @@ namespace smoke_api::config { std::vector get_extra_dlcs(AppId_t app_id); bool is_dlc_unlocked( - uint32_t app_id, - uint32_t dlc_id, + AppId_t app_id, + AppId_t dlc_id, const std::function& original_function ); - - DLL_EXPORT(void) ReloadConfig - ( - ); -} \ No newline at end of file +} diff --git a/src/steam_interface/steam_apps.cpp b/static/smoke_api/interfaces/steam_apps.cpp similarity index 91% rename from src/steam_interface/steam_apps.cpp rename to static/smoke_api/interfaces/steam_apps.cpp index 8582570..9cc1f17 100644 --- a/src/steam_interface/steam_apps.cpp +++ b/static/smoke_api/interfaces/steam_apps.cpp @@ -3,7 +3,7 @@ #include #include -#include "steam_interface/steam_apps.hpp" +#include "smoke_api/interfaces/steam_apps.hpp" #include "smoke_api/api.hpp" #include "smoke_api/cache.hpp" #include "smoke_api/config.hpp" @@ -15,10 +15,10 @@ namespace { /// This means we have to get extra DLC IDs from local config, remote config, or cache. constexpr auto MAX_DLC = 64; - std::map> app_dlcs; // NOLINT(cert-err58-cpp) - std::set fully_fetched; // NOLINT(cert-err58-cpp) + std::map> app_dlcs; // NOLINT(cert-err58-cpp) + std::set fully_fetched; // NOLINT(cert-err58-cpp) - std::string get_app_id_log(const AppId_t app_id) { + std::string get_app_id_log(const uint32_t app_id) { return app_id ? fmt::format("App ID: {:>8}, ", app_id) : ""; } @@ -57,12 +57,12 @@ namespace { append_dlcs(smoke_api::config::get_extra_dlcs(app_id), "local config"); - const auto github_dlcs_opt = api::fetch_dlcs_from_github(app_id); + const auto github_dlcs_opt = smoke_api::api::fetch_dlcs_from_github(app_id); if(github_dlcs_opt) { append_dlcs(*github_dlcs_opt, "GitHub repository"); } - const auto steam_dlcs_opt = api::fetch_dlcs_from_steam(app_id); + const auto steam_dlcs_opt = smoke_api::api::fetch_dlcs_from_steam(app_id); if(steam_dlcs_opt) { append_dlcs(*steam_dlcs_opt, "Steam API"); } @@ -80,11 +80,11 @@ namespace { } } -namespace steam_apps { +namespace smoke_api::steam_apps { bool IsDlcUnlocked( const std::string& function_name, - AppId_t app_id, - AppId_t dlc_id, + const AppId_t app_id, + const AppId_t dlc_id, const std::function& original_function ) { try { @@ -147,12 +147,12 @@ namespace steam_apps { bool GetDLCDataByIndex( const std::string& function_name, - AppId_t app_id, + const AppId_t app_id, int iDLC, AppId_t* pDlcId, bool* pbAvailable, char* pchName, - int cchNameBufferSize, + const int cchNameBufferSize, const std::function& original_function, const std::function& is_originally_unlocked ) { @@ -178,7 +178,7 @@ namespace steam_apps { *pbAvailable = smoke_api::config::is_dlc_unlocked( app_id, *pDlcId, - [&]() { + [&] { return is_originally_unlocked(*pDlcId); } ); @@ -207,7 +207,7 @@ namespace steam_apps { *pbAvailable = smoke_api::config::is_dlc_unlocked( app_id, *pDlcId, - [&]() { + [&] { return *pbAvailable; } ); diff --git a/src/steam_interface/steam_apps.hpp b/static/smoke_api/interfaces/steam_apps.hpp similarity index 90% rename from src/steam_interface/steam_apps.hpp rename to static/smoke_api/interfaces/steam_apps.hpp index e0af894..f50e1e5 100644 --- a/src/steam_interface/steam_apps.hpp +++ b/static/smoke_api/interfaces/steam_apps.hpp @@ -2,7 +2,7 @@ #include "smoke_api/types.hpp" -namespace steam_apps { +namespace smoke_api::steam_apps { bool IsDlcUnlocked( const std::string& function_name, AppId_t app_id, @@ -26,6 +26,5 @@ namespace steam_apps { int cchNameBufferSize, const std::function& original_function, const std::function& is_originally_unlocked - // Aux function to resolve original dlc status ); } diff --git a/src/steam_interface/steam_inventory.cpp b/static/smoke_api/interfaces/steam_inventory.cpp similarity index 95% rename from src/steam_interface/steam_inventory.cpp rename to static/smoke_api/interfaces/steam_inventory.cpp index 815fee6..efd2320 100644 --- a/src/steam_interface/steam_inventory.cpp +++ b/static/smoke_api/interfaces/steam_inventory.cpp @@ -1,9 +1,9 @@ #include +#include "smoke_api/interfaces/steam_inventory.hpp" #include "smoke_api/config.hpp" -#include "steam_interface/steam_inventory.hpp" -namespace steam_inventory { +namespace smoke_api::steam_inventory { EResult GetResultStatus( const std::string& function_name, const SteamInventoryResult_t resultHandle, @@ -27,10 +27,10 @@ namespace steam_inventory { SteamItemDetails_t* pOutItemsArray, uint32_t* punOutItemsArraySize, const std::function& original_function, - const std::function& get_item_definition_ids + const std::function& get_item_definition_ids ) { static std::mutex section; - const std::lock_guard guard(section); + const std::lock_guard guard(section); const auto success = original_function(); @@ -136,7 +136,7 @@ namespace steam_inventory { SteamInventoryResult_t resultHandle, uint32_t unItemIndex, const char* pchPropertyName, - char* pchValueBuffer, + const char* pchValueBuffer, const uint32_t* punValueBufferSizeOut, const std::function& original_function ) { @@ -206,7 +206,7 @@ namespace steam_inventory { const auto success = original_function(); if(pOutBuffer != nullptr) { - std::string buffer((char*) pOutBuffer, *punOutBufferSize); + std::string buffer(static_cast(pOutBuffer), *punOutBufferSize); LOG_DEBUG("{} -> Handle: {}, Buffer: '{}'", function_name, resultHandle, buffer); } else { LOG_DEBUG( @@ -267,4 +267,4 @@ namespace steam_inventory { return true; } -} \ No newline at end of file +} diff --git a/src/steam_interface/steam_inventory.hpp b/static/smoke_api/interfaces/steam_inventory.hpp similarity index 92% rename from src/steam_interface/steam_inventory.hpp rename to static/smoke_api/interfaces/steam_inventory.hpp index 8dea55f..cbaf351 100644 --- a/src/steam_interface/steam_inventory.hpp +++ b/static/smoke_api/interfaces/steam_inventory.hpp @@ -2,7 +2,7 @@ #include "smoke_api/types.hpp" -namespace steam_inventory { +namespace smoke_api::steam_inventory { EResult GetResultStatus( const std::string& function_name, SteamInventoryResult_t resultHandle, @@ -15,7 +15,7 @@ namespace steam_inventory { SteamItemDetails_t* pOutItemsArray, uint32_t* punOutItemsArraySize, const std::function& original_function, - const std::function& get_item_definition_ids + const std::function& get_item_definition_ids ); bool GetResultItemProperty( @@ -23,7 +23,7 @@ namespace steam_inventory { SteamInventoryResult_t resultHandle, uint32_t unItemIndex, const char* pchPropertyName, - char* pchValueBuffer, + const char* pchValueBuffer, const uint32_t* punValueBufferSizeOut, const std::function& original_function ); @@ -63,4 +63,4 @@ namespace steam_inventory { CSteamID steamIDExpected, const std::function& original_function ); -} \ No newline at end of file +} diff --git a/src/steam_interface/steam_user.cpp b/static/smoke_api/interfaces/steam_user.cpp similarity index 85% rename from src/steam_interface/steam_user.cpp rename to static/smoke_api/interfaces/steam_user.cpp index 93ae9bf..52c3d9e 100644 --- a/src/steam_interface/steam_user.cpp +++ b/static/smoke_api/interfaces/steam_user.cpp @@ -1,13 +1,13 @@ #include +#include "smoke_api/interfaces/steam_user.hpp" #include "smoke_api/config.hpp" -#include "steam_interface/steam_user.hpp" -namespace steam_user { +namespace smoke_api::steam_user { EUserHasLicenseForAppResult UserHasLicenseForApp( const std::string& function_name, - AppId_t appId, - AppId_t dlcId, + const AppId_t appId, + const AppId_t dlcId, const std::function& original_function ) { const auto result = original_function(); @@ -20,7 +20,7 @@ namespace steam_user { const auto has_license = smoke_api::config::is_dlc_unlocked( appId, dlcId, - [&]() { + [&] { return result == k_EUserHasLicenseResultHasLicense; } ); @@ -31,4 +31,4 @@ namespace steam_user { ? k_EUserHasLicenseResultHasLicense : k_EUserHasLicenseResultDoesNotHaveLicense; } -} \ No newline at end of file +} diff --git a/src/steam_interface/steam_user.hpp b/static/smoke_api/interfaces/steam_user.hpp similarity index 88% rename from src/steam_interface/steam_user.hpp rename to static/smoke_api/interfaces/steam_user.hpp index e47b90b..57b790e 100644 --- a/src/steam_interface/steam_user.hpp +++ b/static/smoke_api/interfaces/steam_user.hpp @@ -2,11 +2,11 @@ #include "smoke_api/types.hpp" -namespace steam_user { +namespace smoke_api::steam_user { EUserHasLicenseForAppResult UserHasLicenseForApp( const std::string& function_name, AppId_t appId, AppId_t dlcId, const std::function& original_function ); -} \ No newline at end of file +} diff --git a/src/smoke_api/types.cpp b/static/smoke_api/types.cpp similarity index 81% rename from src/smoke_api/types.cpp rename to static/smoke_api/types.cpp index 3b68462..c670db7 100644 --- a/src/smoke_api/types.cpp +++ b/static/smoke_api/types.cpp @@ -1,10 +1,9 @@ #include "smoke_api/types.hpp" -std::vector DLC::get_dlcs_from_apps(const AppDlcNameMap& apps, AppId_t app_id) { +std::vector DLC::get_dlcs_from_apps(const AppDlcNameMap& apps, const AppId_t app_id) { std::vector dlcs; - const auto app_id_str = std::to_string(app_id); - if(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); for(auto const& [id, name] : app.dlcs) { @@ -23,4 +22,4 @@ DlcNameMap DLC::get_dlc_map_from_vector(const std::vector& dlcs) { } return map; -} \ No newline at end of file +} diff --git a/static/smoke_api/types.hpp b/static/smoke_api/types.hpp new file mode 100644 index 0000000..eb4473f --- /dev/null +++ b/static/smoke_api/types.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include + +#include + +// TODO: Replace with direct call +#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \ + static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(#FUNC, FUNC); + +#define DETOUR_ADDRESS(FUNC, ADDRESS) \ + koalabox::hook::detour_or_warn(ADDRESS, #FUNC, reinterpret_cast(FUNC)); + +using AppId_t = uint32_t; +using HSteamPipe = uint32_t; +using EResult = uint32_t; +using HSteamUser = uint32_t; +using SteamInventoryResult_t = uint32_t; +using SteamItemInstanceID_t = uint64_t; +using SteamItemDef_t = uint32_t; +using CSteamID = uint64_t; + +struct SteamItemDetails_t { + SteamItemInstanceID_t m_itemId; + uint32_t m_iDefinition; + uint16_t m_unQuantity; + uint16_t m_unFlags; // see ESteamItemFlags +}; + +// results from UserHasLicenseForApp +enum EUserHasLicenseForAppResult { + k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app + k_EUserHasLicenseResultDoesNotHaveLicense = 1, + // User does not have a license for the specified app + k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated +}; + +// These aliases exist solely to increase code readability + +using AppIdKey = std::string; +using DlcIdKey = std::string; +using DlcNameValue = std::string; +using DlcNameMap = std::map; + +struct App { + DlcNameMap dlcs; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(App, dlcs) // NOLINT(misc-const-correctness) +}; + +using AppDlcNameMap = std::map; + +class DLC { + // These 2 names must match the property names from Steam API + std::string appid; + std::string name; + +public: + explicit DLC() = default; + + explicit DLC(std::string appid, std::string name) : appid{std::move(appid)}, + name{std::move(name)} {} + + [[nodiscard]] std::string get_id_str() const { + return appid; + } + + [[nodiscard]] AppId_t get_id() const { + return std::stoi(appid); + } + + [[nodiscard]] std::string get_name() const { + return name; + } + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(DLC, appid, name) + + static std::vector get_dlcs_from_apps(const AppDlcNameMap& apps, AppId_t app_id); + + static DlcNameMap get_dlc_map_from_vector(const std::vector& dlcs); +}; \ No newline at end of file