ReactOS 0.4.16-dev-2491-g3dc6630
monitor.c
Go to the documentation of this file.
1/*
2 * Unit tests for monitor APIs
3 *
4 * Copyright 2005 Huw Davies
5 * Copyright 2008 Dmitry Timoshkov
6 * Copyright 2019-2022 Zhiyi Zhang for CodeWeavers
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include "ntstatus.h"
24#define WIN32_NO_STATUS
25
26#include "initguid.h"
27
28#include "wine/test.h"
29#include "winbase.h"
30#include "wingdi.h"
31#include "winuser.h"
32#include "winreg.h"
33#ifndef __REACTOS__
34#include "winternl.h"
35#endif
36#include "ddk/d3dkmthk.h"
37#include "setupapi.h"
38#include "shellscalingapi.h"
39#include "ntddvdeo.h"
40#include <stdio.h>
41#include <math.h>
42
43#ifdef __REACTOS__
44#include "devpropdef.h"
45
46typedef struct DISPLAYCONFIG_GET_SOURCE_DPI_SCALE
47{
49 int minRelativeScaleStep; /* Minimum scale step relative to the recommended scale */
50 int curRelativeScaleStep; /* Current scale step relative to the recommended scale */
51 int maxRelativeScaleStep; /* Maximum scale step relative to the recommended scale */
52} DISPLAYCONFIG_GET_SOURCE_DPI_SCALE;
53typedef struct DISPLAYCONFIG_SET_SOURCE_DPI_SCALE
54{
56 int relativeScaleStep; /* Target scale step relative to the recommended scale */
57} DISPLAYCONFIG_SET_SOURCE_DPI_SCALE;
58#endif
59
60DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1);
61DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2);
62
63static LONG (WINAPI *pGetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*);
64static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*);
65static LONG (WINAPI *pQueryDisplayConfig)(UINT32,UINT32*,DISPLAYCONFIG_PATH_INFO*,UINT32*,
67static LONG (WINAPI *pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
68static LONG (WINAPI *pDisplayConfigSetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
69static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
70static DPI_AWARENESS_CONTEXT (WINAPI *pGetThreadDpiAwarenessContext)(void);
71static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND);
72static UINT (WINAPI *pGetDpiForSystem)(void);
73static UINT (WINAPI *pGetDpiForWindow)(HWND);
74static BOOL (WINAPI *pLogicalToPhysicalPointForPerMonitorDPI)(HWND,POINT*);
75static BOOL (WINAPI *pPhysicalToLogicalPointForPerMonitorDPI)(HWND,POINT*);
76
77static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER*);
78static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME*);
79
80static void init_function_pointers(void)
81{
82 HMODULE user32 = GetModuleHandleA("user32.dll");
83 HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
84
85#define GET_PROC(module, func) \
86 p##func = (void *)GetProcAddress(module, #func); \
87 if (!p##func) \
88 trace("GetProcAddress(%s, %s) failed.\n", #module, #func);
89
95 GET_PROC(user32, SetThreadDpiAwarenessContext)
96 GET_PROC(user32, GetThreadDpiAwarenessContext)
100 GET_PROC(user32, LogicalToPhysicalPointForPerMonitorDPI)
101 GET_PROC(user32, PhysicalToLogicalPointForPerMonitorDPI)
102
103 GET_PROC(gdi32, D3DKMTCloseAdapter)
105
106#undef GET_PROC
107}
108
109static void flush_events(void)
110{
111 int diff = 1000;
112 DWORD time;
113 MSG msg;
114
115 time = GetTickCount() + diff;
116 while (diff > 0)
117 {
119 break;
120 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
122 diff = time - GetTickCount();
123 }
124}
125
126static unsigned int get_primary_dpi(void)
127{
128 DPI_AWARENESS_CONTEXT old_context;
129 UINT dpi_x = 0, dpi_y = 0;
130 POINT point = {0, 0};
131 HMONITOR monitor;
132
133 if (!pSetThreadDpiAwarenessContext || !pGetDpiForMonitorInternal)
134 return 0;
135
136 old_context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
137 monitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
138 pGetDpiForMonitorInternal(monitor, 0, &dpi_x, &dpi_y);
139 pSetThreadDpiAwarenessContext(old_context);
140 return dpi_y;
141}
142
143static int get_bitmap_stride(int width, int bpp)
144{
145 return ((width * bpp + 15) >> 3) & ~1;
146}
147
148static int adapter_count = 0;
149static int monitor_count = 0;
150
152{
153 char buffer[128];
154 int number;
155 int vendor_id;
156 int device_id;
157 int subsys_id;
158 int revision_id;
159 HDC hdc;
160
162
163 /* DeviceName */
164 ok(sscanf(device->DeviceName, "\\\\.\\DISPLAY%d", &number) == 1, "#%d: wrong DeviceName %s\n", index,
165 device->DeviceName);
166
167 /* DeviceKey */
168 /* \Device\Video? value in HLKM\HARDWARE\DEVICEMAP\VIDEO are not necessarily in order with adapter index.
169 * Check format only */
170 ok(sscanf(device->DeviceKey, "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\%[^\\]\\%04d", buffer, &number) == 2,
171 "#%d: wrong DeviceKey %s\n", index, device->DeviceKey);
172
173 /* DeviceString */
174 ok(broken(!*device->DeviceString) || /* XP on Testbot will return an empty string, whereas XP on real machine doesn't. Probably a bug in virtual adapter driver */
175 *device->DeviceString, "#%d: expect DeviceString not empty\n", index);
176
177 /* StateFlags */
179 {
180 /* Test creating DC */
181 hdc = CreateDCA(device->DeviceName, NULL, NULL, NULL);
182 ok(hdc != NULL, "#%d: failed to CreateDC(\"%s\") err=%ld\n", index, device->DeviceName, GetLastError());
183 DeleteDC(hdc);
184 }
185
186 /* DeviceID */
187 /* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this
188 * by changing the data and rerun EnumDisplayDevices. But it's difficult to find corresponding PCI device on
189 * userland. So here we check the expected format instead. */
190 if (flags & EDD_GET_DEVICE_INTERFACE_NAME)
191 ok(strlen(device->DeviceID) == 0 || /* vista+ */
192 sscanf(device->DeviceID, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
193 &vendor_id, &device_id, &subsys_id, &revision_id) == 4, /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
194 "#%d: got %s\n", index, device->DeviceID);
195 else
196 {
197 ok(broken(strlen(device->DeviceID) == 0) || /* XP on Testbot returns an empty string, whereas real machine doesn't */
198 sscanf(device->DeviceID, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", &vendor_id, &device_id, &subsys_id,
199 &revision_id) == 4, "#%d: wrong DeviceID %s\n", index, device->DeviceID);
200 }
201}
202
203static void test_enumdisplaydevices_monitor(int monitor_index, const char *adapter_name,
205{
206 static const char device_key_prefix[] = "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"
207 "\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\";
208 char monitor_name[32];
209 char buffer[128];
210 int number;
211
213
214 /* DeviceName */
215 lstrcpyA(monitor_name, adapter_name);
216 sprintf(monitor_name + strlen(monitor_name), "\\Monitor%d", monitor_index);
217 ok(!strcmp(monitor_name, device->DeviceName), "#%d: expect %s, got %s\n", monitor_index, monitor_name, device->DeviceName);
218
219 /* DeviceString */
220 ok(*device->DeviceString, "#%d: expect DeviceString not empty\n", monitor_index);
221
222 /* StateFlags */
223 ok(device->StateFlags <= (DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE),
224 "#%d wrong state %#lx\n", monitor_index, device->StateFlags);
225
226 /* DeviceID */
227 CharLowerA(device->DeviceID);
228 if (flags & EDD_GET_DEVICE_INTERFACE_NAME)
229 { /* HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\[monitor name]\[instance id] GUID_DEVINTERFACE_MONITOR
230 * ^ ^ ^
231 * Expect format \\?\DISPLAY#[monitor name]#[instance id]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} */
232 ok(strlen(device->DeviceID) == 0 || /* vista ~ win7 */
233 sscanf(device->DeviceID, "\\\\?\\display#%[^#]#%[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer, buffer) == 2 || /* win8+ */
234 sscanf(device->DeviceID, "monitor\\%[^\\]\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\%04d", buffer, &number) == 2, /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
235 "#%d: wrong DeviceID : %s\n", monitor_index, device->DeviceID);
236 }
237 else
238 {
239 /* Expect HarewareID value data + Driver value data in HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\[monitor name]\{instance} */
240 /* But we don't know which monitor instance this belongs to, so check format instead */
241 ok(sscanf(device->DeviceID, "monitor\\%[^\\]\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\%04d", buffer, &number) == 2,
242 "#%d: wrong DeviceID : %s\n", monitor_index, device->DeviceID);
243 }
244
245 /* DeviceKey */
246 lstrcpynA(buffer, device->DeviceKey, sizeof(device_key_prefix));
247 ok(!lstrcmpiA(buffer, device_key_prefix), "#%d: wrong DeviceKey : %s\n", monitor_index, device->DeviceKey);
248 ok(sscanf(device->DeviceKey + sizeof(device_key_prefix) - 1, "%04d", &number) == 1,
249 "#%d wrong DeviceKey : %s\n", monitor_index, device->DeviceKey);
250}
251
252static void test_enumdisplaydevices(void)
253{
254 static const DWORD flags[] = {0, EDD_GET_DEVICE_INTERFACE_NAME};
256 char adapter_name[32];
257 int number;
258 int flag_index;
259 int adapter_index;
260 int monitor_index;
261 BOOL ret;
262
263 /* Doesn't accept \\.\DISPLAY */
264 dd.cb = sizeof(dd);
265 ret = EnumDisplayDevicesA("\\\\.\\DISPLAY", 0, &dd, 0);
266 ok(!ret, "Expect failure\n");
267
268 /* Enumeration */
269 for (flag_index = 0; flag_index < ARRAY_SIZE(flags); flag_index++)
270 for (adapter_index = 0; EnumDisplayDevicesA(NULL, adapter_index, &dd, flags[flag_index]); adapter_index++)
271 {
272 lstrcpyA(adapter_name, dd.DeviceName);
273
274 if (sscanf(adapter_name, "\\\\.\\DISPLAYV%d", &number) == 1)
275 {
276 skip("Skipping software devices %s:%s\n", adapter_name, dd.DeviceString);
277 continue;
278 }
279
280 test_enumdisplaydevices_adapter(adapter_index, &dd, flags[flag_index]);
281
282 for (monitor_index = 0; EnumDisplayDevicesA(adapter_name, monitor_index, &dd, flags[flag_index]);
283 monitor_index++)
284 test_enumdisplaydevices_monitor(monitor_index, adapter_name, &dd, flags[flag_index]);
285 }
286
287 ok(adapter_count > 0, "Expect at least one adapter found\n");
288 /* XP on Testbot doesn't report a monitor, whereas XP on real machine does */
289 ok(broken(monitor_count == 0) || monitor_count > 0, "Expect at least one monitor found\n");
290}
291
293{
296};
297
298static const struct vid_mode vid_modes_test[] = {
300 {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY, 1},
301 {1024, 768, 0, 1, DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY, 0},
302 {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL , 0},
303 {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT , 1},
304 {1024, 768, 0, 0, DM_BITSPERPEL , 0},
305 {1024, 768, 0, 0, DM_DISPLAYFREQUENCY, 0},
306
307 {0, 0, 0, 0, DM_PELSWIDTH, 0},
308 {0, 0, 0, 0, DM_PELSHEIGHT, 0},
309
310 {1024, 768, 0, 0, DM_PELSWIDTH, 0},
311 {1024, 768, 0, 0, DM_PELSHEIGHT, 0},
312 { 0, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
313 {1024, 0, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
314
315 /* the following test succeeds under XP SP3
316 {0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0}
317 */
318};
319
321{
325};
326
327#define expect_dm(a, b, c) _expect_dm(__LINE__, a, b, c)
328static void _expect_dm(INT line, const DEVMODEA *expected, const CHAR *device, DWORD test)
329{
330 DEVMODEA dm;
331 BOOL ret;
332
333 memset(&dm, 0, sizeof(dm));
334 dm.dmSize = sizeof(dm);
335 SetLastError(0xdeadbeef);
337 ok_(__FILE__, line)(ret, "Device %s test %ld EnumDisplaySettingsA failed, error %#lx\n", device, test, GetLastError());
338
339 ok_(__FILE__, line)((dm.dmFields & expected->dmFields) == expected->dmFields,
340 "Device %s test %ld expect dmFields to contain %#lx, got %#lx\n", device, test, expected->dmFields, dm.dmFields);
341 ok_(__FILE__, line)(!(expected->dmFields & DM_BITSPERPEL) || dm.dmBitsPerPel == expected->dmBitsPerPel,
342 "Device %s test %ld expect dmBitsPerPel %lu, got %lu\n", device, test, expected->dmBitsPerPel, dm.dmBitsPerPel);
343 ok_(__FILE__, line)(!(expected->dmFields & DM_PELSWIDTH) || dm.dmPelsWidth == expected->dmPelsWidth,
344 "Device %s test %ld expect dmPelsWidth %lu, got %lu\n", device, test, expected->dmPelsWidth, dm.dmPelsWidth);
345 ok_(__FILE__, line)(!(expected->dmFields & DM_PELSHEIGHT) || dm.dmPelsHeight == expected->dmPelsHeight,
346 "Device %s test %ld expect dmPelsHeight %lu, got %lu\n", device, test, expected->dmPelsHeight, dm.dmPelsHeight);
347 ok_(__FILE__, line)(!(expected->dmFields & DM_POSITION) || dm.dmPosition.x == expected->dmPosition.x,
348 "Device %s test %ld expect dmPosition.x %ld, got %ld\n", device, test, expected->dmPosition.x, dm.dmPosition.x);
349 ok_(__FILE__, line)(!(expected->dmFields & DM_POSITION) || dm.dmPosition.y == expected->dmPosition.y,
350 "Device %s test %ld expect dmPosition.y %ld, got %ld\n", device, test, expected->dmPosition.y, dm.dmPosition.y);
351 ok_(__FILE__, line)(!(expected->dmFields & DM_DISPLAYFREQUENCY) ||
352 dm.dmDisplayFrequency == expected->dmDisplayFrequency,
353 "Device %s test %ld expect dmDisplayFrequency %lu, got %lu\n", device, test, expected->dmDisplayFrequency,
355 ok_(__FILE__, line)(!(expected->dmFields & DM_DISPLAYORIENTATION) ||
356 dm.dmDisplayOrientation == expected->dmDisplayOrientation,
357 "Device %s test %ld expect dmDisplayOrientation %ld, got %ld\n", device, test, expected->dmDisplayOrientation,
359}
360
361#define wait_for_dm(a, b, c) wait_for_dm_(__LINE__, a, b, c)
362static void wait_for_dm_(int line, const char *device, DWORD expected_width, DWORD expected_height)
363{
364 DEVMODEA dm;
365 BOOL ret;
366 int i;
367
368 for (i = 0; i < 50; ++i)
369 {
370 memset(&dm, 0, sizeof(dm));
371 dm.dmSize = sizeof(dm);
372 SetLastError(0xdeadbeef);
374 ok_(__FILE__, line)(ret, "Device %s EnumDisplaySettingsA failed, error %#lx\n", device, GetLastError());
375
376 if (dm.dmPelsWidth == expected_width && dm.dmPelsHeight == expected_height)
377 break;
378
379 Sleep(100);
380 }
381
382 ok_(__FILE__, line)(dm.dmPelsWidth == expected_width,
383 "Device %s expect dmPelsWidth %lu, got %lu\n", device, expected_width, dm.dmPelsWidth);
384 ok_(__FILE__, line)(dm.dmPelsHeight == expected_height,
385 "Device %s expect dmPelsHeight %lu, got %lu\n", device, expected_height, dm.dmPelsHeight);
386}
387
388static HANDLE test_child_process_ChangeDisplaySettingsEx(const char *argv0, const char *device, DWORD flags, const char *exit_event_name)
389{
390 static const char *cds_event_name = "test_child_process_cds_event";
392 char buffer[MAX_PATH];
394 DWORD wait_result;
395 HANDLE cds_event;
396 LONG res;
397
398 cds_event = CreateEventA(NULL, FALSE, FALSE, cds_event_name);
399 ok(!!cds_event, "CreateEventA failed, error %#lx\n", GetLastError());
400
401 memset(&startup, 0, sizeof(startup));
402 startup.cb = sizeof(startup);
403
404 snprintf(buffer, sizeof(buffer), "%s monitor fullscreen %s %#lx %s %s", argv0, device, flags,
405 cds_event_name, exit_event_name);
407 ok(res, "CreateProcessA returned unexpected %ld\n", res);
408 wait_result = WaitForSingleObject(cds_event, 5000);
409 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
410
411 CloseHandle(cds_event);
412 CloseHandle(info.hThread);
413
414 return info.hProcess;
415}
416
417static void test_ChangeDisplaySettingsEx(int argc, char **argv)
418{
419 static const DWORD registry_fields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
421 static const char *exit_event0_name = "test_cds_exit_event0";
422 static const char *exit_event1_name = "test_cds_exit_event1";
423 static const DWORD depths[] = {8, 16, 32};
425 UINT primary, device, test, mode;
426 HANDLE exit_event0, exit_event1;
427 UINT device_size, device_count;
428 struct device_info *devices;
429 HANDLE process0, process1;
430 DEVMODEA dm, dm2, dm3;
431 INT count, old_count;
433 DWORD wait_result;
434 POINTL position;
435 DEVMODEW dmW;
436 BOOL found;
437 LONG res;
438 int i;
439
440 /* Test invalid device names */
441 memset(&dm, 0, sizeof(dm));
442 dm.dmSize = sizeof(dm);
444 ok(res, "EnumDisplaySettingsA failed, error %#lx\n", GetLastError());
445
446 res = ChangeDisplaySettingsExA("invalid", &dm, NULL, CDS_TEST, NULL);
447 ok(res == DISP_CHANGE_BADPARAM, "ChangeDisplaySettingsA returned unexpected %ld\n", res);
448
449 res = ChangeDisplaySettingsExA("\\\\.\\DISPLAY0", &dm, NULL, CDS_TEST, NULL);
450 ok(res == DISP_CHANGE_BADPARAM, "ChangeDisplaySettingsA returned unexpected %ld\n", res);
451
452 res = ChangeDisplaySettingsExA("\\\\.\\DISPLAY1\\Monitor0", &dm, NULL, CDS_TEST, NULL);
453 ok(res == DISP_CHANGE_BADPARAM, "ChangeDisplaySettingsA returned unexpected %ld\n", res);
454
455 /* Test dmDriverExtra */
456 memset(&dm, 0, sizeof(dm));
457 dm.dmSize = sizeof(dm);
459 ok(res, "EnumDisplaySettingsA failed, error %#lx\n", GetLastError());
460
461 memset(&dmW, 0, sizeof(dmW));
462 dmW.dmSize = sizeof(dmW);
464 ok(res, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError());
465
466 /* ChangeDisplaySettingsA/W reset dmDriverExtra to 0 */
467 dm.dmDriverExtra = 1;
469 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsA returned unexpected %ld\n", res);
470 ok(dm.dmDriverExtra == 0, "ChangeDisplaySettingsA didn't reset dmDriverExtra to 0\n");
471
472 dmW.dmDriverExtra = 1;
474 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW returned unexpected %ld\n", res);
475 ok(dmW.dmDriverExtra == 0, "ChangeDisplaySettingsW didn't reset dmDriverExtra to 0\n");
476
477 /* ChangeDisplaySettingsExA/W do not modify dmDriverExtra */
478 dm.dmDriverExtra = 1;
480 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld\n", res);
481 ok(dm.dmDriverExtra == 1, "ChangeDisplaySettingsExA shouldn't change dmDriverExtra\n");
482
483 dmW.dmDriverExtra = 1;
485 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW returned unexpected %ld\n", res);
486 ok(dmW.dmDriverExtra == 1, "ChangeDisplaySettingsExW shouldn't change dmDriverExtra\n");
487
488 /* Test dmSize */
489 /* ChangeDisplaySettingsA/ExA report success even if dmSize is 0 */
490 memset(&dm, 0, sizeof(dm));
491 dm.dmSize = sizeof(dm);
493 ok(res, "EnumDisplaySettingsA failed, error %#lx\n", GetLastError());
494
495 dm.dmSize = 0;
497 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsA returned unexpected %ld\n", res);
498
499 dm.dmSize = 0;
501 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld\n", res);
502
503 /* dmSize for ChangeDisplaySettingsW/ExW needs to be at least FIELD_OFFSET(DEVMODEW, dmICMMethod) */
504 memset(&dmW, 0, sizeof(dmW));
505 dmW.dmSize = sizeof(dmW);
507 ok(res, "EnumDisplaySettingsW failed, error %#lx\n", GetLastError());
508
509 dmW.dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod) - 1;
511 ok(res == DISP_CHANGE_BADMODE, "ChangeDisplaySettingsW returned %ld, expect DISP_CHANGE_BADMODE\n", res);
512
513 dmW.dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod) - 1;
515 ok(res == DISP_CHANGE_BADMODE, "ChangeDisplaySettingsExW returned %ld, expect DISP_CHANGE_BADMODE\n", res);
516
517 dmW.dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
519 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW returned unexpected %ld\n", res);
520
521 dmW.dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
523 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW returned unexpected %ld\n", res);
524
525 /* Test clip rectangle after resolution changes */
526 /* GetClipCursor always returns result in physical pixels but GetSystemMetrics(SM_CX/CYVIRTUALSCREEN) are not.
527 * Set per-monitor aware context so that virtual screen rectangles are in physical pixels */
528 if (pSetThreadDpiAwarenessContext)
529 context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
530 memset(&dm, 0, sizeof(dm));
531 dm.dmSize = sizeof(dm);
532
533 for (i = 0; i < ARRAY_SIZE(vid_modes_test); i++)
534 {
537 dm.dmBitsPerPel = vid_modes_test[i].bpp;
539 dm.dmFields = vid_modes_test[i].fields;
541 ok(vid_modes_test[i].must_succeed ?
545 "Unexpected ChangeDisplaySettingsExA() return code for vid_modes_test[%d]: %ld\n", i, res);
546
548 {
549 RECT r, r1, virt;
550
552 if (IsRectEmpty(&virt)) /* NT4 doesn't have SM_CX/YVIRTUALSCREEN */
555
556 /* Resolution change resets clip rect */
557 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
558 ok(EqualRect(&r, &virt), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r));
559
560 if (!ClipCursor(NULL)) continue;
561 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
562 ok(EqualRect(&r, &virt), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r));
563
564 /* This should always work. Primary monitor is at (0,0) */
565 SetRect(&r1, 10, 10, 20, 20);
566 ok(ClipCursor(&r1), "ClipCursor() failed\n");
567 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
568 ok(EqualRect(&r, &r1), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r));
569 SetRect(&r1, 10, 10, 10, 10);
570 ok(ClipCursor(&r1), "ClipCursor() failed\n");
571 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
572 ok(EqualRect(&r, &r1), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r));
573 SetRect(&r1, 10, 10, 10, 9);
574 ok(!ClipCursor(&r1), "ClipCursor() succeeded\n");
575 /* Windows bug: further clipping fails once an empty rect is set, so we have to reset it */
577
578 SetRect(&r1, virt.left - 10, virt.top - 10, virt.right + 20, virt.bottom + 20);
579 ok(ClipCursor(&r1), "ClipCursor() failed\n");
580 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
581 ok(EqualRect(&r, &virt) || broken(EqualRect(&r, &r1)) /* win9x */,
582 "Invalid clip rect: %s\n", wine_dbgstr_rect(&r));
583 ClipCursor(&virt);
584 }
585 }
586 if (pSetThreadDpiAwarenessContext && context)
587 pSetThreadDpiAwarenessContext(context);
588
589 /* Save the original mode for all devices so that they can be restored at the end of tests */
590 device_count = 0;
591 device_size = 2;
592 devices = calloc(device_size, sizeof(*devices));
593 ok(devices != NULL, "Failed to allocate memory.\n");
594
595 primary = 0;
596 memset(&dd, 0, sizeof(dd));
597 dd.cb = sizeof(dd);
598 for (device = 0; EnumDisplayDevicesA(NULL, device, &dd, 0); ++device)
599 {
600 INT number;
601
602 /* Skip software devices */
603 if (sscanf(dd.DeviceName, "\\\\.\\DISPLAY%d", &number) != 1)
604 continue;
605
607 continue;
608
610 primary = device_count;
611
612 if (device_count >= device_size)
613 {
614 device_size *= 2;
615 devices = realloc(devices, device_size * sizeof(*devices));
616 ok(devices != NULL, "Failed to reallocate memory.\n");
617 }
618
619 devices[device_count].index = device;
620 lstrcpyA(devices[device_count].name, dd.DeviceName);
621 memset(&devices[device_count].original_mode, 0, sizeof(devices[device_count].original_mode));
622 devices[device_count].original_mode.dmSize = sizeof(devices[device_count].original_mode);
623 res = EnumDisplaySettingsA(dd.DeviceName, ENUM_CURRENT_SETTINGS, &devices[device_count].original_mode);
624 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", dd.DeviceName, GetLastError());
625 ++device_count;
626 }
627
628 /* Make the primary adapter first */
629 if (primary)
630 {
631 struct device_info tmp;
632 tmp = devices[0];
633 devices[0] = devices[primary];
634 devices[primary] = tmp;
635 }
636
637 /* Test detaching adapters */
638 /* Test that when there is only one adapter, it can't be detached */
639 if (device_count == 1)
640 {
641 old_count = GetSystemMetrics(SM_CMONITORS);
642
643 memset(&dm, 0, sizeof(dm));
644 dm.dmSize = sizeof(dm);
646 dm.dmPosition = devices[0].original_mode.dmPosition;
648 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[0].name, res);
651 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
652 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[0].name, res);
653
654 /* Check that the adapter is still attached */
655 dd.cb = sizeof(dd);
657 ok(res, "EnumDisplayDevicesA %s failed, error %#lx\n", devices[0].name, GetLastError());
658 ok(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP, "Expect device %s still attached.\n", devices[0].name);
659
661 ok(count == old_count, "Expect monitor count %d, got %d\n", old_count, count);
662
663 /* Restore registry settings */
667 broken(res == DISP_CHANGE_BADPARAM) || /* win10 */
668 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
669 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[0].name, res);
670 }
671
672 /* Test that only specifying DM_POSITION in dmFields is not enough to detach an adapter */
673 if (device_count >= 2)
674 {
675 old_count = GetSystemMetrics(SM_CMONITORS);
676
677 /* MSDN says set dmFields to DM_POSITION to detach, but DM_PELSWIDTH and DM_PELSHEIGHT are needed actually.
678 * To successfully detach adapters, settings have to be saved to the registry first, and then call
679 * ChangeDisplaySettingsExA(device, NULL, NULL, 0, NULL) to update settings. Otherwise on some older versions
680 * of Windows, e.g., XP and Win7, the adapter doesn't get detached */
681 memset(&dm, 0, sizeof(dm));
682 dm.dmSize = sizeof(dm);
684 dm.dmPosition = devices[1].original_mode.dmPosition;
686 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[1].name, res);
688 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[1].name, res);
689
690 dd.cb = sizeof(dd);
692 ok(res, "EnumDisplayDevicesA %s failed, error %#lx\n", devices[1].name, GetLastError());
693 ok(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP, "Expect device %s still attached.\n", devices[1].name);
694
696 ok(count == old_count, "Expect monitor count %d, got %d\n", old_count, count);
697 }
698
699 /* Test changing to a mode with depth set but with zero width and height */
700 for (device = 0; device < device_count; ++device)
701 {
702 for (test = 0; test < ARRAY_SIZE(depths); ++test)
703 {
704 /* Find the native resolution */
705 memset(&dm, 0, sizeof(dm));
706 memset(&dm2, 0, sizeof(dm2));
707 dm2.dmSize = sizeof(dm2);
708 for (mode = 0; EnumDisplaySettingsExA(devices[device].name, mode, &dm2, 0); ++mode)
709 {
710 if (dm2.dmBitsPerPel == depths[test]
711 && dm2.dmPelsWidth > dm.dmPelsWidth && dm2.dmPelsHeight > dm.dmPelsHeight)
712 dm = dm2;
713 }
714 if (dm.dmBitsPerPel != depths[test])
715 {
716 skip("Depth %lu is unsupported for %s.\n", depths[test], devices[device].name);
717 continue;
718 }
719
720 /* Find the second resolution */
721 memset(&dm2, 0, sizeof(dm2));
722 dm2.dmSize = sizeof(dm2);
723 for (mode = 0; EnumDisplaySettingsExA(devices[device].name, mode, &dm2, 0); ++mode)
724 {
725 if (dm2.dmBitsPerPel == depths[test]
726 && dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight)
727 break;
728 }
729 if (dm2.dmBitsPerPel != depths[test]
730 || dm2.dmPelsWidth == dm.dmPelsWidth || dm2.dmPelsHeight == dm.dmPelsHeight)
731 {
732 skip("Failed to find the second mode for %s.\n", devices[device].name);
733 continue;
734 }
735
736 /* Find the third resolution */
737 memset(&dm3, 0, sizeof(dm3));
738 dm3.dmSize = sizeof(dm3);
739 for (mode = 0; EnumDisplaySettingsExA(devices[device].name, mode, &dm3, 0); ++mode)
740 {
741 if (dm3.dmBitsPerPel == depths[test]
742 && dm3.dmPelsWidth != dm.dmPelsWidth && dm3.dmPelsHeight != dm.dmPelsHeight
743 && dm3.dmPelsWidth != dm2.dmPelsWidth && dm3.dmPelsHeight != dm2.dmPelsHeight)
744 break;
745 }
746 if (dm3.dmBitsPerPel != depths[test]
747 || dm3.dmPelsWidth == dm.dmPelsWidth || dm3.dmPelsHeight == dm.dmPelsHeight
748 || dm3.dmPelsWidth == dm2.dmPelsWidth || dm3.dmPelsHeight == dm2.dmPelsHeight)
749 {
750 skip("Failed to find the third mode for %s.\n", devices[device].name);
751 continue;
752 }
753
754 /* Change the current mode to the third mode first */
757 || broken(res == DISP_CHANGE_FAILED), /* Win8 TestBots */
758 "ChangeDisplaySettingsExA %s returned unexpected %ld.\n", devices[device].name, res);
760 {
761 win_skip("Failed to change display mode for %s.\n", devices[device].name);
762 continue;
763 }
764 flush_events();
766
767 /* Change the registry mode to the second mode */
770 || broken(res == DISP_CHANGE_BADFLAGS), /* Win10 32bit */
771 "ChangeDisplaySettingsExA %s returned unexpected %ld.\n", devices[device].name, res);
772
773 /* Change to a mode with depth set but with zero width and height */
774 memset(&dm, 0, sizeof(dm));
775 dm.dmSize = sizeof(dm);
777 dm.dmBitsPerPel = depths[test];
779 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
781 flush_events();
782
783 dd.cb = sizeof(dd);
785 ok(res, "EnumDisplayDevicesA %s failed, error %#lx.\n", devices[device].name, GetLastError());
786 ok(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP, "Expect %s attached.\n",
787 devices[device].name);
788
789 memset(&dm, 0, sizeof(dm));
790 dm.dmSize = sizeof(dm);
792 ok(res, "Device %s EnumDisplaySettingsA failed, error %#lx.\n", devices[device].name, GetLastError());
793 ok(dm.dmBitsPerPel == depths[test], "Device %s expect dmBitsPerPel %lu, got %lu.\n",
794 devices[device].name, depths[test], dm.dmBitsPerPel);
795 /* 2008 resets to the resolution in the registry. Newer versions of Windows doesn't
796 * change the current resolution */
797 ok(dm.dmPelsWidth == dm3.dmPelsWidth || broken(dm.dmPelsWidth == dm2.dmPelsWidth),
798 "Device %s expect dmPelsWidth %lu, got %lu.\n",
799 devices[device].name, dm3.dmPelsWidth, dm.dmPelsWidth);
801 "Device %s expect dmPelsHeight %lu, got %lu.\n",
802 devices[device].name, dm3.dmPelsHeight, dm.dmPelsHeight);
803 }
804 }
805
806 /* Detach all non-primary adapters to avoid position conflicts */
807 for (device = 1; device < device_count; ++device)
808 {
809 old_count = GetSystemMetrics(SM_CMONITORS);
810
811 memset(&dm, 0, sizeof(dm));
812 dm.dmSize = sizeof(dm);
814 dm.dmPosition = devices[device].original_mode.dmPosition;
816 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
818 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
819
820 dd.cb = sizeof(dd);
822 ok(res, "EnumDisplayDevicesA %s failed, error %#lx\n", devices[device].name, GetLastError());
823 ok(!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP), "Expect device %s detached.\n", devices[device].name);
824
826 ok(count == old_count - 1, "Expect monitor count %d, got %d\n", old_count - 1, count);
827 }
828
829 /* Test changing each adapter to different width, height, frequency and depth */
830 position.x = 0;
831 position.y = 0;
832 for (device = 0; device < device_count; ++device)
833 {
834 memset(&dm, 0, sizeof(dm));
835 dm.dmSize = sizeof(dm);
836 for (mode = 0; EnumDisplaySettingsExA(devices[device].name, mode, &dm, 0); ++mode)
837 {
838 if (mode == 0)
839 {
840 dm2 = dm;
841 }
842 else
843 {
844 found = FALSE;
845 if (dm2.dmPelsWidth && dm.dmPelsWidth != dm2.dmPelsWidth)
846 {
847 dm2.dmPelsWidth = 0;
848 found = TRUE;
849 }
850 if (dm2.dmPelsHeight && dm.dmPelsHeight != dm2.dmPelsHeight)
851 {
852 dm2.dmPelsHeight = 0;
853 found = TRUE;
854 }
856 {
857 dm2.dmDisplayFrequency = 0;
858 found = TRUE;
859 }
860 if (dm2.dmBitsPerPel && dm.dmBitsPerPel != dm2.dmBitsPerPel)
861 {
862 dm2.dmBitsPerPel = 0;
863 found = TRUE;
864 }
865
866 if (!dm2.dmPelsWidth && !dm2.dmPelsHeight && !dm2.dmDisplayFrequency
867 && !dm2.dmBitsPerPel)
868 break;
869
870 if (!found)
871 continue;
872 }
873
874 dm.dmPosition = position;
875 dm.dmFields |= DM_POSITION;
876 /* Reattach detached non-primary adapters, otherwise ChangeDisplaySettingsExA with only CDS_RESET fails */
877 if (mode == 0 && device)
878 {
880 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s mode %d returned unexpected %ld\n",
883 }
884 else
885 {
887 }
888
890 broken(res == DISP_CHANGE_FAILED), /* TestBots using VGA driver can't change to some modes */
891 "ChangeDisplaySettingsExA %s mode %d returned unexpected %ld\n", devices[device].name, mode, res);
893 {
894 win_skip("Failed to change %s to mode %d.\n", devices[device].name, mode);
895 continue;
896 }
897
898 flush_events();
900 }
901
902 /* Restore settings */
905 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
906 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
907
908 /* Place the next adapter to the right so that there is no position conflict */
909 memset(&dm, 0, sizeof(dm));
910 dm.dmSize = sizeof(dm);
912 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[device].name, GetLastError());
913 position.x = dm.dmPosition.x + dm.dmPelsWidth;
914 }
915
916 /* Test changing modes by saving settings to the registry first */
917 for (device = 0; device < device_count; ++device)
918 {
919 /* Place adapter to the right */
920 if (device == 0)
921 {
922 position.x = 0;
923 position.y = 0;
924 }
925 else
926 {
927 memset(&dm, 0, sizeof(dm));
928 dm.dmSize = sizeof(dm);
930 ok(res, "EnumDisplaySettingsA %s failed, error %#lx.\n", devices[device - 1].name, GetLastError());
931 position.x = dm.dmPosition.x + dm.dmPelsWidth;
932 }
933
934 memset(&dm, 0, sizeof(dm));
935 dm.dmSize = sizeof(dm);
937 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[device].name, GetLastError());
938 dm3 = dm;
939
940 /* Find a mode that's different from the current mode */
941 memset(&dm2, 0, sizeof(dm2));
942 dm2.dmSize = sizeof(dm2);
943 for (mode = 0; EnumDisplaySettingsA(devices[device].name, mode, &dm2); ++mode)
944 {
945 /* Use the same color depth because the win2008 TestBots are unable to change it */
946 if (dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight &&
947 dm2.dmBitsPerPel == dm.dmBitsPerPel)
948 break;
949 }
950 ok(dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight &&
951 dm2.dmBitsPerPel == dm.dmBitsPerPel, "Failed to find a different mode.\n");
952
953 /* Test normal operation */
954 dm = dm2;
955 dm.dmFields |= DM_POSITION;
956 dm.dmPosition = position;
959 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
960 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
963 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
964 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
966 {
967 win_skip("Failed to change mode for %s.\n", devices[device].name);
968 continue;
969 }
970
971 flush_events();
972 expect_dm(&dm, devices[device].name, 0);
973
974 /* Test specifying only position, width and height */
975 memset(&dm, 0, sizeof(dm));
976 dm.dmSize = sizeof(dm);
978 dm.dmPosition = position;
979 dm.dmPelsWidth = dm3.dmPelsWidth;
980 dm.dmPelsHeight = dm3.dmPelsHeight;
982 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %ld.\n", devices[device].name, res);
984 /* Win10 either returns failure here or retrieves outdated display settings until they're applied */
985 if (res)
986 {
987 ok((dm.dmFields & registry_fields) == registry_fields, "Got unexpected dmFields %#lx.\n", dm.dmFields);
988 ok(dm.dmPosition.x == position.x, "Expected dmPosition.x %ld, got %ld.\n", position.x, dm.dmPosition.x);
989 ok(dm.dmPosition.y == position.y, "Expected dmPosition.y %ld, got %ld.\n", position.y, dm.dmPosition.y);
990 ok(dm.dmPelsWidth == dm3.dmPelsWidth || broken(dm.dmPelsWidth == dm2.dmPelsWidth), /* Win10 */
991 "Expected dmPelsWidth %lu, got %lu.\n", dm3.dmPelsWidth, dm.dmPelsWidth);
992 ok(dm.dmPelsHeight == dm3.dmPelsHeight || broken(dm.dmPelsHeight == dm2.dmPelsHeight), /* Win10 */
993 "Expected dmPelsHeight %lu, got %lu.\n", dm3.dmPelsHeight, dm.dmPelsHeight);
994 ok(dm.dmBitsPerPel, "Expected dmBitsPerPel not zero.\n");
995 ok(dm.dmDisplayFrequency, "Expected dmDisplayFrequency not zero.\n");
996 }
997 else
998 {
999 win_skip("EnumDisplaySettingsA %s failed, error %#lx.\n", devices[device].name, GetLastError());
1000 }
1001
1003 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %ld.\n", devices[device].name, res);
1004 flush_events();
1005
1007 ok(res, "EnumDisplaySettingsA %s failed, error %#lx.\n", devices[device].name, GetLastError());
1008 ok((dm.dmFields & registry_fields) == registry_fields, "Got unexpected dmFields %#lx.\n", dm.dmFields);
1009 ok(dm.dmPosition.x == position.x, "Expected dmPosition.x %ld, got %ld.\n", position.x, dm.dmPosition.x);
1010 ok(dm.dmPosition.y == position.y, "Expected dmPosition.y %ld, got %ld.\n", position.y, dm.dmPosition.y);
1011 ok(dm.dmPelsWidth == dm3.dmPelsWidth, "Expected dmPelsWidth %lu, got %lu.\n", dm3.dmPelsWidth, dm.dmPelsWidth);
1012 ok(dm.dmPelsHeight == dm3.dmPelsHeight, "Expected dmPelsHeight %lu, got %lu.\n", dm3.dmPelsHeight,
1013 dm.dmPelsHeight);
1014 ok(dm.dmBitsPerPel, "Expected dmBitsPerPel not zero.\n");
1015 ok(dm.dmDisplayFrequency, "Expected dmDisplayFrequency not zero.\n");
1016
1017 expect_dm(&dm, devices[device].name, 0);
1018 }
1019
1020 /* Test dmPosition */
1021 /* First detach all adapters except for the primary and secondary adapters to avoid position conflicts */
1022 if (device_count >= 3)
1023 {
1024 for (device = 2; device < device_count; ++device)
1025 {
1026 memset(&dm, 0, sizeof(dm));
1027 dm.dmSize = sizeof(dm);
1029 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[device].name, GetLastError());
1030
1031 dm.dmPelsWidth = 0;
1032 dm.dmPelsHeight = 0;
1035 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
1036 }
1038 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld\n", res);
1039 }
1040
1041 if (device_count >= 2)
1042 {
1043 /* Query the primary adapter settings */
1044 memset(&dm, 0, sizeof(dm));
1045 dm.dmSize = sizeof(dm);
1047 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[0].name, GetLastError());
1048
1049 if (res)
1050 {
1051 /* Query the secondary adapter settings */
1052 memset(&dm2, 0, sizeof(dm2));
1053 dm2.dmSize = sizeof(dm2);
1055 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[1].name, GetLastError());
1056 }
1057
1058 if (res)
1059 {
1060 /* The secondary adapter should be to the right of the primary adapter */
1061 ok(dm2.dmPosition.x == dm.dmPosition.x + dm.dmPelsWidth,
1062 "Expected dm2.dmPosition.x %ld, got %ld.\n", dm.dmPosition.x + dm.dmPelsWidth,
1063 dm2.dmPosition.x);
1064 ok(dm2.dmPosition.y == dm.dmPosition.y, "Expected dm2.dmPosition.y %ld, got %ld.\n",
1065 dm.dmPosition.y, dm2.dmPosition.y);
1066
1067 /* Test position conflict */
1068 dm2.dmPosition.x = dm.dmPosition.x - dm2.dmPelsWidth + 1;
1069 dm2.dmPosition.y = dm.dmPosition.y;
1071 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[1].name, res);
1072
1073 /* Position is changed and automatically moved */
1074 memset(&dm2, 0, sizeof(dm2));
1075 dm2.dmSize = sizeof(dm2);
1077 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[1].name, GetLastError());
1078 ok(dm2.dmPosition.x == dm.dmPosition.x - dm2.dmPelsWidth,
1079 "Expected dmPosition.x %ld, got %ld.\n", dm.dmPosition.x - dm2.dmPelsWidth,
1080 dm2.dmPosition.x);
1081
1082 /* Test position with extra space. The extra space will be removed */
1083 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth + 1;
1084 dm2.dmPosition.y = dm.dmPosition.y;
1086 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[1].name, res);
1087
1088 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth;
1089 expect_dm(&dm2, devices[1].name, 0);
1090
1091 /* Test placing the secondary adapter to all sides of the primary adapter */
1092 for (test = 0; test < 8; ++test)
1093 {
1094 switch (test)
1095 {
1096 /* Bottom side with x offset */
1097 case 0:
1098 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth / 2;
1099 dm2.dmPosition.y = dm.dmPosition.y + dm.dmPelsHeight;
1100 break;
1101 /* Left side with y offset */
1102 case 1:
1103 dm2.dmPosition.x = dm.dmPosition.x - dm2.dmPelsWidth;
1104 dm2.dmPosition.y = dm.dmPosition.y + dm.dmPelsHeight / 2;
1105 break;
1106 /* Top side with x offset */
1107 case 2:
1108 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth / 2;
1109 dm2.dmPosition.y = dm.dmPosition.y - dm2.dmPelsHeight;
1110 break;
1111 /* Right side with y offset */
1112 case 3:
1113 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth;
1114 dm2.dmPosition.y = dm.dmPosition.y + dm.dmPelsHeight / 2;
1115 break;
1116 /* Bottom side with the same x */
1117 case 4:
1118 dm2.dmPosition.x = dm.dmPosition.x;
1119 dm2.dmPosition.y = dm.dmPosition.y + dm.dmPelsHeight;
1120 break;
1121 /* Left side with the same y */
1122 case 5:
1123 dm2.dmPosition.x = dm.dmPosition.x - dm2.dmPelsWidth;
1124 dm2.dmPosition.y = dm.dmPosition.y;
1125 break;
1126 /* Top side with the same x */
1127 case 6:
1128 dm2.dmPosition.x = dm.dmPosition.x;
1129 dm2.dmPosition.y = dm.dmPosition.y - dm2.dmPelsHeight;
1130 break;
1131 /* Right side with the same y */
1132 case 7:
1133 dm2.dmPosition.x = dm.dmPosition.x + dm.dmPelsWidth;
1134 dm2.dmPosition.y = dm.dmPosition.y;
1135 break;
1136 }
1137
1139 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s test %d returned unexpected %ld\n",
1140 devices[1].name, test, res);
1142 {
1143 win_skip("ChangeDisplaySettingsExA %s test %d returned unexpected %ld.\n", devices[1].name, test, res);
1144 continue;
1145 }
1146
1147 flush_events();
1148 expect_dm(&dm2, devices[1].name, test);
1149 }
1150
1151 /* Test automatic position update when other adapters change resolution */
1152 /* Find a mode that's different from the current mode */
1153 memset(&dm2, 0, sizeof(dm2));
1154 dm2.dmSize = sizeof(dm2);
1155 for (mode = 0; EnumDisplaySettingsA(devices[0].name, mode, &dm2); ++mode)
1156 {
1157 if (dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight)
1158 break;
1159 }
1160 ok(dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight, "Failed to find a different mode.\n");
1161
1162 /* Change the primary adapter to a different mode */
1163 dm = dm2;
1165 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[0].name, res);
1166
1167 /* Now the position of the second adapter should be changed */
1168 memset(&dm2, 0, sizeof(dm2));
1169 dm2.dmSize = sizeof(dm2);
1171 ok(res, "EnumDisplaySettingsA %s failed, error %#lx\n", devices[1].name, GetLastError());
1172 ok(dm2.dmPosition.x == dm.dmPelsWidth, "Expect dmPosition.x %ld, got %ld\n",
1173 dm.dmPelsWidth, dm2.dmPosition.x);
1174 }
1175 else
1176 {
1177 win_skip("EnumDisplaySettingsA failed\n");
1178 }
1179 }
1180
1181 /* Test changing each adapter to every supported display orientation */
1182 for (device = 0; device < device_count; ++device)
1183 {
1184 memset(&dm, 0, sizeof(dm));
1185 dm.dmSize = sizeof(dm);
1187 ok(res, "EnumDisplaySettingsA %s failed, error %#lx.\n", devices[device].name, GetLastError());
1188
1189 memset(&dm2, 0, sizeof(dm2));
1190 dm2.dmSize = sizeof(dm2);
1191 for (mode = 0; EnumDisplaySettingsExA(devices[device].name, mode, &dm2, EDS_ROTATEDMODE); ++mode)
1192 {
1194 continue;
1195
1197 && (dm2.dmPelsWidth != dm.dmPelsWidth || dm2.dmPelsHeight != dm.dmPelsHeight))
1198 continue;
1199
1201 && (dm2.dmPelsWidth != dm.dmPelsHeight || dm2.dmPelsHeight != dm.dmPelsWidth))
1202 continue;
1203
1206 {
1207 win_skip("Failed to change %s to mode %d.\n", devices[device].name, mode);
1208 continue;
1209 }
1210 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s mode %d returned unexpected %ld.\n",
1212 flush_events();
1213 expect_dm(&dm2, devices[device].name, mode);
1214
1215 /* EnumDisplaySettingsEx without EDS_ROTATEDMODE reports modes with current orientation */
1216 memset(&dm3, 0, sizeof(dm3));
1217 dm3.dmSize = sizeof(dm3);
1218 for (i = 0; EnumDisplaySettingsExA(devices[device].name, i, &dm3, 0); ++i)
1219 {
1221 "Expected %s display mode %d orientation %ld, got %ld.\n",
1223 }
1224 ok(i > 0, "Expected at least one display mode found.\n");
1225
1226 if (device == 0)
1227 {
1228 ok(GetSystemMetrics(SM_CXSCREEN) == dm2.dmPelsWidth, "Expected %ld, got %d.\n",
1230 ok(GetSystemMetrics(SM_CYSCREEN) == dm2.dmPelsHeight, "Expected %ld, got %d.\n",
1232 }
1233
1234 if (device_count == 1)
1235 {
1236 ok(GetSystemMetrics(SM_CXVIRTUALSCREEN) == dm2.dmPelsWidth, "Expected %ld, got %d.\n",
1238 ok(GetSystemMetrics(SM_CYVIRTUALSCREEN) == dm2.dmPelsHeight, "Expected %ld, got %d.\n",
1240 }
1241 }
1242 ok(mode > 0, "Expected at least one display mode found.\n");
1243 }
1244
1245 /* Restore all adapters to the current registry settings */
1248 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
1249 "ChangeDisplaySettingsExA returned unexpected %ld\n", res);
1250
1251 if (res == DISP_CHANGE_FAILED)
1252 {
1253 win_skip("Failed to restore dispay mode.\n");
1254 }
1255 else if (!device_count)
1256 {
1257 win_skip("No suitable devices found.\n");
1258 }
1259 else
1260 {
1261 memset(&dm, 0, sizeof(dm));
1262 dm.dmSize = sizeof(dm);
1264
1265 exit_event0 = CreateEventA(NULL, FALSE, FALSE, exit_event0_name);
1266 ok(!!exit_event0, "CreateEventA failed, error %#lx\n", GetLastError());
1267 exit_event1 = CreateEventA(NULL, FALSE, FALSE, exit_event1_name);
1268 ok(!!exit_event1, "CreateEventA failed, error %#lx\n", GetLastError());
1269
1270 /* Test that if the most recent ChangeDisplaySettingsEx call had
1271 * CDS_FULLSCREEN set, then the settings are restored when the caller
1272 * process exits */
1273
1274 process0 = test_child_process_ChangeDisplaySettingsEx(argv[0], devices[0].name, CDS_FULLSCREEN, exit_event0_name);
1276
1277 /* Verify that the settings are restored to the current registry settings */
1278 for (device = 0; device < device_count; ++device)
1279 {
1280 dm.dmPelsWidth = 800;
1281 dm.dmPelsHeight = 600;
1283 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %ld.\n", devices[device].name, res);
1284 }
1285
1286 SetEvent(exit_event0);
1287 wait_result = WaitForSingleObject(process0, 5000);
1288 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1289
1290 Sleep(100);
1291
1292 dm.dmPelsWidth = 640;
1293 dm.dmPelsHeight = 480;
1294 expect_dm(&dm, devices[0].name, 0);
1295
1296 SetEvent(exit_event1);
1297 wait_result = WaitForSingleObject(process1, 5000);
1298 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1299
1300 wait_for_dm(devices[0].name, 800, 600);
1301
1303 CloseHandle(process0);
1304
1305 /* Test processes exiting in reverse order */
1306
1307 process0 = test_child_process_ChangeDisplaySettingsEx(argv[0], devices[0].name, CDS_FULLSCREEN, exit_event0_name);
1309
1310 SetEvent(exit_event1);
1311 wait_result = WaitForSingleObject(process1, 5000);
1312 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1313
1314 wait_for_dm(devices[0].name, 800, 600);
1315
1316 SetEvent(exit_event0);
1317 wait_result = WaitForSingleObject(process0, 5000);
1318 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1319
1321 CloseHandle(process0);
1322
1323 /* Test that ChangeDisplaySettingsEx without CDS_FULLSCREEN cancels the restoration */
1324
1325 process0 = test_child_process_ChangeDisplaySettingsEx(argv[0], devices[0].name, CDS_FULLSCREEN, exit_event0_name);
1327
1328 SetEvent(exit_event0);
1329 wait_result = WaitForSingleObject(process0, 5000);
1330 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1331
1332 Sleep(100);
1333
1334 dm.dmPelsWidth = 640;
1335 dm.dmPelsHeight = 480;
1336 expect_dm(&dm, devices[0].name, 0);
1337
1338 SetEvent(exit_event1);
1339 wait_result = WaitForSingleObject(process1, 5000);
1340 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1341
1342 Sleep(100);
1343
1344 dm.dmPelsWidth = 640;
1345 dm.dmPelsHeight = 480;
1346 expect_dm(&dm, devices[0].name, 0);
1347
1349 CloseHandle(process0);
1350
1351 /* Test processes exiting in reverse order */
1352
1353 process0 = test_child_process_ChangeDisplaySettingsEx(argv[0], devices[0].name, CDS_FULLSCREEN, exit_event0_name);
1355
1356 SetEvent(exit_event1);
1357 wait_result = WaitForSingleObject(process1, 5000);
1358 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1359
1360 Sleep(100);
1361
1362 dm.dmPelsWidth = 640;
1363 dm.dmPelsHeight = 480;
1364 expect_dm(&dm, devices[0].name, 0);
1365
1366 SetEvent(exit_event0);
1367 wait_result = WaitForSingleObject(process0, 5000);
1368 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1369
1370 Sleep(100);
1371
1372 dm.dmPelsWidth = 640;
1373 dm.dmPelsHeight = 480;
1374 expect_dm(&dm, devices[0].name, 0);
1375
1377 CloseHandle(process0);
1378
1379 if (device_count < 2)
1380 {
1381 skip("Only one device found.\n");
1382 }
1383 else
1384 {
1385 /* Test that the settings are restored for all devices, regardless of
1386 * the process that changed them */
1387
1388 dm.dmPelsWidth = 640;
1389 dm.dmPelsHeight = 480;
1391 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %ld.\n", devices[1].name, res);
1392
1393 process0 = test_child_process_ChangeDisplaySettingsEx(argv[0], devices[0].name, CDS_FULLSCREEN, exit_event0_name);
1394
1395 SetEvent(exit_event0);
1396 wait_result = WaitForSingleObject(process0, 5000);
1397 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
1398
1399 wait_for_dm(devices[0].name, 800, 600);
1400 wait_for_dm(devices[1].name, 800, 600);
1401
1402 CloseHandle(process0);
1403 }
1404
1405 CloseHandle(exit_event1);
1406 CloseHandle(exit_event0);
1407 }
1408
1409 /* Restore all adapters to their original settings */
1410 for (device = 0; device < device_count; ++device)
1411 {
1415 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
1416 "ChangeDisplaySettingsExA %s returned unexpected %ld\n", devices[device].name, res);
1417 }
1420 broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */
1421 "ChangeDisplaySettingsExA returned unexpected %ld\n", res);
1422 for (device = 0; device < device_count; ++device)
1424
1425 free(devices);
1426}
1427
1428static void test_monitors(void)
1429{
1430 HMONITOR monitor, primary, nearest;
1431 POINT pt;
1432 RECT rc;
1434 MONITORINFOEXA miexa;
1435 MONITORINFOEXW miexw;
1436 BOOL ret;
1437 DWORD i;
1438
1439 static const struct
1440 {
1441 DWORD cbSize;
1442 BOOL ret;
1443 } testdatami[] = {
1444 {0, FALSE},
1445 {sizeof(MONITORINFO)+1, FALSE},
1446 {sizeof(MONITORINFO)-1, FALSE},
1447 {sizeof(MONITORINFO), TRUE},
1448 {-1, FALSE},
1449 {0xdeadbeef, FALSE},
1450 },
1451 testdatamiexa[] = {
1452 {0, FALSE},
1453 {sizeof(MONITORINFOEXA)+1, FALSE},
1454 {sizeof(MONITORINFOEXA)-1, FALSE},
1455 {sizeof(MONITORINFOEXA), TRUE},
1456 {-1, FALSE},
1457 {0xdeadbeef, FALSE},
1458 },
1459 testdatamiexw[] = {
1460 {0, FALSE},
1461 {sizeof(MONITORINFOEXW)+1, FALSE},
1462 {sizeof(MONITORINFOEXW)-1, FALSE},
1463 {sizeof(MONITORINFOEXW), TRUE},
1464 {-1, FALSE},
1465 {0xdeadbeef, FALSE},
1466 };
1467
1468 pt.x = pt.y = 0;
1469 primary = MonitorFromPoint( pt, MONITOR_DEFAULTTOPRIMARY );
1470 ok( primary != 0, "couldn't get primary monitor\n" );
1471
1472 monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTONULL );
1473 ok( !monitor, "got %p, should not get a monitor for an invalid window\n", monitor );
1474 monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
1475 ok( monitor == primary, "got %p, should get primary %p for MONITOR_DEFAULTTOPRIMARY\n", monitor, primary );
1476 monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTONEAREST );
1477 ok( monitor == primary, "got %p, should get primary %p for MONITOR_DEFAULTTONEAREST\n", monitor, primary );
1478
1479 SetRect( &rc, 0, 0, 1, 1 );
1480 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1481 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1482
1483 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
1484 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1485
1486 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
1487 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1488
1489 /* Empty rect at 0,0 is considered inside the primary monitor */
1490 SetRect( &rc, 0, 0, -1, -1 );
1491 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1492 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1493
1494 /* Even if there is a monitor left of the primary, the primary will have the most overlapping area */
1495 SetRect( &rc, -1, 0, 2, 1 );
1496 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1497 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1498
1499 /* But the width of the rect doesn't matter if it's empty. */
1500 SetRect( &rc, -1, 0, 2, -1 );
1501 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1502 ok( monitor != primary, "got primary %p\n", monitor );
1503
1504 /* Search for a monitor that has no others equally near to (left, top-1) */
1505 SetRect( &rc, -1, -2, 2, 0 );
1506 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1507 nearest = primary;
1508 while (monitor != NULL)
1509 {
1510 ok( monitor != primary, "got primary %p\n", monitor );
1511 nearest = monitor;
1512 mi.cbSize = sizeof(mi);
1513 ret = GetMonitorInfoA( monitor, &mi );
1514 ok( ret, "GetMonitorInfo failed\n" );
1516 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1517 }
1518
1519 /* tests for cbSize in MONITORINFO */
1520 monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
1521 for (i = 0; i < ARRAY_SIZE(testdatami); i++)
1522 {
1523 memset( &mi, 0, sizeof(mi) );
1524 mi.cbSize = testdatami[i].cbSize;
1525 ret = GetMonitorInfoA( monitor, &mi );
1526 ok( ret == testdatami[i].ret, "GetMonitorInfo returned wrong value\n" );
1527 if (ret)
1528 ok( (mi.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
1529 else
1530 ok( !(mi.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag is set\n" );
1531
1532 memset( &miexw, 0, sizeof(miexw) );
1533 miexw.cbSize = testdatamiexw[i].cbSize;
1534 ret = GetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
1535 ok( ret == testdatamiexw[i].ret, "GetMonitorInfo returned wrong value\n" );
1536 if (ret)
1537 ok( (miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
1538 else
1539 ok( !(miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag is set\n" );
1540 }
1541
1542 /* tests for cbSize in MONITORINFOEXA */
1543 for (i = 0; i < ARRAY_SIZE(testdatamiexa); i++)
1544 {
1545 memset( &miexa, 0, sizeof(miexa) );
1546 miexa.cbSize = testdatamiexa[i].cbSize;
1547 ret = GetMonitorInfoA( monitor, (LPMONITORINFO)&miexa );
1548 ok( ret == testdatamiexa[i].ret, "GetMonitorInfo returned wrong value\n" );
1549 if (ret)
1550 ok( (miexa.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
1551 else
1552 ok( !(miexa.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag is set\n" );
1553 }
1554
1555 /* tests for cbSize in MONITORINFOEXW */
1556 for (i = 0; i < ARRAY_SIZE(testdatamiexw); i++)
1557 {
1558 memset( &miexw, 0, sizeof(miexw) );
1559 miexw.cbSize = testdatamiexw[i].cbSize;
1560 ret = GetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
1561 ok( ret == testdatamiexw[i].ret, "GetMonitorInfo returned wrong value\n" );
1562 if (ret)
1563 ok( (miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
1564 else
1565 ok( !(miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag is set\n" );
1566 }
1567
1568 SetRect( &rc, rc.left+1, rc.top+1, rc.left+2, rc.top+2 );
1569
1570 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
1571 ok( monitor == NULL, "got %p\n", monitor );
1572
1573 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
1574 ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
1575
1576 monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
1577 ok( monitor == nearest, "got %p, should get nearest %p\n", monitor, nearest );
1578}
1579
1581{
1583 BOOL ret;
1584
1585 mi.cbSize = sizeof(mi);
1587 ok(ret, "GetMonitorInfo failed\n");
1588 if (mi.dwFlags & MONITORINFOF_PRIMARY)
1589 {
1590 *(HMONITOR *)lp = hmon;
1591 return FALSE;
1592 }
1593 return TRUE;
1594}
1595
1596static void test_work_area(void)
1597{
1598 HMONITOR hmon;
1600 RECT rc_work, rc_normal;
1601 HWND hwnd;
1602 WINDOWPLACEMENT wp;
1603 BOOL ret;
1604
1605 hmon = 0;
1607 ok(!ret && hmon != 0, "Failed to find primary monitor\n");
1608
1609 mi.cbSize = sizeof(mi);
1610 SetLastError(0xdeadbeef);
1612 ok(ret, "GetMonitorInfo error %lu\n", GetLastError());
1613 ok(mi.dwFlags & MONITORINFOF_PRIMARY, "not a primary monitor\n");
1614 trace("primary monitor %s\n", wine_dbgstr_rect(&mi.rcMonitor));
1615
1616 SetLastError(0xdeadbeef);
1617 ret = SystemParametersInfoA(SPI_GETWORKAREA, 0, &rc_work, 0);
1618 ok(ret, "SystemParametersInfo error %lu\n", GetLastError());
1619 trace("work area %s\n", wine_dbgstr_rect(&rc_work));
1620 ok(EqualRect(&rc_work, &mi.rcWork), "work area is different\n");
1621
1622 hwnd = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW|WS_VISIBLE,100,100,10,10,0,0,0,NULL);
1623 ok(hwnd != 0, "CreateWindowEx failed\n");
1624
1625 ret = GetWindowRect(hwnd, &rc_normal);
1626 ok(ret, "GetWindowRect failed\n");
1627 trace("normal %s\n", wine_dbgstr_rect(&rc_normal));
1628
1629 wp.length = sizeof(wp);
1630 ret = GetWindowPlacement(hwnd, &wp);
1631 ok(ret, "GetWindowPlacement failed\n");
1632 trace("min: %ld,%ld max %ld,%ld normal %s\n", wp.ptMinPosition.x, wp.ptMinPosition.y,
1634 OffsetRect(&wp.rcNormalPosition, rc_work.left, rc_work.top);
1636 mi.rcMonitor.top != mi.rcWork.top) /* FIXME: remove once Wine is fixed */
1637 {
1638 ok(EqualRect(&rc_normal, &wp.rcNormalPosition), "normal pos is different\n");
1639 }
1640
1642
1643 wp.length = sizeof(wp);
1644 ret = GetWindowPlacement(hwnd, &wp);
1645 ok(ret, "GetWindowPlacement failed\n");
1646 trace("min: %ld,%ld max %ld,%ld normal %s\n", wp.ptMinPosition.x, wp.ptMinPosition.y,
1648 ok(EqualRect(&rc_normal, &wp.rcNormalPosition), "normal pos is different\n");
1649
1651}
1652
1654{
1655 UINT32 paths, modes;
1656 LONG ret;
1657
1658 ret = pGetDisplayConfigBufferSizes(QDC_ALL_PATHS, NULL, NULL);
1659 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1660
1661 paths = 100;
1662 ret = pGetDisplayConfigBufferSizes(QDC_ALL_PATHS, &paths, NULL);
1663 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1664 ok(paths == 100, "got %u\n", paths);
1665
1666 modes = 100;
1667 ret = pGetDisplayConfigBufferSizes(QDC_ALL_PATHS, NULL, &modes);
1668 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1669 ok(modes == 100, "got %u\n", modes);
1670
1671 ret = pGetDisplayConfigBufferSizes(0, NULL, NULL);
1672 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1673
1674 paths = 100;
1675 ret = pGetDisplayConfigBufferSizes(0, &paths, NULL);
1676 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1677 ok(paths == 100, "got %u\n", paths);
1678
1679 modes = 100;
1680 ret = pGetDisplayConfigBufferSizes(0, NULL, &modes);
1681 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1682 ok(modes == 100, "got %u\n", modes);
1683
1684 /* Flag validation on Windows is driver-dependent */
1685 paths = modes = 100;
1686 ret = pGetDisplayConfigBufferSizes(0, &paths, &modes);
1687 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
1688 ok((modes == 0 || modes == 100) && paths == 0, "got %u, %u\n", modes, paths);
1689
1690 paths = modes = 100;
1691 ret = pGetDisplayConfigBufferSizes(0xFF, &paths, &modes);
1692 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
1693 ok((modes == 0 || modes == 100) && paths == 0, "got %u, %u\n", modes, paths);
1694
1695 /* Test success */
1696 paths = modes = 0;
1697 ret = pGetDisplayConfigBufferSizes(QDC_ALL_PATHS, &paths, &modes);
1698 if (!ret)
1699 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
1700 else
1701 ok(ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
1702
1703 paths = modes = 0;
1704 ret = pGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &paths, &modes);
1705 if (!ret)
1706 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
1707 else
1708 ok(ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
1709
1710 paths = modes = 0;
1711 ret = pGetDisplayConfigBufferSizes(QDC_DATABASE_CURRENT, &paths, &modes);
1712 if (!ret)
1713 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
1714 else
1715 ok(ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
1716
1717 paths = modes = 0;
1718 ret = pGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE, &paths, &modes);
1719 ok(!ret || broken(ret == ERROR_INVALID_PARAMETER || ret == ERROR_NOT_SUPPORTED) /* before Win10 */, "got %ld\n", ret);
1720 if (!ret)
1721 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
1722}
1723
1725 LPARAM lparam)
1726{
1728 LONG ret;
1729
1730 mi.cbSize = sizeof(mi);
1731 ret = GetMonitorInfoA(monitor, &mi);
1732 ok(ret, "GetMonitorInfoA failed, error %#lx.\n", GetLastError());
1733 ok(EqualRect(rect, &mi.rcMonitor), "Expected rect %s, got %s.\n",
1735
1736 return TRUE;
1737}
1738
1741{
1742 return FALSE;
1743}
1744
1747{
1748 MONITORINFOEXA mi, mi2;
1749 DEVMODEA old_dm, dm;
1750 DWORD error;
1751 INT count;
1752 LONG ret;
1753
1754 mi.cbSize = sizeof(mi);
1755 ret = GetMonitorInfoA(monitor, (MONITORINFO *)&mi);
1756 ok(ret, "GetMonitorInfoA failed, error %#lx.\n", GetLastError());
1757
1758 /* Test that monitor handle is invalid after the monitor is detached */
1759 if (!(mi.dwFlags & MONITORINFOF_PRIMARY))
1760 {
1762
1763 /* Save current display settings */
1764 memset(&old_dm, 0, sizeof(old_dm));
1765 old_dm.dmSize = sizeof(old_dm);
1766 ret = EnumDisplaySettingsA(mi.szDevice, ENUM_CURRENT_SETTINGS, &old_dm);
1767 ok(ret, "EnumDisplaySettingsA %s failed, error %#lx.\n", mi.szDevice, GetLastError());
1768
1769 /* Detach monitor */
1770 memset(&dm, 0, sizeof(dm));
1771 dm.dmSize = sizeof(dm);
1776 NULL);
1777 ok(ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
1778 mi.szDevice, ret);
1779 ret = ChangeDisplaySettingsExA(mi.szDevice, NULL, NULL, 0, NULL);
1780 ok(ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
1781 mi.szDevice, ret);
1782
1783 /* Check if it's really detached */
1785 {
1786 skip("Failed to detach %s.\n", mi.szDevice);
1787 SetLastError(0xdeadbeef);
1788 return TRUE;
1789 }
1790
1791 /* The monitor handle should be invalid now */
1792 mi2.cbSize = sizeof(mi2);
1793 SetLastError(0xdeadbeef);
1794 ret = GetMonitorInfoA(monitor, (MONITORINFO *)&mi2);
1795 ok(!ret, "GetMonitorInfoA succeeded.\n");
1796 error = GetLastError();
1798 "Expected error %#x, got %#lx.\n", ERROR_INVALID_MONITOR_HANDLE, error);
1799
1800 /* Restore the original display settings */
1802 NULL);
1803 ok(ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
1804 mi.szDevice, ret);
1805 ret = ChangeDisplaySettingsExA(mi.szDevice, NULL, NULL, 0, NULL);
1806 ok(ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
1807 mi.szDevice, ret);
1808 }
1809
1810 SetLastError(0xdeadbeef);
1811 return TRUE;
1812}
1813
1815 LPARAM lparam)
1816{
1817 INT *count = (INT *)lparam;
1818 ++(*count);
1819 return TRUE;
1820}
1821
1823{
1824 static const DWORD DESKTOP_ALL_ACCESS = 0x01ff;
1825 HWINSTA winstation, old_winstation;
1826 HDESK desktop, old_desktop;
1828 INT count, old_count;
1829 DWORD error;
1830 BOOL ret;
1831
1833 ok(ret, "EnumDisplayMonitors failed, error %#lx.\n", GetLastError());
1834
1835 SetLastError(0xdeadbeef);
1837 error = GetLastError();
1838 ok(!ret, "EnumDisplayMonitors succeeded.\n");
1839 ok(error == 0xdeadbeef, "Expected error %#x, got %#lx.\n", 0xdeadbeef, error);
1840
1842 SetLastError(0xdeadbeef);
1844 error = GetLastError();
1845 if (count >= 2)
1846 todo_wine ok(!ret, "EnumDisplayMonitors succeeded.\n");
1847 else
1848 ok(ret, "EnumDisplayMonitors failed.\n");
1849 ok(error == 0xdeadbeef, "Expected error %#x, got %#lx.\n", 0xdeadbeef, error);
1850
1851 /* Test that monitor enumeration is not affected by window stations and desktops */
1852 old_winstation = GetProcessWindowStation();
1853 old_desktop = GetThreadDesktop(GetCurrentThreadId());
1854 old_count = GetSystemMetrics(SM_CMONITORS);
1855
1856 count = 0;
1858 ok(ret, "EnumDisplayMonitors failed, error %#lx.\n", GetLastError());
1859 ok(count == old_count, "Expected %d, got %d.\n", old_count, count);
1860
1862 ok(!!winstation && winstation != old_winstation, "CreateWindowStationW failed, error %#lx.\n", GetLastError());
1863 ret = SetProcessWindowStation(winstation);
1864 ok(ret, "SetProcessWindowStation failed, error %#lx.\n", GetLastError());
1865 ok(winstation == GetProcessWindowStation(), "Expected %p, got %p.\n", GetProcessWindowStation(), winstation);
1866
1867 flags.fInherit = FALSE;
1868 flags.fReserved = FALSE;
1869 flags.dwFlags = WSF_VISIBLE;
1870 ret = SetUserObjectInformationW(winstation, UOI_FLAGS, &flags, sizeof(flags));
1871 ok(ret, "SetUserObjectInformationW failed, error %#lx.\n", GetLastError());
1872
1873 desktop = CreateDesktopW(L"test_desktop", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
1874 ok(!!desktop && desktop != old_desktop, "CreateDesktopW failed, error %#lx.\n", GetLastError());
1875 ret = SetThreadDesktop(desktop);
1876 ok(ret, "SetThreadDesktop failed, error %#lx.\n", GetLastError());
1877 ok(desktop == GetThreadDesktop(GetCurrentThreadId()), "Expected %p, got %p.\n",
1879
1881 ok(count == old_count, "Expected %d, got %d.\n", old_count, count);
1882 count = 0;
1884 ok(ret, "EnumDisplayMonitors failed, error %#lx.\n", GetLastError());
1885 ok(count == old_count, "Expected %d, got %d.\n", old_count, count);
1886
1887 ret = SetProcessWindowStation(old_winstation);
1888 ok(ret, "SetProcessWindowStation failed, error %#lx.\n", GetLastError());
1889 ret = SetThreadDesktop(old_desktop);
1890 ok(ret, "SetThreadDesktop failed, error %#lx.\n", GetLastError());
1891 ret = CloseDesktop(desktop);
1892 ok(ret, "CloseDesktop failed, error %#lx.\n", GetLastError());
1893 ret = CloseWindowStation(winstation);
1894 ok(ret, "CloseWindowStation failed, error %#lx.\n", GetLastError());
1895}
1896
1897static void check_device_path(const WCHAR *device_path, const LUID *adapter_id, DWORD id)
1898{
1899#ifdef __REACTOS__
1900 skip("FIXME: check_device_path() cannot be built until we add new functions to setupapi\n");
1901#else
1902 BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)];
1903 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1904 SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
1906 BOOL ret, found = FALSE;
1908 DWORD output_id;
1909 unsigned int i;
1910 HDEVINFO set;
1911 LUID luid;
1912
1913 iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer;
1914 iface_data->cbSize = sizeof(*iface_data);
1915
1916 set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MONITOR, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
1917 ok(set != INVALID_HANDLE_VALUE, "Got error %lu.\n", GetLastError());
1918
1919 i = 0;
1920 while (SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_MONITOR, i, &iface))
1921 {
1922 ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data,
1923 sizeof(iface_detail_buffer), NULL, &device_data);
1924 ok(ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError());
1925
1926 ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID, &type,
1927 (BYTE *)&luid, sizeof(luid), NULL, 0);
1928 ok(ret || broken(GetLastError() == ERROR_NOT_FOUND) /* before Win10 1809 */,
1929 "Got error %lu.\n", GetLastError());
1930 if (!ret)
1931 {
1932 win_skip("DEVPROPKEY_MONITOR_GPU_LUID is not found, skipping device path check.\n");
1934 return;
1935 }
1936 ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
1937 &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0);
1938 ok(ret, "Got error %lu.\n", GetLastError());
1939
1940 if (output_id == id && RtlEqualLuid(&luid, adapter_id) && !wcsicmp(device_path, iface_data->DevicePath))
1941 {
1942 found = TRUE;
1943 break;
1944 }
1945 ++i;
1946 }
1947 ok(found, "device_path %s not found, luid %04lx:%04lx.\n", debugstr_w(device_path), adapter_id->HighPart,
1948 adapter_id->LowPart);
1950#endif
1951}
1952
1953static void check_preferred_mode(const DISPLAYCONFIG_TARGET_PREFERRED_MODE *mode, const WCHAR *gdi_device_name)
1954{
1955 DISPLAYCONFIG_TARGET_PREFERRED_MODE mode2;
1956 DEVMODEW dm, dm2;
1957 LONG lret;
1958 BOOL bret;
1959
1960 dm.dmSize = sizeof(dm);
1961 bret = EnumDisplaySettingsW(gdi_device_name, ENUM_CURRENT_SETTINGS, &dm);
1962#ifdef __REACTOS__
1963 ok(bret || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* Win8 */, "got error %lu.\n", GetLastError());
1964#else
1965 ok(bret, "got error %lu.\n", GetLastError());
1966#endif
1967
1968 if (dm.dmPelsWidth == 1024 && dm.dmPelsHeight == 768)
1969 {
1970 skip("Current display mode is already 1024x768, skipping test.\n");
1971 return;
1972 }
1973 if (mode->width == 1024 && mode->height == 768)
1974 {
1975 skip("Preferred display mode is 1024x768, skipping test.\n");
1976 return;
1977 }
1978
1979 memset(&dm2, 0, sizeof(dm2));
1980 dm2.dmSize = sizeof(dm2);
1982 dm2.dmPelsWidth = 1024;
1983 dm2.dmPelsHeight = 768;
1984 lret = ChangeDisplaySettingsExW(gdi_device_name, &dm2, NULL, 0, 0);
1985 if (lret != DISP_CHANGE_SUCCESSFUL)
1986 {
1987 skip("Can't change display settings, skipping test.\n");
1988 return;
1989 }
1990
1991 memset(&mode2, 0, sizeof(mode2));
1992 mode2.header = mode->header;
1993
1994 lret = pDisplayConfigGetDeviceInfo(&mode2.header);
1995 ok(!lret, "got %ld\n", lret);
1996 ok(mode2.width == mode->width, "got %u, expected %u.\n", mode2.width, mode->width);
1997 ok(mode2.height == mode->height, "got %u, expected %u.\n", mode2.height, mode->height);
1998
1999 lret = ChangeDisplaySettingsExW(gdi_device_name, &dm, NULL, 0, 0);
2000 ok(lret == DISP_CHANGE_SUCCESSFUL, "got %ld.\n", lret);
2001}
2002
2005{
2006 UINT32 i, src_mode_idx, tgt_mode_idx;
2007 LONG ret;
2008 DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;
2009 DISPLAYCONFIG_TARGET_DEVICE_NAME target_name;
2010 DISPLAYCONFIG_TARGET_PREFERRED_MODE preferred_mode;
2011 DISPLAYCONFIG_ADAPTER_NAME adapter_name;
2013
2014 for (i = 0; i < paths; i++)
2015 {
2016 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2017 source_name.header.size = sizeof(source_name);
2018 source_name.header.adapterId = pi[i].sourceInfo.adapterId;
2019 source_name.header.id = pi[i].sourceInfo.id;
2020 source_name.viewGdiDeviceName[0] = '\0';
2021 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2022#ifdef __REACTOS__
2023 ok(!ret || broken(ret == ERROR_GEN_FAILURE) /* Win8 */, "Expected 0, got %ld\n", ret);
2024 if (ret != ERROR_GEN_FAILURE)
2025 ok(source_name.viewGdiDeviceName[0] != '\0', "Expected GDI device name, got empty string\n");
2026#else
2027 ok(!ret, "Expected 0, got %ld\n", ret);
2028 ok(source_name.viewGdiDeviceName[0] != '\0', "Expected GDI device name, got empty string\n");
2029#endif
2030
2031 /* Test with an invalid adapter LUID */
2032 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2033 source_name.header.size = sizeof(source_name);
2034 source_name.header.adapterId.LowPart = 0xFFFF;
2035 source_name.header.adapterId.HighPart = 0xFFFF;
2036 source_name.header.id = pi[i].sourceInfo.id;
2037 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2038 ok(ret == ERROR_GEN_FAILURE, "Expected GEN_FAILURE, got %ld\n", ret);
2039
2040 target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
2041 target_name.header.size = sizeof(target_name);
2042 target_name.header.adapterId = pi[i].targetInfo.adapterId;
2043 target_name.header.id = pi[i].targetInfo.id;
2044 target_name.monitorDevicePath[0] = '\0';
2045 ret = pDisplayConfigGetDeviceInfo(&target_name.header);
2046#ifdef __REACTOS__
2047 ok(!ret || broken(ret == ERROR_GEN_FAILURE) /* Win8 */, "Expected 0, got %ld\n", ret);
2048#else
2049 ok(!ret, "Expected 0, got %ld\n", ret);
2050#endif
2051 check_device_path(target_name.monitorDevicePath, &target_name.header.adapterId, target_name.header.id);
2052
2053 preferred_mode.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
2054 preferred_mode.header.size = sizeof(preferred_mode);
2055 preferred_mode.header.adapterId = pi[i].targetInfo.adapterId;
2056 preferred_mode.header.id = pi[i].targetInfo.id;
2057 preferred_mode.width = preferred_mode.height = 0;
2058 ret = pDisplayConfigGetDeviceInfo(&preferred_mode.header);
2059#ifdef __REACTOS__
2060 ok(!ret || broken(ret == ERROR_GEN_FAILURE) /* Win8 */, "Expected 0, got %ld\n", ret);
2061 if (!ret)
2062 ok(preferred_mode.width > 0 && preferred_mode.height > 0, "Expected non-zero height/width, got %ux%u\n",
2063 preferred_mode.width, preferred_mode.height);
2064#else
2065 ok(!ret, "Expected 0, got %ld\n", ret);
2066 ok(preferred_mode.width > 0 && preferred_mode.height > 0, "Expected non-zero height/width, got %ux%u\n",
2067 preferred_mode.width, preferred_mode.height);
2068#endif
2069 check_preferred_mode(&preferred_mode, source_name.viewGdiDeviceName);
2070
2071 todo_wine {
2072 adapter_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
2073 adapter_name.header.size = sizeof(adapter_name);
2074 adapter_name.header.adapterId = pi[i].sourceInfo.adapterId;
2075 adapter_name.adapterDevicePath[0] = '\0';
2076 ret = pDisplayConfigGetDeviceInfo(&adapter_name.header);
2077#ifdef __REACTOS__
2078 ok(!ret || broken(ret == ERROR_GEN_FAILURE) /* Win8 */, "Expected 0, got %ld\n", ret);
2079 if (!ret)
2080 ok(adapter_name.adapterDevicePath[0] != '\0', "Expected adapter device path, got empty string\n");
2081#else
2082 ok(!ret, "Expected 0, got %ld\n", ret);
2083 ok(adapter_name.adapterDevicePath[0] != '\0', "Expected adapter device path, got empty string\n");
2084#endif
2085 }
2086
2087 /* Check corresponding modes */
2088 if (flags & QDC_VIRTUAL_MODE_AWARE)
2089 {
2090 src_mode_idx = pi[i].sourceInfo.sourceModeInfoIdx;
2091 if (src_mode_idx == DISPLAYCONFIG_PATH_SOURCE_MODE_IDX_INVALID)
2092 {
2093 ok(pi[i].sourceInfo.cloneGroupId != DISPLAYCONFIG_PATH_CLONE_GROUP_INVALID, "got cloneGroupId %#x.\n",
2094 pi[i].sourceInfo.cloneGroupId);
2095 skip("Path doesn't contain source modeInfoIdx\n");
2096 continue;
2097 }
2098 ok(pi[i].sourceInfo.cloneGroupId == DISPLAYCONFIG_PATH_CLONE_GROUP_INVALID, "got cloneGroupId %#x.\n",
2099 pi[i].sourceInfo.cloneGroupId);
2100 }
2101 else
2102 {
2103 src_mode_idx = pi[i].sourceInfo.modeInfoIdx;
2104 if (src_mode_idx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)
2105 {
2106 skip("Path doesn't contain source modeInfoIdx\n");
2107 continue;
2108 }
2109 }
2110 ok(src_mode_idx < modes, "Expected index <%d, got %d\n", modes, src_mode_idx);
2111 if (src_mode_idx >= modes)
2112 continue;
2113
2114 ok(mi[src_mode_idx].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE, "Expected infoType %d, got %d\n",
2115 DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE, mi[src_mode_idx].infoType);
2116 ok(pi[i].sourceInfo.id == mi[src_mode_idx].id, "Expected id %u, got %u\n",
2117 pi[i].sourceInfo.id, mi[src_mode_idx].id);
2118 ok(pi[i].sourceInfo.adapterId.HighPart == mi[src_mode_idx].adapterId.HighPart &&
2119 pi[i].sourceInfo.adapterId.LowPart == mi[src_mode_idx].adapterId.LowPart,
2120 "Expected LUID %08lx:%08lx, got %08lx:%08lx\n",
2121 pi[i].sourceInfo.adapterId.HighPart, pi[i].sourceInfo.adapterId.LowPart,
2122 mi[src_mode_idx].adapterId.HighPart, mi[src_mode_idx].adapterId.LowPart);
2123 ok(mi[src_mode_idx].sourceMode.width > 0 && mi[src_mode_idx].sourceMode.height > 0,
2124 "Expected non-zero height/width, got %ux%u\n",
2125 mi[src_mode_idx].sourceMode.width, mi[src_mode_idx].sourceMode.height);
2126
2127
2128 if (flags & QDC_VIRTUAL_MODE_AWARE)
2129 {
2130 tgt_mode_idx = pi[i].targetInfo.targetModeInfoIdx;
2131 if (tgt_mode_idx == DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID)
2132 {
2133 skip("Path doesn't contain target modeInfoIdx\n");
2134 continue;
2135 }
2136 }
2137 else
2138 {
2139 tgt_mode_idx = pi[i].targetInfo.modeInfoIdx;
2140 if (tgt_mode_idx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)
2141 {
2142 skip("Path doesn't contain target modeInfoIdx\n");
2143 continue;
2144 }
2145 }
2146 ok(tgt_mode_idx < modes, "Expected index <%d, got %d\n", modes, tgt_mode_idx);
2147 if (tgt_mode_idx >= modes)
2148 continue;
2149
2150 ok(mi[tgt_mode_idx].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET, "Expected infoType %d, got %d\n",
2151 DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE, mi[tgt_mode_idx].infoType);
2152 ok(pi[i].targetInfo.id == mi[tgt_mode_idx].id, "Expected id %u, got %u\n",
2153 pi[i].targetInfo.id, mi[tgt_mode_idx].id);
2154 ok(pi[i].targetInfo.adapterId.HighPart == mi[tgt_mode_idx].adapterId.HighPart &&
2155 pi[i].targetInfo.adapterId.LowPart == mi[tgt_mode_idx].adapterId.LowPart,
2156 "Expected LUID %08lx:%08lx, got %08lx:%08lx\n",
2157 pi[i].targetInfo.adapterId.HighPart, pi[i].targetInfo.adapterId.LowPart,
2158 mi[tgt_mode_idx].adapterId.HighPart, mi[tgt_mode_idx].adapterId.LowPart);
2159 ok(mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.activeSize.cx > 0 &&
2160 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.activeSize.cy > 0,
2161 "Expected non-zero height/width, got %ux%u\n",
2162 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.activeSize.cx,
2163 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.activeSize.cy);
2164
2165 if (flags == QDC_DATABASE_CURRENT)
2166 ok(mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cx == 0 &&
2167 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cy == 0,
2168 "Expected zero height/width, got %ux%u\n",
2169 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cx,
2170 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cy);
2171 else
2172 ok(mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cx > 0 &&
2173 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cy > 0,
2174 "Expected non-zero height/width, got %ux%u\n",
2175 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cx,
2176 mi[tgt_mode_idx].targetMode.targetVideoSignalInfo.totalSize.cy);
2177 if (flags & QDC_VIRTUAL_MODE_AWARE)
2178 {
2179 tgt_mode_idx = pi[i].targetInfo.desktopModeInfoIdx;
2180 if (tgt_mode_idx == DISPLAYCONFIG_PATH_DESKTOP_IMAGE_IDX_INVALID)
2181 {
2182 ok(!(pi[i].flags & DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE), "got path flags %#x.\n", pi[i].flags);
2183 skip("Path doesn't contain target desktopModeInfoIdx.\n");
2184 continue;
2185 }
2186 ok(pi[i].flags & DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE, "got path flags %#x.\n", pi[i].flags);
2187 }
2188 else
2189 {
2190 continue;
2191 }
2192
2193 ok(mi[tgt_mode_idx].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE, "Expected infoType %d, got %d\n",
2194 DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE, mi[tgt_mode_idx].infoType);
2195 ok(pi[i].targetInfo.id == mi[tgt_mode_idx].id, "Expected id %u, got %u\n",
2196 pi[i].targetInfo.id, mi[tgt_mode_idx].id);
2197 ok(pi[i].targetInfo.adapterId.HighPart == mi[tgt_mode_idx].adapterId.HighPart &&
2198 pi[i].targetInfo.adapterId.LowPart == mi[tgt_mode_idx].adapterId.LowPart,
2199 "Expected LUID %08lx:%08lx, got %08lx:%08lx\n",
2200 pi[i].targetInfo.adapterId.HighPart, pi[i].targetInfo.adapterId.LowPart,
2201 mi[tgt_mode_idx].adapterId.HighPart, mi[tgt_mode_idx].adapterId.LowPart);
2202 di = &mi[tgt_mode_idx].desktopImageInfo;
2204 "Expected zero left/top, got %lux%lu\n",
2208 "Expected non-zero height/width, got %lux%lu\n",
2212 "Expected zero left/top, got %lux%lu\n",
2214 di->DesktopImageClip.top);
2215 ok(di->DesktopImageClip.right > 0 && di->DesktopImageClip.bottom > 0,
2216 "Expected non-zero height/width, got %lux%lu\n",
2219 ok(di->PathSourceSize.x > 0 && di->PathSourceSize.y > 0,
2220 "Expected non-zero x/y, got %lux%lu\n",
2221 di->PathSourceSize.x,
2222 di->PathSourceSize.y);
2223 }
2224}
2225
2227{
2228 UINT32 paths, modes;
2231 DISPLAYCONFIG_TOPOLOGY_ID topologyid;
2232 LONG ret;
2233
2234 ret = pQueryDisplayConfig(QDC_ALL_PATHS, NULL, NULL, NULL, NULL, NULL);
2235 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2236
2237 paths = modes = 0;
2238 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, NULL, &modes, NULL, NULL);
2239 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2240
2241 paths = modes = 0;
2242 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, pi, &modes, NULL, NULL);
2243 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2244
2245 paths = modes = 0;
2246 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, NULL, &modes, mi, NULL);
2247 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2248
2249 paths = modes = 0;
2250 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, pi, &modes, mi, NULL);
2251 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2252
2253 paths = 0;
2254 modes = 1;
2255 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, pi, &modes, mi, NULL);
2256 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2257 ok (paths == 0, "got %u\n", paths);
2258 ok (modes == 1, "got %u\n", modes);
2259
2260 /* Crashes on Windows 10 */
2261 if (0)
2262 {
2263 ret = pQueryDisplayConfig(QDC_ALL_PATHS, NULL, pi, NULL, mi, NULL);
2264 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2265
2266 ret = pQueryDisplayConfig(QDC_ALL_PATHS, NULL, pi, &modes, mi, NULL);
2267 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2268 }
2269
2270 paths = modes = 1;
2271 ret = pQueryDisplayConfig(0, &paths, pi, &modes, mi, NULL);
2272 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2273
2274 paths = modes = 1;
2275 ret = pQueryDisplayConfig(0xFF, &paths, pi, &modes, mi, NULL);
2276 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2277
2278 paths = modes = 1;
2279 ret = pQueryDisplayConfig(QDC_DATABASE_CURRENT, &paths, pi, &modes, mi, NULL);
2280 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2281
2282 paths = modes = 1;
2283 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, pi, &modes, mi, &topologyid);
2284 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2285
2286 /* Below this point, test functionality that requires a WDDM driver on Windows */
2287 paths = modes = 1;
2288 memset(pi, 0xFF, sizeof(pi[0]));
2289 memset(mi, 0xFF, sizeof(mi[0]));
2290 ret = pQueryDisplayConfig(QDC_ALL_PATHS, &paths, pi, &modes, mi, NULL);
2291 if (ret == ERROR_NOT_SUPPORTED)
2292 {
2293 todo_wine
2294 win_skip("QueryDisplayConfig() functionality is unsupported\n");
2295 return;
2296 }
2297 ok(ret == ERROR_INSUFFICIENT_BUFFER, "got %ld\n", ret);
2298 ok (paths == 1, "got %u\n", paths);
2299 ok (modes == 1, "got %u\n", modes);
2300
2301 paths = ARRAY_SIZE(pi);
2302 modes = ARRAY_SIZE(mi);
2303 memset(pi, 0xFF, sizeof(pi));
2304 memset(mi, 0xFF, sizeof(mi));
2305 ret = pQueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &paths, pi, &modes, mi, NULL);
2306 ok(!ret, "got %ld\n", ret);
2307 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
2308 if (!ret && paths > 0 && modes > 0)
2309 test_QueryDisplayConfig_result(QDC_ONLY_ACTIVE_PATHS, paths, pi, modes, mi);
2310
2311 paths = ARRAY_SIZE(pi);
2312 modes = ARRAY_SIZE(mi);
2313 memset(pi, 0xFF, sizeof(pi));
2314 memset(mi, 0xFF, sizeof(mi));
2315 topologyid = 0xFF;
2316 ret = pQueryDisplayConfig(QDC_DATABASE_CURRENT, &paths, pi, &modes, mi, &topologyid);
2317 ok(!ret, "got %ld\n", ret);
2318 ok(topologyid != 0xFF, "expected topologyid to be set, got %d\n", topologyid);
2319 if (!ret && paths > 0 && modes > 0)
2320 test_QueryDisplayConfig_result(QDC_DATABASE_CURRENT, paths, pi, modes, mi);
2321
2322 paths = ARRAY_SIZE(pi);
2323 modes = ARRAY_SIZE(mi);
2324 memset(pi, 0xFF, sizeof(pi));
2325 memset(mi, 0xFF, sizeof(mi));
2326 ret = pQueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE, &paths, pi, &modes, mi, NULL);
2327 ok(!ret || broken(ret == ERROR_INVALID_PARAMETER) /* before Win10 */, "got %ld\n", ret);
2328 if (!ret)
2329 ok(paths > 0 && modes > 0, "got %u, %u\n", paths, modes);
2330 if (!ret && paths > 0 && modes > 0)
2331 test_QueryDisplayConfig_result(QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE, paths, pi, modes, mi);
2332}
2333
2335{
2336 LONG ret;
2337 DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;
2338 DISPLAYCONFIG_TARGET_DEVICE_NAME target_name;
2339 DISPLAYCONFIG_TARGET_PREFERRED_MODE preferred_mode;
2340 DISPLAYCONFIG_ADAPTER_NAME adapter_name;
2341
2342 ret = pDisplayConfigGetDeviceInfo(NULL);
2343 ok(ret == ERROR_GEN_FAILURE, "got %ld\n", ret);
2344
2345 source_name.header.type = 0xFFFF;
2346 source_name.header.size = 0;
2347 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2348 ok(ret == ERROR_GEN_FAILURE, "got %ld\n", ret);
2349
2350 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2351 source_name.header.size = 0;
2352 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2353 ok(ret == ERROR_GEN_FAILURE, "got %ld\n", ret);
2354
2355 source_name.header.type = 0xFFFF;
2356 source_name.header.size = sizeof(source_name.header);
2357 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2358#ifdef __REACTOS__
2359 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2360#else
2361 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2362#endif
2363
2364 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2365 source_name.header.size = sizeof(source_name.header);
2366 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2367#ifdef __REACTOS__
2368 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2369#else
2370 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2371#endif
2372
2373 source_name.header.type = 0xFFFF;
2374 source_name.header.size = sizeof(source_name);
2375 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2376#ifdef __REACTOS__
2377 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2378#else
2379 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2380#endif
2381
2382 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2383 source_name.header.size = sizeof(source_name) - 1;
2384 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2385#ifdef __REACTOS__
2386 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2387#else
2388 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2389#endif
2390
2391 source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
2392 source_name.header.size = sizeof(source_name);
2393 source_name.header.adapterId.LowPart = 0xFFFF;
2394 source_name.header.adapterId.HighPart = 0xFFFF;
2395 source_name.header.id = 0;
2396 ret = pDisplayConfigGetDeviceInfo(&source_name.header);
2397 ok(ret == ERROR_GEN_FAILURE || ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
2398
2399 target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
2400 target_name.header.size = sizeof(target_name) - 1;
2401 ret = pDisplayConfigGetDeviceInfo(&target_name.header);
2402#ifdef __REACTOS__
2403 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2404#else
2405 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2406#endif
2407
2408 target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
2409 target_name.header.size = sizeof(target_name);
2410 target_name.header.adapterId.LowPart = 0xFFFF;
2411 target_name.header.adapterId.HighPart = 0xFFFF;
2412 target_name.header.id = 0;
2413 ret = pDisplayConfigGetDeviceInfo(&target_name.header);
2414 ok(ret == ERROR_GEN_FAILURE || ret == ERROR_NOT_SUPPORTED, "got %ld\n", ret);
2415
2416 preferred_mode.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
2417 preferred_mode.header.size = sizeof(preferred_mode) - 1;
2418 ret = pDisplayConfigGetDeviceInfo(&preferred_mode.header);
2419#ifdef __REACTOS__
2420 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2421#else
2422 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2423#endif
2424
2425 preferred_mode.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
2426 preferred_mode.header.size = sizeof(preferred_mode);
2427 preferred_mode.header.adapterId.LowPart = 0xFFFF;
2428 preferred_mode.header.adapterId.HighPart = 0xFFFF;
2429 preferred_mode.header.id = 0;
2430 ret = pDisplayConfigGetDeviceInfo(&preferred_mode.header);
2432
2433 adapter_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
2434 adapter_name.header.size = sizeof(adapter_name) - 1;
2435 ret = pDisplayConfigGetDeviceInfo(&adapter_name.header);
2436#ifdef __REACTOS__
2437 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_GEN_FAILURE /* Win7 */, "got %ld\n", ret);
2438#else
2439 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
2440#endif
2441
2442 adapter_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
2443 adapter_name.header.size = sizeof(adapter_name);
2444 adapter_name.header.adapterId.LowPart = 0xFFFF;
2445 adapter_name.header.adapterId.HighPart = 0xFFFF;
2446 ret = pDisplayConfigGetDeviceInfo(&adapter_name.header);
2448}
2449
2450static void test_display_config(void)
2451{
2452 if (!pGetDisplayConfigBufferSizes ||
2453 !pQueryDisplayConfig ||
2454 !pDisplayConfigGetDeviceInfo)
2455 {
2456 win_skip("DisplayConfig APIs are not supported\n");
2457 return;
2458 }
2459
2463}
2464
2466{
2467 static const unsigned int scales[] = {100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500};
2468 static const DWORD enabled = 1;
2469 int current_scale, current_scale_idx, recommended_scale_idx, step, dpi, old_dpi;
2470 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
2471 DISPLAYCONFIG_GET_SOURCE_DPI_SCALE get_scale_req;
2472 DISPLAYCONFIG_SET_SOURCE_DPI_SCALE set_scale_req;
2473 D3DKMT_CLOSEADAPTER close_adapter_desc;
2475 HKEY key;
2476 LONG ret;
2477
2478#define CHECK_FUNC(func) \
2479 if (!p##func) \
2480 { \
2481 win_skip("%s() is unavailable.\n", #func); \
2482 ret = TRUE; \
2483 }
2484
2485 ret = FALSE;
2486 CHECK_FUNC(D3DKMTCloseAdapter)
2491 CHECK_FUNC(SetThreadDpiAwarenessContext)
2492 if (ret) return;
2493
2494#undef CHECK_FUNC
2495
2496 lstrcpyW(open_adapter_gdi_desc.DeviceName, L"\\\\.\\DISPLAY1");
2497 status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
2498 ok(status == STATUS_SUCCESS, "D3DKMTOpenAdapterFromGdiDisplayName failed, status %#lx.\n", status);
2499
2500 get_scale_req.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_DPI_SCALE;
2501 get_scale_req.header.size = sizeof(get_scale_req);
2502 get_scale_req.header.adapterId = open_adapter_gdi_desc.AdapterLuid;
2503 get_scale_req.header.id = open_adapter_gdi_desc.VidPnSourceId;
2504 ret = pDisplayConfigGetDeviceInfo(&get_scale_req.header);
2505 if (ret != NO_ERROR)
2506 {
2507 skip("DisplayConfigGetDeviceInfo failed, returned %ld.\n", ret);
2508 goto failed;
2509 }
2510
2511 /* Set IgnorePerProcessSystemDPIToast to 1 to disable "fix blurry apps popup" on Windows 10,
2512 * which may interfere other tests because it steals focus */
2513 RegOpenKeyA(HKEY_CURRENT_USER, "Control Panel\\Desktop", &key);
2514 RegSetValueExA(key, "IgnorePerProcessSystemDPIToast", 0, REG_DWORD, (const BYTE *)&enabled,
2515 sizeof(enabled));
2516
2517 dpi = get_primary_dpi();
2518 old_dpi = dpi;
2519 current_scale = dpi * 100 / 96;
2520 for (current_scale_idx = 0; current_scale_idx < ARRAY_SIZE(scales); ++current_scale_idx)
2521 {
2522 if (scales[current_scale_idx] == current_scale)
2523 break;
2524 }
2525 ok(scales[current_scale_idx] == current_scale, "Failed to find current scale.\n");
2526 recommended_scale_idx = current_scale_idx - get_scale_req.curRelativeScaleStep;
2527
2528 set_scale_req.header.type = DISPLAYCONFIG_DEVICE_INFO_SET_SOURCE_DPI_SCALE;
2529 set_scale_req.header.size = sizeof(set_scale_req);
2530 set_scale_req.header.adapterId = open_adapter_gdi_desc.AdapterLuid;
2531 set_scale_req.header.id = open_adapter_gdi_desc.VidPnSourceId;
2532 for (step = get_scale_req.minRelativeScaleStep; step <= get_scale_req.maxRelativeScaleStep; ++step)
2533 {
2534 set_scale_req.relativeScaleStep = step;
2535 ret = pDisplayConfigSetDeviceInfo(&set_scale_req.header);
2536 ok(ret == NO_ERROR, "DisplayConfigSetDeviceInfo failed, returned %ld.\n", ret);
2537
2538 dpi = scales[step + recommended_scale_idx] * 96 / 100;
2539 ok(dpi == get_primary_dpi(), "Expected %d, got %d.\n", get_primary_dpi(), dpi);
2540 }
2541
2542 /* Restore to the original scale */
2543 set_scale_req.relativeScaleStep = get_scale_req.curRelativeScaleStep;
2544 ret = pDisplayConfigSetDeviceInfo(&set_scale_req.header);
2545 ok(ret == NO_ERROR, "DisplayConfigSetDeviceInfo failed, returned %ld.\n", ret);
2546 ok(old_dpi == get_primary_dpi(), "Expected %d, got %d.\n", get_primary_dpi(), old_dpi);
2547
2548 /* Remove IgnorePerProcessSystemDPIToast registry value */
2549 RegDeleteValueA(key, "IgnorePerProcessSystemDPIToast");
2551
2552failed:
2553 close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
2554 status = pD3DKMTCloseAdapter(&close_adapter_desc);
2555 ok(status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status);
2556}
2557
2559{
2561 HMONITOR monitor;
2562 BOOL ret;
2563
2564#ifdef _WIN64
2565 if ((ULONG_PTR)full_monitor >> 32)
2566 monitor = full_monitor;
2567 else
2568 monitor = (HMONITOR)((ULONG_PTR)full_monitor | ((ULONG_PTR)~0u << 32));
2569 SetLastError(0xdeadbeef);
2570 ret = GetMonitorInfoW(monitor, &monitor_info);
2571 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
2572
2573 monitor = (HMONITOR)((ULONG_PTR)full_monitor & 0xffffffff);
2574 SetLastError(0xdeadbeef);
2575 ret = GetMonitorInfoW(monitor, &monitor_info);
2576 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
2577
2578 monitor = (HMONITOR)(((ULONG_PTR)full_monitor & 0xffffffff) | ((ULONG_PTR)0x1234 << 32));
2579 SetLastError(0xdeadbeef);
2580 ret = GetMonitorInfoW(monitor, &monitor_info);
2581 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
2582
2583 monitor = (HMONITOR)((ULONG_PTR)full_monitor & 0xffff);
2584 SetLastError(0xdeadbeef);
2585 ret = GetMonitorInfoW(monitor, &monitor_info);
2586 todo_wine ok(!ret, "GetMonitorInfoW succeeded.\n");
2587 todo_wine ok(GetLastError() == ERROR_INVALID_MONITOR_HANDLE, "Expected error code %#x, got %#lx.\n",
2589
2590 monitor = (HMONITOR)(((ULONG_PTR)full_monitor & 0xffff) | ((ULONG_PTR)0x9876 << 16));
2591 SetLastError(0xdeadbeef);
2592 ret = GetMonitorInfoW(monitor, &monitor_info);
2593 ok(!ret, "GetMonitorInfoW succeeded.\n");
2594 ok(GetLastError() == ERROR_INVALID_MONITOR_HANDLE, "Expected error code %#x, got %#lx.\n",
2596
2597 monitor = (HMONITOR)(((ULONG_PTR)full_monitor & 0xffff) | ((ULONG_PTR)0x12345678 << 16));
2598 SetLastError(0xdeadbeef);
2599 ret = GetMonitorInfoW(monitor, &monitor_info);
2600 ok(!ret, "GetMonitorInfoW succeeded.\n");
2601 ok(GetLastError() == ERROR_INVALID_MONITOR_HANDLE, "Expected error code %#x, got %#lx.\n",
2603#else
2604 if ((ULONG_PTR)full_monitor >> 16)
2605 monitor = full_monitor;
2606 else
2607 monitor = (HMONITOR)((ULONG_PTR)full_monitor | ((ULONG_PTR)~0u << 16));
2608 SetLastError(0xdeadbeef);
2609 ret = GetMonitorInfoW(monitor, &monitor_info);
2610 todo_wine_if(((ULONG_PTR)full_monitor >> 16) == 0)
2611 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
2612
2613 monitor = (HMONITOR)((ULONG_PTR)full_monitor & 0xffff);
2614 SetLastError(0xdeadbeef);
2615 ret = GetMonitorInfoW(monitor, &monitor_info);
2616 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
2617
2618 monitor = (HMONITOR)(((ULONG_PTR)full_monitor & 0xffff) | ((ULONG_PTR)0x1234 << 16));
2619 SetLastError(0xdeadbeef);
2620 ret = GetMonitorInfoW(monitor, &monitor_info);
2621 ok(!ret, "GetMonitorInfoW succeeded.\n");
2622 ok(GetLastError() == ERROR_INVALID_MONITOR_HANDLE, "Expected error code %#x, got %#lx.\n",
2624#endif
2625
2626 return TRUE;
2627}
2628
2629static void test_handles(void)
2630{
2631 BOOL ret;
2632
2633 /* Test that monitor handles are user32 handles */
2635 ok(ret, "EnumDisplayMonitors failed, error %#lx.\n", GetLastError());
2636}
2637
2638#define check_display_dc(a, b, c) _check_display_dc(__LINE__, a, b, c)
2639static void _check_display_dc(INT line, HDC hdc, const DEVMODEA *dm, BOOL allow_todo)
2640{
2641#if defined(__REACTOS__) && defined(_MSC_VER)
2642 unsigned char buffer[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256] = {0};
2643#else
2644 unsigned char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])] = {0};
2645#endif
2646 BITMAPINFO *bmi = (BITMAPINFO *)buffer;
2647 DIBSECTION dib;
2648 BITMAP bitmap;
2649 HBITMAP hbmp;
2650 INT value;
2651 BOOL ret;
2652
2655 ok_(__FILE__, line)(value == dm->dmPelsWidth, "Expected HORZRES %ld, got %d.\n",
2656 dm->dmPelsWidth, value);
2657
2660 ok_(__FILE__, line)(value == dm->dmPelsHeight, "Expected VERTRES %ld, got %d.\n",
2661 dm->dmPelsHeight, value);
2662
2666 ok_(__FILE__, line)(value == dm->dmPelsWidth, "Expected DESKTOPHORZRES %ld, got %d.\n",
2667 dm->dmPelsWidth, value);
2668
2672 ok_(__FILE__, line)(value == dm->dmPelsHeight, "Expected DESKTOPVERTRES %ld, got %d.\n",
2673 dm->dmPelsHeight, value);
2674
2676 todo_wine_if(allow_todo)
2677 ok_(__FILE__, line)(value == dm->dmDisplayFrequency, "Expected VREFRESH %ld, got %d.\n",
2679
2681 ok_(__FILE__, line)(value == dm->dmBitsPerPel, "Expected BITSPIXEL %ld, got %d.\n",
2682 dm->dmBitsPerPel, value);
2683
2685 ok_(__FILE__, line)(!!hbmp, "GetCurrentObject failed, error %#lx.\n", GetLastError());
2686
2687 /* Expect hbmp to be a bitmap, not a DIB when GetObjectA() succeeds */
2688 value = GetObjectA(hbmp, sizeof(dib), &dib);
2689 ok(!value || value == sizeof(BITMAP), "GetObjectA failed, value %d.\n", value);
2690
2691 /* Expect GetDIBits() to succeed */
2692 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2694 ok(value, "GetDIBits failed, error %#lx.\n", GetLastError());
2695#ifdef __REACTOS__
2696 ok(bmi->bmiHeader.biCompression == BI_BITFIELDS || broken(bmi->bmiHeader.biCompression == BI_RGB) /* WS03 */, "Got unexpected biCompression %lu.\n", bmi->bmiHeader.biCompression);
2697#else
2698 ok(bmi->bmiHeader.biCompression == BI_BITFIELDS, "Got unexpected biCompression %lu.\n", bmi->bmiHeader.biCompression);
2699#endif
2700
2701 ret = GetObjectA(hbmp, sizeof(bitmap), &bitmap);
2702 /* GetObjectA fails on Win7 and older */
2703 if (ret)
2704 {
2705 ok_(__FILE__, line)(bitmap.bmType == 0, "Expected bmType %d, got %d.\n", 0, bitmap.bmType);
2706 ok_(__FILE__, line)(bitmap.bmWidth == GetSystemMetrics(SM_CXVIRTUALSCREEN),
2707 "Expected bmWidth %d, got %d.\n", GetSystemMetrics(SM_CXVIRTUALSCREEN), bitmap.bmWidth);
2708 ok_(__FILE__, line)(bitmap.bmHeight == GetSystemMetrics(SM_CYVIRTUALSCREEN),
2709 "Expected bmHeight %d, got %d.\n", GetSystemMetrics(SM_CYVIRTUALSCREEN), bitmap.bmHeight);
2710 ok_(__FILE__, line)(bitmap.bmBitsPixel == 32, "Expected bmBitsPixel %d, got %d.\n", 32,
2711 bitmap.bmBitsPixel);
2712 ok_(__FILE__, line)(bitmap.bmWidthBytes == get_bitmap_stride(bitmap.bmWidth, bitmap.bmBitsPixel),
2713 "Expected bmWidthBytes %d, got %d.\n", get_bitmap_stride(bitmap.bmWidth, bitmap.bmBitsPixel),
2714 bitmap.bmWidthBytes);
2715 ok_(__FILE__, line)(bitmap.bmPlanes == 1, "Expected bmPlanes %d, got %d.\n", 1, bitmap.bmPlanes);
2716 ok_(__FILE__, line)(bitmap.bmBits == NULL, "Expected bmBits %p, got %p.\n", NULL, bitmap.bmBits);
2717 }
2718}
2719
2720static void test_display_dc(void)
2721{
2722 static const INT bpps[] = {1, 4, 8, 16, 24, 32};
2723 unsigned char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
2724 HBITMAP hbitmap, hbitmap2, old_hbitmap;
2725 BITMAPINFO *bmi = (BITMAPINFO *)buffer;
2726 INT count, old_count, i, bpp, value;
2727 DWORD device_idx, mode_idx;
2728 DEVMODEA dm, dm2, dm3;
2729 HDC hdc, hdc2, mem_dc;
2730 DISPLAY_DEVICEA dd;
2731 DIBSECTION dib;
2732 BITMAP bitmap;
2733 BOOL ret;
2734 LONG res;
2735#ifdef __REACTOS__
2736 UINT display_bpp;
2737
2738 hdc = GetDC(0);
2739 display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2740 ReleaseDC(0, hdc);
2741#endif
2742
2743 /* Test DCs covering the entire virtual screen */
2744 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2745 ok(!!hdc, "CreateDCA failed.\n");
2746
2747 memset(&dm, 0, sizeof(dm));
2748 dm.dmSize = sizeof(dm);
2750 ok(ret, "EnumDisplaySettingsA failed.\n");
2751
2752 check_display_dc(hdc, &dm, FALSE);
2753
2754 /* Test that CreateCompatibleBitmap() for display DCs creates DDBs */
2756 ok(!!hbitmap, "CreateCompatibleBitmap failed, error %ld.\n", GetLastError());
2757 count = GetObjectW(hbitmap, sizeof(dib), &dib);
2758 ok(count == sizeof(BITMAP), "GetObject failed, count %d.\n", count);
2759 count = GetObjectW(hbitmap, sizeof(bitmap), &bitmap);
2760 ok(count == sizeof(BITMAP), "GetObject failed, count %d.\n", count);
2761 ok(bitmap.bmBitsPixel == dm.dmBitsPerPel, "Expected %ld, got %d.\n", dm.dmBitsPerPel,
2762 bitmap.bmBitsPixel);
2764
2765 /* Test selecting a DDB of a different depth into a display compatible DC */
2766 for (i = 0; i < ARRAY_SIZE(bpps); ++i)
2767 {
2768 winetest_push_context("bpp %d", bpps[i]);
2769
2770 mem_dc = CreateCompatibleDC(hdc);
2771 hbitmap = CreateBitmap(dm.dmPelsWidth, dm.dmPelsHeight, 1, bpps[i], NULL);
2772 ok(!!hbitmap, "CreateBitmap failed, error %ld.\n", GetLastError());
2773 old_hbitmap = SelectObject(mem_dc, hbitmap);
2774#ifdef __REACTOS__
2775 if (bpps[i] != 1 && bpps[i] != display_bpp)
2776#else
2777 if (bpps[i] != 1 && bpps[i] != 32)
2778#endif
2779 ok(!old_hbitmap, "Selecting bitmap succeeded.\n");
2780 else
2781 ok(!!old_hbitmap, "Failed to select bitmap.\n");
2782
2783 SelectObject(mem_dc, old_hbitmap);
2785 DeleteDC(mem_dc);
2786
2788 }
2789
2790 /* Test selecting a DIB of a different depth into a display compatible DC */
2791 for (i = 0; i < ARRAY_SIZE(bpps); ++i)
2792 {
2793 winetest_push_context("bpp %d", bpps[i]);
2794
2795 mem_dc = CreateCompatibleDC(hdc);
2796 memset(buffer, 0, sizeof(buffer));
2797 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2798 bmi->bmiHeader.biWidth = dm.dmPelsWidth;
2800 bmi->bmiHeader.biBitCount = bpps[i];
2801 bmi->bmiHeader.biPlanes = 1;
2804 ok(!!hbitmap, "CreateDIBSection failed, error %ld.\n", GetLastError());
2805 old_hbitmap = SelectObject(mem_dc, hbitmap);
2806 ok(!!old_hbitmap, "Failed to select bitmap.\n");
2807
2808 value = GetDeviceCaps(mem_dc, BITSPIXEL);
2809#ifdef __REACTOS__
2810 ok(value == display_bpp, "Expected %d, got %d.\n", display_bpp, value);
2811#else
2812 ok(value == 32, "Expected 32, got %d.\n", value);
2813#endif
2814 value = GetDeviceCaps(mem_dc, NUMCOLORS);
2815 ok(value == -1, "Expected -1, got %d.\n", value);
2816
2817 SelectObject(mem_dc, old_hbitmap);
2819 DeleteDC(mem_dc);
2820
2822 }
2823
2824 /* Test NUMCOLORS for display DCs */
2825 for (i = ARRAY_SIZE(bpps) - 1; i >= 0; --i)
2826 {
2827 winetest_push_context("bpp %d", bpps[i]);
2828
2830 ok(ret, "EnumDisplaySettingsA failed.\n");
2831 if (bpps[i] == dm.dmBitsPerPel)
2832 {
2834 }
2835 else
2836 {
2837 memset(&dm2, 0, sizeof(dm2));
2838 dm2.dmSize = sizeof(dm2);
2839 for (mode_idx = 0; EnumDisplaySettingsA(NULL, mode_idx, &dm2); ++mode_idx)
2840 {
2841 if (dm2.dmBitsPerPel == bpps[i])
2842 break;
2843 }
2844 if (dm2.dmBitsPerPel != bpps[i])
2845 {
2846 skip("%d-bit display mode not found.\n", bpps[i]);
2848 continue;
2849 }
2850
2852 /* Win8 TestBots */
2854 "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
2855 }
2856
2858 {
2860 ok(value == (bpps[i] == 4 ? 1 : bpps[i]), "Expected %d, got %d.\n",
2861 (bpps[i] == 4 ? 1 : bpps[i]), value);
2862
2864 if (bpps[i] > 8 || (bpps[i] == 8 && LOBYTE(LOWORD(GetVersion())) >= 6))
2865#ifdef __REACTOS__
2866 ok(value == -1 || broken(value == 20) /* Vista */, "Expected -1, got %d.\n", value);
2867#else
2868 ok(value == -1, "Expected -1, got %d.\n", value);
2869#endif
2870 else if (bpps[i] == 8 && LOBYTE(LOWORD(GetVersion())) < 6)
2871 ok(value > 16 && value <= 256, "Got %d.\n", value);
2872 else
2873 ok(value == 1 << bpps[i], "Expected %d, got %d.\n", 1 << bpps[i], value);
2874 }
2876 }
2878 /* Win8 TestBots */
2880 "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
2881
2882 /* Test selecting a DDB of the same color depth into a display compatible DC */
2884 ok(ret, "EnumDisplaySettingsA failed.\n");
2885
2886 mem_dc = CreateCompatibleDC(hdc);
2887 bpp = GetDeviceCaps(mem_dc, BITSPIXEL);
2888 ok(bpp == dm.dmBitsPerPel, "Expected bpp %ld, got %d.\n", dm.dmBitsPerPel, bpp);
2890 count = GetObjectW(hbitmap, sizeof(bitmap), &bitmap);
2891 ok(count == sizeof(BITMAP), "GetObject failed, count %d.\n", count);
2892 ok(bitmap.bmBitsPixel == dm.dmBitsPerPel, "Expected %ld, got %d.\n", dm.dmBitsPerPel, bitmap.bmBitsPixel);
2893 old_hbitmap = SelectObject(mem_dc, hbitmap);
2894 ok(!!old_hbitmap, "Failed to select bitmap.\n");
2895 SelectObject(mem_dc, old_hbitmap);
2896 DeleteDC(mem_dc);
2897
2898 /* Test that the same bitmap handle is used for different display DCs */
2899 old_hbitmap = GetCurrentObject(hdc, OBJ_BITMAP);
2900
2901 hdc2 = CreateDCA("DISPLAY", NULL, NULL, NULL);
2902 ok(!!hdc2, "CreateDCA failed.\n");
2903 hbitmap2 = GetCurrentObject(hdc2, OBJ_BITMAP);
2904 ok(hbitmap2 == old_hbitmap, "Expected the same bitmap handle.\n");
2905
2906 /* Tests after mode changes to a mode with different resolution */
2907 memset(&dm2, 0, sizeof(dm2));
2908 dm2.dmSize = sizeof(dm2);
2909 for (mode_idx = 0; EnumDisplaySettingsA(NULL, mode_idx, &dm2); ++mode_idx)
2910 {
2911 if (dm2.dmPelsWidth != dm.dmPelsWidth || dm2.dmPelsHeight != dm.dmPelsHeight)
2912 break;
2913 }
2914 if (dm2.dmPelsWidth != dm.dmPelsWidth || dm2.dmPelsHeight != dm.dmPelsHeight)
2915 {
2917 /* Win8 TestBots */
2919 "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
2921 {
2922 check_display_dc(hdc, &dm2, FALSE);
2923
2924 /* Test that a different bitmap handle is used for the display DC after resolution changes */
2925 hbitmap2 = GetCurrentObject(hdc, OBJ_BITMAP);
2926 ok(hbitmap2 != old_hbitmap, "Expected a different bitmap handle.\n");
2927
2928 /* Test that the old display bitmap is invalid after waiting for a bit. This suggests
2929 * that the bitmap got released. And note that hdc2 has not been deleted yet and hdc2
2930 * has the same bitmap handle so the display bitmap is not being reference counted */
2931 Sleep(500);
2932 count = GetObjectW(old_hbitmap, sizeof(bitmap), &bitmap);
2933 ok(!count, "GetObject failed, count %d.\n", count);
2934 }
2935 }
2936 else
2937 {
2938 win_skip("Failed to find a different resolution.\n");
2939 }
2940 DeleteDC(hdc2);
2941
2942 /* Tests after mode changes to a mode with different resolution and color depth */
2943 memset(&dm2, 0, sizeof(dm2));
2944 dm2.dmSize = sizeof(dm2);
2945 for (mode_idx = 0; EnumDisplaySettingsA(NULL, mode_idx, &dm2); ++mode_idx)
2946 {
2947 if (dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight &&
2948 dm2.dmBitsPerPel != dm.dmBitsPerPel && dm2.dmBitsPerPel != 1)
2949 break;
2950 }
2951 if (dm2.dmBitsPerPel && dm2.dmBitsPerPel != dm.dmBitsPerPel)
2952 {
2954 /* Win8 TestBots */
2956 "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
2958 {
2959 check_display_dc(hdc, &dm2, FALSE);
2960
2961 /* Test selecting a compatible bitmap of a different color depth previously created for
2962 * a display DC into a new compatible DC */
2963 count = GetObjectW(hbitmap, sizeof(bitmap), &bitmap);
2964 ok(count == sizeof(BITMAP), "GetObject failed, count %d.\n", count);
2965 ok(bitmap.bmBitsPixel == dm.dmBitsPerPel, "Expected %ld, got %d.\n", dm.dmBitsPerPel,
2966 bitmap.bmBitsPixel);
2967
2968 /* Note that hbitmap is of a different color depth and it can be successfully selected
2969 * into the new compatible DC */
2970 mem_dc = CreateCompatibleDC(hdc);
2971 bpp = GetDeviceCaps(mem_dc, BITSPIXEL);
2972 ok(bpp == dm2.dmBitsPerPel, "Expected bpp %ld, got %d.\n", dm2.dmBitsPerPel, bpp);
2973 old_hbitmap = SelectObject(mem_dc, hbitmap);
2974 ok(!!old_hbitmap, "Failed to select bitmap.\n");
2975 bpp = GetDeviceCaps(mem_dc, BITSPIXEL);
2976 ok(bpp == dm2.dmBitsPerPel, "Expected bpp %ld, got %d.\n", dm2.dmBitsPerPel, bpp);
2977 SelectObject(mem_dc, old_hbitmap);
2978 DeleteDC(mem_dc);
2980
2981 /* Test selecting a DDB of a different color depth into a display compatible DC */
2982 for (i = 0; i < ARRAY_SIZE(bpps); ++i)
2983 {
2984 winetest_push_context("bpp %d", bpps[i]);
2985
2986 mem_dc = CreateCompatibleDC(hdc);
2987 hbitmap = CreateBitmap(dm2.dmPelsWidth, dm2.dmPelsHeight, 1, bpps[i], NULL);
2988 ok(!!hbitmap, "CreateBitmap failed, error %ld.\n", GetLastError());
2989 old_hbitmap = SelectObject(mem_dc, hbitmap);
2990 /* On Win7 dual-QXL test bot and XP, only 1-bit DDBs and DDBs with the same color
2991 * depth can be selected to the compatible DC. On newer versions of Windows, only
2992 * 1-bit and 32-bit DDBs can be selected into the compatible DC even if
2993 * GetDeviceCaps(BITSPIXEL) reports a different color depth, for example, 16-bit.
2994 * It's most likely due to the fact that lower color depth are emulated on newer
2995 * versions of Windows as the real color depth is still 32-bit */
2996 if (bpps[i] != 1 && bpps[i] != 32)
2997 todo_wine_if(bpps[i] == dm2.dmBitsPerPel)
2998 ok(!old_hbitmap || broken(!!old_hbitmap) /* Win7 dual-QXL test bot and XP */,
2999 "Selecting bitmap succeeded.\n");
3000 else
3001 ok(!!old_hbitmap || broken(!old_hbitmap) /* Win7 dual-QXL test bot and XP */,
3002 "Failed to select bitmap.\n");
3003
3004 SelectObject(mem_dc, old_hbitmap);
3006 DeleteDC(mem_dc);
3007
3009 }
3010 hbitmap = NULL;
3011
3013 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
3014 }
3015 }
3016 else
3017 {
3018 win_skip("Failed to find a required display mode.\n");
3019 }
3020
3021 if (hbitmap)
3023 DeleteDC(hdc);
3024
3025 /* Test DCs covering a specific monitor */
3026 dd.cb = sizeof(dd);
3027 for (device_idx = 0; EnumDisplayDevicesA(NULL, device_idx, &dd, 0); ++device_idx)
3028 {
3030 continue;
3031
3032 memset(&dm, 0, sizeof(dm));
3033 dm.dmSize = sizeof(dm);
3035 ok(ret, "EnumDisplaySettingsA %s failed.\n", dd.DeviceName);
3036
3038 ok(!!hdc, "CreateDCA %s failed.\n", dd.DeviceName);
3039
3040 check_display_dc(hdc, &dm, FALSE);
3041
3042 /* Tests after mode changes to a different resolution */
3043 memset(&dm2, 0, sizeof(dm2));
3044 dm2.dmSize = sizeof(dm2);
3045 for (mode_idx = 0; EnumDisplaySettingsA(dd.DeviceName, mode_idx, &dm2); ++mode_idx)
3046 {
3047 if (dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight)
3048 break;
3049 }
3050 ok(dm2.dmPelsWidth && dm2.dmPelsWidth != dm.dmPelsWidth && dm2.dmPelsHeight != dm.dmPelsHeight,
3051 "Failed to find a different resolution for %s.\n", dd.DeviceName);
3052
3054 ok(res == DISP_CHANGE_SUCCESSFUL || broken(res == DISP_CHANGE_FAILED), /* Win8 TestBots */
3055 "ChangeDisplaySettingsExA %s returned unexpected %ld.\n", dd.DeviceName, res);
3057 {
3058 win_skip("Failed to change display mode for %s.\n", dd.DeviceName);
3059 DeleteDC(hdc);
3060 continue;
3061 }
3062
3063 check_display_dc(hdc, &dm2, FALSE);
3064
3065 /* Tests after mode changes to a different color depth */
3066 memset(&dm2, 0, sizeof(dm2));
3067 dm2.dmSize = sizeof(dm2);
3068 for (mode_idx = 0; EnumDisplaySettingsA(dd.DeviceName, mode_idx, &dm2); ++mode_idx)
3069 {
3070 if (dm2.dmBitsPerPel != dm.dmBitsPerPel)
3071 break;
3072 }
3073 if (dm2.dmBitsPerPel && dm2.dmBitsPerPel != dm.dmBitsPerPel)
3074 {
3076 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
3077
3078 check_display_dc(hdc, &dm2, FALSE);
3079
3081 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA returned unexpected %ld.\n", res);
3082 }
3083 else
3084 {
3085 win_skip("Failed to find a different color depth other than %lu.\n", dm.dmBitsPerPel);
3086 }
3087
3088 /* Tests after monitor detach */
3090 ok(ret, "EnumDisplaySettingsA %s failed.\n", dd.DeviceName);
3091
3093 {
3094 old_count = GetSystemMetrics(SM_CMONITORS);
3095
3096 memset(&dm3, 0, sizeof(dm3));
3097 dm3.dmSize = sizeof(dm3);
3099 ok(ret, "EnumDisplaySettingsA %s failed.\n", dd.DeviceName);
3100
3102 dm3.dmPelsWidth = 0;
3103 dm3.dmPelsHeight = 0;
3105 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
3106 dd.DeviceName, res);
3108 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
3109 dd.DeviceName, res);
3110
3112 ok(count == old_count - 1, "Expected monitor count %d, got %d.\n", old_count - 1, count);
3113
3114 /* Should report the same values before detach */
3115 check_display_dc(hdc, &dm2, TRUE);
3116 }
3117
3119 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
3120 dd.DeviceName, res);
3122 ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %ld.\n",
3123 dd.DeviceName, res);
3124 DeleteDC(hdc);
3125 }
3126}
3127
3129 LPRECT lprcMonitor, LPARAM dwData)
3130{
3132 static int index;
3133
3134 info.cbSize = sizeof(info);
3135 if (GetMonitorInfoW(hMonitor, (MONITORINFO*)&info))
3136 {
3137 printf("Monitor %d %7s [%02lx] %s %s\n", index,
3138 (info.dwFlags & MONITORINFOF_PRIMARY) ? "primary" : "",
3139 info.dwFlags, wine_dbgstr_rect(&info.rcMonitor),
3140 wine_dbgstr_w(info.szDevice));
3141 }
3142 index++;
3143 return TRUE;
3144}
3145
3146static void test_fullscreen(int argc, char **argv)
3147{
3148 HANDLE event0, event1;
3149 DWORD wait_result;
3150 DWORD flags = 0;
3151 DEVMODEA dm;
3152 LONG res;
3153
3154 if (argc < 7)
3155 {
3156 ok(0, "too few arguments.\n");
3157 return;
3158 }
3159
3160 res = sscanf(argv[4], "%lx", &flags);
3161 ok(res == 1, "sscanf returned unexpected %ld.\n", res);
3162
3163 event0 = OpenEventA(EVENT_MODIFY_STATE, FALSE, argv[5]);
3164 ok(!!event0, "OpenEventA failed, error %#lx\n", GetLastError());
3165 event1 = OpenEventA(SYNCHRONIZE, FALSE, argv[6]);
3166 ok(!!event1, "OpenEventA failed, error %#lx\n", GetLastError());
3167
3168 memset(&dm, 0, sizeof(dm));
3169 dm.dmSize = sizeof(dm);
3171 dm.dmPelsWidth = 640;
3172 dm.dmPelsHeight = 480;
3175 "ChangeDisplaySettingsExA %s returned unexpected %ld.\n", argv[3], res);
3176
3177 SetEvent(event0);
3178 CloseHandle(event0);
3179
3180 wait_result = WaitForSingleObject(event1, 7000);
3181 ok(wait_result == WAIT_OBJECT_0, "WaitForSingleObject returned %lx.\n", wait_result);
3182 CloseHandle(event1);
3183}
3184
3185#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x600
3186static void get_monitor_dpi_scale( HMONITOR monitor, int *min, int *cur, int *max )
3187{
3188 DISPLAYCONFIG_GET_SOURCE_DPI_SCALE req = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_DPI_SCALE, .size = sizeof(req)}};
3189 MONITORINFOEXW info = {.cbSize = sizeof(MONITORINFOEXW)};
3190 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_desc = {{0}};
3191 D3DKMT_CLOSEADAPTER close_desc = {0};
3193 UINT ret;
3194
3195 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&info );
3196 ok( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() );
3197
3198 wcscpy( open_desc.DeviceName, info.szDevice );
3200 ok( !status, "D3DKMTOpenAdapterFromGdiDisplayName returned %#lx\n", status );
3201
3202 req.header.adapterId = open_desc.AdapterLuid;
3203 req.header.id = open_desc.VidPnSourceId;
3204 ret = pDisplayConfigGetDeviceInfo( &req.header );
3205 todo_wine ok( !ret, "DisplayConfigGetDeviceInfo returned %u\n", ret );
3206 *min = req.minRelativeScaleStep;
3207 *cur = req.curRelativeScaleStep;
3208 *max = req.maxRelativeScaleStep;
3209
3210 close_desc.hAdapter = open_desc.hAdapter;
3211 status = D3DKMTCloseAdapter( &close_desc );
3212 ok( !status, "D3DKMTCloseAdapter returned %#lx\n", status );
3213}
3214
3215static void set_monitor_dpi_scale( HMONITOR monitor, int scale )
3216{
3217 DISPLAYCONFIG_SET_SOURCE_DPI_SCALE req = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_SET_SOURCE_DPI_SCALE, .size = sizeof(req)}};
3218 MONITORINFOEXW info = {.cbSize = sizeof(MONITORINFOEXW)};
3219 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_desc = {{0}};
3220 D3DKMT_CLOSEADAPTER close_desc = {0};
3222 UINT ret;
3223
3224 if (!pDisplayConfigSetDeviceInfo) return;
3225
3226 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&info );
3227 ok( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() );
3228
3229 wcscpy( open_desc.DeviceName, info.szDevice );
3231 ok( !status, "D3DKMTOpenAdapterFromGdiDisplayName returned %#lx\n", status );
3232
3233 req.header.adapterId = open_desc.AdapterLuid;
3234 req.header.id = open_desc.VidPnSourceId;
3235 req.relativeScaleStep = scale;
3236 ret = pDisplayConfigSetDeviceInfo( &req.header );
3237 todo_wine ok( !ret, "DisplayConfigSetDeviceInfo returned %u\n", ret );
3238
3239 close_desc.hAdapter = open_desc.hAdapter;
3240 status = D3DKMTCloseAdapter( &close_desc );
3241 ok( !status, "D3DKMTCloseAdapter returned %#lx\n", status );
3242}
3243#endif // __REACTOS__ || DLL_EXPORT_VERSION >= 0x600
3244
3246{
3247 UINT eff_x, eff_y, ang_x, ang_y, raw_x, raw_y; /* default monitor DPIs */
3250};
3251
3252#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x600
3254{
3255 struct monitor_info *info = (struct monitor_info *)lparam;
3256 if (info->handle == handle) info->rect = *rect;
3257 return TRUE;
3258}
3259
3260#define check_physical_dpi(a,b,c,d,e,f) check_physical_dpi_(__LINE__,a,b,c,d,e,f,FALSE)
3261static void check_physical_dpi_( int line, HWND hwnd, UINT log_x, UINT log_y, UINT phy_x, UINT phy_y, BOOL expect_ret, BOOL todo_ret )
3262{
3263 POINT log = {log_x, log_y}, phy = {phy_x, phy_y}, pt;
3264 UINT ret;
3265
3266 pt = log;
3267 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &pt );
3268 todo_wine_if(todo_ret)
3269 ok_(__FILE__, line)( ret == expect_ret, "LogicalToPhysicalPointForPerMonitorDPI returned %u\n", ret );
3270 ok_(__FILE__, line)( pt.x == phy.x && pt.y == phy.y, "got physical %s\n", wine_dbgstr_point(&pt) );
3271}
3272
3273#define check_logical_dpi(a,b,c,d,e,f) check_logical_dpi_(__LINE__,a,b,c,d,e,f,FALSE)
3274static void check_logical_dpi_( int line, HWND hwnd, UINT phy_x, UINT phy_y, UINT log_x, UINT log_y, BOOL expect_ret, BOOL todo_ret )
3275{
3276 POINT log = {log_x, log_y}, phy = {phy_x, phy_y}, pt;
3277 UINT ret;
3278
3279 pt = phy;
3280 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &pt );
3281 todo_wine_if(todo_ret)
3282 ok_(__FILE__, line)( ret == expect_ret, "PhysicalToLogicalPointForPerMonitorDPI returned %u\n", ret );
3283 ok_(__FILE__, line)( pt.x == log.x && pt.y == log.y, "got logical %s\n", wine_dbgstr_point(&pt) );
3284}
3285
3286#define check_logical_physical_dpi(a,b,c,d,e,f) check_logical_physical_dpi_(__LINE__,a,b,c,d,e,f,FALSE)
3287static void check_logical_physical_dpi_( int line, HWND hwnd, UINT log_x, UINT log_y, UINT phy_x, UINT phy_y, BOOL expect_ret, BOOL todo_ret )
3288{
3289 check_logical_dpi_( line, hwnd, phy_x, phy_y, log_x, log_y, expect_ret, todo_ret );
3290 check_physical_dpi_( line, hwnd, log_x, log_y, phy_x, phy_y, expect_ret, todo_ret );
3291}
3292
3293static void test_monitor_dpi_awareness( const struct monitor_info *infos, UINT count, int step, UINT system_dpi,
3294 const struct monitor_info *info, struct monitor_info *phys, BOOL is_virtual )
3295{
3296 static const unsigned int scales[] = {100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500};
3297 static const DPI_AWARENESS_CONTEXT tests[] =
3298 {
3299 0,
3305 (DPI_AWARENESS_CONTEXT)0x7811,
3306 };
3307 RECT virtual = {0}, scaled_virtual = {0}, monitor = {0}, scaled = {0}, primary = {0}, rect, expect_rect;
3308 struct monitor_info tmp_info = {.handle = info->handle};
3309 UINT ret, i, x, y, expect_width, expect_height;
3310 HWND unaware_hwnd, aware_hwnd, primary_hwnd;
3311 MONITORINFO mi = {.cbSize = sizeof(mi)};
3312 DPI_AWARENESS_CONTEXT old_ctx = 0, cur_ctx, ctx;
3313 float scale = scales[step], scale_x, scale_y;
3314 HDC hdc;
3315
3316 scale_x = (info->rect.right - info->rect.left) / (float)(phys->rect.right - phys->rect.left);
3317 scale_y = (info->rect.bottom - info->rect.top) / (float)(phys->rect.bottom - phys->rect.top);
3318
3319 for (i = 0; i < count; i++)
3320 {
3321 if (infos[i].rect.left == 0 && infos[i].rect.top == 0) primary = infos[i].rect;
3322
3323 if (info - infos + i) UnionRect( &scaled_virtual, &scaled_virtual, &infos[i].rect );
3324 else
3325 {
3326 scaled = monitor = infos[i].rect;
3327 scaled.right = scaled.left + MulDiv( scaled.right - scaled.left, 100, scale );
3328 scaled.bottom = scaled.top + MulDiv( scaled.bottom - scaled.top, 100, scale );
3329 UnionRect( &scaled_virtual, &scaled_virtual, &scaled );
3330 }
3331
3332 UnionRect( &virtual, &virtual, &infos[i].rect );
3333 }
3334
3335 unaware_hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, monitor.left + 100,
3336 monitor.top + 100, 100, 100, NULL, NULL, NULL, NULL );
3337 ok( unaware_hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() );
3338 ctx = pGetWindowDpiAwarenessContext( unaware_hwnd );
3339 ok( ctx == (DPI_AWARENESS_CONTEXT)0x6010, "GetWindowDpiAwarenessContext returned %#Ix\n", (UINT_PTR)ctx );
3340 ret = pGetDpiForWindow( unaware_hwnd );
3341 ok( ret == 96, "GetDpiForWindow returned %u\n", ret );
3342
3343 SetRect( &expect_rect, 0, 0, 100, 100 );
3344 ret = GetClientRect( unaware_hwnd, &rect );
3345 ok( ret, "GetClientRect failed, error %lu\n", GetLastError() );
3346 ok( EqualRect( &rect, &expect_rect ), "GetClientRect returned %s\n", wine_dbgstr_rect(&rect) );
3347
3348 SetRect( &expect_rect, monitor.left + 100, monitor.top + 100, monitor.left + 200, monitor.top + 200 );
3349 ret = GetWindowRect( unaware_hwnd, &rect );
3350 ok( ret, "GetWindowRect failed, error %lu\n", GetLastError() );
3351 ok( EqualRect( &rect, &expect_rect ), "GetWindowRect returned %s\n", wine_dbgstr_rect(&rect) );
3352
3353 check_logical_physical_dpi( unaware_hwnd, monitor.left + 99, monitor.top + 99,
3354 monitor.left + 99, monitor.top + 99, FALSE );
3355 check_logical_physical_dpi( unaware_hwnd, monitor.left + 100, monitor.top + 100,
3356 monitor.left + 1 * scale, monitor.top + 1 * scale, TRUE );
3357 check_logical_physical_dpi( unaware_hwnd, monitor.left + 200, monitor.top + 200,
3358 monitor.left + 2 * scale, monitor.top + 2 * scale, TRUE );
3359
3360 /* physical to logical conversion is lossy in the area of the screen where coordinate systems overlap but don't match */
3361 check_physical_dpi( unaware_hwnd, monitor.left + 201, monitor.top + 201,
3362 monitor.left + 201, monitor.top + 201, FALSE );
3363 check_logical_dpi_( __LINE__, unaware_hwnd, monitor.left + 201, monitor.top + 201,
3364 monitor.left + MulDiv( 201, 100, scale ), monitor.top + MulDiv( 201, 100, scale ), TRUE, TRUE );
3365
3366 check_logical_physical_dpi( unaware_hwnd, monitor.left + 2 * scale + 1, monitor.top + 2 * scale + 1,
3367 monitor.left + 2 * scale + 1, monitor.top + 2 * scale + 1, FALSE );
3368
3369 for (i = 0; i < ARRAY_SIZE(tests); i++)
3370 {
3373 if (tests[i]) old_ctx = pSetThreadDpiAwarenessContext( tests[i] );
3374 cur_ctx = pGetThreadDpiAwarenessContext();
3375
3376 winetest_push_context( "ctx %p", tests[i] );
3377
3379 ok( ret == virtual.left, "got SM_XVIRTUALSCREEN %d\n", ret );
3381 ok( ret == virtual.top, "got SM_YVIRTUALSCREEN %d\n", ret );
3382
3383 if (monitor_aware)
3384 {
3385 expect_width = virtual.right - virtual.left;
3386 expect_height = virtual.bottom - virtual.top;
3387 }
3388 else
3389 {
3390 expect_width = scaled_virtual.right - scaled_virtual.left;
3391 expect_height = scaled_virtual.bottom - scaled_virtual.top;
3392 }
3394 ok( ret == expect_width, "got SM_CXVIRTUALSCREEN %d\n", ret );
3396 ok( ret == expect_height, "got SM_CYVIRTUALSCREEN %d\n", ret );
3397
3398 if (monitor.left || monitor.top)
3399 {
3400 expect_width = primary.right - primary.left;
3401 expect_height = primary.bottom - primary.top;
3402 }
3403 else if (monitor_aware)
3404 {
3405 expect_width = monitor.right - monitor.left;
3406 expect_height = monitor.bottom - monitor.top;
3407 }
3408 else
3409 {
3410 expect_width = scaled.right - scaled.left;
3411 expect_height = scaled.bottom - scaled.top;
3412 }
3414 ok( ret == expect_width, "got SM_CXSCREEN %d\n", ret );
3416 ok( ret == expect_height, "got SM_CYSCREEN %d\n", ret );
3417
3418 hdc = GetDC( NULL );
3419 ok( !!hdc, "GetDC failed\n" );
3421 ok( ret == system_dpi, "got LOGPIXELSX %d\n", ret );
3423 ok( ret == system_dpi, "got LOGPIXELSY %d\n", ret );
3425 ok( ret == expect_width, "got HORZRES %u\n", ret );
3427 ok( ret == expect_height, "got VERTRES %u\n", ret );
3428 DeleteDC( hdc );
3429
3430 ret = GetMonitorInfoW( info->handle, &mi );
3431 ok( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() );
3432 ok( mi.dwFlags == (monitor.left || monitor.top ? 0 : MONITORINFOF_PRIMARY), "got dwFlags %#lx\n", mi.dwFlags );
3433 if (monitor_aware) ok( EqualRect( &monitor, &mi.rcMonitor ), "got rect %s\n", wine_dbgstr_rect(&mi.rcMonitor) );
3434 else ok( EqualRect( &scaled, &mi.rcMonitor ), "got rect %s\n", wine_dbgstr_rect(&mi.rcMonitor) );
3435 ok( mi.rcWork.top >= mi.rcMonitor.top, "got rect %s\n", wine_dbgstr_rect(&mi.rcWork) );
3436 ok( mi.rcWork.left >= mi.rcMonitor.left, "got rect %s\n", wine_dbgstr_rect(&mi.rcWork) );
3437 ok( mi.rcWork.right <= mi.rcMonitor.right, "got rect %s\n", wine_dbgstr_rect(&mi.rcWork) );
3438 ok( mi.rcWork.bottom <= mi.rcMonitor.bottom, "got rect %s\n", wine_dbgstr_rect(&mi.rcWork) );
3439
3441 ok( EqualRect( &tmp_info.rect, &mi.rcMonitor ), "got rect %s\n", wine_dbgstr_rect(&tmp_info.rect) );
3442
3443 ret = pGetDpiForMonitorInternal( info->handle, MDT_EFFECTIVE_DPI, &x, &y );
3444 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3445 if (monitor_aware)
3446 {
3447 ok( x == MulDiv( system_dpi, scale, 100 ), "got MDT_EFFECTIVE_DPI x %d\n", x );
3448 ok( y == MulDiv( system_dpi, scale, 100 ), "got MDT_EFFECTIVE_DPI y %d\n", y );
3449 }
3450 else
3451 {
3452 ok( x == system_dpi, "got MDT_EFFECTIVE_DPI x %d\n", x );
3453 ok( y == system_dpi, "got MDT_EFFECTIVE_DPI y %d\n", y );
3454 }
3455
3456 ret = pGetDpiForMonitorInternal( info->handle, MDT_ANGULAR_DPI, &x, &y );
3457 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3458 if (monitor_aware && !is_virtual)
3459 {
3460 ok( x == phys->ang_x, "got MDT_ANGULAR_DPI x %u\n", x );
3461 ok( y == phys->ang_y, "got MDT_ANGULAR_DPI y %u\n", y );
3462 }
3463 else if (monitor_aware)
3464 {
3465 todo_wine ok( fabs( x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI x %u\n", x );
3466 todo_wine ok( fabs( y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI y %u\n", y );
3467 }
3468 else if (!is_virtual)
3469 {
3470 ok( x == MulDiv( phys->ang_x, 100, scale ), "got MDT_ANGULAR_DPI x %d\n", x );
3471 ok( y == MulDiv( phys->ang_y, 100, scale ), "got MDT_ANGULAR_DPI y %d\n", y );
3472 }
3473 else
3474 {
3475 todo_wine ok( fabs( x - system_dpi * scale_x * 100 / scale ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI x %d\n", x );
3476 todo_wine ok( fabs( y - system_dpi * scale_y * 100 / scale ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI y %d\n", y );
3477 }
3478
3479 ret = pGetDpiForMonitorInternal( info->handle, MDT_RAW_DPI, &x, &y );
3480 ok( ret || GetLastError() == ERROR_NOT_SUPPORTED, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3481 if (!ret)
3482 {
3483 ok( x == 0, "got MDT_RAW_DPI x %u\n", x );
3484 ok( y == 0, "got MDT_RAW_DPI y %u\n", y );
3485 }
3486 else if (monitor_aware && !is_virtual)
3487 {
3488 ok( x == phys->raw_x, "got MDT_RAW_DPI x %u\n", x );
3489 ok( y == phys->raw_y, "got MDT_RAW_DPI y %u\n", y );
3490 }
3491 else if (monitor_aware)
3492 {
3493 todo_wine ok( fabs( x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_RAW_DPI x %u\n", x );
3494 todo_wine ok( fabs( y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_RAW_DPI y %u\n", y );
3495 }
3496 else if (!is_virtual)
3497 {
3498 ok( x == MulDiv( phys->raw_x, 100, scale ), "got MDT_RAW_DPI x %d\n", x );
3499 ok( y == MulDiv( phys->raw_y, 100, scale ), "got MDT_RAW_DPI y %d\n", y );
3500 }
3501 else
3502 {
3503 todo_wine ok( fabs( x - system_dpi * scale_x * 100 / scale ) < system_dpi * 0.05, "got MDT_RAW_DPI x %d\n", x );
3504 todo_wine ok( fabs( y - system_dpi * scale_y * 100 / scale ) < system_dpi * 0.05, "got MDT_RAW_DPI y %d\n", y );
3505 }
3506
3507
3508 ctx = pGetWindowDpiAwarenessContext( unaware_hwnd );
3509 ok( ctx == (DPI_AWARENESS_CONTEXT)0x6010, "GetWindowDpiAwarenessContext returned %#Ix\n", (UINT_PTR)ctx );
3510 ret = pGetDpiForWindow( unaware_hwnd );
3511 ok( ret == 96, "GetDpiForWindow returned %u\n", ret );
3512
3513 if (monitor_aware) SetRect( &expect_rect, 0, 0, scale, scale );
3514 else SetRect( &expect_rect, 0, 0, 100, 100 );
3515 ret = GetClientRect( unaware_hwnd, &rect );
3516 ok( ret, "GetClientRect failed, error %lu\n", GetLastError() );
3517 ok( EqualRect( &rect, &expect_rect ), "GetClientRect returned %s\n", wine_dbgstr_rect(&rect) );
3518
3519 if (monitor_aware) SetRect( &expect_rect, monitor.left + scale, monitor.top + scale, monitor.left + 2 * scale, monitor.top + 2 * scale );
3520 else SetRect( &expect_rect, monitor.left + 100, monitor.top + 100, monitor.left + 200, monitor.top + 200 );
3521 ret = GetWindowRect( unaware_hwnd, &rect );
3522 ok( ret, "GetWindowRect failed, error %lu\n", GetLastError() );
3523 ok( EqualRect( &rect, &expect_rect ), "GetWindowRect returned %s\n", wine_dbgstr_rect(&rect) );
3524
3525
3526 aware_hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, mi.rcWork.left + 200,
3527 mi.rcWork.top + 200, 100, 100, NULL, NULL, NULL, NULL );
3528 ok( aware_hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() );
3529
3530 ctx = pGetWindowDpiAwarenessContext( aware_hwnd );
3532 ok( ctx == cur_ctx, "GetWindowDpiAwarenessContext returned %p vs %p\n", ctx, cur_ctx );
3533 ret = pGetDpiForWindow( aware_hwnd );
3534 if (monitor_aware) ok( ret == MulDiv( 96, scale, 100 ), "GetDpiForWindow returned %u\n", ret );
3535 else ok( ret == 96, "GetDpiForWindow returned %u\n", ret );
3536
3537 SetRect( &expect_rect, 0, 0, 100, 100 );
3538 ret = GetClientRect( aware_hwnd, &rect );
3539 ok( ret, "GetClientRect failed, error %lu\n", GetLastError() );
3540 ok( EqualRect( &rect, &expect_rect ), "GetClientRect returned %s\n", wine_dbgstr_rect(&rect) );
3541
3542 SetRect( &expect_rect, mi.rcWork.left + 200, mi.rcWork.top + 200, mi.rcWork.left + 300, mi.rcWork.top + 300 );
3543 ret = GetWindowRect( aware_hwnd, &rect );
3544 ok( ret, "GetWindowRect failed, error %lu\n", GetLastError() );
3545 ok( EqualRect( &rect, &expect_rect ), "GetWindowRect returned %s\n", wine_dbgstr_rect(&rect) );
3546
3547
3548 primary_hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, primary.left + 300,
3549 primary.top + 300, 100, 100, NULL, NULL, NULL, NULL );
3550 ok( primary_hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() );
3551
3552 ctx = pGetWindowDpiAwarenessContext( primary_hwnd );
3554 ok( ctx == cur_ctx, "GetWindowDpiAwarenessContext returned %#Ix\n", (UINT_PTR)ctx );
3555 ret = pGetDpiForWindow( primary_hwnd );
3556 if (!monitor_aware) ok( ret == 96, "GetDpiForWindow returned %u\n", ret );
3557 else if (EqualRect( &primary, &monitor )) ok( ret == MulDiv( 96, scale, 100 ), "GetDpiForWindow returned %u\n", ret );
3558 else ok( ret == 96, "GetDpiForWindow returned %u\n", ret );
3559
3560 SetRect( &expect_rect, 0, 0, 100, 100 );
3561 ret = GetClientRect( primary_hwnd, &rect );
3562 ok( ret, "GetClientRect failed, error %lu\n", GetLastError() );
3563 ok( EqualRect( &rect, &expect_rect ), "GetClientRect returned %s\n", wine_dbgstr_rect(&rect) );
3564
3565 SetRect( &expect_rect, primary.left + 300, primary.top + 300, primary.left + 400, primary.top + 400 );
3566 ret = GetWindowRect( primary_hwnd, &rect );
3567 ok( ret, "GetWindowRect failed, error %lu\n", GetLastError() );
3568 ok( EqualRect( &rect, &expect_rect ), "GetWindowRect returned %s\n", wine_dbgstr_rect(&rect) );
3569
3570
3571 check_logical_physical_dpi( unaware_hwnd, monitor.left + 99, monitor.top + 99,
3572 monitor.left + 99, monitor.top + 99, FALSE );
3573 if (monitor_aware)
3574 {
3575 check_logical_physical_dpi_( __LINE__, unaware_hwnd, monitor.left + 100, monitor.top + 100,
3576 monitor.left + 100, monitor.top + 100, FALSE, TRUE );
3577 check_logical_physical_dpi( unaware_hwnd, monitor.left + 200, monitor.top + 200,
3578 monitor.left + 2 * scale, monitor.top + 2 * scale, TRUE );
3579 /* physical to logical conversion is lossy in the area of the screen where coordinate systems overlap but don't match */
3580 check_physical_dpi_( __LINE__, unaware_hwnd, monitor.left + 201, monitor.top + 201,
3581 monitor.left + MulDiv( 201, scale, 100 ), monitor.top + MulDiv( 201, scale, 100 ), TRUE, TRUE );
3582 check_logical_dpi_( __LINE__, unaware_hwnd, monitor.left + 201, monitor.top + 201,
3583 monitor.left + MulDiv( 201, 100, scale ), monitor.top + MulDiv( 201, 100, scale ), TRUE, TRUE );
3584 }
3585 else
3586 {
3587 check_logical_physical_dpi( unaware_hwnd, monitor.left + 100, monitor.top + 100,
3588 monitor.left + 1 * scale, monitor.top + 1 * scale, TRUE );
3589 check_logical_physical_dpi( unaware_hwnd, monitor.left + 200, monitor.top + 200,
3590 monitor.left + 2 * scale, monitor.top + 2 * scale, TRUE );
3591 /* physical to logical conversion is lossy in the area of the screen where coordinate systems overlap but don't match */
3592 check_physical_dpi( unaware_hwnd, monitor.left + 201, monitor.top + 201,
3593 monitor.left + 201, monitor.top + 201, FALSE );
3594 check_logical_dpi_( __LINE__, unaware_hwnd, monitor.left + 201, monitor.top + 201,
3595 monitor.left + MulDiv( 201, 100, scale ), monitor.top + MulDiv( 201, 100, scale ), TRUE, TRUE );
3596 }
3597
3598 check_logical_physical_dpi( unaware_hwnd, monitor.left + 2 * scale + 1, monitor.top + 2 * scale + 1,
3599 monitor.left + 2 * scale + 1, monitor.top + 2 * scale + 1, FALSE );
3600
3601
3602 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 199, mi.rcWork.top + 199,
3603 mi.rcWork.left + 199, mi.rcWork.top + 199, FALSE );
3604 if (monitor_aware)
3605 {
3606 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 200, mi.rcWork.top + 200,
3607 mi.rcWork.left + 200, mi.rcWork.top + 200, TRUE );
3608 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 300, mi.rcWork.top + 300,
3609 mi.rcWork.left + 300, mi.rcWork.top + 300, TRUE );
3610 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 301, mi.rcWork.top + 301,
3611 mi.rcWork.left + 301, mi.rcWork.top + 301, FALSE );
3612 }
3613 else
3614 {
3615 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 200, mi.rcWork.top + 200,
3616 mi.rcWork.left + 2 * scale, mi.rcWork.top + 2 * scale, TRUE );
3617 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 300, mi.rcWork.top + 300,
3618 mi.rcWork.left + 3 * scale, mi.rcWork.top + 3 * scale, TRUE );
3619 /* physical to logical conversion is lossy in the area of the screen where coordinate systems overlap but don't match */
3620 check_physical_dpi( aware_hwnd, mi.rcWork.left + 301, mi.rcWork.top + 301, mi.rcWork.left + 301, mi.rcWork.top + 301, FALSE );
3621 check_logical_dpi_( __LINE__, aware_hwnd, mi.rcWork.left + 301, mi.rcWork.top + 301, mi.rcWork.left + MulDiv( 301, 100, scale ),
3622 mi.rcWork.top + MulDiv( 301, 100, scale ), TRUE, TRUE );
3623 }
3624
3625 check_logical_physical_dpi( aware_hwnd, mi.rcWork.left + 3 * scale + 1, mi.rcWork.top + 3 * scale + 1,
3626 mi.rcWork.left + 3 * scale + 1, mi.rcWork.top + 3 * scale + 1, FALSE );
3627
3628
3629 check_logical_physical_dpi( primary_hwnd, primary.left + 299, primary.top + 299,
3630 primary.left + 299, primary.top + 299, FALSE );
3631 if (monitor_aware || !EqualRect( &monitor, &primary ))
3632 {
3633 check_logical_physical_dpi( primary_hwnd, primary.left + 300, primary.top + 300,
3634 primary.left + 300, primary.top + 300, TRUE );
3635 check_logical_physical_dpi( primary_hwnd, primary.left + 400, primary.top + 400,
3636 primary.left + 400, primary.top + 400, TRUE );
3637 check_logical_physical_dpi( primary_hwnd, primary.left + 401, primary.top + 401,
3638 primary.left + 401, primary.top + 401, FALSE );
3639 }
3640 else
3641 {
3642 check_logical_physical_dpi( primary_hwnd, primary.left + 300, primary.top + 300,
3643 primary.left + 3 * scale, primary.top + 3 * scale, TRUE );
3644 check_logical_physical_dpi( primary_hwnd, primary.left + 400, primary.top + 400,
3645 primary.left + 4 * scale, primary.top + 4 * scale, TRUE );
3646 /* physical to logical conversion is lossy in the area of the screen where coordinate systems overlap but don't match */
3647 check_physical_dpi( primary_hwnd, primary.left + 401, primary.top + 401, primary.left + 401, primary.top + 401, FALSE );
3648 check_logical_dpi_( __LINE__, primary_hwnd, primary.left + 401, primary.top + 401, primary.left + MulDiv( 401, 100, scale ),
3649 primary.top + MulDiv( 401, 100, scale ), TRUE, TRUE );
3650 }
3651
3652 check_logical_physical_dpi( primary_hwnd, primary.left + 4 * scale + 1, primary.top + 4 * scale + 1,
3653 primary.left + 4 * scale + 1, primary.top + 4 * scale + 1, FALSE );
3654
3655 DestroyWindow( primary_hwnd );
3656 DestroyWindow( aware_hwnd );
3657
3658 if (tests[i]) pSetThreadDpiAwarenessContext( old_ctx );
3659
3661 }
3662
3663 DestroyWindow( unaware_hwnd );
3664 flush_events();
3665}
3666#endif // __REACTOS__ || DLL_EXPORT_VERSION >= 0x600
3667
3669{
3670 struct monitor_info *info, **iter = (struct monitor_info **)lparam;
3671
3672 info = *iter;
3673 info->handle = handle;
3674 info->rect = *rect;
3675 pGetDpiForMonitorInternal( handle, MDT_EFFECTIVE_DPI, &info->eff_x, &info->eff_y );
3676 pGetDpiForMonitorInternal( handle, MDT_ANGULAR_DPI, &info->ang_x, &info->ang_y );
3677 pGetDpiForMonitorInternal( handle, MDT_RAW_DPI, &info->raw_x, &info->raw_y );
3678
3679 *iter = info + 1;
3680
3681 return TRUE;
3682}
3683
3684static void get_monitor_infos( struct monitor_info *infos )
3685{
3686 struct monitor_info *iter = infos;
3687 BOOL ret;
3689 ok( ret, "EnumDisplayMonitors failed\n" );
3690}
3691
3693{
3694 MONITORINFOEXW info = {.cbSize = sizeof(MONITORINFOEXW)};
3695 DEVMODEW mode = {.dmSize = sizeof(DEVMODEW)};
3696 UINT ret;
3697
3698 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&info );
3699 ok( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() );
3700
3702 mode.dmBitsPerPel = 32;
3703 mode.dmPelsWidth = width;
3704 mode.dmPelsHeight = height;
3705
3707 return !ret;
3708}
3709
3710static void test_monitor_dpi(void)
3711{
3712 struct monitor_info infos[64] = {{0}}, phys_infos[ARRAY_SIZE(infos)] = {{0}};
3713 struct { UINT width; UINT height; } tests[] =
3714 {
3715 {0, 0},
3716 {940, 560},
3717 {1600, 900},
3718 {1024, 768},
3719 };
3720 UINT i, j, count, system_dpi, dpi_x, dpi_y;
3721 DPI_AWARENESS_CONTEXT old_ctx;
3722 float scale_x, scale_y;
3723 BOOL ret, is_virtual;
3724
3725 if (!pGetDpiForMonitorInternal || !pSetThreadDpiAwarenessContext)
3726 {
3727 win_skip( "GetDpiForMonitorInternal / SetThreadDpiAwarenessContext not found, skipping tests\n" );
3728 return;
3729 }
3730
3731 old_ctx = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3732 system_dpi = pGetDpiForSystem();
3733
3735 ok( count > 0, "Found zero monitors\n" );
3736 ok( count <= ARRAY_SIZE(infos), "Too many monitors\n" );
3737
3738 get_monitor_infos( infos );
3739 memcpy( phys_infos, infos, sizeof(infos) );
3740
3741 /* check whether display driver (likely) supports display mode virtualization */
3742 is_virtual = abs( (int)infos[0].ang_x - (int)system_dpi ) < system_dpi * 0.05 &&
3743 abs( (int)infos[0].ang_y - (int)system_dpi ) < system_dpi * 0.05 &&
3744 abs( (int)infos[0].raw_x - (int)system_dpi ) < system_dpi * 0.05 &&
3745 abs( (int)infos[0].raw_y - (int)system_dpi ) < system_dpi * 0.05;
3746
3747 for (i = 0; i < count; i++)
3748 {
3749 for (j = 0; j < ARRAY_SIZE(tests); j++)
3750 {
3751 if (tests[j].width && tests[j].height && !set_display_settings( infos[i].handle, tests[j].width, tests[j].height )) continue;
3752
3753 get_monitor_infos( infos ); /* refresh infos as changing display settings may invalidate HMONITOR */
3754 scale_x = (infos[i].rect.right - infos[i].rect.left) / (float)(phys_infos[i].rect.right - phys_infos[i].rect.left);
3755 scale_y = (infos[i].rect.bottom - infos[i].rect.top) / (float)(phys_infos[i].rect.bottom - phys_infos[i].rect.top);
3756
3757 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y );
3758 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3759 ok( dpi_x == system_dpi, "got MDT_EFFECTIVE_DPI x %u\n", dpi_x );
3760 ok( dpi_y == system_dpi, "got MDT_EFFECTIVE_DPI y %u\n", dpi_y );
3761 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_ANGULAR_DPI, &dpi_x, &dpi_y );
3762 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3763 if (!is_virtual)
3764 {
3765 ok( dpi_x == phys_infos[i].ang_x, "got MDT_ANGULAR_DPI x %u\n", dpi_x );
3766 ok( dpi_y == phys_infos[i].ang_y, "got MDT_ANGULAR_DPI y %u\n", dpi_y );
3767 }
3768 else
3769 {
3770 todo_wine_if(scale_x != 1.0)
3771 ok( fabs( dpi_x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI x %u\n", dpi_x );
3772 todo_wine_if(scale_y != 1.0)
3773 ok( fabs( dpi_y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI y %u\n", dpi_y );
3774 }
3775 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_RAW_DPI, &dpi_x, &dpi_y );
3776 ok( ret || GetLastError() == ERROR_NOT_SUPPORTED, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3777 if (!ret)
3778 {
3779 ok( dpi_x == 0, "got MDT_RAW_DPI x %u\n", dpi_x );
3780 ok( dpi_y == 0, "got MDT_RAW_DPI y %u\n", dpi_y );
3781 }
3782 else if (!is_virtual)
3783 {
3784 ok( dpi_x == phys_infos[i].raw_x, "got MDT_RAW_DPI x %u\n", dpi_x );
3785 ok( dpi_y == phys_infos[i].raw_y, "got MDT_RAW_DPI y %u\n", dpi_y );
3786 }
3787 else
3788 {
3789 todo_wine_if(scale_x != 1.0)
3790 ok( fabs( dpi_x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_RAW_DPI x %u\n", dpi_x );
3791 todo_wine_if(scale_y != 1.0)
3792 ok( fabs( dpi_y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_RAW_DPI y %u\n", dpi_y );
3793 }
3794
3795 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 );
3796
3797 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y );
3798 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3799 ok( dpi_x == system_dpi, "got MDT_EFFECTIVE_DPI x %u\n", dpi_x );
3800 ok( dpi_y == system_dpi, "got MDT_EFFECTIVE_DPI y %u\n", dpi_y );
3801 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_ANGULAR_DPI, &dpi_x, &dpi_y );
3802 ok( ret, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3803 if (!is_virtual)
3804 {
3805 ok( dpi_x == phys_infos[i].ang_x, "got MDT_ANGULAR_DPI x %u\n", dpi_x );
3806 ok( dpi_y == phys_infos[i].ang_y, "got MDT_ANGULAR_DPI y %u\n", dpi_y );
3807 }
3808 else
3809 {
3810 todo_wine_if(scale_x != 1.0)
3811 ok( fabs( dpi_x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI x %u\n", dpi_x );
3812 todo_wine_if(scale_y != 1.0)
3813 ok( fabs( dpi_y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_ANGULAR_DPI y %u\n", dpi_y );
3814 }
3815 ret = pGetDpiForMonitorInternal( infos[i].handle, MDT_RAW_DPI, &dpi_x, &dpi_y );
3816 ok( ret || GetLastError() == ERROR_NOT_SUPPORTED, "GetDpiForMonitorInternal failed, error %lu\n", GetLastError() );
3817 if (!ret)
3818 {
3819 ok( dpi_x == 0, "got MDT_RAW_DPI x %u\n", dpi_x );
3820 ok( dpi_y == 0, "got MDT_RAW_DPI y %u\n", dpi_y );
3821 }
3822 else if (!is_virtual)
3823 {
3824 ok( dpi_x == phys_infos[i].raw_x, "got MDT_RAW_DPI x %u\n", dpi_x );
3825 ok( dpi_y == phys_infos[i].raw_y, "got MDT_RAW_DPI y %u\n", dpi_y );
3826 }
3827 else
3828 {
3829 todo_wine_if(scale_x != 1.0)
3830 ok( fabs( dpi_x - system_dpi * scale_x ) < system_dpi * 0.05, "got MDT_RAW_DPI x %u\n", dpi_x );
3831 todo_wine_if(scale_y != 1.0)
3832 ok( fabs( dpi_y - system_dpi * scale_y ) < system_dpi * 0.05, "got MDT_RAW_DPI y %u\n", dpi_y );
3833 }
3834
3835 pSetThreadDpiAwarenessContext( old_ctx );
3836 }
3837 }
3838
3840 pSetThreadDpiAwarenessContext( old_ctx );
3841
3842#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x600
3843 for (i = 0; i < count; i++)
3844 {
3845 int min = 0, max = 0, cur = 0;
3846
3847 set_display_settings( infos[i].handle, 800, 600 );
3848 get_monitor_infos( infos ); /* refresh infos as changing display settings may invalidate HMONITOR */
3849
3850 get_monitor_dpi_scale( infos[i].handle, &min, &cur, &max );
3852 {
3853 skip( "Cannot change monitor %p dpi, skipping tests\n", infos[i].handle );
3854 continue;
3855 }
3856
3857 set_monitor_dpi_scale( infos[i].handle, max );
3858 test_monitor_dpi_awareness( infos, count, max, system_dpi, infos + i, phys_infos + i, is_virtual );
3859 set_monitor_dpi_scale( infos[i].handle, cur );
3860 }
3861#endif // __REACTOS__ || DLL_EXPORT_VERSION >= 0x600
3862
3864}
3865
3867{
3868 char** myARGV;
3870
3872
3873 if (myARGC >= 3)
3874 {
3875 if (strcmp(myARGV[2], "info") == 0)
3876 {
3877 printf("Monitor information:\n");
3879 return;
3880 }
3881 else if (strcmp(myARGV[2], "fullscreen") == 0)
3882 {
3884 return;
3885 }
3886 }
3887
3893 test_monitors();
3896 test_handles();
3898}
static INT myARGC
Definition: FindFiles.c:29
static LPSTR * myARGV
Definition: FindFiles.c:30
static HBITMAP hbitmap
HDC hdc2
Definition: SelectObject.c:10
@ lparam
Definition: SystemMenu.c:31
static void startup(void)
static const char * wine_dbgstr_point(const POINT *ppt)
Definition: atltest.h:138
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define msg(x)
Definition: auth_time.c:54
HANDLE HMONITOR
Definition: axextend.idl:431
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define RegCloseKey(hKey)
Definition: registry.h:49
HBITMAP hbmp
Definition: _set.h:50
#define NO_ERROR
Definition: dderror.h:5
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define CCHDEVICENAME
Definition: ddrawi.h:63
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid)
Definition: devpropdef.h:103
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DWORD bpp
Definition: surface.c:185
#define NTSTATUS
Definition: precomp.h:19
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define lstrcpynA
Definition: compat.h:751
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
HANDLE HWND
Definition: compat.h:19
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define wcsicmp
Definition: compat.h:15
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
LPSTR WINAPI CharLowerA(char *str)
Definition: string.c:1043
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP double __cdecl fabs(double)
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
BOOL WINAPI SetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, CONST GUID *InterfaceClassGuid, DWORD MemberIndex, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
Definition: devinst.c:2780
HDEVINFO WINAPI SetupDiGetClassDevsW(CONST GUID *class, LPCWSTR enumstr, HWND parent, DWORD flags)
Definition: devinst.c:2292
BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData)
Definition: devinst.c:3011
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
Definition: devinst.c:2893
BOOL WINAPI GetDpiForMonitorInternal(_In_ HMONITOR monitor, _In_ UINT type, _Out_ UINT *x, _Out_ UINT *y)
Definition: dpi.c:113
UINT WINAPI GetDpiForWindow(_In_ HWND hWnd)
Definition: dpi.c:41
UINT WINAPI GetDpiForSystem(VOID)
Definition: dpi.c:26
#define pt(x, y)
Definition: drawing.c:79
#define BI_RGB
Definition: precomp.h:44
ULONG RGBQUAD
Definition: precomp.h:47
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
static struct all_devices * devices
Definition: dsm_ctrl.c:48
POINTL point
Definition: edittest.c:50
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define printf
Definition: freeldr.h:104
pKey DeleteObject()
FxCollectionEntry * cur
NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName(_Inout_ D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *unnamedParam1)
Definition: d3dkmt.c:14
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: glext.h:7750
GLuint res
Definition: glext.h:9613
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLenum mode
Definition: glext.h:6217
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLsizei const GLuint * paths
Definition: glext.h:11717
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define LOBYTE(W)
Definition: jmemdos.c:487
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
static HANDLE hmon
Definition: localmon.c:41
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:537
#define todo_wine
Definition: minitest.h:80
LONG_PTR LPARAM
Definition: minwindef.h:175
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define BI_BITFIELDS
Definition: mmreg.h:507
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:22
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
#define expect_rect(r, _left, _top, _right, _bottom)
Definition: combo.c:42
static HDC
Definition: imagelist.c:88
BOOL expected
Definition: store.c:2000
static DNS_RECORDW r1
Definition: record.c:37
static unsigned int number
Definition: dsound.c:1479
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
UINT WINAPI process1(MSIHANDLE hinst)
Definition: custom.c:1376
#define check_logical_physical_dpi(a, b, c, d, e, f)
Definition: monitor.c:3286
static BOOL CALLBACK find_primary_mon(HMONITOR hmon, HDC hdc, LPRECT rc, LPARAM lp)
Definition: monitor.c:1580
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
Definition: monitor.c:3128
static void test_enumdisplaydevices(void)
Definition: monitor.c:252
static BOOL CALLBACK test_EnumDisplayMonitors_return_false_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lparam)
Definition: monitor.c:1739
static void check_physical_dpi_(int line, HWND hwnd, UINT log_x, UINT log_y, UINT phy_x, UINT phy_y, BOOL expect_ret, BOOL todo_ret)
Definition: monitor.c:3261
static void _expect_dm(INT line, const DEVMODEA *expected, const CHAR *device, DWORD test)
Definition: monitor.c:328
static BOOL CALLBACK test_EnumDisplayMonitors_count(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lparam)
Definition: monitor.c:1814
static void test_enumdisplaydevices_monitor(int monitor_index, const char *adapter_name, DISPLAY_DEVICEA *device, DWORD flags)
Definition: monitor.c:203
static void init_function_pointers(void)
Definition: monitor.c:80
static void check_device_path(const WCHAR *device_path, const LUID *adapter_id, DWORD id)
Definition: monitor.c:1897
#define check_display_dc(a, b, c)
Definition: monitor.c:2638
static BOOL CALLBACK enum_monitor_rect(HMONITOR handle, HDC hdc, RECT *rect, LPARAM lparam)
Definition: monitor.c:3253
static unsigned int get_primary_dpi(void)
Definition: monitor.c:126
static int get_bitmap_stride(int width, int bpp)
Definition: monitor.c:143
static void test_display_dc(void)
Definition: monitor.c:2720
static void test_monitor_dpi(void)
Definition: monitor.c:3710
#define expect_dm(a, b, c)
Definition: monitor.c:327
#define wait_for_dm(a, b, c)
Definition: monitor.c:361
static void test_monitors(void)
Definition: monitor.c:1428
#define check_physical_dpi(a, b, c, d, e, f)
Definition: monitor.c:3260
static void get_monitor_infos(struct monitor_info *infos)
Definition: monitor.c:3684
static int adapter_count
Definition: monitor.c:148
static const struct vid_mode vid_modes_test[]
Definition: monitor.c:298
static void flush_events(void)
Definition: monitor.c:109
static void test_monitor_dpi_awareness(const struct monitor_info *infos, UINT count, int step, UINT system_dpi, const struct monitor_info *info, struct monitor_info *phys, BOOL is_virtual)
Definition: monitor.c:3293
static void set_monitor_dpi_scale(HMONITOR monitor, int scale)
Definition: monitor.c:3215
static BOOL CALLBACK test_EnumDisplayMonitors_normal_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lparam)
Definition: monitor.c:1724
static BOOL CALLBACK test_handle_proc(HMONITOR full_monitor, HDC hdc, LPRECT rect, LPARAM lparam)
Definition: monitor.c:2558
static int monitor_count
Definition: monitor.c:149
#define CHECK_FUNC(func)
static void test_DisplayConfigGetDeviceInfo(void)
Definition: monitor.c:2334
static BOOL set_display_settings(HMONITOR monitor, UINT width, UINT height)
Definition: monitor.c:3692
static BOOL CALLBACK enum_monitor_infos(HMONITOR handle, HDC hdc, RECT *rect, LPARAM lparam)
Definition: monitor.c:3668
static void test_QueryDisplayConfig(void)
Definition: monitor.c:2226
static void test_ChangeDisplaySettingsEx(int argc, char **argv)
Definition: monitor.c:417
static UINT32 UINT32 *static UINT
Definition: monitor.c:64
static void check_logical_dpi_(int line, HWND hwnd, UINT phy_x, UINT phy_y, UINT log_x, UINT log_y, BOOL expect_ret, BOOL todo_ret)
Definition: monitor.c:3274
static void test_DisplayConfigSetDeviceInfo(void)
Definition: monitor.c:2465
static void get_monitor_dpi_scale(HMONITOR monitor, int *min, int *cur, int *max)
Definition: monitor.c:3186
static void wait_for_dm_(int line, const char *device, DWORD expected_width, DWORD expected_height)
Definition: monitor.c:362
static BOOL CALLBACK test_EnumDisplayMonitors_invalid_handle_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lparam)
Definition: monitor.c:1745
static void test_display_config(void)
Definition: monitor.c:2450
static void test_GetDisplayConfigBufferSizes(void)
Definition: monitor.c:1653
static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *device, DWORD flags)
Definition: monitor.c:151
static void check_preferred_mode(const DISPLAYCONFIG_TARGET_PREFERRED_MODE *mode, const WCHAR *gdi_device_name)
Definition: monitor.c:1953
static void test_work_area(void)
Definition: monitor.c:1596
#define GET_PROC(module, func)
static HANDLE test_child_process_ChangeDisplaySettingsEx(const char *argv0, const char *device, DWORD flags, const char *exit_event_name)
Definition: monitor.c:388
static void _check_display_dc(INT line, HDC hdc, const DEVMODEA *dm, BOOL allow_todo)
Definition: monitor.c:2639
static void test_QueryDisplayConfig_result(UINT32 flags, UINT32 paths, const DISPLAYCONFIG_PATH_INFO *pi, UINT32 modes, const DISPLAYCONFIG_MODE_INFO *mi)
Definition: monitor.c:2003
static void test_handles(void)
Definition: monitor.c:2629
static void test_EnumDisplayMonitors(void)
Definition: monitor.c:1822
static void check_logical_physical_dpi_(int line, HWND hwnd, UINT log_x, UINT log_y, UINT phy_x, UINT phy_y, BOOL expect_ret, BOOL todo_ret)
Definition: monitor.c:3287
static DPI_AWARENESS_CONTEXT
Definition: sysparams.c:52
static MONITORINFO mi
Definition: win.c:9400
static void test_fullscreen(void)
Definition: win.c:9434
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
HMONITOR WINAPI MonitorFromPoint(POINT, DWORD)
HMONITOR WINAPI MonitorFromRect(LPCRECT, DWORD)
HMONITOR WINAPI MonitorFromWindow(HWND, DWORD)
unsigned int UINT
Definition: ndis.h:50
#define SYNCHRONIZE
Definition: nt_native.h:61
#define BOOL
Definition: nt_native.h:43
static HANDLE ULONG_PTR dwData
Definition: pipe.c:83
#define OBJ_BITMAP
Definition: objidl.idl:1020
#define LOWORD(l)
Definition: pedump.c:82
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define WS_POPUP
Definition: pedump.c:616
#define WS_VISIBLE
Definition: pedump.c:620
long LONG
Definition: pedump.c:60
#define calloc
Definition: rosglue.h:14
#define test
Definition: rosglue.h:37
#define REG_DWORD
Definition: sdbapi.c:615
wcscpy
int winetest_get_mainargs(char ***pargv)
int winetest_platform_is_wine
#define memset(x, y, z)
Definition: compat.h:39
#define log(outFile, fmt,...)
Definition: util.h:15
#define DIGCF_DEVICEINTERFACE
Definition: setupapi.h:175
struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W SP_DEVICE_INTERFACE_DETAIL_DATA_W
#define DIGCF_PRESENT
Definition: setupapi.h:172
#define STATUS_SUCCESS
Definition: shellext.h:65
@ MDT_RAW_DPI
@ MDT_EFFECTIVE_DPI
@ MDT_ANGULAR_DPI
static char argv0[MAX_PATH]
Definition: shlexec.c:49
& rect
Definition: startmenu.cpp:1413
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
DWORD StateFlags
Definition: wingdi.h:3258
CHAR DeviceString[128]
Definition: wingdi.h:3257
CHAR DeviceName[32]
Definition: wingdi.h:3256
LONG HighPart
DWORD LowPart
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
WCHAR DevicePath[ANYSIZE_ARRAY]
Definition: setupapi.h:856
POINT ptMaxPosition
Definition: winuser.h:3402
RECT rcNormalPosition
Definition: winuser.h:3403
POINT ptMinPosition
Definition: winuser.h:3401
DWORD dmDisplayFrequency
Definition: wingdi.h:2048
DWORD dmFields
Definition: wingdi.h:2016
DWORD dmDisplayOrientation
Definition: wingdi.h:2030
DWORD dmPelsWidth
Definition: wingdi.h:2042
DWORD dmPelsHeight
Definition: wingdi.h:2043
DWORD dmBitsPerPel
Definition: wingdi.h:2041
WORD dmDriverExtra
Definition: wingdi.h:2015
POINTL dmPosition
Definition: wingdi.h:2029
WORD dmSize
Definition: wingdi.h:2014
DWORD dmFields
Definition: wingdi.h:2068
DWORD dmPelsWidth
Definition: wingdi.h:2094
WORD dmDriverExtra
Definition: wingdi.h:2067
DWORD dmPelsHeight
Definition: wingdi.h:2095
WORD dmSize
Definition: wingdi.h:2066
Definition: uimain.c:89
Definition: http.c:7252
DEVMODEA original_mode
Definition: monitor.c:324
DWORD index
Definition: monitor.c:322
Definition: devices.h:37
Definition: copy.c:22
Definition: parser.c:49
UINT ang_y
Definition: monitor.c:3247
UINT raw_x
Definition: monitor.c:3247
HMONITOR handle
Definition: monitor.c:3248
UINT raw_y
Definition: monitor.c:3247
UINT eff_y
Definition: monitor.c:3247
UINT ang_x
Definition: monitor.c:3247
UINT eff_x
Definition: monitor.c:3247
Definition: name.c:39
Definition: ps.c:97
USHORT biBitCount
Definition: precomp.h:34
ULONG biCompression
Definition: precomp.h:35
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1922
RECT rcMonitor
Definition: winuser.h:3893
DWORD dwFlags
Definition: winuser.h:3895
DWORD cbSize
Definition: winuser.h:3892
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
DWORD h
Definition: monitor.c:294
DWORD bpp
Definition: monitor.c:294
DWORD w
Definition: monitor.c:294
BOOL must_succeed
Definition: monitor.c:295
DWORD fields
Definition: monitor.c:294
DWORD freq
Definition: monitor.c:294
#define max(a, b)
Definition: svc.c:63
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
Definition: synch.c:605
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t UINT32
Definition: typedefs.h:59
Definition: pdh_main.c:96
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
#define dpi
Definition: sysparams.c:23
HDESK WINAPI CreateDesktopW(LPCWSTR lpszDesktop, LPCWSTR lpszDevice, LPDEVMODEW pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:473
BOOL WINAPI EnumDisplaySettingsExA(LPCSTR lpszDeviceName, DWORD iModeNum, LPDEVMODEA lpDevMode, DWORD dwFlags)
Definition: display.c:182
LONG WINAPI ChangeDisplaySettingsExW(LPCWSTR lpszDeviceName, LPDEVMODEW lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
Definition: display.c:585
BOOL WINAPI EnumDisplayDevicesA(LPCSTR lpDevice, DWORD iDevNum, PDISPLAY_DEVICEA lpDisplayDevice, DWORD dwFlags)
Definition: display.c:23
BOOL WINAPI EnumDisplaySettingsW(LPCWSTR lpszDeviceName, DWORD iModeNum, LPDEVMODEW lpDevMode)
Definition: display.c:408
BOOL WINAPI EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, LPDEVMODEA lpDevMode)
Definition: display.c:312
LONG WINAPI ChangeDisplaySettingsW(LPDEVMODEW lpDevMode, DWORD dwflags)
Definition: display.c:612
LONG WINAPI ChangeDisplaySettingsExA(LPCSTR lpszDeviceName, LPDEVMODEA lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
Definition: display.c:521
LONG WINAPI ChangeDisplaySettingsA(LPDEVMODEA lpDevMode, DWORD dwflags)
Definition: display.c:570
LONG WINAPI QueryDisplayConfig(UINT32 flags, UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId)
Definition: sysparams.c:225
LONG WINAPI DisplayConfigSetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER *packet)
Definition: sysparams.c:256
DISPLAYCONFIG_TOPOLOGY_ID
Definition: sysparams.c:14
LONG WINAPI DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER *packet)
Definition: sysparams.c:247
@ DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME
Definition: sysparams.c:27
@ DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
Definition: sysparams.c:25
@ DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME
Definition: sysparams.c:24
@ DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE
Definition: sysparams.c:26
@ DISPLAYCONFIG_MODE_INFO_TYPE_TARGET
Definition: sysparams.c:195
@ DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE
Definition: sysparams.c:194
@ DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE
Definition: sysparams.c:196
LONG WINAPI GetDisplayConfigBufferSizes(UINT32 flags, UINT32 *numPathArrayElements, UINT32 *numModeInfoArrayElements)
Definition: sysparams.c:213
DPI_AWARENESS_CONTEXT WINAPI GetWindowDpiAwarenessContext(HWND hwnd)
Definition: win.c:630
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define EVENT_MODIFY_STATE
Definition: winbase.h:165
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
#define WAIT_OBJECT_0
Definition: winbase.h:383
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define DPI_AWARENESS_CONTEXT_UNAWARE
Definition: windef.h:87
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
Definition: windef.h:89
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
Definition: windef.h:90
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
Definition: windef.h:88
#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
Definition: windef.h:91
#define WINAPI
Definition: msvc.h:6
#define ERROR_GEN_FAILURE
Definition: winerror.h:256
#define ERROR_INVALID_MONITOR_HANDLE
Definition: winerror.h:1287
#define ERROR_NOT_FOUND
Definition: winerror.h:1014
#define DM_DISPLAYFREQUENCY
Definition: wingdi.h:1272
#define DMDO_DEFAULT
Definition: wingdi.h:1217
#define DIB_RGB_COLORS
Definition: wingdi.h:367
#define HORZRES
Definition: wingdi.h:716
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
int WINAPI GetObjectA(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
#define LOGPIXELSY
Definition: wingdi.h:719
#define DM_PELSWIDTH
Definition: wingdi.h:1269
#define NUMCOLORS
Definition: wingdi.h:725
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
HDC WINAPI CreateDCA(_In_opt_ LPCSTR pszDriver, _In_opt_ LPCSTR pszDevice, _In_opt_ LPCSTR pszOutput, _In_opt_ const DEVMODEA *pdmInit)
#define DM_POSITION
Definition: wingdi.h:1255
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DMDO_180
Definition: wingdi.h:1219
#define VREFRESH
Definition: wingdi.h:741
#define VERTRES
Definition: wingdi.h:717
struct _devicemodeW DEVMODEW
#define DM_BITSPERPEL
Definition: wingdi.h:1268
#define DMDO_270
Definition: wingdi.h:1220
#define DISPLAY_DEVICE_PRIMARY_DEVICE
Definition: wingdi.h:1398
#define DM_DISPLAYORIENTATION
Definition: wingdi.h:1257
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
#define DESKTOPHORZRES
Definition: wingdi.h:742
#define LOGPIXELSX
Definition: wingdi.h:718
#define BITSPIXEL
Definition: wingdi.h:720
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
Definition: wingdi.h:1396
#define DM_PELSHEIGHT
Definition: wingdi.h:1270
#define DMDO_90
Definition: wingdi.h:1218
#define QDC_ALL_PATHS
Definition: wingdi.h:1283
BOOL WINAPI DeleteDC(_In_ HDC)
#define DESKTOPVERTRES
Definition: wingdi.h:743
#define DM_DISPLAYFLAGS
Definition: wingdi.h:1271
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define snprintf
Definition: wintirpc.h:48
HDESK WINAPI GetThreadDesktop(_In_ DWORD)
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define CDS_TEST
Definition: winuser.h:182
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define SM_CYVIRTUALSCREEN
Definition: winuser.h:1050
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
BOOL WINAPI GetClipCursor(_Out_ LPRECT)
#define SM_CYSCREEN
Definition: winuser.h:971
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
BOOL WINAPI GetWindowPlacement(_In_ HWND, _Inout_ WINDOWPLACEMENT *)
HWINSTA WINAPI CreateWindowStationW(_In_opt_ LPCWSTR lpwinsta, _In_ DWORD dwFlags, _In_ ACCESS_MASK dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpsa)
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
LONG WINAPI SetWindowLongA(_In_ HWND, _In_ int, _In_ LONG)
#define DISP_CHANGE_BADMODE
Definition: winuser.h:195
BOOL WINAPI ClipCursor(_In_opt_ LPCRECT)
#define DISP_CHANGE_SUCCESSFUL
Definition: winuser.h:190
struct tagMONITORINFOEXA MONITORINFOEXA
#define WS_EX_TOOLWINDOW
Definition: winuser.h:404
#define CDS_FULLSCREEN
Definition: winuser.h:183
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
#define ENUM_REGISTRY_SETTINGS
Definition: winuser.h:180
#define QS_ALLINPUT
Definition: winuser.h:914
BOOL WINAPI EnumDisplayMonitors(_In_opt_ HDC, _In_opt_ LPCRECT, _In_ MONITORENUMPROC, _In_ LPARAM)
BOOL WINAPI CloseWindowStation(_In_ HWINSTA)
#define DISP_CHANGE_BADPARAM
Definition: winuser.h:193
struct tagMONITORINFOEXW MONITORINFOEXW
#define CDS_UPDATEREGISTRY
Definition: winuser.h:181
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
BOOL WINAPI SetProcessWindowStation(_In_ HWINSTA)
#define DISP_CHANGE_BADFLAGS
Definition: winuser.h:192
#define DISP_CHANGE_FAILED
Definition: winuser.h:194
#define CDS_NORESET
Definition: winuser.h:189
#define SM_CXVIRTUALSCREEN
Definition: winuser.h:1049
#define WINSTA_ALL_ACCESS
Definition: winuser.h:417
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define ENUM_CURRENT_SETTINGS
Definition: winuser.h:179
#define CDS_RESET
Definition: winuser.h:187
#define PM_REMOVE
Definition: winuser.h:1207
BOOL WINAPI GetMonitorInfoA(_In_ HMONITOR, _Inout_ LPMONITORINFO)
#define WSF_VISIBLE
Definition: winuser.h:2488
HDC WINAPI GetDC(_In_opt_ HWND)
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4470
struct tagMONITORINFO MONITORINFO
BOOL WINAPI SystemParametersInfoA(_In_ UINT uiAction, _In_ UINT uiParam, _Inout_opt_ PVOID pvParam, _In_ UINT fWinIni)
BOOL WINAPI PeekMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define UOI_FLAGS
Definition: winuser.h:1094
#define SM_CXSCREEN
Definition: winuser.h:970
BOOL WINAPI GetMonitorInfoW(_In_ HMONITOR, _Inout_ LPMONITORINFO)
#define SM_XVIRTUALSCREEN
Definition: winuser.h:1047
BOOL WINAPI CloseDesktop(_In_ HDESK)
#define DISP_CHANGE_RESTART
Definition: winuser.h:191
BOOL WINAPI UnionRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
BOOL WINAPI SetUserObjectInformationW(_In_ HANDLE hObj, _In_ int nIndex, _In_reads_bytes_(nLength) PVOID pvInfo, _In_ DWORD nLength)
#define SM_CMONITORS
Definition: winuser.h:1051
BOOL WINAPI DestroyWindow(_In_ HWND)
BOOL WINAPI EqualRect(_In_ LPCRECT, _In_ LPCRECT)
int WINAPI GetSystemMetrics(_In_ int)
#define SM_YVIRTUALSCREEN
Definition: winuser.h:1048
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
#define GWL_EXSTYLE
Definition: winuser.h:862
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:304
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193