mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed deadlock when hooking NVIDIA user-mode display drivers
See issue #28
This commit is contained in:
parent
14104894b2
commit
8e8eeb083a
@ -4,6 +4,7 @@
|
||||
|
||||
#include "Common/Hook.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Gdi/Dc.h"
|
||||
#include "Gdi/DcCache.h"
|
||||
@ -29,6 +30,7 @@ namespace
|
||||
|
||||
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
|
||||
|
||||
Compat::CriticalSection g_cs;
|
||||
CompatDcMap g_origDcToCompatDc;
|
||||
|
||||
void restoreDc(const CompatDc& compatDc);
|
||||
@ -147,7 +149,7 @@ namespace Gdi
|
||||
{
|
||||
void dllProcessDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
for (auto& origDcToCompatDc : g_origDcToCompatDc)
|
||||
{
|
||||
restoreDc(origDcToCompatDc.second);
|
||||
@ -158,7 +160,7 @@ namespace Gdi
|
||||
|
||||
void dllThreadDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
const DWORD threadId = GetCurrentThreadId();
|
||||
auto it = g_origDcToCompatDc.begin();
|
||||
while (it != g_origDcToCompatDc.end())
|
||||
@ -183,7 +185,8 @@ namespace Gdi
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DDraw::ScopedThreadLock ddLock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
auto it = g_origDcToCompatDc.find(origDc);
|
||||
if (it != g_origDcToCompatDc.end())
|
||||
{
|
||||
@ -228,7 +231,7 @@ namespace Gdi
|
||||
|
||||
HDC getOrigDc(HDC dc)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
const auto it = std::find_if(g_origDcToCompatDc.begin(), g_origDcToCompatDc.end(),
|
||||
[dc](const CompatDcMap::value_type& compatDc) { return compatDc.second.dc == dc; });
|
||||
return it != g_origDcToCompatDc.end() ? it->first : dc;
|
||||
@ -236,7 +239,7 @@ namespace Gdi
|
||||
|
||||
void releaseDc(HDC origDc)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
auto it = g_origDcToCompatDc.find(origDc);
|
||||
if (it == g_origDcToCompatDc.end())
|
||||
{
|
||||
|
@ -3,12 +3,13 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "Gdi/DcCache.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Compat::CriticalSection g_cs;
|
||||
std::map<DWORD, std::vector<HDC>> g_threadIdToDcCache;
|
||||
}
|
||||
|
||||
@ -18,7 +19,7 @@ namespace Gdi
|
||||
{
|
||||
void deleteDc(HDC cachedDc)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||
{
|
||||
auto& dcCache = threadIdToDcCache.second;
|
||||
@ -34,7 +35,7 @@ namespace Gdi
|
||||
|
||||
void dllProcessDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||
{
|
||||
for (HDC dc : threadIdToDcCache.second)
|
||||
@ -47,7 +48,7 @@ namespace Gdi
|
||||
|
||||
void dllThreadDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
auto it = g_threadIdToDcCache.find(GetCurrentThreadId());
|
||||
if (it == g_threadIdToDcCache.end())
|
||||
{
|
||||
@ -64,7 +65,7 @@ namespace Gdi
|
||||
|
||||
HDC getDc()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
std::vector<HDC>& dcCache = g_threadIdToDcCache[GetCurrentThreadId()];
|
||||
|
||||
if (dcCache.empty())
|
||||
@ -79,7 +80,7 @@ namespace Gdi
|
||||
|
||||
void releaseDc(HDC cachedDc)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
g_threadIdToDcCache[GetCurrentThreadId()].push_back(cachedDc);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "Common/Hook.h"
|
||||
#include "Common/Log.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/Palette.h"
|
||||
#include "VirtualScreen.h"
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
Compat::CriticalSection g_cs;
|
||||
PALETTEENTRY g_systemPalette[256] = {};
|
||||
UINT g_systemPaletteUse = SYSPAL_STATIC;
|
||||
UINT g_systemPaletteFirstUnusedIndex = 10;
|
||||
@ -75,7 +76,7 @@ namespace
|
||||
++g_systemPaletteFirstUnusedIndex;
|
||||
}
|
||||
|
||||
Gdi::VirtualScreen::updatePalette();
|
||||
Gdi::VirtualScreen::updatePalette(g_systemPalette);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -102,7 +103,7 @@ namespace
|
||||
nEntries = 256 - iStartIndex;
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
std::memcpy(lppe, &g_systemPalette[iStartIndex], nEntries * sizeof(PALETTEENTRY));
|
||||
|
||||
return LOG_RESULT(nEntries);
|
||||
@ -115,7 +116,7 @@ namespace
|
||||
{
|
||||
return LOG_RESULT(SYSPAL_ERROR);
|
||||
}
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_systemPaletteUse;
|
||||
}
|
||||
|
||||
@ -124,7 +125,7 @@ namespace
|
||||
LOG_FUNC("RealizePalette", hdc);
|
||||
if (Gdi::isDisplayDc(hdc))
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
if (g_foregroundPaletteDcs.find(hdc) != g_foregroundPaletteDcs.end())
|
||||
{
|
||||
g_systemPaletteFirstUnusedIndex = g_systemPaletteFirstNonReservedIndex;
|
||||
@ -137,7 +138,7 @@ namespace
|
||||
int WINAPI releaseDc(HWND hWnd, HDC hDC)
|
||||
{
|
||||
LOG_FUNC("ReleaseDC", hWnd, hDC);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
g_foregroundPaletteDcs.erase(hDC);
|
||||
return LOG_RESULT(CALL_ORIG_FUNC(ReleaseDC)(hWnd, hDC));
|
||||
}
|
||||
@ -151,7 +152,7 @@ namespace
|
||||
HWND wnd = CALL_ORIG_FUNC(WindowFromDC)(hdc);
|
||||
if (wnd && GetDesktopWindow() != wnd)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
if (bForceBackground || GetStockObject(DEFAULT_PALETTE) == hpal)
|
||||
{
|
||||
g_foregroundPaletteDcs.erase(hdc);
|
||||
@ -173,7 +174,7 @@ namespace
|
||||
return LOG_RESULT(SYSPAL_ERROR);
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
const UINT prevUsage = g_systemPaletteUse;
|
||||
switch (uUsage)
|
||||
{
|
||||
@ -210,7 +211,7 @@ namespace Gdi
|
||||
HPALETTE defaultPalette = reinterpret_cast<HPALETTE>(GetStockObject(DEFAULT_PALETTE));
|
||||
GetPaletteEntries(defaultPalette, 0, 10, g_systemPalette);
|
||||
GetPaletteEntries(defaultPalette, 10, 10, &g_systemPalette[246]);
|
||||
Gdi::VirtualScreen::updatePalette();
|
||||
Gdi::VirtualScreen::updatePalette(g_systemPalette);
|
||||
|
||||
HOOK_FUNCTION(gdi32, GetSystemPaletteEntries, getSystemPaletteEntries);
|
||||
HOOK_FUNCTION(gdi32, GetSystemPaletteUse, getSystemPaletteUse);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
@ -10,6 +11,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
Compat::CriticalSection g_cs;
|
||||
Gdi::Region g_region;
|
||||
RECT g_bounds = {};
|
||||
DWORD g_bpp = 0;
|
||||
@ -70,7 +72,7 @@ namespace Gdi
|
||||
{
|
||||
HDC createDc()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(), DeleteObject);
|
||||
if (!dib)
|
||||
{
|
||||
@ -91,7 +93,6 @@ namespace Gdi
|
||||
|
||||
dib.release();
|
||||
|
||||
|
||||
g_stockBitmap = stockBitmap;
|
||||
g_dcs.insert(dc.get());
|
||||
return dc.release();
|
||||
@ -99,7 +100,7 @@ namespace Gdi
|
||||
|
||||
HBITMAP createDib()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
if (!g_surfaceFileMapping)
|
||||
{
|
||||
return nullptr;
|
||||
@ -109,19 +110,21 @@ namespace Gdi
|
||||
|
||||
HBITMAP createOffScreenDib(DWORD width, DWORD height)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return createDibSection(width, height, nullptr);
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> createSurface(const RECT& rect)
|
||||
{
|
||||
DDraw::ScopedThreadLock ddLock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
|
||||
if (rect.left < g_bounds.left || rect.top < g_bounds.top ||
|
||||
rect.right > g_bounds.right || rect.bottom > g_bounds.bottom)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE;
|
||||
@ -151,7 +154,7 @@ namespace Gdi
|
||||
return;
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DeleteObject(SelectObject(dc, g_stockBitmap));
|
||||
DeleteDC(dc);
|
||||
g_dcs.erase(dc);
|
||||
@ -159,13 +162,13 @@ namespace Gdi
|
||||
|
||||
RECT getBounds()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_bounds;
|
||||
}
|
||||
|
||||
const Region& getRegion()
|
||||
Region getRegion()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_region;
|
||||
}
|
||||
|
||||
@ -177,7 +180,7 @@ namespace Gdi
|
||||
bool update()
|
||||
{
|
||||
LOG_FUNC("VirtualScreen::update");
|
||||
DDraw::ScopedThreadLock lock;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
|
||||
static auto prevDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
||||
const auto currentDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness();
|
||||
@ -220,19 +223,16 @@ namespace Gdi
|
||||
return LOG_RESULT(true);
|
||||
}
|
||||
|
||||
void updatePalette()
|
||||
void updatePalette(PALETTEENTRY(&palette)[256])
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
|
||||
PALETTEENTRY pal[256] = {};
|
||||
GetSystemPaletteEntries(Gdi::getScreenDc(), 0, 256, pal);
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
|
||||
RGBQUAD systemPalette[256] = {};
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
systemPalette[i].rgbRed = pal[i].peRed;
|
||||
systemPalette[i].rgbGreen = pal[i].peGreen;
|
||||
systemPalette[i].rgbBlue = pal[i].peBlue;
|
||||
systemPalette[i].rgbRed = palette[i].peRed;
|
||||
systemPalette[i].rgbGreen = palette[i].peGreen;
|
||||
systemPalette[i].rgbBlue = palette[i].peBlue;
|
||||
}
|
||||
|
||||
if (0 != memcmp(g_systemPalette, systemPalette, sizeof(systemPalette)))
|
||||
|
@ -19,10 +19,10 @@ namespace Gdi
|
||||
void deleteDc(HDC dc);
|
||||
|
||||
RECT getBounds();
|
||||
const Region& getRegion();
|
||||
Region getRegion();
|
||||
|
||||
void init();
|
||||
bool update();
|
||||
void updatePalette();
|
||||
void updatePalette(PALETTEENTRY(&palette)[256]);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user