Added hook retry.

Handed hook detection to a thread that can then retry.
With that, don't need to wait for loadLibrary.
Will remove all those commented functions in another version.
merge-requests/28/head
Nemirtingas 2019-08-19 18:57:55 +02:00
parent 5893b69d1f
commit c99628a88a
2 changed files with 85 additions and 94 deletions

View File

@ -17,23 +17,18 @@
#include <algorithm> #include <algorithm>
#ifdef STEAM_WIN32 #ifdef STEAM_WIN32
decltype(LoadLibraryA )* _LoadLibraryA = LoadLibraryA; static decltype(&IDXGISwapChain::Present) _IDXGISwapChain_Present;
decltype(LoadLibraryW )* _LoadLibraryW = LoadLibraryW; static decltype(&IDirect3DDevice9::Present) _IDirect3DDevice9_Present;
decltype(LoadLibraryExA )* _LoadLibraryExA = LoadLibraryExA; static decltype(&IDirect3DDevice9Ex::PresentEx) _IDirect3DDevice9Ex_PresentEx;
decltype(LoadLibraryExW )* _LoadLibraryExW = LoadLibraryExW; static decltype(wglMakeCurrent)* _wglMakeCurrent;
decltype(&IDXGISwapChain::Present) _IDXGISwapChain_Present;
decltype(&IDirect3DDevice9::Present) _IDirect3DDevice9_Present;
decltype(&IDirect3DDevice9Ex::PresentEx) _IDirect3DDevice9Ex_PresentEx;
decltype(wglMakeCurrent)* _wglMakeCurrent;
HRESULT STDMETHODCALLTYPE Hook_Manager::MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags) HRESULT STDMETHODCALLTYPE Hook_Manager::MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags)
{ {
Hook_Manager& inst = Hook_Manager::Inst(); Hook_Manager& inst = Hook_Manager::Inst();
if (!inst.stop_retry()) if (!inst.stop_retry())
{ {
IUnknown* pDevice; IUnknown* pDevice = nullptr;
_this->GetDevice(__uuidof(ID3D10Device), (void**)& pDevice); _this->GetDevice(__uuidof(ID3D10Device), (void**)&pDevice);
if (pDevice) if (pDevice)
{ {
DX10_Hook* hook = DX10_Hook::Inst(); DX10_Hook* hook = DX10_Hook::Inst();
@ -324,7 +319,7 @@ void Hook_Manager::hook_opengl()
} }
} }
void Hook_Manager::create_hookA(const char* libname) void Hook_Manager::create_hook(const char* libname)
{ {
if (!_stricmp(libname, "d3d9.dll")) if (!_stricmp(libname, "d3d9.dll"))
Hook_Manager::Inst().hook_dx9(); Hook_Manager::Inst().hook_dx9();
@ -338,47 +333,47 @@ void Hook_Manager::create_hookA(const char* libname)
Hook_Manager::Inst().hook_opengl(); Hook_Manager::Inst().hook_opengl();
} }
void Hook_Manager::create_hookW(const wchar_t *libname) //void Hook_Manager::create_hookW(const wchar_t *libname)
{ //{
if (!_wcsicmp(libname, L"d3d9.dll")) // if (!_wcsicmp(libname, L"d3d9.dll"))
Hook_Manager::Inst().hook_dx9(); // Hook_Manager::Inst().hook_dx9();
else if (!_wcsicmp(libname, L"d3d10.dll")) // else if (!_wcsicmp(libname, L"d3d10.dll"))
Hook_Manager::Inst().hook_dx10(); // Hook_Manager::Inst().hook_dx10();
else if (!_wcsicmp(libname, L"d3d11.dll")) // else if (!_wcsicmp(libname, L"d3d11.dll"))
Hook_Manager::Inst().hook_dx11(); // Hook_Manager::Inst().hook_dx11();
else if (!_wcsicmp(libname, L"d3d12.dll")) // else if (!_wcsicmp(libname, L"d3d12.dll"))
Hook_Manager::Inst().hook_dx12(); // Hook_Manager::Inst().hook_dx12();
else if (!_wcsicmp(libname, L"opengl32.dll")) // else if (!_wcsicmp(libname, L"opengl32.dll"))
Hook_Manager::Inst().hook_opengl(); // Hook_Manager::Inst().hook_opengl();
} //}
//
HMODULE WINAPI Hook_Manager::MyLoadLibraryA(LPCTSTR lpLibFileName) //HMODULE WINAPI Hook_Manager::MyLoadLibraryA(LPCTSTR lpLibFileName)
{ //{
auto res = _LoadLibraryA(lpLibFileName); // auto res = _LoadLibraryA(lpLibFileName);
Hook_Manager::Inst().create_hookA(lpLibFileName); // Hook_Manager::Inst().create_hookA(lpLibFileName);
return res; // return res;
} //}
//
HMODULE WINAPI Hook_Manager::MyLoadLibraryW(LPCWSTR lpLibFileName) //HMODULE WINAPI Hook_Manager::MyLoadLibraryW(LPCWSTR lpLibFileName)
{ //{
auto res = _LoadLibraryW(lpLibFileName); // auto res = _LoadLibraryW(lpLibFileName);
Hook_Manager::Inst().create_hookW(lpLibFileName); // Hook_Manager::Inst().create_hookW(lpLibFileName);
return res; // return res;
} //}
//
HMODULE WINAPI Hook_Manager::MyLoadLibraryExA(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) //HMODULE WINAPI Hook_Manager::MyLoadLibraryExA(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{ //{
auto res = _LoadLibraryA(lpLibFileName); // auto res = _LoadLibraryA(lpLibFileName);
Hook_Manager::Inst().create_hookA(lpLibFileName); // Hook_Manager::Inst().create_hookA(lpLibFileName);
return res; // return res;
} //}
//
HMODULE WINAPI Hook_Manager::MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) //HMODULE WINAPI Hook_Manager::MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{ //{
auto res = _LoadLibraryExW(lpLibFileName, hFile, dwFlags); // auto res = _LoadLibraryExW(lpLibFileName, hFile, dwFlags);
Hook_Manager::Inst().create_hookW(lpLibFileName); // Hook_Manager::Inst().create_hookW(lpLibFileName);
return res; // return res;
} //}
bool Hook_Manager::stop_retry() bool Hook_Manager::stop_retry()
{ {
@ -394,25 +389,33 @@ bool Hook_Manager::stop_retry()
return stop; return stop;
} }
void Hook_Manager::HookLoadLibrary() void Hook_Manager::find_renderer(Hook_Manager* _this)
{ {
if (!_renderer_found && !_loadlibrary_hooked) _this->rendererdetect_hook = new Base_Hook();
_this->AddHook(_this->rendererdetect_hook);
std::vector<std::string> const libraries = { "opengl32.dll", "d3d12.dll", "d3d11.dll", "d3d10.dll", "d3d9.dll" };
while (!_this->_renderer_found && !_this->stop_retry())
{ {
_loadlibrary_hooked = true; std::vector<std::string>::const_iterator it = libraries.begin();
while (it != libraries.end())
{
it = std::find_if(it, libraries.end(), [](std::string const& name) {
auto x = GetModuleHandle(name.c_str());
if (x != NULL)
return true;
return false;
});
rendererdetect_hook = new Base_Hook(); if (it == libraries.end())
AddHook(rendererdetect_hook); break;
rendererdetect_hook->BeginHook(); _this->create_hook(it->c_str());
++it;
}
rendererdetect_hook->HookFuncs( std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::pair<void**, void*>((PVOID*)& _LoadLibraryA, &Hook_Manager::MyLoadLibraryA),
std::pair<void**, void*>((PVOID*)& _LoadLibraryW, &Hook_Manager::MyLoadLibraryW),
std::pair<void**, void*>((PVOID*)& _LoadLibraryExA, &Hook_Manager::MyLoadLibraryExA),
std::pair<void**, void*>((PVOID*)& _LoadLibraryExW, &Hook_Manager::MyLoadLibraryExW)
);
rendererdetect_hook->EndHook();
} }
} }
@ -444,24 +447,7 @@ Hook_Manager& Hook_Manager::Inst()
void Hook_Manager::HookRenderer() void Hook_Manager::HookRenderer()
{ {
#ifdef STEAM_WIN32 #ifdef STEAM_WIN32
HookLoadLibrary(); _hook_thread = new std::thread(&Hook_Manager::find_renderer, this);
std::vector<std::string> const libraries = { "opengl32.dll", "d3d12.dll", "d3d11.dll", "d3d10.dll", "d3d9.dll" };
std::vector<std::string>::const_iterator it = libraries.begin();
while (it != libraries.end())
{
it = std::find_if(it, libraries.end(), [](std::string const& name) {
auto x = GetModuleHandle(name.c_str());
if (x != 0 && x != INVALID_HANDLE_VALUE)
return true;
return false;
});
if (it == libraries.end())
break;
create_hookA(it->c_str());
++it;
}
#endif #endif
} }
@ -471,6 +457,9 @@ void Hook_Manager::FoundRenderer(Base_Hook* hook)
{ {
_renderer_found = true; _renderer_found = true;
_hook_thread->join();
delete _hook_thread;
// Remove all hooks that are unused // Remove all hooks that are unused
_hooks.erase(std::remove_if(_hooks.begin(), _hooks.end(), [&hook](Base_Hook* it_hook) { _hooks.erase(std::remove_if(_hooks.begin(), _hooks.end(), [&hook](Base_Hook* it_hook) {
if (hook != it_hook) if (hook != it_hook)
@ -480,8 +469,6 @@ void Hook_Manager::FoundRenderer(Base_Hook* hook)
} }
return false; return false;
}), _hooks.end()); }), _hooks.end());
_loadlibrary_hooked = false;
} }
} }

View File

@ -6,6 +6,7 @@
#ifndef NO_OVERLAY #ifndef NO_OVERLAY
#include <vector> #include <vector>
#include <thread>
#if defined(_WIN32) || defined(WIN32) #if defined(_WIN32) || defined(WIN32)
#include <Windows.h> #include <Windows.h>
@ -31,6 +32,7 @@ protected:
// If you do that, you should consider moving the renderer hooks to its own class and keep this one generic ? // If you do that, you should consider moving the renderer hooks to its own class and keep this one generic ?
std::vector<Base_Hook*> _hooks; std::vector<Base_Hook*> _hooks;
std::thread *_hook_thread;
unsigned int _hook_retries; unsigned int _hook_retries;
bool _renderer_found; // Is the renderer hooked ? bool _renderer_found; // Is the renderer hooked ?
bool _ogl_hooked; // wglMakeCurrent is hooked ? (opengl) bool _ogl_hooked; // wglMakeCurrent is hooked ? (opengl)
@ -44,7 +46,7 @@ protected:
void hook_opengl(); void hook_opengl();
bool stop_retry(); bool stop_retry();
void HookLoadLibrary(); //void HookLoadLibrary();
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
bool _loadlibrary_hooked; // Are the LoadLibrary functions hooked ? bool _loadlibrary_hooked; // Are the LoadLibrary functions hooked ?
@ -66,13 +68,15 @@ protected:
// Setup DX12 Device and get vtable // Setup DX12 Device and get vtable
void hook_dx12(); void hook_dx12();
void create_hookA(const char* libname); void create_hook(const char* libname);
void create_hookW(const wchar_t* libname); //void create_hookW(const wchar_t* libname);
static HMODULE WINAPI MyLoadLibraryA(LPCTSTR lpLibFileName); static void find_renderer(Hook_Manager* _this);
static HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName);
static HMODULE WINAPI MyLoadLibraryExA(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); //static HMODULE WINAPI MyLoadLibraryA(LPCTSTR lpLibFileName);
static HMODULE WINAPI MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); //static HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName);
//static HMODULE WINAPI MyLoadLibraryExA(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
//static HMODULE WINAPI MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
// If this is called, then DX10, DX11 or DX12 will be used to render overlay // If this is called, then DX10, DX11 or DX12 will be used to render overlay
static HRESULT STDMETHODCALLTYPE MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags); static HRESULT STDMETHODCALLTYPE MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags);
// If any of theses is called, then DX9 will be used to render overlay // If any of theses is called, then DX9 will be used to render overlay