1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Fixed crash when rehooking a user-mode display driver

This commit is contained in:
narzoul 2018-12-30 12:41:23 +01:00
parent c1b35e0434
commit d655947f18
9 changed files with 52 additions and 32 deletions

View File

@ -41,17 +41,25 @@ public:
}
}
static void hookDriverVtable(HANDLE context, const Vtable* vtable)
static void hookDriverVtable(HMODULE module, HANDLE context, const Vtable* vtable)
{
if (vtable && s_origVtables.find(context) == s_origVtables.end())
if (!vtable)
{
HookVisitor<DriverHook> visitor(*vtable, s_origVtables[context]);
return;
}
if (s_origModuleVtables.find(module) == s_origModuleVtables.end())
{
HookVisitor<DriverHook> visitor(*vtable, s_origModuleVtables[module]);
forEach<Vtable>(visitor);
}
s_origVtables[context] = s_origModuleVtables[module];
}
static Vtable s_origVtable;
static std::map<HANDLE, Vtable> s_origVtables;
static std::map<HMODULE, Vtable> s_origModuleVtables;
static const Vtable* s_origVtablePtr;
private:
@ -185,6 +193,9 @@ Vtable CompatVtable<Vtable>::s_origVtable = {};
template <typename Vtable>
std::map<HANDLE, Vtable> CompatVtable<Vtable>::s_origVtables;
template <typename Vtable>
std::map<HMODULE, Vtable> CompatVtable<Vtable>::s_origModuleVtables;
template <typename Vtable>
const Vtable* CompatVtable<Vtable>::s_origVtablePtr = nullptr;

View File

@ -7,6 +7,7 @@
namespace
{
std::map<HANDLE, D3DNTHAL_D3DEXTENDEDCAPS> g_d3dExtendedCaps;
std::map<HANDLE, HMODULE> g_adapterModule;
HRESULT APIENTRY closeAdapter(HANDLE hAdapter)
{
@ -15,6 +16,7 @@ namespace
{
D3dDdi::AdapterFuncs::s_origVtables.erase(hAdapter);
g_d3dExtendedCaps.erase(hAdapter);
g_adapterModule.erase(hAdapter);
}
return result;
}
@ -26,7 +28,8 @@ namespace
hAdapter, pCreateData);
if (SUCCEEDED(result))
{
D3dDdi::DeviceFuncs::hookDriverVtable(pCreateData->hDevice, pCreateData->pDeviceFuncs);
D3dDdi::DeviceFuncs::hookDriverVtable(
g_adapterModule[hAdapter], pCreateData->hDevice, pCreateData->pDeviceFuncs);
D3dDdi::DeviceFuncs::onCreateDevice(hAdapter, pCreateData->hDevice);
}
return result;
@ -52,7 +55,7 @@ namespace D3dDdi
return it != g_d3dExtendedCaps.end() ? it->second : emptyCaps;
}
void AdapterFuncs::onOpenAdapter(HANDLE adapter)
void AdapterFuncs::onOpenAdapter(HMODULE module, HANDLE adapter)
{
D3DNTHAL_D3DEXTENDEDCAPS d3dExtendedCaps = {};
D3DDDIARG_GETCAPS getCaps = {};
@ -62,6 +65,7 @@ namespace D3dDdi
D3dDdi::AdapterFuncs::s_origVtables.at(adapter).pfnGetCaps(adapter, &getCaps);
g_d3dExtendedCaps[adapter] = d3dExtendedCaps;
g_adapterModule[adapter] = module;
}
void AdapterFuncs::setCompatVtable(D3DDDI_ADAPTERFUNCS& vtable)

View File

@ -14,7 +14,7 @@ namespace D3dDdi
{
public:
static const D3DNTHAL_D3DEXTENDEDCAPS& getD3dExtendedCaps(HANDLE adapter);
static void onOpenAdapter(HANDLE adapter);
static void onOpenAdapter(HMODULE module, HANDLE adapter);
static void setCompatVtable(D3DDDI_ADAPTERFUNCS& vtable);
};
}

View File

@ -162,7 +162,7 @@ namespace D3dDdi
if (SUCCEEDED(result))
{
m_oversizedResources.emplace(data.hResource,
OversizedResource(m_adapter, m_device, data.Format, origSurfList[0]));
OversizedResource(*m_origVtable, m_adapter, m_device, data.Format, origSurfList[0]));
}
return result;
@ -191,7 +191,7 @@ namespace D3dDdi
if (SUCCEEDED(result) && data.Flags.RenderTarget && !data.Flags.Primary && isVidMemPool(data.Pool))
{
m_renderTargetResources.emplace(data.hResource,
RenderTargetResource(m_device, data.hResource, data.Format, data.SurfCount));
RenderTargetResource(*m_origVtable, m_device, data.hResource, data.Format, data.SurfCount));
}
return result;

View File

@ -26,6 +26,7 @@ namespace
{
UINT g_ddiVersion = 0;
std::wstring g_hookedUmdFileName;
HMODULE g_hookedUmdModule = nullptr;
PFND3DDDI_OPENADAPTER g_origOpenAdapter = nullptr;
void hookOpenAdapter(const std::wstring& umdFileName);
@ -35,12 +36,12 @@ namespace
void hookOpenAdapter(const std::wstring& umdFileName)
{
g_hookedUmdFileName = umdFileName;
HMODULE module = LoadLibraryW(umdFileName.c_str());
if (module)
g_hookedUmdModule = LoadLibraryW(umdFileName.c_str());
if (g_hookedUmdModule)
{
Compat::hookFunction(module, "OpenAdapter",
Compat::hookFunction(g_hookedUmdModule, "OpenAdapter",
reinterpret_cast<void*&>(g_origOpenAdapter), &openAdapter);
FreeLibrary(module);
FreeLibrary(g_hookedUmdModule);
}
}
@ -58,8 +59,8 @@ namespace
hookedUmdFileNames.insert(g_hookedUmdFileName);
}
g_ddiVersion = min(pOpenData->Version, pOpenData->DriverVersion);
D3dDdi::AdapterFuncs::hookDriverVtable(pOpenData->hAdapter, pOpenData->pAdapterFuncs);
D3dDdi::AdapterFuncs::onOpenAdapter(pOpenData->hAdapter);
D3dDdi::AdapterFuncs::hookDriverVtable(g_hookedUmdModule, pOpenData->hAdapter, pOpenData->pAdapterFuncs);
D3dDdi::AdapterFuncs::onOpenAdapter(g_hookedUmdModule, pOpenData->hAdapter);
}
return LOG_RESULT(result);
}

View File

@ -6,8 +6,10 @@
namespace D3dDdi
{
OversizedResource::OversizedResource(
HANDLE adapter, HANDLE device, D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo)
: m_adapter(adapter)
const D3DDDI_DEVICEFUNCS& deviceFuncs, HANDLE adapter, HANDLE device,
D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo)
: m_deviceFuncs(deviceFuncs)
, m_adapter(adapter)
, m_device(device)
, m_format(format)
, m_surfaceInfo(surfaceInfo)
@ -20,7 +22,7 @@ namespace D3dDdi
if (rect.right <= static_cast<LONG>(caps.dwMaxTextureWidth) &&
rect.bottom <= static_cast<LONG>(caps.dwMaxTextureHeight))
{
return D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnBlt(m_device, &data);
return m_deviceFuncs.pfnBlt(m_device, &data);
}
HANDLE origResource = resource;
@ -33,14 +35,13 @@ namespace D3dDdi
rect = RECT{ 0, 0, rect.right - rect.left, rect.bottom - rect.top };
}
const auto& deviceFuncs = D3dDdi::DeviceFuncs::s_origVtables.at(m_device);
HRESULT result = deviceFuncs.pfnBlt(m_device, &data);
HRESULT result = m_deviceFuncs.pfnBlt(m_device, &data);
if (bltResource)
{
resource = origResource;
rect = origRect;
deviceFuncs.pfnDestroyResource(m_device, bltResource);
m_deviceFuncs.pfnDestroyResource(m_device, bltResource);
}
return result;
@ -76,14 +77,13 @@ namespace D3dDdi
bltResourceData.pSurfList = &bltSurfaceInfo;
bltResourceData.SurfCount = 1;
const auto& deviceFuncs = D3dDdi::DeviceFuncs::s_origVtables.at(m_device);
if (deviceFuncs.pfnCreateResource2)
if (m_deviceFuncs.pfnCreateResource2)
{
deviceFuncs.pfnCreateResource2(m_device, &bltResourceData);
m_deviceFuncs.pfnCreateResource2(m_device, &bltResourceData);
}
else
{
deviceFuncs.pfnCreateResource(m_device,
m_deviceFuncs.pfnCreateResource(m_device,
reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&bltResourceData));
}
return bltResourceData.hResource;

View File

@ -8,7 +8,7 @@ namespace D3dDdi
class OversizedResource
{
public:
OversizedResource(HANDLE adapter, HANDLE device,
OversizedResource(const D3DDDI_DEVICEFUNCS& deviceFuncs, HANDLE adapter, HANDLE device,
D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo);
HRESULT bltFrom(D3DDDIARG_BLT data);
@ -20,6 +20,7 @@ namespace D3dDdi
HRESULT blt(D3DDDIARG_BLT& data, HANDLE& resource, RECT& rect);
HANDLE createBltResource(RECT bltRect);
const D3DDDI_DEVICEFUNCS& m_deviceFuncs;
HANDLE m_adapter;
HANDLE m_device;
D3DDDIFORMAT m_format;

View File

@ -4,9 +4,10 @@
namespace D3dDdi
{
RenderTargetResource::RenderTargetResource(
RenderTargetResource::RenderTargetResource(const D3DDDI_DEVICEFUNCS& deviceFuncs,
HANDLE device, HANDLE resource, D3DDDIFORMAT format, UINT surfaceCount)
: m_device(device)
: m_deviceFuncs(deviceFuncs)
, m_device(device)
, m_resource(resource)
, m_bytesPerPixel(getBytesPerPixel(format))
, m_subResources(surfaceCount, SubResource(*this))
@ -17,7 +18,7 @@ namespace D3dDdi
{
if (data.SubResourceIndex >= m_subResources.size())
{
return D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnLock(m_device, &data);
return m_deviceFuncs.pfnLock(m_device, &data);
}
auto& subResource = m_subResources[data.SubResourceIndex];
@ -36,7 +37,7 @@ namespace D3dDdi
const UINT origFlags = data.Flags.Value;
data.Flags.Value = 0;
const HRESULT result = D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnLock(m_device, &data);
const HRESULT result = m_deviceFuncs.pfnLock(m_device, &data);
data.Flags.Value = origFlags;
if (SUCCEEDED(result))
@ -54,7 +55,7 @@ namespace D3dDdi
{
if (data.SubResourceIndex >= m_subResources.size())
{
return D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnUnlock(m_device, &data);
return m_deviceFuncs.pfnUnlock(m_device, &data);
}
m_subResources[data.SubResourceIndex].isLocked = false;
@ -88,7 +89,7 @@ namespace D3dDdi
D3DDDIARG_UNLOCK data = {};
data.hResource = m_resource;
data.SubResourceIndex = subResourceIndex;
D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnUnlock(m_device, &data);
m_deviceFuncs.pfnUnlock(m_device, &data);
subResource.surfacePtr = nullptr;
subResource.pitch = 0;

View File

@ -11,7 +11,8 @@ namespace D3dDdi
class RenderTargetResource
{
public:
RenderTargetResource(HANDLE device, HANDLE resource, D3DDDIFORMAT format, UINT surfaceCount);
RenderTargetResource(const D3DDDI_DEVICEFUNCS& deviceFuncs,
HANDLE device, HANDLE resource, D3DDDIFORMAT format, UINT surfaceCount);
HRESULT lock(D3DDDIARG_LOCK& data);
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
@ -33,6 +34,7 @@ namespace D3dDdi
void prepareSubResourceForRendering(UINT subResourceIndex);
const D3DDDI_DEVICEFUNCS& m_deviceFuncs;
HANDLE m_device;
HANDLE m_resource;
UINT m_bytesPerPixel;