mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
149 lines
4.6 KiB
C++
149 lines
4.6 KiB
C++
#include <functional>
|
|
#include <set>
|
|
|
|
#include <Windows.h>
|
|
#include <winternl.h>
|
|
#include <d3dkmthk.h>
|
|
|
|
#include <Common/Hook.h>
|
|
#include <Common/Log.h>
|
|
#include <D3dDdi/Adapter.h>
|
|
#include <D3dDdi/AdapterCallbacks.h>
|
|
#include <D3dDdi/AdapterFuncs.h>
|
|
#include <D3dDdi/Hooks.h>
|
|
#include <D3dDdi/KernelModeThunks.h>
|
|
#include <D3dDdi/ScopedCriticalSection.h>
|
|
#include <D3dDdi/Log/KernelModeThunksLog.h>
|
|
#include <Dll/Dll.h>
|
|
|
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_OPENADAPTER& data)
|
|
{
|
|
return Compat::LogStruct(os)
|
|
<< data.hAdapter
|
|
<< data.Interface
|
|
<< data.Version
|
|
<< data.pAdapterCallbacks
|
|
<< Compat::out(data.pAdapterFuncs)
|
|
<< data.DriverVersion;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
struct D3D9ON12_CREATE_DEVICE_ARGS {};
|
|
|
|
typedef HRESULT(APIENTRY* PFND3D9ON12_OPENADAPTER)(
|
|
D3DDDIARG_OPENADAPTER* pOpenAdapter, LUID* pLUID, D3D9ON12_CREATE_DEVICE_ARGS* pArgs);
|
|
typedef HRESULT(APIENTRY* PFND3D9ON12_KMTPRESENT)(
|
|
HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs);
|
|
|
|
struct D3D9ON12_PRIVATE_DDI_TABLE
|
|
{
|
|
PFND3D9ON12_OPENADAPTER pfnOpenAdapter;
|
|
FARPROC pfnGetSharedGDIHandle;
|
|
FARPROC pfnCreateSharedNTHandle;
|
|
FARPROC pfnGetDeviceState;
|
|
PFND3D9ON12_KMTPRESENT pfnKMTPresent;
|
|
};
|
|
|
|
void APIENTRY getPrivateDdiTable(D3D9ON12_PRIVATE_DDI_TABLE* pPrivateDDITable);
|
|
HRESULT APIENTRY kmtPresent(HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs);
|
|
HRESULT APIENTRY openAdapter(D3DDDIARG_OPENADAPTER* pOpenData);
|
|
HRESULT APIENTRY openAdapterPrivate(D3DDDIARG_OPENADAPTER* pOpenData, LUID* pLUID, D3D9ON12_CREATE_DEVICE_ARGS* pArgs);
|
|
|
|
decltype(&getPrivateDdiTable) g_origGetPrivateDdiTable = nullptr;
|
|
PFND3DDDI_OPENADAPTER g_origOpenAdapter = nullptr;
|
|
PFND3D9ON12_OPENADAPTER g_origOpenAdapterPrivate = nullptr;
|
|
PFND3D9ON12_KMTPRESENT g_origKmtPresent = nullptr;
|
|
|
|
void APIENTRY getPrivateDdiTable(D3D9ON12_PRIVATE_DDI_TABLE* pPrivateDDITable)
|
|
{
|
|
LOG_FUNC("GetPrivateDDITable", pPrivateDDITable);
|
|
g_origGetPrivateDdiTable(pPrivateDDITable);
|
|
g_origOpenAdapterPrivate = pPrivateDDITable->pfnOpenAdapter;
|
|
g_origKmtPresent = pPrivateDDITable->pfnKMTPresent;
|
|
pPrivateDDITable->pfnOpenAdapter = &openAdapterPrivate;
|
|
pPrivateDDITable->pfnKMTPresent = &kmtPresent;
|
|
}
|
|
|
|
FARPROC WINAPI getProcAddress(HMODULE hModule, LPCSTR lpProcName)
|
|
{
|
|
LOG_FUNC("GetProcAddress", hModule, lpProcName);
|
|
if (lpProcName)
|
|
{
|
|
if ("OpenAdapter" == std::string(lpProcName))
|
|
{
|
|
g_origOpenAdapter = reinterpret_cast<PFND3DDDI_OPENADAPTER>(
|
|
CALL_ORIG_FUNC(GetProcAddress)(hModule, lpProcName));
|
|
if (g_origOpenAdapter)
|
|
{
|
|
static std::set<HMODULE> hookedModules;
|
|
if (hookedModules.find(hModule) == hookedModules.end())
|
|
{
|
|
LOG_INFO << "Hooking user mode display driver: " << Compat::funcPtrToStr(g_origOpenAdapter);
|
|
Dll::pinModule(hModule);
|
|
hookedModules.insert(hModule);
|
|
}
|
|
return reinterpret_cast<FARPROC>(&openAdapter);
|
|
}
|
|
}
|
|
else if ("GetPrivateDDITable" == std::string(lpProcName))
|
|
{
|
|
g_origGetPrivateDdiTable = reinterpret_cast<decltype(&getPrivateDdiTable)>(
|
|
CALL_ORIG_FUNC(GetProcAddress)(hModule, lpProcName));
|
|
if (g_origGetPrivateDdiTable)
|
|
{
|
|
return reinterpret_cast<FARPROC>(&getPrivateDdiTable);
|
|
}
|
|
}
|
|
}
|
|
return LOG_RESULT(CALL_ORIG_FUNC(GetProcAddress)(hModule, lpProcName));
|
|
}
|
|
|
|
HRESULT APIENTRY kmtPresent(HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs)
|
|
{
|
|
LOG_FUNC("KMTPresent", hDevice, pKMTArgs);
|
|
D3dDdi::KernelModeThunks::fixPresent(*pKMTArgs);
|
|
return LOG_RESULT(g_origKmtPresent(hDevice, pKMTArgs));
|
|
}
|
|
|
|
HRESULT openAdapterCommon(D3DDDIARG_OPENADAPTER* pOpenData, std::function<HRESULT()> origOpenAdapter)
|
|
{
|
|
if (pOpenData->Interface > 7)
|
|
{
|
|
return origOpenAdapter();
|
|
}
|
|
|
|
D3dDdi::ScopedCriticalSection lock;
|
|
D3dDdi::AdapterCallbacks::hookVtable(*pOpenData->pAdapterCallbacks, pOpenData->Version);
|
|
HRESULT result = origOpenAdapter();
|
|
if (SUCCEEDED(result))
|
|
{
|
|
D3dDdi::AdapterFuncs::hookVtable(*pOpenData->pAdapterFuncs, pOpenData->DriverVersion);
|
|
D3dDdi::Adapter::add(*pOpenData);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
HRESULT APIENTRY openAdapter(D3DDDIARG_OPENADAPTER* pOpenData)
|
|
{
|
|
LOG_FUNC("OpenAdapter", pOpenData);
|
|
return LOG_RESULT(openAdapterCommon(pOpenData, [=]() { return g_origOpenAdapter(pOpenData); }));
|
|
}
|
|
|
|
HRESULT APIENTRY openAdapterPrivate(D3DDDIARG_OPENADAPTER* pOpenData, LUID* pLUID, D3D9ON12_CREATE_DEVICE_ARGS* pArgs)
|
|
{
|
|
LOG_FUNC("OpenAdapter_Private", pOpenData, pLUID, pArgs);
|
|
return LOG_RESULT(openAdapterCommon(pOpenData, [=]() { return g_origOpenAdapterPrivate(pOpenData, pLUID, pArgs); }));
|
|
}
|
|
}
|
|
|
|
namespace D3dDdi
|
|
{
|
|
void installHooks()
|
|
{
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "GetProcAddress", getProcAddress);
|
|
|
|
KernelModeThunks::installHooks();
|
|
}
|
|
}
|