diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 4acd7299624..1dedf32a52f 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -124,7 +124,7 @@ static CRITICAL_SECTION_DEBUG screen_critsect_debug = }; static CRITICAL_SECTION screen_section = {&screen_critsect_debug, -1, 0, 0, 0, 0}; -static HANDLE get_display_device_init_mutex(void) +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',0}; HANDLE mutex = CreateMutexW(NULL, FALSE, init_mutexW); @@ -133,7 +133,7 @@ static HANDLE get_display_device_init_mutex(void) return mutex; } -static void release_display_device_init_mutex(HANDLE mutex) +void release_display_device_init_mutex(HANDLE mutex) { ReleaseMutex(mutex); CloseHandle(mutex); diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index bc9f7aa1dca..c3f31d0430d 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -19,9 +19,6 @@ */ #include "config.h" -#include -#include -#include #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -32,6 +29,7 @@ #include "winreg.h" #include "wingdi.h" #include "wine/debug.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(x11settings); @@ -154,43 +152,63 @@ void X11DRV_Settings_Init(void) X11DRV_Settings_AddOneMode( primary.right - primary.left, primary.bottom - primary.top, 0, 60); } -static BOOL get_display_device_reg_key(char *key, unsigned len) +static BOOL get_display_device_reg_key(const WCHAR *device_name, WCHAR *key, unsigned len) { - static const char display_device_guid_prop[] = "__wine_display_device_guid"; - static const char video_path[] = "System\\CurrentControlSet\\Control\\Video\\{"; - static const char display0[] = "}\\0000"; - ATOM guid_atom; + static const WCHAR display[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'}; + static const WCHAR video_value_fmt[] = {'\\','D','e','v','i','c','e','\\', + 'V','i','d','e','o','%','d',0}; + static const WCHAR video_key[] = {'H','A','R','D','W','A','R','E','\\', + 'D','E','V','I','C','E','M','A','P','\\', + 'V','I','D','E','O','\\',0}; + WCHAR value_name[MAX_PATH], buffer[MAX_PATH], *end_ptr; + DWORD adapter_index, size; - assert(len >= sizeof(video_path) + sizeof(display0) + 40); - - guid_atom = HandleToULong(GetPropA(GetDesktopWindow(), display_device_guid_prop)); - if (!guid_atom) return FALSE; - - memcpy(key, video_path, sizeof(video_path)); - - if (!GlobalGetAtomNameA(guid_atom, key + strlen(key), 40)) + /* Device name has to be \\.\DISPLAY%d */ + if (strncmpiW(device_name, display, ARRAY_SIZE(display))) return FALSE; - strcat(key, display0); + /* Parse \\.\DISPLAY* */ + adapter_index = strtolW(device_name + ARRAY_SIZE(display), &end_ptr, 10) - 1; + if (*end_ptr) + return FALSE; - TRACE("display device key %s\n", wine_dbgstr_a(key)); + /* Open \Device\Video* in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */ + sprintfW(value_name, video_value_fmt, adapter_index); + size = sizeof(buffer); + if (RegGetValueW(HKEY_LOCAL_MACHINE, video_key, value_name, RRF_RT_REG_SZ, NULL, buffer, &size)) + return FALSE; + + if (len < lstrlenW(buffer + 18) + 1) + return FALSE; + + /* Skip \Registry\Machine\ prefix */ + lstrcpyW(key, buffer + 18); + TRACE("display device %s registry settings key %s.\n", wine_dbgstr_w(device_name), wine_dbgstr_w(key)); return TRUE; } -static BOOL read_registry_settings(DEVMODEW *dm) +static BOOL read_registry_settings(const WCHAR *device_name, DEVMODEW *dm) { - char wine_x11_reg_key[128]; + WCHAR wine_x11_reg_key[MAX_PATH]; + HANDLE mutex; HKEY hkey; DWORD type, size; BOOL ret = TRUE; dm->dmFields = 0; - if (!get_display_device_reg_key(wine_x11_reg_key, sizeof(wine_x11_reg_key))) + mutex = get_display_device_init_mutex(); + if (!get_display_device_reg_key(device_name, wine_x11_reg_key, ARRAY_SIZE(wine_x11_reg_key))) + { + release_display_device_init_mutex(mutex); return FALSE; + } - if (RegOpenKeyExA(HKEY_CURRENT_CONFIG, wine_x11_reg_key, 0, KEY_READ, &hkey)) + if (RegOpenKeyExW(HKEY_CURRENT_CONFIG, wine_x11_reg_key, 0, KEY_READ, &hkey)) + { + release_display_device_init_mutex(mutex); return FALSE; + } #define query_value(name, data) \ size = sizeof(DWORD); \ @@ -218,21 +236,30 @@ static BOOL read_registry_settings(DEVMODEW *dm) #undef query_value RegCloseKey(hkey); + release_display_device_init_mutex(mutex); return ret; } -static BOOL write_registry_settings(const DEVMODEW *dm) +static BOOL write_registry_settings(const WCHAR *device_name, const DEVMODEW *dm) { - char wine_x11_reg_key[128]; + WCHAR wine_x11_reg_key[MAX_PATH]; + HANDLE mutex; HKEY hkey; BOOL ret = TRUE; - if (!get_display_device_reg_key(wine_x11_reg_key, sizeof(wine_x11_reg_key))) + mutex = get_display_device_init_mutex(); + if (!get_display_device_reg_key(device_name, wine_x11_reg_key, ARRAY_SIZE(wine_x11_reg_key))) + { + release_display_device_init_mutex(mutex); return FALSE; + } - if (RegCreateKeyExA(HKEY_CURRENT_CONFIG, wine_x11_reg_key, 0, NULL, + if (RegCreateKeyExW(HKEY_CURRENT_CONFIG, wine_x11_reg_key, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL)) + { + release_display_device_init_mutex(mutex); return FALSE; + } #define set_value(name, data) \ if (RegSetValueExA(hkey, name, 0, REG_DWORD, (const BYTE*)(data), sizeof(DWORD))) \ @@ -251,6 +278,7 @@ static BOOL write_registry_settings(const DEVMODEW *dm) #undef set_value RegCloseKey(hkey); + release_display_device_init_mutex(mutex); return ret; } @@ -301,7 +329,7 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo if (n == ENUM_REGISTRY_SETTINGS) { TRACE("mode %d (registry) -- getting default mode (%s)\n", n, handler_name); - return read_registry_settings(devmode); + return read_registry_settings(name, devmode); } if (n < dd_mode_count) { @@ -368,13 +396,6 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, devmode = &default_mode; } - if (lstrcmpiW(primary_adapter, devname)) - { - FIXME("Changing non-primary adapter %s settings is currently unsupported.\n", - wine_dbgstr_w(devname)); - return DISP_CHANGE_SUCCESSFUL; - } - if (is_detached_mode(devmode)) { FIXME("Detaching adapters is currently unsupported.\n"); @@ -407,8 +428,18 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, /* we have a valid mode */ TRACE("Requested display settings match mode %d (%s)\n", i, handler_name); - if (flags & CDS_UPDATEREGISTRY) - write_registry_settings(devmode); + if (flags & CDS_UPDATEREGISTRY && !write_registry_settings(devname, devmode)) + { + ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname)); + return DISP_CHANGE_NOTUPDATED; + } + + if (lstrcmpiW(primary_adapter, devname)) + { + FIXME("Changing non-primary adapter %s settings is currently unsupported.\n", + wine_dbgstr_w(devname)); + return DISP_CHANGE_SUCCESSFUL; + } if (!(flags & (CDS_TEST | CDS_NORESET))) return pSetCurrentMode(i); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 5021c71a415..a9eaed20cab 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -754,6 +754,8 @@ struct x11drv_display_device_handler void (*register_event_handlers)(void); }; +extern HANDLE get_display_device_init_mutex(void) 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;