mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-24 03:56:34 +00:00
1.5.8 (#17)
* remove d3dx9.dll dependency (still requires dx legacy sdk for development, but not for end users) * fix * Fix to allow gMod to be loaded as "d3d9.dll" Don't check for d3d9 functions when checking dll's, its not that deep. Fix to allow gMod to load "d3d9.dll" using the default method rather than defaulting to system directory * use d3dx sdk for wic texture loading until we figure out how to load volume/cube textures without it * fix jons commit * 1.5.7 * create warning message * pass correct pointer type, shouldn't matter but lets see * use Warning instead of Message for failed actions * need to use d3dpool_managed... * use specialised methods * actually do something in the Direct3DCreate9Ex method? * spaces * test loading WIC textures with modified WICTextureLoader9.cpp * include * Hook into GetProcAddress instead of d3d9 dll * extern "C" the Direct3DCreate9/Ex functions * turn on debug messages * add back in creating of our replacement textures, woopsies * add messages back in, not loading yet, debug later * remove SingleTexture stuff * dont rely on d3dx anymore :) * Tidied up assertion error box Added logic to use gmod as d3d9.dll or gmod.dll Added check to avoid recursive calls to create d3d9 * Remove unused func
This commit is contained in:
+122
-99
@@ -1,6 +1,5 @@
|
||||
#include "dll_main.h"
|
||||
|
||||
#include <array>
|
||||
#include <Windows.h>
|
||||
#include "Main.h"
|
||||
#include <Psapi.h>
|
||||
@@ -10,42 +9,29 @@
|
||||
|
||||
namespace {
|
||||
|
||||
#define DISABLE_HOOK(var) if(var) { MH_DisableHook(var);}
|
||||
|
||||
using Direct3DCreate9_type = IDirect3D9* (APIENTRY*)(UINT);
|
||||
using Direct3DCreate9Ex_type = HRESULT(APIENTRY*)(UINT SDKVersion, IDirect3D9Ex** ppD3D);
|
||||
using GetProcAddress_type = FARPROC(APIENTRY*)(HMODULE, LPCSTR);
|
||||
|
||||
// Pointer to original address of Direct3DCreate9
|
||||
Direct3DCreate9_type Direct3DCreate9_fn = nullptr;
|
||||
Direct3DCreate9_type Direct3DCreate9_ret = nullptr;
|
||||
|
||||
// Pointer to original address of Direct3DCreate9
|
||||
Direct3DCreate9Ex_type Direct3DCreate9Ex_fn = nullptr;
|
||||
Direct3DCreate9Ex_type Direct3DCreate9Ex_ret = nullptr;
|
||||
|
||||
GetProcAddress_type GetProcAddress_fn = nullptr;
|
||||
GetProcAddress_type GetProcAddress_ret = nullptr;
|
||||
|
||||
static FILE* stdout_proxy;
|
||||
static FILE* stderr_proxy;
|
||||
FILE* stdout_proxy;
|
||||
FILE* stderr_proxy;
|
||||
|
||||
// If not nullptr, we're responsible for freeing this library on termination
|
||||
HMODULE gMod_Loaded_d3d9_Module_Handle = nullptr;
|
||||
|
||||
// If this hModule called d3d9.dll?
|
||||
bool IsD3d9Dll(HMODULE hModule)
|
||||
{
|
||||
TCHAR szModuleName[MAX_PATH];
|
||||
ASSERT(GetModuleFileName(hModule, szModuleName, sizeof(szModuleName) / sizeof(*szModuleName)) > 0);
|
||||
const auto basename = strrchr(szModuleName, '\\');
|
||||
return basename && strcmp(basename + 1, "d3d9.dll") == 0;
|
||||
}
|
||||
|
||||
// Does this module contain exported function calls for creating a d3d9 device?
|
||||
bool HasD3d9Methods(HMODULE hModule)
|
||||
{
|
||||
return GetProcAddress(hModule, "Direct3DCreate9")
|
||||
&& GetProcAddress(hModule, "Direct3DCreate9Ex");
|
||||
}
|
||||
|
||||
HMODULE FindLoadedDll()
|
||||
{
|
||||
HMODULE FindLoadedModuleByName(const char* name, bool include_this_module = false) {
|
||||
HMODULE hModules[1024];
|
||||
HANDLE hProcess;
|
||||
DWORD cbNeeded;
|
||||
@@ -56,46 +42,137 @@ namespace {
|
||||
if (!EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded))
|
||||
return nullptr;
|
||||
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
|
||||
if (hModules[i] == gl_hThisInstance)
|
||||
if (hModules[i] == gl_hThisInstance && !include_this_module)
|
||||
continue;
|
||||
if (IsD3d9Dll(hModules[i])) {
|
||||
TCHAR szModuleName[MAX_PATH];
|
||||
ASSERT(GetModuleFileName(hModules[i], szModuleName, _countof(szModuleName)) > 0);
|
||||
const auto basename = strrchr(szModuleName, '\\');
|
||||
if (basename && stricmp(basename + 1, name) == 0)
|
||||
return hModules[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HMODULE LoadD3d9Dll()
|
||||
{
|
||||
HMODULE found = FindLoadedModuleByName("d3d9.dll");
|
||||
if (!found) {
|
||||
char executable_path[MAX_PATH]{};
|
||||
ASSERT(GetModuleFileName(GetModuleHandle(nullptr), executable_path, _countof(executable_path)) > 0);
|
||||
|
||||
char dll_path[MAX_PATH]{};
|
||||
ASSERT(GetModuleFileName(gl_hThisInstance, dll_path, _countof(dll_path)) > 0);
|
||||
|
||||
const auto exe_path = std::filesystem::path(executable_path);
|
||||
const auto gmod_path = std::filesystem::path(dll_path);
|
||||
|
||||
bool successful_load = false;
|
||||
|
||||
if (exe_path.parent_path() != gmod_path.parent_path()
|
||||
|| gmod_path.filename() != "d3d9.dll") {
|
||||
// Call basic LoadLibrary function; we're not in the same directory as the exe.
|
||||
gMod_Loaded_d3d9_Module_Handle = LoadLibrary("d3d9.dll");
|
||||
}
|
||||
if (!gMod_Loaded_d3d9_Module_Handle) {
|
||||
// Tried resolving d3d9.dll locally, didn't work. Try system directory
|
||||
char buffer[MAX_PATH] ;
|
||||
ASSERT(GetSystemDirectory(buffer, _countof(buffer)) > 0); //get the system directory, we need to open the original d3d9.dll
|
||||
|
||||
// Append dll name
|
||||
strcat_s(buffer, _countof(buffer), "\\d3d9.dll");
|
||||
gMod_Loaded_d3d9_Module_Handle = LoadLibrary(buffer);
|
||||
}
|
||||
|
||||
ASSERT(gMod_Loaded_d3d9_Module_Handle);
|
||||
|
||||
found = FindLoadedModuleByName("d3d9.dll");
|
||||
ASSERT(found && found == gMod_Loaded_d3d9_Module_Handle);
|
||||
}
|
||||
|
||||
DISABLE_HOOK(GetProcAddress_fn);
|
||||
// GetProcAddress, hooked via OnGetProcAddress
|
||||
Direct3DCreate9_ret = (Direct3DCreate9_type)GetProcAddress(found, "Direct3DCreate9");
|
||||
Direct3DCreate9Ex_ret = (Direct3DCreate9Ex_type)GetProcAddress(found, "Direct3DCreate9Ex");
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
FARPROC APIENTRY OnGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
|
||||
ASSERT(GetProcAddress_ret);
|
||||
if ((int)lpProcName < 0xffff)
|
||||
return GetProcAddress_ret(hModule, lpProcName); // lpProcName is ordinal offset, not string
|
||||
|
||||
if (strcmp(lpProcName, "Direct3DCreate9") == 0) {
|
||||
Direct3DCreate9_ret = (Direct3DCreate9_type)GetProcAddress_ret(hModule, lpProcName);
|
||||
return (FARPROC)Direct3DCreate9;
|
||||
}
|
||||
if (strcmp(lpProcName, "Direct3DCreate9Ex") == 0) {
|
||||
Direct3DCreate9Ex_ret = (Direct3DCreate9Ex_type)GetProcAddress_ret(hModule, lpProcName);
|
||||
return (FARPROC)Direct3DCreate9Ex;
|
||||
}
|
||||
return GetProcAddress_ret(hModule, lpProcName);
|
||||
}
|
||||
|
||||
// If the original d3d9 function is nullptr or points to gMod, load the actual d3d9 dll and redirect the addresses
|
||||
void CheckLoadD3d9Dll() {
|
||||
if (!(Direct3DCreate9_ret && Direct3DCreate9_ret != Direct3DCreate9)) {
|
||||
ASSERT(LoadD3d9Dll());
|
||||
ASSERT(Direct3DCreate9_ret && Direct3DCreate9_ret != Direct3DCreate9);
|
||||
}
|
||||
if (!(Direct3DCreate9Ex_ret && Direct3DCreate9Ex_ret != Direct3DCreate9Ex)) {
|
||||
ASSERT(LoadD3d9Dll());
|
||||
ASSERT(Direct3DCreate9Ex_ret && Direct3DCreate9Ex_ret != Direct3DCreate9Ex);
|
||||
}
|
||||
}
|
||||
|
||||
// There may be a sitation where more than 1 gmod is loaded; avoid recursions!
|
||||
bool creating_d3d9 = false;
|
||||
}
|
||||
|
||||
unsigned int gl_ErrorState = 0;
|
||||
HINSTANCE gl_hThisInstance = nullptr;
|
||||
|
||||
IDirect3D9* APIENTRY Direct3DCreate9(UINT SDKVersion)
|
||||
extern "C" IDirect3D9* APIENTRY Direct3DCreate9(UINT SDKVersion)
|
||||
{
|
||||
Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, Direct3DCreate9);
|
||||
Message("uMod_Direct3DCreate9: uMod %p\n", Direct3DCreate9);
|
||||
|
||||
ASSERT(Direct3DCreate9_ret);
|
||||
ASSERT(!creating_d3d9);
|
||||
creating_d3d9 = true;
|
||||
|
||||
DISABLE_HOOK(GetProcAddress_fn);
|
||||
CheckLoadD3d9Dll();
|
||||
|
||||
IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); //creating the original IDirect3D9 object
|
||||
ASSERT(pIDirect3D9_orig);
|
||||
|
||||
creating_d3d9 = false;
|
||||
|
||||
return new uMod_IDirect3D9(pIDirect3D9_orig); //return our object instead of the "real one"
|
||||
}
|
||||
|
||||
HRESULT APIENTRY Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D)
|
||||
extern "C" HRESULT APIENTRY Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D)
|
||||
{
|
||||
Message("uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, Direct3DCreate9Ex);
|
||||
Message("uMod_Direct3DCreate9Ex: uMod %p\n", Direct3DCreate9Ex);
|
||||
|
||||
ASSERT(Direct3DCreate9Ex_ret);
|
||||
ASSERT(!creating_d3d9);
|
||||
creating_d3d9 = true;
|
||||
|
||||
|
||||
DISABLE_HOOK(GetProcAddress_fn);
|
||||
CheckLoadD3d9Dll();
|
||||
|
||||
IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr;
|
||||
HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object
|
||||
|
||||
creating_d3d9 = false;
|
||||
|
||||
if (ret != S_OK)
|
||||
return ret;
|
||||
|
||||
// @Cleanup: should be we freeing pIDirect3D9Ex at the end of our own lifecycle?
|
||||
uMod_IDirect3D9Ex* pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig);
|
||||
ppD3D = (IDirect3D9Ex**)&pIDirect3D9Ex;
|
||||
const auto pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig);
|
||||
// original umod does not do this for some reason
|
||||
*ppD3D = static_cast<IDirect3D9Ex*>(pIDirect3D9Ex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -135,42 +212,29 @@ void InitInstance(HINSTANCE hModule)
|
||||
// Store the handle to this module
|
||||
gl_hThisInstance = hModule;
|
||||
|
||||
const auto d3d9_dll = LoadOriginalDll();
|
||||
ASSERT(d3d9_dll);
|
||||
// d3d9.dll shouldn't be loaded at this point.
|
||||
const auto d3d9_loaded = FindLoadedModuleByName("d3d9.dll");
|
||||
ASSERT(!d3d9_loaded);
|
||||
|
||||
MH_Initialize();
|
||||
|
||||
// Hook our loaded Dll's dx9 calls though to uMod's functions
|
||||
Direct3DCreate9_fn = reinterpret_cast<Direct3DCreate9_type>(GetProcAddress(d3d9_dll, "Direct3DCreate9"));
|
||||
ASSERT(Direct3DCreate9_fn);
|
||||
if (Direct3DCreate9_fn) {
|
||||
MH_CreateHook(Direct3DCreate9_fn, Direct3DCreate9, (void**)&Direct3DCreate9_ret);
|
||||
MH_EnableHook(Direct3DCreate9_fn);
|
||||
// Hook into LoadLibraryA - we'll do our hooks on the flip side
|
||||
GetProcAddress_fn = reinterpret_cast<GetProcAddress_type>(GetProcAddress);
|
||||
ASSERT(GetProcAddress_fn);
|
||||
if (GetProcAddress_fn) {
|
||||
MH_CreateHook(GetProcAddress_fn, OnGetProcAddress, (void**)&GetProcAddress_ret);
|
||||
MH_EnableHook(GetProcAddress_fn);
|
||||
}
|
||||
|
||||
Direct3DCreate9Ex_fn = reinterpret_cast<Direct3DCreate9Ex_type>(GetProcAddress(d3d9_dll, "Direct3DCreate9Ex"));
|
||||
ASSERT(Direct3DCreate9Ex_fn);
|
||||
if (Direct3DCreate9Ex_fn) {
|
||||
MH_CreateHook(Direct3DCreate9Ex_fn, Direct3DCreate9Ex, (void**)&Direct3DCreate9Ex_ret);
|
||||
MH_EnableHook(Direct3DCreate9Ex_fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ExitInstance()
|
||||
{
|
||||
if (Direct3DCreate9_fn)
|
||||
MH_DisableHook(Direct3DCreate9_fn);
|
||||
if (Direct3DCreate9Ex_fn)
|
||||
MH_DisableHook(Direct3DCreate9Ex_fn);
|
||||
DISABLE_HOOK(GetProcAddress_fn);
|
||||
|
||||
MH_Uninitialize();
|
||||
|
||||
// Release the system's d3d9.dll
|
||||
if (gMod_Loaded_d3d9_Module_Handle != nullptr) {
|
||||
ASSERT(FreeLibrary(gMod_Loaded_d3d9_Module_Handle));
|
||||
gMod_Loaded_d3d9_Module_Handle = nullptr;
|
||||
}
|
||||
if (gMod_Loaded_d3d9_Module_Handle)
|
||||
FreeLibrary(gMod_Loaded_d3d9_Module_Handle);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (stdout_proxy)
|
||||
@@ -184,44 +248,3 @@ void ExitInstance()
|
||||
#endif
|
||||
}
|
||||
|
||||
HMODULE LoadOriginalDll()
|
||||
{
|
||||
HMODULE found = FindLoadedDll();
|
||||
if (found)
|
||||
return found;
|
||||
|
||||
char executable_path[MAX_PATH]{};
|
||||
ASSERT(GetModuleFileName(GetModuleHandle(nullptr), executable_path, _countof(executable_path)) > 0);
|
||||
|
||||
char gMod_path[MAX_PATH]{};
|
||||
ASSERT(GetModuleFileName(gl_hThisInstance, gMod_path, _countof(gMod_path)) > 0);
|
||||
|
||||
const auto exe_fs_path = std::filesystem::path(executable_path);
|
||||
const auto gMod_fs_path = std::filesystem::path(gMod_path);
|
||||
|
||||
if (exe_fs_path.parent_path() != gMod_fs_path.parent_path()
|
||||
|| gMod_fs_path.filename() != "d3d9.dll") {
|
||||
// Call basic LoadLibrary function; we're not in the same directory as the exe.
|
||||
gMod_Loaded_d3d9_Module_Handle = LoadLibrary("d3d9.dll");
|
||||
}
|
||||
else {
|
||||
// We're in the same directory as the exe, and we're called 'd3d9.dll'. Calling vanilla "LoadLibrary" will be recursive!
|
||||
char buffer[MAX_PATH];
|
||||
ASSERT(GetSystemDirectory(buffer, _countof(buffer) > 0)); //get the system directory, we need to open the original d3d9.dll
|
||||
|
||||
// Append dll name
|
||||
strcat_s(buffer, _countof(buffer), "\\d3d9.dll");
|
||||
gMod_Loaded_d3d9_Module_Handle = LoadLibrary(buffer);
|
||||
}
|
||||
|
||||
ASSERT(gMod_Loaded_d3d9_Module_Handle);
|
||||
|
||||
found = FindLoadedDll();
|
||||
ASSERT(found && found == gMod_Loaded_d3d9_Module_Handle);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* We inject the dll into the game, thus we retour the original Direct3DCreate9 function to our MyDirect3DCreate9 function
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user