From 24bb72138d27a9f66b8f3dad7f7a3b99b11d1cb9 Mon Sep 17 00:00:00 2001 From: narzoul Date: Mon, 20 May 2024 18:01:32 +0200 Subject: [PATCH] Fixed a race condition leading to a crash when installing hooks See issue #306. --- DDrawCompat/DDraw/DirectDraw.cpp | 1 + DDrawCompat/Dll/DllMain.cpp | 109 +++++++++++++++++-------------- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp index 668cb8b..8f6119a 100644 --- a/DDrawCompat/DDraw/DirectDraw.cpp +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -336,6 +336,7 @@ namespace DDraw void onCreate(GUID* guid, CompatRef dd) { + DDraw::ScopedThreadLock lock; static std::map> repositories; auto adapterInfo = D3dDdi::KernelModeThunks::getAdapterInfo(dd); auto it = repositories.find(adapterInfo.luid); diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 0907f80..254a782 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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 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 dd7; - result = CALL_ORIG_PROC(DirectDrawCreateEx)( - nullptr, reinterpret_cast(&dd7.getRef()), IID_IDirectDraw7, nullptr); - if (FAILED(result)) - { - LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result); - return; - } - - CompatVtable::s_origVtable = *dd.get()->lpVtbl; - result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL); - if (SUCCEEDED(result)) - { - CompatVtable::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 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 dd7; + result = CALL_ORIG_PROC(DirectDrawCreateEx)( + nullptr, reinterpret_cast(&dd7.getRef()), IID_IDirectDraw7, nullptr); + if (FAILED(result)) + { + LOG_INFO << "ERROR: Failed to create a DirectDraw object for hooking: " << Compat::hex(result); + return; + } + + CompatVtable::s_origVtable = *dd.get()->lpVtbl; + result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL); + if (SUCCEEDED(result)) + { + CompatVtable::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*/)