Skip to content

Commit

Permalink
Done moving to cmake build system.
Browse files Browse the repository at this point in the history
Added compatible linker_pc executable.
  • Loading branch information
T-Maxxx committed Jun 10, 2020
1 parent 46ead94 commit 883eca7
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 44 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ add_library(${PROJECT_NAME} SHARED ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PRIVATE src)

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SRC} ${INC})

set(LINKER_PATCH_DEPLOY_DIR $ENV{LINKER_PATCH_DEPLOY_DIR})
if (LINKER_PATCH_DEPLOY_DIR)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E echo "Copying library to game directory: ${LINKER_PATCH_DEPLOY_DIR}"
COMMAND "${CMAKE_COMMAND}" -E copy "$<TARGET_FILE:${PROJECT_NAME}>" "${LINKER_PATCH_DEPLOY_DIR}/lnkpatch.dll"
)
endif()
12 changes: 8 additions & 4 deletions src/Exports.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
#include "proxy_lib.hpp"

#pragma comment(linker, "/export:D3DXGetShaderOutputSemantics=_D3DXGetShaderOutputSemantics@12")
// pSemantics is D3DXSEMANTIC*
HRESULT WINAPI stub_D3DXGetShaderOutputSemantics(const DWORD *pFunction, void *pSemantics, UINT *pCount)
extern "C" HRESULT WINAPI D3DXGetShaderOutputSemantics(const DWORD *pFunction, void *pSemantics, UINT *pCount)
{
return CProxyLib::Instance().D3DXGetShaderOutputSemantics(pFunction, pSemantics, pCount);
}

#pragma comment(linker, "/export:D3DXCreateBuffer=_D3DXCreateBuffer@8")
// ppBuffer is LPD3DXBUFFER*
HRESULT WINAPI stub_D3DXCreateBuffer(DWORD NumBytes, DWORD ppBuffer)
extern "C" HRESULT WINAPI D3DXCreateBuffer(DWORD NumBytes, DWORD ppBuffer)
{
return CProxyLib::Instance().D3DXCreateBuffer(NumBytes, ppBuffer);
}

#pragma comment(linker, "/export:D3DXGetShaderInputSemantics=_D3DXGetShaderInputSemantics@12")
// pSemantics is D3DXSEMANTIC*
HRESULT WINAPI stub_D3DXGetShaderInputSemantics(const DWORD *pFunction, void *pSemantics, UINT *pCount)
extern "C" HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *pFunction, void *pSemantics, UINT *pCount)
{
return CProxyLib::Instance().D3DXGetShaderInputSemantics(pFunction, pSemantics, pCount);
}

#pragma comment(linker, "/export:D3DXGetShaderConstantTable=_D3DXGetShaderConstantTable@8")
// ppConstantTable is LPD3DXCONSTANTTABLE*
HRESULT WINAPI stub_D3DXGetShaderConstantTable(const DWORD *pFunction, void *ppConstantTable)
extern "C" HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *pFunction, void *ppConstantTable)
{
return CProxyLib::Instance().D3DXGetShaderConstantTable(pFunction, ppConstantTable);
}
5 changes: 4 additions & 1 deletion src/core/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@

namespace core
{
hooks::CNativeFunc<FPComAssert>& Com_Assert = hooks::CNativeFunc<FPComAssert>::Create(0x0048E6A0, 0x0048E806);
hooks::CNativeFunc<Com_Assert_t>& Com_Assert = hooks::CNativeFunc<Com_Assert_t>::Create(0x0048E6A0, 0x0048E806);
hooks::CNativeFunc<Com_PrintErrorf_t>& Com_PrintErrorf = hooks::CNativeFunc<Com_PrintErrorf_t>::Create(0x00412AC0, 0x00412C3F);
hooks::CNativeFunc<main_t>& main = hooks::CNativeFunc<main_t>::Create(0x00416060, 0x004160C2);
hooks::CNativeFunc<printf_t>& printf = hooks::CNativeFunc<printf_t>::Create(0x4B4778, 0x4B4826);
}
13 changes: 11 additions & 2 deletions src/core/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

namespace core
{
using FPComAssert = void(*)(const char *FilePath_, int Line_, int Unknown_, const char *MsgFormat_, ...);
extern hooks::CNativeFunc<FPComAssert>& Com_Assert;
using Com_Assert_t = void(*)(const char *FilePath_, int Line_, int Unknown_, const char *MsgFormat_, ...);
extern hooks::CNativeFunc<Com_Assert_t>& Com_Assert;

using Com_PrintErrorf_t = void(*)(int Channel_, const char* Format_, ...);
extern hooks::CNativeFunc<Com_PrintErrorf_t>& Com_PrintErrorf;

using main_t = int(*)(const int, const char**);
extern hooks::CNativeFunc<main_t>& main;

using printf_t = int(*)(const char*, ...);
extern hooks::CNativeFunc<printf_t>& printf;
}
16 changes: 8 additions & 8 deletions src/ep_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@
#include "module_manager.hpp"
#include "hooks/jump_hook.hpp"
#include "hooks/native_function.hpp"
#include "core/functions.hpp"

#include "modules/database.hpp"


using FPMain = int(__cdecl*)(const int argc, const char **const argv);

bool IsSuitableExe()
{
char path[MAX_PATH] = { '\0' };
GetModuleFileNameEx(GetCurrentProcess(), NULL, path, sizeof(path));

return GetFileHash_CRC32(path) == 0x21E01F1E;
return GetFileHash_CRC32(path) == 0x7168CCFE;
}


static int __cdecl FakeMain(const int argc, const char **const argv)
static int __cdecl HookedMain(const int argc, const char **const argv)
{
CModuleManager manager;
manager.AddModule<modules::CDatabase>();
manager.AddModule<modules::CDatabase>();

// Process modules' logic.
manager.InitGlobals();
manager.Patch();

// Call original untouched winmain.
return (hooks::CNativeFunc<FPMain>::Create(0x00416060, 0x004160C2))(argc, argv);
core::printf("IW3 linker patch by T-Max\n");

// Call original main.
return core::main(argc, argv);
}


void PatchEntryPoint()
{
hooks::CJumpHook::Create(0x004B7944, FakeMain, true);
hooks::CJumpHook::Create(0x004B7944, HookedMain, true);
}
16 changes: 7 additions & 9 deletions src/hooks/replace_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@
namespace hooks
{
CReplaceFunc::~CReplaceFunc()
{
assert(!m_pOriginalInstruction && "WTF? Destructor called earlier than Release method RECHECK urself");
}
{}

void CReplaceFunc::Install()
{
assert(!m_pOriginalInstruction);
m_pOriginalInstruction = new SJumpHook();
if (IsInstalled())
return;

ReadFromMemory(CBaseHook::GetStartAddress(), m_pOriginalInstruction);
ReadFromMemory(CBaseHook::GetStartAddress(), &m_Original);
SJumpHook hook;
hook.OpCode = 0xe9;
hook.JumpOffset = m_iRawTarget - CBaseHook::GetStartAddress() - sizeof(SJumpHook);
Expand All @@ -28,10 +26,10 @@ namespace hooks

void CReplaceFunc::Release()
{
WriteToMemory(CBaseHook::GetStartAddress(), m_pOriginalInstruction);
delete m_pOriginalInstruction;
m_pOriginalInstruction = nullptr;
if (!IsInstalled())
return;

WriteToMemory(CBaseHook::GetStartAddress(), &m_Original);
SetInstalled(false);
}
}
2 changes: 1 addition & 1 deletion src/hooks/replace_function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace hooks
};
#pragma pack(pop)

SJumpHook* m_pOriginalInstruction;
SJumpHook m_Original;
uint32_t m_iRawTarget;
};
}
10 changes: 5 additions & 5 deletions src/module_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ CModuleManager::~CModuleManager() = default;

void CModuleManager::InitGlobals() const
{
for (auto spModule : m_vModules)
for (const auto [_, spModule] : m_vModules)
spModule->InitGlobals();
}


void CModuleManager::Patch() const
{
for (auto spModule : m_vModules)
for (const auto [_, spModule] : m_vModules)
spModule->Patch();
}


bool CModuleManager::isModuleExist(const CModule* pModule_) const
bool CModuleManager::isModuleExist(const std::type_index& TI_) const
{
for (const auto spModule : m_vModules)
if (typeid(spModule) == typeid(pModule_))
for (const auto [ti, _] : m_vModules)
if (ti == TI_)
return true;

return false;
Expand Down
10 changes: 6 additions & 4 deletions src/module_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <vector>
#include <memory>
#include <cassert>
#include <typeindex>

class CModule;

Expand All @@ -15,20 +16,21 @@ class CModuleManager
void AddModule()
{
std::shared_ptr<CModule> spModule = std::make_unique<T>();
if (isModuleExist(spModule.get()))
std::type_index ti(typeid(T));
if (isModuleExist(ti))
{
assert(!"Module already exist");
return;
}

m_vModules.push_back(spModule);
m_vModules.emplace_back(ti, spModule);
}

void InitGlobals() const;
void Patch() const;

private:
bool isModuleExist(const CModule* pModule_) const;
bool isModuleExist(const std::type_index& TI_) const;

std::vector<std::shared_ptr<CModule>> m_vModules;
std::vector<std::pair<std::type_index, std::shared_ptr<CModule>>> m_vModules;
};
34 changes: 24 additions & 10 deletions src/proxy_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
#include <cstdio>


using FPD3DXGetShaderOutputSemantics = HRESULT(WINAPI*)(const DWORD* pFunction, void* pSemantics, UINT* pCount);
using FPD3DXCreateBuffer = HRESULT(WINAPI*)(DWORD NumBytes, DWORD ppBuffer);
using FPD3DXGetShaderInputSemantics = HRESULT(WINAPI*)(const DWORD* pFunction, void* pSemantics, UINT* pCount);
using FPD3DXGetShaderConstantTable = HRESULT(WINAPI*)(const DWORD* pFunction, void* ppConstantTable);


template<class FP>
FP GetLibFunction(HMODULE hLib_, const char* FunctionName_)
{
Expand Down Expand Up @@ -48,23 +42,43 @@ bool CProxyLib::IsReady() const

HRESULT CProxyLib::D3DXGetShaderOutputSemantics(const DWORD* pFunction, void* pSemantics, UINT* pCount)
{
return GetLibFunction<FPD3DXGetShaderOutputSemantics>(m_hOriginalLib, "D3DXGetShaderOutputSemantics")(pFunction, pSemantics, pCount);
using D3DXGetShaderOutputSemantics_t = HRESULT(WINAPI*)(const DWORD*, void*, UINT*);
static D3DXGetShaderOutputSemantics_t fn = nullptr;
if (!fn)
fn = GetLibFunction<D3DXGetShaderOutputSemantics_t>(m_hOriginalLib, "D3DXGetShaderOutputSemantics");

return fn ? fn(pFunction, pSemantics, pCount) : -1;
}


HRESULT CProxyLib::D3DXCreateBuffer(DWORD NumBytes, DWORD ppBuffer)
{
return GetLibFunction<FPD3DXCreateBuffer>(m_hOriginalLib, "D3DXCreateBuffer")(NumBytes, ppBuffer);
using D3DXCreateBuffer_t = HRESULT(WINAPI*)(DWORD, DWORD);
static D3DXCreateBuffer_t fn = nullptr;
if (!fn)
fn = GetLibFunction<D3DXCreateBuffer_t>(m_hOriginalLib, "D3DXCreateBuffer");

return fn ? fn(NumBytes, ppBuffer) : -1;
}


HRESULT CProxyLib::D3DXGetShaderInputSemantics(const DWORD* pFunction, void* pSemantics, UINT* pCount)
{
return GetLibFunction<FPD3DXGetShaderInputSemantics>(m_hOriginalLib, "D3DXGetShaderInputSemantics")(pFunction, pSemantics, pCount);
using D3DXGetShaderInputSemantics_t = HRESULT(WINAPI*)(const DWORD*, void*, UINT*);
static D3DXGetShaderInputSemantics_t fn = nullptr;
if (!fn)
fn = GetLibFunction<D3DXGetShaderInputSemantics_t>(m_hOriginalLib, "D3DXGetShaderInputSemantics");

return fn ? fn(pFunction, pSemantics, pCount) : -1;
}


HRESULT CProxyLib::D3DXGetShaderConstantTable(const DWORD* pFunction, void* ppConstantTable)
{
return GetLibFunction<FPD3DXGetShaderConstantTable>(m_hOriginalLib, "D3DXGetShaderConstantTable")(pFunction, ppConstantTable);
using FPD3DXGetShaderConstantTable_t = HRESULT(WINAPI*)(const DWORD*, void*);
static FPD3DXGetShaderConstantTable_t fn = nullptr;
if (!fn)
fn = GetLibFunction<FPD3DXGetShaderConstantTable_t>(m_hOriginalLib, "D3DXGetShaderConstantTable");

return fn ? fn(pFunction, ppConstantTable) : -1;
}
Binary file added thirdparty/linker_pc.exe
Binary file not shown.

0 comments on commit 883eca7

Please sign in to comment.