user32: Also ignore dynamic DPI awareness changes when DPI scaling is disabled.
[wine.git] / dlls / user32 / tests / sysparams.c
blobf74c9e75613145b4918ddbe06188bd908ad02677
1 /* Unit test suite for functions SystemParametersInfo and GetSystemMetrics.
3 * Copyright 2002 Andriy Palamarchuk
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define _WIN32_WINNT 0x0600 /* For SPI_GETMOUSEHOVERWIDTH and more */
21 #define _WIN32_IE 0x0700
22 #define WINVER 0x0600 /* For COLOR_MENUBAR, NONCLIENTMETRICS with padding */
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <stdio.h>
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winreg.h"
34 #include "winuser.h"
35 #include "winnls.h"
37 #ifndef SPI_GETDESKWALLPAPER
38 # define SPI_GETDESKWALLPAPER 0x0073
39 #endif
41 static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
42 static BOOL (WINAPI *pIsProcessDPIAware)(void);
43 static BOOL (WINAPI *pSetProcessDPIAware)(void);
44 static BOOL (WINAPI *pSetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
45 static BOOL (WINAPI *pGetProcessDpiAwarenessInternal)(HANDLE,DPI_AWARENESS*);
46 static BOOL (WINAPI *pSetProcessDpiAwarenessInternal)(DPI_AWARENESS);
47 static UINT (WINAPI *pGetDpiForSystem)(void);
48 static UINT (WINAPI *pGetDpiForWindow)(HWND);
49 static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*);
50 static DPI_AWARENESS_CONTEXT (WINAPI *pGetThreadDpiAwarenessContext)(void);
51 static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
52 static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND);
53 static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
54 static BOOL (WINAPI *pIsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
55 static INT (WINAPI *pGetSystemMetricsForDpi)(INT,UINT);
56 static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT);
57 static BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
58 static BOOL (WINAPI *pLogicalToPhysicalPointForPerMonitorDPI)(HWND,POINT*);
59 static BOOL (WINAPI *pPhysicalToLogicalPointForPerMonitorDPI)(HWND,POINT*);
60 static LONG (WINAPI *pGetAutoRotationState)(PAR_STATE);
62 static BOOL strict;
63 static int dpi, real_dpi;
65 #define eq(received, expected, label, type) \
66 ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
69 #define SPI_SETBEEP_REGKEY "Control Panel\\Sound"
70 #define SPI_SETBEEP_VALNAME "Beep"
71 #define SPI_SETMOUSE_REGKEY "Control Panel\\Mouse"
72 #define SPI_SETMOUSE_VALNAME1 "MouseThreshold1"
73 #define SPI_SETMOUSE_VALNAME2 "MouseThreshold2"
74 #define SPI_SETMOUSE_VALNAME3 "MouseSpeed"
75 #define SPI_SETBORDER_REGKEY "Control Panel\\Desktop\\WindowMetrics"
76 #define SPI_SETBORDER_REGKEY2 "Control Panel\\Desktop"
77 #define SPI_SETBORDER_VALNAME "BorderWidth"
78 #define SPI_METRIC_REGKEY "Control Panel\\Desktop\\WindowMetrics"
79 #define SPI_SCROLLWIDTH_VALNAME "ScrollWidth"
80 #define SPI_SCROLLHEIGHT_VALNAME "ScrollHeight"
81 #define SPI_CAPTIONWIDTH_VALNAME "CaptionWidth"
82 #define SPI_CAPTIONHEIGHT_VALNAME "CaptionHeight"
83 #define SPI_CAPTIONFONT_VALNAME "CaptionFont"
84 #define SPI_SMCAPTIONWIDTH_VALNAME "SmCaptionWidth"
85 #define SPI_SMCAPTIONHEIGHT_VALNAME "SmCaptionHeight"
86 #define SPI_SMCAPTIONFONT_VALNAME "SmCaptionFont"
87 #define SPI_MENUWIDTH_VALNAME "MenuWidth"
88 #define SPI_MENUHEIGHT_VALNAME "MenuHeight"
89 #define SPI_MENUFONT_VALNAME "MenuFont"
90 #define SPI_STATUSFONT_VALNAME "StatusFont"
91 #define SPI_MESSAGEFONT_VALNAME "MessageFont"
93 #define SPI_SETKEYBOARDSPEED_REGKEY "Control Panel\\Keyboard"
94 #define SPI_SETKEYBOARDSPEED_VALNAME "KeyboardSpeed"
95 #define SPI_ICONHORIZONTALSPACING_REGKEY "Control Panel\\Desktop\\WindowMetrics"
96 #define SPI_ICONHORIZONTALSPACING_REGKEY2 "Control Panel\\Desktop"
97 #define SPI_ICONHORIZONTALSPACING_VALNAME "IconSpacing"
98 #define SPI_ICONVERTICALSPACING_REGKEY "Control Panel\\Desktop\\WindowMetrics"
99 #define SPI_ICONVERTICALSPACING_REGKEY2 "Control Panel\\Desktop"
100 #define SPI_ICONVERTICALSPACING_VALNAME "IconVerticalSpacing"
101 #define SPI_MINIMIZEDMETRICS_REGKEY "Control Panel\\Desktop\\WindowMetrics"
102 #define SPI_MINWIDTH_VALNAME "MinWidth"
103 #define SPI_MINHORZGAP_VALNAME "MinHorzGap"
104 #define SPI_MINVERTGAP_VALNAME "MinVertGap"
105 #define SPI_MINARRANGE_VALNAME "MinArrange"
106 #define SPI_SETSCREENSAVETIMEOUT_REGKEY "Control Panel\\Desktop"
107 #define SPI_SETSCREENSAVETIMEOUT_VALNAME "ScreenSaveTimeOut"
108 #define SPI_SETSCREENSAVEACTIVE_REGKEY "Control Panel\\Desktop"
109 #define SPI_SETSCREENSAVEACTIVE_VALNAME "ScreenSaveActive"
110 #define SPI_SETGRIDGRANULARITY_REGKEY "Control Panel\\Desktop"
111 #define SPI_SETGRIDGRANULARITY_VALNAME "GridGranularity"
112 #define SPI_SETKEYBOARDDELAY_REGKEY "Control Panel\\Keyboard"
113 #define SPI_SETKEYBOARDDELAY_VALNAME "KeyboardDelay"
114 #define SPI_SETICONTITLEWRAP_REGKEY1 "Control Panel\\Desktop\\WindowMetrics"
115 #define SPI_SETICONTITLEWRAP_REGKEY2 "Control Panel\\Desktop"
116 #define SPI_SETICONTITLEWRAP_VALNAME "IconTitleWrap"
117 #define SPI_SETMENUDROPALIGNMENT_REGKEY1 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
118 #define SPI_SETMENUDROPALIGNMENT_REGKEY2 "Control Panel\\Desktop"
119 #define SPI_SETMENUDROPALIGNMENT_VALNAME "MenuDropAlignment"
120 #define SPI_SETDOUBLECLKWIDTH_REGKEY1 "Control Panel\\Mouse"
121 #define SPI_SETDOUBLECLKWIDTH_REGKEY2 "Control Panel\\Desktop"
122 #define SPI_SETDOUBLECLKWIDTH_VALNAME "DoubleClickWidth"
123 #define SPI_SETDOUBLECLKHEIGHT_REGKEY1 "Control Panel\\Mouse"
124 #define SPI_SETDOUBLECLKHEIGHT_REGKEY2 "Control Panel\\Desktop"
125 #define SPI_SETDOUBLECLKHEIGHT_VALNAME "DoubleClickHeight"
126 #define SPI_SETDOUBLECLICKTIME_REGKEY "Control Panel\\Mouse"
127 #define SPI_SETDOUBLECLICKTIME_VALNAME "DoubleClickSpeed"
128 #define SPI_SETMOUSEBUTTONSWAP_REGKEY "Control Panel\\Mouse"
129 #define SPI_SETMOUSEBUTTONSWAP_VALNAME "SwapMouseButtons"
130 #define SPI_SETWORKAREA_REGKEY "Control Panel\\Desktop"
131 #define SPI_SETWORKAREA_VALNAME "WINE_WorkArea"
132 #define SPI_SETSHOWSOUNDS_REGKEY "Control Panel\\Accessibility\\ShowSounds"
133 #define SPI_SETSHOWSOUNDS_VALNAME "On"
134 #define SPI_SETKEYBOARDPREF_REGKEY "Control Panel\\Accessibility\\Keyboard Preference"
135 #define SPI_SETKEYBOARDPREF_VALNAME "On"
136 #define SPI_SETKEYBOARDPREF_REGKEY_LEGACY "Control Panel\\Accessibility"
137 #define SPI_SETKEYBOARDPREF_VALNAME_LEGACY "Keyboard Preference"
138 #define SPI_SETSCREENREADER_REGKEY "Control Panel\\Accessibility\\Blind Access"
139 #define SPI_SETSCREENREADER_VALNAME "On"
140 #define SPI_SETSCREENREADER_REGKEY_LEGACY "Control Panel\\Accessibility"
141 #define SPI_SETSCREENREADER_VALNAME_LEGACY "Blind Access"
142 #define SPI_SETFONTSMOOTHING_REGKEY "Control Panel\\Desktop"
143 #define SPI_SETFONTSMOOTHING_VALNAME "FontSmoothing"
144 #define SPI_SETFONTSMOOTHINGTYPE_VALNAME "FontSmoothingType"
145 #define SPI_SETFONTSMOOTHINGCONTRAST_VALNAME "FontSmoothingGamma"
146 #define SPI_SETFONTSMOOTHINGORIENTATION_VALNAME "FontSmoothingOrientation"
147 #define SPI_SETLOWPOWERACTIVE_REGKEY "Control Panel\\Desktop"
148 #define SPI_SETLOWPOWERACTIVE_VALNAME "LowPowerActive"
149 #define SPI_SETPOWEROFFACTIVE_REGKEY "Control Panel\\Desktop"
150 #define SPI_SETPOWEROFFACTIVE_VALNAME "PowerOffActive"
151 #define SPI_SETDRAGFULLWINDOWS_REGKEY "Control Panel\\Desktop"
152 #define SPI_SETDRAGFULLWINDOWS_VALNAME "DragFullWindows"
153 #define SPI_SETSNAPTODEFBUTTON_REGKEY "Control Panel\\Mouse"
154 #define SPI_SETSNAPTODEFBUTTON_VALNAME "SnapToDefaultButton"
155 #define SPI_SETMOUSEHOVERWIDTH_REGKEY "Control Panel\\Mouse"
156 #define SPI_SETMOUSEHOVERWIDTH_VALNAME "MouseHoverWidth"
157 #define SPI_SETMOUSEHOVERHEIGHT_REGKEY "Control Panel\\Mouse"
158 #define SPI_SETMOUSEHOVERHEIGHT_VALNAME "MouseHoverHeight"
159 #define SPI_SETMOUSEHOVERTIME_REGKEY "Control Panel\\Mouse"
160 #define SPI_SETMOUSEHOVERTIME_VALNAME "MouseHoverTime"
161 #define SPI_SETMOUSESCROLLCHARS_REGKEY "Control Panel\\Desktop"
162 #define SPI_SETMOUSESCROLLCHARS_VALNAME "WheelScrollChars"
163 #define SPI_SETMOUSESCROLLLINES_REGKEY "Control Panel\\Desktop"
164 #define SPI_SETMOUSESCROLLLINES_VALNAME "WheelScrollLines"
165 #define SPI_SETMENUSHOWDELAY_REGKEY "Control Panel\\Desktop"
166 #define SPI_SETMENUSHOWDELAY_VALNAME "MenuShowDelay"
167 #define SPI_SETDESKWALLPAPER_REGKEY "Control Panel\\Desktop"
168 #define SPI_SETDESKWALLPAPER_VALNAME "Wallpaper"
170 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
171 #define WINE_CURRENT_USER_REGKEY "Wine"
173 static HWND ghTestWnd;
175 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam );
176 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
177 LPARAM lParam );
178 static int change_counter;
179 static int change_setworkarea_param, change_iconverticalspacing_param;
180 static int change_last_param;
181 static int last_bpp;
182 static BOOL displaychange_ok = FALSE, displaychange_test_active = FALSE;
183 static HANDLE displaychange_sem = 0;
185 static BOOL get_reg_dword(HKEY base, const char *key_name, const char *value_name, DWORD *value)
187 HKEY key;
188 DWORD type, data, size = sizeof(data);
189 BOOL ret = FALSE;
191 if (RegOpenKeyA(base, key_name, &key) == ERROR_SUCCESS)
193 if (RegQueryValueExA(key, value_name, NULL, &type, (void *)&data, &size) == ERROR_SUCCESS &&
194 type == REG_DWORD)
196 *value = data;
197 ret = TRUE;
199 RegCloseKey(key);
201 return ret;
204 static DWORD get_real_dpi(void)
206 DWORD dpi;
208 if (pSetThreadDpiAwarenessContext)
210 DPI_AWARENESS_CONTEXT context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
211 dpi = pGetDpiForSystem();
212 pSetThreadDpiAwarenessContext( context );
213 return dpi;
215 if (get_reg_dword(HKEY_CURRENT_USER, "Control Panel\\Desktop", "LogPixels", &dpi))
216 return dpi;
217 if (get_reg_dword(HKEY_CURRENT_CONFIG, "Software\\Fonts", "LogPixels", &dpi))
218 return dpi;
219 return USER_DEFAULT_SCREEN_DPI;
222 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
223 LPARAM lParam )
225 switch (msg) {
227 case WM_DISPLAYCHANGE:
228 ok(displaychange_ok, "Unexpected WM_DISPLAYCHANGE message\n");
229 last_bpp = wParam;
230 displaychange_ok = FALSE;
231 ReleaseSemaphore(displaychange_sem, 1, 0);
232 break;
234 case WM_SETTINGCHANGE:
235 if (change_counter>0) {
236 /* ignore these messages caused by resizing of toolbars */
237 if( wParam == SPI_SETWORKAREA){
238 change_setworkarea_param = 1;
239 break;
240 } else if( wParam == SPI_ICONVERTICALSPACING) {
241 change_iconverticalspacing_param = 1;
242 break;
243 } else if( displaychange_test_active)
244 break;
245 if( !change_last_param){
246 change_last_param = wParam;
247 break;
249 ok(0,"too many changes counter=%d last change=%d\n",
250 change_counter,change_last_param);
251 change_counter++;
252 change_last_param = wParam;
253 break;
255 change_counter++;
256 change_last_param = change_setworkarea_param = change_iconverticalspacing_param =0;
257 if( wParam == SPI_SETWORKAREA)
258 change_setworkarea_param = 1;
259 else if( wParam == SPI_ICONVERTICALSPACING)
260 change_iconverticalspacing_param = 1;
261 else
262 change_last_param = wParam;
263 break;
265 case WM_DESTROY:
266 PostQuitMessage( 0 );
267 break;
269 /* drop through */
270 default:
271 return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
274 return 0;
278 Performs testing for system parameters messages
279 params:
280 - system parameter id
281 - supposed value of the registry key
283 static void test_change_message( int action, int optional )
285 if (change_counter==0 && optional==1)
286 return;
287 ok( 1 == change_counter,
288 "Missed a message: change_counter=%d\n", change_counter );
289 change_counter = 0;
290 ok( action == change_last_param ||
291 ( change_setworkarea_param && action == SPI_SETWORKAREA) ||
292 ( change_iconverticalspacing_param && action == SPI_ICONVERTICALSPACING),
293 "Wrong action got %d expected %d\n", change_last_param, action );
294 change_last_param = 0;
297 static BOOL test_error_msg ( int rc, const char *name )
299 DWORD last_error = GetLastError();
301 if (rc==0)
303 if (last_error==0xdeadbeef || last_error==ERROR_INVALID_SPI_VALUE || last_error==ERROR_INVALID_PARAMETER)
305 skip("%s not supported on this platform\n", name);
307 else if (last_error==ERROR_ACCESS_DENIED)
309 skip("%s does not have privileges to run\n", name);
311 else
313 trace("%s failed for reason: %d. Indicating test failure and skipping remainder of test\n",name,last_error);
314 ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
316 return FALSE;
318 else
320 ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
321 return TRUE;
326 * Tests the HKEY_CURRENT_USER subkey value.
327 * The value should contain string value.
329 static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName1, LPCSTR valName2,
330 const void *exp_value, DWORD exp_type, BOOL optional )
332 CHAR value[MAX_PATH];
333 DWORD valueLen;
334 DWORD type;
335 HKEY hKey;
336 LONG rc;
337 int found=0;
339 *value='\0';
340 valueLen=sizeof(value);
341 RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
342 rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
343 RegCloseKey( hKey );
344 if (rc==ERROR_SUCCESS)
346 ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
347 switch (exp_type)
349 case REG_DWORD:
350 ok( *(DWORD *)value == *(DWORD *)exp_value,
351 "Wrong value in registry: %s %s %08x/%08x\n",
352 subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
353 break;
354 case REG_SZ:
355 ok( !strcmp( exp_value, value ),
356 "Wrong value in registry: %s %s '%s' instead of '%s'\n",
357 subKey1, valName1, value, (const char *)exp_value );
358 break;
360 found++;
362 else if (strict)
364 ok(0,"Missing registry entry: subKey=%s, valName=%s\n",
365 subKey1, valName1);
367 if (valName2)
369 *value='\0';
370 valueLen=sizeof(value);
371 RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
372 rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
373 RegCloseKey( hKey );
374 if (rc==ERROR_SUCCESS)
376 ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
377 switch (exp_type)
379 case REG_DWORD:
380 ok( *(DWORD *)value == *(DWORD *)exp_value,
381 "Wrong value in registry: %s %s %08x/%08x\n",
382 subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
383 break;
384 case REG_SZ:
385 ok( !strcmp( exp_value, value ),
386 "Wrong value in registry: %s %s '%s' instead of '%s'\n",
387 subKey1, valName1, value, (const char *)exp_value );
388 break;
390 found++;
392 else if (strict)
394 ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
395 subKey1, valName2 );
398 if (subKey2 && !strict)
400 *value='\0';
401 valueLen=sizeof(value);
402 RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
403 rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
404 RegCloseKey( hKey );
405 if (rc==ERROR_SUCCESS)
407 ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
408 switch (exp_type)
410 case REG_DWORD:
411 ok( *(DWORD *)value == *(DWORD *)exp_value,
412 "Wrong value in registry: %s %s %08x/%08x\n",
413 subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
414 break;
415 case REG_SZ:
416 ok( !strcmp( exp_value, value ),
417 "Wrong value in registry: %s %s '%s' instead of '%s'\n",
418 subKey1, valName1, value, (const char *)exp_value );
419 break;
421 found++;
423 else if (strict)
425 ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
426 subKey2, valName1 );
428 if (valName2)
430 *value='\0';
431 valueLen=sizeof(value);
432 RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
433 rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
434 RegCloseKey( hKey );
435 if (rc==ERROR_SUCCESS)
437 ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
438 switch (exp_type)
440 case REG_DWORD:
441 ok( *(DWORD *)value == *(DWORD *)exp_value,
442 "Wrong value in registry: %s %s %08x/%08x\n",
443 subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
444 break;
445 case REG_SZ:
446 ok( !strcmp( exp_value, value ),
447 "Wrong value in registry: %s %s '%s' instead of '%s'\n",
448 subKey1, valName1, value, (const char *)exp_value );
449 break;
451 found++;
453 else if (strict)
455 ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
456 subKey2, valName2 );
460 ok(found || optional,
461 "Missing registry values: %s or %s in keys: %s or %s\n",
462 valName1, (valName2?valName2:"<n/a>"), subKey1, (subKey2?subKey2:"<n/a>") );
465 #define test_reg_key( subKey, valName, testValue ) \
466 _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, FALSE )
467 #define test_reg_key_optional( subKey, valName, testValue ) \
468 _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, TRUE )
469 #define test_reg_key_ex( subKey1, subKey2, valName, testValue ) \
470 _test_reg_key( subKey1, subKey2, valName, NULL, testValue, REG_SZ, FALSE )
471 #define test_reg_key_ex2( subKey1, subKey2, valName1, valName2, testValue ) \
472 _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, FALSE )
473 #define test_reg_key_ex2_optional( subKey1, subKey2, valName1, valName2, testValue ) \
474 _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, TRUE )
475 #define test_reg_key_dword( subKey, valName, testValue ) \
476 _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_DWORD, FALSE )
478 /* get a metric from the registry. If the value is negative
479 * it is assumed to be in twips and converted to pixels */
480 static UINT metricfromreg( const char *keyname, const char *valname, int dpi)
482 HKEY hkey;
483 char buf[64];
484 DWORD ret;
485 DWORD size, type;
486 int value;
488 RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
489 size = sizeof(buf);
490 ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)buf, &size );
491 RegCloseKey( hkey );
492 if( ret != ERROR_SUCCESS) return -1;
493 value = atoi( buf);
494 if( value < 0)
495 value = ( -value * dpi + 720) / 1440;
496 return value;
499 typedef struct
501 INT16 lfHeight;
502 INT16 lfWidth;
503 INT16 lfEscapement;
504 INT16 lfOrientation;
505 INT16 lfWeight;
506 BYTE lfItalic;
507 BYTE lfUnderline;
508 BYTE lfStrikeOut;
509 BYTE lfCharSet;
510 BYTE lfOutPrecision;
511 BYTE lfClipPrecision;
512 BYTE lfQuality;
513 BYTE lfPitchAndFamily;
514 CHAR lfFaceName[LF_FACESIZE];
515 } LOGFONT16, *LPLOGFONT16;
517 /* get logfont from the registry */
518 static int lffromreg( const char *keyname, const char *valname, LOGFONTA *plf)
520 HKEY hkey;
521 LOGFONTW lfw;
522 DWORD ret, size, type;
524 RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
525 size = sizeof( lfw);
526 ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)&lfw, &size );
527 RegCloseKey( hkey );
528 ok( ret == ERROR_SUCCESS, "Key \"%s\" value \"%s\" not found\n", keyname, valname);
529 if( ret != ERROR_SUCCESS)
530 return FALSE;
531 if( size <= sizeof( LOGFONT16)) {
532 LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
533 plf->lfHeight = plf16->lfHeight;
534 plf->lfWidth = plf16->lfWidth;
535 plf->lfEscapement = plf16->lfEscapement;
536 plf->lfOrientation = plf16->lfOrientation;
537 plf->lfWeight = plf16->lfWeight;
538 plf->lfItalic = plf16->lfItalic;
539 plf->lfUnderline = plf16->lfUnderline;
540 plf->lfStrikeOut = plf16->lfStrikeOut;
541 plf->lfCharSet = plf16->lfCharSet;
542 plf->lfOutPrecision = plf16->lfOutPrecision;
543 plf->lfClipPrecision = plf16->lfClipPrecision;
544 plf->lfQuality = plf16->lfQuality;
545 plf->lfPitchAndFamily = plf16->lfPitchAndFamily;
546 memcpy( plf->lfFaceName, plf16->lfFaceName, LF_FACESIZE );
547 } else if( size <= sizeof( LOGFONTA)) {
548 plf = (LOGFONTA*) &lfw;
549 } else {
550 plf->lfHeight = lfw.lfHeight;
551 plf->lfWidth = lfw.lfWidth;
552 plf->lfEscapement = lfw.lfEscapement;
553 plf->lfOrientation = lfw.lfOrientation;
554 plf->lfWeight = lfw.lfWeight;
555 plf->lfItalic = lfw.lfItalic;
556 plf->lfUnderline = lfw.lfUnderline;
557 plf->lfStrikeOut = lfw.lfStrikeOut;
558 plf->lfCharSet = lfw.lfCharSet;
559 plf->lfOutPrecision = lfw.lfOutPrecision;
560 plf->lfClipPrecision = lfw.lfClipPrecision;
561 plf->lfQuality = lfw.lfQuality;
562 plf->lfPitchAndFamily = lfw.lfPitchAndFamily;
563 WideCharToMultiByte( CP_ACP, 0, lfw.lfFaceName, -1, plf->lfFaceName,
564 LF_FACESIZE, NULL, NULL);
567 return TRUE;
570 static void test_SPI_SETBEEP( void ) /* 2 */
572 BOOL rc;
573 BOOL old_b;
574 BOOL b;
575 BOOL curr_val;
577 trace("testing SPI_{GET,SET}BEEP\n");
578 SetLastError(0xdeadbeef);
579 rc=SystemParametersInfoA( SPI_GETBEEP, 0, &old_b, 0 );
580 if (!test_error_msg(rc,"SPI_{GET,SET}BEEP"))
581 return;
583 curr_val = TRUE;
584 rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
585 if (!test_error_msg(rc,"SPI_SETBEEP")) return;
586 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
587 test_change_message( SPI_SETBEEP, 0 );
588 test_reg_key( SPI_SETBEEP_REGKEY,
589 SPI_SETBEEP_VALNAME,
590 curr_val ? "Yes" : "No" );
591 rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
592 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
593 eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
594 rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
595 if (rc || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
597 ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
598 eq( b, curr_val, "SystemParametersInfoW", "%d" );
601 /* is a message sent for the second change? */
602 rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
603 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
604 test_change_message( SPI_SETBEEP, 0 );
606 curr_val = FALSE;
607 rc=SystemParametersInfoW( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
608 if (rc == FALSE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
609 rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
610 ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
611 test_change_message( SPI_SETBEEP, 0 );
612 test_reg_key( SPI_SETBEEP_REGKEY,
613 SPI_SETBEEP_VALNAME,
614 curr_val ? "Yes" : "No" );
615 rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
616 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
617 eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
618 rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
619 if (rc || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
621 ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
622 eq( b, curr_val, "SystemParametersInfoW", "%d" );
624 ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled\n" );
626 rc=SystemParametersInfoA( SPI_SETBEEP, old_b, 0, SPIF_UPDATEINIFILE );
627 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
630 static const char *setmouse_valuenames[3] = {
631 SPI_SETMOUSE_VALNAME1,
632 SPI_SETMOUSE_VALNAME2,
633 SPI_SETMOUSE_VALNAME3
637 * Runs check for one setting of spi_setmouse.
639 static BOOL run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *proj_change, int nchange )
641 BOOL rc;
642 INT mi[3];
643 static int aw_turn = 0;
645 char buf[20];
646 int i;
648 aw_turn++;
649 rc = FALSE;
650 SetLastError(0xdeadbeef);
651 if (aw_turn % 2) /* call unicode on odd (non even) calls */
652 rc=SystemParametersInfoW( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
653 else
654 rc=SystemParametersInfoA( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
655 if (!test_error_msg(rc,"SPI_SETMOUSE")) return FALSE;
657 ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
658 test_change_message( SPI_SETMOUSE, 0 );
659 for (i = 0; i < 3; i++)
661 sprintf( buf, "%d", curr_val[i] );
662 test_reg_key( SPI_SETMOUSE_REGKEY, setmouse_valuenames[i], buf );
665 rc=SystemParametersInfoA( SPI_GETMOUSE, 0, mi, 0 );
666 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
667 for (i = 0; i < 3; i++)
669 ok(mi[i] == curr_val[i],
670 "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
673 rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
674 ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
675 for (i = 0; i < 3; i++)
677 ok(mi[i] == curr_val[i],
678 "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
681 if (0)
683 /* FIXME: this always fails for me - AJ */
684 for (i = 0; i < nchange; i++)
686 POINT mv;
687 mouse_event( MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
688 mouse_event( MOUSEEVENTF_MOVE, req_change[i].x, req_change[i].y, 0, 0 );
689 GetCursorPos( &mv );
690 ok( proj_change[i].x == mv.x, "Projected dx and real dx comparison. May fail under high load.\n" );
691 ok( proj_change[i].y == mv.y, "Projected dy equals real dy. May fail under high load.\n" );
694 return TRUE;
697 static void test_SPI_SETMOUSE( void ) /* 4 */
699 BOOL rc;
700 INT old_mi[3];
702 /* win nt default values - 6, 10, 1 */
703 INT curr_val[3] = {6, 10, 1};
705 /* requested and projected mouse movements */
706 POINT req_change[] = { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
707 POINT proj_change1[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
708 POINT proj_change2[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {44, 20}, {400, 400} };
709 POINT proj_change3[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
710 POINT proj_change4[] = { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
711 POINT proj_change5[] = { {6, 6}, { 7, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
712 POINT proj_change6[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
713 POINT proj_change7[] = { {6, 6}, {14, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
714 POINT proj_change8[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
716 int nchange = ARRAY_SIZE(req_change);
718 trace("testing SPI_{GET,SET}MOUSE\n");
719 SetLastError(0xdeadbeef);
720 rc=SystemParametersInfoA( SPI_GETMOUSE, 0, old_mi, 0 );
721 if (!test_error_msg(rc,"SPI_{GET,SET}MOUSE"))
722 return;
724 if (!run_spi_setmouse_test( curr_val, req_change, proj_change1, nchange )) return;
726 /* acceleration change */
727 curr_val[2] = 2;
728 run_spi_setmouse_test( curr_val, req_change, proj_change2, nchange );
730 /* acceleration change */
731 curr_val[2] = 3;
732 run_spi_setmouse_test( curr_val, req_change, proj_change3, nchange );
734 /* acceleration change */
735 curr_val[2] = 0;
736 run_spi_setmouse_test( curr_val, req_change, proj_change4, nchange );
738 /* threshold change */
739 curr_val[2] = 1;
740 curr_val[0] = 7;
741 run_spi_setmouse_test( curr_val, req_change, proj_change5, nchange );
743 /* threshold change */
744 curr_val[2] = 2;
745 curr_val[0] = 6;
746 curr_val[1] = 6;
747 run_spi_setmouse_test( curr_val, req_change, proj_change6, nchange );
749 /* threshold change */
750 curr_val[1] = 7;
751 run_spi_setmouse_test( curr_val, req_change, proj_change7, nchange );
753 /* threshold change */
754 curr_val[1] = 5;
755 run_spi_setmouse_test( curr_val, req_change, proj_change8, nchange );
757 rc=SystemParametersInfoA( SPI_SETMOUSE, 0, old_mi, SPIF_UPDATEINIFILE );
758 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
761 static BOOL test_setborder(UINT curr_val, int usesetborder, int dpi)
763 BOOL rc;
764 UINT border, regval;
765 INT frame;
766 NONCLIENTMETRICSA ncm;
768 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
769 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
770 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
771 if( usesetborder) {
772 rc=SystemParametersInfoA( SPI_SETBORDER, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
773 if (!test_error_msg(rc,"SPI_SETBORDER")) return FALSE;
774 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
775 test_change_message( SPI_SETBORDER, 1 );
776 } else { /* set non client metrics */
777 ncm.iBorderWidth = curr_val;
778 rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
779 SPIF_SENDCHANGE);
780 if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return FALSE;
781 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
782 test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
784 if( curr_val) { /* skip if 0, some windows versions return 0 others 1 */
785 regval = metricfromreg( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_VALNAME, dpi);
786 if( regval != curr_val)
787 regval = metricfromreg( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, dpi);
788 ok( regval==curr_val, "wrong value in registry %d, expected %d\n", regval, curr_val);
790 /* minimum border width is 1 */
791 if (curr_val == 0) curr_val = 1;
792 /* should be the same as the non client metrics */
793 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
794 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
795 eq( (UINT)ncm.iBorderWidth, curr_val, "NonClientMetric.iBorderWidth", "%d");
796 /* and from SPI_GETBORDER */
797 rc=SystemParametersInfoA( SPI_GETBORDER, 0, &border, 0 );
798 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
799 eq( border, curr_val, "SPI_{GET,SET}BORDER", "%d");
800 /* test some SystemMetrics */
801 frame = curr_val + GetSystemMetrics( SM_CXDLGFRAME );
802 eq( frame, GetSystemMetrics( SM_CXFRAME ), "SM_CXFRAME", "%d" );
803 eq( frame, GetSystemMetrics( SM_CYFRAME ), "SM_CYFRAME", "%d" );
804 eq( frame, GetSystemMetrics( SM_CXSIZEFRAME ), "SM_CXSIZEFRAME", "%d" );
805 eq( frame, GetSystemMetrics( SM_CYSIZEFRAME ), "SM_CYSIZEFRAME", "%d" );
806 return TRUE;
809 static void test_SPI_SETBORDER( void ) /* 6 */
811 BOOL rc;
812 UINT old_border;
813 NONCLIENTMETRICSA ncmsave;
814 INT CaptionWidth,
815 PaddedBorderWidth;
817 ncmsave.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
818 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncmsave, 0);
819 if( !rc) {
820 win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
821 return;
823 /* CaptionWidth from the registry may have different value of iCaptionWidth
824 * from the non client metrics (observed on WinXP).
825 * Fix this so we can safely restore settings with the nonclientmetrics */
826 CaptionWidth = metricfromreg(
827 "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
828 ncmsave.iCaptionWidth = CaptionWidth;
830 /* These tests hang when XFree86 4.0 for Windows is running (tested on
831 * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
832 * running.
834 if (FindWindowA( NULL, "Cygwin/XFree86" ))
835 return;
837 trace("testing SPI_{GET,SET}BORDER\n");
839 SetLastError(0xdeadbeef);
840 rc=SystemParametersInfoA( SPI_GETBORDER, 0, &old_border, 0 );
841 if (!test_error_msg(rc,"SPI_{GET,SET}BORDER"))
842 return;
843 /* FIXME: include new PaddedBorderWidth parameter */
844 PaddedBorderWidth = ncmsave.iBorderWidth - old_border;
845 if( PaddedBorderWidth){
846 win_skip( "Cannot reliably restore border width yet (PaddedBorderWidth = %d)\n",
847 PaddedBorderWidth);
848 return;
850 /* This will restore sane values if the test hang previous run. */
851 if ( old_border == 7 || old_border == 20 )
852 old_border = 1;
854 /* win2k3 fails if you set the same border twice, or if size is 0 */
855 if (!test_setborder(2, 1, dpi)) return;
856 test_setborder(1, 1, dpi);
857 test_setborder(3, 1, dpi);
858 if (!test_setborder(1, 0, dpi)) return;
859 test_setborder(0, 0, dpi);
860 test_setborder(3, 0, dpi);
862 rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncmsave,
863 SPIF_UPDATEINIFILE| SPIF_SENDCHANGE);
864 test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
865 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
868 static void test_SPI_SETKEYBOARDSPEED( void ) /* 10 */
870 BOOL rc;
871 UINT old_speed;
872 const UINT vals[]={0,20,31};
873 unsigned int i;
875 trace("testing SPI_{GET,SET}KEYBOARDSPEED\n");
876 SetLastError(0xdeadbeef);
877 rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &old_speed, 0 );
878 if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDSPEED"))
879 return;
881 for (i=0;i<ARRAY_SIZE(vals);i++)
883 UINT v;
884 char buf[10];
886 rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, vals[i], 0,
887 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
888 if (!test_error_msg(rc,"SPI_SETKEYBOARDSPEED")) return;
889 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
890 test_change_message( SPI_SETKEYBOARDSPEED, 0 );
891 sprintf( buf, "%d", vals[i] );
892 test_reg_key( SPI_SETKEYBOARDSPEED_REGKEY, SPI_SETKEYBOARDSPEED_VALNAME, buf );
894 rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &v, 0 );
895 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
896 eq( v, vals[i], "SPI_{GET,SET}KEYBOARDSPEED", "%d" );
899 rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, old_speed, 0, SPIF_UPDATEINIFILE );
900 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
903 /* test_SPI_ICONHORIZONTALSPACING helper */
904 static BOOL dotest_spi_iconhorizontalspacing( INT curr_val)
906 BOOL rc;
907 INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
908 ICONMETRICSA im;
910 rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
911 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
912 if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING")) return FALSE;
913 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
914 test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
915 curr_val = max( curr_val, min_val );
916 /* The registry keys depend on the Windows version and the values too
917 * let's test (works on win95,ME,NT4,2k,XP)
919 regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY2, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
920 if( regval != curr_val)
921 regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
922 ok( curr_val == regval,
923 "wrong value in registry %d, expected %d\n", regval, curr_val);
924 /* compare with what SPI_ICONHORIZONTALSPACING returns */
925 rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
926 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
927 eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
928 /* and with a system metrics */
929 eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
930 /* and with what SPI_GETICONMETRICS returns */
931 im.cbSize = sizeof(ICONMETRICSA);
932 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
933 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
934 eq( im.iHorzSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
935 return TRUE;
938 static void test_SPI_ICONHORIZONTALSPACING( void ) /* 13 */
940 BOOL rc;
941 INT old_spacing;
943 trace("testing SPI_ICONHORIZONTALSPACING\n");
944 SetLastError(0xdeadbeef);
945 /* default value: 75 */
946 rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &old_spacing, 0 );
947 if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING"))
948 return;
949 /* do not increase the value as it would upset the user's icon layout */
950 if (!dotest_spi_iconhorizontalspacing( old_spacing - 1)) return;
951 dotest_spi_iconhorizontalspacing( 10); /* minimum is 32 */
952 /* restore */
953 rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, old_spacing, 0, SPIF_UPDATEINIFILE );
954 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
957 static void test_SPI_SETSCREENSAVETIMEOUT( void ) /* 14 */
959 BOOL rc;
960 UINT old_timeout;
961 const UINT vals[]={0,32767};
962 unsigned int i;
964 trace("testing SPI_{GET,SET}SCREENSAVETIMEOUT\n");
965 SetLastError(0xdeadbeef);
966 rc=SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &old_timeout, 0 );
967 if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVETIMEOUT"))
968 return;
970 for (i=0;i<ARRAY_SIZE(vals);i++)
972 UINT v;
973 char buf[10];
975 rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, vals[i], 0,
976 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
977 if (!test_error_msg(rc,"SPI_SETSCREENSAVETIMEOUT")) return;
978 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
979 test_change_message( SPI_SETSCREENSAVETIMEOUT, 0 );
980 sprintf( buf, "%d", vals[i] );
981 test_reg_key( SPI_SETSCREENSAVETIMEOUT_REGKEY,
982 SPI_SETSCREENSAVETIMEOUT_VALNAME, buf );
984 rc = SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &v, 0 );
985 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
986 eq( v, vals[i], "SPI_{GET,SET}SCREENSAVETIMEOUT", "%d" );
989 rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, old_timeout, 0,
990 SPIF_UPDATEINIFILE );
991 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
994 static void test_SPI_SETSCREENSAVEACTIVE( void ) /* 17 */
996 BOOL rc;
997 BOOL old_b;
998 const UINT vals[]={TRUE,FALSE};
999 unsigned int i;
1001 trace("testing SPI_{GET,SET}SCREENSAVEACTIVE\n");
1002 SetLastError(0xdeadbeef);
1003 rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &old_b, 0 );
1004 if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVEACTIVE"))
1005 return;
1007 for (i=0;i<ARRAY_SIZE(vals);i++)
1009 UINT v;
1011 rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, vals[i], 0,
1012 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1013 if (!test_error_msg(rc,"SPI_SETSCREENSAVEACTIVE")) return;
1014 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1015 test_change_message( SPI_SETSCREENSAVEACTIVE, 0 );
1016 test_reg_key( SPI_SETSCREENSAVEACTIVE_REGKEY,
1017 SPI_SETSCREENSAVEACTIVE_VALNAME,
1018 vals[i] ? "1" : "0" );
1020 rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &v, 0 );
1021 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1022 ok(v == vals[i] || broken(! v) /* Win 7 */,
1023 "SPI_{GET,SET}SCREENSAVEACTIVE: got %d instead of %d\n", v, vals[i]);
1026 rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1027 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1030 static void test_SPI_SETGRIDGRANULARITY( void ) /* 19 */
1032 /* ??? */;
1035 static void test_SPI_SETKEYBOARDDELAY( void ) /* 23 */
1037 BOOL rc;
1038 UINT old_delay;
1039 const UINT vals[]={0,3};
1040 unsigned int i;
1042 trace("testing SPI_{GET,SET}KEYBOARDDELAY\n");
1043 SetLastError(0xdeadbeef);
1044 rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &old_delay, 0 );
1045 if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
1046 return;
1048 for (i=0;i<ARRAY_SIZE(vals);i++)
1050 UINT delay;
1051 char buf[10];
1053 rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, vals[i], 0,
1054 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1055 if (!test_error_msg(rc,"SPI_SETKEYBOARDDELAY")) return;
1056 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1057 test_change_message( SPI_SETKEYBOARDDELAY, 0 );
1058 sprintf( buf, "%d", vals[i] );
1059 test_reg_key( SPI_SETKEYBOARDDELAY_REGKEY,
1060 SPI_SETKEYBOARDDELAY_VALNAME, buf );
1062 rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &delay, 0 );
1063 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1064 eq( delay, vals[i], "SPI_{GET,SET}KEYBOARDDELAY", "%d" );
1067 rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, old_delay, 0, SPIF_UPDATEINIFILE );
1068 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1072 /* test_SPI_ICONVERTICALSPACING helper */
1073 static BOOL dotest_spi_iconverticalspacing( INT curr_val)
1075 BOOL rc;
1076 INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
1077 ICONMETRICSA im;
1079 rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
1080 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1081 if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING")) return FALSE;
1082 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1083 test_change_message( SPI_ICONVERTICALSPACING, 0 );
1084 curr_val = max( curr_val, min_val );
1085 /* The registry keys depend on the Windows version and the values too
1086 * let's test (works on win95,ME,NT4,2k,XP)
1088 regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY2, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1089 if( regval != curr_val)
1090 regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1091 ok( curr_val == regval,
1092 "wrong value in registry %d, expected %d\n", regval, curr_val);
1093 /* compare with what SPI_ICONVERTICALSPACING returns */
1094 rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1095 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1096 eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
1097 /* and with a system metrics */
1098 eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
1099 /* and with what SPI_GETICONMETRICS returns */
1100 im.cbSize = sizeof(ICONMETRICSA);
1101 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1102 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1103 eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
1104 return TRUE;
1107 static void test_SPI_ICONVERTICALSPACING( void ) /* 24 */
1109 BOOL rc;
1110 INT old_spacing;
1112 trace("testing SPI_ICONVERTICALSPACING\n");
1113 SetLastError(0xdeadbeef);
1114 /* default value: 75 */
1115 rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
1116 if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
1117 return;
1118 /* do not increase the value as it would upset the user's icon layout */
1119 if (!dotest_spi_iconverticalspacing( old_spacing - 1)) return;
1120 /* same tests with a value less than the minimum 32 */
1121 dotest_spi_iconverticalspacing( 10);
1122 /* restore */
1123 rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
1124 SPIF_UPDATEINIFILE );
1125 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1128 static void test_SPI_SETICONTITLEWRAP( void ) /* 26 */
1130 BOOL rc;
1131 BOOL old_b;
1132 const UINT vals[]={TRUE,FALSE};
1133 unsigned int i;
1134 ICONMETRICSA im;
1136 /* These tests hang when XFree86 4.0 for Windows is running (tested on
1137 * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
1138 * running.
1140 if (FindWindowA( NULL, "Cygwin/XFree86" ))
1141 return;
1143 trace("testing SPI_{GET,SET}ICONTITLEWRAP\n");
1144 SetLastError(0xdeadbeef);
1145 rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &old_b, 0 );
1146 if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
1147 return;
1149 for (i=0;i<ARRAY_SIZE(vals);i++)
1151 UINT v;
1152 UINT regval;
1154 rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, vals[i], 0,
1155 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1156 if (!test_error_msg(rc,"SPI_SETICONTITLEWRAP")) return;
1157 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1158 test_change_message( SPI_SETICONTITLEWRAP, 1 );
1159 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2,
1160 SPI_SETICONTITLEWRAP_VALNAME, dpi);
1161 if( regval != vals[i])
1162 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
1163 SPI_SETICONTITLEWRAP_VALNAME, dpi);
1164 ok( regval == vals[i], "wrong value in registry %d, expected %d\n", regval, vals[i] );
1166 rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
1167 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1168 eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
1169 /* and test with what SPI_GETICONMETRICS returns */
1170 im.cbSize = sizeof(ICONMETRICSA);
1171 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1172 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1173 eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
1176 rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, old_b, 0, SPIF_UPDATEINIFILE );
1177 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1180 static void test_SPI_SETMENUDROPALIGNMENT( void ) /* 28 */
1182 BOOL rc;
1183 BOOL old_b;
1184 const UINT vals[]={TRUE,FALSE};
1185 unsigned int i;
1187 trace("testing SPI_{GET,SET}MENUDROPALIGNMENT\n");
1188 SetLastError(0xdeadbeef);
1189 rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &old_b, 0 );
1190 if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
1191 return;
1193 for (i=0;i<ARRAY_SIZE(vals);i++)
1195 UINT v;
1197 rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, vals[i], 0,
1198 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1199 if (!test_error_msg(rc,"SPI_SETMENUDROPALIGNMENT")) return;
1200 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1201 test_change_message( SPI_SETMENUDROPALIGNMENT, 0 );
1202 test_reg_key_ex( SPI_SETMENUDROPALIGNMENT_REGKEY1,
1203 SPI_SETMENUDROPALIGNMENT_REGKEY2,
1204 SPI_SETMENUDROPALIGNMENT_VALNAME,
1205 vals[i] ? "1" : "0" );
1207 rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &v, 0 );
1208 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1209 eq( v, vals[i], "SPI_{GET,SET}MENUDROPALIGNMENT", "%d" );
1210 eq( GetSystemMetrics( SM_MENUDROPALIGNMENT ), (int)vals[i],
1211 "SM_MENUDROPALIGNMENT", "%d" );
1214 rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, old_b, 0,
1215 SPIF_UPDATEINIFILE );
1216 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1219 static void test_SPI_SETDOUBLECLKWIDTH( void ) /* 29 */
1221 BOOL rc;
1222 INT old_width;
1223 const UINT vals[]={0,10000};
1224 unsigned int i;
1226 trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
1227 old_width = GetSystemMetrics( SM_CXDOUBLECLK );
1229 for (i=0;i<ARRAY_SIZE(vals);i++)
1231 char buf[10];
1233 SetLastError(0xdeadbeef);
1234 rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, vals[i], 0,
1235 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1236 if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKWIDTH"))
1237 return;
1239 test_change_message( SPI_SETDOUBLECLKWIDTH, 0 );
1240 sprintf( buf, "%d", vals[i] );
1241 test_reg_key_ex( SPI_SETDOUBLECLKWIDTH_REGKEY1,
1242 SPI_SETDOUBLECLKWIDTH_REGKEY2,
1243 SPI_SETDOUBLECLKWIDTH_VALNAME, buf );
1244 eq( GetSystemMetrics( SM_CXDOUBLECLK ), (int)vals[i],
1245 "SM_CXDOUBLECLK", "%d" );
1248 rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, old_width, 0,
1249 SPIF_UPDATEINIFILE );
1250 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1253 static void test_SPI_SETDOUBLECLKHEIGHT( void ) /* 30 */
1255 BOOL rc;
1256 INT old_height;
1257 const UINT vals[]={0,10000};
1258 unsigned int i;
1260 trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
1261 old_height = GetSystemMetrics( SM_CYDOUBLECLK );
1263 for (i=0;i<ARRAY_SIZE(vals);i++)
1265 char buf[10];
1267 SetLastError(0xdeadbeef);
1268 rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, vals[i], 0,
1269 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1270 if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKHEIGHT"))
1271 return;
1273 test_change_message( SPI_SETDOUBLECLKHEIGHT, 0 );
1274 sprintf( buf, "%d", vals[i] );
1275 test_reg_key_ex( SPI_SETDOUBLECLKHEIGHT_REGKEY1,
1276 SPI_SETDOUBLECLKHEIGHT_REGKEY2,
1277 SPI_SETDOUBLECLKHEIGHT_VALNAME, buf );
1278 eq( GetSystemMetrics( SM_CYDOUBLECLK ), (int)vals[i],
1279 "SM_CYDOUBLECLK", "%d" );
1282 rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, old_height, 0,
1283 SPIF_UPDATEINIFILE );
1284 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1287 static void test_SPI_SETDOUBLECLICKTIME( void ) /* 32 */
1289 BOOL rc;
1290 UINT curr_val;
1291 UINT saved_val;
1292 UINT old_time;
1293 char buf[10];
1295 trace("testing SPI_{GET,SET}DOUBLECLICKTIME\n");
1296 old_time = GetDoubleClickTime();
1298 curr_val = 0;
1299 SetLastError(0xdeadbeef);
1300 rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1301 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1302 if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLICKTIME"))
1303 return;
1305 test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1306 sprintf( buf, "%d", curr_val );
1307 test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1308 SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1309 curr_val = 500; /* used value for 0 */
1310 eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1312 curr_val = 1000;
1313 rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1314 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1315 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1316 test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1317 sprintf( buf, "%d", curr_val );
1318 test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1319 SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1320 eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1322 saved_val = curr_val;
1324 curr_val = 0;
1325 SetDoubleClickTime( curr_val );
1326 sprintf( buf, "%d", saved_val );
1327 test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1328 SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1329 curr_val = 500; /* used value for 0 */
1330 eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1332 curr_val = 1000;
1333 SetDoubleClickTime( curr_val );
1334 sprintf( buf, "%d", saved_val );
1335 test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1336 SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1337 eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1339 rc=SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, old_time, 0, SPIF_UPDATEINIFILE);
1340 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1343 static void test_SPI_SETMOUSEBUTTONSWAP( void ) /* 33 */
1345 BOOL rc;
1346 BOOL old_b;
1347 const UINT vals[]={TRUE,FALSE};
1348 unsigned int i;
1350 trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
1351 old_b = GetSystemMetrics( SM_SWAPBUTTON );
1353 for (i=0;i<ARRAY_SIZE(vals);i++)
1355 SetLastError(0xdeadbeef);
1356 rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
1357 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1358 if (!test_error_msg(rc,"SPI_SETMOUSEBUTTONSWAP")) return;
1360 test_change_message( SPI_SETMOUSEBUTTONSWAP, 0 );
1361 test_reg_key( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1362 SPI_SETMOUSEBUTTONSWAP_VALNAME,
1363 vals[i] ? "1" : "0" );
1364 eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
1365 "SM_SWAPBUTTON", "%d" );
1366 rc=SwapMouseButton((BOOL)vals[i^1]);
1367 eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
1368 "SwapMouseButton", "%d" );
1369 ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
1372 rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, old_b, 0,
1373 SPIF_UPDATEINIFILE );
1374 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1377 static void test_SPI_SETFASTTASKSWITCH( void ) /* 36 */
1379 BOOL rc;
1380 BOOL v;
1382 trace("testing SPI_GETFASTTASKSWITCH\n");
1383 SetLastError(0xdeadbeef);
1384 rc=SystemParametersInfoA( SPI_GETFASTTASKSWITCH, 0, &v, 0 );
1385 if (!test_error_msg(rc,"SPI_{GET,SET}FASTTASKSWITCH"))
1386 return;
1388 /* there is not a single Windows platform on which SPI_GETFASTTASKSWITCH
1389 * works. That sure simplifies testing!
1393 static void test_SPI_SETDRAGFULLWINDOWS( void ) /* 37 */
1395 BOOL rc;
1396 BOOL old_b;
1397 const UINT vals[]={TRUE,FALSE};
1398 unsigned int i;
1400 trace("testing SPI_{GET,SET}DRAGFULLWINDOWS\n");
1401 SetLastError(0xdeadbeef);
1402 rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &old_b, 0 );
1404 /* SPI_{GET,SET}DRAGFULLWINDOWS is not implemented on Win95 */
1405 if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
1406 return;
1408 for (i=0;i<ARRAY_SIZE(vals);i++)
1410 UINT v;
1412 rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, vals[i], 0,
1413 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1414 if (!test_error_msg(rc,"SPI_SETDRAGFULLWINDOWS")) return;
1415 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1416 test_change_message( SPI_SETDRAGFULLWINDOWS, 0 );
1417 test_reg_key( SPI_SETDRAGFULLWINDOWS_REGKEY,
1418 SPI_SETDRAGFULLWINDOWS_VALNAME,
1419 vals[i] ? "1" : "0" );
1421 rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &v, 0 );
1422 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1423 eq( v, vals[i], "SPI_{GET,SET}DRAGFULLWINDOWS", "%d" );
1426 rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, old_b, 0, SPIF_UPDATEINIFILE );
1427 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1430 #define test_reg_metric( KEY, VAL, val) do { \
1431 INT regval;\
1432 regval = metricfromreg( KEY, VAL, dpi);\
1433 ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1434 } while(0)
1436 #define test_reg_metric2( KEY1, KEY2, VAL, val) do { \
1437 INT regval;\
1438 regval = metricfromreg( KEY1, VAL, dpi);\
1439 if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
1440 ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1441 } while(0)
1443 #define test_reg_font( KEY, VAL, LF) do { \
1444 LOGFONTA lfreg;\
1445 lffromreg( KEY, VAL, &lfreg);\
1446 ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == MulDiv( lfreg.lfHeight, dpi, real_dpi ) : \
1447 MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
1448 (LF).lfWidth == lfreg.lfWidth &&\
1449 (LF).lfWeight == lfreg.lfWeight &&\
1450 !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
1451 , "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
1452 } while(0)
1454 #define TEST_NONCLIENTMETRICS_REG( ncm) do { \
1455 /*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
1456 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
1457 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
1458 /*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
1459 test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
1460 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
1461 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
1462 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
1463 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
1464 test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
1465 test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
1466 test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
1467 test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
1468 test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont); } while(0)
1470 /* get text metric height value for the specified logfont */
1471 static int get_tmheight( LOGFONTA *plf, int flag)
1473 TEXTMETRICA tm;
1474 HDC hdc = GetDC(0);
1475 HFONT hfont = CreateFontIndirectA( plf);
1476 hfont = SelectObject( hdc, hfont);
1477 GetTextMetricsA( hdc, &tm);
1478 hfont = SelectObject( hdc, hfont);
1479 ReleaseDC( 0, hdc );
1480 return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1483 static int get_tmheightW( LOGFONTW *plf, int flag)
1485 TEXTMETRICW tm;
1486 HDC hdc = GetDC(0);
1487 HFONT hfont = CreateFontIndirectW( plf);
1488 hfont = SelectObject( hdc, hfont);
1489 GetTextMetricsW( hdc, &tm);
1490 hfont = SelectObject( hdc, hfont);
1491 ReleaseDC( 0, hdc );
1492 return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1495 static void test_GetSystemMetrics( void);
1496 static UINT smcxsmsize = 999999999;
1498 static void test_SPI_SETNONCLIENTMETRICS( void ) /* 44 */
1500 BOOL rc;
1501 INT expect;
1502 NONCLIENTMETRICSA Ncmorig;
1503 NONCLIENTMETRICSA Ncmnew;
1504 NONCLIENTMETRICSA Ncmcur;
1505 NONCLIENTMETRICSA Ncmstart;
1507 Ncmorig.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1508 Ncmnew.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1509 Ncmcur.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1510 Ncmstart.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1512 trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1513 change_counter = 0;
1514 SetLastError(0xdeadbeef);
1515 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmorig, FALSE );
1516 if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1517 return;
1518 Ncmstart = Ncmorig;
1519 smcxsmsize = Ncmstart.iSmCaptionWidth;
1520 /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if
1521 the caption font height is higher than the CaptionHeight field,
1522 the latter is adjusted accordingly. To be able to restore these setting
1523 accurately be restore the raw values. */
1524 Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, real_dpi);
1525 Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1526 Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1527 Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1528 /* test registry entries */
1529 TEST_NONCLIENTMETRICS_REG( Ncmorig);
1531 /* make small changes */
1532 Ncmnew = Ncmstart;
1533 Ncmnew.iBorderWidth += 1;
1534 Ncmnew.iScrollWidth += 1;
1535 Ncmnew.iScrollHeight -= 1;
1536 Ncmnew.iCaptionWidth -= 2;
1537 Ncmnew.iCaptionHeight += 2;
1538 Ncmnew.lfCaptionFont.lfHeight +=1;
1539 Ncmnew.lfCaptionFont.lfWidth +=2;
1540 Ncmnew.lfCaptionFont.lfWeight +=1;
1541 Ncmnew.iSmCaptionWidth += 1;
1542 Ncmnew.iSmCaptionHeight += 2;
1543 Ncmnew.lfSmCaptionFont.lfHeight +=3;
1544 Ncmnew.lfSmCaptionFont.lfWidth -=1;
1545 Ncmnew.lfSmCaptionFont.lfWeight +=3;
1546 Ncmnew.iMenuWidth += 1;
1547 Ncmnew.iMenuHeight += 2;
1548 Ncmnew.lfMenuFont.lfHeight +=1;
1549 Ncmnew.lfMenuFont.lfWidth +=1;
1550 Ncmnew.lfMenuFont.lfWeight +=2;
1551 Ncmnew.lfStatusFont.lfHeight -=1;
1552 Ncmnew.lfStatusFont.lfWidth -=1;
1553 Ncmnew.lfStatusFont.lfWeight +=3;
1554 Ncmnew.lfMessageFont.lfHeight -=2;
1555 Ncmnew.lfMessageFont.lfWidth -=1;
1556 Ncmnew.lfMessageFont.lfWeight +=4;
1558 rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1559 SPIF_SENDCHANGE);
1560 if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return;
1561 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1562 test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1563 /* get them back */
1564 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1565 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1566 /* test registry entries */
1567 TEST_NONCLIENTMETRICS_REG( Ncmcur );
1568 /* test the system metrics with these settings */
1569 test_GetSystemMetrics();
1570 /* now for something invalid: increase the {menu|caption|smcaption} fonts
1571 by a large amount will increase the {menu|caption|smcaption} height*/
1572 Ncmnew = Ncmstart;
1573 Ncmnew.lfMenuFont.lfHeight -= 8;
1574 Ncmnew.lfCaptionFont.lfHeight =-4;
1575 Ncmnew.lfSmCaptionFont.lfHeight -=10;
1576 /* also show that a few values are lo limited */
1577 Ncmnew.iCaptionWidth = 0;
1578 Ncmnew.iCaptionHeight = 0;
1579 Ncmnew.iScrollHeight = 0;
1580 Ncmnew.iScrollWidth = 0;
1582 rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1583 SPIF_SENDCHANGE);
1584 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1585 test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1586 /* raw values are in registry */
1587 TEST_NONCLIENTMETRICS_REG( Ncmnew );
1588 /* get them back */
1589 rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1590 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1591 /* cooked values are returned */
1592 expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1593 ok( Ncmcur.iMenuHeight == expect,
1594 "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1595 expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1596 ok( Ncmcur.iCaptionHeight == expect,
1597 "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1598 expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1599 ok( Ncmcur.iSmCaptionHeight == expect,
1600 "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1602 /* iCaptionWidth depends on a version, could be 8, 12 (Vista, Win7), 13 */
1603 ok( (Ncmcur.iCaptionWidth >= 8 && Ncmcur.iCaptionWidth <= 13) ||
1604 Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme, the value never changes */
1605 "CaptionWidth: %d expected from [8, 13] or %d\n", Ncmcur.iCaptionWidth, Ncmstart.iCaptionWidth);
1606 ok( Ncmcur.iScrollWidth == 8,
1607 "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1608 ok( Ncmcur.iScrollHeight == 8,
1609 "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1610 /* test the system metrics with these settings */
1611 test_GetSystemMetrics();
1612 /* restore */
1613 rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA),
1614 &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1615 test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1616 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1617 /* test the system metrics with these settings */
1618 test_GetSystemMetrics();
1621 static void test_SPI_SETMINIMIZEDMETRICS( void ) /* 44 */
1623 BOOL rc;
1624 INT regval;
1625 MINIMIZEDMETRICS lpMm_orig;
1626 MINIMIZEDMETRICS lpMm_new;
1627 MINIMIZEDMETRICS lpMm_cur;
1629 lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1630 lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1631 lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1633 trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1634 SetLastError(0xdeadbeef);
1635 rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1636 if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1637 return;
1638 /* Test registry. Note that it is perfectly valid for some fields to
1639 * not be set.
1641 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1642 ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1643 regval, lpMm_orig.iWidth);
1644 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1645 ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1646 regval, lpMm_orig.iHorzGap);
1647 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1648 ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1649 regval, lpMm_orig.iVertGap);
1650 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1651 ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1652 regval, lpMm_orig.iArrange);
1653 /* set some new values */
1654 lpMm_cur.iWidth = 180;
1655 lpMm_cur.iHorzGap = 1;
1656 lpMm_cur.iVertGap = 1;
1657 lpMm_cur.iArrange = 5;
1658 rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1659 &lpMm_cur, SPIF_UPDATEINIFILE );
1660 if (!test_error_msg(rc,"SPI_SETMINIMIZEDMETRICS")) return;
1661 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1662 /* read them back */
1663 rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1664 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1665 /* and compare */
1666 eq( lpMm_new.iWidth, lpMm_cur.iWidth, "iWidth", "%d" );
1667 eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1668 eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1669 eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1670 /* test registry */
1671 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1672 ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1673 regval, lpMm_new.iWidth);
1674 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1675 ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1676 regval, lpMm_new.iHorzGap);
1677 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1678 ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1679 regval, lpMm_new.iVertGap);
1680 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1681 ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1682 regval, lpMm_new.iArrange);
1683 /* test some system metrics */
1684 eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1685 lpMm_new.iWidth, "iWidth", "%d" );
1686 eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1687 lpMm_new.iHorzGap, "iHorzGap", "%d" );
1688 eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1689 lpMm_new.iVertGap, "iVertGap", "%d" );
1690 eq( GetSystemMetrics( SM_ARRANGE ),
1691 lpMm_new.iArrange, "iArrange", "%d" );
1692 /* now some really invalid settings */
1693 lpMm_cur.iWidth = -1;
1694 lpMm_cur.iHorzGap = -1;
1695 lpMm_cur.iVertGap = -1;
1696 lpMm_cur.iArrange = - 1;
1697 rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1698 &lpMm_cur, SPIF_UPDATEINIFILE );
1699 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1700 /* read back */
1701 rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1702 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1703 /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1704 eq( lpMm_new.iWidth, 0, "iWidth", "%d" );
1705 eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1706 eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1707 eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1708 /* test registry */
1709 if (0)
1711 /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1712 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1713 ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1714 regval, lpMm_new.iWidth);
1715 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1716 ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1717 regval, lpMm_new.iHorzGap);
1718 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1719 ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1720 regval, lpMm_new.iVertGap);
1721 regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1722 ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1723 regval, lpMm_new.iArrange);
1725 /* test some system metrics */
1726 eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1727 lpMm_new.iWidth, "iWidth", "%d" );
1728 eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1729 lpMm_new.iHorzGap, "iHorzGap", "%d" );
1730 eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1731 lpMm_new.iVertGap, "iVertGap", "%d" );
1732 eq( GetSystemMetrics( SM_ARRANGE ),
1733 lpMm_new.iArrange, "iArrange", "%d" );
1734 /* restore */
1735 rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1736 &lpMm_orig, SPIF_UPDATEINIFILE );
1737 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1738 /* check that */
1739 rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1740 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1741 eq( lpMm_new.iWidth, lpMm_orig.iWidth, "iWidth", "%d" );
1742 eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1743 eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1744 eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1747 static void test_SPI_SETICONMETRICS( void ) /* 46 */
1749 BOOL rc, wrap;
1750 INT spacing;
1751 ICONMETRICSA im_orig;
1752 ICONMETRICSA im_new;
1753 ICONMETRICSA im_cur;
1754 INT regval;
1756 im_orig.cbSize = sizeof(ICONMETRICSA);
1757 im_new.cbSize = sizeof(ICONMETRICSA);
1758 im_cur.cbSize = sizeof(ICONMETRICSA);
1760 trace("testing SPI_{GET,SET}ICONMETRICS\n");
1761 SetLastError(0xdeadbeef);
1762 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1763 if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1764 return;
1765 /* check some registry values */
1766 regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1767 ok( regval==im_orig.iHorzSpacing,
1768 "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1769 regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1770 ok( regval==im_orig.iVertSpacing,
1771 "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1772 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1773 if( regval != im_orig.iTitleWrap)
1774 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1775 ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1777 /* change everything without creating something invalid ( Win9x would ignore
1778 * an invalid font for instance) */
1779 im_cur = im_orig;
1780 im_cur.iHorzSpacing += 10;
1781 im_cur.iVertSpacing += 6;
1782 im_cur.iTitleWrap = !im_cur.iTitleWrap;
1783 im_cur.lfFont.lfHeight += 1;
1784 im_cur.lfFont.lfWidth += 2;
1785 im_cur.lfFont.lfEscapement = 1;
1786 im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1787 im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1788 im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1789 im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1790 im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1791 im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1792 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1793 im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1794 im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1795 im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ?
1796 DRAFT_QUALITY : DEFAULT_QUALITY;
1797 if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1798 strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1799 else
1800 strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1802 rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1803 if (!test_error_msg(rc,"SPI_SETICONMETRICS")) return;
1804 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1806 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1807 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1808 /* test GET <-> SETICONMETRICS */
1809 eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1810 eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1811 eq( im_new.iTitleWrap, im_cur.iTitleWrap, "iTitleWrap", "%d" );
1812 eq( im_new.lfFont.lfHeight, im_cur.lfFont.lfHeight, "lfHeight", "%d" );
1813 eq( im_new.lfFont.lfWidth, im_cur.lfFont.lfWidth, "lfWidth", "%d" );
1814 eq( im_new.lfFont.lfEscapement, im_cur.lfFont.lfEscapement, "lfEscapement", "%d" );
1815 eq( im_new.lfFont.lfWeight, im_cur.lfFont.lfWeight, "lfWeight", "%d" );
1816 eq( im_new.lfFont.lfItalic, im_cur.lfFont.lfItalic, "lfItalic", "%d" );
1817 eq( im_new.lfFont.lfStrikeOut, im_cur.lfFont.lfStrikeOut, "lfStrikeOut", "%d" );
1818 eq( im_new.lfFont.lfUnderline, im_cur.lfFont.lfUnderline, "lfUnderline", "%d" );
1819 eq( im_new.lfFont.lfCharSet, im_cur.lfFont.lfCharSet, "lfCharSet", "%d" );
1820 eq( im_new.lfFont.lfOutPrecision, im_cur.lfFont.lfOutPrecision, "lfOutPrecision", "%d" );
1821 eq( im_new.lfFont.lfClipPrecision, im_cur.lfFont.lfClipPrecision, "lfClipPrecision", "%d" );
1822 eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1823 eq( im_new.lfFont.lfQuality, im_cur.lfFont.lfQuality, "lfQuality", "%d" );
1824 ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1825 "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1826 im_cur.lfFont.lfFaceName);
1827 /* test some system metrics */
1828 eq( GetSystemMetrics( SM_CXICONSPACING ),
1829 im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1830 eq( GetSystemMetrics( SM_CYICONSPACING ),
1831 im_new.iVertSpacing, "iVertSpacing", "%d" );
1832 /* check some registry values */
1833 regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1834 ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1835 regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1836 ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1837 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1838 if( regval != im_cur.iTitleWrap)
1839 regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1840 ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1841 /* test some values from other SPI_GETxxx calls */
1842 rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1843 ok( rc && spacing == im_cur.iHorzSpacing,
1844 "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1845 spacing, im_cur.iHorzSpacing);
1846 rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1847 ok( rc && spacing == im_cur.iVertSpacing,
1848 "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1849 spacing, im_cur.iVertSpacing);
1850 rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1851 ok( rc && wrap == im_cur.iTitleWrap,
1852 "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1853 wrap, im_cur.iTitleWrap);
1854 /* restore old values */
1855 rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1856 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1858 rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1859 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1861 eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1862 eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1863 eq( im_new.iTitleWrap, im_orig.iTitleWrap, "iTitleWrap", "%d" );
1866 static void test_SPI_SETWORKAREA( void ) /* 47 */
1868 BOOL rc;
1869 RECT old_area;
1870 RECT area;
1871 RECT curr_val;
1873 trace("testing SPI_{GET,SET}WORKAREA\n");
1874 SetLastError(0xdeadbeef);
1875 rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1876 if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1877 return;
1879 /* Modify the work area only minimally as this causes the icons that
1880 * fall outside it to be moved around thus requiring the user to
1881 * reposition them manually one by one.
1882 * Changing the work area by just one pixel should make this occurrence
1883 * reasonably unlikely.
1885 SetRect(&curr_val, old_area.left, old_area.top, old_area.right - 1, old_area.bottom - 1);
1886 rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1887 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1888 if (!test_error_msg(rc,"SPI_SETWORKAREA")) return;
1889 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1890 rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1891 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1892 if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1893 test_change_message( SPI_SETWORKAREA, 0);
1894 eq( area.left, curr_val.left, "left", "%d" );
1895 eq( area.top, curr_val.top, "top", "%d" );
1896 /* size may be rounded */
1897 ok( area.right >= curr_val.right - 16 && area.right < curr_val.right + 16,
1898 "right: got %d instead of %d\n", area.right, curr_val.right );
1899 ok( area.bottom >= curr_val.bottom - 16 && area.bottom < curr_val.bottom + 16,
1900 "bottom: got %d instead of %d\n", area.bottom, curr_val.bottom );
1901 curr_val = area;
1902 rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1903 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1904 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1905 rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1906 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1907 if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1908 test_change_message( SPI_SETWORKAREA, 0 );
1909 eq( area.left, old_area.left, "left", "%d" );
1910 eq( area.top, old_area.top, "top", "%d" );
1911 /* size may be rounded */
1912 ok( area.right >= old_area.right - 16 && area.right < old_area.right + 16,
1913 "right: got %d instead of %d\n", area.right, old_area.right );
1914 ok( area.bottom >= old_area.bottom - 16 && area.bottom < old_area.bottom + 16,
1915 "bottom: got %d instead of %d\n", area.bottom, old_area.bottom );
1918 static void test_SPI_SETSHOWSOUNDS( void ) /* 57 */
1920 BOOL rc;
1921 BOOL old_b;
1922 const UINT vals[]={TRUE,FALSE};
1923 unsigned int i;
1925 trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1926 SetLastError(0xdeadbeef);
1927 rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1928 if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1929 return;
1931 for (i=0;i<ARRAY_SIZE(vals);i++)
1933 UINT v;
1935 rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1936 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1937 if (!test_error_msg(rc,"SPI_SETSHOWSOUNDS")) return;
1938 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1939 test_change_message( SPI_SETSHOWSOUNDS, 1 );
1940 test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1941 SPI_SETSHOWSOUNDS_VALNAME,
1942 vals[i] ? "1" : "0" );
1944 rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1945 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1946 eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1947 eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1948 "SM_SHOWSOUNDS", "%d" );
1951 rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1952 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1955 static void test_SPI_SETKEYBOARDPREF( void ) /* 69 */
1957 BOOL rc;
1958 BOOL old_b;
1959 const UINT vals[]={TRUE,FALSE};
1960 unsigned int i;
1962 trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1963 SetLastError(0xdeadbeef);
1964 rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1965 if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1966 return;
1968 for (i=0;i<ARRAY_SIZE(vals);i++)
1970 BOOL v;
1972 rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1973 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1974 if (!test_error_msg(rc,"SPI_SETKEYBOARDPREF")) return;
1975 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1976 test_change_message( SPI_SETKEYBOARDPREF, 1 );
1977 test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1978 SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1979 vals[i] ? "1" : "0" );
1981 rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1982 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1983 eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1986 rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1987 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1990 static void test_SPI_SETSCREENREADER( void ) /* 71 */
1992 BOOL rc;
1993 BOOL old_b;
1994 const UINT vals[]={TRUE,FALSE};
1995 unsigned int i;
1997 trace("testing SPI_{GET,SET}SCREENREADER\n");
1998 SetLastError(0xdeadbeef);
1999 rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
2000 if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
2001 return;
2003 for (i=0;i<ARRAY_SIZE(vals);i++)
2005 BOOL v;
2007 rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
2008 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2009 if (!test_error_msg(rc,"SPI_SETSCREENREADER")) return;
2010 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2011 test_change_message( SPI_SETSCREENREADER, 1 );
2012 test_reg_key_ex2_optional( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
2013 SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
2014 vals[i] ? "1" : "0" );
2016 rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
2017 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2018 eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
2021 rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
2022 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2025 static void test_SPI_SETFONTSMOOTHING( void ) /* 75 */
2027 BOOL rc;
2028 BOOL old_b;
2029 DWORD old_type, old_contrast, old_orient;
2030 const UINT vals[]={0xffffffff,0,1,2};
2031 unsigned int i;
2033 trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
2034 SetLastError(0xdeadbeef);
2035 rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
2036 if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
2037 return;
2038 SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &old_type, 0 );
2039 SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &old_contrast, 0 );
2040 SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &old_orient, 0 );
2042 for (i=0;i<ARRAY_SIZE(vals);i++)
2044 UINT v;
2046 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
2047 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2048 if (!test_error_msg(rc,"SPI_SETFONTSMOOTHING")) return;
2049 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2050 test_change_message( SPI_SETFONTSMOOTHING, 0 );
2051 test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
2052 SPI_SETFONTSMOOTHING_VALNAME,
2053 vals[i] ? "2" : "0" );
2055 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, 0, UlongToPtr(vals[i]),
2056 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2057 if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGTYPE")) return;
2058 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2059 test_change_message( SPI_SETFONTSMOOTHINGTYPE, 0 );
2060 test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2061 SPI_SETFONTSMOOTHINGTYPE_VALNAME, &vals[i] );
2063 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, 0, UlongToPtr(vals[i]),
2064 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2065 if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGCONTRAST")) return;
2066 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2067 test_change_message( SPI_SETFONTSMOOTHINGCONTRAST, 0 );
2068 test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2069 SPI_SETFONTSMOOTHINGCONTRAST_VALNAME, &vals[i] );
2071 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, 0, UlongToPtr(vals[i]),
2072 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2073 if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGORIENTATION")) return;
2074 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2075 test_change_message( SPI_SETFONTSMOOTHINGORIENTATION, 0 );
2076 test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2077 SPI_SETFONTSMOOTHINGORIENTATION_VALNAME, &vals[i] );
2079 rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
2080 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2081 eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
2083 rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &v, 0 );
2084 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2085 ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2087 rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &v, 0 );
2088 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2089 ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2091 rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &v, 0 );
2092 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2093 ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2096 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
2097 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2098 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, old_type, 0, SPIF_UPDATEINIFILE );
2099 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2100 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, old_contrast, 0, SPIF_UPDATEINIFILE );
2101 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2102 rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, old_orient, 0, SPIF_UPDATEINIFILE );
2103 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2106 static void test_SPI_SETLOWPOWERACTIVE( void ) /* 85 */
2108 BOOL rc;
2109 BOOL old_b;
2110 const UINT vals[]={TRUE,FALSE};
2111 unsigned int i;
2113 trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
2114 SetLastError(0xdeadbeef);
2115 rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
2116 if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
2117 return;
2119 for (i=0;i<ARRAY_SIZE(vals);i++)
2121 UINT v;
2123 rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
2124 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2125 if (!test_error_msg(rc,"SPI_SETLOWPOWERACTIVE")) return;
2126 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2127 test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
2128 test_reg_key_optional( SPI_SETLOWPOWERACTIVE_REGKEY,
2129 SPI_SETLOWPOWERACTIVE_VALNAME,
2130 vals[i] ? "1" : "0" );
2132 /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
2133 v = 0xdeadbeef;
2134 rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
2135 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2136 ok(v == vals[i] || v == 0, /* win2k3 */
2137 "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2140 rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2141 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2144 static void test_SPI_SETPOWEROFFACTIVE( void ) /* 86 */
2146 BOOL rc;
2147 BOOL old_b;
2148 const UINT vals[]={TRUE,FALSE};
2149 unsigned int i;
2151 trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
2152 SetLastError(0xdeadbeef);
2153 rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
2154 if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
2155 return;
2157 for (i=0;i<ARRAY_SIZE(vals);i++)
2159 UINT v;
2161 rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
2162 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2163 if (!test_error_msg(rc,"SPI_SETPOWEROFFACTIVE")) return;
2164 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2165 test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
2166 test_reg_key_optional( SPI_SETPOWEROFFACTIVE_REGKEY,
2167 SPI_SETPOWEROFFACTIVE_VALNAME,
2168 vals[i] ? "1" : "0" );
2170 /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
2171 v = 0xdeadbeef;
2172 rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
2173 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2174 ok(v == vals[i] || v == 0, /* win2k3 */
2175 "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2178 rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2179 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2182 static void test_SPI_SETSNAPTODEFBUTTON( void ) /* 95 */
2184 BOOL rc;
2185 BOOL old_b;
2186 const UINT vals[]={TRUE,FALSE};
2187 unsigned int i;
2189 trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
2190 SetLastError(0xdeadbeef);
2191 rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
2192 if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
2193 return;
2195 for (i=0;i<ARRAY_SIZE(vals);i++)
2197 UINT v;
2199 rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
2200 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2201 if (!test_error_msg(rc,"SPI_SETSNAPTODEFBUTTON")) return;
2202 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2203 test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
2204 test_reg_key_optional( SPI_SETSNAPTODEFBUTTON_REGKEY,
2205 SPI_SETSNAPTODEFBUTTON_VALNAME,
2206 vals[i] ? "1" : "0" );
2208 rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2209 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2210 eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2213 rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2214 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2217 static void test_SPI_SETMOUSEHOVERWIDTH( void ) /* 99 */
2219 BOOL rc;
2220 UINT old_width;
2221 const UINT vals[]={0,32767};
2222 unsigned int i;
2224 trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2225 SetLastError(0xdeadbeef);
2226 rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2227 if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2228 return;
2230 for (i=0;i<ARRAY_SIZE(vals);i++)
2232 UINT v;
2233 char buf[10];
2235 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2236 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2237 if (!test_error_msg(rc,"SPI_SETMOUSEHOVERWIDTH")) return;
2238 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2239 test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2240 sprintf( buf, "%d", vals[i] );
2241 test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
2242 SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
2244 SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2245 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2246 eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2249 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2250 SPIF_UPDATEINIFILE );
2251 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2254 static void test_SPI_SETMOUSEHOVERHEIGHT( void ) /* 101 */
2256 BOOL rc;
2257 UINT old_height;
2258 const UINT vals[]={0,32767};
2259 unsigned int i;
2261 trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2262 SetLastError(0xdeadbeef);
2263 rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2264 if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2265 return;
2267 for (i=0;i<ARRAY_SIZE(vals);i++)
2269 UINT v;
2270 char buf[10];
2272 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2273 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2274 if (!test_error_msg(rc,"SPI_SETMOUSEHOVERHEIGHT")) return;
2275 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2276 test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2277 sprintf( buf, "%d", vals[i] );
2278 test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2279 SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2281 SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2282 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2283 eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2286 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2287 SPIF_UPDATEINIFILE );
2288 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2291 static void test_SPI_SETMOUSEHOVERTIME( void ) /* 103 */
2293 BOOL rc;
2294 UINT old_time;
2296 /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2297 * defaulted to a value of 10 automatically.
2299 const UINT vals[]={10,32767};
2300 unsigned int i;
2302 trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2303 SetLastError(0xdeadbeef);
2304 rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2305 if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2306 return;
2308 for (i=0;i<ARRAY_SIZE(vals);i++)
2310 UINT v;
2311 char buf[10];
2313 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2314 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2315 if (!test_error_msg(rc,"SPI_SETMOUSEHOVERTIME")) return;
2316 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2317 test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2318 sprintf( buf, "%d", vals[i] );
2319 test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2320 SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2322 SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2323 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2324 eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2327 rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2328 SPIF_UPDATEINIFILE );
2329 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2332 static void test_SPI_SETWHEELSCROLLLINES( void ) /* 105 */
2334 BOOL rc;
2335 UINT old_lines;
2336 const UINT vals[]={0,32767};
2337 unsigned int i;
2339 trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2340 SetLastError(0xdeadbeef);
2341 rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2343 /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2344 if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2345 return;
2347 for (i=0;i<ARRAY_SIZE(vals);i++)
2349 UINT v;
2350 char buf[10];
2352 rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2353 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2354 if (!test_error_msg(rc,"SPI_SETWHEELSCROLLLINES")) return;
2355 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2356 test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2357 sprintf( buf, "%d", vals[i] );
2358 test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2359 SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2361 SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2362 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2363 eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2366 rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2367 SPIF_UPDATEINIFILE );
2368 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2371 static void test_SPI_SETMENUSHOWDELAY( void ) /* 107 */
2373 BOOL rc;
2374 UINT old_delay;
2375 const UINT vals[]={0,32767};
2376 unsigned int i;
2378 trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2379 SetLastError(0xdeadbeef);
2380 rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2382 /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2383 if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2384 return;
2386 for (i=0;i<ARRAY_SIZE(vals);i++)
2388 UINT v;
2389 char buf[10];
2391 rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2392 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2393 if (!test_error_msg(rc,"SPI_SETMENUSHOWDELAY")) return;
2394 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2395 test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2396 sprintf( buf, "%d", vals[i] );
2397 test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2398 SPI_SETMENUSHOWDELAY_VALNAME, buf );
2400 SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2401 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2402 eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2405 rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2406 SPIF_UPDATEINIFILE );
2407 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2410 static void test_SPI_SETWHEELSCROLLCHARS( void ) /* 108 */
2412 BOOL rc;
2413 UINT old_chars;
2414 const UINT vals[]={32767,0};
2415 unsigned int i;
2417 trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2418 SetLastError(0xdeadbeef);
2419 rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2421 /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2422 if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2423 return;
2425 for (i=0;i<ARRAY_SIZE(vals);i++)
2427 UINT v;
2428 char buf[10];
2430 rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2431 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2432 if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2433 test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2434 sprintf( buf, "%d", vals[i] );
2435 test_reg_key( SPI_SETMOUSESCROLLCHARS_REGKEY,
2436 SPI_SETMOUSESCROLLCHARS_VALNAME, buf );
2438 SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2439 ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2440 eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2443 rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2444 SPIF_UPDATEINIFILE );
2445 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2448 static void test_SPI_SETWALLPAPER( void ) /* 115 */
2450 BOOL rc;
2451 char oldval[260];
2452 char newval[260];
2454 trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2455 SetLastError(0xdeadbeef);
2456 rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2457 if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2458 return;
2460 strcpy(newval, "");
2461 rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2462 if (!test_error_msg(rc,"SPI_SETDESKWALLPAPER")) return;
2463 ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
2464 test_change_message(SPI_SETDESKWALLPAPER, 0);
2466 rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2467 ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2469 test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2472 static void test_WM_DISPLAYCHANGE(void)
2474 DEVMODEA mode, startmode;
2475 int start_bpp, last_set_bpp = 0;
2476 int test_bpps[] = {8, 16, 24, 32}, i;
2477 LONG change_ret;
2478 DWORD wait_ret;
2480 if (!pChangeDisplaySettingsExA)
2482 win_skip("ChangeDisplaySettingsExA is not available\n");
2483 return;
2486 displaychange_test_active = TRUE;
2488 memset(&startmode, 0, sizeof(startmode));
2489 startmode.dmSize = sizeof(startmode);
2490 EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &startmode);
2491 start_bpp = startmode.dmBitsPerPel;
2493 displaychange_sem = CreateSemaphoreW(NULL, 0, 1, NULL);
2495 for(i = 0; i < ARRAY_SIZE(test_bpps); i++) {
2496 last_bpp = -1;
2498 memset(&mode, 0, sizeof(mode));
2499 mode.dmSize = sizeof(mode);
2500 mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2501 mode.dmBitsPerPel = test_bpps[i];
2502 mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2503 mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2505 change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2506 displaychange_ok = TRUE;
2507 change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2508 /* Wait quite long for the message, screen setting changes can take some time */
2509 if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2510 wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2511 /* we may not get a notification if nothing changed */
2512 if (wait_ret == WAIT_TIMEOUT && !last_set_bpp && start_bpp == test_bpps[i])
2513 continue;
2514 ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2516 displaychange_ok = FALSE;
2518 if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2519 skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2520 ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despite mode change failure\n", last_bpp);
2521 continue;
2524 todo_wine_if(start_bpp != test_bpps[i]) {
2525 ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2527 last_set_bpp = test_bpps[i];
2530 if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2531 memset(&mode, 0, sizeof(mode));
2532 mode.dmSize = sizeof(mode);
2533 mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2534 mode.dmBitsPerPel = start_bpp;
2535 mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2536 mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2538 displaychange_ok = TRUE;
2539 change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2540 WaitForSingleObject(displaychange_sem, 10000);
2541 displaychange_ok = FALSE;
2542 CloseHandle(displaychange_sem);
2543 displaychange_sem = 0;
2546 displaychange_test_active = FALSE;
2550 * Registry entries for the system parameters.
2551 * Names are created by 'SET' flags names.
2552 * We assume that corresponding 'GET' entries use the same registry keys.
2554 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2556 test_SPI_SETBEEP(); /* 1 */
2557 test_SPI_SETMOUSE(); /* 4 */
2558 test_SPI_SETBORDER(); /* 6 */
2559 test_SPI_SETKEYBOARDSPEED(); /* 10 */
2560 test_SPI_ICONHORIZONTALSPACING(); /* 13 */
2561 test_SPI_SETSCREENSAVETIMEOUT(); /* 14 */
2562 test_SPI_SETSCREENSAVEACTIVE(); /* 17 */
2563 test_SPI_SETGRIDGRANULARITY(); /* 19 */
2564 test_SPI_SETKEYBOARDDELAY(); /* 23 */
2565 test_SPI_ICONVERTICALSPACING(); /* 24 */
2566 test_SPI_SETICONTITLEWRAP(); /* 26 */
2567 test_SPI_SETMENUDROPALIGNMENT(); /* 28 */
2568 test_SPI_SETDOUBLECLKWIDTH(); /* 29 */
2569 test_SPI_SETDOUBLECLKHEIGHT(); /* 30 */
2570 test_SPI_SETDOUBLECLICKTIME(); /* 32 */
2571 test_SPI_SETMOUSEBUTTONSWAP(); /* 33 */
2572 test_SPI_SETFASTTASKSWITCH(); /* 36 */
2573 test_SPI_SETDRAGFULLWINDOWS(); /* 37 */
2574 /* test_WM_DISPLAYCHANGE seems to be somewhat buggy on
2575 * some versions of Windows (Vista, Win2k8, Win7B) in that
2576 * not all metrics are properly restored. Problems are
2577 * SM_CXMAXTRACK, SM_CYMAXTRACK
2578 * Fortunately setting the Non-Client metrics like in
2579 * test_SPI_SETNONCLIENTMETRICS will correct this. That is why
2580 * we do the DISPLAY change now... */
2581 test_WM_DISPLAYCHANGE();
2582 test_SPI_SETNONCLIENTMETRICS(); /* 42 */
2583 test_SPI_SETMINIMIZEDMETRICS(); /* 44 */
2584 test_SPI_SETICONMETRICS(); /* 46 */
2585 test_SPI_SETWORKAREA(); /* 47 */
2586 test_SPI_SETSHOWSOUNDS(); /* 57 */
2587 test_SPI_SETKEYBOARDPREF(); /* 69 */
2588 test_SPI_SETSCREENREADER(); /* 71 */
2589 test_SPI_SETFONTSMOOTHING(); /* 75 */
2590 test_SPI_SETLOWPOWERACTIVE(); /* 85 */
2591 test_SPI_SETPOWEROFFACTIVE(); /* 86 */
2592 test_SPI_SETSNAPTODEFBUTTON(); /* 95 */
2593 test_SPI_SETMOUSEHOVERWIDTH(); /* 99 */
2594 test_SPI_SETMOUSEHOVERHEIGHT(); /* 101 */
2595 test_SPI_SETMOUSEHOVERTIME(); /* 103 */
2596 test_SPI_SETWHEELSCROLLLINES(); /* 105 */
2597 test_SPI_SETMENUSHOWDELAY(); /* 107 */
2598 test_SPI_SETWHEELSCROLLCHARS(); /* 108 */
2599 test_SPI_SETWALLPAPER(); /* 115 */
2602 SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2603 return 0;
2606 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2607 * icon metrics and minimized metrics.
2610 /* copied from wine's GdiGetCharDimensions, which is not available on most
2611 * windows versions */
2612 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2614 SIZE sz;
2615 static const CHAR alphabet[] = {
2616 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2617 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2618 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2620 if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2622 if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2624 if (height) *height = sz.cy;
2625 return (sz.cx / 26 + 1) / 2;
2628 /* get text metrics and/or "average" char width of the specified logfont
2629 * for the specified dc */
2630 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2632 HFONT hfont, hfontsav;
2633 TEXTMETRICA tm;
2634 if( !ptm) ptm = &tm;
2635 hfont = CreateFontIndirectA( plf);
2636 if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2637 ptm->tmHeight = -1;
2638 if( psz) *psz = 10;
2639 if( hfont) DeleteObject( hfont);
2640 return;
2642 GetTextMetricsA( hdc, ptm);
2643 if( psz)
2644 if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2645 *psz = 10;
2646 SelectObject( hdc, hfontsav);
2647 DeleteObject( hfont);
2650 static int gsm_error_ctr;
2652 #define ok_gsm( i, e)\
2654 int exp = (e);\
2655 int act = GetSystemMetrics( (i));\
2656 if( exp != act) gsm_error_ctr++;\
2657 ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2659 #define ok_gsm_2( i, e1, e2)\
2661 int exp1 = (e1);\
2662 int exp2 = (e2);\
2663 int act = GetSystemMetrics( (i));\
2664 if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2665 ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2667 #define ok_gsm_3( i, e1, e2, e3)\
2669 int exp1 = (e1);\
2670 int exp2 = (e2);\
2671 int exp3 = (e3);\
2672 int act = GetSystemMetrics( (i));\
2673 if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2674 ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2677 static INT CALLBACK enum_all_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
2679 return lstrcmpiA(elf->lfFaceName, (const char *)lparam);
2682 static BOOL is_font_enumerated(const char *name)
2684 HDC hdc = CreateCompatibleDC(0);
2685 BOOL ret = FALSE;
2687 if (!EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)name))
2688 ret = TRUE;
2690 DeleteDC(hdc);
2691 return ret;
2694 static int get_cursor_size( int size )
2696 /* only certain sizes are allowed for cursors */
2697 if (size >= 64) return 64;
2698 if (size >= 48) return 48;
2699 return 32;
2702 static void test_GetSystemMetrics( void)
2704 TEXTMETRICA tmMenuFont;
2705 UINT IconSpacing, IconVerticalSpacing;
2706 BOOL rc;
2708 HDC hdc = CreateICA( "Display", 0, 0, 0);
2709 UINT avcwCaption;
2710 INT CaptionWidthfromreg, smicon, broken_val;
2711 MINIMIZEDMETRICS minim;
2712 NONCLIENTMETRICSA ncm;
2713 SIZE screen;
2715 assert(sizeof(ncm) == 344);
2717 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2718 rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2719 ok(rc, "SystemParametersInfoA failed\n");
2721 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) - 1;
2722 rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2723 ok(!rc, "SystemParametersInfoA should fail\n");
2725 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) + 1;
2726 SetLastError(0xdeadbeef);
2727 rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2728 ok(!rc, "SystemParametersInfoA should fail\n");
2730 ncm.cbSize = sizeof(ncm); /* Vista added padding */
2731 SetLastError(0xdeadbeef);
2732 ncm.iPaddedBorderWidth = 0xcccc;
2733 rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2734 ok(rc || broken(!rc) /* before Vista */, "SystemParametersInfoA failed\n");
2735 if (rc) ok( ncm.iPaddedBorderWidth == 0, "wrong iPaddedBorderWidth %u\n", ncm.iPaddedBorderWidth );
2737 minim.cbSize = sizeof( minim);
2738 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2739 SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2740 rc = SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2741 if( !rc) {
2742 win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
2743 return;
2746 ok(is_font_enumerated(ncm.lfCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfCaptionFont.lfFaceName);
2747 ok(is_font_enumerated(ncm.lfSmCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfSmCaptionFont.lfFaceName);
2748 ok(is_font_enumerated(ncm.lfMenuFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMenuFont.lfFaceName);
2749 ok(is_font_enumerated(ncm.lfStatusFont.lfFaceName), "font %s should be enumerated\n", ncm.lfStatusFont.lfFaceName);
2750 ok(is_font_enumerated(ncm.lfMessageFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMessageFont.lfFaceName);
2752 /* CaptionWidth from the registry may have different value of iCaptionWidth
2753 * from the non client metrics (observed on WinXP) */
2754 CaptionWidthfromreg = metricfromreg(
2755 "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2756 get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2757 get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2758 /* FIXME: use icon metric */
2759 if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2760 IconVerticalSpacing = 0;
2761 if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2762 IconSpacing = 0;
2763 /* reset error counters */
2764 gsm_error_ctr = 0;
2766 /* the tests: */
2768 /* SM_CXSCREEN, cannot test these two */
2769 /* SM_CYSCREEN */
2770 ok_gsm( SM_CXVSCROLL, ncm.iScrollWidth);
2771 ok_gsm( SM_CYHSCROLL, ncm.iScrollWidth);
2772 ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2773 ok_gsm( SM_CXBORDER, 1);
2774 ok_gsm( SM_CYBORDER, 1);
2775 ok_gsm( SM_CXDLGFRAME, 3);
2776 ok_gsm( SM_CYDLGFRAME, 3);
2777 ok_gsm( SM_CYVTHUMB, ncm.iScrollHeight);
2778 ok_gsm( SM_CXHTHUMB, ncm.iScrollHeight);
2779 /* These don't depend on the Shell Icon Size registry value */
2780 ok_gsm( SM_CXICON, MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI ) );
2781 ok_gsm( SM_CYICON, MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI ) );
2782 ok_gsm( SM_CXCURSOR, get_cursor_size( MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI )));
2783 ok_gsm( SM_CYCURSOR, get_cursor_size( MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI )));
2784 ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2785 ok_gsm( SM_CXFULLSCREEN,
2786 GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2787 ok_gsm( SM_CYFULLSCREEN,
2788 GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2789 /* SM_CYKANJIWINDOW */
2790 /* SM_MOUSEPRESENT */
2791 ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2792 ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2793 /* SM_DEBUG */
2794 /* SM_SWAPBUTTON */
2795 /* SM_RESERVED1 */
2796 /* SM_RESERVED2 */
2797 /* SM_RESERVED3 */
2798 /* SM_RESERVED4 */
2799 ok_gsm( SM_CXMIN, 3 * max( CaptionWidthfromreg >= 0 ? CaptionWidthfromreg : ncm.iCaptionWidth, 8) +
2800 GetSystemMetrics( SM_CYSIZE) + 4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2801 ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2802 2 * GetSystemMetrics( SM_CYFRAME));
2803 ok_gsm_2( SM_CXSIZE,
2804 ncm.iCaptionWidth, /* classic/standard windows style */
2805 GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2807 ok_gsm( SM_CYSIZE, ncm.iCaptionHeight);
2808 ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2809 ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2810 ok_gsm( SM_CXMINTRACK, GetSystemMetrics( SM_CXMIN));
2811 ok_gsm( SM_CYMINTRACK, GetSystemMetrics( SM_CYMIN));
2812 /* SM_CXDOUBLECLK */
2813 /* SM_CYDOUBLECLK */
2814 if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2815 if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2816 /* SM_MENUDROPALIGNMENT */
2817 /* SM_PENWINDOWS */
2818 /* SM_DBCSENABLED */
2819 /* SM_CMOUSEBUTTONS */
2820 /* SM_SECURE */
2821 ok_gsm( SM_CXEDGE, 2);
2822 ok_gsm( SM_CYEDGE, 2);
2823 /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2824 ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + (short)minim.iHorzGap );
2825 ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + (short)minim.iVertGap );
2827 smicon = MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI );
2828 if (!pIsProcessDPIAware || pIsProcessDPIAware())
2829 smicon = max( min( smicon, CaptionWidthfromreg - 2), 4 ) & ~1;
2830 todo_wine_if( real_dpi == dpi && smicon != (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI) & ~1) )
2832 broken_val = (min( ncm.iCaptionHeight, CaptionWidthfromreg ) - 2) & ~1;
2833 broken_val = min( broken_val, 20 );
2835 if (smicon == 4)
2837 ok_gsm_2( SM_CXSMICON, smicon, 6 );
2838 ok_gsm_2( SM_CYSMICON, smicon, 6 );
2840 else if (smicon < broken_val)
2842 ok_gsm_2( SM_CXSMICON, smicon, broken_val );
2843 ok_gsm_2( SM_CYSMICON, smicon, broken_val );
2845 else
2847 ok_gsm( SM_CXSMICON, smicon );
2848 ok_gsm( SM_CYSMICON, smicon );
2852 ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2853 ok_gsm_3( SM_CXSMSIZE,
2854 ncm.iSmCaptionWidth, /* classic/standard windows style */
2855 GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2856 smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2857 does not change it */
2859 ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2860 ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2861 ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2862 /* SM_ARRANGE */
2863 ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2864 ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2865 screen.cx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
2866 screen.cy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
2867 if (!screen.cx || !screen.cy) /* not supported on NT4 */
2869 screen.cx = GetSystemMetrics( SM_CXSCREEN );
2870 screen.cy = GetSystemMetrics( SM_CYSCREEN );
2872 ok_gsm_3( SM_CXMAXTRACK, screen.cx + 4 + 2 * GetSystemMetrics(SM_CXFRAME),
2873 screen.cx - 4 + 2 * GetSystemMetrics(SM_CXFRAME), /* Vista */
2874 screen.cx + 2 * GetSystemMetrics(SM_CXFRAME)); /* Win8 */
2875 ok_gsm_3( SM_CYMAXTRACK, screen.cy + 4 + 2 * GetSystemMetrics(SM_CYFRAME),
2876 screen.cy - 4 + 2 * GetSystemMetrics(SM_CYFRAME), /* Vista */
2877 screen.cy + 2 * GetSystemMetrics(SM_CYFRAME)); /* Win8 */
2878 /* the next two cannot really be tested as they depend on (application)
2879 * toolbars */
2880 /* SM_CXMAXIMIZED */
2881 /* SM_CYMAXIMIZED */
2882 /* SM_NETWORK */
2883 /* */
2884 /* */
2885 /* */
2886 /* SM_CLEANBOOT */
2887 /* SM_CXDRAG */
2888 /* SM_CYDRAG */
2889 /* SM_SHOWSOUNDS */
2890 ok_gsm( SM_CXMENUCHECK,
2891 ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2892 ok_gsm( SM_CYMENUCHECK,
2893 ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2894 /* SM_SLOWMACHINE */
2895 /* SM_MIDEASTENABLED */
2896 /* SM_MOUSEWHEELPRESENT */
2897 /* SM_XVIRTUALSCREEN */
2898 /* SM_YVIRTUALSCREEN */
2899 /* SM_CXVIRTUALSCREEN */
2900 /* SM_CYVIRTUALSCREEN */
2901 /* SM_CMONITORS */
2902 /* SM_SAMEDISPLAYFORMAT */
2903 /* SM_IMMENABLED */
2904 /* SM_CXFOCUSBORDER */
2905 /* SM_CYFOCUSBORDER */
2906 /* SM_TABLETPC */
2907 /* SM_MEDIACENTER */
2908 /* SM_CMETRICS */
2909 /* end of tests */
2910 if( gsm_error_ctr ) { /* if any errors where found */
2911 trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2912 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2913 trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2914 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2915 trace( "Captionfontchar width %d MenuFont %d,%d CaptionWidth from registry: %d screen %d,%d\n",
2916 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidthfromreg, screen.cx, screen.cy);
2919 DeleteDC(hdc);
2922 static void compare_font( const LOGFONTW *lf1, const LOGFONTW *lf2, int dpi, int custom_dpi, int line )
2924 ok_(__FILE__,line)( lf1->lfHeight == MulDiv( lf2->lfHeight, dpi, custom_dpi ),
2925 "wrong lfHeight %d vs %d\n", lf1->lfHeight, lf2->lfHeight );
2926 ok_(__FILE__,line)( abs( lf1->lfWidth - MulDiv( lf2->lfWidth, dpi, custom_dpi )) <= 1,
2927 "wrong lfWidth %d vs %d\n", lf1->lfWidth, lf2->lfWidth );
2928 ok_(__FILE__,line)( !memcmp( &lf1->lfEscapement, &lf2->lfEscapement,
2929 offsetof( LOGFONTW, lfFaceName ) - offsetof( LOGFONTW, lfEscapement )),
2930 "font differs\n" );
2931 ok_(__FILE__,line)( !lstrcmpW( lf1->lfFaceName, lf2->lfFaceName ), "wrong face name %s vs %s\n",
2932 wine_dbgstr_w( lf1->lfFaceName ), wine_dbgstr_w( lf2->lfFaceName ));
2935 static void test_metrics_for_dpi( int custom_dpi )
2937 int i, val;
2938 NONCLIENTMETRICSW ncm1, ncm2;
2939 ICONMETRICSW im1, im2;
2940 LOGFONTW lf1, lf2;
2941 BOOL ret;
2943 if (!pSystemParametersInfoForDpi)
2945 win_skip( "custom dpi metrics not supported\n" );
2946 return;
2949 ncm1.cbSize = sizeof(ncm1);
2950 ret = SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof(ncm1), &ncm1, FALSE );
2951 ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
2952 ncm2.cbSize = sizeof(ncm2);
2953 ret = pSystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, sizeof(ncm2), &ncm2, FALSE, custom_dpi );
2954 ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
2956 for (i = 0; i < 92; i++)
2958 int ret1 = GetSystemMetrics( i );
2959 int ret2 = pGetSystemMetricsForDpi( i, custom_dpi );
2960 switch (i)
2962 case SM_CXVSCROLL:
2963 case SM_CYHSCROLL:
2964 case SM_CYVTHUMB:
2965 case SM_CXHTHUMB:
2966 case SM_CXICON:
2967 case SM_CYICON:
2968 case SM_CYVSCROLL:
2969 case SM_CXHSCROLL:
2970 case SM_CYSIZE:
2971 case SM_CXICONSPACING:
2972 case SM_CYICONSPACING:
2973 case SM_CXSMSIZE:
2974 case SM_CYSMSIZE:
2975 case SM_CYMENUSIZE:
2976 ok( ret1 == MulDiv( ret2, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2977 break;
2978 case SM_CXSIZE:
2979 ok( ret1 == ncm1.iCaptionWidth && ret2 == ncm2.iCaptionWidth,
2980 "%u: wrong value %u vs %u caption %u vs %u\n",
2981 i, ret1, ret2, ncm1.iCaptionWidth, ncm2.iCaptionWidth );
2982 break;
2983 case SM_CXCURSOR:
2984 case SM_CYCURSOR:
2985 val = MulDiv( 32, custom_dpi, USER_DEFAULT_SCREEN_DPI );
2986 if (val < 48) val = 32;
2987 else if (val < 64) val = 48;
2988 else val = 64;
2989 ok( val == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2990 break;
2991 case SM_CYCAPTION:
2992 case SM_CYSMCAPTION:
2993 case SM_CYMENU:
2994 ok( ret1 - 1 == MulDiv( ret2 - 1, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2995 break;
2996 case SM_CXMENUSIZE:
2997 ok( ret1 / 8 == MulDiv( ret2, dpi, custom_dpi ) / 8, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2998 break;
2999 case SM_CXFRAME:
3000 case SM_CYFRAME:
3001 ok( ret1 == ncm1.iBorderWidth + 3 && ret2 == ncm2.iBorderWidth + 3,
3002 "%u: wrong value %u vs %u borders %u+%u vs %u+%u\n", i, ret1, ret2,
3003 ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
3004 break;
3005 case SM_CXSMICON:
3006 case SM_CYSMICON:
3007 ok( ret1 == (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI ) & ~1) &&
3008 ret2 == (MulDiv( 16, custom_dpi, USER_DEFAULT_SCREEN_DPI ) & ~1),
3009 "%u: wrong value %u vs %u\n", i, ret1, ret2 );
3010 break;
3011 case SM_CXMENUCHECK:
3012 case SM_CYMENUCHECK:
3013 ok( ret1 == ((get_tmheightW( &ncm1.lfMenuFont, 1 ) - 1) | 1) &&
3014 ret2 == ((get_tmheightW( &ncm2.lfMenuFont, 1 ) - 1) | 1),
3015 "%u: wrong value %u vs %u font %u vs %u\n", i, ret1, ret2,
3016 get_tmheightW( &ncm1.lfMenuFont, 1 ), get_tmheightW( &ncm2.lfMenuFont, 1 ));
3017 break;
3018 default:
3019 ok( ret1 == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
3020 break;
3023 im1.cbSize = sizeof(im1);
3024 ret = SystemParametersInfoW( SPI_GETICONMETRICS, sizeof(im1), &im1, FALSE );
3025 ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
3026 im2.cbSize = sizeof(im2);
3027 ret = pSystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im2), &im2, FALSE, custom_dpi );
3028 ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
3029 ok( im1.iHorzSpacing == MulDiv( im2.iHorzSpacing, dpi, custom_dpi ), "wrong iHorzSpacing %u vs %u\n",
3030 im1.iHorzSpacing, im2.iHorzSpacing );
3031 ok( im1.iVertSpacing == MulDiv( im2.iVertSpacing, dpi, custom_dpi ), "wrong iVertSpacing %u vs %u\n",
3032 im1.iVertSpacing, im2.iVertSpacing );
3033 ok( im1.iTitleWrap == im2.iTitleWrap, "wrong iTitleWrap %u vs %u\n",
3034 im1.iTitleWrap, im2.iTitleWrap );
3035 compare_font( &im1.lfFont, &im2.lfFont, dpi, custom_dpi, __LINE__ );
3037 ret = SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf1), &lf1, FALSE );
3038 ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
3039 ret = pSystemParametersInfoForDpi( SPI_GETICONTITLELOGFONT, sizeof(lf2), &lf2, FALSE, custom_dpi );
3040 ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
3041 compare_font( &lf1, &lf2, dpi, custom_dpi, __LINE__ );
3043 /* on high-dpi iPaddedBorderWidth is used in addition to iBorderWidth */
3044 ok( ncm1.iBorderWidth + ncm1.iPaddedBorderWidth == MulDiv( ncm2.iBorderWidth + ncm2.iPaddedBorderWidth, dpi, custom_dpi ),
3045 "wrong iBorderWidth %u+%u vs %u+%u\n",
3046 ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
3047 ok( ncm1.iScrollWidth == MulDiv( ncm2.iScrollWidth, dpi, custom_dpi ),
3048 "wrong iScrollWidth %u vs %u\n", ncm1.iScrollWidth, ncm2.iScrollWidth );
3049 ok( ncm1.iScrollHeight == MulDiv( ncm2.iScrollHeight, dpi, custom_dpi ),
3050 "wrong iScrollHeight %u vs %u\n", ncm1.iScrollHeight, ncm2.iScrollHeight );
3051 ok( ((ncm1.iCaptionWidth + 1) & ~1) == ((MulDiv( ncm2.iCaptionWidth, dpi, custom_dpi ) + 1) & ~1),
3052 "wrong iCaptionWidth %u vs %u\n", ncm1.iCaptionWidth, ncm2.iCaptionWidth );
3053 ok( ncm1.iCaptionHeight == MulDiv( ncm2.iCaptionHeight, dpi, custom_dpi ),
3054 "wrong iCaptionHeight %u vs %u\n", ncm1.iCaptionHeight, ncm2.iCaptionHeight );
3055 compare_font( &ncm1.lfCaptionFont, &ncm2.lfCaptionFont, dpi, custom_dpi, __LINE__ );
3056 ok( ncm1.iSmCaptionHeight == MulDiv( ncm2.iSmCaptionHeight, dpi, custom_dpi ),
3057 "wrong iSmCaptionHeight %u vs %u\n", ncm1.iSmCaptionHeight, ncm2.iSmCaptionHeight );
3058 compare_font( &ncm1.lfSmCaptionFont, &ncm2.lfSmCaptionFont, dpi, custom_dpi, __LINE__ );
3059 ok( ncm1.iMenuHeight == MulDiv( ncm2.iMenuHeight, dpi, custom_dpi ),
3060 "wrong iMenuHeight %u vs %u\n", ncm1.iMenuHeight, ncm2.iMenuHeight );
3061 /* iSmCaptionWidth and iMenuWidth apparently need to be multiples of 8 */
3062 ok( ncm1.iSmCaptionWidth / 8 == MulDiv( ncm2.iSmCaptionWidth, dpi, custom_dpi ) / 8,
3063 "wrong iSmCaptionWidth %u vs %u\n", ncm1.iSmCaptionWidth, ncm2.iSmCaptionWidth );
3064 ok( ncm1.iMenuWidth / 8 == MulDiv( ncm2.iMenuWidth, dpi, custom_dpi ) / 8,
3065 "wrong iMenuWidth %u vs %u\n", ncm1.iMenuWidth, ncm2.iMenuWidth );
3066 compare_font( &ncm1.lfMenuFont, &ncm2.lfMenuFont, dpi, custom_dpi, __LINE__ );
3067 compare_font( &ncm1.lfStatusFont, &ncm2.lfStatusFont, dpi, custom_dpi, __LINE__ );
3068 compare_font( &ncm1.lfMessageFont, &ncm2.lfMessageFont, dpi, custom_dpi, __LINE__ );
3070 for (i = 1; i < 120; i++)
3072 if (i == SPI_GETICONTITLELOGFONT || i == SPI_GETNONCLIENTMETRICS || i == SPI_GETICONMETRICS)
3073 continue;
3074 SetLastError( 0xdeadbeef );
3075 ret = pSystemParametersInfoForDpi( i, 0, &val, 0, custom_dpi );
3076 ok( !ret, "%u: SystemParametersInfoForDpi succeeded\n", i );
3077 ok( GetLastError() == ERROR_INVALID_PARAMETER, "%u: wrong error %u\n", i, GetLastError() );
3081 static void test_EnumDisplaySettings(void)
3083 DEVMODEA devmode;
3084 DWORD val;
3085 HDC hdc;
3086 DWORD num;
3088 memset(&devmode, 0, sizeof(devmode));
3089 EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3091 hdc = GetDC(0);
3092 val = GetDeviceCaps(hdc, BITSPIXEL);
3093 ok(devmode.dmBitsPerPel == val,
3094 "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
3095 val, devmode.dmBitsPerPel);
3097 val = GetDeviceCaps(hdc, NUMCOLORS);
3098 if(devmode.dmBitsPerPel <= 8) {
3099 ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
3100 } else {
3101 ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
3104 ReleaseDC(0, hdc);
3106 num = 1;
3107 while (1) {
3108 SetLastError (0xdeadbeef);
3109 if (!EnumDisplaySettingsA(NULL, num, &devmode)) {
3110 DWORD le = GetLastError();
3111 ok(le == ERROR_NO_MORE_FILES ||
3112 le == ERROR_MOD_NOT_FOUND /* Win8 */ ||
3113 le == 0xdeadbeef, /* XP, 2003 */
3114 "Expected ERROR_NO_MORE_FILES, ERROR_MOD_NOT_FOUND or 0xdeadbeef, got %d for %d\n", le, num);
3115 break;
3117 num++;
3121 static void test_GetSysColorBrush(void)
3123 HBRUSH hbr;
3125 SetLastError(0xdeadbeef);
3126 hbr = GetSysColorBrush(-1);
3127 ok(hbr == NULL, "Expected NULL brush\n");
3128 ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
3129 /* greater than max index */
3130 hbr = GetSysColorBrush(COLOR_MENUBAR);
3131 if (hbr)
3133 SetLastError(0xdeadbeef);
3134 hbr = GetSysColorBrush(COLOR_MENUBAR + 1);
3135 ok(hbr == NULL, "Expected NULL brush\n");
3136 ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
3138 else
3139 win_skip("COLOR_MENUBAR unsupported\n");
3142 static void test_dpi_stock_objects( HDC hdc )
3144 DPI_AWARENESS_CONTEXT context;
3145 HGDIOBJ obj[STOCK_LAST + 1], obj2[STOCK_LAST + 1];
3146 LOGFONTW lf, lf2;
3147 UINT i, dpi;
3149 context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3150 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3151 ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3152 ok( !pIsProcessDPIAware(), "not aware\n" );
3153 for (i = 0; i <= STOCK_LAST; i++) obj[i] = GetStockObject( i );
3155 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3156 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3157 ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
3158 ok( pIsProcessDPIAware(), "not aware\n" );
3159 for (i = 0; i <= STOCK_LAST; i++) obj2[i] = GetStockObject( i );
3161 for (i = 0; i <= STOCK_LAST; i++)
3163 switch (i)
3165 case OEM_FIXED_FONT:
3166 case SYSTEM_FIXED_FONT:
3167 ok( obj[i] != obj2[i], "%u: same object\n", i );
3168 break;
3169 case SYSTEM_FONT:
3170 case DEFAULT_GUI_FONT:
3171 ok( obj[i] != obj2[i], "%u: same object\n", i );
3172 GetObjectW( obj[i], sizeof(lf), &lf );
3173 GetObjectW( obj2[i], sizeof(lf2), &lf2 );
3174 ok( lf.lfHeight == MulDiv( lf2.lfHeight, USER_DEFAULT_SCREEN_DPI, real_dpi ),
3175 "%u: wrong height %d / %d\n", i, lf.lfHeight, lf2.lfHeight );
3176 break;
3177 default:
3178 ok( obj[i] == obj2[i], "%u: different object\n", i );
3179 break;
3183 pSetThreadDpiAwarenessContext( context );
3186 static void scale_point_dpi( POINT *pt, UINT src_dpi, UINT target_dpi )
3188 pt->x = MulDiv( pt->x, target_dpi, src_dpi );
3189 pt->y = MulDiv( pt->y, target_dpi, src_dpi );
3192 static void scale_rect_dpi( RECT *rect, UINT src_dpi, UINT target_dpi )
3194 rect->left = MulDiv( rect->left, target_dpi, src_dpi );
3195 rect->top = MulDiv( rect->top, target_dpi, src_dpi );
3196 rect->right = MulDiv( rect->right, target_dpi, src_dpi );
3197 rect->bottom = MulDiv( rect->bottom, target_dpi, src_dpi );
3200 static void scale_point_dpi_aware( POINT *pt, DPI_AWARENESS from, DPI_AWARENESS to )
3202 if (from == DPI_AWARENESS_UNAWARE && to != DPI_AWARENESS_UNAWARE)
3203 scale_point_dpi( pt, USER_DEFAULT_SCREEN_DPI, real_dpi );
3204 else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
3205 scale_point_dpi( pt, real_dpi, USER_DEFAULT_SCREEN_DPI );
3208 static void scale_rect_dpi_aware( RECT *rect, DPI_AWARENESS from, DPI_AWARENESS to )
3210 if (from == DPI_AWARENESS_UNAWARE && to != DPI_AWARENESS_UNAWARE)
3211 scale_rect_dpi( rect, USER_DEFAULT_SCREEN_DPI, real_dpi );
3212 else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
3213 scale_rect_dpi( rect, real_dpi, USER_DEFAULT_SCREEN_DPI );
3216 static void test_dpi_mapping(void)
3218 HWND hwnd, child;
3219 HDC hdc;
3220 UINT win_dpi, units;
3221 POINT point;
3222 BOOL ret;
3223 HRGN rgn, update;
3224 RECT rect, orig, client, desktop, expect;
3225 ULONG_PTR i, j, k;
3226 WINDOWPLACEMENT wpl_orig, wpl;
3227 HMONITOR monitor;
3228 MONITORINFO mon_info;
3229 DPI_AWARENESS_CONTEXT context;
3231 if (!pLogicalToPhysicalPointForPerMonitorDPI)
3233 win_skip( "LogicalToPhysicalPointForPerMonitorDPI not supported\n" );
3234 return;
3236 context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3237 GetWindowRect( GetDesktopWindow(), &desktop );
3238 for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
3240 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3241 /* test desktop rect */
3242 GetWindowRect( GetDesktopWindow(), &rect );
3243 expect = desktop;
3244 if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
3245 ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
3246 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3247 SetRect( &rect, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ));
3248 ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
3249 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3250 SetRect( &rect, 0, 0, GetSystemMetrics( SM_CXVIRTUALSCREEN ), GetSystemMetrics( SM_CYVIRTUALSCREEN ));
3251 ok( EqualRect( &expect, &rect ), "%lu: wrong virt desktop rect %s expected %s\n",
3252 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3253 SetRect( &rect, 0, 0, 1, 1 );
3254 monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
3255 ok( monitor != 0, "failed to get monitor\n" );
3256 mon_info.cbSize = sizeof(mon_info);
3257 ok( GetMonitorInfoW( monitor, &mon_info ), "GetMonitorInfoExW failed\n" );
3258 ok( EqualRect( &expect, &mon_info.rcMonitor ), "%lu: wrong monitor rect %s expected %s\n",
3259 i, wine_dbgstr_rect(&mon_info.rcMonitor), wine_dbgstr_rect(&expect) );
3260 hdc = CreateDCA( "display", NULL, NULL, NULL );
3261 SetRect( &rect, 0, 0, GetDeviceCaps( hdc, HORZRES ), GetDeviceCaps( hdc, VERTRES ));
3262 ok( EqualRect( &expect, &rect ), "%lu: wrong caps desktop rect %s expected %s\n",
3263 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3264 SetRect( &rect, 0, 0, GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ));
3265 ok( EqualRect( &desktop, &rect ), "%lu: wrong caps virt desktop rect %s expected %s\n",
3266 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
3267 DeleteDC( hdc );
3268 /* test message window rect */
3269 hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_CHILD,
3270 10, 10, 20, 20, HWND_MESSAGE, 0, GetModuleHandleA(0), NULL );
3271 GetWindowRect( GetAncestor( hwnd, GA_PARENT ), &rect );
3272 SetRect( &expect, 0, 0, 100, 100 );
3273 if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
3274 ok( EqualRect( &expect, &rect ), "%lu: wrong message rect %s expected %s\n",
3275 i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3276 DestroyWindow( hwnd );
3278 for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
3280 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3281 hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3282 193, 177, 295, 303, 0, 0, GetModuleHandleA(0), NULL );
3283 ok( hwnd != 0, "creating window failed err %u\n", GetLastError());
3284 child = CreateWindowA( "SysParamsTestClass", "child", WS_CHILD | WS_VISIBLE,
3285 50, 60, 70, 80, hwnd, 0, GetModuleHandleA(0), NULL );
3286 ok( child != 0, "creating child failed err %u\n", GetLastError());
3287 GetWindowRect( hwnd, &orig );
3288 SetRect( &rect, 0, 0, 0, 0 );
3289 pAdjustWindowRectExForDpi( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0, pGetDpiForWindow( hwnd ));
3290 SetRect( &client, orig.left - rect.left, orig.top - rect.top,
3291 orig.right - rect.right, orig.bottom - rect.bottom );
3292 ShowWindow( hwnd, SW_MINIMIZE );
3293 ShowWindow( hwnd, SW_RESTORE );
3294 GetWindowPlacement( hwnd, &wpl_orig );
3295 units = GetDialogBaseUnits();
3297 for (j = DPI_AWARENESS_UNAWARE; j <= DPI_AWARENESS_PER_MONITOR_AWARE; j++)
3299 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3300 /* test window rect */
3301 GetWindowRect( hwnd, &rect );
3302 expect = orig;
3303 scale_rect_dpi_aware( &expect, i, j );
3304 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong window rect %s expected %s\n",
3305 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3306 /* test client rect */
3307 GetClientRect( hwnd, &rect );
3308 expect = client;
3309 OffsetRect( &expect, -expect.left, -expect.top );
3310 scale_rect_dpi_aware( &expect, i, j );
3311 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong client rect %s expected %s\n",
3312 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3313 /* test window placement */
3314 GetWindowPlacement( hwnd, &wpl );
3315 point = wpl_orig.ptMinPosition;
3316 if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
3317 ok( wpl.ptMinPosition.x == point.x && wpl.ptMinPosition.y == point.y,
3318 "%lu/%lu: wrong placement min pos %d,%d expected %d,%d\n", i, j,
3319 wpl.ptMinPosition.x, wpl.ptMinPosition.y, point.x, point.y );
3320 point = wpl_orig.ptMaxPosition;
3321 if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
3322 ok( wpl.ptMaxPosition.x == point.x && wpl.ptMaxPosition.y == point.y,
3323 "%lu/%lu: wrong placement max pos %d,%d expected %d,%d\n", i, j,
3324 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, point.x, point.y );
3325 expect = wpl_orig.rcNormalPosition;
3326 scale_rect_dpi_aware( &expect, i, j );
3327 ok( EqualRect( &wpl.rcNormalPosition, &expect ),
3328 "%lu/%lu: wrong placement rect %s expect %s\n", i, j,
3329 wine_dbgstr_rect(&wpl.rcNormalPosition), wine_dbgstr_rect(&expect));
3330 /* test DC rect */
3331 hdc = GetDC( hwnd );
3332 GetClipBox( hdc, &rect );
3333 SetRect( &expect, 0, 0, client.right - client.left, client.bottom - client.top );
3334 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box %s expected %s\n",
3335 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3336 /* test DC resolution */
3337 SetRect( &rect, 0, 0, GetDeviceCaps( hdc, HORZRES ), GetDeviceCaps( hdc, VERTRES ));
3338 expect = desktop;
3339 if (j == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
3340 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong DC resolution %s expected %s\n",
3341 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3342 SetRect( &rect, 0, 0, GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ));
3343 ok( EqualRect( &desktop, &rect ), "%lu/%lu: wrong desktop resolution %s expected %s\n",
3344 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
3345 ReleaseDC( hwnd, hdc );
3346 /* test DC win rect */
3347 hdc = GetWindowDC( hwnd );
3348 GetClipBox( hdc, &rect );
3349 SetRect( &expect, 0, 0, 295, 303 );
3350 todo_wine
3351 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box win DC %s expected %s\n",
3352 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3353 ReleaseDC( hwnd, hdc );
3354 /* test window invalidation */
3355 UpdateWindow( hwnd );
3356 update = CreateRectRgn( 0, 0, 0, 0 );
3357 ret = GetUpdateRgn( hwnd, update, FALSE );
3358 ok( ret == NULLREGION, "update region not empty\n" );
3359 rgn = CreateRectRgn( 20, 20, 25, 25 );
3360 for (k = DPI_AWARENESS_UNAWARE; k <= DPI_AWARENESS_PER_MONITOR_AWARE; k++)
3362 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
3363 RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
3364 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3365 GetUpdateRgn( hwnd, update, FALSE );
3366 GetRgnBox( update, &rect );
3367 SetRect( &expect, 20, 20, 25, 25 );
3368 ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
3369 i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3370 GetUpdateRect( hwnd, &rect, FALSE );
3371 scale_rect_dpi_aware( &expect, i, j );
3372 ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
3373 i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3374 UpdateWindow( hwnd );
3376 for (k = DPI_AWARENESS_UNAWARE; k <= DPI_AWARENESS_PER_MONITOR_AWARE; k++)
3378 RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
3379 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
3380 GetUpdateRgn( hwnd, update, FALSE );
3381 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3382 GetRgnBox( update, &rect );
3383 SetRect( &expect, 20, 20, 25, 25 );
3384 ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
3385 i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3386 GetUpdateRect( hwnd, &rect, FALSE );
3387 scale_rect_dpi_aware( &expect, i, j );
3388 ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
3389 i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3390 UpdateWindow( hwnd );
3392 /* test desktop window invalidation */
3393 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3394 GetClientRect( hwnd, &rect );
3395 InflateRect( &rect, -50, -50 );
3396 expect = rect;
3397 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
3398 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3399 RedrawWindow( 0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN );
3400 GetUpdateRgn( hwnd, update, TRUE );
3401 GetRgnBox( update, &rect );
3402 if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
3403 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update region %s expected %s\n",
3404 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3405 GetUpdateRect( hwnd, &rect, FALSE );
3406 scale_rect_dpi_aware( &expect, i, j );
3407 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update rect %s expected %s\n",
3408 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3409 UpdateWindow( hwnd );
3410 DeleteObject( update );
3411 /* test dialog units */
3412 ret = GetDialogBaseUnits();
3413 point.x = LOWORD( units );
3414 point.y = HIWORD( units );
3415 scale_point_dpi_aware( &point, i, j );
3416 ok( LOWORD(ret) == point.x && HIWORD(ret) == point.y, "%lu/%lu: wrong units %d,%d / %d,%d\n",
3417 i, j, LOWORD(ret), HIWORD(ret), point.x, point.y );
3418 /* test window points mapping */
3419 SetRect( &rect, 0, 0, 100, 100 );
3420 rect.right = rect.left + 100;
3421 rect.bottom = rect.top + 100;
3422 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
3423 expect = client;
3424 scale_rect_dpi_aware( &expect, i, j );
3425 expect.right = expect.left + 100;
3426 expect.bottom = expect.top + 100;
3427 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints rect %s expected %s\n",
3428 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3429 SetRect( &rect, 50, 60, 70, 80 );
3430 scale_rect_dpi_aware( &rect, i, j );
3431 SetRect( &expect, 40, 30, 60, 80 );
3432 OffsetRect( &expect, -rect.left, -rect.top );
3433 SetRect( &rect, 40, 30, 60, 80 );
3434 MapWindowPoints( hwnd, child, (POINT *)&rect, 2 );
3435 ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints child rect %s expected %s\n",
3436 i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
3437 /* test logical<->physical coords mapping */
3438 win_dpi = pGetDpiForWindow( hwnd );
3439 if (i == DPI_AWARENESS_UNAWARE)
3440 ok( win_dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", win_dpi );
3441 else if (i == DPI_AWARENESS_SYSTEM_AWARE)
3442 ok( win_dpi == real_dpi, "wrong dpi %u / %u\n", win_dpi, real_dpi );
3443 point.x = 373;
3444 point.y = 377;
3445 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3446 ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3447 ok( point.x == MulDiv( 373, real_dpi, win_dpi ) &&
3448 point.y == MulDiv( 377, real_dpi, win_dpi ),
3449 "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
3450 point.x = 405;
3451 point.y = 423;
3452 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3453 ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3454 ok( point.x == MulDiv( 405, win_dpi, real_dpi ) &&
3455 point.y == MulDiv( 423, win_dpi, real_dpi ),
3456 "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
3457 /* point outside the window fails, but note that Windows (wrongly) checks against the
3458 * window rect transformed relative to the thread's awareness */
3459 GetWindowRect( hwnd, &rect );
3460 point.x = rect.left - 1;
3461 point.y = rect.top;
3462 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3463 ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3464 point.x++;
3465 point.y--;
3466 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3467 ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3468 point.y++;
3469 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3470 ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3471 point.x = rect.right;
3472 point.y = rect.bottom + 1;
3473 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3474 ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3475 point.x++;
3476 point.y--;
3477 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3478 ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3479 point.x--;
3480 ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3481 ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3482 /* get physical window rect */
3483 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3484 GetWindowRect( hwnd, &rect );
3485 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3486 point.x = rect.left - 1;
3487 point.y = rect.top;
3488 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3489 ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3490 point.x++;
3491 point.y--;
3492 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3493 ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3494 point.y++;
3495 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3496 ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3497 point.x = rect.right;
3498 point.y = rect.bottom + 1;
3499 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3500 ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3501 point.x++;
3502 point.y--;
3503 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3504 ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3505 point.x--;
3506 ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3507 ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3509 DestroyWindow( hwnd );
3511 pSetThreadDpiAwarenessContext( context );
3514 static void test_dpi_aware(void)
3516 BOOL ret;
3518 if (!pIsProcessDPIAware)
3520 win_skip("IsProcessDPIAware not available\n");
3521 return;
3524 ret = pSetProcessDPIAware();
3525 ok(ret, "got %d\n", ret);
3527 ret = pIsProcessDPIAware();
3528 ok(ret, "got %d\n", ret);
3530 dpi = real_dpi;
3531 test_GetSystemMetrics();
3532 test_metrics_for_dpi( 96 );
3533 test_metrics_for_dpi( 192 );
3536 static void test_dpi_context(void)
3538 DPI_AWARENESS awareness;
3539 DPI_AWARENESS_CONTEXT context;
3540 ULONG_PTR i, flags;
3541 BOOL ret;
3542 UINT dpi;
3543 HDC hdc = GetDC( 0 );
3545 context = pGetThreadDpiAwarenessContext();
3546 /* Windows 10 >= 1709 adds extra 0x6000 flags */
3547 flags = (ULONG_PTR)context & 0x6000;
3548 todo_wine
3549 ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
3550 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3551 todo_wine
3552 ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
3553 todo_wine
3554 ok( !pIsProcessDPIAware(), "already aware\n" );
3555 dpi = pGetDpiForSystem();
3556 todo_wine_if (real_dpi != USER_DEFAULT_SCREEN_DPI)
3557 ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3558 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3559 todo_wine_if (real_dpi != USER_DEFAULT_SCREEN_DPI)
3560 ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3561 SetLastError( 0xdeadbeef );
3562 ret = pSetProcessDpiAwarenessContext( NULL );
3563 ok( !ret, "got %d\n", ret );
3564 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3565 SetLastError( 0xdeadbeef );
3566 ret = pSetProcessDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)-6 );
3567 ok( !ret, "got %d\n", ret );
3568 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3569 ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3570 todo_wine
3571 ok( ret, "got %d\n", ret );
3572 ok( pIsProcessDPIAware(), "not aware\n" );
3573 real_dpi = pGetDpiForSystem();
3574 SetLastError( 0xdeadbeef );
3575 ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3576 ok( !ret, "got %d\n", ret );
3577 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
3578 SetLastError( 0xdeadbeef );
3579 ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3580 ok( !ret, "got %d\n", ret );
3581 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
3583 ret = pSetProcessDpiAwarenessInternal( DPI_AWARENESS_INVALID );
3584 ok( !ret, "got %d\n", ret );
3585 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3586 ret = pSetProcessDpiAwarenessInternal( DPI_AWARENESS_UNAWARE );
3587 ok( !ret, "got %d\n", ret );
3588 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
3589 ret = pGetProcessDpiAwarenessInternal( 0, &awareness );
3590 ok( ret, "got %d\n", ret );
3591 todo_wine
3592 ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong value %d\n", awareness );
3593 ret = pGetProcessDpiAwarenessInternal( GetCurrentProcess(), &awareness );
3594 ok( ret, "got %d\n", ret );
3595 todo_wine
3596 ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong value %d\n", awareness );
3597 ret = pGetProcessDpiAwarenessInternal( (HANDLE)0xdeadbeef, &awareness );
3598 ok( ret, "got %d\n", ret );
3599 ok( awareness == DPI_AWARENESS_UNAWARE, "wrong value %d\n", awareness );
3601 ret = pIsProcessDPIAware();
3602 ok(ret, "got %d\n", ret);
3603 context = pGetThreadDpiAwarenessContext();
3604 todo_wine
3605 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3606 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3607 todo_wine
3608 ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong awareness %u\n", awareness );
3609 SetLastError( 0xdeadbeef );
3610 context = pSetThreadDpiAwarenessContext( 0 );
3611 ok( !context, "got %p\n", context );
3612 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3613 SetLastError( 0xdeadbeef );
3614 context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)-6 );
3615 ok( !context, "got %p\n", context );
3616 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3617 context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3618 todo_wine
3619 ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
3620 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3621 todo_wine
3622 ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong awareness %u\n", awareness );
3623 dpi = pGetDpiForSystem();
3624 ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3625 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3626 ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3627 ok( !pIsProcessDPIAware(), "still aware\n" );
3628 context = pGetThreadDpiAwarenessContext();
3629 ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
3630 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3631 ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
3632 context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3633 ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
3634 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3635 ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
3636 dpi = pGetDpiForSystem();
3637 ok( dpi == real_dpi, "wrong dpi %u/%u\n", dpi, real_dpi );
3638 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3639 ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
3640 context = pGetThreadDpiAwarenessContext();
3641 ok( context == (DPI_AWARENESS_CONTEXT)0x12, "wrong context %p\n", context );
3642 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3643 ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
3644 context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3645 ok( context == (DPI_AWARENESS_CONTEXT)0x12, "wrong context %p\n", context );
3646 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3647 ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
3648 dpi = pGetDpiForSystem();
3649 ok( dpi == real_dpi, "wrong dpi %u/%u\n", dpi, real_dpi );
3650 dpi = GetDeviceCaps( hdc, LOGPIXELSX );
3651 ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
3652 ok( pIsProcessDPIAware(), "not aware\n" );
3653 context = pGetThreadDpiAwarenessContext();
3654 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3655 context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(0x80000010 | flags) );
3656 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3657 context = pGetThreadDpiAwarenessContext();
3658 todo_wine
3659 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3660 context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(0x80000011 | flags) );
3661 todo_wine
3662 ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
3663 context = pGetThreadDpiAwarenessContext();
3664 todo_wine
3665 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3666 context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)0x12 );
3667 todo_wine
3668 ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
3669 context = pSetThreadDpiAwarenessContext( context );
3670 ok( context == (DPI_AWARENESS_CONTEXT)(0x12), "wrong context %p\n", context );
3671 context = pGetThreadDpiAwarenessContext();
3672 todo_wine
3673 ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
3674 for (i = 0; i < 0x100; i++)
3676 awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i );
3677 switch (i)
3679 case 0x10:
3680 case 0x11:
3681 case 0x12:
3682 ok( awareness == (i & ~0x10), "%lx: wrong value %u\n", i, awareness );
3683 ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i ), "%lx: not valid\n", i );
3684 break;
3685 default:
3686 ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", i, awareness );
3687 ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i ), "%lx: valid\n", i );
3688 break;
3690 awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) );
3691 switch (i)
3693 case 0x10:
3694 case 0x11:
3695 case 0x12:
3696 ok( awareness == (i & ~0x10), "%lx: wrong value %u\n", i | 0x80000000, awareness );
3697 ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) ),
3698 "%lx: not valid\n", i | 0x80000000 );
3699 break;
3700 default:
3701 ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", i | 0x80000000, awareness );
3702 ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) ),
3703 "%lx: valid\n", i | 0x80000000 );
3704 break;
3706 awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3707 switch (~i)
3709 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
3710 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
3711 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
3712 ok( awareness == i, "%lx: wrong value %u\n", ~i, awareness );
3713 ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ), "%lx: not valid\n", ~i );
3714 break;
3715 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
3716 if (pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ))
3717 ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "%lx: wrong value %u\n", ~i, awareness );
3718 else
3719 ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
3720 break;
3721 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED:
3722 if (pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ))
3723 ok( awareness == DPI_AWARENESS_UNAWARE, "%lx: wrong value %u\n", ~i, awareness );
3724 else
3725 ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
3726 break;
3727 default:
3728 ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
3729 ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ), "%lx: valid\n", ~i );
3730 break;
3733 if (real_dpi != USER_DEFAULT_SCREEN_DPI) test_dpi_stock_objects( hdc );
3734 ReleaseDC( 0, hdc );
3737 static LRESULT CALLBACK dpi_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
3739 DPI_AWARENESS_CONTEXT ctx = pGetWindowDpiAwarenessContext( hwnd );
3740 DPI_AWARENESS_CONTEXT ctx2 = pGetThreadDpiAwarenessContext();
3741 DWORD pos, pos2;
3743 ok( pGetAwarenessFromDpiAwarenessContext( ctx ) == pGetAwarenessFromDpiAwarenessContext( ctx2 ),
3744 "msg %04x wrong awareness %p / %p\n", msg, ctx, ctx2 );
3745 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3746 pos = GetMessagePos();
3747 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3748 pos2 = GetMessagePos();
3749 ok( pos == pos2, "wrong pos %08x / %08x\n", pos, pos2 );
3750 pSetThreadDpiAwarenessContext( ctx2 );
3751 return DefWindowProcA( hwnd, msg, wp, lp );
3754 static void test_dpi_window(void)
3756 DPI_AWARENESS_CONTEXT context, orig;
3757 DPI_AWARENESS awareness;
3758 ULONG_PTR i, j;
3759 UINT dpi;
3760 HWND hwnd, child, ret;
3761 MSG msg = { 0, WM_USER + 1, 0, 0 };
3763 if (!pGetWindowDpiAwarenessContext)
3765 win_skip( "GetWindowDpiAwarenessContext not supported\n" );
3766 return;
3768 orig = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3769 for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
3771 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3772 hwnd = CreateWindowA( "DpiTestClass", "Test",
3773 WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
3774 ok( hwnd != 0, "failed to create window\n" );
3775 context = pGetWindowDpiAwarenessContext( hwnd );
3776 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3777 ok( awareness == i, "%lu: wrong awareness %u\n", i, awareness );
3778 dpi = pGetDpiForWindow( hwnd );
3779 ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3780 "%lu: got %u / %u\n", i, dpi, real_dpi );
3781 if (pGetDpiForMonitorInternal)
3783 BOOL res;
3784 SetLastError( 0xdeadbeef );
3785 res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 0, &dpi, NULL );
3786 ok( !res, "succeeded\n" );
3787 ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
3788 SetLastError( 0xdeadbeef );
3789 res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 3, &dpi, &dpi );
3790 ok( !res, "succeeded\n" );
3791 ok( GetLastError() == ERROR_BAD_ARGUMENTS, "wrong error %u\n", GetLastError() );
3792 SetLastError( 0xdeadbeef );
3793 res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 3, &dpi, NULL );
3794 ok( !res, "succeeded\n" );
3795 ok( GetLastError() == ERROR_BAD_ARGUMENTS, "wrong error %u\n", GetLastError() );
3796 res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 0, &dpi, &dpi );
3797 ok( res, "failed err %u\n", GetLastError() );
3798 ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3799 "%lu: got %u / %u\n", i, dpi, real_dpi );
3801 msg.hwnd = hwnd;
3802 for (j = DPI_AWARENESS_UNAWARE; j <= DPI_AWARENESS_PER_MONITOR_AWARE; j++)
3804 pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3805 SendMessageA( hwnd, WM_USER, 0, 0 );
3806 DispatchMessageA( &msg );
3807 CallWindowProcA( dpi_winproc, hwnd, WM_USER + 2, 0, 0 );
3808 child = CreateWindowA( "DpiTestClass", "Test",
3809 WS_CHILD, 0, 0, 100, 100, hwnd, 0, GetModuleHandleA(0), NULL );
3810 context = pGetWindowDpiAwarenessContext( child );
3811 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3812 ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
3813 dpi = pGetDpiForWindow( child );
3814 ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3815 "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
3816 ret = SetParent( child, NULL );
3817 ok( ret != 0, "SetParent failed err %u\n", GetLastError() );
3818 context = pGetWindowDpiAwarenessContext( child );
3819 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3820 ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
3821 dpi = pGetDpiForWindow( child );
3822 ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3823 "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
3824 DestroyWindow( child );
3825 child = CreateWindowA( "DpiTestClass", "Test",
3826 WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
3827 context = pGetWindowDpiAwarenessContext( child );
3828 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3829 ok( awareness == j, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
3830 dpi = pGetDpiForWindow( child );
3831 ok( dpi == (j == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3832 "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
3833 ret = SetParent( child, hwnd );
3834 ok( ret != 0 || GetLastError() == ERROR_INVALID_STATE,
3835 "SetParent failed err %u\n", GetLastError() );
3836 context = pGetWindowDpiAwarenessContext( child );
3837 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3838 ok( awareness == (ret ? i : j), "%lu/%lu: wrong awareness %u\n", i, j, awareness );
3839 dpi = pGetDpiForWindow( child );
3840 ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
3841 "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
3842 DestroyWindow( child );
3844 DestroyWindow( hwnd );
3847 SetLastError( 0xdeadbeef );
3848 context = pGetWindowDpiAwarenessContext( (HWND)0xdeadbeef );
3849 ok( !context, "got %p\n", context );
3850 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
3851 SetLastError( 0xdeadbeef );
3852 dpi = pGetDpiForWindow( (HWND)0xdeadbeef );
3853 ok( !dpi, "got %u\n", dpi );
3854 ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
3855 "wrong error %u\n", GetLastError() );
3857 SetLastError( 0xdeadbeef );
3858 context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
3859 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3860 ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
3861 dpi = pGetDpiForWindow( GetDesktopWindow() );
3862 ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
3864 pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3865 SetLastError( 0xdeadbeef );
3866 context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
3867 awareness = pGetAwarenessFromDpiAwarenessContext( context );
3868 ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
3869 dpi = pGetDpiForWindow( GetDesktopWindow() );
3870 ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
3872 pSetThreadDpiAwarenessContext( orig );
3875 static void test_GetAutoRotationState(void)
3877 AR_STATE state;
3878 BOOL ret;
3880 if (!pGetAutoRotationState)
3882 win_skip("GetAutoRotationState not supported\n");
3883 return;
3886 SetLastError(0xdeadbeef);
3887 ret = pGetAutoRotationState(NULL);
3888 ok(!ret, "Expected GetAutoRotationState to fail\n");
3889 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3891 state = 0;
3892 ret = pGetAutoRotationState(&state);
3893 ok(ret, "Expected GetAutoRotationState to succeed, error %d\n", GetLastError());
3896 START_TEST(sysparams)
3898 int argc;
3899 char** argv;
3900 WNDCLASSA wc;
3901 MSG msg;
3902 HDC hdc;
3903 HANDLE hThread;
3904 DWORD dwThreadId;
3905 HANDLE hInstance, hdll;
3907 hdll = GetModuleHandleA("user32.dll");
3908 pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
3909 pIsProcessDPIAware = (void*)GetProcAddress(hdll, "IsProcessDPIAware");
3910 pSetProcessDPIAware = (void*)GetProcAddress(hdll, "SetProcessDPIAware");
3911 pGetDpiForSystem = (void*)GetProcAddress(hdll, "GetDpiForSystem");
3912 pGetDpiForWindow = (void*)GetProcAddress(hdll, "GetDpiForWindow");
3913 pGetDpiForMonitorInternal = (void*)GetProcAddress(hdll, "GetDpiForMonitorInternal");
3914 pSetProcessDpiAwarenessContext = (void*)GetProcAddress(hdll, "SetProcessDpiAwarenessContext");
3915 pGetProcessDpiAwarenessInternal = (void*)GetProcAddress(hdll, "GetProcessDpiAwarenessInternal");
3916 pSetProcessDpiAwarenessInternal = (void*)GetProcAddress(hdll, "SetProcessDpiAwarenessInternal");
3917 pGetThreadDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetThreadDpiAwarenessContext");
3918 pSetThreadDpiAwarenessContext = (void*)GetProcAddress(hdll, "SetThreadDpiAwarenessContext");
3919 pGetWindowDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetWindowDpiAwarenessContext");
3920 pGetAwarenessFromDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetAwarenessFromDpiAwarenessContext");
3921 pIsValidDpiAwarenessContext = (void*)GetProcAddress(hdll, "IsValidDpiAwarenessContext");
3922 pGetSystemMetricsForDpi = (void*)GetProcAddress(hdll, "GetSystemMetricsForDpi");
3923 pSystemParametersInfoForDpi = (void*)GetProcAddress(hdll, "SystemParametersInfoForDpi");
3924 pAdjustWindowRectExForDpi = (void*)GetProcAddress(hdll, "AdjustWindowRectExForDpi");
3925 pLogicalToPhysicalPointForPerMonitorDPI = (void*)GetProcAddress(hdll, "LogicalToPhysicalPointForPerMonitorDPI");
3926 pPhysicalToLogicalPointForPerMonitorDPI = (void*)GetProcAddress(hdll, "PhysicalToLogicalPointForPerMonitorDPI");
3927 pGetAutoRotationState = (void*)GetProcAddress(hdll, "GetAutoRotationState");
3929 hInstance = GetModuleHandleA( NULL );
3930 hdc = GetDC(0);
3931 dpi = GetDeviceCaps( hdc, LOGPIXELSY);
3932 real_dpi = get_real_dpi();
3933 trace("dpi %d real_dpi %d\n", dpi, real_dpi);
3934 ReleaseDC( 0, hdc);
3936 /* This test requires interactivity, if we don't have it, give up */
3937 if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
3938 GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
3940 argc = winetest_get_mainargs(&argv);
3941 strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
3942 trace("strict=%d\n",strict);
3944 trace("testing GetSystemMetrics with your current desktop settings\n");
3945 test_GetSystemMetrics( );
3946 test_metrics_for_dpi( 192 );
3947 test_EnumDisplaySettings( );
3948 test_GetSysColorBrush( );
3949 test_GetAutoRotationState( );
3951 change_counter = 0;
3952 change_last_param = 0;
3954 wc.lpszClassName = "SysParamsTestClass";
3955 wc.lpfnWndProc = SysParamsTestWndProc;
3956 wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
3957 wc.hInstance = hInstance;
3958 wc.hIcon = LoadIconA( 0, (LPCSTR)IDI_APPLICATION );
3959 wc.hCursor = LoadCursorA( 0, (LPCSTR)IDC_ARROW );
3960 wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
3961 wc.lpszMenuName = 0;
3962 wc.cbClsExtra = 0;
3963 wc.cbWndExtra = 0;
3964 RegisterClassA( &wc );
3965 wc.lpszClassName = "DpiTestClass";
3966 wc.lpfnWndProc = dpi_winproc;
3967 RegisterClassA( &wc );
3969 ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
3970 WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
3972 hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
3973 assert( hThread );
3974 CloseHandle( hThread );
3976 while( GetMessageA( &msg, 0, 0, 0 )) {
3977 TranslateMessage( &msg );
3978 DispatchMessageA( &msg );
3981 if (pSetThreadDpiAwarenessContext)
3983 test_dpi_context();
3984 test_dpi_mapping();
3985 test_dpi_window();
3987 else win_skip( "SetThreadDpiAwarenessContext not supported\n" );
3989 test_dpi_aware();