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@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)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=81096
Your paranoid android.
=== debiant (32 bit report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (1031,26)-(2041,732).
=== debiant (32 bit French report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760).
=== debiant (32 bit Japanese:Japan report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706).
=== debiant (32 bit Chinese:China report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760).
=== debiant (build log) ===
The task timed out
=== debiant (32 bit WoW report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760).
=== debiant (64 bit WoW report) ===
ddraw: ddraw1.c:14162: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw1.c:14180: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw1.c:14187: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15054: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw2.c:15072: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw2.c:15079: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1017,761). ddraw4.c:18114: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1010,706). ddraw4.c:18132: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw4.c:18139: Test failed: Expect window rect (0,0)-(1024,768), got (0,1)-(1024,769). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (0,-8)-(1024,760). ddraw7.c:18376: Test failed: Expect window rect (0,0)-(1024,768), got (7,26)-(1031,794). ddraw7.c:18394: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760). ddraw7.c:18401: Test failed: Expect window rect (0,0)-(1024,768), got (1024,-8)-(2048,760).