From 13ab6546656ffc73dc1eade81c3d96819836b323 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 2 Jan 2021 22:31:23 +0100 Subject: [PATCH] Moved presentation window implementation to separate file --- DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 6 + DDrawCompat/Gdi/Gdi.cpp | 8 +- DDrawCompat/Gdi/PresentationWindow.cpp | 185 ++++++++++++++++++++++++ DDrawCompat/Gdi/PresentationWindow.h | 18 +++ DDrawCompat/Gdi/WinProc.cpp | 5 +- DDrawCompat/Gdi/Window.cpp | 170 +--------------------- DDrawCompat/Gdi/Window.h | 4 - 8 files changed, 226 insertions(+), 172 deletions(-) create mode 100644 DDrawCompat/Gdi/PresentationWindow.cpp create mode 100644 DDrawCompat/Gdi/PresentationWindow.h diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 8d80be5..c122075 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -221,6 +221,7 @@ + @@ -294,6 +295,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index d4ec640..3aa806d 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -399,6 +399,9 @@ Header Files\Gdi + + Header Files\Gdi + @@ -614,5 +617,8 @@ Source Files\Gdi + + Source Files\Gdi + \ No newline at end of file diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp index e1a1a67..a12b587 100644 --- a/DDrawCompat/Gdi/Gdi.cpp +++ b/DDrawCompat/Gdi/Gdi.cpp @@ -6,9 +6,9 @@ #include #include #include +#include #include #include -#include #include namespace @@ -38,9 +38,9 @@ namespace Gdi { DcFunctions::installHooks(); Palette::installHooks(); + PresentationWindow::installHooks(); ScrollFunctions::installHooks(); User32WndProcs::installHooks(); - Window::installHooks(); WinProc::installHooks(); Caret::installHooks(); Font::installHooks(); @@ -59,7 +59,7 @@ namespace Gdi void redrawWindow(HWND hwnd, HRGN rgn) { - if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || Window::isPresentationWindow(hwnd)) + if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || PresentationWindow::isPresentationWindow(hwnd)) { return; } @@ -89,8 +89,8 @@ namespace Gdi void uninstallHooks() { Caret::uninstallHooks(); + PresentationWindow::uninstallHooks(); WinProc::uninstallHooks(); - Window::uninstallHooks(); Dc::dllProcessDetach(); DcCache::dllProcessDetach(); } diff --git a/DDrawCompat/Gdi/PresentationWindow.cpp b/DDrawCompat/Gdi/PresentationWindow.cpp new file mode 100644 index 0000000..80bb889 --- /dev/null +++ b/DDrawCompat/Gdi/PresentationWindow.cpp @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +namespace +{ + const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER; + const UINT WM_SETPRESENTATIONWINDOWPOS = WM_USER + 1; + const UINT WM_SETPRESENTATIONWINDOWRGN = WM_USER + 2; + + HANDLE g_presentationWindowThread = nullptr; + DWORD g_presentationWindowThreadId = 0; + HWND g_messageWindow = nullptr; + + LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam)); + + switch (uMsg) + { + case WM_CREATEPRESENTATIONWINDOW: + { + // Workaround for ForceSimpleWindow shim + static auto origCreateWindowExA = reinterpret_cast( + Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA")); + + HWND owner = reinterpret_cast(wParam); + HWND presentationWindow = origCreateWindowExA( + WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW, + "DDrawCompatPresentationWindow", + nullptr, + WS_DISABLED | WS_POPUP, + 0, 0, 1, 1, + owner, + nullptr, + nullptr, + nullptr); + + if (presentationWindow) + { + CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA); + } + + return LOG_RESULT(reinterpret_cast(presentationWindow)); + } + + case WM_DESTROY: + PostQuitMessage(0); + return LOG_RESULT(0); + } + + return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam)); + } + + LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam)); + + switch (uMsg) + { + case WM_SETPRESENTATIONWINDOWPOS: + { + const auto& wp = *reinterpret_cast(lParam); + return SetWindowPos(hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); + } + + case WM_SETPRESENTATIONWINDOWRGN: + { + HRGN rgn = nullptr; + if (wParam) + { + rgn = CreateRectRgn(0, 0, 0, 0); + CombineRgn(rgn, reinterpret_cast(wParam), nullptr, RGN_COPY); + } + return SetWindowRgn(hwnd, rgn, FALSE); + } + } + + return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam); + } + + DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/) + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + WNDCLASS wc = {}; + wc.lpfnWndProc = &messageWindowProc; + wc.hInstance = Dll::g_currentModule; + wc.lpszClassName = "DDrawCompatMessageWindow"; + RegisterClass(&wc); + + g_messageWindow = CreateWindow( + "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr); + if (!g_messageWindow) + { + return 0; + } + + MSG msg = {}; + while (GetMessage(&msg, nullptr, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return 0; + } + + LRESULT sendMessageBlocking(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + DWORD_PTR result = 0; + SendMessageTimeout(hwnd, msg, wParam, lParam, SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result); + return result; + } +} + +namespace Gdi +{ + namespace PresentationWindow + { + HWND create(HWND owner) + { + return reinterpret_cast(sendMessageBlocking( + g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast(owner), 0)); + } + + void destroy(HWND hwnd) + { + sendMessageBlocking(hwnd, WM_CLOSE, 0, 0); + } + + void installHooks() + { + WNDCLASS wc = {}; + wc.lpfnWndProc = &presentationWindowProc; + wc.hInstance = Dll::g_currentModule; + wc.lpszClassName = "DDrawCompatPresentationWindow"; + RegisterClass(&wc); + + g_presentationWindowThread = CreateThread( + nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId); + + int i = 0; + while (!g_messageWindow && i < 1000) + { + Sleep(1); + ++i; + } + + if (!g_messageWindow) + { + Compat::Log() << "ERROR: Failed to create a message-only window"; + } + } + + bool isPresentationWindow(HWND hwnd) + { + return GetWindowThreadProcessId(hwnd, nullptr) == g_presentationWindowThreadId; + } + + void setWindowPos(HWND hwnd, const WINDOWPOS& wp) + { + sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWPOS, 0, reinterpret_cast(&wp)); + } + + void setWindowRgn(HWND hwnd, HRGN rgn) + { + sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWRGN, reinterpret_cast(rgn), 0); + } + + void uninstallHooks() + { + if (g_presentationWindowThread) + { + sendMessageBlocking(g_messageWindow, WM_CLOSE, 0, 0); + if (WAIT_OBJECT_0 != WaitForSingleObject(g_presentationWindowThread, 1000)) + { + TerminateThread(g_presentationWindowThread, 0); + Compat::Log() << "The presentation window thread was terminated forcefully"; + } + } + } + } +} diff --git a/DDrawCompat/Gdi/PresentationWindow.h b/DDrawCompat/Gdi/PresentationWindow.h new file mode 100644 index 0000000..93102a4 --- /dev/null +++ b/DDrawCompat/Gdi/PresentationWindow.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace Gdi +{ + namespace PresentationWindow + { + HWND create(HWND owner); + void destroy(HWND hwnd); + bool isPresentationWindow(HWND hwnd); + void setWindowPos(HWND hwnd, const WINDOWPOS& wp); + void setWindowRgn(HWND hwnd, HRGN rgn); + + void installHooks(); + void uninstallHooks(); + } +} diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index 0c79867..7e79422 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -9,12 +9,13 @@ #include #include #include -#include +#include #include #include #include #include #include +#include namespace { @@ -171,7 +172,7 @@ namespace DWORD /*dwEventThread*/, DWORD /*dwmsEventTime*/) { - if (OBJID_WINDOW == idObject && !Gdi::Window::isPresentationWindow(hwnd)) + if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd)) { onCreateWindow(hwnd); } diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index 95d9ec5..e8940a8 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -4,12 +4,11 @@ #include -#include #include #include #include #include -#include +#include #include #include @@ -50,14 +49,8 @@ namespace } }; - const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER; - const UINT WM_SETPRESENTATIONWINDOWPOS = WM_USER + 1; - const UINT WM_SETPRESENTATIONWINDOWRGN = WM_USER + 2; const RECT REGION_OVERRIDE_MARKER_RECT = { 32000, 32000, 32001, 32001 }; - HANDLE g_presentationWindowThread = nullptr; - DWORD g_presentationWindowThreadId = 0; - HWND g_messageWindow = nullptr; std::map g_windows; std::vector g_windowZOrder; @@ -102,107 +95,6 @@ namespace return rgn; } - LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam)); - switch (uMsg) - { - case WM_CREATEPRESENTATIONWINDOW: - { - // Workaround for ForceSimpleWindow shim - static auto origCreateWindowExA = reinterpret_cast( - Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA")); - - HWND owner = reinterpret_cast(wParam); - HWND presentationWindow = origCreateWindowExA( - WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW, - "DDrawCompatPresentationWindow", - nullptr, - WS_DISABLED | WS_POPUP, - 0, 0, 1, 1, - owner, - nullptr, - nullptr, - nullptr); - - if (presentationWindow) - { - CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA); - } - - return reinterpret_cast(presentationWindow); - } - - case WM_DESTROY: - PostQuitMessage(0); - return 0; - - default: - return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam); - } - } - - LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam)); - - switch (uMsg) - { - case WM_SETPRESENTATIONWINDOWPOS: - { - const auto& wp = *reinterpret_cast(lParam); - return SetWindowPos(hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); - } - - case WM_SETPRESENTATIONWINDOWRGN: - { - HRGN rgn = nullptr; - if (wParam) - { - rgn = CreateRectRgn(0, 0, 0, 0); - CombineRgn(rgn, reinterpret_cast(wParam), nullptr, RGN_COPY); - } - return SetWindowRgn(hwnd, rgn, FALSE); - } - } - - return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam); - } - - DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/) - { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - WNDCLASS wc = {}; - wc.lpfnWndProc = &messageWindowProc; - wc.hInstance = Dll::g_currentModule; - wc.lpszClassName = "DDrawCompatMessageWindow"; - RegisterClass(&wc); - - g_messageWindow = CreateWindow( - "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr); - if (!g_messageWindow) - { - return 0; - } - - MSG msg = {}; - while (GetMessage(&msg, nullptr, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return 0; - } - - LRESULT sendMessageBlocking(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) - { - DWORD_PTR result = 0; - SendMessageTimeout(hwnd, msg, wParam, lParam, SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result); - return result; - } - void updatePosition(Window& window, const RECT& oldWindowRect, const RECT& oldClientRect, const Gdi::Region& oldVisibleRegion) { @@ -286,8 +178,8 @@ namespace DWORD processId = 0; GetWindowThreadProcessId(hwnd, &processId); - if (GetWindowThreadProcessId(hwnd, &processId) == g_presentationWindowThreadId || - processId != context.processId) + if (processId != context.processId || + Gdi::PresentationWindow::isPresentationWindow(hwnd)) { return TRUE; } @@ -310,13 +202,12 @@ namespace it->second.isVisibleRegionChanged = isVisible; if (!isLayered) { - it->second.presentationWindow = reinterpret_cast( - sendMessageBlocking(g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast(hwnd), 0)); + it->second.presentationWindow = Gdi::PresentationWindow::create(hwnd); setPresentationWindowRgn = true; } else if (it->second.presentationWindow) { - sendMessageBlocking(it->second.presentationWindow, WM_CLOSE, 0, 0); + Gdi::PresentationWindow::destroy(it->second.presentationWindow); it->second.presentationWindow = nullptr; } } @@ -382,9 +273,7 @@ namespace { if (setPresentationWindowRgn) { - HRGN rgn = it->second.windowRegion; - sendMessageBlocking(it->second.presentationWindow, WM_SETPRESENTATIONWINDOWRGN, - reinterpret_cast(rgn), 0); + Gdi::PresentationWindow::setWindowRgn(it->second.presentationWindow, it->second.windowRegion); } WINDOWPOS wp = {}; @@ -412,8 +301,7 @@ namespace wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER; } - sendMessageBlocking(it->second.presentationWindow, WM_SETPRESENTATIONWINDOWPOS, - 0, reinterpret_cast(&wp)); + Gdi::PresentationWindow::setWindowPos(it->second.presentationWindow, wp); } } return TRUE; @@ -424,35 +312,6 @@ namespace Gdi { namespace Window { - void installHooks() - { - WNDCLASS wc = {}; - wc.lpfnWndProc = &presentationWindowProc; - wc.hInstance = Dll::g_currentModule; - wc.lpszClassName = "DDrawCompatPresentationWindow"; - RegisterClass(&wc); - - g_presentationWindowThread = CreateThread( - nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId); - - int i = 0; - while (!g_messageWindow && i < 1000) - { - Sleep(1); - ++i; - } - - if (!g_messageWindow) - { - Compat::Log() << "ERROR: Failed to create a message-only window"; - } - } - - bool isPresentationWindow(HWND hwnd) - { - return g_presentationWindowThreadId == GetWindowThreadProcessId(hwnd, nullptr); - } - void onStyleChanged(HWND hwnd, WPARAM wParam) { if (GWL_EXSTYLE == wParam) @@ -655,7 +514,7 @@ namespace Gdi { if (it->second.presentationWindow) { - sendMessageBlocking(it->second.presentationWindow, WM_CLOSE, 0, 0); + Gdi::PresentationWindow::destroy(it->second.presentationWindow); } it = g_windows.erase(it); } @@ -695,18 +554,5 @@ namespace Gdi } } } - - void uninstallHooks() - { - if (g_presentationWindowThread) - { - sendMessageBlocking(g_messageWindow, WM_CLOSE, 0, 0); - if (WAIT_OBJECT_0 != WaitForSingleObject(g_presentationWindowThread, 1000)) - { - TerminateThread(g_presentationWindowThread, 0); - Compat::Log() << "The presentation window thread was terminated forcefully"; - } - } - } } } diff --git a/DDrawCompat/Gdi/Window.h b/DDrawCompat/Gdi/Window.h index 654febd..38bb546 100644 --- a/DDrawCompat/Gdi/Window.h +++ b/DDrawCompat/Gdi/Window.h @@ -9,7 +9,6 @@ namespace Gdi { namespace Window { - bool isPresentationWindow(HWND hwnd); void onStyleChanged(HWND hwnd, WPARAM wParam); void onSyncPaint(HWND hwnd); void present(CompatRef dst, CompatRef src, @@ -18,8 +17,5 @@ namespace Gdi void presentLayered(CompatRef dst, POINT offset); void updateAll(); void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha); - - void installHooks(); - void uninstallHooks(); } }