#include "Hook.h"
#include "Drawing.h"
LPDIRECT3DDEVICE9 Hook::pDevice = nullptr; // Direct3D9 Device Object
tEndScene Hook::oEndScene = nullptr; // Pointer of the original EndScene function
tReset Hook::oReset = nullptr; // Pointer of the original Reset function
HWND Hook::window = nullptr; // Window of the current process
HMODULE Hook::hDDLModule = nullptr; // HMODULE of the DLL
int Hook::windowHeight = 0; // Height of the window
int Hook::windowWidth = 0; // Width of the window
void* Hook::d3d9Device[119]; // Array of pointer of the DirectX functions.
WNDPROC Hook::OWndProc = nullptr; // Pointer of the original window message handler.
/**
[USER=1181103]@Brief[/USER] : Function that hook the Reset and EndScene function.
**/
void Hook::HookDirectX()
{
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device)))
{
oEndScene = (tEndScene)d3d9Device[42];
oReset = (tReset)d3d9Device[16];
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)oEndScene, Drawing::hkEndScene);
DetourAttach(&(PVOID&)oReset, hkReset);
DetourTransactionCommit();
}
}
/**
[USER=1181103]@Brief[/USER] : Function that unhook Reset and EnScene functions, and also disable the window message handler.
**/
void Hook::UnHookDirectX()
{
if (Drawing::bInit)
{
UnHookWindow();
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
Drawing::bInit = FALSE;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)oEndScene, Drawing::hkEndScene);
DetourDetach(&(PVOID&)oReset, hkReset);
DetourTransactionCommit();
}
/**
[USER=1181103]@Brief[/USER] : Function that enumerate windows.
**/
BOOL CALLBACK Hook::enumWind(const HWND handle, LPARAM lp)
{
DWORD procID;
GetWindowThreadProcessId(handle, &procID);
if (GetCurrentProcessId() != procID)
return TRUE;
window = handle;
return FALSE;
}
/**
[USER=1181103]@Brief[/USER] : Function that retrieve the window of the current process.
@retval : window of the current process.
**/
HWND Hook::GetProcessWindow()
{
window = nullptr;
EnumWindows(enumWind, NULL);
RECT size;
if (window == nullptr)
return nullptr;
GetWindowRect(window, &size);
windowWidth = size.right - size.left;
windowHeight = size.bottom - size.top;
windowHeight -= 29;
windowWidth -= 5;
return window;
}
/**
[USER=1181103]@Brief[/USER] : Function that get a Direct3D9 Device Object. (https://guidedhacking.com/threads/get-direct3d9-and-direct3d11-devices-dummy-device-method.11867/)
[USER=804731]@param[/USER] pTable : Array of functions pointer.
[USER=804731]@param[/USER] size : Size of the array of pointers.
@retval : True if the function succeed else False.
**/
BOOL Hook::GetD3D9Device(void** pTable, const size_t size)
{
if (!pTable)
return FALSE;
IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!pD3D)
return FALSE;
IDirect3DDevice9* pDummyDevice = nullptr;
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = GetProcessWindow();
d3dpp.Windowed = (GetWindowLongPtr(d3dpp.hDeviceWindow, GWL_STYLE) & WS_POPUP) != 0 ? FALSE : TRUE;
if (HRESULT dummyDevCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice); dummyDevCreated != S_OK)
{
d3dpp.Windowed = !d3dpp.Windowed;
dummyDevCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
if (dummyDevCreated != S_OK)
{
pD3D->Release();
return FALSE;
}
}
memcpy(pTable, [I](void**[/I])(pDummyDevice), size);
pDummyDevice->Release();
pD3D->Release();
return TRUE;
}
/**
[USER=1181103]@Brief[/USER] : Function that setup the WndProc callback function.
**/
void Hook::HookWindow()
{
OWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)WndProc);
}
/**
[USER=1181103]@Brief[/USER] : Function that disable the WndProc callback function.
**/
void Hook::UnHookWindow()
{
SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)OWndProc);
}
/**
[USER=1181103]@Brief[/USER] : A callback function, which you define in your application, that processes messages sent to a window. (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc)
[USER=804731]@param[/USER] hWnd : A handle to the window.
[USER=804731]@param[/USER] msg : The message.
[USER=804731]@param[/USER] wParam : Additional message information.
[USER=804731]@param[/USER] lParam : Additional message information.
@retval : The return value is the result of the message processing, and depends on the message sent.
**/
LRESULT WINAPI Hook::WndProc(const HWND hWnd, const UINT msg, const WPARAM wParam, const LPARAM lParam)
{
if (Drawing::bDisplay && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
{
ImGui::GetIO().MouseDrawCursor = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
return true;
}
if(Drawing::bInit)
ImGui::GetIO().MouseDrawCursor = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
if (msg == WM_CLOSE)
{
UnHookDirectX();
UnHookWindow();
TerminateProcess(GetCurrentProcess(), 0);
}
if (ImGui::GetIO().WantCaptureMouse)
{
if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
return true;
return false;
}
return CallWindowProc(OWndProc, hWnd, msg, wParam, lParam);
}
/**
[USER=1181103]@Brief[/USER] : Hook of the function IDirect3DDevice9::Reset, to handle resize, etc...
[USER=804731]@param[/USER] pDevice : Direct3D9 Device Object
[USER=804731]@param[/USER] pPresentationParameters : parameters passed to the original function.
@retval : return value of the original function.
**/
HRESULT Hook::hkReset(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
HRESULT tmpReset = oReset(pDevice, pPresentationParameters);
ImGui_ImplDX9_CreateDeviceObjects();
return tmpReset;
}