Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ add_library(OpenSteamTool SHARED

# Per-category hook modules
Hook/HookManager.cpp
Hook/Hooks_CallBack.cpp
Hook/Hooks_Decryption.cpp
Hook/Hooks_IPC.cpp
Hook/Hooks_IPC_ISteamUser.cpp
Expand Down
55 changes: 38 additions & 17 deletions src/Hook/HookMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// ─────────────────────────────────────────────────────────────────
// Hook boilerplate elimination macros.
//
// Convention: macros ending in _D use diversion_hMdoule as module.
// Convention: macros ending in _D use client_hModule as module.
// Standard macros (no _D suffix) take an explicit module argument.
// ─────────────────────────────────────────────────────────────────

Expand Down Expand Up @@ -44,26 +44,21 @@
inline name##_t o##name = nullptr; \
ret __fastcall hk##name(__VA_ARGS__)


// ── install ─────────────────────────────────────────────────────
// Call between HOOK_BEGIN / HOOK_END.
#define INSTALL_HOOK(module, name) \
do { \
void* _p_ = FIND_SIG(module, name); \
if (_p_) { \
o##name = (name##_t)_p_; \
DetourAttach(reinterpret_cast<PVOID*>(&o##name), \
reinterpret_cast<PVOID>(hk##name)); \
} \
} while (0)
do { \
void* _p_ = FIND_SIG(module, name); \
if (_p_) { \
o##name = (name##_t)_p_; \
DetourAttach(reinterpret_cast<PVOID*>(&o##name), \
reinterpret_cast<PVOID>(hk##name)); \
} \
} while (0)

#define INSTALL_HOOK_D(name) INSTALL_HOOK(diversion_hMdoule, name)

// ── resolve ─────────────────────────────────────────────────────
// Find signature → cast to name##_t → assign to o##name. No Detours.
#define RESOLVE(module, name) \
o##name = reinterpret_cast<name##_t>(FIND_SIG(module, name))

#define RESOLVE_D(name) RESOLVE(diversion_hMdoule, name)
#define INSTALL_HOOK_C(name) INSTALL_HOOK(client_hModule, name)
#define INSTALL_HOOK_U(name) INSTALL_HOOK(ui_hModule, name)

// ── uninstall ───────────────────────────────────────────────────
// Call between UNHOOK_BEGIN / UNHOOK_END.
Expand All @@ -75,3 +70,29 @@
o##name = nullptr; \
} \
} while (0)
#define UNINSTALL_HOOK_C(name) UNINSTALL_HOOK(name)
#define UNINSTALL_HOOK_U(name) UNINSTALL_HOOK(name)

// ── resolve function definition ────────────────────────────────────
// RESOLVE_FUNC(CUtlMemoryGrow, void*, CUtlVector<AppId_t>*, int);
// generates:
// using CUtlMemoryGrow_t = void*(__fastcall*)(CUtlVector<AppId_t>*, int);
// inline CUtlMemoryGrow_t oCUtlMemoryGrow = nullptr;
#define RESOLVE_FUNC(name, ret, ...) \
using name##_t = ret(__fastcall*)(__VA_ARGS__); \
inline name##_t o##name = nullptr

// ── resolve ─────────────────────────────────────────────────────
// Find signature → cast to name##_t → assign to o##name.
#define RESOLVE(module, name) \
do { \
void* _p_ = FIND_SIG(module, name); \
if (_p_) { \
o##name = reinterpret_cast<name##_t>(_p_); \
} \
} while (0)

#define RESOLVE_C(name) RESOLVE(client_hModule, name)
#define RESOLVE_U(name) RESOLVE(ui_hModule, name)


14 changes: 12 additions & 2 deletions src/Hook/HookManager.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "HookManager.h"
#include "Hooks_CallBack.h"
#include "Hooks_Decryption.h"
#include "Hooks_IPC.h"
#include "Hooks_KeyValues.h"
Expand All @@ -7,17 +8,23 @@
#include "Hooks_NetPacket.h"
#include "Hooks_Package.h"
#include "Hooks_SteamUI.h"
#include "Utils/VehCommon.h"


namespace SteamUI {

void CoreHook() { Hooks_SteamUI::Install(); }
void CoreUnhook() { Hooks_SteamUI::Uninstall(); }
void CoreHook() {
Hooks_SteamUI::Install();
}
void CoreUnhook() {
Hooks_SteamUI::Uninstall();
}
}

namespace SteamClient {

void CoreHook() {
Hooks_CallBack::Install();
Hooks_Decryption::Install();
Hooks_IPC::Install();
// Hooks_KeyValues::Install();
Expand All @@ -28,12 +35,15 @@ namespace SteamClient {
}

void CoreUnhook() {
Hooks_CallBack::Uninstall();
Hooks_Decryption::Uninstall();
Hooks_IPC::Uninstall();
// Hooks_KeyValues::Uninstall();
Hooks_Manifest::Uninstall();
Hooks_Misc::Uninstall();
Hooks_NetPacket::Uninstall();
Hooks_Package::Uninstall();
VehCommon::DisarmAll();
VehCommon::RemoveHandler();
}
}
29 changes: 29 additions & 0 deletions src/Hook/Hooks_CallBack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "Hooks_CallBack.h"
#include "HookMacros.h"
#include "dllmain.h"
namespace {

HOOK_FUNC(SendCallbackToPipe, bool, void* pSteamEngine, HSteamPipe hSteamPipe,
HSteamUser iClientUser, int iCallback, void* pCallbackData, int cubCallbackData) {
// ── Callback modifier dispatch ─────────────────────────────────────────
// Intercept callbacks before they reach the pipe and modify data in-place.
// To add a new callback: add an else-if branch here.

return oSendCallbackToPipe(pSteamEngine, hSteamPipe, iClientUser,
iCallback, pCallbackData, cubCallbackData);
}
}

namespace Hooks_CallBack {
void Install() {
HOOK_BEGIN();
INSTALL_HOOK_C(SendCallbackToPipe);
HOOK_END();
}

void Uninstall() {
UNHOOK_BEGIN();
UNINSTALL_HOOK_C(SendCallbackToPipe);
UNHOOK_END();
}
}
7 changes: 7 additions & 0 deletions src/Hook/Hooks_CallBack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

namespace Hooks_CallBack {
// CallBack hook: handles various callback events.
void Install();
void Uninstall();
}
4 changes: 2 additions & 2 deletions src/Hook/Hooks_Decryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ namespace {
namespace Hooks_Decryption {
void Install() {
HOOK_BEGIN();
INSTALL_HOOK_D(LoadDepotDecryptionKey);
INSTALL_HOOK_C(LoadDepotDecryptionKey);
HOOK_END();
}

void Uninstall() {
UNHOOK_BEGIN();
UNINSTALL_HOOK(LoadDepotDecryptionKey);
UNINSTALL_HOOK_C(LoadDepotDecryptionKey);
UNHOOK_END();
}
}
17 changes: 7 additions & 10 deletions src/Hook/Hooks_IPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

namespace {

using GetPipeClient_t = CSteamPipeClient*(*)(void* pEngine, HSteamPipe hSteamPipe);
GetPipeClient_t oGetPipeClient = nullptr;
RESOLVE_FUNC(GetPipeClient, CSteamPipeClient*, void* pEngine, HSteamPipe hSteamPipe);

static CSteamPipeClient* GetPipe(void* pServer, HSteamPipe hSteamPipe) {
return oGetPipeClient ? oGetPipeClient(pServer, hSteamPipe) : nullptr;
Expand All @@ -36,7 +35,7 @@ namespace {
void* pServer, HSteamPipe hSteamPipe,
CUtlBuffer* pRead, CUtlBuffer* pWrite)
{
auto* pipe = GetPipe(pServer, hSteamPipe);
CSteamPipeClient* pipe = GetPipe(pServer, hSteamPipe);

// ── Parse header, find handler ──────────────────────────
const IpcHandlerEntry* entry = nullptr;
Expand All @@ -60,14 +59,14 @@ namespace {
LOG_IPC_DEBUG("[InterfaceCall] {} {} realAppId={},AppId={}",
entry->name, pipe->DebugString(),
Hooks_Misc::ResolveAppId(),
Hooks_Misc::GetAppIDForCurrentPipe()
Hooks_Misc::GetAppIDForCurrentPipeWrap()
);
} else {
LOG_IPC_TRACE("[InterfaceCall(unhandled)]{}::0x{:08X} {} realAppId={},AppId={}",
EIPCInterfaceName(iface), funcHash,
pipe->DebugString(),
Hooks_Misc::ResolveAppId(),
Hooks_Misc::GetAppIDForCurrentPipe()
Hooks_Misc::GetAppIDForCurrentPipeWrap()
);
}
} else {
Expand Down Expand Up @@ -101,23 +100,21 @@ namespace Hooks_IPC {
}

void Install() {
RESOLVE_D(GetPipeClient);
RESOLVE_C(GetPipeClient);

// Interface modules register their handlers here.
Hooks_IPC_ISteamUser::Register();
Hooks_IPC_ISteamUtils::Register();

HOOK_BEGIN();
INSTALL_HOOK_D(IPCProcessMessage);
INSTALL_HOOK_C(IPCProcessMessage);
HOOK_END();
}

void Uninstall() {
UNHOOK_BEGIN();
UNINSTALL_HOOK(IPCProcessMessage);
UNINSTALL_HOOK_C(IPCProcessMessage);
UNHOOK_END();
oGetPipeClient = nullptr;
g_Handlers.clear();
}

}
6 changes: 5 additions & 1 deletion src/Hook/Hooks_IPC_ISteamUser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ namespace {

const uint32 ticketSize = static_cast<uint32>(ticket.size());
const int32 totalSize = 1 + 1 + 4 + ticketSize;
Hooks_Misc::EnsureBufferSize(pWrite, totalSize);
if (!Hooks_Misc::EnsureBufferSize(pWrite, totalSize)) {
LOG_IPC_DEBUG("GetEncryptedAppTicket: AppId={} - failed to ensure buffer size", appId);
return;
}
pWrite->m_Put = totalSize;

uint8* base = pWrite->Base();
base[0] = RESPONSE_PREFIX;
Expand Down
2 changes: 1 addition & 1 deletion src/Hook/Hooks_IPC_ISteamUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ namespace {
const auto* req = reinterpret_cast<const GetAPICallResultRequest*>(
pRead->Base() + OFFSET_ARGS);

AppId_t appId = Hooks_Misc::GetAppIDForCurrentPipe();
AppId_t appId = Hooks_Misc::GetAppIDForCurrentPipeWrap();
LOG_IPC_DEBUG("GetAPICallResult: hAsyncCall=0x{:016X} AppId={} iCallback={} cubCallback={}",
req->hSteamAPICall, appId, req->iCallbackExpected, req->cubCallback);
for (auto& entry : g_GacrDispatch) {
Expand Down
34 changes: 14 additions & 20 deletions src/Hook/Hooks_KeyValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@

namespace {

HOOK_FUNC(ReadAsBinary, bool, KeyValues* root, void* buf, int depth,
bool textMode, void* symTable) {
bool ok = oReadAsBinary(root, buf, depth, textMode, symTable);
return ok;
RESOLVE_FUNC(FindOrCreateKey, KeyValues*, KeyValues* parent, const char* name, bool create, KeyValues** out);
KeyValues* KV_FindKey(KeyValues* parent, const char* name) {
return oFindOrCreateKey ? oFindOrCreateKey(parent, name, false, nullptr) : nullptr;
}

using FindOrCreateKey_t = KeyValues*(*)(KeyValues*, const char*, bool, KeyValues**);
FindOrCreateKey_t oFindOrCreateKey = nullptr;


// ── KeyValuesSystem — symbol ↔ string (from vstdlib_s64.dll) ───

IKeyValuesSystem* GetKeyValuesSystem() {
static IKeyValuesSystem* sys = []() -> IKeyValuesSystem* {
HMODULE vstdlib = GetModuleHandleW(L"vstdlib_s64.dll");
Expand All @@ -27,37 +22,36 @@ namespace {
}();
return sys;
}

const char* GetKeyName(int symbol) {
auto* sys = GetKeyValuesSystem();
auto name = sys->GetStringForSymbol(symbol);
LOG_KEYVALUE_TRACE("GetKeyName: symbol={} -> name={}", symbol, name);
return name ? name : nullptr;
}

KeyValues* KV_FindKey(KeyValues* parent, const char* name) {
return oFindOrCreateKey ? oFindOrCreateKey(parent, name, false, nullptr) : nullptr;

HOOK_FUNC(ReadAsBinary, bool, KeyValues* root, void* buf, int depth,
bool textMode, void* symTable) {
bool ok = oReadAsBinary(root, buf, depth, textMode, symTable);
return ok;
}

} // anonymous namespace

namespace Hooks_KeyValues {

void Install() {
RESOLVE_D(FindOrCreateKey);
if (!oFindOrCreateKey) return;

RESOLVE_C(FindOrCreateKey);

HOOK_BEGIN();
INSTALL_HOOK_D(ReadAsBinary);
INSTALL_HOOK_C(ReadAsBinary);
HOOK_END();
}

void Uninstall() {
if (!oReadAsBinary) return;
UNHOOK_BEGIN();
UNINSTALL_HOOK(ReadAsBinary);
UNINSTALL_HOOK_C(ReadAsBinary);
UNHOOK_END();
oFindOrCreateKey = nullptr;
}

} // namespace Hooks_KeyValues
2 changes: 1 addition & 1 deletion src/Hook/Hooks_Manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ namespace Hooks_Manifest {

void Install() {
HOOK_BEGIN();
INSTALL_HOOK_D(BuildDepotDependency);
INSTALL_HOOK_C(BuildDepotDependency);
HOOK_END();
}

Expand Down
Loading
Loading