diff --git a/DDrawCompat/CompatGdiSurface.cpp b/DDrawCompat/CompatGdiSurface.cpp index eb2d23c..4329ebe 100644 --- a/DDrawCompat/CompatGdiSurface.cpp +++ b/DDrawCompat/CompatGdiSurface.cpp @@ -1,6 +1,7 @@ #define CINTERFACE #define WIN32_LEAN_AND_MEAN +#include #include #include @@ -13,6 +14,7 @@ #include "CompatPrimarySurface.h" #include "DDrawLog.h" #include "DDrawProcs.h" +#include "DDrawScopedThreadLock.h" #include "RealPrimarySurface.h" namespace @@ -40,7 +42,7 @@ namespace HWND rootWnd; }; - bool g_suppressGdiHooks = false; + std::atomic g_suppressGdiHooks = false; class HookRecursionGuard { @@ -72,6 +74,22 @@ namespace CaretData g_caret = {}; + CRITICAL_SECTION g_gdiCriticalSection; + + class GdiScopedThreadLock + { + public: + GdiScopedThreadLock() + { + EnterCriticalSection(&g_gdiCriticalSection); + } + + ~GdiScopedThreadLock() + { + LeaveCriticalSection(&g_gdiCriticalSection); + } + }; + POINT getClientOrigin(HWND hwnd); HDC getCompatDc(HWND hwnd, HDC origDc, const POINT& origin); HDC releaseCompatDc(HDC hdc); @@ -88,6 +106,7 @@ namespace else if (WM_ERASEBKGND == ret->message && ret->lResult) { HDC origDc = reinterpret_cast(ret->wParam); + GdiScopedThreadLock gdiLock; if (g_dcToSurface.find(origDc) == g_dcToSurface.end()) { HWND hwnd = WindowFromDC(origDc); @@ -129,6 +148,8 @@ namespace IDirectDrawSurface7* createGdiSurface() { + Compat::DDrawScopedThreadLock ddLock; + DDSURFACEDESC2 desc = {}; desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE; @@ -184,11 +205,12 @@ namespace HDC getCompatDc(HWND hwnd, HDC origDc, const POINT& origin) { - if (!CompatPrimarySurface::surfacePtr || !origDc || !RealPrimarySurface::isFullScreen() || g_suppressGdiHooks) + if (!CompatPrimarySurface::surfacePtr || !origDc || !RealPrimarySurface::isFullScreen() || g_suppressGdiHooks) { return origDc; } + GdiScopedThreadLock gdiLock; HookRecursionGuard recursionGuard; IDirectDrawSurface7* surface = createGdiSurface(); @@ -296,6 +318,7 @@ namespace return hdc; } + GdiScopedThreadLock gdiLock; HookRecursionGuard recursionGuard; auto it = g_dcToSurface.find(hdc); @@ -360,6 +383,7 @@ namespace { if (STATE_SYSTEM_INVISIBLE == getCaretState(accessible)) { + GdiScopedThreadLock gdiLock; drawCaret(); g_caret.isDrawn = false; } @@ -369,69 +393,48 @@ namespace HDC WINAPI getDc(HWND hWnd) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("GetDC", hWnd); - HDC compatDc = getCompatDc(hWnd, g_origGetDc(hWnd), getClientOrigin(hWnd)); - Compat::LogLeave("GetDC", hWnd) << compatDc; - Compat::origProcs.ReleaseDDThreadLock(); return compatDc; } HDC WINAPI getDcEx(HWND hWnd, HRGN hrgnClip, DWORD flags) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("GetDCEx", hWnd); - HDC compatDc = getCompatDc(hWnd, g_origGetDcEx(hWnd, hrgnClip, flags), flags & (DCX_WINDOW | DCX_PARENTCLIP) ? getWindowOrigin(hWnd) : getClientOrigin(hWnd)); - Compat::LogLeave("GetDCEx", hWnd) << compatDc; - Compat::origProcs.ReleaseDDThreadLock(); return compatDc; } HDC WINAPI getWindowDc(HWND hWnd) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("GetWindowDC", hWnd); - HDC compatDc = getCompatDc(hWnd, g_origGetWindowDc(hWnd), getWindowOrigin(hWnd)); - Compat::LogLeave("GetWindowDC", hWnd) << compatDc; - Compat::origProcs.ReleaseDDThreadLock(); return compatDc; } int WINAPI releaseDc(HWND hWnd, HDC hDC) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("ReleaseDC", hWnd, hDC); - int result = g_origReleaseDc(hWnd, releaseCompatDc(hDC)); - Compat::LogLeave("ReleaseDC", hWnd, hDC) << result; - Compat::origProcs.ReleaseDDThreadLock(); return result; } HDC WINAPI beginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("BeginPaint", hWnd, lpPaint); - HDC compatDc = getCompatDc(hWnd, g_origBeginPaint(hWnd, lpPaint), getClientOrigin(hWnd)); lpPaint->hdc = compatDc; - Compat::LogLeave("BeginPaint", hWnd, lpPaint) << compatDc; - Compat::origProcs.ReleaseDDThreadLock(); return compatDc; } BOOL WINAPI endPaint(HWND hWnd, const PAINTSTRUCT* lpPaint) { - Compat::origProcs.AcquireDDThreadLock(); Compat::LogEnter("EndPaint", hWnd, lpPaint); BOOL result = FALSE; @@ -447,7 +450,6 @@ namespace } Compat::LogLeave("EndPaint", hWnd, lpPaint) << result; - Compat::origProcs.ReleaseDDThreadLock(); return result; } @@ -456,6 +458,7 @@ namespace BOOL result = g_origCreateCaret(hWnd, hBitmap, nWidth, nHeight); if (result) { + GdiScopedThreadLock gdiLock; if (g_caret.isDrawn) { drawCaret(); @@ -470,6 +473,7 @@ namespace BOOL WINAPI showCaret(HWND hWnd) { BOOL result = g_origShowCaret(hWnd); + GdiScopedThreadLock gdiLock; if (result && !g_caret.isDrawn) { IAccessible* accessible = nullptr; @@ -496,6 +500,7 @@ namespace BOOL WINAPI hideCaret(HWND hWnd) { BOOL result = g_origHideCaret(hWnd); + GdiScopedThreadLock gdiLock; if (result && g_caret.isDrawn) { drawCaret(); @@ -513,6 +518,7 @@ void CompatGdiSurface::hookGdi() return; } + InitializeCriticalSection(&g_gdiCriticalSection); g_directDraw = createDirectDraw(); if (g_directDraw) { diff --git a/DDrawCompat/CompatPrimarySurface.cpp b/DDrawCompat/CompatPrimarySurface.cpp index d570042..1c53519 100644 --- a/DDrawCompat/CompatPrimarySurface.cpp +++ b/DDrawCompat/CompatPrimarySurface.cpp @@ -57,6 +57,6 @@ namespace CompatPrimarySurface LONG height = 0; DDPIXELFORMAT pixelFormat = {}; LONG pitch = 0; - void* surfacePtr = nullptr; + std::atomic surfacePtr = nullptr; IReleaseNotifier releaseNotifier(onRelease); } diff --git a/DDrawCompat/CompatPrimarySurface.h b/DDrawCompat/CompatPrimarySurface.h index 68f3c68..ea60793 100644 --- a/DDrawCompat/CompatPrimarySurface.h +++ b/DDrawCompat/CompatPrimarySurface.h @@ -2,6 +2,7 @@ #define CINTERFACE +#include #include class IReleaseNotifier; @@ -25,6 +26,6 @@ namespace CompatPrimarySurface extern LONG height; extern DDPIXELFORMAT pixelFormat; extern LONG pitch; - extern void* surfacePtr; + extern std::atomic surfacePtr; extern IReleaseNotifier releaseNotifier; } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 73acdd7..e584587 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -150,6 +150,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index dbe2d1a..b6f054c 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -63,6 +63,9 @@ Header Files + + Header Files + diff --git a/DDrawCompat/DDrawScopedThreadLock.h b/DDrawCompat/DDrawScopedThreadLock.h new file mode 100644 index 0000000..a72898c --- /dev/null +++ b/DDrawCompat/DDrawScopedThreadLock.h @@ -0,0 +1,20 @@ +#pragma once + +#include "DDrawProcs.h" + +namespace Compat +{ + class DDrawScopedThreadLock + { + public: + DDrawScopedThreadLock() + { + origProcs.AcquireDDThreadLock(); + } + + ~DDrawScopedThreadLock() + { + origProcs.ReleaseDDThreadLock(); + } + }; +} diff --git a/DDrawCompat/RealPrimarySurface.cpp b/DDrawCompat/RealPrimarySurface.cpp index 9e766e5..e4a89c7 100644 --- a/DDrawCompat/RealPrimarySurface.cpp +++ b/DDrawCompat/RealPrimarySurface.cpp @@ -1,3 +1,5 @@ +#include + #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatGdiSurface.h" @@ -24,6 +26,8 @@ namespace LARGE_INTEGER g_lastUpdateTime = {}; LARGE_INTEGER g_qpcFrequency = {}; + std::atomic g_isFullScreen(false); + bool compatBlt(IDirectDrawSurface7* dest) { Compat::LogEnter("RealPrimarySurface::compatBlt", dest); @@ -111,6 +115,7 @@ namespace g_frontBuffer = nullptr; g_backBuffer = nullptr; + g_isFullScreen = false; if (g_paletteConverterSurface) { g_paletteConverterSurface->lpVtbl->Release(g_paletteConverterSurface); @@ -246,6 +251,8 @@ HRESULT RealPrimarySurface::create(DirectDraw& dd) g_frontBuffer->lpVtbl->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier, &g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER); + g_isFullScreen = isFlippable; + return DD_OK; } @@ -290,7 +297,7 @@ IDirectDrawSurface7* RealPrimarySurface::getSurface() bool RealPrimarySurface::isFullScreen() { - return nullptr != g_backBuffer; + return g_isFullScreen; } bool RealPrimarySurface::isLost()