Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2020
- 82 participants
- 799 discussions
[PATCH 2/4] winemac.drv: Store monitor information in the wineserver for EnumDisplayMonitors().
by Zhiyi Zhang 28 Oct '20
by Zhiyi Zhang 28 Oct '20
28 Oct '20
Fix Office 2016/365 having a 640x480 main window.
Office 2016/365 hooks NtOpenKeyEx() and prevents access to SetupAPI device properties.
After failed to query monitor information from SetupAPI, EnumDisplayMonitors() reports
a fallback monitor of size 640x480.
As to why store the monitor information in wineserver, it seems the 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(a)codeweavers.com>
---
dlls/winemac.drv/display.c | 65 ++++++++++++++++++++++++++++++--------
1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index f6390becea7..9e7d5214e47 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -32,6 +32,7 @@
#include "setupapi.h"
#define WIN32_NO_STATUS
#include "winternl.h"
+#include "wine/server.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(display);
@@ -57,8 +58,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";
@@ -1628,10 +1627,11 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m
int video_index, const LUID *gpu_luid, UINT output_id)
{
SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
+ RECT monitor_rect, work_rect;
WCHAR nameW[MAX_PATH];
WCHAR bufferW[MAX_PATH];
+ DWORD size;
HKEY hkey;
- RECT rect;
BOOL ret = FALSE;
/* Create GUID_DEVCLASS_MONITOR instance */
@@ -1666,22 +1666,35 @@ 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 */
sprintfW(bufferW, adapter_name_fmtW, video_index + 1);
+ size = (lstrlenW(bufferW) + 1) * sizeof(WCHAR);
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING,
- (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR), 0))
+ (const BYTE *)bufferW, size, 0))
goto done;
+ /* EnumDisplayMonitors() doesn't enumerate mirrored replicas and inactive monitors */
+ if (monitor_index == 0 && monitor->state_flags & DISPLAY_DEVICE_ACTIVE)
+ {
+ SERVER_START_REQ(create_monitor)
+ {
+ monitor_rect = rect_from_cgrect(monitor->rc_monitor);
+ req->monitor_rect.top = monitor_rect.top;
+ req->monitor_rect.left = monitor_rect.left;
+ req->monitor_rect.right = monitor_rect.right;
+ req->monitor_rect.bottom = monitor_rect.bottom;
+ work_rect = rect_from_cgrect(monitor->rc_work);
+ req->work_rect.top = work_rect.top;
+ req->work_rect.left = work_rect.left;
+ req->work_rect.right = work_rect.right;
+ req->work_rect.bottom = work_rect.bottom;
+ wine_server_add_data(req, bufferW, size);
+ if (wine_server_call(req))
+ goto done;
+ }
+ SERVER_END_REQ;
+ }
+
ret = TRUE;
done:
if (!ret)
@@ -1693,7 +1706,9 @@ static void prepare_devices(HKEY video_hkey)
{
static const BOOL not_present = FALSE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HMONITOR monitor = NULL;
HDEVINFO devinfo;
+ NTSTATUS status;
DWORD i = 0;
/* Remove all monitors */
@@ -1705,6 +1720,28 @@ static void prepare_devices(HKEY video_hkey)
}
SetupDiDestroyDeviceInfoList(devinfo);
+ while (TRUE)
+ {
+ SERVER_START_REQ(enum_monitor)
+ {
+ req->index = 0;
+ if (!(status = wine_server_call(req)))
+ monitor = wine_server_ptr_handle(reply->handle);
+ }
+ SERVER_END_REQ;
+
+ if (status)
+ break;
+
+ SERVER_START_REQ(destroy_monitor)
+ {
+ req->handle = wine_server_obj_handle(monitor);
+ if (wine_server_call(req))
+ ERR("Failed to remove monitor.\n");
+ }
+ SERVER_END_REQ;
+ }
+
/* Clean up old adapter keys for reinitialization */
RegDeleteTreeW(video_hkey, NULL);
--
2.27.0
2
1
[PATCH 8/8] wined3d: Restore display modes for all outputs when doing mode restoration.
by Zhiyi Zhang 28 Oct '20
by Zhiyi Zhang 28 Oct '20
28 Oct '20
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d8/tests/device.c | 30 ++++++-------
dlls/d3d9/tests/device.c | 30 ++++++-------
dlls/ddraw/ddraw.c | 2 +-
dlls/ddraw/tests/ddraw1.c | 10 ++---
dlls/ddraw/tests/ddraw2.c | 10 ++---
dlls/ddraw/tests/ddraw4.c | 10 ++---
dlls/ddraw/tests/ddraw7.c | 10 ++---
dlls/dxgi/tests/dxgi.c | 14 +++---
dlls/wined3d/directx.c | 93 +++++++++++++++++++++++++--------------
dlls/wined3d/swapchain.c | 55 +++++++++++++----------
dlls/wined3d/wined3d.spec | 1 +
include/wine/wined3d.h | 1 +
12 files changed, 151 insertions(+), 115 deletions(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 8c7737f6601..80de1ec9dbb 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -4331,7 +4331,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
ok(ret, "Failed to get display mode.\n");
- todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
+ ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
&& devmode.dmPelsHeight == registry_mode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n",
registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
@@ -4411,7 +4411,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
@@ -4449,7 +4449,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
@@ -4535,15 +4535,15 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
old_devmode.dmPelsWidth, d3ddm.Width);
- todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
old_devmode.dmPelsHeight, d3ddm.Height);
refcount = IDirect3DDevice8_Release(device);
@@ -4571,15 +4571,15 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
old_devmode.dmPelsWidth, d3ddm.Width);
- todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
old_devmode.dmPelsHeight, d3ddm.Height);
ret = restore_display_modes(original_modes, display_count);
ok(ret, "Failed to restore display modes.\n");
@@ -4600,7 +4600,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -4610,7 +4610,7 @@ static void test_mode_change(void)
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
+ ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
d3ddm.Width, d3ddm.Height);
ret = restore_display_modes(original_modes, display_count);
@@ -4645,13 +4645,13 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
@@ -4686,13 +4686,13 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index d7b71152b03..bc9e1d32d11 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -5418,7 +5418,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
ok(ret, "Failed to get display mode.\n");
- todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
+ ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
&& devmode.dmPelsHeight == registry_mode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n",
registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
@@ -5498,7 +5498,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
@@ -5536,7 +5536,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
@@ -5622,15 +5622,15 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
old_devmode.dmPelsWidth, d3ddm.Width);
- todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
old_devmode.dmPelsHeight, d3ddm.Height);
refcount = IDirect3DDevice9_Release(device);
@@ -5658,15 +5658,15 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
old_devmode.dmPelsWidth, d3ddm.Width);
- todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
old_devmode.dmPelsHeight, d3ddm.Height);
ret = restore_display_modes(original_modes, display_count);
ok(ret, "Failed to restore display modes.\n");
@@ -5687,7 +5687,7 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -5697,7 +5697,7 @@ static void test_mode_change(void)
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
+ ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
d3ddm.Width, d3ddm.Height);
ret = restore_display_modes(original_modes, display_count);
@@ -5732,13 +5732,13 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
@@ -5773,13 +5773,13 @@ static void test_mode_change(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
- todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 11a16f8d535..f78d344c085 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -698,7 +698,7 @@ static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
return DDERR_NOEXCLUSIVEMODE;
}
- if (SUCCEEDED(hr = wined3d_output_set_display_mode(ddraw->wined3d_output, NULL)))
+ if (SUCCEEDED(hr = wined3d_restore_display_modes(ddraw->wined3d)))
{
ddraw->flags &= ~DDRAW_RESTORE_MODE;
if (ddraw->cooperative_level & DDSCL_EXCLUSIVE &&
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 783c1b961a0..e1a315f291f 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -3784,7 +3784,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3805,7 +3805,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3830,7 +3830,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -3860,7 +3860,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3891,7 +3891,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 23d3e0c1f02..849d510a349 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -3944,7 +3944,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3965,7 +3965,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3990,7 +3990,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -4020,7 +4020,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -4051,7 +4051,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 12cfbc3784f..56a4777add5 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -4172,7 +4172,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -4193,7 +4193,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -4218,7 +4218,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -4248,7 +4248,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -4279,7 +4279,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index c214cbc221e..c9ba50287be 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -3819,7 +3819,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3840,7 +3840,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3865,7 +3865,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -3895,7 +3895,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
@@ -3926,7 +3926,7 @@ static void test_coop_level_mode_set_multi(void)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 4d9677b3762..e6c8e0eb8c4 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -7097,7 +7097,7 @@ static void test_mode_change(IUnknown *device, BOOL is_d3d12)
ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
@@ -7196,16 +7196,16 @@ static void test_mode_change(IUnknown *device, BOOL is_d3d12)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
hr = IDXGIOutput_GetDesc(second_output, &output_desc);
ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
- todo_wine ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
+ ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
old_devmode.dmPelsWidth, "Expected width %u, got %u.\n", old_devmode.dmPelsWidth,
output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left);
- todo_wine ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
+ ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
old_devmode.dmPelsHeight, "Expected height %u, got %u.\n", old_devmode.dmPelsHeight,
output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top);
@@ -7228,7 +7228,7 @@ static void test_mode_change(IUnknown *device, BOOL is_d3d12)
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
- todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
"Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
@@ -7238,10 +7238,10 @@ static void test_mode_change(IUnknown *device, BOOL is_d3d12)
devmode2.dmPelsWidth, devmode2.dmPelsHeight);
hr = IDXGIOutput_GetDesc(second_output, &output_desc);
ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
- todo_wine ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
+ ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
devmode.dmPelsWidth, "Expected width %u, got %u.\n", devmode.dmPelsWidth,
output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left);
- todo_wine ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
+ ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
devmode.dmPelsHeight, "Expected height %u, got %u.\n", devmode.dmPelsHeight,
output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index c11fa22cc38..aa257de44ee 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1320,54 +1320,79 @@ HRESULT CDECL wined3d_output_get_display_mode(const struct wined3d_output *outpu
return WINED3D_OK;
}
+HRESULT CDECL wined3d_restore_display_modes(struct wined3d *wined3d)
+{
+ unsigned int adapter_idx, output_idx;
+ struct wined3d_adapter *adapter;
+ struct wined3d_output *output;
+ DEVMODEW devmode;
+ LONG ret;
+
+ TRACE("wined3d %p.\n", wined3d);
+
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ {
+ ERR("Failed to restore all outputs to their registry display settings, error %d.\n", ret);
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ for (adapter_idx = 0; adapter_idx < wined3d->adapter_count; ++adapter_idx)
+ {
+ adapter = wined3d->adapters[adapter_idx];
+ for (output_idx = 0; output_idx < adapter->output_count; ++output_idx)
+ {
+ output = &adapter->outputs[output_idx];
+
+ if (!EnumDisplaySettingsExW(output->device_name, ENUM_CURRENT_SETTINGS, &devmode, 0))
+ {
+ ERR("Failed to read the current display mode for %s.\n",
+ wine_dbgstr_w(output->device_name));
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ output->screen_format = pixelformat_for_depth(devmode.dmBitsPerPel);
+ }
+ }
+
+ return WINED3D_OK;
+}
+
HRESULT CDECL wined3d_output_set_display_mode(struct wined3d_output *output,
const struct wined3d_display_mode *mode)
{
+ enum wined3d_format_id new_format_id;
+ const struct wined3d_format *format;
DEVMODEW new_mode, current_mode;
LONG ret;
- enum wined3d_format_id new_format_id;
TRACE("output %p, mode %p.\n", output, mode);
+ TRACE("mode %ux%u@%u %s %#x.\n", mode->width, mode->height, mode->refresh_rate,
+ debug_d3dformat(mode->format_id), mode->scanline_ordering);
memset(&new_mode, 0, sizeof(new_mode));
new_mode.dmSize = sizeof(new_mode);
memset(¤t_mode, 0, sizeof(current_mode));
current_mode.dmSize = sizeof(current_mode);
- if (mode)
+
+ format = wined3d_get_format(output->adapter, mode->format_id, WINED3D_BIND_RENDER_TARGET);
+
+ new_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ new_mode.dmBitsPerPel = format->byte_count * CHAR_BIT;
+ new_mode.dmPelsWidth = mode->width;
+ new_mode.dmPelsHeight = mode->height;
+ new_mode.dmDisplayFrequency = mode->refresh_rate;
+ if (mode->refresh_rate)
+ new_mode.dmFields |= DM_DISPLAYFREQUENCY;
+ if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN)
{
- const struct wined3d_format *format;
-
- TRACE("mode %ux%u@%u %s %#x.\n", mode->width, mode->height, mode->refresh_rate,
- debug_d3dformat(mode->format_id), mode->scanline_ordering);
-
- format = wined3d_get_format(output->adapter, mode->format_id, WINED3D_BIND_RENDER_TARGET);
-
- new_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
- new_mode.dmBitsPerPel = format->byte_count * CHAR_BIT;
- new_mode.dmPelsWidth = mode->width;
- new_mode.dmPelsHeight = mode->height;
-
- new_mode.dmDisplayFrequency = mode->refresh_rate;
- if (mode->refresh_rate)
- new_mode.dmFields |= DM_DISPLAYFREQUENCY;
-
- if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN)
- {
- new_mode.dmFields |= DM_DISPLAYFLAGS;
- if (mode->scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED)
- new_mode.u2.dmDisplayFlags |= DM_INTERLACED;
- }
- new_format_id = mode->format_id;
- }
- else
- {
- if (!EnumDisplaySettingsW(output->device_name, ENUM_REGISTRY_SETTINGS, &new_mode))
- {
- ERR("Failed to read mode from registry.\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- new_format_id = pixelformat_for_depth(new_mode.dmBitsPerPel);
+ new_mode.dmFields |= DM_DISPLAYFLAGS;
+ if (mode->scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED)
+ new_mode.u2.dmDisplayFlags |= DM_INTERLACED;
}
+ new_format_id = mode->format_id;
/* Only change the mode if necessary. */
if (!EnumDisplaySettingsW(output->device_name, ENUM_CURRENT_SETTINGS, ¤t_mode))
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 847907c6d4c..7e46e5c6150 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -28,8 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain)
{
- struct wined3d_output *output;
- HRESULT hr = E_FAIL;
+ HRESULT hr;
UINT i;
TRACE("Destroying swapchain %p.\n", swapchain);
@@ -71,9 +70,7 @@ void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain)
{
if (swapchain->state.desc.auto_restore_display_mode)
{
- output = wined3d_swapchain_get_output(swapchain);
- if (!output || FAILED(hr = wined3d_output_set_display_mode(output,
- &swapchain->state.original_mode)))
+ if (FAILED(hr = wined3d_restore_display_modes(swapchain->device->wined3d)))
ERR("Failed to restore display mode, hr %#x.\n", hr);
if (swapchain->state.desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT)
@@ -1543,8 +1540,7 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc
err:
if (displaymode_set)
{
- if (FAILED(wined3d_output_set_display_mode(desc->output,
- &swapchain->state.original_mode)))
+ if (FAILED(wined3d_restore_display_modes(device->wined3d)))
ERR("Failed to restore display mode.\n");
}
@@ -1791,13 +1787,6 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
if (!(focus_messages = device->wined3d->flags & WINED3D_FOCUS_MESSAGES))
filter = wined3d_filter_messages(window, TRUE);
- output = wined3d_swapchain_get_output(swapchain);
- if (!output)
- {
- ERR("Failed to get output from swapchain %p.\n", swapchain);
- return;
- }
-
if (activate)
{
SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, 0, &screensaver_active, 0);
@@ -1813,6 +1802,13 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
*
* Guild Wars 1 wants a WINDOWPOSCHANGED message on the device window to
* resume drawing after a focus loss. */
+ output = wined3d_swapchain_get_output(swapchain);
+ if (!output)
+ {
+ ERR("Failed to get output from swapchain %p.\n", swapchain);
+ return;
+ }
+
if (SUCCEEDED(hr = wined3d_output_get_desc(output, &output_desc)))
SetWindowPos(window, NULL, output_desc.desktop_rect.left,
output_desc.desktop_rect.top, swapchain->state.desc.backbuffer_width,
@@ -1823,6 +1819,13 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
if (device->wined3d->flags & WINED3D_RESTORE_MODE_ON_ACTIVATE)
{
+ output = wined3d_swapchain_get_output(swapchain);
+ if (!output)
+ {
+ ERR("Failed to get output from swapchain %p.\n", swapchain);
+ return;
+ }
+
if (FAILED(hr = wined3d_output_set_display_mode(output,
&swapchain->state.d3d_mode)))
ERR("Failed to set display mode, hr %#x.\n", hr);
@@ -1839,8 +1842,8 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
device->restore_screensaver = FALSE;
}
- if (FAILED(hr = wined3d_output_set_display_mode(output, NULL)))
- ERR("Failed to set display mode, hr %#x.\n", hr);
+ if (FAILED(hr = wined3d_restore_display_modes(device->wined3d)))
+ ERR("Failed to restore display modes, hr %#x.\n", hr);
swapchain->reapply_mode = TRUE;
@@ -1974,9 +1977,9 @@ static HRESULT wined3d_swapchain_state_set_display_mode(struct wined3d_swapchain
if (output != state->desc.output)
{
- if (FAILED(hr = wined3d_output_set_display_mode(state->desc.output, &state->original_mode)))
+ if (FAILED(hr = wined3d_restore_display_modes(state->wined3d)))
{
- WARN("Failed to set display mode, hr %#x.\n", hr);
+ WARN("Failed to restore display modes, hr %#x.\n", hr);
return hr;
}
@@ -2199,6 +2202,9 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st
if (mode)
{
actual_mode = *mode;
+ if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, swapchain_desc->output,
+ &actual_mode)))
+ return hr;
}
else
{
@@ -2210,16 +2216,19 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st
actual_mode.format_id = adapter_format_from_backbuffer_format(swapchain_desc->output->adapter,
swapchain_desc->backbuffer_format);
actual_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+ if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, swapchain_desc->output,
+ &actual_mode)))
+ return hr;
}
else
{
- actual_mode = state->original_mode;
+ if (FAILED(hr = wined3d_restore_display_modes(state->wined3d)))
+ {
+ WARN("Failed to restore display modes for all outputs, hr %#x.\n", hr);
+ return hr;
+ }
}
}
-
- if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, swapchain_desc->output,
- &actual_mode)))
- return hr;
}
else
{
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index e4ff1161bce..44008119a8d 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -15,6 +15,7 @@
@ cdecl wined3d_incref(ptr)
@ cdecl wined3d_register_software_device(ptr ptr)
@ cdecl wined3d_register_window(ptr ptr ptr long)
+@ cdecl wined3d_restore_display_modes(ptr)
@ cdecl wined3d_unregister_windows(ptr)
@ cdecl wined3d_adapter_get_identifier(ptr long ptr)
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 62ea3960118..4a06b511211 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2313,6 +2313,7 @@ ULONG __cdecl wined3d_incref(struct wined3d *wined3d);
HRESULT __cdecl wined3d_register_software_device(struct wined3d *wined3d, void *init_function);
BOOL __cdecl wined3d_register_window(struct wined3d *wined3d, HWND window,
struct wined3d_device *device, unsigned int flags);
+HRESULT __cdecl wined3d_restore_display_modes(struct wined3d *wined3d);
void __cdecl wined3d_unregister_windows(struct wined3d *wined3d);
HRESULT __cdecl wined3d_adapter_get_identifier(const struct wined3d_adapter *adapter,
--
2.27.0
2
1
[PATCH 1/4] winex11.drv: Store monitor information in the wineserver for EnumDisplayMonitors().
by Zhiyi Zhang 28 Oct '20
by Zhiyi Zhang 28 Oct '20
28 Oct '20
Fix Office 2016/365 having a 640x480 main window.
Office 2016/365 hooks NtOpenKeyEx() and prevents access to SetupAPI device properties.
After failed to query monitor information from SetupAPI, EnumDisplayMonitors() reports
a fallback monitor of size 640x480.
As to why store the monitor information in wineserver, it seems the 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(a)codeweavers.com>
---
dlls/user32/sysparams.c | 53 ++++++++++
dlls/winex11.drv/display.c | 54 +++++++++--
server/Makefile.in | 1 +
server/display.c | 192 +++++++++++++++++++++++++++++++++++++
server/protocol.def | 35 +++++++
server/user.h | 11 +++
6 files changed, 340 insertions(+), 6 deletions(-)
create mode 100644 server/display.c
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c
index 1381f387e03..227d57b0e5c 100644
--- a/dlls/user32/sysparams.c
+++ b/dlls/user32/sysparams.c
@@ -46,6 +46,7 @@
#include "win.h"
#include "user_private.h"
#include "wine/gdi_driver.h"
+#include "wine/server.h"
#include "wine/asm.h"
#include "wine/debug.h"
@@ -3858,9 +3859,31 @@ fail:
BOOL CDECL nulldrv_GetMonitorInfo( HMONITOR handle, MONITORINFO *info )
{
UINT index = (UINT_PTR)handle - 1;
+ WCHAR adapter_name[CCHDEVICENAME];
TRACE("(%p, %p)\n", handle, info);
+ SERVER_START_REQ( get_monitor_info )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ wine_server_set_reply( req, adapter_name, sizeof(adapter_name) );
+ if (!wine_server_call( req ))
+ {
+ SetRect( &info->rcMonitor, reply->monitor_rect.left, reply->monitor_rect.top,
+ reply->monitor_rect.right, reply->monitor_rect.bottom );
+ SetRect( &info->rcWork, reply->work_rect.left, reply->work_rect.top,
+ reply->work_rect.right, reply->work_rect.bottom );
+ if (!IsRectEmpty( &info->rcMonitor ) && !info->rcMonitor.top && !info->rcMonitor.left)
+ info->dwFlags = MONITORINFOF_PRIMARY;
+ else
+ info->dwFlags = 0;
+ if (info->cbSize >= sizeof(MONITORINFOEXW))
+ lstrcpyW( ((MONITORINFOEXW *)info)->szDevice, adapter_name );
+ return TRUE;
+ }
+ }
+ SERVER_END_REQ;
+
/* Fallback to report one monitor */
if (handle == NULLDRV_DEFAULT_HMONITOR)
{
@@ -3874,7 +3897,10 @@ BOOL CDECL nulldrv_GetMonitorInfo( HMONITOR handle, MONITORINFO *info )
}
if (!update_monitor_cache())
+ {
+ SetLastError( ERROR_INVALID_MONITOR_HANDLE );
return FALSE;
+ }
EnterCriticalSection( &monitors_section );
if (index < monitor_count)
@@ -3995,11 +4021,38 @@ static BOOL CALLBACK enum_mon_callback( HMONITOR monitor, HDC hdc, LPRECT rect,
BOOL CDECL nulldrv_EnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp )
{
+ HMONITOR monitor = NULL;
RECT monitor_rect;
+ NTSTATUS status;
DWORD i = 0;
TRACE("(%p, %p, %p, 0x%lx)\n", hdc, rect, proc, lp);
+ while (TRUE)
+ {
+ SERVER_START_REQ( enum_monitor )
+ {
+ req->index = i;
+ if (!(status = wine_server_call( req )))
+ {
+ SetRect( &monitor_rect, reply->monitor_rect.left, reply->monitor_rect.top,
+ reply->monitor_rect.right, reply->monitor_rect.bottom );
+ monitor = wine_server_ptr_handle( reply->handle );
+ }
+ }
+ SERVER_END_REQ;
+
+ if (status)
+ break;
+
+ ++i;
+ if (!proc( monitor, hdc, &monitor_rect, lp ))
+ return FALSE;
+ }
+
+ if (i)
+ return TRUE;
+
if (update_monitor_cache())
{
while (TRUE)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index 0f61f9f7b2e..abc4f2a07cc 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -34,6 +34,7 @@
#define WIN32_NO_STATUS
#include "winternl.h"
#include "wine/debug.h"
+#include "wine/server.h"
#include "wine/unicode.h"
#include "x11drv.h"
@@ -47,7 +48,6 @@ DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1
DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_GPU_VULKAN_UUID, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5c, 2);
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 WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
@@ -586,6 +586,7 @@ static BOOL X11DRV_InitMonitor(HDEVINFO devinfo, const struct x11drv_monitor *mo
{
SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
WCHAR bufferW[MAX_PATH];
+ DWORD size;
HKEY hkey;
BOOL ret = FALSE;
@@ -624,16 +625,33 @@ static BOOL X11DRV_InitMonitor(HDEVINFO devinfo, const struct x11drv_monitor *mo
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, DEVPROP_TYPE_BINARY,
(const BYTE *)&monitor->rc_monitor, sizeof(monitor->rc_monitor), 0))
goto done;
- /* RcWork */
- if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, DEVPROP_TYPE_BINARY,
- (const BYTE *)&monitor->rc_work, sizeof(monitor->rc_work), 0))
- goto done;
/* Adapter name */
sprintfW(bufferW, adapter_name_fmtW, video_index + 1);
+ size = (strlenW(bufferW) + 1) * sizeof(WCHAR);
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING,
- (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR), 0))
+ (const BYTE *)bufferW, size, 0))
goto done;
+ /* EnumDisplayMonitors() doesn't enumerate mirrored replicas and inactive monitors */
+ if (monitor_index == 0 && monitor->state_flags & DISPLAY_DEVICE_ACTIVE)
+ {
+ SERVER_START_REQ(create_monitor)
+ {
+ req->monitor_rect.top = monitor->rc_monitor.top;
+ req->monitor_rect.left = monitor->rc_monitor.left;
+ req->monitor_rect.right = monitor->rc_monitor.right;
+ req->monitor_rect.bottom = monitor->rc_monitor.bottom;
+ req->work_rect.top = monitor->rc_work.top;
+ req->work_rect.left = monitor->rc_work.left;
+ req->work_rect.right = monitor->rc_work.right;
+ req->work_rect.bottom = monitor->rc_work.bottom;
+ wine_server_add_data(req, bufferW, size);
+ if (wine_server_call(req))
+ goto done;
+ }
+ SERVER_END_REQ;
+ }
+
ret = TRUE;
done:
if (!ret)
@@ -645,7 +663,9 @@ static void prepare_devices(HKEY video_hkey)
{
static const BOOL not_present = FALSE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HMONITOR monitor = NULL;
HDEVINFO devinfo;
+ NTSTATUS status;
DWORD i = 0;
/* Remove all monitors */
@@ -657,6 +677,28 @@ static void prepare_devices(HKEY video_hkey)
}
SetupDiDestroyDeviceInfoList(devinfo);
+ while (TRUE)
+ {
+ SERVER_START_REQ(enum_monitor)
+ {
+ req->index = 0;
+ if (!(status = wine_server_call(req)))
+ monitor = wine_server_ptr_handle(reply->handle);
+ }
+ SERVER_END_REQ;
+
+ if (status)
+ break;
+
+ SERVER_START_REQ(destroy_monitor)
+ {
+ req->handle = wine_server_obj_handle(monitor);
+ if (wine_server_call(req))
+ ERR("Failed to remove monitor.\n");
+ }
+ SERVER_END_REQ;
+ }
+
/* Clean up old adapter keys for reinitialization */
RegDeleteTreeW(video_hkey, NULL);
diff --git a/server/Makefile.in b/server/Makefile.in
index e90c5d1336c..af6cbc2b6f8 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -10,6 +10,7 @@ C_SRCS = \
console.c \
debugger.c \
device.c \
+ display.c \
directory.c \
event.c \
fd.c \
diff --git a/server/display.c b/server/display.c
new file mode 100644
index 00000000000..ebaa9925253
--- /dev/null
+++ b/server/display.c
@@ -0,0 +1,192 @@
+/*
+ * Server-side display device management
+ *
+ * Copyright (C) 2020 Zhiyi Zhang 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 "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winternl.h"
+
+#include "object.h"
+#include "handle.h"
+#include "request.h"
+#include "unicode.h"
+#include "user.h"
+
+static struct list monitor_list = LIST_INIT(monitor_list);
+
+static void monitor_dump( struct object *obj, int verbose );
+static void monitor_destroy( struct object *obj );
+
+static const struct object_ops monitor_ops =
+{
+ sizeof(struct monitor), /* size */
+ monitor_dump, /* dump */
+ no_get_type, /* get_type */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ no_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ no_get_full_name, /* get_full_name */
+ no_lookup_name, /* lookup_name */
+ no_link_name, /* link_name */
+ default_unlink_name, /* unlink_name */
+ no_open_file, /* open_file */
+ no_kernel_obj_list, /* get_kernel_obj_list */
+ no_close_handle, /* close_handle */
+ monitor_destroy /* destroy */
+};
+
+/* create a monitor */
+static struct monitor *create_monitor( const rectangle_t *monitor_rect,
+ const rectangle_t *work_rect,
+ const struct unicode_str *adapter_name )
+{
+ struct monitor *monitor;
+ obj_handle_t handle;
+
+ if ((monitor = alloc_object( &monitor_ops )))
+ {
+ if (!(monitor->adapter_name = memdup( adapter_name->str, adapter_name->len )))
+ {
+ release_object( monitor );
+ return NULL;
+ }
+ monitor->adapter_name_len = adapter_name->len;
+
+ if (!(handle = alloc_handle( current->process, monitor, 0, 0 )))
+ {
+ release_object( monitor );
+ return NULL;
+ }
+
+ if (!(monitor->handle = duplicate_handle( current->process, handle, NULL, 0, 0,
+ DUP_HANDLE_MAKE_GLOBAL )))
+ {
+ close_handle( current->process, handle );
+ release_object( monitor );
+ return NULL;
+ }
+
+ monitor->monitor_rect = *monitor_rect;
+ monitor->work_rect = *work_rect;
+ release_object( monitor );
+ close_handle( current->process, handle );
+ list_add_tail( &monitor_list, &monitor->entry );
+ }
+ return monitor;
+}
+
+static void monitor_dump( struct object *obj, int verbose )
+{
+ struct monitor *monitor = (struct monitor *)obj;
+ assert( obj->ops == &monitor_ops );
+ fprintf( stderr, "Monitor handle=%#x ", monitor->handle);
+ fprintf( stderr, "monitor_rect=(%d, %d, %d, %d) ", monitor->monitor_rect.left,
+ monitor->monitor_rect.top, monitor->monitor_rect.right, monitor->monitor_rect.bottom );
+ fprintf( stderr, "work_rect=(%d, %d, %d, %d) ", monitor->work_rect.left, monitor->work_rect.top,
+ monitor->work_rect.right, monitor->work_rect.bottom );
+ fprintf( stderr, "adapter_name=\"");
+ dump_strW( monitor->adapter_name, monitor->adapter_name_len, stderr, "\"\"" );
+ fprintf( stderr, "\"\n" );
+}
+
+static void monitor_destroy( struct object *obj )
+{
+ struct monitor *monitor = (struct monitor *)obj;
+
+ if (monitor->adapter_name)
+ free( monitor->adapter_name );
+ list_remove( &monitor->entry );
+}
+
+/* create a monitor */
+DECL_HANDLER(create_monitor)
+{
+ struct unicode_str adapter_name;
+ struct monitor *monitor;
+
+ adapter_name = get_req_unicode_str();
+ if ((monitor = create_monitor( &req->monitor_rect, &req->work_rect, &adapter_name )))
+ {
+ reply->handle = monitor->handle;
+ clear_error();
+ }
+}
+
+/* get information about a monitor */
+DECL_HANDLER(get_monitor_info)
+{
+ struct monitor *monitor;
+ struct object *obj;
+
+ if (!(obj = get_handle_obj( current->process, req->handle, 0, &monitor_ops )))
+ return;
+
+ monitor = (struct monitor *)obj;
+ reply->monitor_rect = monitor->monitor_rect;
+ reply->work_rect = monitor->work_rect;
+ set_reply_data( monitor->adapter_name, min(monitor->adapter_name_len, get_reply_max_size()) );
+ release_object( monitor );
+ clear_error();
+ return;
+}
+
+/* enumerate monitors */
+DECL_HANDLER(enum_monitor)
+{
+ struct monitor *monitor;
+ unsigned int index = 0;
+
+ LIST_FOR_EACH_ENTRY( monitor, &monitor_list, struct monitor, entry )
+ {
+ if (req->index > index++)
+ continue;
+
+ reply->handle = monitor->handle;
+ reply->monitor_rect = monitor->monitor_rect;
+ clear_error();
+ return;
+ }
+ set_error( STATUS_NO_MORE_ENTRIES );
+}
+
+/* destroy a monitor */
+DECL_HANDLER(destroy_monitor)
+{
+ struct object *obj;
+
+ if ((obj = get_handle_obj( current->process, req->handle, 0, &monitor_ops )))
+ {
+ close_handle( current->process, req->handle );
+ release_object( obj );
+ clear_error();
+ }
+}
diff --git a/server/protocol.def b/server/protocol.def
index 846d2e15602..93b8e783f85 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2667,6 +2667,41 @@ enum coords_relative
#define SET_USER_OBJECT_GET_FULL_NAME 2
+/* Create a monitor */
+(a)REQ(create_monitor)
+ rectangle_t monitor_rect; /* monitor rectangle */
+ rectangle_t work_rect; /* monitor work area rectangle */
+ VARARG(adapter,unicode_str); /* adapter name */
+(a)REPLY
+ obj_handle_t handle; /* handle to the object */
+(a)END
+
+
+/* Get monitor information */
+(a)REQ(get_monitor_info)
+ obj_handle_t handle; /* handle to the object */
+(a)REPLY
+ rectangle_t monitor_rect; /* monitor rectangle */
+ rectangle_t work_rect; /* monitor work area rectangle */
+ VARARG(adapter,unicode_str); /* adapter name */
+(a)END
+
+
+/* Enumerate monitors */
+(a)REQ(enum_monitor)
+ unsigned int index; /* current index */
+(a)REPLY
+ obj_handle_t handle; /* handle to the object */
+ rectangle_t monitor_rect; /* monitor rectangle */
+(a)END
+
+
+/* Destroy a monitor */
+(a)REQ(destroy_monitor)
+ obj_handle_t handle; /* handle to the monitor */
+(a)END
+
+
/* Register a hotkey */
@REQ(register_hotkey)
user_handle_t window; /* handle to the window */
diff --git a/server/user.h b/server/user.h
index 6267f3e2881..f986dcc3d58 100644
--- a/server/user.h
+++ b/server/user.h
@@ -79,6 +79,17 @@ struct desktop
unsigned char keystate[256]; /* asynchronous key state */
};
+struct monitor
+{
+ struct object obj; /* object header */
+ obj_handle_t handle; /* object handle */
+ struct list entry; /* entry in global monitor list */
+ rectangle_t monitor_rect; /* monitor rectangle */
+ rectangle_t work_rect; /* monitor work area rectangle */
+ WCHAR *adapter_name; /* adapter name */
+ data_size_t adapter_name_len; /* adapter name length */
+};
+
/* user handles functions */
extern user_handle_t alloc_user_handle( void *ptr, enum user_object type );
--
2.27.0
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/wrap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index 046a7fd5423..75bbb2c05c5 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -886,7 +886,7 @@ static void ME_WrapTextParagraph( ME_TextEditor *editor, ME_Context *c, ME_Parag
linespace = ME_GetParaLineSpace( c, para );
ME_BeginRow( &wc );
- run = &ME_FindItemFwd( para_get_di( para ), diRun )->member.run;
+ run = para_first_run( para );
while (run)
{
run = ME_WrapHandleRun( &wc, run );
--
2.23.0
1
0
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/undo.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index 72e3b74f4c8..d9c5d28d6dc 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -335,13 +335,11 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
case undo_set_para_fmt:
{
ME_Cursor tmp;
- ME_DisplayItem *para;
cursor_from_char_ofs( editor, undo->u.set_para_fmt.pos, &tmp );
- para = ME_FindItemBack(tmp.pRun, diParagraph);
- add_undo_set_para_fmt( editor, ¶->member.para );
- para->member.para.fmt = undo->u.set_para_fmt.fmt;
- para->member.para.border = undo->u.set_para_fmt.border;
- para_mark_rewrap( editor, ¶->member.para );
+ add_undo_set_para_fmt( editor, &tmp.pPara->member.para );
+ tmp.pPara->member.para.fmt = undo->u.set_para_fmt.fmt;
+ tmp.pPara->member.para.border = undo->u.set_para_fmt.border;
+ para_mark_rewrap( editor, &tmp.pPara->member.para );
break;
}
case undo_set_char_fmt:
--
2.23.0
1
0
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/writer.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 9e79eda274d..98ae352ab7b 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -1148,7 +1148,8 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream,
nChars -= nLen;
cursor.nOffset = 0;
- cursor.pRun = ME_FindItemFwd(cursor.pRun, diRun);
+ cursor.pRun = run_next_all_paras( &cursor.pRun->member.run ) ?
+ run_get_di( run_next_all_paras( &cursor.pRun->member.run ) ) : NULL;
}
heap_free(buffer);
--
2.23.0
1
0
28 Oct '20
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/paint.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index d3bbbc9d672..d15c47b72aa 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -846,7 +846,7 @@ static void draw_table_borders( ME_Context *c, ME_Paragraph *para )
rowY = c->pt.y + para->pt.y;
if (para->fmt.dwMask & PFM_SPACEBEFORE)
rowY += ME_twips2pointsY(c, para->fmt.dySpaceBefore);
- nHeight = ME_FindItemFwd( para_get_di( para ), diStartRow )->member.row.nHeight;
+ nHeight = para_first_row( para )->nHeight;
rowBottom = rowY + nHeight;
/* Draw horizontal lines */
--
2.23.0
1
0
[PATCH 1/5] riched20: Pass para ptrs to the various para selection functions.
by Huw Davies 28 Oct '20
by Huw Davies 28 Oct '20
28 Oct '20
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/caret.c | 2 +-
dlls/riched20/editor.c | 14 +++---
dlls/riched20/editor.h | 8 ++--
dlls/riched20/editstr.h | 2 +-
dlls/riched20/paint.c | 48 ++++++++++---------
dlls/riched20/para.c | 100 ++++++++++++++++++++--------------------
dlls/riched20/reader.c | 2 +-
7 files changed, 90 insertions(+), 86 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 47fe77df922..8af0f1de724 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -433,7 +433,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start,
continue;
}
}
- if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->fmt );
+ if (delete_all) editor_set_default_para_fmt( editor, &start_para->fmt );
return TRUE;
}
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 462245db233..d06693232ab 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -678,7 +678,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
{
PARAFORMAT2 fmt;
fmt.cbSize = sizeof(fmt);
- ME_GetSelectionParaFormat(info->editor, &fmt);
+ editor_get_selection_para_fmt( info->editor, &fmt );
info->fmt.dwMask |= PFM_STARTINDENT | PFM_OFFSET;
info->fmt.dxStartIndent = fmt.dxStartIndent;
info->fmt.dxOffset = fmt.dxOffset;
@@ -713,7 +713,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
{
PARAFORMAT2 fmt;
fmt.cbSize = sizeof(fmt);
- ME_GetSelectionParaFormat(info->editor, &fmt);
+ editor_get_selection_para_fmt( info->editor, &fmt );
memcpy(info->fmt.rgxTabs, fmt.rgxTabs,
fmt.cTabCount * sizeof(fmt.rgxTabs[0]));
info->fmt.cTabCount = fmt.cTabCount;
@@ -1637,7 +1637,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
ME_GetTextLength(editor), FALSE);
from = to = 0;
ME_ClearTempStyle(editor);
- ME_SetDefaultParaFormat(editor, &editor->pCursors[0].pPara->member.para.fmt);
+ editor_set_default_para_fmt( editor, &editor->pCursors[0].pPara->member.para.fmt );
}
@@ -2533,7 +2533,7 @@ static BOOL handle_enter(ME_TextEditor *editor)
ME_InsertTextFromCursor(editor, 0, &endl, 1,
editor->pCursors[0].pRun->member.run.style);
para = editor->pBuffer->pFirst->member.para.next_para;
- ME_SetDefaultParaFormat(editor, ¶->member.para.fmt);
+ editor_set_default_para_fmt( editor, ¶->member.para.fmt );
para->member.para.nFlags = 0;
para_mark_rewrap( editor, ¶->member.para );
editor->pCursors[0].pPara = para;
@@ -3131,7 +3131,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
ed->nUndoMode = umAddToUndo;
ed->nParagraphs = 1;
ed->nLastSelStart = ed->nLastSelEnd = 0;
- ed->pLastSelStartPara = ed->pLastSelEndPara = ed->pCursors[0].pPara;
+ ed->last_sel_start_para = ed->last_sel_end_para = &ed->pCursors[0].pPara->member.para;
ed->bHideSelection = FALSE;
ed->pfnWordBreak = NULL;
ed->lpOleCallback = NULL;
@@ -4027,14 +4027,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
}
case EM_SETPARAFORMAT:
{
- BOOL result = ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
+ BOOL result = editor_set_selection_para_fmt( editor, (PARAFORMAT2 *)lParam );
ME_WrapMarkedParagraphs(editor);
ME_UpdateScrollBar(editor);
ME_CommitUndo(editor);
return result;
}
case EM_GETPARAFORMAT:
- ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
+ editor_get_selection_para_fmt( editor, (PARAFORMAT2 *)lParam );
return ((PARAFORMAT2 *)lParam)->dwMask;
case EM_GETFIRSTVISIBLELINE:
{
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 1a2346854e7..ddb6d138957 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -204,15 +204,15 @@ void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, ME_
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN;
/* para.c */
+void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN;
+void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
+void editor_set_default_para_fmt(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
+BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN;
-void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) DECLSPEC_HIDDEN;
void ME_MakeFirstParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_DumpParaStyle(ME_Paragraph *s) DECLSPEC_HIDDEN;
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) DECLSPEC_HIDDEN;
-BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
-void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN;
-void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_Cell *para_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_destroy( ME_TextEditor *editor, ME_Paragraph *item ) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 8722890bf47..bd839afb0c0 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -407,7 +407,7 @@ typedef struct tagME_TextEditor
ME_UndoMode nUndoMode;
int nParagraphs;
int nLastSelStart, nLastSelEnd;
- ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
+ ME_Paragraph *last_sel_start_para, *last_sel_end_para;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
int nZoomNumerator, nZoomDenominator;
RECT prevClientRect;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 180307ae01b..d3bbbc9d672 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -1312,8 +1312,8 @@ void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor )
void
ME_InvalidateSelection(ME_TextEditor *editor)
{
- ME_DisplayItem *sel_start, *sel_end;
- ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL;
+ ME_Paragraph *sel_start, *sel_end;
+ ME_Paragraph *repaint_start = NULL, *repaint_end = NULL;
int nStart, nEnd;
int len = ME_GetTextLength(editor);
@@ -1323,41 +1323,47 @@ ME_InvalidateSelection(ME_TextEditor *editor)
if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd)
return;
ME_WrapMarkedParagraphs(editor);
- ME_GetSelectionParas(editor, &sel_start, &sel_end);
- assert(sel_start->type == diParagraph);
- assert(sel_end->type == diParagraph);
+ editor_get_selection_paras( editor, &sel_start, &sel_end );
+
/* last selection markers aren't always updated, which means
* they can point past the end of the document */
- if (editor->nLastSelStart > len || editor->nLastSelEnd > len) {
- repaint_start = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph);
- repaint_end = editor->pBuffer->pLast->member.para.prev_para;
- } else {
+ if (editor->nLastSelStart > len || editor->nLastSelEnd > len)
+ {
+ repaint_start = editor_first_para( editor );
+ repaint_end = para_prev( editor_end_para( editor ) );
+ }
+ else
+ {
/* if the start part of selection is being expanded or contracted... */
- if (nStart < editor->nLastSelStart) {
+ if (nStart < editor->nLastSelStart)
+ {
repaint_start = sel_start;
- repaint_end = editor->pLastSelStartPara;
- } else if (nStart > editor->nLastSelStart) {
- repaint_start = editor->pLastSelStartPara;
+ repaint_end = editor->last_sel_start_para;
+ }
+ else if (nStart > editor->nLastSelStart)
+ {
+ repaint_start = editor->last_sel_start_para;
repaint_end = sel_start;
}
/* if the end part of selection is being contracted or expanded... */
- if (nEnd < editor->nLastSelEnd) {
+ if (nEnd < editor->nLastSelEnd)
+ {
if (!repaint_start) repaint_start = sel_end;
- repaint_end = editor->pLastSelEndPara;
- } else if (nEnd > editor->nLastSelEnd) {
- if (!repaint_start) repaint_start = editor->pLastSelEndPara;
+ repaint_end = editor->last_sel_end_para;
+ }
+ else if (nEnd > editor->nLastSelEnd)
+ {
+ if (!repaint_start) repaint_start = editor->last_sel_end_para;
repaint_end = sel_end;
}
}
if (repaint_start)
- para_range_invalidate( editor, &repaint_start->member.para, &repaint_end->member.para );
+ para_range_invalidate( editor, repaint_start, repaint_end );
/* remember the last invalidated position */
ME_GetSelectionOfs(editor, &editor->nLastSelStart, &editor->nLastSelEnd);
- ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara);
- assert(editor->pLastSelStartPara->type == diParagraph);
- assert(editor->pLastSelEndPara->type == diParagraph);
+ editor_get_selection_paras( editor, &editor->last_sel_start_para, &editor->last_sel_end_para );
}
BOOL
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index c7a0e271510..4348530bbdb 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -33,7 +33,7 @@ static ME_Paragraph *para_create( ME_TextEditor *editor )
{
ME_DisplayItem *item = ME_MakeDI(diParagraph);
- ME_SetDefaultParaFormat(editor, &item->member.para.fmt);
+ editor_set_default_para_fmt( editor, &item->member.para.fmt );
item->member.para.nFlags = MEPF_REWRAP;
return &item->member.para;
@@ -459,7 +459,7 @@ static void para_num_clear_list( ME_TextEditor *editor, ME_Paragraph *para, cons
} while (para_num_same_list( ¶->fmt, orig_fmt ));
}
-static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt)
+static BOOL para_set_fmt( ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt )
{
PARAFORMAT2 copy;
DWORD dwMask;
@@ -782,10 +782,10 @@ ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_fir
ME_Remove( run_get_di( end_run ) );
ME_DestroyDisplayItem( run_get_di( end_run) );
- if (editor->pLastSelStartPara == para_get_di( next ))
- editor->pLastSelStartPara = para_get_di( para );
- if (editor->pLastSelEndPara == para_get_di( next ))
- editor->pLastSelEndPara = para_get_di( para );
+ if (editor->last_sel_start_para == next)
+ editor->last_sel_start_para = para;
+ if (editor->last_sel_end_para == next)
+ editor->last_sel_end_para = para;
para->next_para = next->next_para;
next->next_para->member.para.prev_para = para_get_di( para );
@@ -868,18 +868,18 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
#undef DUMP_EFFECT
}
-void
-ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
+void editor_get_selection_paras( ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end )
{
ME_Cursor *pEndCursor = &editor->pCursors[1];
- *para = editor->pCursors[0].pPara;
- *para_end = editor->pCursors[1].pPara;
+ *para = &editor->pCursors[0].pPara->member.para;
+ *para_end = &editor->pCursors[1].pPara->member.para;
if (*para == *para_end)
return;
- if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) {
- ME_DisplayItem *tmp = *para;
+ if ((*para_end)->nCharOfs < (*para)->nCharOfs)
+ {
+ ME_Paragraph *tmp = *para;
*para = *para_end;
*para_end = tmp;
@@ -889,79 +889,77 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte
/* The paragraph at the end of a non-empty selection isn't included
* if the selection ends at the start of the paragraph. */
if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset)
- *para_end = (*para_end)->member.para.prev_para;
+ *para_end = para_prev( *para_end );
}
-BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt)
+BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt )
{
- ME_DisplayItem *para, *para_end;
+ ME_Paragraph *para, *para_end;
- ME_GetSelectionParas(editor, ¶, ¶_end);
+ editor_get_selection_paras( editor, ¶, ¶_end );
- do {
- ME_SetParaFormat(editor, ¶->member.para, pFmt);
- if (para == para_end)
- break;
- para = para->member.para.next_para;
- } while(1);
+ do
+ {
+ para_set_fmt( editor, para, fmt );
+ if (para == para_end) break;
+ para = para_next( para );
+ } while(1);
- return TRUE;
+ return TRUE;
}
-static void ME_GetParaFormat(ME_TextEditor *editor,
- const ME_DisplayItem *para,
- PARAFORMAT2 *pFmt)
+static void para_copy_fmt( const ME_Paragraph *para, PARAFORMAT2 *fmt )
{
- UINT cbSize = pFmt->cbSize;
- if (pFmt->cbSize >= sizeof(PARAFORMAT2)) {
- *pFmt = para->member.para.fmt;
- } else {
- CopyMemory(pFmt, ¶->member.para.fmt, pFmt->cbSize);
- pFmt->dwMask &= PFM_ALL;
- }
- pFmt->cbSize = cbSize;
+ UINT size = fmt->cbSize;
+
+ if (fmt->cbSize >= sizeof(PARAFORMAT2))
+ *fmt = para->fmt;
+ else
+ {
+ memcpy( fmt, ¶->fmt, fmt->cbSize );
+ fmt->dwMask &= PFM_ALL;
+ }
+ fmt->cbSize = size;
}
-void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
+void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt )
{
- ME_DisplayItem *para, *para_end;
- PARAFORMAT2 *curFmt;
+ ME_Paragraph *para, *para_end;
- if (pFmt->cbSize < sizeof(PARAFORMAT))
+ if (fmt->cbSize < sizeof(PARAFORMAT))
{
- pFmt->dwMask = 0;
+ fmt->dwMask = 0;
return;
}
- ME_GetSelectionParas(editor, ¶, ¶_end);
+ editor_get_selection_paras( editor, ¶, ¶_end );
- ME_GetParaFormat(editor, para, pFmt);
+ para_copy_fmt( para, fmt );
/* Invalidate values that change across the selected paragraphs. */
while (para != para_end)
{
- para = para->member.para.next_para;
- curFmt = ¶->member.para.fmt;
+ para = para_next( para );
#define CHECK_FIELD(m, f) \
- if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m);
+ if (fmt->f != para->fmt.f) fmt->dwMask &= ~(m);
CHECK_FIELD(PFM_NUMBERING, wNumbering);
CHECK_FIELD(PFM_STARTINDENT, dxStartIndent);
CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent);
CHECK_FIELD(PFM_OFFSET, dxOffset);
CHECK_FIELD(PFM_ALIGNMENT, wAlignment);
- if (pFmt->dwMask & PFM_TABSTOPS)
+ if (fmt->dwMask & PFM_TABSTOPS)
{
- if (pFmt->cTabCount != para->member.para.fmt.cTabCount ||
- memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int)))
- pFmt->dwMask &= ~PFM_TABSTOPS;
+ if (fmt->cTabCount != para->fmt.cTabCount ||
+ memcmp(fmt->rgxTabs, para->fmt.rgxTabs, para->fmt.cTabCount * sizeof(int) ))
+ fmt->dwMask &= ~PFM_TABSTOPS;
}
- if (pFmt->cbSize >= sizeof(PARAFORMAT2))
+ if (fmt->cbSize >= sizeof(PARAFORMAT2))
{
- pFmt->dwMask &= ~((pFmt->wEffects ^ curFmt->wEffects) << 16);
+ fmt->dwMask &= ~((fmt->wEffects ^ para->fmt.wEffects) << 16);
CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore);
CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter);
CHECK_FIELD(PFM_LINESPACING, dyLineSpacing);
@@ -980,7 +978,7 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
}
}
-void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
+void editor_set_default_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *pFmt )
{
const PARAFORMAT2 *host_fmt;
HRESULT hr;
diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c
index dc551bf5841..e73b8b87e9d 100644
--- a/dlls/riched20/reader.c
+++ b/dlls/riched20/reader.c
@@ -2519,7 +2519,7 @@ static void SpecialChar (RTF_Info *info)
case rtfSect:
case rtfPar:
RTFFlushOutputBuffer(info);
- ME_SetSelectionParaFormat(info->editor, &info->fmt);
+ editor_set_selection_para_fmt( info->editor, &info->fmt );
memset(&info->fmt, 0, sizeof(info->fmt));
info->fmt.cbSize = sizeof(info->fmt);
RTFPutUnicodeChar (info, '\r');
--
2.23.0
1
0
Mostly to test that when doing mode restoration, all display outputs get restored to their display
settings in the registry, not just one output gets restored.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/ddraw/tests/ddraw1.c | 396 ++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw2.c | 397 +++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw4.c | 396 ++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw7.c | 396 ++++++++++++++++++++++++++++++++++++-
4 files changed, 1581 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 63791c5b606..783c1b961a0 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -265,6 +265,69 @@ static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
@@ -1301,6 +1364,14 @@ static void test_coop_level_threaded(void)
IDirectDraw_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2630,6 +2701,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw *ddraw;
@@ -2640,7 +2713,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2716,6 +2788,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2728,6 +2812,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3315,19 +3400,125 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
done:
expect_messages = NULL;
DestroyWindow(window);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3509,7 +3700,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 4b83230de1f..23d3e0c1f02 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -22,6 +22,7 @@
#define COBJMACROS
#include "wine/test.h"
+#include "wine/heap.h"
#include <limits.h>
#include <math.h>
#include "ddrawi.h"
@@ -261,6 +262,69 @@ static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -1458,6 +1522,14 @@ done:
if (ddraw) IDirectDraw2_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2694,6 +2766,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw2 *ddraw;
@@ -2704,7 +2778,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2780,6 +2853,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2792,6 +2877,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3472,21 +3558,127 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
done:
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw2 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3668,7 +3860,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 72aad35b1e1..12cfbc3784f 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -263,6 +263,69 @@ static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -1628,6 +1691,14 @@ static void test_texture_load_ckey(void)
IDirectDraw4_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2935,6 +3006,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface4 *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw4 *ddraw;
@@ -2945,7 +3018,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -3021,6 +3093,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -3033,6 +3117,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3709,20 +3794,126 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw4 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3897,7 +4088,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index e85b7d76369..c214cbc221e 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -102,6 +102,14 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
&& compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *iface)
{
IUnknown_AddRef(iface);
@@ -281,6 +289,69 @@ static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -2582,6 +2653,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface7 *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw7 *ddraw;
@@ -2592,7 +2665,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2668,6 +2740,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2680,6 +2764,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3356,20 +3441,126 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw7 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3544,7 +3735,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
--
2.27.0
2
1
[PATCH 1/8] d3d8/tests: Restore display modes at the end of test_wndproc().
by Zhiyi Zhang 28 Oct '20
by Zhiyi Zhang 28 Oct '20
28 Oct '20
test_wndproc() makes a series of ChangeDisplaySettings() calls that could make the current display
mode no longer match the registry display mode. Restore display modes at the end of test_wndproc()
so that other tests are not affected.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d8/tests/device.c | 72 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 4c567a47603..f48a51cee85 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -114,6 +114,69 @@ static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER8 *identifier)
return !strcmp(identifier->Driver, "d3d10warp.dll");
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND focus_window, const struct device_desc *desc)
{
D3DPRESENT_PARAMETERS present_parameters = {0};
@@ -2763,6 +2826,8 @@ static DWORD WINAPI wndproc_thread(void *param)
static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
+ DEVMODEW devmode, *original_modes = NULL;
+ unsigned int display_count = 0;
struct device_desc device_desc;
static WINDOWPOS windowpos;
IDirect3DDevice8 *device;
@@ -2777,7 +2842,6 @@ static void test_wndproc(void)
HRESULT hr;
D3DDISPLAYMODE d3ddm;
DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
- DEVMODEW devmode;
LONG change_ret, device_style;
BOOL ret;
@@ -2959,6 +3023,9 @@ static void test_wndproc(void)
return;
}
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
filter_messages = NULL;
expect_messages = NULL;
@@ -3361,6 +3428,9 @@ done:
DestroyWindow(device_window);
DestroyWindow(focus_window);
UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_wndproc_windowed(void)
--
2.27.0
2
1