mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Hook all GDI threads
This commit is contained in:
parent
4717b9aa1b
commit
58aba66ca2
@ -6,6 +6,20 @@
|
|||||||
|
|
||||||
namespace Compat
|
namespace Compat
|
||||||
{
|
{
|
||||||
|
class CriticalSection : public CRITICAL_SECTION
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CriticalSection()
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CriticalSection()
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ScopedCriticalSection
|
class ScopedCriticalSection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -39,7 +39,7 @@ namespace
|
|||||||
D3DKMT_HANDLE g_lastPresentContext = 0;
|
D3DKMT_HANDLE g_lastPresentContext = 0;
|
||||||
UINT g_presentCount = 0;
|
UINT g_presentCount = 0;
|
||||||
std::atomic<long long> g_qpcLastVerticalBlank = 0;
|
std::atomic<long long> g_qpcLastVerticalBlank = 0;
|
||||||
CRITICAL_SECTION g_vblankCs = {};
|
Compat::CriticalSection g_vblankCs;
|
||||||
|
|
||||||
decltype(D3DKMTCreateContextVirtual)* g_origD3dKmtCreateContextVirtual = nullptr;
|
decltype(D3DKMTCreateContextVirtual)* g_origD3dKmtCreateContextVirtual = nullptr;
|
||||||
|
|
||||||
@ -313,7 +313,6 @@ namespace D3dDdi
|
|||||||
|
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&g_vblankCs);
|
|
||||||
HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter);
|
HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter);
|
||||||
HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext);
|
HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext);
|
||||||
HOOK_FUNCTION(gdi32, D3DKMTCreateDevice, createDevice);
|
HOOK_FUNCTION(gdi32, D3DKMTCreateDevice, createDevice);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "DDraw/ActivateAppHandler.h"
|
#include "DDraw/ActivateAppHandler.h"
|
||||||
#include "DDraw/DirectDraw.h"
|
#include "DDraw/DirectDraw.h"
|
||||||
#include "DDraw/Repository.h"
|
#include "DDraw/Repository.h"
|
||||||
#include "DDraw/Surfaces/TagSurface.h"
|
|
||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
#include "Win32/DisplayMode.h"
|
#include "Win32/DisplayMode.h"
|
||||||
|
|
||||||
@ -182,15 +181,6 @@ namespace DDraw
|
|||||||
HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags);
|
HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags);
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
void* ddObject = getDdObject(*This);
|
|
||||||
TagSurface* tagSurface = TagSurface::get(ddObject);
|
|
||||||
if (!tagSurface)
|
|
||||||
{
|
|
||||||
CompatPtr<IDirectDraw> dd(Compat::queryInterface<IDirectDraw>(This));
|
|
||||||
TagSurface::create(*dd);
|
|
||||||
tagSurface = TagSurface::get(ddObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivateAppHandler::setCooperativeLevel(hWnd, dwFlags);
|
ActivateAppHandler::setCooperativeLevel(hWnd, dwFlags);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -50,7 +50,11 @@ namespace
|
|||||||
|
|
||||||
BOOL CALLBACK addVisibleLayeredWindowToVector(HWND hwnd, LPARAM lParam)
|
BOOL CALLBACK addVisibleLayeredWindowToVector(HWND hwnd, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (IsWindowVisible(hwnd) && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
DWORD windowPid = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||||
|
if (GetCurrentProcessId() == windowPid &&
|
||||||
|
IsWindowVisible(hwnd) &&
|
||||||
|
(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||||
!Gdi::Window::isPresentationWindow(hwnd))
|
!Gdi::Window::isPresentationWindow(hwnd))
|
||||||
{
|
{
|
||||||
auto& visibleLayeredWindows = *reinterpret_cast<std::vector<HWND>*>(lParam);
|
auto& visibleLayeredWindows = *reinterpret_cast<std::vector<HWND>*>(lParam);
|
||||||
@ -119,8 +123,7 @@ namespace
|
|||||||
void bltVisibleLayeredWindowsToBackBuffer()
|
void bltVisibleLayeredWindowsToBackBuffer()
|
||||||
{
|
{
|
||||||
std::vector<HWND> visibleLayeredWindows;
|
std::vector<HWND> visibleLayeredWindows;
|
||||||
EnumThreadWindows(Gdi::getGdiThreadId(), addVisibleLayeredWindowToVector,
|
EnumWindows(addVisibleLayeredWindowToVector, reinterpret_cast<LPARAM>(&visibleLayeredWindows));
|
||||||
reinterpret_cast<LPARAM>(&visibleLayeredWindows));
|
|
||||||
|
|
||||||
if (visibleLayeredWindows.empty())
|
if (visibleLayeredWindows.empty())
|
||||||
{
|
{
|
||||||
|
@ -151,7 +151,6 @@ namespace DDraw
|
|||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
PrimarySurface::onRestore();
|
PrimarySurface::onRestore();
|
||||||
Gdi::redraw(nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "DDraw/DirectDraw.h"
|
|
||||||
#include "DDraw/Repository.h"
|
|
||||||
#include "DDraw/Surfaces/TagSurface.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::map<void*, DDraw::TagSurface*> g_tagSurfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace DDraw
|
|
||||||
{
|
|
||||||
TagSurface::~TagSurface()
|
|
||||||
{
|
|
||||||
Repository::onRelease(m_ddObject);
|
|
||||||
g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
|
|
||||||
[=](auto& i) { return i.second == this; }));
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT TagSurface::create(CompatRef<IDirectDraw> dd)
|
|
||||||
{
|
|
||||||
DDSURFACEDESC desc = {};
|
|
||||||
desc.dwSize = sizeof(desc);
|
|
||||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
|
||||||
desc.dwWidth = 1;
|
|
||||||
desc.dwHeight = 1;
|
|
||||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
||||||
|
|
||||||
IDirectDrawSurface* surface = nullptr;
|
|
||||||
HRESULT result = Surface::create(dd, desc, surface);
|
|
||||||
if (SUCCEEDED(result))
|
|
||||||
{
|
|
||||||
std::unique_ptr<Surface> privateData(new TagSurface());
|
|
||||||
g_tagSurfaces[getDdObject(dd.get())] = static_cast<TagSurface*>(privateData.get());
|
|
||||||
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(surface));
|
|
||||||
attach(*surface7, privateData);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagSurface* TagSurface::get(void* ddObject)
|
|
||||||
{
|
|
||||||
auto it = g_tagSurfaces.find(ddObject);
|
|
||||||
return it != g_tagSurfaces.end() ? it->second : nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DDraw/Surfaces/Surface.h"
|
|
||||||
|
|
||||||
namespace DDraw
|
|
||||||
{
|
|
||||||
class TagSurface : public Surface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~TagSurface();
|
|
||||||
|
|
||||||
static HRESULT create(CompatRef<IDirectDraw> dd);
|
|
||||||
static TagSurface* get(void* ddObject);
|
|
||||||
};
|
|
||||||
}
|
|
@ -188,7 +188,6 @@
|
|||||||
<ClInclude Include="DDraw\Hooks.h" />
|
<ClInclude Include="DDraw\Hooks.h" />
|
||||||
<ClInclude Include="DDraw\Repository.h" />
|
<ClInclude Include="DDraw\Repository.h" />
|
||||||
<ClInclude Include="DDraw\ScopedThreadLock.h" />
|
<ClInclude Include="DDraw\ScopedThreadLock.h" />
|
||||||
<ClInclude Include="DDraw\Surfaces\TagSurface.h" />
|
|
||||||
<ClInclude Include="DDraw\Surfaces\PrimarySurface.h" />
|
<ClInclude Include="DDraw\Surfaces\PrimarySurface.h" />
|
||||||
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h" />
|
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h" />
|
||||||
<ClInclude Include="DDraw\Surfaces\Surface.h" />
|
<ClInclude Include="DDraw\Surfaces\Surface.h" />
|
||||||
@ -261,7 +260,6 @@
|
|||||||
<ClCompile Include="DDraw\Repository.cpp" />
|
<ClCompile Include="DDraw\Repository.cpp" />
|
||||||
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
|
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
|
||||||
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
|
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
|
||||||
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp" />
|
|
||||||
<ClCompile Include="DDraw\Surfaces\PrimarySurface.cpp" />
|
<ClCompile Include="DDraw\Surfaces\PrimarySurface.cpp" />
|
||||||
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp" />
|
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp" />
|
||||||
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />
|
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />
|
||||||
|
@ -255,9 +255,6 @@
|
|||||||
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h">
|
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h">
|
||||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
<Filter>Header Files\DDraw\Surfaces</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="DDraw\Surfaces\TagSurface.h">
|
|
||||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Direct3d\Visitors\Direct3dViewportVtblVisitor.h">
|
<ClInclude Include="Direct3d\Visitors\Direct3dViewportVtblVisitor.h">
|
||||||
<Filter>Header Files\Direct3d\Visitors</Filter>
|
<Filter>Header Files\Direct3d\Visitors</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -449,9 +446,6 @@
|
|||||||
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp">
|
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp">
|
||||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp">
|
|
||||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Direct3d\Direct3dViewport.cpp">
|
<ClCompile Include="Direct3d\Direct3dViewport.cpp">
|
||||||
<Filter>Source Files\Direct3d</Filter>
|
<Filter>Source Files\Direct3d</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -84,7 +84,7 @@ namespace
|
|||||||
#define LOAD_ORIGINAL_PROC(procName) \
|
#define LOAD_ORIGINAL_PROC(procName) \
|
||||||
Dll::g_origProcs.procName = Compat::getProcAddress(g_origDDrawModule, #procName);
|
Dll::g_origProcs.procName = Compat::getProcAddress(g_origDDrawModule, #procName);
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
@ -96,7 +96,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
|||||||
|
|
||||||
char currentDllPath[MAX_PATH] = {};
|
char currentDllPath[MAX_PATH] = {};
|
||||||
GetModuleFileName(hinstDLL, currentDllPath, MAX_PATH);
|
GetModuleFileName(hinstDLL, currentDllPath, MAX_PATH);
|
||||||
Compat::Log() << "Loading DDrawCompat from " << currentDllPath;
|
Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically")
|
||||||
|
<< " from " << currentDllPath;
|
||||||
|
|
||||||
char systemDirectory[MAX_PATH] = {};
|
char systemDirectory[MAX_PATH] = {};
|
||||||
GetSystemDirectory(systemDirectory, MAX_PATH);
|
GetSystemDirectory(systemDirectory, MAX_PATH);
|
||||||
@ -138,17 +139,24 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
|||||||
}
|
}
|
||||||
else if (fdwReason == DLL_PROCESS_DETACH)
|
else if (fdwReason == DLL_PROCESS_DETACH)
|
||||||
{
|
{
|
||||||
Compat::Log() << "Detaching DDrawCompat";
|
Compat::Log() << "Detaching DDrawCompat due to " << (lpvReserved ? "process termination" : "FreeLibrary");
|
||||||
DDraw::uninstallHooks();
|
if (!lpvReserved)
|
||||||
D3dDdi::uninstallHooks();
|
{
|
||||||
Gdi::uninstallHooks();
|
DDraw::uninstallHooks();
|
||||||
Compat::unhookAllFunctions();
|
D3dDdi::uninstallHooks();
|
||||||
FreeLibrary(g_origDInputModule);
|
Gdi::uninstallHooks();
|
||||||
FreeLibrary(g_origDDrawModule);
|
Compat::unhookAllFunctions();
|
||||||
|
FreeLibrary(g_origDInputModule);
|
||||||
|
FreeLibrary(g_origDDrawModule);
|
||||||
|
}
|
||||||
Win32::FontSmoothing::setSystemSettingsForced(Win32::FontSmoothing::g_origSystemSettings);
|
Win32::FontSmoothing::setSystemSettingsForced(Win32::FontSmoothing::g_origSystemSettings);
|
||||||
timeEndPeriod(1);
|
timeEndPeriod(1);
|
||||||
Compat::Log() << "DDrawCompat detached successfully";
|
Compat::Log() << "DDrawCompat detached successfully";
|
||||||
}
|
}
|
||||||
|
else if (fdwReason == DLL_THREAD_DETACH)
|
||||||
|
{
|
||||||
|
Gdi::dllThreadDetach();
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace
|
|||||||
bool isDrawn;
|
bool isDrawn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CaretData g_caret = {};
|
CaretData g_caret = {};
|
||||||
long long g_qpcLastBlink = 0;
|
long long g_qpcLastBlink = 0;
|
||||||
|
|
||||||
|
@ -18,14 +18,15 @@ namespace
|
|||||||
HDC dc;
|
HDC dc;
|
||||||
DWORD refCount;
|
DWORD refCount;
|
||||||
HDC origDc;
|
HDC origDc;
|
||||||
|
DWORD threadId;
|
||||||
int savedState;
|
int savedState;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<HDC__, void(*)(HDC)> OrigDc;
|
|
||||||
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
|
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
|
||||||
|
|
||||||
CompatDcMap g_origDcToCompatDc;
|
CompatDcMap g_origDcToCompatDc;
|
||||||
thread_local std::vector<OrigDc> g_threadDcs;
|
|
||||||
|
void restoreDc(const CompatDc& compatDc);
|
||||||
|
|
||||||
void copyDcAttributes(const CompatDc& compatDc, HDC origDc, const POINT& origin)
|
void copyDcAttributes(const CompatDc& compatDc, HDC origDc, const POINT& origin)
|
||||||
{
|
{
|
||||||
@ -79,13 +80,12 @@ namespace
|
|||||||
MoveToEx(compatDc.dc, currentPos.x, currentPos.y, nullptr);
|
MoveToEx(compatDc.dc, currentPos.x, currentPos.y, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteDc(HDC origDc)
|
void restoreDc(const CompatDc& compatDc)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
// Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one
|
||||||
auto it = g_origDcToCompatDc.find(origDc);
|
HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP);
|
||||||
RestoreDC(it->second.dc, it->second.savedState);
|
RestoreDC(compatDc.dc, compatDc.savedState);
|
||||||
Gdi::DcCache::deleteDc(it->second.dc);
|
SelectObject(compatDc.dc, bitmap);
|
||||||
g_origDcToCompatDc.erase(origDc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setClippingRegion(HDC compatDc, HDC origDc, HWND hwnd, const POINT& origin)
|
void setClippingRegion(HDC compatDc, HDC origDc, HWND hwnd, const POINT& origin)
|
||||||
@ -115,6 +115,37 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace Dc
|
namespace Dc
|
||||||
{
|
{
|
||||||
|
void dllProcessDetach()
|
||||||
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
|
for (auto& origDcToCompatDc : g_origDcToCompatDc)
|
||||||
|
{
|
||||||
|
restoreDc(origDcToCompatDc.second);
|
||||||
|
Gdi::DcCache::deleteDc(origDcToCompatDc.second.dc);
|
||||||
|
}
|
||||||
|
g_origDcToCompatDc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dllThreadDetach()
|
||||||
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
|
const DWORD threadId = GetCurrentThreadId();
|
||||||
|
auto it = g_origDcToCompatDc.begin();
|
||||||
|
while (it != g_origDcToCompatDc.end())
|
||||||
|
{
|
||||||
|
if (threadId == it->second.threadId)
|
||||||
|
{
|
||||||
|
restoreDc(it->second);
|
||||||
|
Gdi::DcCache::deleteDc(it->second.dc);
|
||||||
|
it = g_origDcToCompatDc.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HDC getDc(HDC origDc)
|
HDC getDc(HDC origDc)
|
||||||
{
|
{
|
||||||
if (!origDc || OBJ_DC != GetObjectType(origDc) || DT_RASDISPLAY != GetDeviceCaps(origDc, TECHNOLOGY))
|
if (!origDc || OBJ_DC != GetObjectType(origDc) || DT_RASDISPLAY != GetDeviceCaps(origDc, TECHNOLOGY))
|
||||||
@ -161,8 +192,8 @@ namespace Gdi
|
|||||||
|
|
||||||
compatDc.refCount = 1;
|
compatDc.refCount = 1;
|
||||||
compatDc.origDc = origDc;
|
compatDc.origDc = origDc;
|
||||||
|
compatDc.threadId = GetCurrentThreadId();
|
||||||
g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));
|
g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));
|
||||||
g_threadDcs.emplace_back(origDc, &deleteDc);
|
|
||||||
|
|
||||||
return compatDc.dc;
|
return compatDc.dc;
|
||||||
}
|
}
|
||||||
@ -188,12 +219,7 @@ namespace Gdi
|
|||||||
--compatDc.refCount;
|
--compatDc.refCount;
|
||||||
if (0 == compatDc.refCount)
|
if (0 == compatDc.refCount)
|
||||||
{
|
{
|
||||||
auto threadDcIter = std::find_if(g_threadDcs.begin(), g_threadDcs.end(),
|
restoreDc(compatDc);
|
||||||
[origDc](const OrigDc& dc) { return dc.get() == origDc; });
|
|
||||||
threadDcIter->release();
|
|
||||||
g_threadDcs.erase(threadDcIter);
|
|
||||||
|
|
||||||
RestoreDC(compatDc.dc, compatDc.savedState);
|
|
||||||
Gdi::DcCache::releaseDc(compatDc.dc);
|
Gdi::DcCache::releaseDc(compatDc.dc);
|
||||||
g_origDcToCompatDc.erase(origDc);
|
g_origDcToCompatDc.erase(origDc);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace Dc
|
namespace Dc
|
||||||
{
|
{
|
||||||
|
void dllProcessDetach();
|
||||||
|
void dllThreadDetach();
|
||||||
HDC getDc(HDC origDc);
|
HDC getDc(HDC origDc);
|
||||||
HDC getOrigDc(HDC dc);
|
HDC getOrigDc(HDC dc);
|
||||||
void releaseDc(HDC origDc);
|
void releaseDc(HDC origDc);
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "DDraw/ScopedThreadLock.h"
|
||||||
#include "Gdi/DcCache.h"
|
#include "Gdi/DcCache.h"
|
||||||
#include "Gdi/VirtualScreen.h"
|
#include "Gdi/VirtualScreen.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
typedef std::unique_ptr<HDC__, void(*)(HDC)> CachedDc;
|
std::map<DWORD, std::vector<HDC>> g_threadIdToDcCache;
|
||||||
|
|
||||||
thread_local std::vector<CachedDc> g_cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
@ -17,29 +18,69 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
void deleteDc(HDC cachedDc)
|
void deleteDc(HDC cachedDc)
|
||||||
{
|
{
|
||||||
Gdi::VirtualScreen::deleteDc(cachedDc);
|
DDraw::ScopedThreadLock lock;
|
||||||
|
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||||
|
{
|
||||||
|
auto& dcCache = threadIdToDcCache.second;
|
||||||
|
auto it = std::find(dcCache.begin(), dcCache.end(), cachedDc);
|
||||||
|
if (it != dcCache.end())
|
||||||
|
{
|
||||||
|
Gdi::VirtualScreen::deleteDc(*it);
|
||||||
|
dcCache.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dllProcessDetach()
|
||||||
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
|
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||||
|
{
|
||||||
|
for (HDC dc : threadIdToDcCache.second)
|
||||||
|
{
|
||||||
|
Gdi::VirtualScreen::deleteDc(dc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_threadIdToDcCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dllThreadDetach()
|
||||||
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
|
auto it = g_threadIdToDcCache.find(GetCurrentThreadId());
|
||||||
|
if (it == g_threadIdToDcCache.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HDC dc : it->second)
|
||||||
|
{
|
||||||
|
Gdi::VirtualScreen::deleteDc(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_threadIdToDcCache.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC getDc()
|
HDC getDc()
|
||||||
{
|
{
|
||||||
HDC cachedDc = nullptr;
|
DDraw::ScopedThreadLock lock;
|
||||||
|
std::vector<HDC>& dcCache = g_threadIdToDcCache[GetCurrentThreadId()];
|
||||||
|
|
||||||
if (g_cache.empty())
|
if (dcCache.empty())
|
||||||
{
|
{
|
||||||
cachedDc = Gdi::VirtualScreen::createDc();
|
return Gdi::VirtualScreen::createDc();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cachedDc = g_cache.back().release();
|
|
||||||
g_cache.pop_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cachedDc;
|
HDC dc = dcCache.back();
|
||||||
|
dcCache.pop_back();
|
||||||
|
return dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void releaseDc(HDC cachedDc)
|
void releaseDc(HDC cachedDc)
|
||||||
{
|
{
|
||||||
g_cache.emplace_back(CachedDc(cachedDc, &deleteDc));
|
DDraw::ScopedThreadLock lock;
|
||||||
|
g_threadIdToDcCache[GetCurrentThreadId()].push_back(cachedDc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ namespace Gdi
|
|||||||
namespace DcCache
|
namespace DcCache
|
||||||
{
|
{
|
||||||
void deleteDc(HDC cachedDc);
|
void deleteDc(HDC cachedDc);
|
||||||
|
void dllProcessDetach();
|
||||||
|
void dllThreadDetach();
|
||||||
HDC getDc();
|
HDC getDc();
|
||||||
void releaseDc(HDC cachedDc);
|
void releaseDc(HDC cachedDc);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,39 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
class CompatDc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CompatDc(const CompatDc&) = delete;
|
||||||
|
|
||||||
|
CompatDc(CompatDc&& other) : m_origDc(nullptr), m_compatDc(nullptr)
|
||||||
|
{
|
||||||
|
std::swap(m_origDc, other.m_origDc);
|
||||||
|
std::swap(m_compatDc, other.m_compatDc);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CompatDc()
|
||||||
|
{
|
||||||
|
if (m_compatDc)
|
||||||
|
{
|
||||||
|
Gdi::Dc::releaseDc(m_origDc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator HDC() const
|
||||||
|
{
|
||||||
|
return m_compatDc ? m_compatDc : m_origDc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HDC m_origDc;
|
||||||
|
HDC m_compatDc;
|
||||||
|
};
|
||||||
|
|
||||||
struct ExcludeRgnForOverlappingWindowArgs
|
struct ExcludeRgnForOverlappingWindowArgs
|
||||||
{
|
{
|
||||||
HRGN rgn;
|
HRGN rgn;
|
||||||
@ -56,25 +89,9 @@ namespace
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC replaceDc(HDC dc)
|
CompatDc replaceDc(HDC dc)
|
||||||
{
|
{
|
||||||
HDC compatDc = Gdi::Dc::getDc(dc);
|
return CompatDc(dc);
|
||||||
return compatDc ? compatDc : dc;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void releaseDc(T) {}
|
|
||||||
|
|
||||||
void releaseDc(HDC dc)
|
|
||||||
{
|
|
||||||
Gdi::Dc::releaseDc(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Params>
|
|
||||||
void releaseDc(T t, Params... params)
|
|
||||||
{
|
|
||||||
releaseDc(params...);
|
|
||||||
releaseDc(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||||
@ -90,7 +107,6 @@ namespace
|
|||||||
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(params...));
|
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(params...));
|
||||||
Gdi::GdiAccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE);
|
Gdi::GdiAccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE);
|
||||||
result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...);
|
result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...);
|
||||||
releaseDc(params...);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -135,7 +151,6 @@ namespace
|
|||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
result = CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx);
|
result = CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx);
|
||||||
releaseDc(hdc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -155,7 +170,10 @@ namespace
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsWindowVisible(hwnd) ||
|
DWORD windowPid = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||||
|
if (GetCurrentProcessId() != windowPid ||
|
||||||
|
!IsWindowVisible(hwnd) ||
|
||||||
(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & (WS_EX_LAYERED | WS_EX_TRANSPARENT)))
|
(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & (WS_EX_LAYERED | WS_EX_TRANSPARENT)))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -248,8 +266,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExcludeRgnForOverlappingWindowArgs args = { hrgn, GetAncestor(hwnd, GA_ROOT) };
|
ExcludeRgnForOverlappingWindowArgs args = { hrgn, GetAncestor(hwnd, GA_ROOT) };
|
||||||
EnumThreadWindows(Gdi::getGdiThreadId(), excludeRgnForOverlappingWindow,
|
EnumWindows(excludeRgnForOverlappingWindow, reinterpret_cast<LPARAM>(&args));
|
||||||
reinterpret_cast<LPARAM>(&args));
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -282,8 +299,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
HRGN rgn = getWindowRegion(hwnd);
|
HRGN rgn = getWindowRegion(hwnd);
|
||||||
ExcludeRgnForOverlappingWindowArgs args = { rgn, hwnd };
|
ExcludeRgnForOverlappingWindowArgs args = { rgn, hwnd };
|
||||||
EnumThreadWindows(Gdi::getGdiThreadId(), excludeRgnForOverlappingWindow,
|
EnumWindows(excludeRgnForOverlappingWindow, reinterpret_cast<LPARAM>(&args));
|
||||||
reinterpret_cast<LPARAM>(&args));
|
|
||||||
return rgn;
|
return rgn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
#include "Gdi/Caret.h"
|
#include "Gdi/Caret.h"
|
||||||
|
#include "Gdi/Dc.h"
|
||||||
|
#include "Gdi/DcCache.h"
|
||||||
#include "Gdi/DcFunctions.h"
|
#include "Gdi/DcFunctions.h"
|
||||||
#include "Gdi/Gdi.h"
|
#include "Gdi/Gdi.h"
|
||||||
#include "Gdi/PaintHandlers.h"
|
#include "Gdi/PaintHandlers.h"
|
||||||
@ -9,21 +11,27 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
DWORD g_gdiThreadId = 0;
|
|
||||||
HDC g_screenDc = nullptr;
|
HDC g_screenDc = nullptr;
|
||||||
|
|
||||||
BOOL CALLBACK redrawWindowCallback(HWND hwnd, LPARAM lParam)
|
BOOL CALLBACK redrawWindowCallback(HWND hwnd, LPARAM lParam)
|
||||||
{
|
{
|
||||||
Gdi::redrawWindow(hwnd, reinterpret_cast<HRGN>(lParam));
|
DWORD windowPid = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||||
|
if (GetCurrentProcessId() == windowPid)
|
||||||
|
{
|
||||||
|
Gdi::redrawWindow(hwnd, reinterpret_cast<HRGN>(lParam));
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
{
|
{
|
||||||
DWORD getGdiThreadId()
|
void dllThreadDetach()
|
||||||
{
|
{
|
||||||
return g_gdiThreadId;
|
WinProc::dllThreadDetach();
|
||||||
|
Dc::dllThreadDetach();
|
||||||
|
DcCache::dllThreadDetach();
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC getScreenDc()
|
HDC getScreenDc()
|
||||||
@ -38,19 +46,18 @@ namespace Gdi
|
|||||||
|
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
g_gdiThreadId = GetCurrentThreadId();
|
|
||||||
g_screenDc = GetDC(nullptr);
|
g_screenDc = GetDC(nullptr);
|
||||||
|
|
||||||
Gdi::DcFunctions::installHooks();
|
DcFunctions::installHooks();
|
||||||
Gdi::PaintHandlers::installHooks();
|
PaintHandlers::installHooks();
|
||||||
Gdi::ScrollFunctions::installHooks();
|
ScrollFunctions::installHooks();
|
||||||
Gdi::WinProc::installHooks();
|
WinProc::installHooks();
|
||||||
Gdi::Caret::installHooks();
|
Caret::installHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void redraw(HRGN rgn)
|
void redraw(HRGN rgn)
|
||||||
{
|
{
|
||||||
EnumThreadWindows(g_gdiThreadId, &redrawWindowCallback, reinterpret_cast<LPARAM>(rgn));
|
EnumWindows(&redrawWindowCallback, reinterpret_cast<LPARAM>(rgn));
|
||||||
}
|
}
|
||||||
|
|
||||||
void redrawWindow(HWND hwnd, HRGN rgn)
|
void redrawWindow(HWND hwnd, HRGN rgn)
|
||||||
@ -68,7 +75,6 @@ namespace Gdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
RedrawWindow(hwnd, nullptr, rgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
RedrawWindow(hwnd, nullptr, rgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||||||
RedrawWindow(hwnd, nullptr, rgn, RDW_ERASENOW);
|
|
||||||
|
|
||||||
if (rgn)
|
if (rgn)
|
||||||
{
|
{
|
||||||
@ -85,9 +91,10 @@ namespace Gdi
|
|||||||
|
|
||||||
void uninstallHooks()
|
void uninstallHooks()
|
||||||
{
|
{
|
||||||
Gdi::Caret::uninstallHooks();
|
Caret::uninstallHooks();
|
||||||
Gdi::WinProc::uninstallHooks();
|
WinProc::uninstallHooks();
|
||||||
Gdi::PaintHandlers::uninstallHooks();
|
Dc::dllProcessDetach();
|
||||||
|
DcCache::dllProcessDetach();
|
||||||
ReleaseDC(nullptr, g_screenDc);
|
ReleaseDC(nullptr, g_screenDc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace Gdi
|
|||||||
|
|
||||||
typedef void(*WindowPosChangeNotifyFunc)();
|
typedef void(*WindowPosChangeNotifyFunc)();
|
||||||
|
|
||||||
DWORD getGdiThreadId();
|
void dllThreadDetach();
|
||||||
HDC getScreenDc();
|
HDC getScreenDc();
|
||||||
HRGN getVisibleWindowRgn(HWND hwnd);
|
HRGN getVisibleWindowRgn(HWND hwnd);
|
||||||
void installHooks();
|
void installHooks();
|
||||||
|
@ -41,7 +41,6 @@ namespace
|
|||||||
LRESULT onPaint(HWND hwnd, WNDPROC origWndProc);
|
LRESULT onPaint(HWND hwnd, WNDPROC origWndProc);
|
||||||
LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc);
|
LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc);
|
||||||
|
|
||||||
HHOOK g_cbtProcHook = nullptr;
|
|
||||||
int g_menuWndProcIndex = 0;
|
int g_menuWndProcIndex = 0;
|
||||||
int g_scrollBarWndProcIndex = 0;
|
int g_scrollBarWndProcIndex = 0;
|
||||||
|
|
||||||
@ -71,52 +70,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK cbtProc(int nCode, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
Compat::LogEnter("cbtProc", Compat::hex(nCode), Compat::hex(wParam), Compat::hex(lParam));
|
|
||||||
LRESULT result = 0;
|
|
||||||
|
|
||||||
if (nCode < 0)
|
|
||||||
{
|
|
||||||
result = CallNextHookEx(nullptr, nCode, wParam, lParam);
|
|
||||||
}
|
|
||||||
else if (HCBT_CREATEWND == nCode)
|
|
||||||
{
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(wParam);
|
|
||||||
WNDPROC wndProcA = reinterpret_cast<WNDPROC>(GetWindowLongA(hwnd, GWL_WNDPROC));
|
|
||||||
WNDPROC wndProcW = reinterpret_cast<WNDPROC>(GetWindowLongW(hwnd, GWL_WNDPROC));
|
|
||||||
|
|
||||||
int index = -1;
|
|
||||||
if (wndProcA == g_user32WndProcA[g_menuWndProcIndex].oldWndProc ||
|
|
||||||
wndProcW == g_user32WndProcW[g_menuWndProcIndex].oldWndProc)
|
|
||||||
{
|
|
||||||
index = g_menuWndProcIndex;
|
|
||||||
}
|
|
||||||
else if (wndProcA == g_user32WndProcA[g_scrollBarWndProcIndex].oldWndProc ||
|
|
||||||
wndProcW == g_user32WndProcW[g_scrollBarWndProcIndex].oldWndProc)
|
|
||||||
{
|
|
||||||
index = g_scrollBarWndProcIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 != index)
|
|
||||||
{
|
|
||||||
if (IsWindowUnicode(hwnd))
|
|
||||||
{
|
|
||||||
CALL_ORIG_FUNC(SetWindowLongW)(hwnd, GWL_WNDPROC,
|
|
||||||
reinterpret_cast<LONG>(g_user32WndProcW[index].newWndProc));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC,
|
|
||||||
reinterpret_cast<LONG>(g_user32WndProcA[index].newWndProc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Compat::LogLeave("cbtProc", Compat::hex(nCode), Compat::hex(wParam), Compat::hex(lParam)) << result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT comboBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc)
|
LRESULT comboBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc)
|
||||||
{
|
{
|
||||||
return defPaintProc(hwnd, msg, wParam, lParam, origWndProc);
|
return defPaintProc(hwnd, msg, wParam, lParam, origWndProc);
|
||||||
@ -481,13 +434,38 @@ namespace Gdi
|
|||||||
HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
|
HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
|
||||||
HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
|
HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
|
||||||
HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
|
HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
|
||||||
|
|
||||||
g_cbtProcHook = SetWindowsHookEx(WH_CBT, cbtProc, nullptr, Gdi::getGdiThreadId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninstallHooks()
|
void onCreateWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
UnhookWindowsHookEx(g_cbtProcHook);
|
WNDPROC wndProcA = reinterpret_cast<WNDPROC>(GetWindowLongA(hwnd, GWL_WNDPROC));
|
||||||
|
WNDPROC wndProcW = reinterpret_cast<WNDPROC>(GetWindowLongW(hwnd, GWL_WNDPROC));
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
if (wndProcA == g_user32WndProcA[g_menuWndProcIndex].oldWndProc ||
|
||||||
|
wndProcW == g_user32WndProcW[g_menuWndProcIndex].oldWndProc)
|
||||||
|
{
|
||||||
|
index = g_menuWndProcIndex;
|
||||||
|
}
|
||||||
|
else if (wndProcA == g_user32WndProcA[g_scrollBarWndProcIndex].oldWndProc ||
|
||||||
|
wndProcW == g_user32WndProcW[g_scrollBarWndProcIndex].oldWndProc)
|
||||||
|
{
|
||||||
|
index = g_scrollBarWndProcIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 != index)
|
||||||
|
{
|
||||||
|
if (IsWindowUnicode(hwnd))
|
||||||
|
{
|
||||||
|
CALL_ORIG_FUNC(SetWindowLongW)(hwnd, GWL_WNDPROC,
|
||||||
|
reinterpret_cast<LONG>(g_user32WndProcW[index].newWndProc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC,
|
||||||
|
reinterpret_cast<LONG>(g_user32WndProcA[index].newWndProc));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,6 @@ namespace Gdi
|
|||||||
namespace PaintHandlers
|
namespace PaintHandlers
|
||||||
{
|
{
|
||||||
void installHooks();
|
void installHooks();
|
||||||
void uninstallHooks();
|
void onCreateWindow(HWND hwnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "Common/ScopedCriticalSection.h"
|
|
||||||
#include "DDraw/DirectDraw.h"
|
#include "DDraw/DirectDraw.h"
|
||||||
#include "DDraw/Repository.h"
|
#include "DDraw/Repository.h"
|
||||||
|
#include "DDraw/ScopedThreadLock.h"
|
||||||
#include "Gdi/Gdi.h"
|
#include "Gdi/Gdi.h"
|
||||||
#include "Gdi/Region.h"
|
#include "Gdi/Region.h"
|
||||||
#include "Gdi/VirtualScreen.h"
|
#include "Gdi/VirtualScreen.h"
|
||||||
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
CRITICAL_SECTION g_cs = {};
|
|
||||||
Gdi::Region g_region;
|
Gdi::Region g_region;
|
||||||
RECT g_bounds = {};
|
RECT g_bounds = {};
|
||||||
DWORD g_bpp = 0;
|
DWORD g_bpp = 0;
|
||||||
@ -71,7 +70,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
HDC createDc()
|
HDC createDc()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(), DeleteObject);
|
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(), DeleteObject);
|
||||||
if (!dib)
|
if (!dib)
|
||||||
{
|
{
|
||||||
@ -100,7 +99,7 @@ namespace Gdi
|
|||||||
|
|
||||||
HBITMAP createDib()
|
HBITMAP createDib()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
if (!g_surfaceFileMapping)
|
if (!g_surfaceFileMapping)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -110,7 +109,7 @@ namespace Gdi
|
|||||||
|
|
||||||
HBITMAP createOffScreenDib(DWORD width, DWORD height)
|
HBITMAP createOffScreenDib(DWORD width, DWORD height)
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
return createDibSection(width, height, nullptr);
|
return createDibSection(width, height, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ namespace Gdi
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
DDSURFACEDESC2 desc = {};
|
DDSURFACEDESC2 desc = {};
|
||||||
desc.dwSize = sizeof(desc);
|
desc.dwSize = sizeof(desc);
|
||||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE;
|
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE;
|
||||||
@ -148,7 +147,7 @@ namespace Gdi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
DeleteObject(SelectObject(dc, g_stockBitmap));
|
DeleteObject(SelectObject(dc, g_stockBitmap));
|
||||||
DeleteDC(dc);
|
DeleteDC(dc);
|
||||||
g_dcs.erase(dc);
|
g_dcs.erase(dc);
|
||||||
@ -156,19 +155,18 @@ namespace Gdi
|
|||||||
|
|
||||||
RECT getBounds()
|
RECT getBounds()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
return g_bounds;
|
return g_bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Region& getRegion()
|
const Region& getRegion()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
return g_region;
|
return g_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&g_cs);
|
|
||||||
update();
|
update();
|
||||||
updatePalette();
|
updatePalette();
|
||||||
}
|
}
|
||||||
@ -176,7 +174,7 @@ namespace Gdi
|
|||||||
bool update()
|
bool update()
|
||||||
{
|
{
|
||||||
Compat::LogEnter("VirtualScreen::update");
|
Compat::LogEnter("VirtualScreen::update");
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
|
|
||||||
static auto prevDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
static auto prevDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
||||||
const auto currentDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness();
|
const auto currentDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness();
|
||||||
@ -224,7 +222,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void updatePalette()
|
void updatePalette()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
DDraw::ScopedThreadLock lock;
|
||||||
if (8 != g_bpp)
|
if (8 != g_bpp)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
@ -11,15 +10,20 @@
|
|||||||
#include "Common/ScopedCriticalSection.h"
|
#include "Common/ScopedCriticalSection.h"
|
||||||
#include "Gdi/AccessGuard.h"
|
#include "Gdi/AccessGuard.h"
|
||||||
#include "Gdi/Dc.h"
|
#include "Gdi/Dc.h"
|
||||||
|
#include "Gdi/PaintHandlers.h"
|
||||||
#include "Gdi/ScrollBar.h"
|
#include "Gdi/ScrollBar.h"
|
||||||
#include "Gdi/ScrollFunctions.h"
|
#include "Gdi/ScrollFunctions.h"
|
||||||
#include "Gdi/TitleBar.h"
|
#include "Gdi/TitleBar.h"
|
||||||
#include "Gdi/Window.h"
|
#include "Gdi/Window.h"
|
||||||
#include "Gdi/WinProc.h"
|
#include "Gdi/WinProc.h"
|
||||||
|
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
HHOOK g_callWndRetProcHook = nullptr;
|
std::multimap<DWORD, HHOOK> g_threadIdToHook;
|
||||||
|
Compat::CriticalSection g_threadIdToHookCs;
|
||||||
|
HWINEVENTHOOK g_objectCreateEventHook = nullptr;
|
||||||
HWINEVENTHOOK g_objectStateChangeEventHook = nullptr;
|
HWINEVENTHOOK g_objectStateChangeEventHook = nullptr;
|
||||||
std::set<Gdi::WindowPosChangeNotifyFunc> g_windowPosChangeNotifyFuncs;
|
std::set<Gdi::WindowPosChangeNotifyFunc> g_windowPosChangeNotifyFuncs;
|
||||||
|
|
||||||
@ -35,13 +39,9 @@ namespace
|
|||||||
auto ret = reinterpret_cast<CWPRETSTRUCT*>(lParam);
|
auto ret = reinterpret_cast<CWPRETSTRUCT*>(lParam);
|
||||||
Compat::LogEnter("callWndRetProc", Compat::hex(nCode), Compat::hex(wParam), ret);
|
Compat::LogEnter("callWndRetProc", Compat::hex(nCode), Compat::hex(wParam), ret);
|
||||||
|
|
||||||
if (HC_ACTION == nCode)
|
if (HC_ACTION == nCode && !Gdi::Window::isPresentationWindow(ret->hwnd))
|
||||||
{
|
{
|
||||||
if (WM_CREATE == ret->message)
|
if (WM_DESTROY == ret->message)
|
||||||
{
|
|
||||||
onCreateWindow(ret->hwnd);
|
|
||||||
}
|
|
||||||
else if (WM_DESTROY == ret->message)
|
|
||||||
{
|
{
|
||||||
onDestroyWindow(ret->hwnd);
|
onDestroyWindow(ret->hwnd);
|
||||||
}
|
}
|
||||||
@ -79,8 +79,25 @@ namespace
|
|||||||
&disableTransitions, sizeof(disableTransitions));
|
&disableTransitions, sizeof(disableTransitions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hookThread(DWORD threadId)
|
||||||
|
{
|
||||||
|
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||||
|
if (g_threadIdToHook.end() == g_threadIdToHook.find(threadId))
|
||||||
|
{
|
||||||
|
g_threadIdToHook.emplace(threadId,
|
||||||
|
SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
|
BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
|
||||||
{
|
{
|
||||||
|
DWORD windowPid = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||||
|
if (GetCurrentProcessId() != windowPid)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
onCreateWindow(hwnd);
|
onCreateWindow(hwnd);
|
||||||
if (!(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED))
|
if (!(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED))
|
||||||
{
|
{
|
||||||
@ -90,6 +107,21 @@ namespace
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CALLBACK objectCreateEvent(
|
||||||
|
HWINEVENTHOOK /*hWinEventHook*/,
|
||||||
|
DWORD /*event*/,
|
||||||
|
HWND hwnd,
|
||||||
|
LONG idObject,
|
||||||
|
LONG /*idChild*/,
|
||||||
|
DWORD /*dwEventThread*/,
|
||||||
|
DWORD /*dwmsEventTime*/)
|
||||||
|
{
|
||||||
|
if (OBJID_WINDOW == idObject && !Gdi::Window::isPresentationWindow(hwnd))
|
||||||
|
{
|
||||||
|
onCreateWindow(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CALLBACK objectStateChangeEvent(
|
void CALLBACK objectStateChangeEvent(
|
||||||
HWINEVENTHOOK /*hWinEventHook*/,
|
HWINEVENTHOOK /*hWinEventHook*/,
|
||||||
DWORD /*event*/,
|
DWORD /*event*/,
|
||||||
@ -149,9 +181,14 @@ namespace
|
|||||||
|
|
||||||
void onCreateWindow(HWND hwnd)
|
void onCreateWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
|
hookThread(GetWindowThreadProcessId(hwnd, nullptr));
|
||||||
disableDwmAttributes(hwnd);
|
disableDwmAttributes(hwnd);
|
||||||
removeDropShadow(hwnd);
|
removeDropShadow(hwnd);
|
||||||
Gdi::Window::add(hwnd);
|
Gdi::PaintHandlers::onCreateWindow(hwnd);
|
||||||
|
if (Gdi::Window::isTopLevelNonLayeredWindow(hwnd))
|
||||||
|
{
|
||||||
|
Gdi::Window::add(hwnd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDestroyWindow(HWND hwnd)
|
void onDestroyWindow(HWND hwnd)
|
||||||
@ -191,14 +228,30 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace WinProc
|
namespace WinProc
|
||||||
{
|
{
|
||||||
|
void dllThreadDetach()
|
||||||
|
{
|
||||||
|
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||||
|
const DWORD threadId = GetCurrentThreadId();
|
||||||
|
for (auto threadIdToHook : g_threadIdToHook)
|
||||||
|
{
|
||||||
|
if (threadId == threadIdToHook.first)
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(threadIdToHook.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_threadIdToHook.erase(threadId);
|
||||||
|
}
|
||||||
|
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
const DWORD threadId = Gdi::getGdiThreadId();
|
g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
||||||
g_callWndRetProcHook = SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId);
|
reinterpret_cast<HMODULE>(&__ImageBase), &objectCreateEvent,
|
||||||
|
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||||
g_objectStateChangeEventHook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE,
|
g_objectStateChangeEventHook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE,
|
||||||
nullptr, &objectStateChangeEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
reinterpret_cast<HMODULE>(&__ImageBase), &objectStateChangeEvent,
|
||||||
|
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||||
|
|
||||||
EnumThreadWindows(threadId, initTopLevelWindow, 0);
|
EnumWindows(initTopLevelWindow, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
|
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
|
||||||
@ -209,7 +262,16 @@ namespace Gdi
|
|||||||
void uninstallHooks()
|
void uninstallHooks()
|
||||||
{
|
{
|
||||||
UnhookWinEvent(g_objectStateChangeEventHook);
|
UnhookWinEvent(g_objectStateChangeEventHook);
|
||||||
UnhookWindowsHookEx(g_callWndRetProcHook);
|
UnhookWinEvent(g_objectCreateEventHook);
|
||||||
|
|
||||||
|
{
|
||||||
|
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||||
|
for (auto threadIdToHook : g_threadIdToHook)
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(threadIdToHook.second);
|
||||||
|
}
|
||||||
|
g_threadIdToHook.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace WinProc
|
namespace WinProc
|
||||||
{
|
{
|
||||||
|
void dllThreadDetach();
|
||||||
void installHooks();
|
void installHooks();
|
||||||
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc);
|
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc);
|
||||||
void uninstallHooks();
|
void uninstallHooks();
|
||||||
|
@ -66,13 +66,9 @@ namespace Gdi
|
|||||||
|
|
||||||
bool Window::add(HWND hwnd)
|
bool Window::add(HWND hwnd)
|
||||||
{
|
{
|
||||||
const bool isTopLevelNonLayeredWindow = !(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
if (isTopLevelNonLayeredWindow(hwnd) && !get(hwnd))
|
||||||
(!(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) || GetParent(hwnd) == GetDesktopWindow() ||
|
|
||||||
getComboLBoxAtom() == GetClassLong(hwnd, GCW_ATOM));
|
|
||||||
|
|
||||||
if (isTopLevelNonLayeredWindow && !get(hwnd) &&
|
|
||||||
GetClassLong(hwnd, GCW_ATOM) != getPresentationWindowClassAtom())
|
|
||||||
{
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
s_windows.emplace(hwnd, std::make_shared<Window>(hwnd));
|
s_windows.emplace(hwnd, std::make_shared<Window>(hwnd));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -143,7 +139,14 @@ namespace Gdi
|
|||||||
|
|
||||||
bool Window::isPresentationWindow(HWND hwnd)
|
bool Window::isPresentationWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
return GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom();
|
return IsWindow(hwnd) && GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::isTopLevelNonLayeredWindow(HWND hwnd)
|
||||||
|
{
|
||||||
|
return !(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||||
|
(!(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) || GetParent(hwnd) == GetDesktopWindow() ||
|
||||||
|
getComboLBoxAtom() == GetClassLong(hwnd, GCW_ATOM));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::remove(HWND hwnd)
|
void Window::remove(HWND hwnd)
|
||||||
@ -175,14 +178,14 @@ namespace Gdi
|
|||||||
newVisibleRegion &= VirtualScreen::getRegion();
|
newVisibleRegion &= VirtualScreen::getRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_presentationWindow)
|
if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))
|
||||||
{
|
{
|
||||||
SetWindowPos(m_presentationWindow, nullptr, newWindowRect.left, newWindowRect.top,
|
SetWindowPos(m_presentationWindow, nullptr, newWindowRect.left, newWindowRect.top,
|
||||||
newWindowRect.right - newWindowRect.left, newWindowRect.bottom - newWindowRect.top,
|
newWindowRect.right - newWindowRect.left, newWindowRect.bottom - newWindowRect.top,
|
||||||
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW);
|
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_presentationWindow)
|
else if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))
|
||||||
{
|
{
|
||||||
ShowWindow(m_presentationWindow, SW_HIDE);
|
ShowWindow(m_presentationWindow, SW_HIDE);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ namespace Gdi
|
|||||||
|
|
||||||
static std::map<HWND, std::shared_ptr<Window>> getWindows();
|
static std::map<HWND, std::shared_ptr<Window>> getWindows();
|
||||||
static bool isPresentationWindow(HWND hwnd);
|
static bool isPresentationWindow(HWND hwnd);
|
||||||
|
static bool isTopLevelNonLayeredWindow(HWND hwnd);
|
||||||
static void updateAll();
|
static void updateAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "Common/CompatPtr.h"
|
#include "Common/CompatPtr.h"
|
||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "DDraw/DirectDraw.h"
|
#include "DDraw/DirectDraw.h"
|
||||||
#include "DDraw/RealPrimarySurface.h"
|
#include "DDraw/ScopedThreadLock.h"
|
||||||
#include "Win32/DisplayMode.h"
|
#include "Win32/DisplayMode.h"
|
||||||
|
|
||||||
BOOL WINAPI DWM8And16Bit_IsShimApplied_CallOut() { return FALSE; };
|
BOOL WINAPI DWM8And16Bit_IsShimApplied_CallOut() { return FALSE; };
|
||||||
@ -48,12 +48,12 @@ namespace
|
|||||||
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx,
|
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx,
|
||||||
CStr lpszDeviceName, DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
|
CStr lpszDeviceName, DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
|
||||||
{
|
{
|
||||||
|
DDraw::ScopedThreadLock lock;
|
||||||
DevMode prevDevMode = {};
|
DevMode prevDevMode = {};
|
||||||
if (!(dwflags & CDS_TEST))
|
if (!(dwflags & CDS_TEST))
|
||||||
{
|
{
|
||||||
prevDevMode.dmSize = sizeof(prevDevMode);
|
prevDevMode.dmSize = sizeof(prevDevMode);
|
||||||
origEnumDisplaySettingsEx(lpszDeviceName, ENUM_CURRENT_SETTINGS, &prevDevMode, 0);
|
origEnumDisplaySettingsEx(lpszDeviceName, ENUM_CURRENT_SETTINGS, &prevDevMode, 0);
|
||||||
DDraw::RealPrimarySurface::disableUpdates();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL result = FALSE;
|
BOOL result = FALSE;
|
||||||
@ -99,11 +99,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dwflags & CDS_TEST))
|
|
||||||
{
|
|
||||||
DDraw::RealPrimarySurface::enableUpdates();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user