Fix a regression that Office 2016/365 has a 640x480 main window.
Office 2016/365 hooks NtOpenKeyEx() and prevents access to SetupAPI device properties. After querying monitor information from SetupAPI failed, EnumDisplayMonitors() reports a fallback monitor of size 640x480.
As to why store the monitor information in the wineserver, it seems that EnumDisplayMonitors() reports monitors connected to current user logon session. For instance, EnumDisplayMonitors() always report one monitor when called by services.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/winemac.drv/display.c | 85 ++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 13 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 5a87e2331be..ee0061d6c05 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -32,6 +32,8 @@ #include "setupapi.h" #define WIN32_NO_STATUS #include "winternl.h" +#include "wine/heap.h" +#include "wine/server.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(display); @@ -57,8 +59,6 @@ DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1
/* Wine specific monitor properties */ DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2); -DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCMONITOR, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 3); -DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCWORK, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 4); DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
static const char initial_mode_key[] = "Initial Display Mode"; @@ -1632,7 +1632,6 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m WCHAR bufferW[MAX_PATH]; DWORD length; HKEY hkey; - RECT rect; BOOL ret = FALSE;
/* Create GUID_DEVCLASS_MONITOR instance */ @@ -1667,16 +1666,6 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32, (const BYTE *)&monitor->state_flags, sizeof(monitor->state_flags), 0)) goto done; - /* RcMonitor */ - rect = rect_from_cgrect(monitor->rc_monitor); - if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, DEVPROP_TYPE_BINARY, - (const BYTE *)&rect, sizeof(rect), 0)) - goto done; - /* RcWork */ - rect = rect_from_cgrect(monitor->rc_work); - if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, DEVPROP_TYPE_BINARY, - (const BYTE *)&rect, sizeof(rect), 0)) - goto done; /* Adapter name */ length = sprintfW(bufferW, adapter_name_fmtW, video_index + 1); if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING, @@ -1745,6 +1734,65 @@ static void cleanup_devices(void) SetupDiDestroyDeviceInfoList(devinfo); }
+/* Wine server monitor list management */ + +struct server_monitor_info +{ + unsigned int entry_count; + unsigned int entry_capacity; + struct update_monitor_entry *entries; +}; + +static BOOL server_add_monitor_info(struct server_monitor_info *info, + const struct macdrv_monitor *monitor, int adapter_index) +{ + struct update_monitor_entry *entry, *new_entries; + RECT monitor_rect, work_rect; + unsigned int length; + + if (info->entry_count <= info->entry_capacity) + info->entry_capacity = info->entry_capacity ? info->entry_capacity * 2 : 2; + + if (info->entries) + new_entries = heap_realloc(info->entries, info->entry_capacity * sizeof(*new_entries)); + else + new_entries = heap_calloc(info->entry_capacity, sizeof(*new_entries)); + + if (!new_entries) + return FALSE; + + info->entries = new_entries; + entry = &info->entries[info->entry_count++]; + monitor_rect = rect_from_cgrect(monitor->rc_monitor); + work_rect = rect_from_cgrect(monitor->rc_work); + entry->monitor_rect.top = monitor_rect.top; + entry->monitor_rect.left = monitor_rect.left; + entry->monitor_rect.right = monitor_rect.right; + entry->monitor_rect.bottom = monitor_rect.bottom; + entry->work_rect.top = work_rect.top; + entry->work_rect.left = work_rect.left; + entry->work_rect.right = work_rect.right; + entry->work_rect.bottom = work_rect.bottom; + length = sprintfW(entry->adapter_name, adapter_name_fmtW, adapter_index + 1); + entry->adapter_name_len = length * sizeof(WCHAR); + return TRUE; +} + +static void server_submit_monitor_info(const struct server_monitor_info *info) +{ + unsigned int status; + + SERVER_START_REQ(update_monitors) + { + wine_server_add_data(req, info->entries, info->entry_count * sizeof(*info->entries)); + status = wine_server_call(req); + } + SERVER_END_REQ; + + if (status) + ERR("Failed to update the monitor list in the wine server, status %#x\n", status); +} + /*********************************************************************** * macdrv_init_display_devices * @@ -1759,6 +1807,7 @@ void macdrv_init_display_devices(BOOL force) INT gpu_count, adapter_count, monitor_count; INT gpu, adapter, monitor; HDEVINFO gpu_devinfo = NULL, monitor_devinfo = NULL; + struct server_monitor_info info = {0}; HKEY video_hkey = NULL; INT video_index = 0; DWORD disposition = 0; @@ -1820,6 +1869,13 @@ void macdrv_init_display_devices(BOOL force) TRACE("monitor: %#x %s\n", monitor, monitors[monitor].name); if (!macdrv_init_monitor(monitor_devinfo, &monitors[monitor], monitor, video_index, &gpu_luid, output_id++)) goto done; + + /* EnumDisplayMonitors() doesn't enumerate mirrored replicas and inactive monitors */ + if (monitor != 0 || !(monitors[monitor].state_flags & DISPLAY_DEVICE_ACTIVE)) + continue; + + if (!server_add_monitor_info(&info, &monitors[monitor], video_index)) + goto done; }
macdrv_free_monitors(monitors); @@ -1831,7 +1887,10 @@ void macdrv_init_display_devices(BOOL force) adapters = NULL; }
+ server_submit_monitor_info(&info); + done: + heap_free(info.entries); cleanup_devices(); SetupDiDestroyDeviceInfoList(monitor_devinfo); SetupDiDestroyDeviceInfoList(gpu_devinfo);