From dee081c083bfc40d859d5973c2c55fdf3978fe28 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 29 Nov 2020 16:23:17 +0100 Subject: [PATCH] Fixed black taskbar icons --- DDrawCompat/Gdi/DcFunctions.cpp | 130 ++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 6 deletions(-) diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index 0616e9e..4e6157b 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -54,6 +54,7 @@ namespace }; std::unordered_map g_funcNames; + thread_local bool g_redirectToDib = true; template HDC getDestinationDc(Params... params); @@ -175,7 +176,7 @@ namespace HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy) { LOG_FUNC("CreateCompatibleBitmap", hdc, cx, cy); - if (Gdi::isDisplayDc(hdc)) + if (g_redirectToDib && Gdi::isDisplayDc(hdc)) { return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(cx, cy)); } @@ -186,12 +187,13 @@ namespace const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage) { LOG_FUNC("CreateDIBitmap", hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage); - if (lpbmih && (!(fdwInit & CBM_INIT) || lpbInit && lpbmi)) + const DWORD CBM_CREATDIB = 2; + if (g_redirectToDib && !(fdwInit & CBM_CREATDIB) && lpbmih && Gdi::isDisplayDc(hdc)) { - HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(lpbmih->biWidth, lpbmih->biHeight); - if (bitmap && (fdwInit & CBM_INIT)) + HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight); + if (bitmap && lpbInit && lpbmi) { - SetDIBits(hdc, bitmap, 0, std::abs(lpbmih->biHeight), lpbInit, lpbmi, fuUsage); + SetDIBits(hdc, bitmap, 0, std::abs(lpbmi->bmiHeader.biHeight), lpbInit, lpbmi, fuUsage); } return LOG_RESULT(bitmap); } @@ -201,7 +203,7 @@ namespace HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight) { LOG_FUNC("CreateDiscardableBitmap", hdc, nWidth, nHeight); - if (Gdi::isDisplayDc(hdc)) + if (g_redirectToDib && Gdi::isDisplayDc(hdc)) { return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(nWidth, nHeight)); } @@ -334,6 +336,114 @@ namespace return 1; } + template + ATOM WINAPI registerClass(const WndClass* lpWndClass, ATOM(WINAPI* origRegisterClass)(const WndClass*), + ATOM(WINAPI* registerClassEx)(const WndClassEx*)) + { + if (!lpWndClass) + { + return origRegisterClass(lpWndClass); + } + + WndClassEx wc = {}; + wc.cbSize = sizeof(wc); + memcpy(&wc.style, &lpWndClass->style, sizeof(WndClass)); + return registerClassEx(&wc); + } + + template + ATOM registerClassEx(const WndClassEx* lpWndClassEx, + ATOM(WINAPI* origRegisterClassEx)(const WndClassEx*), + decltype(&SetClassLong) origSetClassLong, + decltype(&DefWindowProc) origDefWindowProc) + { + if (!lpWndClassEx || (!lpWndClassEx->hIcon && !lpWndClassEx->hIconSm)) + { + return origRegisterClassEx(lpWndClassEx); + } + + WndClassEx wc = *lpWndClassEx; + wc.lpfnWndProc = origDefWindowProc; + wc.hIcon = nullptr; + wc.hIconSm = nullptr; + + ATOM atom = origRegisterClassEx(&wc); + if (atom) + { + HWND hwnd = CreateWindow(reinterpret_cast(atom), "", 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + if (!hwnd) + { + UnregisterClass(reinterpret_cast(atom), GetModuleHandle(nullptr)); + return origRegisterClassEx(lpWndClassEx); + } + + if (lpWndClassEx->hIcon) + { + SetClassLong(hwnd, GCL_HICON, reinterpret_cast(lpWndClassEx->hIcon)); + } + if (lpWndClassEx->hIconSm) + { + SetClassLong(hwnd, GCL_HICONSM, reinterpret_cast(lpWndClassEx->hIconSm)); + } + + origSetClassLong(hwnd, GCL_WNDPROC, reinterpret_cast(lpWndClassEx->lpfnWndProc)); + SetWindowLong(hwnd, GWL_WNDPROC, reinterpret_cast(CALL_ORIG_FUNC(DefWindowProcA))); + DestroyWindow(hwnd); + } + + return atom; + } + + ATOM WINAPI registerClassA(const WNDCLASSA* lpWndClass) + { + LOG_FUNC("RegisterClassA", lpWndClass); + return LOG_RESULT(registerClass(lpWndClass, CALL_ORIG_FUNC(RegisterClassA), RegisterClassExA)); + } + + ATOM WINAPI registerClassW(const WNDCLASSW* lpWndClass) + { + LOG_FUNC("RegisterClassW", lpWndClass); + return LOG_RESULT(registerClass(lpWndClass, CALL_ORIG_FUNC(RegisterClassW), RegisterClassExW)); + } + + ATOM WINAPI registerClassExA(const WNDCLASSEXA* lpWndClassEx) + { + LOG_FUNC("RegisterClassExA", lpWndClassEx); + return LOG_RESULT(registerClassEx(lpWndClassEx, CALL_ORIG_FUNC(RegisterClassExA), CALL_ORIG_FUNC(SetClassLongA), + CALL_ORIG_FUNC(DefWindowProcA))); + } + + ATOM WINAPI registerClassExW(const WNDCLASSEXW* lpWndClassEx) + { + LOG_FUNC("RegisterClassExW", lpWndClassEx); + return LOG_RESULT(registerClassEx(lpWndClassEx, CALL_ORIG_FUNC(RegisterClassExW), CALL_ORIG_FUNC(SetClassLongW), + CALL_ORIG_FUNC(DefWindowProcW))); + } + + DWORD WINAPI setClassLong(HWND hWnd, int nIndex, LONG dwNewLong, decltype(&SetClassLong) origSetClassLong) + { + if (GCL_HICON == nIndex || GCL_HICONSM == nIndex) + { + g_redirectToDib = false; + DWORD result = origSetClassLong(hWnd, nIndex, dwNewLong); + g_redirectToDib = true; + return result; + } + return origSetClassLong(hWnd, nIndex, dwNewLong); + } + + DWORD WINAPI setClassLongA(HWND hWnd, int nIndex, LONG dwNewLong) + { + LOG_FUNC("setClassLongA", hWnd, nIndex, dwNewLong); + return LOG_RESULT(setClassLong(hWnd, nIndex, dwNewLong, CALL_ORIG_FUNC(SetClassLongA))); + } + + DWORD WINAPI setClassLongW(HWND hWnd, int nIndex, LONG dwNewLong) + { + LOG_FUNC("setClassLongW", hWnd, nIndex, dwNewLong); + return LOG_RESULT(setClassLong(hWnd, nIndex, dwNewLong, CALL_ORIG_FUNC(SetClassLongW))); + } + HWND WINAPI windowFromDc(HDC dc) { return CALL_ORIG_FUNC(WindowFromDC)(Gdi::Dc::getOrigDc(dc)); @@ -451,6 +561,14 @@ namespace Gdi // Undocumented functions HOOK_GDI_DC_FUNCTION(gdi32, GdiDrawStream); HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt); + + // Window class functions + HOOK_FUNCTION(user32, RegisterClassA, registerClassA); + HOOK_FUNCTION(user32, RegisterClassW, registerClassW); + HOOK_FUNCTION(user32, RegisterClassExA, registerClassExA); + HOOK_FUNCTION(user32, RegisterClassExW, registerClassExW); + HOOK_FUNCTION(user32, SetClassLongA, setClassLongA); + HOOK_FUNCTION(user32, SetClassLongW, setClassLongW); } } }