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

Fixed a race condition leading to a crash when installing hooks

See issue #306.
This commit is contained in:
narzoul 2024-05-20 18:01:32 +02:00
parent ed40a6d5e9
commit 24bb72138d
2 changed files with 60 additions and 50 deletions

View File

@ -336,6 +336,7 @@ namespace DDraw
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd)
{
DDraw::ScopedThreadLock lock;
static std::map<LUID, CompatWeakPtr<IDirectDraw7>> repositories;
auto adapterInfo = D3dDdi::KernelModeThunks::getAdapterInfo(dd);
auto it = repositories.find(adapterInfo.luid);

View File

@ -20,6 +20,7 @@
#include <DDraw/DirectDraw.h>
#include <DDraw/Hooks.h>
#include <DDraw/LogUsedResourceFormat.h>
#include <DDraw/ScopedThreadLock.h>
#include <Direct3d/Hooks.h>
#include <Dll/Dll.h>
#include <Gdi/Gdi.h>
@ -81,58 +82,66 @@ namespace
void installHooks()
{
if (!Dll::g_isHooked)
if (Dll::g_isHooked)
{
Dll::g_isHooked = true;
DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs;
Overlay::Steam::installHooks();
LOG_INFO << "Installing display mode hooks";
Win32::DisplayMode::installHooks();
LOG_INFO << "Installing registry hooks";
Win32::Registry::installHooks();
LOG_INFO << "Installing Direct3D driver hooks";
D3dDdi::installHooks();
Gdi::VirtualScreen::init();
CompatPtr<IDirectDraw> dd;
HRESULT result = CALL_ORIG_PROC(DirectDrawCreate)(nullptr, &dd.getRef(), nullptr);
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result);
return;
}
CompatPtr<IDirectDraw7> dd7;
result = CALL_ORIG_PROC(DirectDrawCreateEx)(
nullptr, reinterpret_cast<void**>(&dd7.getRef()), IID_IDirectDraw7, nullptr);
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result);
return;
}
CompatVtable<IDirectDrawVtbl>::s_origVtable = *dd.get()->lpVtbl;
result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (SUCCEEDED(result))
{
CompatVtable<IDirectDraw7Vtbl>::s_origVtable = *dd7.get()->lpVtbl;
dd7->SetCooperativeLevel(dd7, nullptr, DDSCL_NORMAL | DDSCL_FPUPRESERVE);
}
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to set the cooperative level for hooking: " << Compat::hex(result);
return;
}
LOG_INFO << "Installing DirectDraw hooks";
DDraw::installHooks(dd7);
LOG_INFO << "Installing Direct3D hooks";
Direct3d::installHooks(dd, dd7);
LOG_INFO << "Installing GDI hooks";
Gdi::installHooks();
Compat::closeDbgEng();
LOG_INFO << "Finished installing hooks";
return;
}
DDraw::ScopedThreadLock lock;
if (Dll::g_isHooked)
{
return;
}
Dll::g_isHooked = true;
DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs;
Overlay::Steam::installHooks();
LOG_INFO << "Installing display mode hooks";
Win32::DisplayMode::installHooks();
LOG_INFO << "Installing registry hooks";
Win32::Registry::installHooks();
LOG_INFO << "Installing Direct3D driver hooks";
D3dDdi::installHooks();
Gdi::VirtualScreen::init();
CompatPtr<IDirectDraw> dd;
HRESULT result = CALL_ORIG_PROC(DirectDrawCreate)(nullptr, &dd.getRef(), nullptr);
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result);
return;
}
CompatPtr<IDirectDraw7> dd7;
result = CALL_ORIG_PROC(DirectDrawCreateEx)(
nullptr, reinterpret_cast<void**>(&dd7.getRef()), IID_IDirectDraw7, nullptr);
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result);
return;
}
CompatVtable<IDirectDrawVtbl>::s_origVtable = *dd.get()->lpVtbl;
result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (SUCCEEDED(result))
{
CompatVtable<IDirectDraw7Vtbl>::s_origVtable = *dd7.get()->lpVtbl;
dd7->SetCooperativeLevel(dd7, nullptr, DDSCL_NORMAL | DDSCL_FPUPRESERVE);
}
if (FAILED(result))
{
LOG_INFO << "ERROR: Failed to set the cooperative level for hooking: " << Compat::hex(result);
return;
}
LOG_INFO << "Installing DirectDraw hooks";
DDraw::installHooks(dd7);
LOG_INFO << "Installing Direct3D hooks";
Direct3d::installHooks(dd, dd7);
LOG_INFO << "Installing GDI hooks";
Gdi::installHooks();
Compat::closeDbgEng();
LOG_INFO << "Finished installing hooks";
}
unsigned WINAPI installHooksThreadProc(LPVOID /*lpParameter*/)