ddraw/tests: Test display mode restoration.

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>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2020-10-30 14:45:26 +08:00 committed by Alexandre Julliard
parent ddf1967fd0
commit 1a4f2e23c0
4 changed files with 1581 additions and 4 deletions

View File

@ -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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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)

View File

@ -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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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)

View File

@ -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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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)

View File

@ -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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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, &registry_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)