Skip to content

Commit

Permalink
Hook swap chain functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Noisyfox committed Jun 5, 2019
1 parent 0b819d2 commit b837073
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 10 deletions.
78 changes: 78 additions & 0 deletions Overlay/ApiHook.h
@@ -1,6 +1,7 @@
#pragma once

#include "framework.h"
#include "MinHook.h"

inline PVOID getVFunction(const PVOID obj, const int index)
{
Expand All @@ -17,3 +18,80 @@ inline PVOID getVFunction(const PVOID obj, const int index)

return pVTable[index];
}


template <
typename ReturnType,
typename... ArgumentType
>
class ApiHook
{
public:
using TargetFuncType = ReturnType(WINAPI*)(ArgumentType ...);

private:
TargetFuncType pHookedOriginalFunc_{nullptr};
TargetFuncType pTargetFunc_{nullptr};
TargetFuncType pHookFunc_{nullptr};

public:

ApiHook(TargetFuncType pTargetFunc, TargetFuncType pHookFunc):
pTargetFunc_(pTargetFunc), pHookFunc_(pHookFunc)
{
}

~ApiHook()
{
unhook();
}

bool hook()
{
if (!hooked())
{
auto s = MH_CreateHook(reinterpret_cast<LPVOID>(pTargetFunc_), reinterpret_cast<LPVOID>(pHookFunc_),
reinterpret_cast<LPVOID*>(&pHookedOriginalFunc_));
if (s == MH_OK)
{
s = MH_EnableHook(reinterpret_cast<LPVOID>(pTargetFunc_));
if (s == MH_OK)
{
_ASSERT(pHookedOriginalFunc_ != nullptr);
}
else
{
OutputDebugString(_T("MH_EnableHook failed!"));
MH_RemoveHook(reinterpret_cast<LPVOID>(pTargetFunc_));
pHookedOriginalFunc_ = nullptr;
}
}
else
{
OutputDebugString(_T("MH_CreateHook failed!"));
pHookedOriginalFunc_ = nullptr;
}
}

return hooked();
}

void unhook()
{
if (hooked())
{
MH_RemoveHook(reinterpret_cast<LPVOID>(pTargetFunc_));
pHookedOriginalFunc_ = nullptr;
}
}

ReturnType callOrigin(ArgumentType ... args)
{
return pHookedOriginalFunc_(std::forward<ArgumentType>(args)...);
}

bool hooked() const
{
return pHookedOriginalFunc_ != nullptr;
}
};
41 changes: 34 additions & 7 deletions Overlay/DXGISwapChainHook.cpp
Expand Up @@ -14,12 +14,23 @@ using DXGISwapChainPresent1WrapperType = MemberFuncWrapper<
CallingConvs::kStdcall, DXGISwapChainHook, HRESULT, IDXGISwapChain1*, UINT, UINT, _In_ const
DXGI_PRESENT_PARAMETERS*>;

using DXGISwapChainPresentHookType = ApiHook<HRESULT, IDXGISwapChain*, UINT, UINT>;
using DXGISwapChainResizeBuffersHookType = ApiHook<HRESULT, IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT>;
using DXGISwapChainResizeTargetHookType = ApiHook<HRESULT, IDXGISwapChain*, const DXGI_MODE_DESC*>;
using DXGISwapChainPresent1HookType = ApiHook<HRESULT, IDXGISwapChain1*, UINT, UINT,
_In_ const DXGI_PRESENT_PARAMETERS*>;

struct SwapChainHookedFunctions
{
std::unique_ptr<DXGISwapChainPresentWrapperType> Hooked_DXGISwapChainPresent{nullptr};
std::unique_ptr<DXGISwapChainResizeBuffersWrapperType> Hooked_DXGISwapChainResizeBuffers{nullptr};
std::unique_ptr<DXGISwapChainResizeTargetWrapperType> Hooked_DXGISwapChainResizeTarget{nullptr};
std::unique_ptr<DXGISwapChainPresent1WrapperType> Hooked_DXGISwapChainPresent1{nullptr};

std::unique_ptr<DXGISwapChainPresentHookType> DXGISwapChainPresentHook{nullptr};
std::unique_ptr<DXGISwapChainResizeBuffersHookType> DXGISwapChainResizeBuffersHook{nullptr};
std::unique_ptr<DXGISwapChainResizeTargetHookType> DXGISwapChainResizeTargetHook{nullptr};
std::unique_ptr<DXGISwapChainPresent1HookType> DXGISwapChainPresent1Hook{nullptr};
};

DXGISwapChainHook::DXGISwapChainHook()
Expand All @@ -39,13 +50,24 @@ DXGISwapChainHook::DXGISwapChainHook()

bool DXGISwapChainHook::hookSwapChain(IUnknownPtr<IDXGISwapChain> pSwapChain)
{
auto hookSuccess = true;

const auto pSwapChainPresentOrig = reinterpret_cast<DXGISwapChainPresentWrapperType::ExposedFuncType>(
getVFunction(pSwapChain.underlying(), 8));
const auto pSwapChainResizeBuffersOrig = reinterpret_cast<DXGISwapChainResizeBuffersWrapperType::ExposedFuncType>(
getVFunction(pSwapChain.underlying(), 13));
const auto pSwapChainResizeTargetOrig = reinterpret_cast<DXGISwapChainResizeTargetWrapperType::ExposedFuncType>(
getVFunction(pSwapChain.underlying(), 14));
// TODO: hook func
// Hook func
hookedFunctions_->DXGISwapChainPresentHook = std::make_unique<DXGISwapChainPresentHookType>(
pSwapChainPresentOrig, hookedFunctions_->Hooked_DXGISwapChainPresent->func());
hookSuccess &= hookedFunctions_->DXGISwapChainPresentHook->hook();
hookedFunctions_->DXGISwapChainResizeBuffersHook = std::make_unique<DXGISwapChainResizeBuffersHookType>(
pSwapChainResizeBuffersOrig, hookedFunctions_->Hooked_DXGISwapChainResizeBuffers->func());
hookSuccess &= hookedFunctions_->DXGISwapChainResizeBuffersHook->hook();
hookedFunctions_->DXGISwapChainResizeTargetHook = std::make_unique<DXGISwapChainResizeTargetHookType>(
pSwapChainResizeTargetOrig, hookedFunctions_->Hooked_DXGISwapChainResizeTarget->func());
hookSuccess &= hookedFunctions_->DXGISwapChainResizeTargetHook->hook();

IUnknownPtr<IDXGISwapChain1> pDXGISwapChain1;
auto hr = pSwapChain.queryInterface(pDXGISwapChain1);
Expand All @@ -55,30 +77,35 @@ bool DXGISwapChainHook::hookSwapChain(IUnknownPtr<IDXGISwapChain> pSwapChain)

const auto pSwapChainPresent1Orig = reinterpret_cast<DXGISwapChainPresent1WrapperType::ExposedFuncType>(
getVFunction(pDXGISwapChain1.underlying(), 22));
// TODO: hook func
// Hook func
hookedFunctions_->DXGISwapChainPresent1Hook = std::make_unique<DXGISwapChainPresent1HookType>(
pSwapChainPresent1Orig, hookedFunctions_->Hooked_DXGISwapChainPresent1->func());
hookSuccess &= hookedFunctions_->DXGISwapChainPresent1Hook->hook();
}

return true;
return hookSuccess;
}

HRESULT DXGISwapChainHook::presentHook(IDXGISwapChain* swapChain, UINT SyncInterval, UINT Flags)
{
return 0;
return hookedFunctions_->DXGISwapChainPresentHook->callOrigin(swapChain, SyncInterval, Flags);
}

HRESULT DXGISwapChainHook::resizeBuffersHook(IDXGISwapChain* swapChain, UINT BufferCount, UINT Width, UINT Height,
DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
return 0;
return hookedFunctions_->DXGISwapChainResizeBuffersHook->callOrigin(swapChain, BufferCount, Width, Height,
NewFormat, SwapChainFlags);
}

HRESULT DXGISwapChainHook::resizeTargetHook(IDXGISwapChain* swapChain, const DXGI_MODE_DESC* pNewTargetParameters)
{
return 0;
return hookedFunctions_->DXGISwapChainResizeTargetHook->callOrigin(swapChain, pNewTargetParameters);
}

HRESULT DXGISwapChainHook::present1Hook(IDXGISwapChain1* swapChain, UINT SyncInterval, UINT PresentFlags,
_In_ const DXGI_PRESENT_PARAMETERS* pPresentParameters)
{
return 0;
return hookedFunctions_->DXGISwapChainPresent1Hook->callOrigin(swapChain, SyncInterval, PresentFlags,
pPresentParameters);
}
6 changes: 3 additions & 3 deletions Overlay/Overlay.vcxproj.filters
Expand Up @@ -85,12 +85,12 @@
<ClInclude Include="IUnknownPtr.h">
<Filter>util</Filter>
</ClInclude>
<ClInclude Include="ApiHook.h">
<Filter>util</Filter>
</ClInclude>
<ClInclude Include="FunctionWrapper.h">
<Filter>hook</Filter>
</ClInclude>
<ClInclude Include="ApiHook.h">
<Filter>hook</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="json11.cpp">
Expand Down

0 comments on commit b837073

Please sign in to comment.