mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Disable DIB redirection for icon and cursor creating functions
Fixes corrupt icon in volume mixer.
This commit is contained in:
parent
8b8a4e544f
commit
b83f7ca879
@ -220,6 +220,7 @@
|
||||
<ClInclude Include="Gdi\Dc.h" />
|
||||
<ClInclude Include="Gdi\DcCache.h" />
|
||||
<ClInclude Include="Gdi\DcFunctions.h" />
|
||||
<ClInclude Include="Gdi\Icon.h" />
|
||||
<ClInclude Include="Gdi\Metrics.h" />
|
||||
<ClInclude Include="Gdi\PresentationWindow.h" />
|
||||
<ClInclude Include="Gdi\User32WndProcs.h" />
|
||||
@ -294,6 +295,7 @@
|
||||
<ClCompile Include="Gdi\Dc.cpp" />
|
||||
<ClCompile Include="Gdi\DcCache.cpp" />
|
||||
<ClCompile Include="Gdi\DcFunctions.cpp" />
|
||||
<ClCompile Include="Gdi\Icon.cpp" />
|
||||
<ClCompile Include="Gdi\Metrics.cpp" />
|
||||
<ClCompile Include="Gdi\PresentationWindow.cpp" />
|
||||
<ClCompile Include="Gdi\User32WndProcs.cpp" />
|
||||
|
@ -402,6 +402,9 @@
|
||||
<ClInclude Include="Gdi\CompatDc.h">
|
||||
<Filter>Header Files\Gdi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Gdi\Icon.h">
|
||||
<Filter>Header Files\Gdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -620,5 +623,8 @@
|
||||
<ClCompile Include="Gdi\CompatDc.cpp">
|
||||
<Filter>Source Files\Gdi</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Gdi\Icon.cpp">
|
||||
<Filter>Source Files\Gdi</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -9,13 +9,12 @@
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/Region.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<void*, const char*> g_funcNames;
|
||||
thread_local bool g_redirectToDib = true;
|
||||
thread_local UINT g_disableDibRedirection = 0;
|
||||
|
||||
#define CREATE_DC_FUNC_ATTRIBUTE(attribute) \
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc> \
|
||||
@ -175,7 +174,7 @@ namespace
|
||||
HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy)
|
||||
{
|
||||
LOG_FUNC("CreateCompatibleBitmap", hdc, cx, cy);
|
||||
if (g_redirectToDib && Gdi::isDisplayDc(hdc))
|
||||
if (!g_disableDibRedirection && Gdi::isDisplayDc(hdc))
|
||||
{
|
||||
const bool useDefaultPalette = false;
|
||||
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(cx, cy, useDefaultPalette));
|
||||
@ -188,7 +187,7 @@ namespace
|
||||
{
|
||||
LOG_FUNC("CreateDIBitmap", hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
|
||||
const DWORD CBM_CREATDIB = 2;
|
||||
if (g_redirectToDib && !(fdwInit & CBM_CREATDIB) && lpbmih && Gdi::isDisplayDc(hdc))
|
||||
if (!g_disableDibRedirection && !(fdwInit & CBM_CREATDIB) && lpbmih && Gdi::isDisplayDc(hdc))
|
||||
{
|
||||
const bool useDefaultPalette = false;
|
||||
HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(
|
||||
@ -205,7 +204,7 @@ namespace
|
||||
HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight)
|
||||
{
|
||||
LOG_FUNC("CreateDiscardableBitmap", hdc, nWidth, nHeight);
|
||||
if (g_redirectToDib && Gdi::isDisplayDc(hdc))
|
||||
if (!g_disableDibRedirection && Gdi::isDisplayDc(hdc))
|
||||
{
|
||||
const bool useDefaultPalette = false;
|
||||
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(nWidth, nHeight, useDefaultPalette));
|
||||
@ -257,114 +256,6 @@ namespace
|
||||
moduleName, funcName, getCompatGdiTextDcFuncPtr<OrigFuncPtr, origFunc>(origFunc));
|
||||
}
|
||||
|
||||
template <typename WndClass, typename WndClassEx>
|
||||
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 <typename WndClassEx>
|
||||
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<LPCSTR>(atom), "", 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
|
||||
if (!hwnd)
|
||||
{
|
||||
UnregisterClass(reinterpret_cast<LPCSTR>(atom), GetModuleHandle(nullptr));
|
||||
return origRegisterClassEx(lpWndClassEx);
|
||||
}
|
||||
|
||||
if (lpWndClassEx->hIcon)
|
||||
{
|
||||
SetClassLong(hwnd, GCL_HICON, reinterpret_cast<LONG>(lpWndClassEx->hIcon));
|
||||
}
|
||||
if (lpWndClassEx->hIconSm)
|
||||
{
|
||||
SetClassLong(hwnd, GCL_HICONSM, reinterpret_cast<LONG>(lpWndClassEx->hIconSm));
|
||||
}
|
||||
|
||||
origSetClassLong(hwnd, GCL_WNDPROC, reinterpret_cast<LONG>(lpWndClassEx->lpfnWndProc));
|
||||
SetWindowLong(hwnd, GWL_WNDPROC, reinterpret_cast<LONG>(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));
|
||||
@ -382,6 +273,11 @@ namespace Gdi
|
||||
{
|
||||
namespace DcFunctions
|
||||
{
|
||||
void disableDibRedirection(bool disable)
|
||||
{
|
||||
g_disableDibRedirection += disable ? 1 : -1;
|
||||
}
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
// Bitmap functions
|
||||
@ -469,14 +365,6 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace Gdi
|
||||
{
|
||||
namespace DcFunctions
|
||||
{
|
||||
void disableDibRedirection(bool disable);
|
||||
|
||||
void installHooks();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <Gdi/DcFunctions.h>
|
||||
#include <Gdi/Font.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/Icon.h>
|
||||
#include <Gdi/Metrics.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
@ -40,6 +41,7 @@ namespace Gdi
|
||||
DisableProcessWindowsGhosting();
|
||||
|
||||
DcFunctions::installHooks();
|
||||
Icon::installHooks();
|
||||
Metrics::installHooks();
|
||||
Palette::installHooks();
|
||||
PresentationWindow::installHooks();
|
||||
|
165
DDrawCompat/Gdi/Icon.cpp
Normal file
165
DDrawCompat/Gdi/Icon.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include <map>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Gdi/DcFunctions.h>
|
||||
#include <Gdi/Icon.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<void*, const char*> g_funcNames;
|
||||
|
||||
template <typename Result, typename... Params>
|
||||
using FuncPtr = Result(WINAPI*)(Params...);
|
||||
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
|
||||
struct EnableDibRedirection
|
||||
{
|
||||
bool operator()(Params...) { return false; }
|
||||
};
|
||||
|
||||
template <typename... Params>
|
||||
struct EnableDibRedirection<decltype(&CopyImage), &CopyImage, Params...>
|
||||
{
|
||||
bool operator()(HANDLE, UINT type, int, int, UINT)
|
||||
{
|
||||
return IMAGE_CURSOR != type && IMAGE_ICON != type;
|
||||
}
|
||||
};
|
||||
|
||||
struct EnableDibRedirectionLoadImage
|
||||
{
|
||||
template <typename String>
|
||||
bool operator()(HINSTANCE, String, UINT type, int, int, UINT)
|
||||
{
|
||||
return IMAGE_CURSOR != type && IMAGE_ICON != type;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Params>
|
||||
struct EnableDibRedirection<decltype(&LoadImageA), &LoadImageA, Params...> : EnableDibRedirectionLoadImage {};
|
||||
template <typename... Params>
|
||||
struct EnableDibRedirection<decltype(&LoadImageW), &LoadImageW, Params...> : EnableDibRedirectionLoadImage {};
|
||||
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||
Result WINAPI iconFunc(Params... params)
|
||||
{
|
||||
LOG_FUNC(g_funcNames[origFunc], params...);
|
||||
|
||||
if (EnableDibRedirection<OrigFuncPtr, origFunc, Params...>()(params...))
|
||||
{
|
||||
return LOG_RESULT(Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...));
|
||||
}
|
||||
|
||||
Gdi::DcFunctions::disableDibRedirection(true);
|
||||
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...);
|
||||
Gdi::DcFunctions::disableDibRedirection(false);
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||
OrigFuncPtr getIconFuncPtr(FuncPtr<Result, Params...>)
|
||||
{
|
||||
return &iconFunc<OrigFuncPtr, origFunc, Result, Params...>;
|
||||
}
|
||||
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
|
||||
void hookIconFunc(const char* moduleName, const char* funcName)
|
||||
{
|
||||
#ifdef DEBUGLOGS
|
||||
g_funcNames[origFunc] = funcName;
|
||||
#endif
|
||||
|
||||
Compat::hookFunction<OrigFuncPtr, origFunc>(
|
||||
moduleName, funcName, getIconFuncPtr<OrigFuncPtr, origFunc>(origFunc));
|
||||
}
|
||||
|
||||
template <typename WndClass, typename WndClassEx>
|
||||
ATOM registerClass(const WndClass* lpWndClass, ATOM(WINAPI* origRegisterClassEx)(const WndClassEx*))
|
||||
{
|
||||
if (!lpWndClass)
|
||||
{
|
||||
return origRegisterClassEx(nullptr);
|
||||
}
|
||||
|
||||
WndClassEx wc = {};
|
||||
wc.cbSize = sizeof(wc);
|
||||
memcpy(&wc.style, lpWndClass, sizeof(*lpWndClass));
|
||||
wc.hIconSm = wc.hIcon;
|
||||
return origRegisterClassEx(&wc);
|
||||
}
|
||||
|
||||
template <typename WndClassEx>
|
||||
ATOM registerClassEx(const WndClassEx* lpwcx, ATOM(WINAPI* origRegisterClassEx)(const WndClassEx*))
|
||||
{
|
||||
if (!lpwcx)
|
||||
{
|
||||
return origRegisterClassEx(nullptr);
|
||||
}
|
||||
|
||||
WndClassEx wc = *lpwcx;
|
||||
if (!wc.hIconSm)
|
||||
{
|
||||
wc.hIconSm = wc.hIcon;
|
||||
}
|
||||
return origRegisterClassEx(&wc);
|
||||
}
|
||||
|
||||
ATOM WINAPI registerClassA(const WNDCLASSA* lpWndClass)
|
||||
{
|
||||
LOG_FUNC("RegisterClassA", lpWndClass);
|
||||
return LOG_RESULT(registerClass(lpWndClass, CALL_ORIG_FUNC(RegisterClassExA)));
|
||||
}
|
||||
|
||||
ATOM WINAPI registerClassW(const WNDCLASSW* lpWndClass)
|
||||
{
|
||||
LOG_FUNC("RegisterClassW", lpWndClass);
|
||||
return LOG_RESULT(registerClass(lpWndClass, CALL_ORIG_FUNC(RegisterClassExW)));
|
||||
}
|
||||
|
||||
ATOM WINAPI registerClassExA(const WNDCLASSEXA* lpwcx)
|
||||
{
|
||||
LOG_FUNC("RegisterClassExA", lpwcx);
|
||||
return LOG_RESULT(registerClassEx(lpwcx, CALL_ORIG_FUNC(RegisterClassExA)));
|
||||
}
|
||||
|
||||
ATOM WINAPI registerClassExW(const WNDCLASSEXW* lpwcx)
|
||||
{
|
||||
LOG_FUNC("RegisterClassExW", lpwcx);
|
||||
return LOG_RESULT(registerClassEx(lpwcx, CALL_ORIG_FUNC(RegisterClassExW)));
|
||||
}
|
||||
}
|
||||
|
||||
#define HOOK_ICON_FUNCTION(module, func) hookIconFunc<decltype(&func), &func>(#module, #func)
|
||||
|
||||
namespace Gdi
|
||||
{
|
||||
namespace Icon
|
||||
{
|
||||
void installHooks()
|
||||
{
|
||||
HOOK_ICON_FUNCTION(user32, CopyIcon);
|
||||
HOOK_ICON_FUNCTION(user32, CopyImage);
|
||||
HOOK_ICON_FUNCTION(user32, CreateCursor);
|
||||
HOOK_ICON_FUNCTION(user32, CreateIcon);
|
||||
HOOK_ICON_FUNCTION(user32, CreateIconFromResource);
|
||||
HOOK_ICON_FUNCTION(user32, CreateIconFromResourceEx);
|
||||
HOOK_ICON_FUNCTION(user32, CreateIconIndirect);
|
||||
HOOK_ICON_FUNCTION(user32, LoadCursorA);
|
||||
HOOK_ICON_FUNCTION(user32, LoadCursorW);
|
||||
HOOK_ICON_FUNCTION(user32, LoadCursorFromFileA);
|
||||
HOOK_ICON_FUNCTION(user32, LoadCursorFromFileW);
|
||||
HOOK_ICON_FUNCTION(user32, LoadIconA);
|
||||
HOOK_ICON_FUNCTION(user32, LoadIconW);
|
||||
HOOK_ICON_FUNCTION(user32, LoadImageA);
|
||||
HOOK_ICON_FUNCTION(user32, LoadImageW);
|
||||
HOOK_ICON_FUNCTION(user32, PrivateExtractIconsA);
|
||||
HOOK_ICON_FUNCTION(user32, PrivateExtractIconsW);
|
||||
|
||||
HOOK_FUNCTION(user32, RegisterClassA, registerClassA);
|
||||
HOOK_FUNCTION(user32, RegisterClassW, registerClassW);
|
||||
HOOK_FUNCTION(user32, RegisterClassExA, registerClassExA);
|
||||
HOOK_FUNCTION(user32, RegisterClassExW, registerClassExW);
|
||||
}
|
||||
}
|
||||
}
|
9
DDrawCompat/Gdi/Icon.h
Normal file
9
DDrawCompat/Gdi/Icon.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace Gdi
|
||||
{
|
||||
namespace Icon
|
||||
{
|
||||
void installHooks();
|
||||
}
|
||||
}
|
@ -88,7 +88,7 @@ namespace
|
||||
wc.lpfnWndProc = &messageWindowProc;
|
||||
wc.hInstance = Dll::g_currentModule;
|
||||
wc.lpszClassName = "DDrawCompatMessageWindow";
|
||||
RegisterClass(&wc);
|
||||
CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||
|
||||
g_messageWindow = CreateWindow(
|
||||
"DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
|
||||
@ -136,7 +136,7 @@ namespace Gdi
|
||||
wc.lpfnWndProc = &presentationWindowProc;
|
||||
wc.hInstance = Dll::g_currentModule;
|
||||
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
||||
RegisterClass(&wc);
|
||||
CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||
|
||||
g_presentationWindowThread = CreateThread(
|
||||
nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user