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:
parent
c1b35e0434
commit
d655947f18
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user