diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.cpp b/DDrawCompat/D3dDdi/DrawPrimitive.cpp index b7333ff..35c9f74 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.cpp +++ b/DDrawCompat/D3dDdi/DrawPrimitive.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index b976dce..0616e9e 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -220,7 +220,7 @@ namespace GetWindowThreadProcessId(hwnd, &windowPid); if (GetCurrentProcessId() != windowPid || !IsWindowVisible(hwnd) || - (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & (WS_EX_LAYERED | WS_EX_TRANSPARENT))) + (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE) & (WS_EX_LAYERED | WS_EX_TRANSPARENT))) { return TRUE; } @@ -323,7 +323,7 @@ namespace } HWND hwnd = WindowFromDC(hdc); - if (!hwnd || hwnd == GetDesktopWindow() || (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)) + if (!hwnd || hwnd == GetDesktopWindow() || (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)) { return 1; } diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp index b58eaae..cabbbd9 100644 --- a/DDrawCompat/Gdi/Gdi.cpp +++ b/DDrawCompat/Gdi/Gdi.cpp @@ -54,7 +54,7 @@ namespace Gdi bool isDisplayDc(HDC dc) { return dc && OBJ_DC == GetObjectType(dc) && DT_RASDISPLAY == CALL_ORIG_FUNC(GetDeviceCaps)(dc, TECHNOLOGY) && - !(GetWindowLongPtr(CALL_ORIG_FUNC(WindowFromDC)(dc), GWL_EXSTYLE) & WS_EX_LAYERED); + !(CALL_ORIG_FUNC(GetWindowLongA)(CALL_ORIG_FUNC(WindowFromDC)(dc), GWL_EXSTYLE) & WS_EX_LAYERED); } void redraw(HRGN rgn) diff --git a/DDrawCompat/Gdi/PaintHandlers.cpp b/DDrawCompat/Gdi/PaintHandlers.cpp index 73175a5..201cf67 100644 --- a/DDrawCompat/Gdi/PaintHandlers.cpp +++ b/DDrawCompat/Gdi/PaintHandlers.cpp @@ -1,18 +1,12 @@ #include -#include "Common/Hook.h" -#include "Common/Log.h" -#include "D3dDdi/ScopedCriticalSection.h" -#include "DDraw/RealPrimarySurface.h" -#include "Gdi/AccessGuard.h" -#include "Gdi/Dc.h" -#include "Gdi/Gdi.h" -#include "Gdi/PaintHandlers.h" -#include "Gdi/ScrollBar.h" -#include "Gdi/ScrollFunctions.h" -#include "Gdi/TitleBar.h" -#include "Gdi/VirtualScreen.h" -#include "Gdi/Window.h" +#include +#include +#include +#include +#include +#include +#include std::ostream& operator<<(std::ostream& os, const MENUITEMINFOW& val) { @@ -91,7 +85,7 @@ namespace isUnicode == g_currentUser32WndProc->isUnicode && !g_currentUser32WndProc->oldWndProc) { - decltype(&GetWindowLong) getWindowLong = isUnicode ? GetWindowLongW : GetWindowLongA; + decltype(&GetWindowLong) getWindowLong = isUnicode ? CALL_ORIG_FUNC(GetWindowLongW) : CALL_ORIG_FUNC(GetWindowLongA); auto wndProc = reinterpret_cast(getWindowLong(hwnd, GWL_WNDPROC)); HMODULE wndProcModule = nullptr; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @@ -403,7 +397,7 @@ namespace return onPaint(hwnd, origWndProc); case WM_SETCURSOR: - if (GetWindowLong(hwnd, GWL_STYLE) & (SBS_SIZEBOX | SBS_SIZEGRIP)) + if (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE) & (SBS_SIZEBOX | SBS_SIZEGRIP)) { SetCursor(LoadCursor(nullptr, IDC_SIZENWSE)); } @@ -492,29 +486,5 @@ namespace Gdi HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW); HOOK_FUNCTION(user32, SetMenuItemInfoW, setMenuItemInfoW); } - - void onCreateWindow(HWND hwnd) - { - if (!IsWindowUnicode(hwnd)) - { - return; - } - - const auto wndProc = reinterpret_cast(GetWindowLongW(hwnd, GWL_WNDPROC)); - User32WndProc* user32WndProc = nullptr; - if (getUser32WndProcW().oldWndProc == wndProc) - { - user32WndProc = &getUser32WndProcW(); - } - else if (getUser32WndProcW().oldWndProc == wndProc) - { - user32WndProc = &getUser32WndProcW(); - } - - if (user32WndProc) - { - SetWindowLongW(hwnd, GWL_WNDPROC, reinterpret_cast(user32WndProc->newWndProc)); - } - } } } diff --git a/DDrawCompat/Gdi/PaintHandlers.h b/DDrawCompat/Gdi/PaintHandlers.h index cb14bf1..f87ae1d 100644 --- a/DDrawCompat/Gdi/PaintHandlers.h +++ b/DDrawCompat/Gdi/PaintHandlers.h @@ -5,6 +5,5 @@ namespace Gdi namespace PaintHandlers { void installHooks(); - void onCreateWindow(HWND hwnd); } } diff --git a/DDrawCompat/Gdi/ScrollBar.cpp b/DDrawCompat/Gdi/ScrollBar.cpp index 72b88b9..6c7b510 100644 --- a/DDrawCompat/Gdi/ScrollBar.cpp +++ b/DDrawCompat/Gdi/ScrollBar.cpp @@ -22,7 +22,7 @@ namespace Gdi m_isLeftMouseButtonDown(false), m_cursorPos(), m_horizontalSbi(), m_verticalSbi() { - const LONG windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + const LONG windowStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE); m_horizontalSbi.isVisible = 0 != (windowStyle & WS_HSCROLL); m_verticalSbi.isVisible = 0 != (windowStyle & WS_VSCROLL); diff --git a/DDrawCompat/Gdi/TitleBar.cpp b/DDrawCompat/Gdi/TitleBar.cpp index 0ffa4f8..14d0cf3 100644 --- a/DDrawCompat/Gdi/TitleBar.cpp +++ b/DDrawCompat/Gdi/TitleBar.cpp @@ -23,7 +23,7 @@ namespace Gdi m_hwnd(hwnd), m_compatDc(compatDc), m_buttonWidth(0), m_buttonHeight(0), m_tbi(), m_windowRect(), m_hasIcon(false), m_hasTitleBar(false) { - m_hasTitleBar = 0 != (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CAPTION); + m_hasTitleBar = 0 != (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE) & WS_CAPTION); if (!m_hasTitleBar) { return; diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index 4783325..9f12a13 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -29,73 +28,119 @@ namespace ChildWindowInfo() : rect{} {} }; - std::multimap g_threadIdToHook; - Compat::CriticalSection g_threadIdToHookCs; + struct WindowProc + { + WNDPROC wndProcA; + WNDPROC wndProcW; + }; + HWINEVENTHOOK g_objectCreateEventHook = nullptr; HWINEVENTHOOK g_objectStateChangeEventHook = nullptr; std::set g_windowPosChangeNotifyFuncs; + Compat::CriticalSection g_windowProcCs; + std::map g_windowProc; + + WindowProc getWindowProc(HWND hwnd); void onActivate(HWND hwnd); void onCreateWindow(HWND hwnd); void onDestroyWindow(HWND hwnd); void onWindowPosChanged(HWND hwnd); void onWindowPosChanging(HWND hwnd, const WINDOWPOS& wp); + void setWindowProc(HWND hwnd, WNDPROC wndProcA, WNDPROC wndProcW); - LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam) + LRESULT CALLBACK ddcWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, + decltype(&CallWindowProcA) callWindowProc, WNDPROC wndProc) { - auto ret = reinterpret_cast(lParam); - LOG_FUNC("callWndRetProc", Compat::hex(nCode), Compat::hex(wParam), ret); + LOG_FUNC("ddcWindowProc", hwnd, Compat::logWm(uMsg), Compat::hex(wParam), Compat::hex(lParam)); + LRESULT result = callWindowProc(wndProc, hwnd, uMsg, wParam, lParam); - if (HC_ACTION == nCode && !Gdi::Window::isPresentationWindow(ret->hwnd)) + switch (uMsg) { - switch (ret->message) + case WM_ACTIVATE: + onActivate(hwnd); + break; + + case WM_COMMAND: + { + auto notifCode = HIWORD(wParam); + if (lParam && (EN_HSCROLL == notifCode || EN_VSCROLL == notifCode)) { - case WM_ACTIVATE: - onActivate(ret->hwnd); - break; - - case WM_COMMAND: - { - auto notifCode = HIWORD(ret->wParam); - if (ret->lParam && (EN_HSCROLL == notifCode || EN_VSCROLL == notifCode)) - { - Gdi::ScrollFunctions::updateScrolledWindow(reinterpret_cast(ret->lParam)); - } - break; - } - - case WM_DESTROY: - onDestroyWindow(ret->hwnd); - break; - - case WM_STYLECHANGED: - if (GWL_EXSTYLE == ret->wParam) - { - onWindowPosChanged(ret->hwnd); - } - break; - - case WM_WINDOWPOSCHANGED: - onWindowPosChanged(ret->hwnd); - break; - - case WM_WINDOWPOSCHANGING: - onWindowPosChanging(ret->hwnd, *reinterpret_cast(ret->lParam)); - break; + Gdi::ScrollFunctions::updateScrolledWindow(reinterpret_cast(lParam)); } + break; } - return LOG_RESULT(CallNextHookEx(nullptr, nCode, wParam, lParam)); + case WM_NCDESTROY: + onDestroyWindow(hwnd); + break; + + case WM_STYLECHANGED: + if (GWL_EXSTYLE == wParam) + { + onWindowPosChanged(hwnd); + } + break; + + case WM_WINDOWPOSCHANGED: + onWindowPosChanged(hwnd); + break; + + case WM_WINDOWPOSCHANGING: + onWindowPosChanging(hwnd, *reinterpret_cast(lParam)); + break; + } + + return LOG_RESULT(result); } - void hookThread(DWORD threadId) + LRESULT CALLBACK ddcWindowProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - Compat::ScopedCriticalSection lock(g_threadIdToHookCs); - if (g_threadIdToHook.end() == g_threadIdToHook.find(threadId)) + return ddcWindowProc(hwnd, uMsg, wParam, lParam, CallWindowProcA, getWindowProc(hwnd).wndProcA); + } + + LRESULT CALLBACK ddcWindowProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return ddcWindowProc(hwnd, uMsg, wParam, lParam, CallWindowProcW, getWindowProc(hwnd).wndProcW); + } + + LONG getWindowLong(HWND hWnd, int nIndex, + decltype(&GetWindowLongA) origGetWindowLong, WNDPROC(WindowProc::* wndProc)) + { + if (GWL_WNDPROC == nIndex) { - g_threadIdToHook.emplace(threadId, - SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId)); + Compat::ScopedCriticalSection lock(g_windowProcCs); + auto it = g_windowProc.find(hWnd); + if (it != g_windowProc.end()) + { + return reinterpret_cast(it->second.*wndProc); + } } + return origGetWindowLong(hWnd, nIndex); + } + + LONG WINAPI getWindowLongA(HWND hWnd, int nIndex) + { + LOG_FUNC("GetWindowLongA", hWnd, nIndex); + return LOG_RESULT(getWindowLong(hWnd, nIndex, CALL_ORIG_FUNC(GetWindowLongA), &WindowProc::wndProcA)); + } + + LONG WINAPI getWindowLongW(HWND hWnd, int nIndex) + { + LOG_FUNC("GetWindowLongW", hWnd, nIndex); + return LOG_RESULT(getWindowLong(hWnd, nIndex, CALL_ORIG_FUNC(GetWindowLongW), &WindowProc::wndProcW)); + } + + WindowProc getWindowProc(HWND hwnd) + { + Compat::ScopedCriticalSection lock(g_windowProcCs); + return g_windowProc[hwnd]; + } + + BOOL CALLBACK initChildWindow(HWND hwnd, LPARAM /*lParam*/) + { + onCreateWindow(hwnd); + return TRUE; } BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/) @@ -105,6 +150,7 @@ namespace if (GetCurrentProcessId() == windowPid) { onCreateWindow(hwnd); + EnumChildWindows(hwnd, &initChildWindow, 0); if (8 == Win32::DisplayMode::getBpp()) { PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast(GetDesktopWindow()), 0); @@ -196,8 +242,18 @@ namespace return; } - hookThread(GetWindowThreadProcessId(hwnd, nullptr)); - Gdi::PaintHandlers::onCreateWindow(hwnd); + if (!Gdi::Window::isPresentationWindow(hwnd)) + { + Compat::ScopedCriticalSection lock(g_windowProcCs); + if (g_windowProc.find(hwnd) == g_windowProc.end()) + { + auto wndProcA = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC)); + auto wndProcW = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongW)(hwnd, GWL_WNDPROC)); + g_windowProc[hwnd] = { wndProcA, wndProcW }; + setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW); + } + } + Gdi::Window::add(hwnd); } @@ -205,16 +261,24 @@ namespace { Gdi::Window::remove(hwnd); delete reinterpret_cast(RemoveProp(hwnd, PROP_DDRAWCOMPAT)); + + Compat::ScopedCriticalSection lock(g_windowProcCs); + auto it = g_windowProc.find(hwnd); + if (it != g_windowProc.end()) + { + setWindowProc(hwnd, it->second.wndProcA, it->second.wndProcW); + g_windowProc.erase(it); + } } void onWindowPosChanged(HWND hwnd) { if (Gdi::MENU_ATOM == GetClassLongPtr(hwnd, GCW_ATOM)) { - auto exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); + auto exStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE); if (exStyle & WS_EX_LAYERED) { - SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED); + CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED); return; } } @@ -271,6 +335,38 @@ namespace } } + LONG setWindowLong(HWND hWnd, int nIndex, LONG dwNewLong, + decltype(&SetWindowLongA) origSetWindowLong, WNDPROC(WindowProc::* wndProc)) + { + if (GWL_WNDPROC == nIndex) + { + Compat::ScopedCriticalSection lock(g_windowProcCs); + auto it = g_windowProc.find(hWnd); + if (it != g_windowProc.end() && 0 != origSetWindowLong(hWnd, nIndex, dwNewLong)) + { + WNDPROC oldWndProc = it->second.*wndProc; + it->second.wndProcA = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongA)(hWnd, GWL_WNDPROC)); + it->second.wndProcW = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongW)(hWnd, GWL_WNDPROC)); + WindowProc newWindowProc = { ddcWindowProcA, ddcWindowProcW }; + origSetWindowLong(hWnd, GWL_WNDPROC, reinterpret_cast(newWindowProc.*wndProc)); + return reinterpret_cast(oldWndProc); + } + } + return origSetWindowLong(hWnd, nIndex, dwNewLong); + } + + LONG WINAPI setWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong) + { + LOG_FUNC("SetWindowLongA", hWnd, nIndex, dwNewLong); + return LOG_RESULT(setWindowLong(hWnd, nIndex, dwNewLong, CALL_ORIG_FUNC(SetWindowLongA), &WindowProc::wndProcA)); + } + + LONG WINAPI setWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong) + { + LOG_FUNC("SetWindowLongW", hWnd, nIndex, dwNewLong); + return LOG_RESULT(setWindowLong(hWnd, nIndex, dwNewLong, CALL_ORIG_FUNC(SetWindowLongW), &WindowProc::wndProcW)); + } + BOOL WINAPI setWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) { LOG_FUNC("SetWindowPos", hWnd, hWndInsertAfter, X, Y, cx, cy, Compat::hex(uFlags)); @@ -290,6 +386,18 @@ namespace delete reinterpret_cast(RemoveProp(hWnd, PROP_DDRAWCOMPAT)); return LOG_RESULT(result); } + + void setWindowProc(HWND hwnd, WNDPROC wndProcA, WNDPROC wndProcW) + { + if (IsWindowUnicode(hwnd)) + { + CALL_ORIG_FUNC(SetWindowLongW)(hwnd, GWL_WNDPROC, reinterpret_cast(wndProcW)); + } + else + { + CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC, reinterpret_cast(wndProcA)); + } + } } namespace Gdi @@ -298,20 +406,28 @@ namespace Gdi { void dllThreadDetach() { - Compat::ScopedCriticalSection lock(g_threadIdToHookCs); - const DWORD threadId = GetCurrentThreadId(); - for (auto threadIdToHook : g_threadIdToHook) + auto threadId = GetCurrentThreadId(); + Compat::ScopedCriticalSection lock(g_windowProcCs); + auto it = g_windowProc.begin(); + while (it != g_windowProc.end()) { - if (threadId == threadIdToHook.first) + if (threadId == GetWindowThreadProcessId(it->first, nullptr)) { - UnhookWindowsHookEx(threadIdToHook.second); + it = g_windowProc.erase(it); + } + else + { + ++it; } } - g_threadIdToHook.erase(threadId); } void installHooks() { + HOOK_FUNCTION(user32, GetWindowLongA, getWindowLongA); + HOOK_FUNCTION(user32, GetWindowLongW, getWindowLongW); + HOOK_FUNCTION(user32, SetWindowLongA, setWindowLongA); + HOOK_FUNCTION(user32, SetWindowLongW, setWindowLongW); HOOK_FUNCTION(user32, SetWindowPos, setWindowPos); g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, @@ -333,14 +449,12 @@ namespace Gdi UnhookWinEvent(g_objectStateChangeEventHook); UnhookWinEvent(g_objectCreateEventHook); + Compat::ScopedCriticalSection lock(g_windowProcCs); + for (const auto& windowProc : g_windowProc) { - Compat::ScopedCriticalSection lock(g_threadIdToHookCs); - for (auto threadIdToHook : g_threadIdToHook) - { - UnhookWindowsHookEx(threadIdToHook.second); - } - g_threadIdToHook.clear(); + setWindowProc(windowProc.first, windowProc.second.wndProcA, windowProc.second.wndProcW); } + g_windowProc.clear(); } } } diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index 3c57313..7a25d04 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -212,7 +212,7 @@ namespace Gdi , m_windowRect{ 0, 0, 0, 0 } , m_colorKey(CLR_INVALID) , m_alpha(255) - , m_isLayered(GetWindowLong(m_hwnd, GWL_EXSTYLE)& WS_EX_LAYERED) + , m_isLayered(CALL_ORIG_FUNC(GetWindowLongA)(m_hwnd, GWL_EXSTYLE)& WS_EX_LAYERED) { DWMNCRENDERINGPOLICY ncRenderingPolicy = DWMNCRP_DISABLED; DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncRenderingPolicy, sizeof(ncRenderingPolicy)); @@ -410,7 +410,7 @@ namespace Gdi void Window::update() { D3dDdi::ScopedCriticalSection lock; - const bool isLayered = GetWindowLong(m_hwnd, GWL_EXSTYLE) & WS_EX_LAYERED; + const bool isLayered = CALL_ORIG_FUNC(GetWindowLongA)(m_hwnd, GWL_EXSTYLE) & WS_EX_LAYERED; if (isLayered != m_isLayered) { if (!isLayered) diff --git a/DDrawCompat/Win32/Log.cpp b/DDrawCompat/Win32/Log.cpp index d59b68d..46139e1 100644 --- a/DDrawCompat/Win32/Log.cpp +++ b/DDrawCompat/Win32/Log.cpp @@ -106,8 +106,8 @@ std::ostream& operator<<(std::ostream& os, HWND hwnd) << name << Compat::hex(GetClassLong(hwnd, GCL_STYLE)) << rect - << Compat::hex(GetWindowLong(hwnd, GWL_STYLE)) - << Compat::hex(GetWindowLong(hwnd, GWL_EXSTYLE)); + << Compat::hex(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE)) + << Compat::hex(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE)); } std::ostream& operator<<(std::ostream& os, const MEMORYSTATUS& ms)