win32u: Move writing mode to registry out of graphics drivers.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
This commit is contained in:
Rémi Bernon 2022-07-04 11:36:26 +02:00 committed by Alexandre Julliard
parent a7e135f4b3
commit d83fcafcd3
5 changed files with 73 additions and 215 deletions

View file

@ -420,6 +420,35 @@ static void release_display_device_init_mutex( HANDLE mutex )
NtClose( mutex );
}
static BOOL write_adapter_mode( HKEY adapter_key, const DEVMODEW *mode )
{
static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0};
WCHAR bufferW[MAX_PATH];
#define set_mode_field( name, field, flag ) \
do \
{ \
lstrcpyW( bufferW, default_settingsW ); \
lstrcatW( bufferW, (name) ); \
if (!set_reg_value( adapter_key, bufferW, REG_DWORD, &mode->field, sizeof(mode->field) )) \
return FALSE; \
} while (0)
set_mode_field( bits_per_pelW, dmBitsPerPel, DM_BITSPERPEL );
set_mode_field( x_resolutionW, dmPelsWidth, DM_PELSWIDTH );
set_mode_field( y_resolutionW, dmPelsHeight, DM_PELSHEIGHT );
set_mode_field( v_refreshW, dmDisplayFrequency, DM_DISPLAYFREQUENCY );
set_mode_field( flagsW, dmDisplayFlags, DM_DISPLAYFLAGS );
set_mode_field( orientationW, dmDisplayOrientation, DM_DISPLAYORIENTATION );
set_mode_field( fixed_outputW, dmDisplayFixedOutput, DM_DISPLAYFIXEDOUTPUT );
set_mode_field( x_panningW, dmPosition.x, DM_POSITION );
set_mode_field( y_panningW, dmPosition.y, DM_POSITION );
#undef set_mode_field
return TRUE;
}
static BOOL read_adapter_mode( HKEY adapter_key, DEVMODEW *mode )
{
static const WCHAR default_settingsW[] = {'D','e','f','a','u','l','t','S','e','t','t','i','n','g','s','.',0};
@ -473,6 +502,26 @@ static BOOL read_registry_settings( const WCHAR *adapter_path, DEVMODEW *mode )
return ret;
}
static BOOL write_registry_settings( const WCHAR *adapter_path, const DEVMODEW *mode )
{
HANDLE mutex;
HKEY hkey;
BOOL ret;
mutex = get_display_device_init_mutex();
if (!config_key && !(config_key = reg_open_key( NULL, config_keyW, sizeof(config_keyW) ))) ret = FALSE;
if (!(hkey = reg_open_key( config_key, adapter_path, lstrlenW( adapter_path ) * sizeof(WCHAR) ))) ret = FALSE;
else
{
ret = write_adapter_mode( hkey, mode );
NtClose( hkey );
}
release_display_device_init_mutex( mutex );
return ret;
}
static BOOL read_display_adapter_settings( unsigned int index, struct adapter *info )
{
char buffer[4096];
@ -1973,6 +2022,9 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm
if (!NtUserEnumDisplaySettings( devname, ENUM_CURRENT_SETTINGS, &current_mode, 0 )) current_mode.dmSize = 0;
if (!(devmode = validate_display_settings( &default_mode, &current_mode, devmode ))) ret = DISP_CHANGE_BADMODE;
else if (user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags | CDS_TEST, lparam )) ret = DISP_CHANGE_BADMODE;
else if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings( adapter_path, devmode )) ret = DISP_CHANGE_NOTUPDATED;
else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL;
else ret = user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags, lparam );
if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret );

View file

@ -60,73 +60,6 @@ static pthread_mutex_t modes_mutex = PTHREAD_MUTEX_INITIALIZER;
static BOOL inited_original_display_mode;
static HANDLE get_display_device_init_mutex(void)
{
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t'};
UNICODE_STRING name = { sizeof(init_mutexW), sizeof(init_mutexW), (WCHAR *)init_mutexW };
OBJECT_ATTRIBUTES attr;
HANDLE mutex = 0;
InitializeObjectAttributes(&attr, &name, OBJ_OPENIF, NULL, NULL);
NtCreateMutant(&mutex, MUTEX_ALL_ACCESS, &attr, FALSE);
if (mutex) NtWaitForSingleObject(mutex, FALSE, NULL);
return mutex;
}
static void release_display_device_init_mutex(HANDLE mutex)
{
NtReleaseMutant(mutex, NULL);
NtClose(mutex);
}
static HKEY get_display_device_reg_key(const WCHAR *device_name)
{
static const WCHAR display[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
static const WCHAR video_key[] = {
'\\','R','e','g','i','s','t','r','y',
'\\','M','a','c','h','i','n','e',
'\\','H','A','R','D','W','A','R','E',
'\\','D','E','V','I','C','E','M','A','P',
'\\','V','I','D','E','O'};
static const WCHAR current_config_key[] = {
'\\','R','e','g','i','s','t','r','y',
'\\','M','a','c','h','i','n','e',
'\\','S','y','s','t','e','m',
'\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
'\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s',
'\\','C','u','r','r','e','n','t'};
WCHAR value_name[MAX_PATH], buffer[4096], *end_ptr;
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
DWORD adapter_index, size;
char adapter_name[100];
HKEY hkey;
/* Device name has to be \\.\DISPLAY%d */
if (wcsnicmp(device_name, display, ARRAY_SIZE(display)))
return FALSE;
/* Parse \\.\DISPLAY* */
adapter_index = wcstol(device_name + ARRAY_SIZE(display), &end_ptr, 10) - 1;
if (*end_ptr)
return FALSE;
/* Open \Device\Video* in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
if (!(hkey = reg_open_key(NULL, video_key, sizeof(video_key)))) return FALSE;
sprintf(adapter_name, "\\Device\\Video%d", adapter_index);
asciiz_to_unicode(value_name, adapter_name);
size = query_reg_value(hkey, value_name, value, sizeof(buffer));
NtClose(hkey);
if (!size || value->Type != REG_SZ) return FALSE;
/* Replace \Registry\Machine\ prefix with HKEY_CURRENT_CONFIG */
memmove(buffer + ARRAYSIZE(current_config_key), (const WCHAR *)value->Data + 17,
size - 17 * sizeof(WCHAR));
memcpy(buffer, current_config_key, sizeof(current_config_key));
TRACE("display device %s registry settings key %s.\n", wine_dbgstr_w(device_name),
wine_dbgstr_w(buffer));
return reg_open_key(NULL, buffer, lstrlenW(buffer) * sizeof(WCHAR));
}
static BOOL set_setting_value(HKEY hkey, const char *name, DWORD val)
{
@ -136,35 +69,6 @@ static BOOL set_setting_value(HKEY hkey, const char *name, DWORD val)
}
static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm)
{
HANDLE mutex;
HKEY hkey;
BOOL ret = TRUE;
mutex = get_display_device_init_mutex();
if (!(hkey = get_display_device_reg_key(device_name)))
{
release_display_device_init_mutex(mutex);
return FALSE;
}
ret &= set_setting_value(hkey, "DefaultSettings.BitsPerPel", dm->dmBitsPerPel);
ret &= set_setting_value(hkey, "DefaultSettings.XResolution", dm->dmPelsWidth);
ret &= set_setting_value(hkey, "DefaultSettings.YResolution", dm->dmPelsHeight);
ret &= set_setting_value(hkey, "DefaultSettings.VRefresh", dm->dmDisplayFrequency);
ret &= set_setting_value(hkey, "DefaultSettings.Flags", dm->dmDisplayFlags);
ret &= set_setting_value(hkey, "DefaultSettings.XPanning", dm->dmPosition.x);
ret &= set_setting_value(hkey, "DefaultSettings.YPanning", dm->dmPosition.y);
ret &= set_setting_value(hkey, "DefaultSettings.Orientation", dm->dmDisplayOrientation);
ret &= set_setting_value(hkey, "DefaultSettings.FixedOutput", dm->dmDisplayFixedOutput);
NtClose(hkey);
release_display_device_init_mutex(mutex);
return ret;
}
static BOOL write_display_settings(HKEY parent_hkey, CGDirectDisplayID displayID)
{
BOOL ret = FALSE;
@ -934,13 +838,7 @@ better:
/* we have a valid mode */
TRACE("Requested display settings match mode %ld\n", best);
if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings(devname, devmode))
{
WARN("Failed to update registry\n");
ret = DISP_CHANGE_NOTUPDATED;
}
else if (flags & (CDS_TEST | CDS_NORESET))
ret = DISP_CHANGE_SUCCESSFUL;
if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL;
else if (wcsicmp(primary_adapter, devname))
{
FIXME("Changing non-primary adapter settings is currently unsupported.\n");

View file

@ -209,89 +209,6 @@ void init_registry_display_settings(void)
}
}
static HKEY get_display_device_reg_key( const WCHAR *device_name )
{
static const WCHAR display[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
static const WCHAR video_key[] = {
'\\','R','e','g','i','s','t','r','y',
'\\','M','a','c','h','i','n','e',
'\\','H','A','R','D','W','A','R','E',
'\\','D','E','V','I','C','E','M','A','P',
'\\','V','I','D','E','O'};
static const WCHAR current_config_key[] = {
'\\','R','e','g','i','s','t','r','y',
'\\','M','a','c','h','i','n','e',
'\\','S','y','s','t','e','m',
'\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
'\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s',
'\\','C','u','r','r','e','n','t'};
WCHAR value_name[MAX_PATH], buffer[4096], *end_ptr;
KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
DWORD adapter_index, size;
char adapter_name[100];
HKEY hkey;
/* Device name has to be \\.\DISPLAY%d */
if (wcsnicmp( device_name, display, ARRAY_SIZE(display) ))
return FALSE;
/* Parse \\.\DISPLAY* */
adapter_index = wcstol( device_name + ARRAY_SIZE(display), &end_ptr, 10 ) - 1;
if (*end_ptr)
return FALSE;
/* Open \Device\Video* in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
if (!(hkey = reg_open_key( NULL, video_key, sizeof(video_key) ))) return FALSE;
sprintf( adapter_name, "\\Device\\Video%d", adapter_index );
asciiz_to_unicode( value_name, adapter_name );
size = query_reg_value( hkey, value_name, value, sizeof(buffer) );
NtClose( hkey );
if (!size || value->Type != REG_SZ) return FALSE;
/* Replace \Registry\Machine\ prefix with HKEY_CURRENT_CONFIG */
memmove( buffer + ARRAYSIZE(current_config_key), (const WCHAR *)value->Data + 17,
size - 17 * sizeof(WCHAR) );
memcpy( buffer, current_config_key, sizeof(current_config_key) );
TRACE( "display device %s registry settings key %s.\n", wine_dbgstr_w(device_name),
wine_dbgstr_w(buffer) );
return reg_open_key( NULL, buffer, lstrlenW(buffer) * sizeof(WCHAR) );
}
static BOOL set_setting_value( HKEY hkey, const char *name, DWORD val )
{
WCHAR nameW[128];
UNICODE_STRING str = { asciiz_to_unicode( nameW, name ) - sizeof(WCHAR), sizeof(nameW), nameW };
return !NtSetValueKey( hkey, &str, 0, REG_DWORD, &val, sizeof(val) );
}
static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm)
{
HANDLE mutex;
HKEY hkey;
BOOL ret = TRUE;
mutex = get_display_device_init_mutex();
if (!(hkey = get_display_device_reg_key( device_name )))
{
release_display_device_init_mutex(mutex);
return FALSE;
}
ret &= set_setting_value( hkey, "DefaultSettings.BitsPerPel", dm->dmBitsPerPel );
ret &= set_setting_value( hkey, "DefaultSettings.XResolution", dm->dmPelsWidth );
ret &= set_setting_value( hkey, "DefaultSettings.YResolution", dm->dmPelsHeight );
ret &= set_setting_value( hkey, "DefaultSettings.VRefresh", dm->dmDisplayFrequency );
ret &= set_setting_value( hkey, "DefaultSettings.Flags", dm->dmDisplayFlags );
ret &= set_setting_value( hkey, "DefaultSettings.XPanning", dm->dmPosition.x );
ret &= set_setting_value( hkey, "DefaultSettings.YPanning", dm->dmPosition.y );
ret &= set_setting_value( hkey, "DefaultSettings.Orientation", dm->dmDisplayOrientation );
ret &= set_setting_value( hkey, "DefaultSettings.FixedOutput", dm->dmDisplayFixedOutput );
NtClose( hkey );
release_display_device_init_mutex(mutex);
return ret;
}
BOOL get_primary_adapter(WCHAR *name)
{
DISPLAY_DEVICEW dd;
@ -883,14 +800,7 @@ LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
return DISP_CHANGE_BADMODE;
}
if (!write_registry_settings(devname, full_mode))
{
ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname));
free_full_mode(full_mode);
free(displays);
return DISP_CHANGE_NOTUPDATED;
}
memcpy( &devmode->dmFields, &full_mode->dmFields, devmode->dmSize - offsetof(DEVMODEW, dmFields) );
free_full_mode(full_mode);
break;
}
@ -922,25 +832,6 @@ LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
return ret;
}
HANDLE get_display_device_init_mutex(void)
{
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t'};
UNICODE_STRING name = { sizeof(init_mutexW), sizeof(init_mutexW), (WCHAR *)init_mutexW };
OBJECT_ATTRIBUTES attr;
HANDLE mutex = 0;
InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE );
if (mutex) NtWaitForSingleObject( mutex, FALSE, NULL );
return mutex;
}
void release_display_device_init_mutex(HANDLE mutex)
{
NtReleaseMutant( mutex, NULL );
NtClose( mutex );
}
POINT virtual_screen_to_root(INT x, INT y)
{
RECT virtual = NtUserGetVirtualScreenRect();

View file

@ -805,9 +805,7 @@ struct x11drv_display_device_handler
void (*register_event_handlers)(void);
};
extern HANDLE get_display_device_init_mutex(void) DECLSPEC_HIDDEN;
extern BOOL get_host_primary_gpu(struct gdi_gpu *gpu) DECLSPEC_HIDDEN;
extern void release_display_device_init_mutex(HANDLE) DECLSPEC_HIDDEN;
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN;
extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN;

View file

@ -1017,6 +1017,25 @@ NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDP
return STATUS_SUCCESS;
}
static HANDLE get_display_device_init_mutex(void)
{
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t'};
UNICODE_STRING name = { sizeof(init_mutexW), sizeof(init_mutexW), (WCHAR *)init_mutexW };
OBJECT_ATTRIBUTES attr;
HANDLE mutex = 0;
InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE );
if (mutex) NtWaitForSingleObject( mutex, FALSE, NULL );
return mutex;
}
static void release_display_device_init_mutex(HANDLE mutex)
{
NtReleaseMutant( mutex, NULL );
NtClose( mutex );
}
/* Find the Vulkan device UUID corresponding to a LUID */
static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
{