From cdfcafafa16f76499f366e1ef50b03056cbbc0f1 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 29 Sep 2021 14:08:05 +0200 Subject: [PATCH] gdi32: Introduce user_callbacks. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/Makefile.in | 3 +- dlls/gdi32/driver.c | 74 ++++++++----------- dlls/gdi32/freetype.c | 18 +++++ dlls/gdi32/gdiobj.c | 9 +-- dlls/gdi32/ntgdi_private.h | 3 +- dlls/gdi32/palette.c | 25 ++----- dlls/gdi32/region.c | 11 +-- dlls/gdi32/win32u_private.h | 41 +++++++++++ dlls/gdi32/wrappers.c | 141 ++++++++++++++++++++++++++++++++++++ 9 files changed, 245 insertions(+), 80 deletions(-) create mode 100644 dlls/gdi32/win32u_private.h create mode 100644 dlls/gdi32/wrappers.c diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in index 074dc8b6dde..a1b153edf07 100644 --- a/dlls/gdi32/Makefile.in +++ b/dlls/gdi32/Makefile.in @@ -54,7 +54,8 @@ C_SRCS = \ uniscribe/shaping.c \ uniscribe/usp10.c \ vertical.c \ - vulkan.c + vulkan.c \ + wrappers.c RC_SRCS = gdi32.rc diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index b277dc17452..201341d7701 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -65,14 +65,6 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -static BOOL (WINAPI *pEnumDisplayMonitors)(HDC, LPRECT, MONITORENUMPROC, LPARAM); -static BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW); -static HWND (WINAPI *pGetDesktopWindow)(void); -static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR, LPMONITORINFO); -static INT (WINAPI *pGetSystemMetrics)(INT); -static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); - - /********************************************************************** * get_display_driver * @@ -82,10 +74,7 @@ const struct gdi_dc_funcs *get_display_driver(void) { if (!driver_funcs) { - HMODULE user32 = LoadLibraryA( "user32.dll" ); - pGetDesktopWindow = (void *)GetProcAddress( user32, "GetDesktopWindow" ); - - if (!pGetDesktopWindow() || !driver_funcs) + if (!user_callbacks || !user_callbacks->pGetDesktopWindow() || !driver_funcs) { static struct gdi_dc_funcs empty_funcs; WARN( "failed to load the display driver, falling back to null driver\n" ); @@ -95,7 +84,6 @@ const struct gdi_dc_funcs *get_display_driver(void) return driver_funcs; } - /*********************************************************************** * __wine_set_display_driver (win32u.@) */ @@ -103,7 +91,6 @@ void CDECL __wine_set_display_driver( HMODULE module ) { const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int ); const struct gdi_dc_funcs *funcs = NULL; - HMODULE user32; wine_get_gdi_driver = (void *)GetProcAddress( module, "wine_get_gdi_driver" ); if (wine_get_gdi_driver) funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION ); @@ -113,13 +100,6 @@ void CDECL __wine_set_display_driver( HMODULE module ) NtTerminateProcess( GetCurrentThread(), 1 ); } InterlockedExchangePointer( (void **)&driver_funcs, (void *)funcs ); - - user32 = LoadLibraryA( "user32.dll" ); - pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" ); - pGetSystemMetrics = (void *)GetProcAddress( user32, "GetSystemMetrics" ); - pEnumDisplayMonitors = (void *)GetProcAddress( user32, "EnumDisplayMonitors" ); - pEnumDisplaySettingsW = (void *)GetProcAddress( user32, "EnumDisplaySettingsW" ); - pSetThreadDpiAwarenessContext = (void *)GetProcAddress( user32, "SetThreadDpiAwarenessContext" ); } struct monitor_info @@ -134,8 +114,8 @@ static BOOL CALLBACK monitor_enum_proc( HMONITOR monitor, HDC hdc, LPRECT rect, MONITORINFOEXW mi; mi.cbSize = sizeof(mi); - pGetMonitorInfoW( monitor, (MONITORINFO *)&mi ); - if (!lstrcmpiW( info->name, mi.szDevice )) + user_callbacks->pGetMonitorInfoW( monitor, (MONITORINFO *)&mi ); + if (!wcsicmp( info->name, mi.szDevice )) { info->rect = mi.rcMonitor; return FALSE; @@ -264,33 +244,41 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap ) { DC *dc = get_nulldrv_dc( dev ); struct monitor_info info; + int ret; - if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW) + if (!user_callbacks) return 640; + + if (dc->display[0]) { info.name = dc->display; SetRectEmpty( &info.rect ); - pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); + user_callbacks->pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); if (!IsRectEmpty( &info.rect )) return info.rect.right - info.rect.left; } - return pGetSystemMetrics ? pGetSystemMetrics( SM_CXSCREEN ) : 640; + ret = user_callbacks->pGetSystemMetrics( SM_CXSCREEN ); + return ret ? ret : 640; } case VERTRES: { DC *dc = get_nulldrv_dc( dev ); struct monitor_info info; + int ret; - if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW) + if (!user_callbacks) return 480; + + if (dc->display[0] && user_callbacks) { info.name = dc->display; SetRectEmpty( &info.rect ); - pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); + user_callbacks->pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); if (!IsRectEmpty( &info.rect )) return info.rect.bottom - info.rect.top; } - return pGetSystemMetrics ? pGetSystemMetrics( SM_CYSCREEN ) : 480; + ret = user_callbacks->pGetSystemMetrics( SM_CYSCREEN ); + return ret ? ret : 480; } case BITSPIXEL: { @@ -298,13 +286,13 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap ) WCHAR *display; DC *dc; - if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pEnumDisplaySettingsW) + if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks) { dc = get_nulldrv_dc( dev ); display = dc->display[0] ? dc->display : NULL; memset( &devmode, 0, sizeof(devmode) ); devmode.dmSize = sizeof(devmode); - if (pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode ) + if (user_callbacks->pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode ) && devmode.dmFields & DM_BITSPERPEL && devmode.dmBitsPerPel) return devmode.dmBitsPerPel; } @@ -351,39 +339,39 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap ) if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) != DT_RASDISPLAY) return 0; - if (pEnumDisplaySettingsW) + if (user_callbacks) { dc = get_nulldrv_dc( dev ); memset( &devmode, 0, sizeof(devmode) ); devmode.dmSize = sizeof(devmode); display = dc->display[0] ? dc->display : NULL; - if (pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode )) + if (user_callbacks->pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode )) return devmode.dmDisplayFrequency ? devmode.dmDisplayFrequency : 1; } return 1; } case DESKTOPHORZRES: - if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pGetSystemMetrics) + if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks) { DPI_AWARENESS_CONTEXT context; UINT ret; - context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); - ret = pGetSystemMetrics( SM_CXVIRTUALSCREEN ); - pSetThreadDpiAwarenessContext( context ); - return ret; + context = user_callbacks->pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); + ret = user_callbacks->pGetSystemMetrics( SM_CXVIRTUALSCREEN ); + user_callbacks->pSetThreadDpiAwarenessContext( context ); + if (ret) return ret; } return NtGdiGetDeviceCaps( dev->hdc, HORZRES ); case DESKTOPVERTRES: - if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pGetSystemMetrics) + if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks) { DPI_AWARENESS_CONTEXT context; UINT ret; - context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); - ret = pGetSystemMetrics( SM_CYVIRTUALSCREEN ); - pSetThreadDpiAwarenessContext( context ); - return ret; + context = user_callbacks->pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); + ret = user_callbacks->pGetSystemMetrics( SM_CYVIRTUALSCREEN ); + user_callbacks->pSetThreadDpiAwarenessContext( context ); + if (ret) return ret; } return NtGdiGetDeviceCaps( dev->hdc, VERTRES ); case BLTALIGNMENT: return 0; diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 2ce1ad58bb8..fc84a481fd3 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -45,21 +45,30 @@ #ifdef HAVE_CARBON_CARBON_H #define LoadResource __carbon_LoadResource +#define CheckMenuItem __carbon_CheckMenuItem #define CompareString __carbon_CompareString #define GetCurrentThread __carbon_GetCurrentThread #define GetCurrentProcess __carbon_GetCurrentProcess #define AnimatePalette __carbon_AnimatePalette +#define DeleteMenu __carbon_DeleteMenu +#define DrawMenu __carbon_DrawMenu +#define DrawMenuBar __carbon_DrawMenuBar +#define EnableMenuItem __carbon_EnableMenuItem #define EqualRgn __carbon_EqualRgn #define FillRgn __carbon_FillRgn #define FrameRgn __carbon_FrameRgn +#define GetMenu __carbon_GetMenu #define GetPixel __carbon_GetPixel #define InvertRgn __carbon_InvertRgn +#define IsWindowVisible __carbon_IsWindowVisible #define LineTo __carbon_LineTo +#define MoveWindow __carbon_MoveWindow #define OffsetRgn __carbon_OffsetRgn #define PaintRgn __carbon_PaintRgn #define Polygon __carbon_Polygon #define ResizePalette __carbon_ResizePalette #define SetRectRgn __carbon_SetRectRgn +#define ShowWindow __carbon_ShowWindow #include #undef LoadResource #undef CompareString @@ -67,17 +76,26 @@ #undef _CDECL #undef GetCurrentProcess #undef AnimatePalette +#undef CheckMenuItem +#undef DeleteMenu +#undef DrawMenu +#undef DrawMenuBar +#undef EnableMenuItem #undef EqualRgn #undef FillRgn #undef FrameRgn +#undef GetMenu #undef GetPixel #undef InvertRgn +#undef IsWindowVisible #undef LineTo +#undef MoveWindow #undef OffsetRgn #undef PaintRgn #undef Polygon #undef ResizePalette #undef SetRectRgn +#undef ShowWindow #endif /* HAVE_CARBON_CARBON_H */ #ifdef HAVE_FT2BUILD_H diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index c0912c3ad2d..84514bd9d91 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -579,14 +579,7 @@ BOOL GDI_dec_ref_count( HGDIOBJ handle ) */ DWORD get_system_dpi(void) { - static UINT (WINAPI *pGetDpiForSystem)(void); - - if (!pGetDpiForSystem) - { - HMODULE user = GetModuleHandleW( L"user32.dll" ); - if (user) pGetDpiForSystem = (void *)GetProcAddress( user, "GetDpiForSystem" ); - } - return pGetDpiForSystem ? pGetDpiForSystem() : 96; + return user_callbacks ? user_callbacks->pGetDpiForSystem() : 96; } static HFONT create_font( const LOGFONTW *deffont ) diff --git a/dlls/gdi32/ntgdi_private.h b/dlls/gdi32/ntgdi_private.h index a39fe05bc01..6bcc1a710e3 100644 --- a/dlls/gdi32/ntgdi_private.h +++ b/dlls/gdi32/ntgdi_private.h @@ -28,7 +28,7 @@ #include "windef.h" #include "winbase.h" #include "ntgdi.h" -#include "wine/gdi_driver.h" +#include "win32u_private.h" /* extra stock object: default 1x1 bitmap for memory DCs */ #define DEFAULT_BITMAP (STOCK_LAST+1) @@ -649,5 +649,6 @@ void set_gdi_client_ptr( HGDIOBJ handle, void *ptr ) DECLSPEC_HIDDEN; extern HMODULE gdi32_module DECLSPEC_HIDDEN; extern SYSTEM_BASIC_INFORMATION system_info DECLSPEC_HIDDEN; +extern const struct user_callbacks *user_callbacks DECLSPEC_HIDDEN; #endif /* __WINE_NTGDI_PRIVATE_H */ diff --git a/dlls/gdi32/palette.c b/dlls/gdi32/palette.c index 2f3fc7dd215..61c31a8e11b 100644 --- a/dlls/gdi32/palette.c +++ b/dlls/gdi32/palette.c @@ -580,29 +580,18 @@ typedef BOOL (WINAPI *RedrawWindow_funcptr)( HWND, const RECT *, HRGN, UINT ); */ BOOL WINAPI NtGdiUpdateColors( HDC hDC ) { - HMODULE mod; int size = NtGdiGetDeviceCaps( hDC, SIZEPALETTE ); + HWND hwnd; if (!size) return FALSE; + if (!user_callbacks) return TRUE; - mod = GetModuleHandleA("user32.dll"); - if (mod) - { - WindowFromDC_funcptr pWindowFromDC = (WindowFromDC_funcptr)GetProcAddress(mod,"WindowFromDC"); - if (pWindowFromDC) - { - HWND hWnd = pWindowFromDC( hDC ); + hwnd = user_callbacks->pWindowFromDC( hDC ); - /* Docs say that we have to remap current drawable pixel by pixel - * but it would take forever given the speed of XGet/PutPixel. - */ - if (hWnd && size) - { - RedrawWindow_funcptr pRedrawWindow = (void *)GetProcAddress( mod, "RedrawWindow" ); - if (pRedrawWindow) pRedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE ); - } - } - } + /* Docs say that we have to remap current drawable pixel by pixel + * but it would take forever given the speed of XGet/PutPixel. + */ + if (hwnd && size) user_callbacks->pRedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE ); return TRUE; } diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c index 44ac1744793..0c4e4745e91 100644 --- a/dlls/gdi32/region.c +++ b/dlls/gdi32/region.c @@ -1375,17 +1375,10 @@ INT mirror_region( HRGN dst, HRGN src, INT width ) */ BOOL WINAPI MirrorRgn( HWND hwnd, HRGN hrgn ) { - static BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect ); RECT rect; - /* yes, a HWND in gdi32, don't ask */ - if (!pGetWindowRect) - { - HMODULE user32 = GetModuleHandleW(L"user32.dll"); - if (!user32) return FALSE; - if (!(pGetWindowRect = (void *)GetProcAddress( user32, "GetWindowRect" ))) return FALSE; - } - pGetWindowRect( hwnd, &rect ); + if (!user_callbacks) return FALSE; + user_callbacks->pGetWindowRect( hwnd, &rect ); return mirror_region( hrgn, hrgn, rect.right - rect.left ) != ERROR; } diff --git a/dlls/gdi32/win32u_private.h b/dlls/gdi32/win32u_private.h new file mode 100644 index 00000000000..cafd06b03f1 --- /dev/null +++ b/dlls/gdi32/win32u_private.h @@ -0,0 +1,41 @@ +/* + * Unix call wrappers + * + * Copyright 2021 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WIN32U_PRIVATE +#define __WINE_WIN32U_PRIVATE + +#include "wine/gdi_driver.h" +#include "winuser.h" + +struct user_callbacks +{ + HWND (WINAPI *pGetDesktopWindow)(void); + UINT (WINAPI *pGetDpiForSystem)(void); + BOOL (WINAPI *pGetMonitorInfoW)( HMONITOR, LPMONITORINFO ); + INT (WINAPI *pGetSystemMetrics)(INT); + BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect ); + BOOL (WINAPI *pEnumDisplayMonitors)( HDC, LPRECT, MONITORENUMPROC, LPARAM ); + BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW ); + BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT ); + DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)( DPI_AWARENESS_CONTEXT ); + HWND (WINAPI *pWindowFromDC)( HDC ); +}; + +#endif /* __WINE_WIN32U_PRIVATE */ diff --git a/dlls/gdi32/wrappers.c b/dlls/gdi32/wrappers.c new file mode 100644 index 00000000000..e6b1ddc12e1 --- /dev/null +++ b/dlls/gdi32/wrappers.c @@ -0,0 +1,141 @@ +/* + * Unix call wrappers + * + * Copyright 2021 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gdi_private.h" +#include "win32u_private.h" + + +static void *get_user_proc( const char *name, BOOL force_load ) +{ + ANSI_STRING name_str; + FARPROC proc = NULL; + static HMODULE user32; + + if (!user32) + { + UNICODE_STRING str; + NTSTATUS status; + RtlInitUnicodeString( &str, L"user32.dll" ); + status = force_load + ? LdrLoadDll( NULL, 0, &str, &user32 ) + : LdrGetDllHandle( NULL, 0, &str, &user32 ); + if (status < 0) return NULL; + } + RtlInitAnsiString( &name_str, name ); + LdrGetProcedureAddress( user32, &name_str, 0, (void**)&proc ); + return proc; +} + +static HWND WINAPI call_GetDesktopWindow(void) +{ + static HWND (WINAPI *pGetDesktopWindow)(void); + if (!pGetDesktopWindow) + pGetDesktopWindow = get_user_proc( "GetDesktopWindow", TRUE ); + return pGetDesktopWindow ? pGetDesktopWindow() : NULL; +} + +static UINT WINAPI call_GetDpiForSystem(void) +{ + static UINT (WINAPI *pGetDpiForSystem)(void); + if (!pGetDpiForSystem) + pGetDpiForSystem = get_user_proc( "GetDpiForSystem", FALSE ); + return pGetDpiForSystem ? pGetDpiForSystem() : 96; +} + +static BOOL WINAPI call_GetMonitorInfoW( HMONITOR monitor, MONITORINFO *info ) +{ + static BOOL (WINAPI *pGetMonitorInfoW)( HMONITOR, LPMONITORINFO ); + if (!pGetMonitorInfoW) + pGetMonitorInfoW = get_user_proc( "GetMonitorInfoW", FALSE ); + return pGetMonitorInfoW && pGetMonitorInfoW( monitor, info ); +} + +static INT WINAPI call_GetSystemMetrics( INT metric ) +{ + static INT (WINAPI *pGetSystemMetrics)(INT); + if (!pGetSystemMetrics) + pGetSystemMetrics = get_user_proc( "GetSystemMetrics", FALSE ); + return pGetSystemMetrics ? pGetSystemMetrics( metric ) : 0; +} + +static BOOL WINAPI call_GetWindowRect( HWND hwnd, LPRECT rect ) +{ + static BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect ); + if (!pGetWindowRect) + pGetWindowRect = get_user_proc( "GetWindowRect", FALSE ); + return pGetWindowRect && pGetWindowRect( hwnd, rect ); +} + +static BOOL WINAPI call_EnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, + LPARAM lparam ) +{ + static BOOL (WINAPI *pEnumDisplayMonitors)( HDC, LPRECT, MONITORENUMPROC, LPARAM ); + if (!pEnumDisplayMonitors) + pEnumDisplayMonitors = get_user_proc( "EnumDisplayMonitors", FALSE ); + return pEnumDisplayMonitors && pEnumDisplayMonitors( hdc, rect, proc, lparam ); +} + +static BOOL WINAPI call_EnumDisplaySettingsW( const WCHAR *device, DWORD mode, DEVMODEW *devmode ) +{ + static BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW ); + if (!pEnumDisplaySettingsW) + pEnumDisplaySettingsW = get_user_proc( "EnumDisplaySettingsW", FALSE ); + return pEnumDisplaySettingsW && pEnumDisplaySettingsW( device, mode, devmode ); +} + +static BOOL WINAPI call_RedrawWindow( HWND hwnd, const RECT *rect, HRGN rgn, UINT flags ) +{ + static BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT ); + if (!pRedrawWindow) + pRedrawWindow = get_user_proc( "RedrawWindow", FALSE ); + return pRedrawWindow && pRedrawWindow( hwnd, rect, rgn, flags ); +} + +static DPI_AWARENESS_CONTEXT WINAPI call_SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT ctx ) +{ + static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)( DPI_AWARENESS_CONTEXT ); + if (!pSetThreadDpiAwarenessContext) + pSetThreadDpiAwarenessContext = get_user_proc( "SetThreadDpiAwarenessContext", FALSE ); + return pSetThreadDpiAwarenessContext ? pSetThreadDpiAwarenessContext( ctx ) : 0; +} + +static HWND WINAPI call_WindowFromDC( HDC hdc ) +{ + static HWND (WINAPI *pWindowFromDC)( HDC ); + if (!pWindowFromDC) + pWindowFromDC = get_user_proc( "WindowFromDC", FALSE ); + return pWindowFromDC ? pWindowFromDC( hdc ) : NULL; +} + +static const struct user_callbacks callbacks = +{ + call_GetDesktopWindow, + call_GetDpiForSystem, + call_GetMonitorInfoW, + call_GetSystemMetrics, + call_GetWindowRect, + call_EnumDisplayMonitors, + call_EnumDisplaySettingsW, + call_RedrawWindow, + call_SetThreadDpiAwarenessContext, + call_WindowFromDC, +}; + +const struct user_callbacks *user_callbacks = &callbacks;