From 3867d253ed548985e481a117771002f652651702 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 2 Dec 2021 01:14:35 +0100 Subject: [PATCH] win32u: Move NtUserChangeDisplaySettings implementation from user32. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/user32/driver.c | 8 +- dlls/user32/sysparams.c | 198 +---------------------------------- dlls/win32u/driver.c | 7 ++ dlls/win32u/gdiobj.c | 1 + dlls/win32u/sysparams.c | 167 +++++++++++++++++++++++++++++ dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 2 + dlls/win32u/wrappers.c | 6 ++ include/ntuser.h | 2 + 9 files changed, 190 insertions(+), 203 deletions(-) diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 5dc11d2b9fa..295a7ee2cd7 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -263,12 +263,6 @@ static void CDECL loaderdrv_UpdateClipboard(void) load_driver()->pUpdateClipboard(); } -static LONG CDECL loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND hwnd, - DWORD flags, LPVOID lparam ) -{ - return load_driver()->pChangeDisplaySettingsEx( name, mode, hwnd, flags, lparam ); -} - static BOOL CDECL loaderdrv_CreateDesktopWindow( HWND hwnd ) { return load_driver()->pCreateDesktopWindow( hwnd ); @@ -328,7 +322,7 @@ static struct user_driver_funcs lazy_load_driver = /* clipboard functions */ loaderdrv_UpdateClipboard, /* display modes */ - loaderdrv_ChangeDisplaySettingsEx, + NULL, NULL, NULL, /* windowing functions */ diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index d1036c77390..803c583237d 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -370,39 +370,6 @@ static INT get_monitor_count(void) return count; } -static BOOL get_primary_adapter(WCHAR *name) -{ - DISPLAY_DEVICEW dd; - DWORD i; - - dd.cb = sizeof(dd); - for (i = 0; EnumDisplayDevicesW(NULL, i, &dd, 0); ++i) - { - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - lstrcpyW(name, dd.DeviceName); - return TRUE; - } - } - - return FALSE; -} - -static BOOL is_valid_adapter_name(const WCHAR *name) -{ - long int adapter_idx; - WCHAR *end; - - if (wcsnicmp(name, L"\\\\.\\DISPLAY", lstrlenW(L"\\\\.\\DISPLAY"))) - return FALSE; - - adapter_idx = wcstol(name + lstrlenW(L"\\\\.\\DISPLAY"), &end, 10); - if (*end || adapter_idx < 1) - return FALSE; - - return TRUE; -} - /* get text metrics and/or "average" char width of the specified logfont * for the specified dc */ static void get_text_metr_size( HDC hdc, LOGFONTW *plf, TEXTMETRICW * ptm, UINT *psz) @@ -3040,83 +3007,6 @@ LONG WINAPI ChangeDisplaySettingsExA( LPCSTR devname, LPDEVMODEA devmode, HWND h return ret; } -#define _X_FIELD(prefix, bits) \ - if ((fields) & prefix##_##bits) \ - { \ - p += sprintf(p, "%s%s", first ? "" : ",", #bits); \ - first = FALSE; \ - } - -static const CHAR *_CDS_flags(DWORD fields) -{ - BOOL first = TRUE; - CHAR buf[128]; - CHAR *p = buf; - - _X_FIELD(CDS, UPDATEREGISTRY) - _X_FIELD(CDS, TEST) - _X_FIELD(CDS, FULLSCREEN) - _X_FIELD(CDS, GLOBAL) - _X_FIELD(CDS, SET_PRIMARY) - _X_FIELD(CDS, VIDEOPARAMETERS) - _X_FIELD(CDS, ENABLE_UNSAFE_MODES) - _X_FIELD(CDS, DISABLE_UNSAFE_MODES) - _X_FIELD(CDS, RESET) - _X_FIELD(CDS, RESET_EX) - _X_FIELD(CDS, NORESET) - - *p = 0; - return wine_dbg_sprintf("%s", buf); -} - -static const CHAR *_DM_fields(DWORD fields) -{ - BOOL first = TRUE; - CHAR buf[128]; - CHAR *p = buf; - - _X_FIELD(DM, BITSPERPEL) - _X_FIELD(DM, PELSWIDTH) - _X_FIELD(DM, PELSHEIGHT) - _X_FIELD(DM, DISPLAYFLAGS) - _X_FIELD(DM, DISPLAYFREQUENCY) - _X_FIELD(DM, POSITION) - _X_FIELD(DM, DISPLAYORIENTATION) - - *p = 0; - return wine_dbg_sprintf("%s", buf); -} - -#undef _X_FIELD - -static void trace_devmode(const DEVMODEW *devmode) -{ - TRACE("dmFields=%s ", _DM_fields(devmode->dmFields)); - if (devmode->dmFields & DM_BITSPERPEL) - TRACE("dmBitsPerPel=%u ", devmode->dmBitsPerPel); - if (devmode->dmFields & DM_PELSWIDTH) - TRACE("dmPelsWidth=%u ", devmode->dmPelsWidth); - if (devmode->dmFields & DM_PELSHEIGHT) - TRACE("dmPelsHeight=%u ", devmode->dmPelsHeight); - if (devmode->dmFields & DM_DISPLAYFREQUENCY) - TRACE("dmDisplayFrequency=%u ", devmode->dmDisplayFrequency); - if (devmode->dmFields & DM_POSITION) - TRACE("dmPosition=(%d,%d) ", devmode->u1.s2.dmPosition.x, devmode->u1.s2.dmPosition.y); - if (devmode->dmFields & DM_DISPLAYFLAGS) - TRACE("dmDisplayFlags=%#x ", devmode->u2.dmDisplayFlags); - if (devmode->dmFields & DM_DISPLAYORIENTATION) - TRACE("dmDisplayOrientation=%u ", devmode->u1.s2.dmDisplayOrientation); - TRACE("\n"); -} - -static BOOL is_detached_mode(const DEVMODEW *mode) -{ - return mode->dmFields & DM_POSITION && - mode->dmFields & DM_PELSWIDTH && - mode->dmFields & DM_PELSHEIGHT && - mode->dmPelsWidth == 0 && - mode->dmPelsHeight == 0; -} /*********************************************************************** * ChangeDisplaySettingsExW (USER32.@) @@ -3124,91 +3014,9 @@ static BOOL is_detached_mode(const DEVMODEW *mode) LONG WINAPI ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lparam ) { - WCHAR primary_adapter[CCHDEVICENAME]; - BOOL def_mode = TRUE; - DEVMODEW dm; - LONG ret; - - TRACE("%s %p %p %#x %p\n", debugstr_w(devname), devmode, hwnd, flags, lparam); - TRACE("flags=%s\n", _CDS_flags(flags)); - - if (!devname && !devmode) - { - ret = USER_Driver->pChangeDisplaySettingsEx(NULL, NULL, hwnd, flags, lparam); - if (ret != DISP_CHANGE_SUCCESSFUL) - ERR("Restoring all displays to their registry settings returned %d.\n", ret); - return ret; - } - - if (!devname && devmode) - { - if (!get_primary_adapter(primary_adapter)) - return DISP_CHANGE_FAILED; - - devname = primary_adapter; - } - - if (!is_valid_adapter_name(devname)) - { - ERR("Invalid device name %s.\n", wine_dbgstr_w(devname)); - return DISP_CHANGE_BADPARAM; - } - - if (devmode) - { - trace_devmode(devmode); - - if (devmode->dmSize < FIELD_OFFSET(DEVMODEW, dmICMMethod)) - return DISP_CHANGE_BADMODE; - - if (is_detached_mode(devmode) || - ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel) || - ((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth) || - ((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight) || - ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency)) - def_mode = FALSE; - } - - if (def_mode) - { - memset(&dm, 0, sizeof(dm)); - dm.dmSize = sizeof(dm); - if (!EnumDisplaySettingsExW(devname, ENUM_REGISTRY_SETTINGS, &dm, 0)) - { - ERR("Default mode not found!\n"); - return DISP_CHANGE_BADMODE; - } - - TRACE("Return to original display mode\n"); - devmode = &dm; - } - - if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) - { - WARN("devmode doesn't specify the resolution: %#x\n", devmode->dmFields); - return DISP_CHANGE_BADMODE; - } - - if (!is_detached_mode(devmode) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight)) - { - memset(&dm, 0, sizeof(dm)); - dm.dmSize = sizeof(dm); - if (!EnumDisplaySettingsExW(devname, ENUM_CURRENT_SETTINGS, &dm, 0)) - { - ERR("Current mode not found!\n"); - return DISP_CHANGE_BADMODE; - } - - if (!devmode->dmPelsWidth) - devmode->dmPelsWidth = dm.dmPelsWidth; - if (!devmode->dmPelsHeight) - devmode->dmPelsHeight = dm.dmPelsHeight; - } - - ret = USER_Driver->pChangeDisplaySettingsEx(devname, devmode, hwnd, flags, lparam); - if (ret != DISP_CHANGE_SUCCESSFUL) - ERR("Changing %s display settings returned %d.\n", wine_dbgstr_w(devname), ret); - return ret; + UNICODE_STRING str; + RtlInitUnicodeString( &str, devname ); + return NtUserChangeDisplaySettings( &str, devmode, hwnd, flags, lparam ); } diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 03594aa58d0..5d43daf2355 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1021,6 +1021,12 @@ static SHORT CDECL loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout ) return load_driver()->pVkKeyScanEx( ch, layout ); } +static LONG CDECL loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND hwnd, + DWORD flags, LPVOID lparam ) +{ + return load_driver()->pChangeDisplaySettingsEx( name, mode, hwnd, flags, lparam ); +} + static BOOL CDECL loaderdrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags ) { return load_driver()->pEnumDisplaySettingsEx( name, num, mode, flags ); @@ -1046,6 +1052,7 @@ static const struct user_driver_funcs lazy_load_driver = .pToUnicodeEx = loaderdrv_ToUnicodeEx, .pUnregisterHotKey = loaderdrv_UnregisterHotKey, .pVkKeyScanEx = loaderdrv_VkKeyScanEx, + .pChangeDisplaySettingsEx = loaderdrv_ChangeDisplaySettingsEx, .pEnumDisplaySettingsEx = loaderdrv_EnumDisplaySettingsEx, .pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices, .pUpdateClipboard = loaderdrv_UpdateClipboard, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 7af551dad19..e0a036f4d0d 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1169,6 +1169,7 @@ static struct unix_funcs unix_funcs = NtGdiWidenPath, NtUserActivateKeyboardLayout, NtUserCallTwoParam, + NtUserChangeDisplaySettings, NtUserCountClipboardFormats, NtUserEnumDisplayDevices, NtUserEnumDisplayMonitors, diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 2da659aa3e5..d2406672ee6 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1347,6 +1347,173 @@ BOOL WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index, return !!found; } +#define _X_FIELD(prefix, bits) \ + if ((fields) & prefix##_##bits) \ + { \ + p += sprintf( p, "%s%s", first ? "" : ",", #bits ); \ + first = FALSE; \ + } + +static const char *_CDS_flags( DWORD fields ) +{ + BOOL first = TRUE; + CHAR buf[128]; + CHAR *p = buf; + + _X_FIELD(CDS, UPDATEREGISTRY) + _X_FIELD(CDS, TEST) + _X_FIELD(CDS, FULLSCREEN) + _X_FIELD(CDS, GLOBAL) + _X_FIELD(CDS, SET_PRIMARY) + _X_FIELD(CDS, VIDEOPARAMETERS) + _X_FIELD(CDS, ENABLE_UNSAFE_MODES) + _X_FIELD(CDS, DISABLE_UNSAFE_MODES) + _X_FIELD(CDS, RESET) + _X_FIELD(CDS, RESET_EX) + _X_FIELD(CDS, NORESET) + + *p = 0; + return wine_dbg_sprintf( "%s", buf ); +} + +static const char *_DM_fields( DWORD fields ) +{ + BOOL first = TRUE; + CHAR buf[128]; + CHAR *p = buf; + + _X_FIELD(DM, BITSPERPEL) + _X_FIELD(DM, PELSWIDTH) + _X_FIELD(DM, PELSHEIGHT) + _X_FIELD(DM, DISPLAYFLAGS) + _X_FIELD(DM, DISPLAYFREQUENCY) + _X_FIELD(DM, POSITION) + _X_FIELD(DM, DISPLAYORIENTATION) + + *p = 0; + return wine_dbg_sprintf( "%s", buf ); +} + +#undef _X_FIELD + +static void trace_devmode( const DEVMODEW *devmode ) +{ + TRACE( "dmFields=%s ", _DM_fields(devmode->dmFields) ); + if (devmode->dmFields & DM_BITSPERPEL) + TRACE( "dmBitsPerPel=%u ", devmode->dmBitsPerPel ); + if (devmode->dmFields & DM_PELSWIDTH) + TRACE( "dmPelsWidth=%u ", devmode->dmPelsWidth ); + if (devmode->dmFields & DM_PELSHEIGHT) + TRACE( "dmPelsHeight=%u ", devmode->dmPelsHeight ); + if (devmode->dmFields & DM_DISPLAYFREQUENCY) + TRACE( "dmDisplayFrequency=%u ", devmode->dmDisplayFrequency ); + if (devmode->dmFields & DM_POSITION) + TRACE( "dmPosition=(%d,%d) ", devmode->dmPosition.x, devmode->dmPosition.y ); + if (devmode->dmFields & DM_DISPLAYFLAGS) + TRACE( "dmDisplayFlags=%#x ", devmode->dmDisplayFlags ); + if (devmode->dmFields & DM_DISPLAYORIENTATION) + TRACE( "dmDisplayOrientation=%u ", devmode->dmDisplayOrientation ); + TRACE("\n"); +} + +static BOOL is_detached_mode( const DEVMODEW *mode ) +{ + return mode->dmFields & DM_POSITION && + mode->dmFields & DM_PELSWIDTH && + mode->dmFields & DM_PELSHEIGHT && + mode->dmPelsWidth == 0 && + mode->dmPelsHeight == 0; +} + +/*********************************************************************** + * NtUserChangeDisplaySettingsExW (win32u.@) + */ +LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, + DWORD flags, void *lparam ) +{ + WCHAR device_name[CCHDEVICENAME]; + struct adapter *adapter; + BOOL def_mode = TRUE; + DEVMODEW dm; + LONG ret; + + TRACE( "%s %p %p %#x %p\n", debugstr_us(devname), devmode, hwnd, flags, lparam ); + TRACE( "flags=%s\n", _CDS_flags(flags) ); + + if ((!devname || !devname->Length) && !devmode) + { + ret = user_driver->pChangeDisplaySettingsEx( NULL, NULL, hwnd, flags, lparam ); + if (ret != DISP_CHANGE_SUCCESSFUL) + ERR( "Restoring all displays to their registry settings returned %d.\n", ret ); + return ret; + } + + if (!lock_display_devices()) return FALSE; + if ((adapter = find_adapter( devname ))) lstrcpyW( device_name, adapter->dev.device_name ); + unlock_display_devices(); + if (!adapter) + { + WARN( "Invalid device name %s.\n", debugstr_us(devname) ); + return DISP_CHANGE_BADPARAM; + } + + if (devmode) + { + trace_devmode( devmode ); + + if (devmode->dmSize < FIELD_OFFSET(DEVMODEW, dmICMMethod)) + return DISP_CHANGE_BADMODE; + + if (is_detached_mode(devmode) || + ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel) || + ((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth) || + ((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight) || + ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency)) + def_mode = FALSE; + } + + if (def_mode) + { + memset( &dm, 0, sizeof(dm) ); + dm.dmSize = sizeof(dm); + if (!NtUserEnumDisplaySettings( devname, ENUM_REGISTRY_SETTINGS, &dm, 0 )) + { + ERR( "Default mode not found!\n" ); + return DISP_CHANGE_BADMODE; + } + + TRACE( "Return to original display mode\n" ); + devmode = &dm; + } + + if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) + { + WARN( "devmode doesn't specify the resolution: %#x\n", devmode->dmFields ); + return DISP_CHANGE_BADMODE; + } + + if (!is_detached_mode(devmode) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight)) + { + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + if (!NtUserEnumDisplaySettings( devname, ENUM_CURRENT_SETTINGS, &dm, 0 )) + { + ERR( "Current mode not found!\n" ); + return DISP_CHANGE_BADMODE; + } + + if (!devmode->dmPelsWidth) + devmode->dmPelsWidth = dm.dmPelsWidth; + if (!devmode->dmPelsHeight) + devmode->dmPelsHeight = dm.dmPelsHeight; + } + + ret = user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags, lparam ); + if (ret != DISP_CHANGE_SUCCESSFUL) + ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret ); + return ret; +} + /*********************************************************************** * NtUserEnumDisplaySettings (win32u.@) */ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index f7291214763..82c232617fb 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -783,7 +783,7 @@ @ stdcall NtUserCallTwoParam(long long long) @ stub NtUserCanBrokerForceForeground @ stub NtUserChangeClipboardChain -@ stub NtUserChangeDisplaySettings +@ stdcall NtUserChangeDisplaySettings(ptr ptr long long ptr) @ stub NtUserChangeWindowMessageFilterEx @ stub NtUserCheckAccessForIntegrityLevel @ stub NtUserCheckMenuItem diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 159d2a722d0..d301d8b6b8b 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -196,6 +196,8 @@ struct unix_funcs BOOL (WINAPI *pNtGdiWidenPath)( HDC hdc ); HKL (WINAPI *pNtUserActivateKeyboardLayout)( HKL layout, UINT flags ); ULONG_PTR (WINAPI *pNtUserCallTwoParam)( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code ); + LONG (WINAPI *pNtUserChangeDisplaySettings)( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, + DWORD flags, void *lparam ); INT (WINAPI *pNtUserCountClipboardFormats)(void); BOOL (WINAPI *pNtUserEnumDisplayDevices)( UNICODE_STRING *device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags ); diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index f51ed303b8b..4b9a291bf6b 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -606,6 +606,12 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code return unix_funcs->pNtUserCallTwoParam( arg1, arg2, code ); } +LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, + DWORD flags, void *lparam ) +{ + return unix_funcs->pNtUserChangeDisplaySettings( devname, devmode, hwnd, flags, lparam ); +} + INT WINAPI NtUserCountClipboardFormats(void) { return unix_funcs->pNtUserCountClipboardFormats(); diff --git a/include/ntuser.h b/include/ntuser.h index 886ade70685..ec0ccc0c2c5 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -79,6 +79,8 @@ HKL WINAPI NtUserActivateKeyboardLayout( HKL layout, UINT flags ); BOOL WINAPI NtUserAddClipboardFormatListener( HWND hwnd ); BOOL WINAPI NtUserAttachThreadInput( DWORD from, DWORD to, BOOL attach ); ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code ); +LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, + DWORD flags, void *lparam ); BOOL WINAPI NtUserCloseDesktop( HDESK handle ); BOOL WINAPI NtUserCloseWindowStation( HWINSTA handle ); INT WINAPI NtUserCountClipboardFormats(void);