ReactOS  0.4.14-dev-608-gd495a4f
sysparams.c
Go to the documentation of this file.
1 /* Unit test suite for functions SystemParametersInfo and GetSystemMetrics.
2  *
3  * Copyright 2002 Andriy Palamarchuk
4  *
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.
9  *
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.
14  *
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
18  */
19 
20 #ifndef __REACTOS__
21 #define _WIN32_WINNT 0x0600 /* For SPI_GETMOUSEHOVERWIDTH and more */
22 #define _WIN32_IE 0x0700
23 #define WINVER 0x0600 /* For COLOR_MENUBAR, NONCLIENTMETRICS with padding */
24 #endif
25 
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 
31 #include "wine/test.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wingdi.h"
35 #include "winreg.h"
36 #include "winuser.h"
37 #include "winnls.h"
38 
39 #ifndef SPI_GETDESKWALLPAPER
40 # define SPI_GETDESKWALLPAPER 0x0073
41 #endif
42 
43 static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
44 static BOOL (WINAPI *pIsProcessDPIAware)(void);
45 static BOOL (WINAPI *pSetProcessDPIAware)(void);
46 static BOOL (WINAPI *pSetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
47 static BOOL (WINAPI *pGetProcessDpiAwarenessInternal)(HANDLE,DPI_AWARENESS*);
48 static BOOL (WINAPI *pSetProcessDpiAwarenessInternal)(DPI_AWARENESS);
49 static UINT (WINAPI *pGetDpiForSystem)(void);
50 static UINT (WINAPI *pGetDpiForWindow)(HWND);
51 static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*);
52 static DPI_AWARENESS_CONTEXT (WINAPI *pGetThreadDpiAwarenessContext)(void);
53 static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
54 static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND);
55 static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
56 static BOOL (WINAPI *pIsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
57 static INT (WINAPI *pGetSystemMetricsForDpi)(INT,UINT);
58 static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT);
59 static BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
60 static BOOL (WINAPI *pLogicalToPhysicalPointForPerMonitorDPI)(HWND,POINT*);
61 static BOOL (WINAPI *pPhysicalToLogicalPointForPerMonitorDPI)(HWND,POINT*);
62 static LONG (WINAPI *pGetAutoRotationState)(PAR_STATE);
63 
64 static BOOL strict;
65 static int dpi, real_dpi;
66 
67 #define eq(received, expected, label, type) \
68  ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
69 
70 
71 #define SPI_SETBEEP_REGKEY "Control Panel\\Sound"
72 #define SPI_SETBEEP_VALNAME "Beep"
73 #define SPI_SETMOUSE_REGKEY "Control Panel\\Mouse"
74 #define SPI_SETMOUSE_VALNAME1 "MouseThreshold1"
75 #define SPI_SETMOUSE_VALNAME2 "MouseThreshold2"
76 #define SPI_SETMOUSE_VALNAME3 "MouseSpeed"
77 #define SPI_SETBORDER_REGKEY "Control Panel\\Desktop\\WindowMetrics"
78 #define SPI_SETBORDER_REGKEY2 "Control Panel\\Desktop"
79 #define SPI_SETBORDER_VALNAME "BorderWidth"
80 #define SPI_METRIC_REGKEY "Control Panel\\Desktop\\WindowMetrics"
81 #define SPI_SCROLLWIDTH_VALNAME "ScrollWidth"
82 #define SPI_SCROLLHEIGHT_VALNAME "ScrollHeight"
83 #define SPI_CAPTIONWIDTH_VALNAME "CaptionWidth"
84 #define SPI_CAPTIONHEIGHT_VALNAME "CaptionHeight"
85 #define SPI_CAPTIONFONT_VALNAME "CaptionFont"
86 #define SPI_SMCAPTIONWIDTH_VALNAME "SmCaptionWidth"
87 #define SPI_SMCAPTIONHEIGHT_VALNAME "SmCaptionHeight"
88 #define SPI_SMCAPTIONFONT_VALNAME "SmCaptionFont"
89 #define SPI_MENUWIDTH_VALNAME "MenuWidth"
90 #define SPI_MENUHEIGHT_VALNAME "MenuHeight"
91 #define SPI_MENUFONT_VALNAME "MenuFont"
92 #define SPI_STATUSFONT_VALNAME "StatusFont"
93 #define SPI_MESSAGEFONT_VALNAME "MessageFont"
94 
95 #define SPI_SETKEYBOARDSPEED_REGKEY "Control Panel\\Keyboard"
96 #define SPI_SETKEYBOARDSPEED_VALNAME "KeyboardSpeed"
97 #define SPI_ICONHORIZONTALSPACING_REGKEY "Control Panel\\Desktop\\WindowMetrics"
98 #define SPI_ICONHORIZONTALSPACING_REGKEY2 "Control Panel\\Desktop"
99 #define SPI_ICONHORIZONTALSPACING_VALNAME "IconSpacing"
100 #define SPI_ICONVERTICALSPACING_REGKEY "Control Panel\\Desktop\\WindowMetrics"
101 #define SPI_ICONVERTICALSPACING_REGKEY2 "Control Panel\\Desktop"
102 #define SPI_ICONVERTICALSPACING_VALNAME "IconVerticalSpacing"
103 #define SPI_MINIMIZEDMETRICS_REGKEY "Control Panel\\Desktop\\WindowMetrics"
104 #define SPI_MINWIDTH_VALNAME "MinWidth"
105 #define SPI_MINHORZGAP_VALNAME "MinHorzGap"
106 #define SPI_MINVERTGAP_VALNAME "MinVertGap"
107 #define SPI_MINARRANGE_VALNAME "MinArrange"
108 #define SPI_SETSCREENSAVETIMEOUT_REGKEY "Control Panel\\Desktop"
109 #define SPI_SETSCREENSAVETIMEOUT_VALNAME "ScreenSaveTimeOut"
110 #define SPI_SETSCREENSAVEACTIVE_REGKEY "Control Panel\\Desktop"
111 #define SPI_SETSCREENSAVEACTIVE_VALNAME "ScreenSaveActive"
112 #define SPI_SETGRIDGRANULARITY_REGKEY "Control Panel\\Desktop"
113 #define SPI_SETGRIDGRANULARITY_VALNAME "GridGranularity"
114 #define SPI_SETKEYBOARDDELAY_REGKEY "Control Panel\\Keyboard"
115 #define SPI_SETKEYBOARDDELAY_VALNAME "KeyboardDelay"
116 #define SPI_SETICONTITLEWRAP_REGKEY1 "Control Panel\\Desktop\\WindowMetrics"
117 #define SPI_SETICONTITLEWRAP_REGKEY2 "Control Panel\\Desktop"
118 #define SPI_SETICONTITLEWRAP_VALNAME "IconTitleWrap"
119 #define SPI_SETMENUDROPALIGNMENT_REGKEY1 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
120 #define SPI_SETMENUDROPALIGNMENT_REGKEY2 "Control Panel\\Desktop"
121 #define SPI_SETMENUDROPALIGNMENT_VALNAME "MenuDropAlignment"
122 #define SPI_SETDOUBLECLKWIDTH_REGKEY1 "Control Panel\\Mouse"
123 #define SPI_SETDOUBLECLKWIDTH_REGKEY2 "Control Panel\\Desktop"
124 #define SPI_SETDOUBLECLKWIDTH_VALNAME "DoubleClickWidth"
125 #define SPI_SETDOUBLECLKHEIGHT_REGKEY1 "Control Panel\\Mouse"
126 #define SPI_SETDOUBLECLKHEIGHT_REGKEY2 "Control Panel\\Desktop"
127 #define SPI_SETDOUBLECLKHEIGHT_VALNAME "DoubleClickHeight"
128 #define SPI_SETDOUBLECLICKTIME_REGKEY "Control Panel\\Mouse"
129 #define SPI_SETDOUBLECLICKTIME_VALNAME "DoubleClickSpeed"
130 #define SPI_SETMOUSEBUTTONSWAP_REGKEY "Control Panel\\Mouse"
131 #define SPI_SETMOUSEBUTTONSWAP_VALNAME "SwapMouseButtons"
132 #define SPI_SETWORKAREA_REGKEY "Control Panel\\Desktop"
133 #define SPI_SETWORKAREA_VALNAME "WINE_WorkArea"
134 #define SPI_SETSHOWSOUNDS_REGKEY "Control Panel\\Accessibility\\ShowSounds"
135 #define SPI_SETSHOWSOUNDS_VALNAME "On"
136 #define SPI_SETKEYBOARDPREF_REGKEY "Control Panel\\Accessibility\\Keyboard Preference"
137 #define SPI_SETKEYBOARDPREF_VALNAME "On"
138 #define SPI_SETKEYBOARDPREF_REGKEY_LEGACY "Control Panel\\Accessibility"
139 #define SPI_SETKEYBOARDPREF_VALNAME_LEGACY "Keyboard Preference"
140 #define SPI_SETSCREENREADER_REGKEY "Control Panel\\Accessibility\\Blind Access"
141 #define SPI_SETSCREENREADER_VALNAME "On"
142 #define SPI_SETSCREENREADER_REGKEY_LEGACY "Control Panel\\Accessibility"
143 #define SPI_SETSCREENREADER_VALNAME_LEGACY "Blind Access"
144 #define SPI_SETFONTSMOOTHING_REGKEY "Control Panel\\Desktop"
145 #define SPI_SETFONTSMOOTHING_VALNAME "FontSmoothing"
146 #define SPI_SETFONTSMOOTHINGTYPE_VALNAME "FontSmoothingType"
147 #define SPI_SETFONTSMOOTHINGCONTRAST_VALNAME "FontSmoothingGamma"
148 #define SPI_SETFONTSMOOTHINGORIENTATION_VALNAME "FontSmoothingOrientation"
149 #define SPI_SETLOWPOWERACTIVE_REGKEY "Control Panel\\Desktop"
150 #define SPI_SETLOWPOWERACTIVE_VALNAME "LowPowerActive"
151 #define SPI_SETPOWEROFFACTIVE_REGKEY "Control Panel\\Desktop"
152 #define SPI_SETPOWEROFFACTIVE_VALNAME "PowerOffActive"
153 #define SPI_SETDRAGFULLWINDOWS_REGKEY "Control Panel\\Desktop"
154 #define SPI_SETDRAGFULLWINDOWS_VALNAME "DragFullWindows"
155 #define SPI_SETSNAPTODEFBUTTON_REGKEY "Control Panel\\Mouse"
156 #define SPI_SETSNAPTODEFBUTTON_VALNAME "SnapToDefaultButton"
157 #define SPI_SETMOUSEHOVERWIDTH_REGKEY "Control Panel\\Mouse"
158 #define SPI_SETMOUSEHOVERWIDTH_VALNAME "MouseHoverWidth"
159 #define SPI_SETMOUSEHOVERHEIGHT_REGKEY "Control Panel\\Mouse"
160 #define SPI_SETMOUSEHOVERHEIGHT_VALNAME "MouseHoverHeight"
161 #define SPI_SETMOUSEHOVERTIME_REGKEY "Control Panel\\Mouse"
162 #define SPI_SETMOUSEHOVERTIME_VALNAME "MouseHoverTime"
163 #define SPI_SETMOUSESCROLLCHARS_REGKEY "Control Panel\\Desktop"
164 #define SPI_SETMOUSESCROLLCHARS_VALNAME "WheelScrollChars"
165 #define SPI_SETMOUSESCROLLLINES_REGKEY "Control Panel\\Desktop"
166 #define SPI_SETMOUSESCROLLLINES_VALNAME "WheelScrollLines"
167 #define SPI_SETMENUSHOWDELAY_REGKEY "Control Panel\\Desktop"
168 #define SPI_SETMENUSHOWDELAY_VALNAME "MenuShowDelay"
169 #define SPI_SETDESKWALLPAPER_REGKEY "Control Panel\\Desktop"
170 #define SPI_SETDESKWALLPAPER_VALNAME "Wallpaper"
171 
172 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
173 #define WINE_CURRENT_USER_REGKEY "Wine"
174 
176 
177 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam );
179  LPARAM lParam );
180 static int change_counter;
182 static int change_last_param;
183 static int last_bpp;
186 
187 static BOOL get_reg_dword(HKEY base, const char *key_name, const char *value_name, DWORD *value)
188 {
189  HKEY key;
190  DWORD type, data, size = sizeof(data);
191  BOOL ret = FALSE;
192 
194  {
195  if (RegQueryValueExA(key, value_name, NULL, &type, (void *)&data, &size) == ERROR_SUCCESS &&
196  type == REG_DWORD)
197  {
198  *value = data;
199  ret = TRUE;
200  }
201  RegCloseKey(key);
202  }
203  return ret;
204 }
205 
206 static DWORD get_real_dpi(void)
207 {
208  DWORD dpi;
209 
210  if (pSetThreadDpiAwarenessContext)
211  {
212  DPI_AWARENESS_CONTEXT context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
213  dpi = pGetDpiForSystem();
214  pSetThreadDpiAwarenessContext( context );
215  return dpi;
216  }
217  if (get_reg_dword(HKEY_CURRENT_USER, "Control Panel\\Desktop", "LogPixels", &dpi))
218  return dpi;
219  if (get_reg_dword(HKEY_CURRENT_CONFIG, "Software\\Fonts", "LogPixels", &dpi))
220  return dpi;
222 }
223 
225  LPARAM lParam )
226 {
227  switch (msg) {
228 
229  case WM_DISPLAYCHANGE:
230  ok(displaychange_ok, "Unexpected WM_DISPLAYCHANGE message\n");
231  last_bpp = wParam;
234  break;
235 
236  case WM_SETTINGCHANGE:
237  if (change_counter>0) {
238  /* ignore these messages caused by resizing of toolbars */
239  if( wParam == SPI_SETWORKAREA){
241  break;
242  } else if( wParam == SPI_ICONVERTICALSPACING) {
244  break;
245  } else if( displaychange_test_active)
246  break;
247  if( !change_last_param){
249  break;
250  }
251  ok(0,"too many changes counter=%d last change=%d\n",
253  change_counter++;
255  break;
256  }
257  change_counter++;
259  if( wParam == SPI_SETWORKAREA)
261  else if( wParam == SPI_ICONVERTICALSPACING)
263  else
265  break;
266 
267  case WM_DESTROY:
268  PostQuitMessage( 0 );
269  break;
270 
271  /* drop through */
272  default:
273  return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
274  }
275 
276  return 0;
277 }
278 
279 /*
280 Performs testing for system parameters messages
281 params:
282  - system parameter id
283  - supposed value of the registry key
284 */
285 static void test_change_message( int action, int optional )
286 {
287  if (change_counter==0 && optional==1)
288  return;
289  ok( 1 == change_counter,
290  "Missed a message: change_counter=%d\n", change_counter );
291  change_counter = 0;
293  ( change_setworkarea_param && action == SPI_SETWORKAREA) ||
295  "Wrong action got %d expected %d\n", change_last_param, action );
296  change_last_param = 0;
297 }
298 
299 static BOOL test_error_msg ( int rc, const char *name )
300 {
302 
303  if (rc==0)
304  {
306  {
307  skip("%s not supported on this platform\n", name);
308  }
310  {
311  skip("%s does not have privileges to run\n", name);
312  }
313  else
314  {
315  trace("%s failed for reason: %d. Indicating test failure and skipping remainder of test\n",name,last_error);
316  ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
317  }
318  return FALSE;
319  }
320  else
321  {
322  ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
323  return TRUE;
324  }
325 }
326 
327 /*
328  * Tests the HKEY_CURRENT_USER subkey value.
329  * The value should contain string value.
330  */
331 static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName1, LPCSTR valName2,
332  const void *exp_value, DWORD exp_type, BOOL optional )
333 {
335  DWORD valueLen;
336  DWORD type;
337  HKEY hKey;
338  LONG rc;
339  int found=0;
340 
341  *value='\0';
342  valueLen=sizeof(value);
343  RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
344  rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
345  RegCloseKey( hKey );
346  if (rc==ERROR_SUCCESS)
347  {
348  ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
349  switch (exp_type)
350  {
351  case REG_DWORD:
352  ok( *(DWORD *)value == *(DWORD *)exp_value,
353  "Wrong value in registry: %s %s %08x/%08x\n",
354  subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
355  break;
356  case REG_SZ:
357  ok( !strcmp( exp_value, value ),
358  "Wrong value in registry: %s %s '%s' instead of '%s'\n",
359  subKey1, valName1, value, (const char *)exp_value );
360  break;
361  }
362  found++;
363  }
364  else if (strict)
365  {
366  ok(0,"Missing registry entry: subKey=%s, valName=%s\n",
367  subKey1, valName1);
368  }
369  if (valName2)
370  {
371  *value='\0';
372  valueLen=sizeof(value);
373  RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
374  rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
375  RegCloseKey( hKey );
376  if (rc==ERROR_SUCCESS)
377  {
378  ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
379  switch (exp_type)
380  {
381  case REG_DWORD:
382  ok( *(DWORD *)value == *(DWORD *)exp_value,
383  "Wrong value in registry: %s %s %08x/%08x\n",
384  subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
385  break;
386  case REG_SZ:
387  ok( !strcmp( exp_value, value ),
388  "Wrong value in registry: %s %s '%s' instead of '%s'\n",
389  subKey1, valName1, value, (const char *)exp_value );
390  break;
391  }
392  found++;
393  }
394  else if (strict)
395  {
396  ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
397  subKey1, valName2 );
398  }
399  }
400  if (subKey2 && !strict)
401  {
402  *value='\0';
403  valueLen=sizeof(value);
404  RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
405  rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
406  RegCloseKey( hKey );
407  if (rc==ERROR_SUCCESS)
408  {
409  ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
410  switch (exp_type)
411  {
412  case REG_DWORD:
413  ok( *(DWORD *)value == *(DWORD *)exp_value,
414  "Wrong value in registry: %s %s %08x/%08x\n",
415  subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
416  break;
417  case REG_SZ:
418  ok( !strcmp( exp_value, value ),
419  "Wrong value in registry: %s %s '%s' instead of '%s'\n",
420  subKey1, valName1, value, (const char *)exp_value );
421  break;
422  }
423  found++;
424  }
425  else if (strict)
426  {
427  ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
428  subKey2, valName1 );
429  }
430  if (valName2)
431  {
432  *value='\0';
433  valueLen=sizeof(value);
434  RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
435  rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
436  RegCloseKey( hKey );
437  if (rc==ERROR_SUCCESS)
438  {
439  ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
440  switch (exp_type)
441  {
442  case REG_DWORD:
443  ok( *(DWORD *)value == *(DWORD *)exp_value,
444  "Wrong value in registry: %s %s %08x/%08x\n",
445  subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
446  break;
447  case REG_SZ:
448  ok( !strcmp( exp_value, value ),
449  "Wrong value in registry: %s %s '%s' instead of '%s'\n",
450  subKey1, valName1, value, (const char *)exp_value );
451  break;
452  }
453  found++;
454  }
455  else if (strict)
456  {
457  ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
458  subKey2, valName2 );
459  }
460  }
461  }
462  ok(found || optional,
463  "Missing registry values: %s or %s in keys: %s or %s\n",
464  valName1, (valName2?valName2:"<n/a>"), subKey1, (subKey2?subKey2:"<n/a>") );
465 }
466 
467 #define test_reg_key( subKey, valName, testValue ) \
468  _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, FALSE )
469 #define test_reg_key_optional( subKey, valName, testValue ) \
470  _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, TRUE )
471 #define test_reg_key_ex( subKey1, subKey2, valName, testValue ) \
472  _test_reg_key( subKey1, subKey2, valName, NULL, testValue, REG_SZ, FALSE )
473 #define test_reg_key_ex2( subKey1, subKey2, valName1, valName2, testValue ) \
474  _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, FALSE )
475 #define test_reg_key_ex2_optional( subKey1, subKey2, valName1, valName2, testValue ) \
476  _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, TRUE )
477 #define test_reg_key_dword( subKey, valName, testValue ) \
478  _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_DWORD, FALSE )
479 
480 /* get a metric from the registry. If the value is negative
481  * it is assumed to be in twips and converted to pixels */
482 static UINT metricfromreg( const char *keyname, const char *valname, int dpi)
483 {
484  HKEY hkey;
485  char buf[64];
486  DWORD ret;
487  DWORD size, type;
488  int value;
489 
490  RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
491  size = sizeof(buf);
492  ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)buf, &size );
493  RegCloseKey( hkey );
494  if( ret != ERROR_SUCCESS) return -1;
495  value = atoi( buf);
496  if( value < 0)
497  value = ( -value * dpi + 720) / 1440;
498  return value;
499 }
500 
501 typedef struct
502 {
516  CHAR lfFaceName[LF_FACESIZE];
518 
519 /* get logfont from the registry */
520 static int lffromreg( const char *keyname, const char *valname, LOGFONTA *plf)
521 {
522  HKEY hkey;
523  LOGFONTW lfw;
524  DWORD ret, size, type;
525 
526  RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
527  size = sizeof( lfw);
528  ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)&lfw, &size );
529  RegCloseKey( hkey );
530  ok( ret == ERROR_SUCCESS, "Key \"%s\" value \"%s\" not found\n", keyname, valname);
531  if( ret != ERROR_SUCCESS)
532  return FALSE;
533  if( size <= sizeof( LOGFONT16)) {
534  LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
535  plf->lfHeight = plf16->lfHeight;
536  plf->lfWidth = plf16->lfWidth;
537  plf->lfEscapement = plf16->lfEscapement;
538  plf->lfOrientation = plf16->lfOrientation;
539  plf->lfWeight = plf16->lfWeight;
540  plf->lfItalic = plf16->lfItalic;
541  plf->lfUnderline = plf16->lfUnderline;
542  plf->lfStrikeOut = plf16->lfStrikeOut;
543  plf->lfCharSet = plf16->lfCharSet;
544  plf->lfOutPrecision = plf16->lfOutPrecision;
545  plf->lfClipPrecision = plf16->lfClipPrecision;
546  plf->lfQuality = plf16->lfQuality;
547  plf->lfPitchAndFamily = plf16->lfPitchAndFamily;
548  memcpy( plf->lfFaceName, plf16->lfFaceName, LF_FACESIZE );
549  } else if( size <= sizeof( LOGFONTA)) {
550  plf = (LOGFONTA*) &lfw;
551  } else {
552  plf->lfHeight = lfw.lfHeight;
553  plf->lfWidth = lfw.lfWidth;
554  plf->lfEscapement = lfw.lfEscapement;
555  plf->lfOrientation = lfw.lfOrientation;
556  plf->lfWeight = lfw.lfWeight;
557  plf->lfItalic = lfw.lfItalic;
558  plf->lfUnderline = lfw.lfUnderline;
559  plf->lfStrikeOut = lfw.lfStrikeOut;
560  plf->lfCharSet = lfw.lfCharSet;
561  plf->lfOutPrecision = lfw.lfOutPrecision;
562  plf->lfClipPrecision = lfw.lfClipPrecision;
563  plf->lfQuality = lfw.lfQuality;
564  plf->lfPitchAndFamily = lfw.lfPitchAndFamily;
565  WideCharToMultiByte( CP_ACP, 0, lfw.lfFaceName, -1, plf->lfFaceName,
566  LF_FACESIZE, NULL, NULL);
567 
568  }
569  return TRUE;
570 }
571 
572 static void test_SPI_SETBEEP( void ) /* 2 */
573 {
574  BOOL rc;
575  BOOL old_b;
576  BOOL b;
577  BOOL curr_val;
578 
579  trace("testing SPI_{GET,SET}BEEP\n");
580  SetLastError(0xdeadbeef);
581  rc=SystemParametersInfoA( SPI_GETBEEP, 0, &old_b, 0 );
582  if (!test_error_msg(rc,"SPI_{GET,SET}BEEP"))
583  return;
584 
585  curr_val = TRUE;
587  if (!test_error_msg(rc,"SPI_SETBEEP")) return;
588  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
592  curr_val ? "Yes" : "No" );
593  rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
594  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
595  eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
596  rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
598  {
599  ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
600  eq( b, curr_val, "SystemParametersInfoW", "%d" );
601  }
602 
603  /* is a message sent for the second change? */
605  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
607 
608  curr_val = FALSE;
612  ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
616  curr_val ? "Yes" : "No" );
617  rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
618  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
619  eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
620  rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
622  {
623  ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
624  eq( b, curr_val, "SystemParametersInfoW", "%d" );
625  }
626  ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled\n" );
627 
629  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
630 }
631 
632 static const char *setmouse_valuenames[3] = {
636 };
637 
638 /*
639  * Runs check for one setting of spi_setmouse.
640  */
641 static BOOL run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *proj_change, int nchange )
642 {
643  BOOL rc;
644  INT mi[3];
645  static int aw_turn = 0;
646 
647  char buf[20];
648  int i;
649 
650  aw_turn++;
651  rc = FALSE;
652  SetLastError(0xdeadbeef);
653  if (aw_turn % 2) /* call unicode on odd (non even) calls */
655  else
657  if (!test_error_msg(rc,"SPI_SETMOUSE")) return FALSE;
658 
659  ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
661  for (i = 0; i < 3; i++)
662  {
663  sprintf( buf, "%d", curr_val[i] );
665  }
666 
668  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
669  for (i = 0; i < 3; i++)
670  {
671  ok(mi[i] == curr_val[i],
672  "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
673  }
674 
676  ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
677  for (i = 0; i < 3; i++)
678  {
679  ok(mi[i] == curr_val[i],
680  "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
681  }
682 
683  if (0)
684  {
685  /* FIXME: this always fails for me - AJ */
686  for (i = 0; i < nchange; i++)
687  {
688  POINT mv;
690  mouse_event( MOUSEEVENTF_MOVE, req_change[i].x, req_change[i].y, 0, 0 );
691  GetCursorPos( &mv );
692  ok( proj_change[i].x == mv.x, "Projected dx and real dx comparison. May fail under high load.\n" );
693  ok( proj_change[i].y == mv.y, "Projected dy equals real dy. May fail under high load.\n" );
694  }
695  }
696  return TRUE;
697 }
698 
699 static void test_SPI_SETMOUSE( void ) /* 4 */
700 {
701  BOOL rc;
702  INT old_mi[3];
703 
704  /* win nt default values - 6, 10, 1 */
705  INT curr_val[3] = {6, 10, 1};
706 
707  /* requested and projected mouse movements */
708  POINT req_change[] = { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
709  POINT proj_change1[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
710  POINT proj_change2[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {44, 20}, {400, 400} };
711  POINT proj_change3[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
712  POINT proj_change4[] = { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
713  POINT proj_change5[] = { {6, 6}, { 7, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
714  POINT proj_change6[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
715  POINT proj_change7[] = { {6, 6}, {14, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
716  POINT proj_change8[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
717 
718  int nchange = ARRAY_SIZE(req_change);
719 
720  trace("testing SPI_{GET,SET}MOUSE\n");
721  SetLastError(0xdeadbeef);
722  rc=SystemParametersInfoA( SPI_GETMOUSE, 0, old_mi, 0 );
723  if (!test_error_msg(rc,"SPI_{GET,SET}MOUSE"))
724  return;
725 
726  if (!run_spi_setmouse_test( curr_val, req_change, proj_change1, nchange )) return;
727 
728  /* acceleration change */
729  curr_val[2] = 2;
730  run_spi_setmouse_test( curr_val, req_change, proj_change2, nchange );
731 
732  /* acceleration change */
733  curr_val[2] = 3;
734  run_spi_setmouse_test( curr_val, req_change, proj_change3, nchange );
735 
736  /* acceleration change */
737  curr_val[2] = 0;
738  run_spi_setmouse_test( curr_val, req_change, proj_change4, nchange );
739 
740  /* threshold change */
741  curr_val[2] = 1;
742  curr_val[0] = 7;
743  run_spi_setmouse_test( curr_val, req_change, proj_change5, nchange );
744 
745  /* threshold change */
746  curr_val[2] = 2;
747  curr_val[0] = 6;
748  curr_val[1] = 6;
749  run_spi_setmouse_test( curr_val, req_change, proj_change6, nchange );
750 
751  /* threshold change */
752  curr_val[1] = 7;
753  run_spi_setmouse_test( curr_val, req_change, proj_change7, nchange );
754 
755  /* threshold change */
756  curr_val[1] = 5;
757  run_spi_setmouse_test( curr_val, req_change, proj_change8, nchange );
758 
760  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
761 }
762 
763 static BOOL test_setborder(UINT curr_val, int usesetborder, int dpi)
764 {
765  BOOL rc;
766  UINT border, regval;
767  INT frame;
768  NONCLIENTMETRICSA ncm;
769 
770  ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
771  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
772  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
773  if( usesetborder) {
775  if (!test_error_msg(rc,"SPI_SETBORDER")) return FALSE;
776  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
778  } else { /* set non client metrics */
779  ncm.iBorderWidth = curr_val;
780  rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
782  if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return FALSE;
783  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
784  test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
785  }
786  if( curr_val) { /* skip if 0, some windows versions return 0 others 1 */
788  if( regval != curr_val)
790  ok( regval==curr_val, "wrong value in registry %d, expected %d\n", regval, curr_val);
791  }
792  /* minimum border width is 1 */
793  if (curr_val == 0) curr_val = 1;
794  /* should be the same as the non client metrics */
795  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
796  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
797  eq( (UINT)ncm.iBorderWidth, curr_val, "NonClientMetric.iBorderWidth", "%d");
798  /* and from SPI_GETBORDER */
800  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
801  eq( border, curr_val, "SPI_{GET,SET}BORDER", "%d");
802  /* test some SystemMetrics */
803  frame = curr_val + GetSystemMetrics( SM_CXDLGFRAME );
804  eq( frame, GetSystemMetrics( SM_CXFRAME ), "SM_CXFRAME", "%d" );
805  eq( frame, GetSystemMetrics( SM_CYFRAME ), "SM_CYFRAME", "%d" );
806  eq( frame, GetSystemMetrics( SM_CXSIZEFRAME ), "SM_CXSIZEFRAME", "%d" );
807  eq( frame, GetSystemMetrics( SM_CYSIZEFRAME ), "SM_CYSIZEFRAME", "%d" );
808  return TRUE;
809 }
810 
811 static void test_SPI_SETBORDER( void ) /* 6 */
812 {
813  BOOL rc;
814  UINT old_border;
815  NONCLIENTMETRICSA ncmsave;
816  INT CaptionWidth,
817  PaddedBorderWidth;
818 
819  ncmsave.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
820  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncmsave, 0);
821  if( !rc) {
822  win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
823  return;
824  }
825  /* CaptionWidth from the registry may have different value of iCaptionWidth
826  * from the non client metrics (observed on WinXP).
827  * Fix this so we can safely restore settings with the nonclientmetrics */
828  CaptionWidth = metricfromreg(
829  "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
830  ncmsave.iCaptionWidth = CaptionWidth;
831 
832  /* These tests hang when XFree86 4.0 for Windows is running (tested on
833  * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
834  * running.
835  */
836  if (FindWindowA( NULL, "Cygwin/XFree86" ))
837  return;
838 
839  trace("testing SPI_{GET,SET}BORDER\n");
840 
841  SetLastError(0xdeadbeef);
842  rc=SystemParametersInfoA( SPI_GETBORDER, 0, &old_border, 0 );
843  if (!test_error_msg(rc,"SPI_{GET,SET}BORDER"))
844  return;
845  /* FIXME: include new PaddedBorderWidth parameter */
846  PaddedBorderWidth = ncmsave.iBorderWidth - old_border;
847  if( PaddedBorderWidth){
848  win_skip( "Cannot reliably restore border width yet (PaddedBorderWidth = %d)\n",
849  PaddedBorderWidth);
850  return;
851  }
852  /* This will restore sane values if the test hang previous run. */
853  if ( old_border == 7 || old_border == 20 )
854  old_border = 1;
855 
856  /* win2k3 fails if you set the same border twice, or if size is 0 */
857  if (!test_setborder(2, 1, dpi)) return;
858  test_setborder(1, 1, dpi);
859  test_setborder(3, 1, dpi);
860  if (!test_setborder(1, 0, dpi)) return;
861  test_setborder(0, 0, dpi);
862  test_setborder(3, 0, dpi);
863 
864  rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncmsave,
866  test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
867  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
868 }
869 
870 static void test_SPI_SETKEYBOARDSPEED( void ) /* 10 */
871 {
872  BOOL rc;
873  UINT old_speed;
874  const UINT vals[]={0,20,31};
875  unsigned int i;
876 
877  trace("testing SPI_{GET,SET}KEYBOARDSPEED\n");
878  SetLastError(0xdeadbeef);
879  rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &old_speed, 0 );
880  if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDSPEED"))
881  return;
882 
883  for (i=0;i<ARRAY_SIZE(vals);i++)
884  {
885  UINT v;
886  char buf[10];
887 
890  if (!test_error_msg(rc,"SPI_SETKEYBOARDSPEED")) return;
891  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
893  sprintf( buf, "%d", vals[i] );
895 
897  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
898  eq( v, vals[i], "SPI_{GET,SET}KEYBOARDSPEED", "%d" );
899  }
900 
902  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
903 }
904 
905 /* test_SPI_ICONHORIZONTALSPACING helper */
907 {
908  BOOL rc;
909  INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
910  ICONMETRICSA im;
911 
914  if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING")) return FALSE;
915  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
917  curr_val = max( curr_val, min_val );
918  /* The registry keys depend on the Windows version and the values too
919  * let's test (works on win95,ME,NT4,2k,XP)
920  */
922  if( regval != curr_val)
924  ok( curr_val == regval,
925  "wrong value in registry %d, expected %d\n", regval, curr_val);
926  /* compare with what SPI_ICONHORIZONTALSPACING returns */
927  rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
928  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
929  eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
930  /* and with a system metrics */
931  eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
932  /* and with what SPI_GETICONMETRICS returns */
933  im.cbSize = sizeof(ICONMETRICSA);
934  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
935  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
936  eq( im.iHorzSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
937  return TRUE;
938 }
939 
940 static void test_SPI_ICONHORIZONTALSPACING( void ) /* 13 */
941 {
942  BOOL rc;
943  INT old_spacing;
944 
945  trace("testing SPI_ICONHORIZONTALSPACING\n");
946  SetLastError(0xdeadbeef);
947  /* default value: 75 */
948  rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &old_spacing, 0 );
949  if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING"))
950  return;
951  /* do not increase the value as it would upset the user's icon layout */
952  if (!dotest_spi_iconhorizontalspacing( old_spacing - 1)) return;
953  dotest_spi_iconhorizontalspacing( 10); /* minimum is 32 */
954  /* restore */
956  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
957 }
958 
959 static void test_SPI_SETSCREENSAVETIMEOUT( void ) /* 14 */
960 {
961  BOOL rc;
962  UINT old_timeout;
963  const UINT vals[]={0,32767};
964  unsigned int i;
965 
966  trace("testing SPI_{GET,SET}SCREENSAVETIMEOUT\n");
967  SetLastError(0xdeadbeef);
968  rc=SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &old_timeout, 0 );
969  if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVETIMEOUT"))
970  return;
971 
972  for (i=0;i<ARRAY_SIZE(vals);i++)
973  {
974  UINT v;
975  char buf[10];
976 
979  if (!test_error_msg(rc,"SPI_SETSCREENSAVETIMEOUT")) return;
980  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
982  sprintf( buf, "%d", vals[i] );
985 
987  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
988  eq( v, vals[i], "SPI_{GET,SET}SCREENSAVETIMEOUT", "%d" );
989  }
990 
993  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
994 }
995 
996 static void test_SPI_SETSCREENSAVEACTIVE( void ) /* 17 */
997 {
998  BOOL rc;
999  BOOL old_b;
1000  const UINT vals[]={TRUE,FALSE};
1001  unsigned int i;
1002 
1003  trace("testing SPI_{GET,SET}SCREENSAVEACTIVE\n");
1004  SetLastError(0xdeadbeef);
1005  rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &old_b, 0 );
1006  if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVEACTIVE"))
1007  return;
1008 
1009  for (i=0;i<ARRAY_SIZE(vals);i++)
1010  {
1011  UINT v;
1012 
1015  if (!test_error_msg(rc,"SPI_SETSCREENSAVEACTIVE")) return;
1016  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1020  vals[i] ? "1" : "0" );
1021 
1023  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1024  ok(v == vals[i] || broken(! v) /* Win 7 */,
1025  "SPI_{GET,SET}SCREENSAVEACTIVE: got %d instead of %d\n", v, vals[i]);
1026  }
1027 
1029  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1030 }
1031 
1032 static void test_SPI_SETGRIDGRANULARITY( void ) /* 19 */
1033 {
1034  /* ??? */;
1035 }
1036 
1037 static void test_SPI_SETKEYBOARDDELAY( void ) /* 23 */
1038 {
1039  BOOL rc;
1040  UINT old_delay;
1041  const UINT vals[]={0,3};
1042  unsigned int i;
1043 
1044  trace("testing SPI_{GET,SET}KEYBOARDDELAY\n");
1045  SetLastError(0xdeadbeef);
1046  rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &old_delay, 0 );
1047  if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
1048  return;
1049 
1050  for (i=0;i<ARRAY_SIZE(vals);i++)
1051  {
1052  UINT delay;
1053  char buf[10];
1054 
1057  if (!test_error_msg(rc,"SPI_SETKEYBOARDDELAY")) return;
1058  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1060  sprintf( buf, "%d", vals[i] );
1063 
1065  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1066  eq( delay, vals[i], "SPI_{GET,SET}KEYBOARDDELAY", "%d" );
1067  }
1068 
1070  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1071 }
1072 
1073 
1074 /* test_SPI_ICONVERTICALSPACING helper */
1076 {
1077  BOOL rc;
1078  INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
1079  ICONMETRICSA im;
1080 
1083  if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING")) return FALSE;
1084  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1086  curr_val = max( curr_val, min_val );
1087  /* The registry keys depend on the Windows version and the values too
1088  * let's test (works on win95,ME,NT4,2k,XP)
1089  */
1091  if( regval != curr_val)
1093  ok( curr_val == regval,
1094  "wrong value in registry %d, expected %d\n", regval, curr_val);
1095  /* compare with what SPI_ICONVERTICALSPACING returns */
1096  rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1097  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1098  eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
1099  /* and with a system metrics */
1100  eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
1101  /* and with what SPI_GETICONMETRICS returns */
1102  im.cbSize = sizeof(ICONMETRICSA);
1103  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1104  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1105  eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
1106  return TRUE;
1107 }
1108 
1109 static void test_SPI_ICONVERTICALSPACING( void ) /* 24 */
1110 {
1111  BOOL rc;
1112  INT old_spacing;
1113 
1114  trace("testing SPI_ICONVERTICALSPACING\n");
1115  SetLastError(0xdeadbeef);
1116  /* default value: 75 */
1117  rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
1118  if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
1119  return;
1120  /* do not increase the value as it would upset the user's icon layout */
1121  if (!dotest_spi_iconverticalspacing( old_spacing - 1)) return;
1122  /* same tests with a value less than the minimum 32 */
1124  /* restore */
1125  rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
1127  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1128 }
1129 
1130 static void test_SPI_SETICONTITLEWRAP( void ) /* 26 */
1131 {
1132  BOOL rc;
1133  BOOL old_b;
1134  const UINT vals[]={TRUE,FALSE};
1135  unsigned int i;
1136  ICONMETRICSA im;
1137 
1138  /* These tests hang when XFree86 4.0 for Windows is running (tested on
1139  * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
1140  * running.
1141  */
1142  if (FindWindowA( NULL, "Cygwin/XFree86" ))
1143  return;
1144 
1145  trace("testing SPI_{GET,SET}ICONTITLEWRAP\n");
1146  SetLastError(0xdeadbeef);
1147  rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &old_b, 0 );
1148  if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
1149  return;
1150 
1151  for (i=0;i<ARRAY_SIZE(vals);i++)
1152  {
1153  UINT v;
1154  UINT regval;
1155 
1158  if (!test_error_msg(rc,"SPI_SETICONTITLEWRAP")) return;
1159  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1163  if( regval != vals[i])
1166  ok( regval == vals[i], "wrong value in registry %d, expected %d\n", regval, vals[i] );
1167 
1169  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1170  eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
1171  /* and test with what SPI_GETICONMETRICS returns */
1172  im.cbSize = sizeof(ICONMETRICSA);
1173  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1174  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1175  eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
1176  }
1177 
1179  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1180 }
1181 
1182 static void test_SPI_SETMENUDROPALIGNMENT( void ) /* 28 */
1183 {
1184  BOOL rc;
1185  BOOL old_b;
1186  const UINT vals[]={TRUE,FALSE};
1187  unsigned int i;
1188 
1189  trace("testing SPI_{GET,SET}MENUDROPALIGNMENT\n");
1190  SetLastError(0xdeadbeef);
1191  rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &old_b, 0 );
1192  if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
1193  return;
1194 
1195  for (i=0;i<ARRAY_SIZE(vals);i++)
1196  {
1197  UINT v;
1198 
1201  if (!test_error_msg(rc,"SPI_SETMENUDROPALIGNMENT")) return;
1202  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1207  vals[i] ? "1" : "0" );
1208 
1210  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1211  eq( v, vals[i], "SPI_{GET,SET}MENUDROPALIGNMENT", "%d" );
1212  eq( GetSystemMetrics( SM_MENUDROPALIGNMENT ), (int)vals[i],
1213  "SM_MENUDROPALIGNMENT", "%d" );
1214  }
1215 
1218  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1219 }
1220 
1221 static void test_SPI_SETDOUBLECLKWIDTH( void ) /* 29 */
1222 {
1223  BOOL rc;
1224  INT old_width;
1225  const UINT vals[]={0,10000};
1226  unsigned int i;
1227 
1228  trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
1229  old_width = GetSystemMetrics( SM_CXDOUBLECLK );
1230 
1231  for (i=0;i<ARRAY_SIZE(vals);i++)
1232  {
1233  char buf[10];
1234 
1235  SetLastError(0xdeadbeef);
1238  if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKWIDTH"))
1239  return;
1240 
1242  sprintf( buf, "%d", vals[i] );
1246  eq( GetSystemMetrics( SM_CXDOUBLECLK ), (int)vals[i],
1247  "SM_CXDOUBLECLK", "%d" );
1248  }
1249 
1250  rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, old_width, 0,
1252  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1253 }
1254 
1255 static void test_SPI_SETDOUBLECLKHEIGHT( void ) /* 30 */
1256 {
1257  BOOL rc;
1258  INT old_height;
1259  const UINT vals[]={0,10000};
1260  unsigned int i;
1261 
1262  trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
1263  old_height = GetSystemMetrics( SM_CYDOUBLECLK );
1264 
1265  for (i=0;i<ARRAY_SIZE(vals);i++)
1266  {
1267  char buf[10];
1268 
1269  SetLastError(0xdeadbeef);
1272  if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKHEIGHT"))
1273  return;
1274 
1276  sprintf( buf, "%d", vals[i] );
1280  eq( GetSystemMetrics( SM_CYDOUBLECLK ), (int)vals[i],
1281  "SM_CYDOUBLECLK", "%d" );
1282  }
1283 
1284  rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, old_height, 0,
1286  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1287 }
1288 
1289 static void test_SPI_SETDOUBLECLICKTIME( void ) /* 32 */
1290 {
1291  BOOL rc;
1292  UINT curr_val;
1293  UINT saved_val;
1294  UINT old_time;
1295  char buf[10];
1296 
1297  trace("testing SPI_{GET,SET}DOUBLECLICKTIME\n");
1298  old_time = GetDoubleClickTime();
1299 
1300  curr_val = 0;
1301  SetLastError(0xdeadbeef);
1304  if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLICKTIME"))
1305  return;
1306 
1308  sprintf( buf, "%d", curr_val );
1311  curr_val = 500; /* used value for 0 */
1312  eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1313 
1314  curr_val = 1000;
1317  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1319  sprintf( buf, "%d", curr_val );
1322  eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1323 
1324  saved_val = curr_val;
1325 
1326  curr_val = 0;
1327  SetDoubleClickTime( curr_val );
1328  sprintf( buf, "%d", saved_val );
1331  curr_val = 500; /* used value for 0 */
1332  eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1333 
1334  curr_val = 1000;
1335  SetDoubleClickTime( curr_val );
1336  sprintf( buf, "%d", saved_val );
1339  eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1340 
1342  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1343 }
1344 
1345 static void test_SPI_SETMOUSEBUTTONSWAP( void ) /* 33 */
1346 {
1347  BOOL rc;
1348  BOOL old_b;
1349  const UINT vals[]={TRUE,FALSE};
1350  unsigned int i;
1351 
1352  trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
1353  old_b = GetSystemMetrics( SM_SWAPBUTTON );
1354 
1355  for (i=0;i<ARRAY_SIZE(vals);i++)
1356  {
1357  SetLastError(0xdeadbeef);
1360  if (!test_error_msg(rc,"SPI_SETMOUSEBUTTONSWAP")) return;
1361 
1365  vals[i] ? "1" : "0" );
1366  eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
1367  "SM_SWAPBUTTON", "%d" );
1368  rc=SwapMouseButton((BOOL)vals[i^1]);
1369  eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
1370  "SwapMouseButton", "%d" );
1371  ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
1372  }
1373 
1376  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1377 }
1378 
1379 static void test_SPI_SETFASTTASKSWITCH( void ) /* 36 */
1380 {
1381  BOOL rc;
1382  BOOL v;
1383 
1384  trace("testing SPI_GETFASTTASKSWITCH\n");
1385  SetLastError(0xdeadbeef);
1387  if (!test_error_msg(rc,"SPI_{GET,SET}FASTTASKSWITCH"))
1388  return;
1389 
1390  /* there is not a single Windows platform on which SPI_GETFASTTASKSWITCH
1391  * works. That sure simplifies testing!
1392  */
1393 }
1394 
1395 static void test_SPI_SETDRAGFULLWINDOWS( void ) /* 37 */
1396 {
1397  BOOL rc;
1398  BOOL old_b;
1399  const UINT vals[]={TRUE,FALSE};
1400  unsigned int i;
1401 
1402  trace("testing SPI_{GET,SET}DRAGFULLWINDOWS\n");
1403  SetLastError(0xdeadbeef);
1404  rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &old_b, 0 );
1405 
1406  /* SPI_{GET,SET}DRAGFULLWINDOWS is not implemented on Win95 */
1407  if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
1408  return;
1409 
1410  for (i=0;i<ARRAY_SIZE(vals);i++)
1411  {
1412  UINT v;
1413 
1414  rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, vals[i], 0,
1416  if (!test_error_msg(rc,"SPI_SETDRAGFULLWINDOWS")) return;
1417  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1418  test_change_message( SPI_SETDRAGFULLWINDOWS, 0 );
1421  vals[i] ? "1" : "0" );
1422 
1423  rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &v, 0 );
1424  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1425  eq( v, vals[i], "SPI_{GET,SET}DRAGFULLWINDOWS", "%d" );
1426  }
1427 
1428  rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, old_b, 0, SPIF_UPDATEINIFILE );
1429  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1430 }
1431 
1432 #define test_reg_metric( KEY, VAL, val) do { \
1433  INT regval;\
1434  regval = metricfromreg( KEY, VAL, dpi);\
1435  ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1436 } while(0)
1437 
1438 #define test_reg_metric2( KEY1, KEY2, VAL, val) do { \
1439  INT regval;\
1440  regval = metricfromreg( KEY1, VAL, dpi);\
1441  if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
1442  ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1443 } while(0)
1444 
1445 #define test_reg_font( KEY, VAL, LF) do { \
1446  LOGFONTA lfreg;\
1447  lffromreg( KEY, VAL, &lfreg);\
1448  ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == MulDiv( lfreg.lfHeight, dpi, real_dpi ) : \
1449  MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
1450  (LF).lfWidth == lfreg.lfWidth &&\
1451  (LF).lfWeight == lfreg.lfWeight &&\
1452  !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
1453  , "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
1454 } while(0)
1455 
1456 #define TEST_NONCLIENTMETRICS_REG( ncm) do { \
1457 /*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
1458 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
1459 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
1460 /*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
1461 test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
1462 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
1463 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
1464 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
1465 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
1466 test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
1467 test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
1468 test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
1469 test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
1470 test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont); } while(0)
1471 
1472 /* get text metric height value for the specified logfont */
1473 static int get_tmheight( LOGFONTA *plf, int flag)
1474 {
1475  TEXTMETRICA tm;
1476  HDC hdc = GetDC(0);
1478  hfont = SelectObject( hdc, hfont);
1479  GetTextMetricsA( hdc, &tm);
1480  hfont = SelectObject( hdc, hfont);
1481  ReleaseDC( 0, hdc );
1482  return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1483 }
1484 
1485 static int get_tmheightW( LOGFONTW *plf, int flag)
1486 {
1487  TEXTMETRICW tm;
1488  HDC hdc = GetDC(0);
1490  hfont = SelectObject( hdc, hfont);
1491  GetTextMetricsW( hdc, &tm);
1492  hfont = SelectObject( hdc, hfont);
1493  ReleaseDC( 0, hdc );
1494  return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1495 }
1496 
1497 static void test_GetSystemMetrics( void);
1498 static UINT smcxsmsize = 999999999;
1499 
1500 static void test_SPI_SETNONCLIENTMETRICS( void ) /* 44 */
1501 {
1502  BOOL rc;
1503  INT expect;
1504  NONCLIENTMETRICSA Ncmorig;
1505  NONCLIENTMETRICSA Ncmnew;
1506  NONCLIENTMETRICSA Ncmcur;
1507  NONCLIENTMETRICSA Ncmstart;
1508 
1509  Ncmorig.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1510  Ncmnew.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1511  Ncmcur.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1512  Ncmstart.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1513 
1514  trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1515  change_counter = 0;
1516  SetLastError(0xdeadbeef);
1517  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmorig, FALSE );
1518  if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1519  return;
1520  Ncmstart = Ncmorig;
1521  smcxsmsize = Ncmstart.iSmCaptionWidth;
1522  /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if
1523  the caption font height is higher than the CaptionHeight field,
1524  the latter is adjusted accordingly. To be able to restore these setting
1525  accurately be restore the raw values. */
1527  Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1528  Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1529  Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1530  /* test registry entries */
1531  TEST_NONCLIENTMETRICS_REG( Ncmorig);
1532 
1533  /* make small changes */
1534  Ncmnew = Ncmstart;
1535  Ncmnew.iBorderWidth += 1;
1536  Ncmnew.iScrollWidth += 1;
1537  Ncmnew.iScrollHeight -= 1;
1538  Ncmnew.iCaptionWidth -= 2;
1539  Ncmnew.iCaptionHeight += 2;
1540  Ncmnew.lfCaptionFont.lfHeight +=1;
1541  Ncmnew.lfCaptionFont.lfWidth +=2;
1542  Ncmnew.lfCaptionFont.lfWeight +=1;
1543  Ncmnew.iSmCaptionWidth += 1;
1544  Ncmnew.iSmCaptionHeight += 2;
1545  Ncmnew.lfSmCaptionFont.lfHeight +=3;
1546  Ncmnew.lfSmCaptionFont.lfWidth -=1;
1547  Ncmnew.lfSmCaptionFont.lfWeight +=3;
1548  Ncmnew.iMenuWidth += 1;
1549  Ncmnew.iMenuHeight += 2;
1550  Ncmnew.lfMenuFont.lfHeight +=1;
1551  Ncmnew.lfMenuFont.lfWidth +=1;
1552  Ncmnew.lfMenuFont.lfWeight +=2;
1553  Ncmnew.lfStatusFont.lfHeight -=1;
1554  Ncmnew.lfStatusFont.lfWidth -=1;
1555  Ncmnew.lfStatusFont.lfWeight +=3;
1556  Ncmnew.lfMessageFont.lfHeight -=2;
1557  Ncmnew.lfMessageFont.lfWidth -=1;
1558  Ncmnew.lfMessageFont.lfWeight +=4;
1559 
1560  rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1561  SPIF_SENDCHANGE);
1562  if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return;
1563  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1564  test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1565  /* get them back */
1566  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1567  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1568  /* test registry entries */
1569  TEST_NONCLIENTMETRICS_REG( Ncmcur );
1570  /* test the system metrics with these settings */
1572  /* now for something invalid: increase the {menu|caption|smcaption} fonts
1573  by a large amount will increase the {menu|caption|smcaption} height*/
1574  Ncmnew = Ncmstart;
1575  Ncmnew.lfMenuFont.lfHeight -= 8;
1576  Ncmnew.lfCaptionFont.lfHeight =-4;
1577  Ncmnew.lfSmCaptionFont.lfHeight -=10;
1578  /* also show that a few values are lo limited */
1579  Ncmnew.iCaptionWidth = 0;
1580  Ncmnew.iCaptionHeight = 0;
1581  Ncmnew.iScrollHeight = 0;
1582  Ncmnew.iScrollWidth = 0;
1583 
1584  rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1585  SPIF_SENDCHANGE);
1586  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1587  test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1588  /* raw values are in registry */
1589  TEST_NONCLIENTMETRICS_REG( Ncmnew );
1590  /* get them back */
1591  rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1592  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1593  /* cooked values are returned */
1594  expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1595  ok( Ncmcur.iMenuHeight == expect,
1596  "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1597  expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1598  ok( Ncmcur.iCaptionHeight == expect,
1599  "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1600  expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1601  ok( Ncmcur.iSmCaptionHeight == expect,
1602  "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1603 
1604  /* iCaptionWidth depends on a version, could be 8, 12 (Vista, Win7), 13 */
1605  ok( (Ncmcur.iCaptionWidth >= 8 && Ncmcur.iCaptionWidth <= 13) ||
1606  Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme, the value never changes */
1607  "CaptionWidth: %d expected from [8, 13] or %d\n", Ncmcur.iCaptionWidth, Ncmstart.iCaptionWidth);
1608  ok( Ncmcur.iScrollWidth == 8,
1609  "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1610  ok( Ncmcur.iScrollHeight == 8,
1611  "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1612  /* test the system metrics with these settings */
1614  /* restore */
1615  rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA),
1616  &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1617  test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1618  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1619  /* test the system metrics with these settings */
1621 }
1622 
1623 static void test_SPI_SETMINIMIZEDMETRICS( void ) /* 44 */
1624 {
1625  BOOL rc;
1626  INT regval;
1627  MINIMIZEDMETRICS lpMm_orig;
1628  MINIMIZEDMETRICS lpMm_new;
1629  MINIMIZEDMETRICS lpMm_cur;
1630 
1631  lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1632  lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1633  lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1634 
1635  trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1636  SetLastError(0xdeadbeef);
1637  rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1638  if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1639  return;
1640  /* Test registry. Note that it is perfectly valid for some fields to
1641  * not be set.
1642  */
1644  ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1645  regval, lpMm_orig.iWidth);
1647  ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1648  regval, lpMm_orig.iHorzGap);
1650  ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1651  regval, lpMm_orig.iVertGap);
1653  ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1654  regval, lpMm_orig.iArrange);
1655  /* set some new values */
1656  lpMm_cur.iWidth = 180;
1657  lpMm_cur.iHorzGap = 1;
1658  lpMm_cur.iVertGap = 1;
1659  lpMm_cur.iArrange = 5;
1660  rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1661  &lpMm_cur, SPIF_UPDATEINIFILE );
1662  if (!test_error_msg(rc,"SPI_SETMINIMIZEDMETRICS")) return;
1663  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1664  /* read them back */
1665  rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1666  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1667  /* and compare */
1668  eq( lpMm_new.iWidth, lpMm_cur.iWidth, "iWidth", "%d" );
1669  eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1670  eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1671  eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1672  /* test registry */
1674  ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1675  regval, lpMm_new.iWidth);
1677  ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1678  regval, lpMm_new.iHorzGap);
1680  ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1681  regval, lpMm_new.iVertGap);
1683  ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1684  regval, lpMm_new.iArrange);
1685  /* test some system metrics */
1687  lpMm_new.iWidth, "iWidth", "%d" );
1689  lpMm_new.iHorzGap, "iHorzGap", "%d" );
1691  lpMm_new.iVertGap, "iVertGap", "%d" );
1693  lpMm_new.iArrange, "iArrange", "%d" );
1694  /* now some really invalid settings */
1695  lpMm_cur.iWidth = -1;
1696  lpMm_cur.iHorzGap = -1;
1697  lpMm_cur.iVertGap = -1;
1698  lpMm_cur.iArrange = - 1;
1699  rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1700  &lpMm_cur, SPIF_UPDATEINIFILE );
1701  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1702  /* read back */
1703  rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1704  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1705  /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1706  eq( lpMm_new.iWidth, 0, "iWidth", "%d" );
1707  eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1708  eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1709  eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1710  /* test registry */
1711  if (0)
1712  {
1713  /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1715  ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1716  regval, lpMm_new.iWidth);
1718  ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1719  regval, lpMm_new.iHorzGap);
1721  ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1722  regval, lpMm_new.iVertGap);
1724  ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1725  regval, lpMm_new.iArrange);
1726  }
1727  /* test some system metrics */
1729  lpMm_new.iWidth, "iWidth", "%d" );
1731  lpMm_new.iHorzGap, "iHorzGap", "%d" );
1733  lpMm_new.iVertGap, "iVertGap", "%d" );
1735  lpMm_new.iArrange, "iArrange", "%d" );
1736  /* restore */
1737  rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1738  &lpMm_orig, SPIF_UPDATEINIFILE );
1739  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1740  /* check that */
1741  rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1742  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1743  eq( lpMm_new.iWidth, lpMm_orig.iWidth, "iWidth", "%d" );
1744  eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1745  eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1746  eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1747 }
1748 
1749 static void test_SPI_SETICONMETRICS( void ) /* 46 */
1750 {
1751  BOOL rc, wrap;
1752  INT spacing;
1753  ICONMETRICSA im_orig;
1754  ICONMETRICSA im_new;
1755  ICONMETRICSA im_cur;
1756  INT regval;
1757 
1758  im_orig.cbSize = sizeof(ICONMETRICSA);
1759  im_new.cbSize = sizeof(ICONMETRICSA);
1760  im_cur.cbSize = sizeof(ICONMETRICSA);
1761 
1762  trace("testing SPI_{GET,SET}ICONMETRICS\n");
1763  SetLastError(0xdeadbeef);
1764  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1765  if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1766  return;
1767  /* check some registry values */
1769  ok( regval==im_orig.iHorzSpacing,
1770  "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1772  ok( regval==im_orig.iVertSpacing,
1773  "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1775  if( regval != im_orig.iTitleWrap)
1777  ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1778 
1779  /* change everything without creating something invalid ( Win9x would ignore
1780  * an invalid font for instance) */
1781  im_cur = im_orig;
1782  im_cur.iHorzSpacing += 10;
1783  im_cur.iVertSpacing += 6;
1784  im_cur.iTitleWrap = !im_cur.iTitleWrap;
1785  im_cur.lfFont.lfHeight += 1;
1786  im_cur.lfFont.lfWidth += 2;
1787  im_cur.lfFont.lfEscapement = 1;
1788  im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1789  im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1790  im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1791  im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1792  im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1793  im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1795  im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1796  im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1797  im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ?
1799  if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1800  strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1801  else
1802  strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1803 
1804  rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1805  if (!test_error_msg(rc,"SPI_SETICONMETRICS")) return;
1806  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1807 
1808  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1809  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1810  /* test GET <-> SETICONMETRICS */
1811  eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1812  eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1813  eq( im_new.iTitleWrap, im_cur.iTitleWrap, "iTitleWrap", "%d" );
1814  eq( im_new.lfFont.lfHeight, im_cur.lfFont.lfHeight, "lfHeight", "%d" );
1815  eq( im_new.lfFont.lfWidth, im_cur.lfFont.lfWidth, "lfWidth", "%d" );
1816  eq( im_new.lfFont.lfEscapement, im_cur.lfFont.lfEscapement, "lfEscapement", "%d" );
1817  eq( im_new.lfFont.lfWeight, im_cur.lfFont.lfWeight, "lfWeight", "%d" );
1818  eq( im_new.lfFont.lfItalic, im_cur.lfFont.lfItalic, "lfItalic", "%d" );
1819  eq( im_new.lfFont.lfStrikeOut, im_cur.lfFont.lfStrikeOut, "lfStrikeOut", "%d" );
1820  eq( im_new.lfFont.lfUnderline, im_cur.lfFont.lfUnderline, "lfUnderline", "%d" );
1821  eq( im_new.lfFont.lfCharSet, im_cur.lfFont.lfCharSet, "lfCharSet", "%d" );
1822  eq( im_new.lfFont.lfOutPrecision, im_cur.lfFont.lfOutPrecision, "lfOutPrecision", "%d" );
1823  eq( im_new.lfFont.lfClipPrecision, im_cur.lfFont.lfClipPrecision, "lfClipPrecision", "%d" );
1824  eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1825  eq( im_new.lfFont.lfQuality, im_cur.lfFont.lfQuality, "lfQuality", "%d" );
1826  ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1827  "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1828  im_cur.lfFont.lfFaceName);
1829  /* test some system metrics */
1831  im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1833  im_new.iVertSpacing, "iVertSpacing", "%d" );
1834  /* check some registry values */
1836  ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1838  ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1840  if( regval != im_cur.iTitleWrap)
1842  ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1843  /* test some values from other SPI_GETxxx calls */
1844  rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1845  ok( rc && spacing == im_cur.iHorzSpacing,
1846  "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1847  spacing, im_cur.iHorzSpacing);
1848  rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1849  ok( rc && spacing == im_cur.iVertSpacing,
1850  "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1851  spacing, im_cur.iVertSpacing);
1853  ok( rc && wrap == im_cur.iTitleWrap,
1854  "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1855  wrap, im_cur.iTitleWrap);
1856  /* restore old values */
1857  rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1858  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1859 
1860  rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1861  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1862 
1863  eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1864  eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1865  eq( im_new.iTitleWrap, im_orig.iTitleWrap, "iTitleWrap", "%d" );
1866 }
1867 
1868 static void test_SPI_SETWORKAREA( void ) /* 47 */
1869 {
1870  BOOL rc;
1871  RECT old_area;
1872  RECT area;
1873  RECT curr_val;
1874 
1875  trace("testing SPI_{GET,SET}WORKAREA\n");
1876  SetLastError(0xdeadbeef);
1877  rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1878  if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1879  return;
1880 
1881  /* Modify the work area only minimally as this causes the icons that
1882  * fall outside it to be moved around thus requiring the user to
1883  * reposition them manually one by one.
1884  * Changing the work area by just one pixel should make this occurrence
1885  * reasonably unlikely.
1886  */
1887  SetRect(&curr_val, old_area.left, old_area.top, old_area.right - 1, old_area.bottom - 1);
1888  rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1890  if (!test_error_msg(rc,"SPI_SETWORKAREA")) return;
1891  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1892  rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1893  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1894  if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1895  test_change_message( SPI_SETWORKAREA, 0);
1896  eq( area.left, curr_val.left, "left", "%d" );
1897  eq( area.top, curr_val.top, "top", "%d" );
1898  /* size may be rounded */
1899  ok( area.right >= curr_val.right - 16 && area.right < curr_val.right + 16,
1900  "right: got %d instead of %d\n", area.right, curr_val.right );
1901  ok( area.bottom >= curr_val.bottom - 16 && area.bottom < curr_val.bottom + 16,
1902  "bottom: got %d instead of %d\n", area.bottom, curr_val.bottom );
1903  curr_val = area;
1904  rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1906  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1907  rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1908  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1909  if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1910  test_change_message( SPI_SETWORKAREA, 0 );
1911  eq( area.left, old_area.left, "left", "%d" );
1912  eq( area.top, old_area.top, "top", "%d" );
1913  /* size may be rounded */
1914  ok( area.right >= old_area.right - 16 && area.right < old_area.right + 16,
1915  "right: got %d instead of %d\n", area.right, old_area.right );
1916  ok( area.bottom >= old_area.bottom - 16 && area.bottom < old_area.bottom + 16,
1917  "bottom: got %d instead of %d\n", area.bottom, old_area.bottom );
1918 }
1919 
1920 static void test_SPI_SETSHOWSOUNDS( void ) /* 57 */
1921 {
1922  BOOL rc;
1923  BOOL old_b;
1924  const UINT vals[]={TRUE,FALSE};
1925  unsigned int i;
1926 
1927  trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1928  SetLastError(0xdeadbeef);
1929  rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1930  if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1931  return;
1932 
1933  for (i=0;i<ARRAY_SIZE(vals);i++)
1934  {
1935  UINT v;
1936 
1939  if (!test_error_msg(rc,"SPI_SETSHOWSOUNDS")) return;
1940  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1944  vals[i] ? "1" : "0" );
1945 
1947  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1948  eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1949  eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1950  "SM_SHOWSOUNDS", "%d" );
1951  }
1952 
1954  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1955 }
1956 
1957 static void test_SPI_SETKEYBOARDPREF( void ) /* 69 */
1958 {
1959  BOOL rc;
1960  BOOL old_b;
1961  const UINT vals[]={TRUE,FALSE};
1962  unsigned int i;
1963 
1964  trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1965  SetLastError(0xdeadbeef);
1966  rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1967  if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1968  return;
1969 
1970  for (i=0;i<ARRAY_SIZE(vals);i++)
1971  {
1972  BOOL v;
1973 
1974  rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1976  if (!test_error_msg(rc,"SPI_SETKEYBOARDPREF")) return;
1977  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1978  test_change_message( SPI_SETKEYBOARDPREF, 1 );
1981  vals[i] ? "1" : "0" );
1982 
1983  rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1984  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1985  eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1986  }
1987 
1988  rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1989  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1990 }
1991 
1992 static void test_SPI_SETSCREENREADER( void ) /* 71 */
1993 {
1994  BOOL rc;
1995  BOOL old_b;
1996  const UINT vals[]={TRUE,FALSE};
1997  unsigned int i;
1998 
1999  trace("testing SPI_{GET,SET}SCREENREADER\n");
2000  SetLastError(0xdeadbeef);
2001  rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
2002  if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
2003  return;
2004 
2005  for (i=0;i<ARRAY_SIZE(vals);i++)
2006  {
2007  BOOL v;
2008 
2009  rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
2011  if (!test_error_msg(rc,"SPI_SETSCREENREADER")) return;
2012  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2013  test_change_message( SPI_SETSCREENREADER, 1 );
2016  vals[i] ? "1" : "0" );
2017 
2018  rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
2019  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2020  eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
2021  }
2022 
2023  rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
2024  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2025 }
2026 
2027 static void test_SPI_SETFONTSMOOTHING( void ) /* 75 */
2028 {
2029  BOOL rc;
2030  BOOL old_b;
2031  DWORD old_type, old_contrast, old_orient;
2032  const UINT vals[]={0xffffffff,0,1,2};
2033  unsigned int i;
2034 
2035  trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
2036  SetLastError(0xdeadbeef);
2037  rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
2038  if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
2039  return;
2040  SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &old_type, 0 );
2041  SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &old_contrast, 0 );
2042  SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &old_orient, 0 );
2043 
2044  for (i=0;i<ARRAY_SIZE(vals);i++)
2045  {
2046  UINT v;
2047 
2048  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
2050  if (!test_error_msg(rc,"SPI_SETFONTSMOOTHING")) return;
2051  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2052  test_change_message( SPI_SETFONTSMOOTHING, 0 );
2055  vals[i] ? "2" : "0" );
2056 
2057  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, 0, UlongToPtr(vals[i]),
2059  if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGTYPE")) return;
2060  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2061  test_change_message( SPI_SETFONTSMOOTHINGTYPE, 0 );
2064 
2065  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, 0, UlongToPtr(vals[i]),
2067  if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGCONTRAST")) return;
2068  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2069  test_change_message( SPI_SETFONTSMOOTHINGCONTRAST, 0 );
2072 
2073  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, 0, UlongToPtr(vals[i]),
2075  if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGORIENTATION")) return;
2076  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2077  test_change_message( SPI_SETFONTSMOOTHINGORIENTATION, 0 );
2080 
2081  rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
2082  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2083  eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
2084 
2085  rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &v, 0 );
2086  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2087  ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2088 
2089  rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &v, 0 );
2090  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2091  ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2092 
2093  rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &v, 0 );
2094  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2095  ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2096  }
2097 
2098  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
2099  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2100  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, old_type, 0, SPIF_UPDATEINIFILE );
2101  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2102  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, old_contrast, 0, SPIF_UPDATEINIFILE );
2103  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2104  rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, old_orient, 0, SPIF_UPDATEINIFILE );
2105  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2106 }
2107 
2108 static void test_SPI_SETLOWPOWERACTIVE( void ) /* 85 */
2109 {
2110  BOOL rc;
2111  BOOL old_b;
2112  const UINT vals[]={TRUE,FALSE};
2113  unsigned int i;
2114 
2115  trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
2116  SetLastError(0xdeadbeef);
2117  rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
2118  if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
2119  return;
2120 
2121  for (i=0;i<ARRAY_SIZE(vals);i++)
2122  {
2123  UINT v;
2124 
2125  rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
2127  if (!test_error_msg(rc,"SPI_SETLOWPOWERACTIVE")) return;
2128  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2129  test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
2132  vals[i] ? "1" : "0" );
2133 
2134  /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
2135  v = 0xdeadbeef;
2136  rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
2137  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2138  ok(v == vals[i] || v == 0, /* win2k3 */
2139  "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2140  }
2141 
2142  rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2143  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2144 }
2145 
2146 static void test_SPI_SETPOWEROFFACTIVE( void ) /* 86 */
2147 {
2148  BOOL rc;
2149  BOOL old_b;
2150  const UINT vals[]={TRUE,FALSE};
2151  unsigned int i;
2152 
2153  trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
2154  SetLastError(0xdeadbeef);
2155  rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
2156  if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
2157  return;
2158 
2159  for (i=0;i<ARRAY_SIZE(vals);i++)
2160  {
2161  UINT v;
2162 
2163  rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
2165  if (!test_error_msg(rc,"SPI_SETPOWEROFFACTIVE")) return;
2166  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2167  test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
2170  vals[i] ? "1" : "0" );
2171 
2172  /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
2173  v = 0xdeadbeef;
2174  rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
2175  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2176  ok(v == vals[i] || v == 0, /* win2k3 */
2177  "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2178  }
2179 
2180  rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2181  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2182 }
2183 
2184 static void test_SPI_SETSNAPTODEFBUTTON( void ) /* 95 */
2185 {
2186  BOOL rc;
2187  BOOL old_b;
2188  const UINT vals[]={TRUE,FALSE};
2189  unsigned int i;
2190 
2191  trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
2192  SetLastError(0xdeadbeef);
2193  rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
2194  if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
2195  return;
2196 
2197  for (i=0;i<ARRAY_SIZE(vals);i++)
2198  {
2199  UINT v;
2200 
2201  rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
2203  if (!test_error_msg(rc,"SPI_SETSNAPTODEFBUTTON")) return;
2204  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2205  test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
2208  vals[i] ? "1" : "0" );
2209 
2210  rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2211  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2212  eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2213  }
2214 
2215  rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2216  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2217 }
2218 
2219 static void test_SPI_SETMOUSEHOVERWIDTH( void ) /* 99 */
2220 {
2221  BOOL rc;
2222  UINT old_width;
2223  const UINT vals[]={0,32767};
2224  unsigned int i;
2225 
2226  trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2227  SetLastError(0xdeadbeef);
2228  rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2229  if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2230  return;
2231 
2232  for (i=0;i<ARRAY_SIZE(vals);i++)
2233  {
2234  UINT v;
2235  char buf[10];
2236 
2237  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2239  if (!test_error_msg(rc,"SPI_SETMOUSEHOVERWIDTH")) return;
2240  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2241  test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2242  sprintf( buf, "%d", vals[i] );
2245 
2246  SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2247  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2248  eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2249  }
2250 
2251  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2253  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2254 }
2255 
2256 static void test_SPI_SETMOUSEHOVERHEIGHT( void ) /* 101 */
2257 {
2258  BOOL rc;
2259  UINT old_height;
2260  const UINT vals[]={0,32767};
2261  unsigned int i;
2262 
2263  trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2264  SetLastError(0xdeadbeef);
2265  rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2266  if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2267  return;
2268 
2269  for (i=0;i<ARRAY_SIZE(vals);i++)
2270  {
2271  UINT v;
2272  char buf[10];
2273 
2274  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2276  if (!test_error_msg(rc,"SPI_SETMOUSEHOVERHEIGHT")) return;
2277  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2278  test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2279  sprintf( buf, "%d", vals[i] );
2282 
2283  SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2284  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2285  eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2286  }
2287 
2288  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2290  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2291 }
2292 
2293 static void test_SPI_SETMOUSEHOVERTIME( void ) /* 103 */
2294 {
2295  BOOL rc;
2296  UINT old_time;
2297 
2298  /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2299  * defaulted to a value of 10 automatically.
2300  */
2301  const UINT vals[]={10,32767};
2302  unsigned int i;
2303 
2304  trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2305  SetLastError(0xdeadbeef);
2306  rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2307  if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2308  return;
2309 
2310  for (i=0;i<ARRAY_SIZE(vals);i++)
2311  {
2312  UINT v;
2313  char buf[10];
2314 
2315  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2317  if (!test_error_msg(rc,"SPI_SETMOUSEHOVERTIME")) return;
2318  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2319  test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2320  sprintf( buf, "%d", vals[i] );
2323 
2324  SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2325  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2326  eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2327  }
2328 
2329  rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2331  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2332 }
2333 
2334 static void test_SPI_SETWHEELSCROLLLINES( void ) /* 105 */
2335 {
2336  BOOL rc;
2337  UINT old_lines;
2338  const UINT vals[]={0,32767};
2339  unsigned int i;
2340 
2341  trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2342  SetLastError(0xdeadbeef);
2343  rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2344 
2345  /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2346  if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2347  return;
2348 
2349  for (i=0;i<ARRAY_SIZE(vals);i++)
2350  {
2351  UINT v;
2352  char buf[10];
2353 
2356  if (!test_error_msg(rc,"SPI_SETWHEELSCROLLLINES")) return;
2357  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2359  sprintf( buf, "%d", vals[i] );
2362 
2363  SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2364  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2365  eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2366  }
2367 
2370  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2371 }
2372 
2373 static void test_SPI_SETMENUSHOWDELAY( void ) /* 107 */
2374 {
2375  BOOL rc;
2376  UINT old_delay;
2377  const UINT vals[]={0,32767};
2378  unsigned int i;
2379 
2380  trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2381  SetLastError(0xdeadbeef);
2382  rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2383 
2384  /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2385  if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2386  return;
2387 
2388  for (i=0;i<ARRAY_SIZE(vals);i++)
2389  {
2390  UINT v;
2391  char buf[10];
2392 
2393  rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2395  if (!test_error_msg(rc,"SPI_SETMENUSHOWDELAY")) return;
2396  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2397  test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2398  sprintf( buf, "%d", vals[i] );
2401 
2402  SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2403  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2404  eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2405  }
2406 
2407  rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2409  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2410 }
2411 
2412 static void test_SPI_SETWHEELSCROLLCHARS( void ) /* 108 */
2413 {
2414  BOOL rc;
2415  UINT old_chars;
2416  const UINT vals[]={32767,0};
2417  unsigned int i;
2418 
2419  trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2420  SetLastError(0xdeadbeef);
2421  rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2422 
2423  /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2424  if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2425  return;
2426 
2427  for (i=0;i<ARRAY_SIZE(vals);i++)
2428  {
2429  UINT v;
2430  char buf[10];
2431 
2432  rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2434  if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2435  test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2436  sprintf( buf, "%d", vals[i] );
2439 
2440  SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2441  ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2442  eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2443  }
2444 
2445  rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2447  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2448 }
2449 
2450 static void test_SPI_SETWALLPAPER( void ) /* 115 */
2451 {
2452  BOOL rc;
2453  char oldval[260];
2454  char newval[260];
2455 
2456  trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2457  SetLastError(0xdeadbeef);
2458  rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2459  if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2460  return;
2461 
2462  strcpy(newval, "");
2464  if (!test_error_msg(rc,"SPI_SETDESKWALLPAPER")) return;
2465  ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
2467 
2469  ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2470 
2472 }
2473 
2474 static void test_WM_DISPLAYCHANGE(void)
2475 {
2476  DEVMODEA mode, startmode;
2477  int start_bpp, last_set_bpp = 0;
2478  int test_bpps[] = {8, 16, 24, 32}, i;
2479  LONG change_ret;
2480  DWORD wait_ret;
2481 
2482  if (!pChangeDisplaySettingsExA)
2483  {
2484  win_skip("ChangeDisplaySettingsExA is not available\n");
2485  return;
2486  }
2487 
2489 
2490  memset(&startmode, 0, sizeof(startmode));
2491  startmode.dmSize = sizeof(startmode);
2493  start_bpp = startmode.dmBitsPerPel;
2494 
2496 
2497  for(i = 0; i < ARRAY_SIZE(test_bpps); i++) {
2498  last_bpp = -1;
2499 
2500  memset(&mode, 0, sizeof(mode));
2501  mode.dmSize = sizeof(mode);
2503  mode.dmBitsPerPel = test_bpps[i];
2504  mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2505  mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2506 
2507  change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2509  change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2510  /* Wait quite long for the message, screen setting changes can take some time */
2511  if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2512  wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2513  /* we may not get a notification if nothing changed */
2514  if (wait_ret == WAIT_TIMEOUT && !last_set_bpp && start_bpp == test_bpps[i])
2515  continue;
2516  ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2517  }
2519 
2520  if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2521  skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2522  ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despite mode change failure\n", last_bpp);
2523  continue;
2524  }
2525 
2526  todo_wine_if(start_bpp != test_bpps[i]) {
2527  ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2528  }
2529  last_set_bpp = test_bpps[i];
2530  }
2531 
2532  if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2533  memset(&mode, 0, sizeof(mode));
2534  mode.dmSize = sizeof(mode);
2536  mode.dmBitsPerPel = start_bpp;
2537  mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2538  mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2539 
2541  change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2545  displaychange_sem = 0;
2546  }
2547 
2549 }
2550 
2551 /*
2552  * Registry entries for the system parameters.
2553  * Names are created by 'SET' flags names.
2554  * We assume that corresponding 'GET' entries use the same registry keys.
2555  */
2557 {
2558  test_SPI_SETBEEP(); /* 1 */
2559  test_SPI_SETMOUSE(); /* 4 */
2560  test_SPI_SETBORDER(); /* 6 */
2561  test_SPI_SETKEYBOARDSPEED(); /* 10 */
2562  test_SPI_ICONHORIZONTALSPACING(); /* 13 */
2563  test_SPI_SETSCREENSAVETIMEOUT(); /* 14 */
2564  test_SPI_SETSCREENSAVEACTIVE(); /* 17 */
2565  test_SPI_SETGRIDGRANULARITY(); /* 19 */
2566  test_SPI_SETKEYBOARDDELAY(); /* 23 */
2567  test_SPI_ICONVERTICALSPACING(); /* 24 */
2568  test_SPI_SETICONTITLEWRAP(); /* 26 */
2569  test_SPI_SETMENUDROPALIGNMENT(); /* 28 */
2570  test_SPI_SETDOUBLECLKWIDTH(); /* 29 */
2571  test_SPI_SETDOUBLECLKHEIGHT(); /* 30 */
2572  test_SPI_SETDOUBLECLICKTIME(); /* 32 */
2573  test_SPI_SETMOUSEBUTTONSWAP(); /* 33 */
2574  test_SPI_SETFASTTASKSWITCH(); /* 36 */
2575  test_SPI_SETDRAGFULLWINDOWS(); /* 37 */
2576  /* test_WM_DISPLAYCHANGE seems to be somewhat buggy on
2577  * some versions of Windows (Vista, Win2k8, Win7B) in that
2578  * not all metrics are properly restored. Problems are
2579  * SM_CXMAXTRACK, SM_CYMAXTRACK
2580  * Fortunately setting the Non-Client metrics like in
2581  * test_SPI_SETNONCLIENTMETRICS will correct this. That is why
2582  * we do the DISPLAY change now... */
2584  test_SPI_SETNONCLIENTMETRICS(); /* 42 */
2585  test_SPI_SETMINIMIZEDMETRICS(); /* 44 */
2586  test_SPI_SETICONMETRICS(); /* 46 */
2587  test_SPI_SETWORKAREA(); /* 47 */
2588  test_SPI_SETSHOWSOUNDS(); /* 57 */
2589  test_SPI_SETKEYBOARDPREF(); /* 69 */
2590  test_SPI_SETSCREENREADER(); /* 71 */
2591  test_SPI_SETFONTSMOOTHING(); /* 75 */
2592  test_SPI_SETLOWPOWERACTIVE(); /* 85 */
2593  test_SPI_SETPOWEROFFACTIVE(); /* 86 */
2594  test_SPI_SETSNAPTODEFBUTTON(); /* 95 */
2595  test_SPI_SETMOUSEHOVERWIDTH(); /* 99 */
2596  test_SPI_SETMOUSEHOVERHEIGHT(); /* 101 */
2597  test_SPI_SETMOUSEHOVERTIME(); /* 103 */
2598  test_SPI_SETWHEELSCROLLLINES(); /* 105 */
2599  test_SPI_SETMENUSHOWDELAY(); /* 107 */
2600  test_SPI_SETWHEELSCROLLCHARS(); /* 108 */
2601  test_SPI_SETWALLPAPER(); /* 115 */
2602 
2603 
2604  SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2605  return 0;
2606 }
2607 
2608 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2609  * icon metrics and minimized metrics.
2610  */
2611 
2612 /* copied from wine's GdiGetCharDimensions, which is not available on most
2613  * windows versions */
2615 {
2616  SIZE sz;
2617  static const CHAR alphabet[] = {
2618  'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2619  'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2620  'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2621 
2622  if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2623 
2624  if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2625 
2626  if (height) *height = sz.cy;
2627  return (sz.cx / 26 + 1) / 2;
2628 }
2629 
2630 /* get text metrics and/or "average" char width of the specified logfont
2631  * for the specified dc */
2632 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2633 {
2634  HFONT hfont, hfontsav;
2635  TEXTMETRICA tm;
2636  if( !ptm) ptm = &tm;
2637  hfont = CreateFontIndirectA( plf);
2638  if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2639  ptm->tmHeight = -1;
2640  if( psz) *psz = 10;
2641  if( hfont) DeleteObject( hfont);
2642  return;
2643  }
2644  GetTextMetricsA( hdc, ptm);
2645  if( psz)
2646  if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2647  *psz = 10;
2648  SelectObject( hdc, hfontsav);
2649  DeleteObject( hfont);
2650 }
2651 
2652 static int gsm_error_ctr;
2653 
2654 #define ok_gsm( i, e)\
2655 {\
2656  int exp = (e);\
2657  int act = GetSystemMetrics( (i));\
2658  if( exp != act) gsm_error_ctr++;\
2659  ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2660 }
2661 #define ok_gsm_2( i, e1, e2)\
2662 {\
2663  int exp1 = (e1);\
2664  int exp2 = (e2);\
2665  int act = GetSystemMetrics( (i));\
2666  if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2667  ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2668 }
2669 #define ok_gsm_3( i, e1, e2, e3)\
2670 {\
2671  int exp1 = (e1);\
2672  int exp2 = (e2);\
2673  int exp3 = (e3);\
2674  int act = GetSystemMetrics( (i));\
2675  if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2676  ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2677 }
2678 
2680 {
2681  return lstrcmpiA(elf->lfFaceName, (const char *)lparam);
2682 }
2683 
2684 static BOOL is_font_enumerated(const char *name)
2685 {
2686  HDC hdc = CreateCompatibleDC(0);
2687  BOOL ret = FALSE;
2688 
2690  ret = TRUE;
2691 
2692  DeleteDC(hdc);
2693  return ret;
2694 }
2695 
2696 static int get_cursor_size( int size )
2697 {
2698  /* only certain sizes are allowed for cursors */
2699  if (size >= 64) return 64;
2700  if (size >= 48) return 48;
2701  return 32;
2702 }
2703 
2704 static void test_GetSystemMetrics( void)
2705 {
2706  TEXTMETRICA tmMenuFont;
2707  UINT IconSpacing, IconVerticalSpacing;
2708  BOOL rc;
2709 
2710  HDC hdc = CreateICA( "Display", 0, 0, 0);
2711  UINT avcwCaption;
2712  INT CaptionWidthfromreg, smicon, broken_val;
2713  MINIMIZEDMETRICS minim;
2714  NONCLIENTMETRICSA ncm;
2715  SIZE screen;
2716 
2717  assert(sizeof(ncm) == 344);
2718 
2719  ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2720  rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2721  ok(rc, "SystemParametersInfoA failed\n");
2722 
2723  ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) - 1;
2724  rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2725  ok(!rc, "SystemParametersInfoA should fail\n");
2726 
2727  ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) + 1;
2728  SetLastError(0xdeadbeef);
2729  rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2730  ok(!rc, "SystemParametersInfoA should fail\n");
2731 
2732  ncm.cbSize = sizeof(ncm); /* Vista added padding */
2733  SetLastError(0xdeadbeef);
2734  ncm.iPaddedBorderWidth = 0xcccc;
2735  rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2736  ok(rc || broken(!rc) /* before Vista */, "SystemParametersInfoA failed\n");
2737  if (rc) ok( ncm.iPaddedBorderWidth == 0, "wrong iPaddedBorderWidth %u\n", ncm.iPaddedBorderWidth );
2738 
2739  minim.cbSize = sizeof( minim);
2740  ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2741  SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2742  rc = SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2743  if( !rc) {
2744  win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
2745  return;
2746  }
2747 
2748  ok(is_font_enumerated(ncm.lfCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfCaptionFont.lfFaceName);
2749  ok(is_font_enumerated(ncm.lfSmCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfSmCaptionFont.lfFaceName);
2750  ok(is_font_enumerated(ncm.lfMenuFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMenuFont.lfFaceName);
2751  ok(is_font_enumerated(ncm.lfStatusFont.lfFaceName), "font %s should be enumerated\n", ncm.lfStatusFont.lfFaceName);
2752  ok(is_font_enumerated(ncm.lfMessageFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMessageFont.lfFaceName);
2753 
2754  /* CaptionWidth from the registry may have different value of iCaptionWidth
2755  * from the non client metrics (observed on WinXP) */
2756  CaptionWidthfromreg = metricfromreg(
2757  "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2758  get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2759  get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2760  /* FIXME: use icon metric */
2761  if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2762  IconVerticalSpacing = 0;
2763  if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2764  IconSpacing = 0;
2765  /* reset error counters */
2766  gsm_error_ctr = 0;
2767 
2768  /* the tests: */
2769 
2770  /* SM_CXSCREEN, cannot test these two */
2771  /* SM_CYSCREEN */
2772  ok_gsm( SM_CXVSCROLL, ncm.iScrollWidth);
2773  ok_gsm( SM_CYHSCROLL, ncm.iScrollWidth);
2774  ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2775  ok_gsm( SM_CXBORDER, 1);
2776  ok_gsm( SM_CYBORDER, 1);
2777  ok_gsm( SM_CXDLGFRAME, 3);
2778  ok_gsm( SM_CYDLGFRAME, 3);
2779  ok_gsm( SM_CYVTHUMB, ncm.iScrollHeight);
2780  ok_gsm( SM_CXHTHUMB, ncm.iScrollHeight);
2781  /* These don't depend on the Shell Icon Size registry value */
2786  ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2791  /* SM_CYKANJIWINDOW */
2792  /* SM_MOUSEPRESENT */
2793  ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2794  ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2795  /* SM_DEBUG */
2796  /* SM_SWAPBUTTON */
2797  /* SM_RESERVED1 */
2798  /* SM_RESERVED2 */
2799  /* SM_RESERVED3 */
2800  /* SM_RESERVED4 */
2801  ok_gsm( SM_CXMIN, 3 * max( CaptionWidthfromreg >= 0 ? CaptionWidthfromreg : ncm.iCaptionWidth, 8) +
2802  GetSystemMetrics( SM_CYSIZE) + 4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2806  ncm.iCaptionWidth, /* classic/standard windows style */
2807  GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2808  );
2809  ok_gsm( SM_CYSIZE, ncm.iCaptionHeight);
2810  ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2811  ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2814  /* SM_CXDOUBLECLK */
2815  /* SM_CYDOUBLECLK */
2816  if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2817  if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2818  /* SM_MENUDROPALIGNMENT */
2819  /* SM_PENWINDOWS */
2820  /* SM_DBCSENABLED */
2821  /* SM_CMOUSEBUTTONS */
2822  /* SM_SECURE */
2823  ok_gsm( SM_CXEDGE, 2);
2824  ok_gsm( SM_CYEDGE, 2);
2825  /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2828 
2829  smicon = MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI );
2830  if (!pIsProcessDPIAware || pIsProcessDPIAware())
2831  smicon = max( min( smicon, CaptionWidthfromreg - 2), 4 ) & ~1;
2832  todo_wine_if( real_dpi == dpi && smicon != (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI) & ~1) )
2833  {
2834  broken_val = (min( ncm.iCaptionHeight, CaptionWidthfromreg ) - 2) & ~1;
2835  broken_val = min( broken_val, 20 );
2836 
2837  if (smicon == 4)
2838  {
2839  ok_gsm_2( SM_CXSMICON, smicon, 6 );
2840  ok_gsm_2( SM_CYSMICON, smicon, 6 );
2841  }
2842  else if (smicon < broken_val)
2843  {
2844  ok_gsm_2( SM_CXSMICON, smicon, broken_val );
2845  ok_gsm_2( SM_CYSMICON, smicon, broken_val );
2846  }
2847  else
2848  {
2849  ok_gsm( SM_CXSMICON, smicon );
2850  ok_gsm( SM_CYSMICON, smicon );
2851  }
2852  }
2853 
2854  ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2856  ncm.iSmCaptionWidth, /* classic/standard windows style */
2857  GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2858  smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2859  does not change it */
2860  );
2862  ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2863  ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2864  /* SM_ARRANGE */
2865  ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2869  if (!screen.cx || !screen.cy) /* not supported on NT4 */
2870  {
2873  }
2875  screen.cx - 4 + 2 * GetSystemMetrics(SM_CXFRAME), /* Vista */
2876  screen.cx + 2 * GetSystemMetrics(SM_CXFRAME)); /* Win8 */
2878  screen.cy - 4 + 2 * GetSystemMetrics(SM_CYFRAME), /* Vista */
2879  screen.cy + 2 * GetSystemMetrics(SM_CYFRAME)); /* Win8 */
2880  /* the next two cannot really be tested as they depend on (application)
2881  * toolbars */
2882  /* SM_CXMAXIMIZED */
2883  /* SM_CYMAXIMIZED */
2884  /* SM_NETWORK */
2885  /* */
2886  /* */
2887  /* */
2888  /* SM_CLEANBOOT */
2889  /* SM_CXDRAG */
2890  /* SM_CYDRAG */
2891  /* SM_SHOWSOUNDS */
2893  ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2895  ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2896  /* SM_SLOWMACHINE */
2897  /* SM_MIDEASTENABLED */
2898  /* SM_MOUSEWHEELPRESENT */
2899  /* SM_XVIRTUALSCREEN */
2900  /* SM_YVIRTUALSCREEN */
2901  /* SM_CXVIRTUALSCREEN */
2902  /* SM_CYVIRTUALSCREEN */
2903  /* SM_CMONITORS */
2904  /* SM_SAMEDISPLAYFORMAT */
2905  /* SM_IMMENABLED */
2906  /* SM_CXFOCUSBORDER */
2907  /* SM_CYFOCUSBORDER */
2908  /* SM_TABLETPC */
2909  /* SM_MEDIACENTER */
2910  /* SM_CMETRICS */
2911  /* end of tests */
2912  if( gsm_error_ctr ) { /* if any errors where found */
2913  trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2914  ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2915  trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2916  ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2917  trace( "Captionfontchar width %d MenuFont %d,%d CaptionWidth from registry: %d screen %d,%d\n",
2918  avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidthfromreg, screen.cx, screen.cy);
2919  }
2920 
2921  DeleteDC(hdc);
2922 }
2923 
2924 static void compare_font( const LOGFONTW *lf1, const LOGFONTW *lf2, int dpi, int custom_dpi, int line )
2925 {
2926  ok_(__FILE__,line)( lf1->lfHeight == MulDiv( lf2->lfHeight, dpi, custom_dpi ),
2927  "wrong lfHeight %d vs %d\n", lf1->lfHeight, lf2->lfHeight );
2928  ok_(__FILE__,line)( abs( lf1->lfWidth - MulDiv( lf2->lfWidth, dpi, custom_dpi )) <= 1,
2929  "wrong lfWidth %d vs %d\n", lf1->lfWidth, lf2->lfWidth );
2930  ok_(__FILE__,line)( !memcmp( &lf1->lfEscapement, &lf2->lfEscapement,
2931  offsetof( LOGFONTW, lfFaceName ) - offsetof( LOGFONTW, lfEscapement )),
2932  "font differs\n" );
2933  ok_(__FILE__,line)( !lstrcmpW( lf1->lfFaceName, lf2->lfFaceName ), "wrong face name %s vs %s\n",
2935 }
2936 
2937 static void test_metrics_for_dpi( int custom_dpi )
2938 {
2939  int i, val;
2940  NONCLIENTMETRICSW ncm1, ncm2;
2941  ICONMETRICSW im1, im2;
2942  LOGFONTW lf1, lf2;
2943  BOOL ret;
2944 
2945  if (!pSystemParametersInfoForDpi)
2946  {
2947  win_skip( "custom dpi metrics not supported\n" );
2948  return;
2949  }
2950 
2951  ncm1.cbSize = sizeof(ncm1);
2952  ret = SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof(ncm1), &ncm1, FALSE );
2953  ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
2954  ncm2.cbSize = sizeof(ncm2);
2955  ret = pSystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, sizeof(ncm2), &ncm2, FALSE, custom_dpi );
2956  ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
2957 
2958  for (i = 0; i < 92; i++)
2959  {
2960  int ret1 = GetSystemMetrics( i );
2961  int ret2 = pGetSystemMetricsForDpi( i, custom_dpi );
2962  switch (i)
2963  {
2964  case SM_CXVSCROLL:
2965  case SM_CYHSCROLL:
2966  case SM_CYVTHUMB:
2967  case SM_CXHTHUMB:
2968  case SM_CXICON:
2969  case SM_CYICON:
2970  case SM_CYVSCROLL:
2971  case SM_CXHSCROLL:
2972  case SM_CYSIZE:
2973  case SM_CXICONSPACING:
2974  case SM_CYICONSPACING:
2975  case SM_CXSMSIZE:
2976  case SM_CYSMSIZE:
2977  case SM_CYMENUSIZE:
2978  ok( ret1 == MulDiv( ret2, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2979  break;
2980  case SM_CXSIZE:
2981  ok( ret1 == ncm1.iCaptionWidth && ret2 == ncm2.iCaptionWidth,
2982  "%u: wrong value %u vs %u caption %u vs %u\n",
2983  i, ret1, ret2, ncm1.iCaptionWidth, ncm2.iCaptionWidth );
2984  break;
2985  case SM_CXCURSOR:
2986  case SM_CYCURSOR:
2987  val = MulDiv( 32, custom_dpi, USER_DEFAULT_SCREEN_DPI );
2988  if (val < 48) val = 32;
2989  else if (val < 64) val = 48;
2990  else val = 64;
2991  ok( val == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2992  break;
2993  case SM_CYCAPTION:
2994  case SM_CYSMCAPTION:
2995  case SM_CYMENU:
2996  ok( ret1 - 1 == MulDiv( ret2 - 1, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
2997  break;
2998  case SM_CXMENUSIZE:
2999  ok( ret1 / 8 == MulDiv( ret2, dpi, custom_dpi ) / 8, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
3000  break;
3001  case SM_CXFRAME:
3002  case SM_CYFRAME:
3003  ok( ret1 == ncm1.iBorderWidth + 3 && ret2 == ncm2.iBorderWidth + 3,
3004  "%u: wrong value %u vs %u borders %u+%u vs %u+%u\n", i, ret1, ret2,
3005  ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
3006  break;
3007  case SM_CXSMICON:
3008  case SM_CYSMICON:
3009  ok( ret1 == (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI ) & ~1) &&
3010  ret2 == (MulDiv( 16, custom_dpi, USER_DEFAULT_SCREEN_DPI ) & ~1),
3011  "%u: wrong value %u vs %u\n", i, ret1, ret2 );
3012  break;
3013  case SM_CXMENUCHECK:
3014  case SM_CYMENUCHECK:
3015  ok( ret1 == ((get_tmheightW( &ncm1.lfMenuFont, 1 ) - 1) | 1) &&
3016  ret2 == ((get_tmheightW( &ncm2.lfMenuFont, 1 ) - 1) | 1),
3017  "%u: wrong value %u vs %u font %u vs %u\n", i, ret1, ret2,
3018  get_tmheightW( &ncm1.lfMenuFont, 1 ), get_tmheightW( &ncm2.lfMenuFont, 1 ));
3019  break;
3020  default:
3021  ok( ret1 == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
3022  break;
3023  }
3024  }
3025  im1.cbSize = sizeof(im1);
3026  ret = SystemParametersInfoW( SPI_GETICONMETRICS, sizeof(im1), &im1, FALSE );
3027  ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
3028  im2.cbSize = sizeof(im2);
3029  ret = pSystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im2), &im2, FALSE, custom_dpi );
3030  ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
3031  ok( im1.iHorzSpacing == MulDiv( im2.iHorzSpacing, dpi, custom_dpi ), "wrong iHorzSpacing %u vs %u\n",
3032  im1.iHorzSpacing, im2.iHorzSpacing );
3033  ok( im1.iVertSpacing == MulDiv( im2.iVertSpacing, dpi, custom_dpi ), "wrong iVertSpacing %u vs %u\n",
3034  im1.iVertSpacing, im2.iVertSpacing );
3035  ok( im1.iTitleWrap == im2.iTitleWrap, "wrong iTitleWrap %u vs %u\n",
3036  im1.iTitleWrap, im2.iTitleWrap );
3037  compare_font( &im1.lfFont, &im2.lfFont, dpi, custom_dpi, __LINE__ );
3038 
3039  ret = SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf1), &lf1, FALSE );
3040  ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
3041  ret = pSystemParametersInfoForDpi( SPI_GETICONTITLELOGFONT, sizeof(lf2), &lf2, FALSE, custom_dpi );
3042  ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
3043  compare_font( &lf1, &lf2, dpi, custom_dpi, __LINE__ );
3044 
3045  /* on high-dpi iPaddedBorderWidth is used in addition to iBorderWidth */
3046  ok( ncm1.iBorderWidth + ncm1.iPaddedBorderWidth == MulDiv( ncm2.iBorderWidth + ncm2.iPaddedBorderWidth, dpi, custom_dpi ),
3047  "wrong iBorderWidth %u+%u vs %u+%u\n",
3048  ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
3049  ok( ncm1.iScrollWidth == MulDiv( ncm2.iScrollWidth, dpi, custom_dpi ),
3050  "wrong iScrollWidth %u vs %u\n", ncm1.iScrollWidth, ncm2.iScrollWidth );
3051  ok( ncm1.iScrollHeight == MulDiv( ncm2.iScrollHeight, dpi, custom_dpi ),
3052  "wrong iScrollHeight %u vs %u\n", ncm1.iScrollHeight, ncm2.iScrollHeight );
3053  ok( ((ncm1.iCaptionWidth + 1) & ~1) == ((MulDiv( ncm2.iCaptionWidth, dpi, custom_dpi ) + 1) & ~1),
3054  "wrong iCaptionWidth %u vs %u\n", ncm1.iCaptionWidth, ncm2.iCaptionWidth );
3055  ok( ncm1.iCaptionHeight == MulDiv( ncm2.iCaptionHeight, dpi, custom_dpi ),
3056  "wrong iCaptionHeight %u vs %u\n", ncm1.iCaptionHeight, ncm2.iCaptionHeight );
3057  compare_font( &ncm1.lfCaptionFont, &ncm2.lfCaptionFont, dpi, custom_dpi, __LINE__ );
3058  ok( ncm1.iSmCaptionHeight == MulDiv( ncm2.iSmCaptionHeight, dpi, custom_dpi ),
3059  "wrong iSmCaptionHeight %u vs %u\n", ncm1.iSmCaptionHeight, ncm2.iSmCaptionHeight );
3060  compare_font( &ncm1.lfSmCaptionFont, &ncm2.lfSmCaptionFont, dpi, custom_dpi, __LINE__ );
3061  ok( ncm1.iMenuHeight == MulDiv( ncm2.iMenuHeight, dpi, custom_dpi ),
3062  "wrong iMenuHeight %u vs %u\n", ncm1.iMenuHeight, ncm2.iMenuHeight );
3063  /* iSmCaptionWidth and iMenuWidth apparently need to be multiples of 8 */
3064  ok( ncm1.iSmCaptionWidth / 8 == MulDiv( ncm2.iSmCaptionWidth, dpi, custom_dpi ) / 8,
3065  "wrong iSmCaptionWidth %u vs %u\n", ncm1.iSmCaptionWidth, ncm2.iSmCaptionWidth );
3066  ok( ncm1.iMenuWidth / 8 == MulDiv( ncm2.iMenuWidth, dpi, custom_dpi ) / 8,
3067  "wrong iMenuWidth %u vs %u\n", ncm1.iMenuWidth, ncm2.iMenuWidth );
3068  compare_font( &ncm1.lfMenuFont, &ncm2.lfMenuFont, dpi, custom_dpi, __LINE__ );
3069  compare_font( &ncm1.lfStatusFont, &ncm2.lfStatusFont, dpi, custom_dpi, __LINE__ );
3070  compare_font( &ncm1.lfMessageFont, &ncm2.lfMessageFont, dpi, custom_dpi, __LINE__ );
3071 
3072  for (i = 1; i < 120; i++)
3073  {
3074  if (i == SPI_GETICONTITLELOGFONT || i == SPI_GETNONCLIENTMETRICS || i == SPI_GETICONMETRICS)
3075  continue;
3076  SetLastError( 0xdeadbeef );
3077  ret = pSystemParametersInfoForDpi( i, 0, &val, 0, custom_dpi );
3078  ok( !ret, "%u: SystemParametersInfoForDpi succeeded\n", i );
3079  ok( GetLastError() == ERROR_INVALID_PARAMETER, "%u: wrong error %u\n", i, GetLastError() );
3080  }
3081 }
3082 
3083 static void test_EnumDisplaySettings(void)
3084 {
3085  DEVMODEA devmode;
3086  DWORD val;
3087  HDC hdc;
3088  DWORD num;
3089 
3090  memset(&devmode, 0, sizeof(devmode));
3092 
3093  hdc = GetDC(0);
3096  "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
3098 
3100  if(devmode.dmBitsPerPel <= 8) {
3101  ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
3102  } else {
3103  ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
3104  }
3105 
3106  ReleaseDC(0, hdc);
3107 
3108  num = 1;
3109  while (1) {
3110  SetLastError (0xdeadbeef);
3111  if (!EnumDisplaySettingsA(NULL, num, &devmode)) {
3112  DWORD le = GetLastError();
3113  ok(le == ERROR_NO_MORE_FILES ||
3114  le == ERROR_MOD_NOT_FOUND /* Win8 */ ||
3115  le == 0xdeadbeef, /* XP, 2003 */
3116  "Expected ERROR_NO_MORE_FILES, ERROR_MOD_NOT_FOUND or 0xdeadbeef, got %d for %d\n", le, num);
3117  break;
3118  }
3119  num++;
3120  }
3121 }
3122 
3123 static void test_GetSysColorBrush(void)
3124 {
3125  HBRUSH hbr;
3126 
3127  SetLastError(0xdeadbeef);
3128  hbr = GetSysColorBrush(-1);
3129  ok(hbr == NULL, "Expected NULL brush\n");
3130  ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
3131  /* greater than max index */
3132  hbr = GetSysColorBrush(COLOR_MENUBAR);
3133  if (hbr)
3134  {
3135  SetLastError(0xdeadbeef);
3136  hbr = GetSysColorBrush(COLOR_MENUBAR + 1);
3137  ok(hbr == NULL, "Expected NULL brush\n");
3138  ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
3139  }
3140  else
3141  win_skip("COLOR_MENUBAR unsupported\n");
3142 }
3143 
3145 {
3147  HGDIOBJ obj[STOCK_LAST + 1], obj2[STOCK_LAST + 1];
3148  LOGFONTW lf, lf2;
3149  UINT i, dpi;
3150 
3151  context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
3153  ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3154  ok( !pIsProcessDPIAware(), "not aware\n" );
3155  for (i = 0; i <= STOCK_LAST; i++) obj[i] = GetStockObject( i );
3156 
3157  pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3159  ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
3160  ok( pIsProcessDPIAware(), "not aware\n" );
3161  for (i = 0; i <= STOCK_LAST; i++) obj2[i] = GetStockObject( i );
3162 
3163  for (i = 0; i <= STOCK_LAST; i++)
3164  {
3165  switch (i)
3166  {
3167  case OEM_FIXED_FONT:
3168  case SYSTEM_FIXED_FONT:
3169  ok( obj[i] != obj2[i], "%u: same object\n", i );
3170  break;
3171  case SYSTEM_FONT:
3172  case DEFAULT_GUI_FONT:
3173  ok( obj[i] != obj2[i], "%u: same object\n", i );
3174  GetObjectW( obj[i], sizeof(lf), &lf );
3175  GetObjectW( obj2[i], sizeof(lf2), &lf2 );
3177  "%u: wrong height %d / %d\n", i, lf.lfHeight, lf2.lfHeight );
3178  break;
3179  default:
3180  ok( obj[i] == obj2[i], "%u: different object\n", i );
3181  break;
3182  }
3183  }
3184 
3185  pSetThreadDpiAwarenessContext( context );
3186 }
3187 
3188 static void scale_point_dpi( POINT *pt, UINT src_dpi, UINT target_dpi )
3189 {
3190  pt->x = MulDiv( pt->x, target_dpi, src_dpi );
3191  pt->y = MulDiv( pt->y, target_dpi, src_dpi );
3192 }
3193 
3194 static void scale_rect_dpi( RECT *rect, UINT src_dpi, UINT target_dpi )
3195 {
3196  rect->left = MulDiv( rect->left, target_dpi, src_dpi );
3197  rect->top = MulDiv( rect->top, target_dpi, src_dpi );
3198  rect->right = MulDiv( rect->right, target_dpi, src_dpi );
3199  rect->bottom = MulDiv( rect->bottom, target_dpi, src_dpi );
3200 }
3201 
3203 {
3206  else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
3208 }
3209 
3211 {
3214  else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
3216 }
3217 
3218 static void test_dpi_mapping(void)
3219 {
3220  HWND hwnd, child;
3221  HDC hdc;
3222  UINT win_dpi, units;
3223  POINT point;
3224  BOOL ret;
3225  HRGN rgn, update;
3226  RECT rect, orig, client, desktop, expect;
3227  ULONG_PTR i, j, k;
3228  WINDOWPLACEMENT wpl_orig, wpl;
3229  HMONITOR monitor;
3230  MONITORINFO mon_info;
3232 
3233  if (!pLogicalToPhysicalPointForPerMonitorDPI)
3234  {
3235  win_skip( "LogicalToPhysicalPointForPerMonitorDPI not supported\n" );
3236  return;
3237  }
3238  context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3239  GetWindowRect( GetDesktopWindow(), &desktop );
3241  {
3242  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3243  /* test desktop rect */
3245  expect = desktop;
3247  ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
3250  ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
3253  ok( EqualRect( &expect, &rect ), "%lu: wrong virt desktop rect %s expected %s\n",
3255  SetRect( &rect, 0, 0, 1, 1 );
3256  monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
3257  ok( monitor != 0, "failed to get monitor\n" );
3258  mon_info.cbSize = sizeof(mon_info);
3259  ok( GetMonitorInfoW( monitor, &mon_info ), "GetMonitorInfoExW failed\n" );
3260  ok( EqualRect( &expect, &mon_info.rcMonitor ), "%lu: wrong monitor rect %s expected %s\n",
3262  hdc = CreateDCA( "display", NULL, NULL, NULL );
3264  ok( EqualRect( &expect, &rect ), "%lu: wrong caps desktop rect %s expected %s\n",
3267  ok( EqualRect( &desktop, &rect ), "%lu: wrong caps virt desktop rect %s expected %s\n",
3268  i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
3269  DeleteDC( hdc );
3270  /* test message window rect */
3271  hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_CHILD,
3272  10, 10, 20, 20, HWND_MESSAGE, 0, GetModuleHandleA(0), NULL );
3274  SetRect( &expect, 0, 0, 100, 100 );
3276  ok( EqualRect( &expect, &rect ), "%lu: wrong message rect %s expected %s\n",
3278  DestroyWindow( hwnd );
3279  }
3281  {
3282  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
3283  hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3284  193, 177, 295, 303, 0, 0, GetModuleHandleA(0), NULL );
3285  ok( hwnd != 0, "creating window failed err %u\n", GetLastError());
3286  child = CreateWindowA( "SysParamsTestClass", "child", WS_CHILD | WS_VISIBLE,
3287  50, 60, 70, 80, hwnd, 0, GetModuleHandleA(0), NULL );
3288  ok( child != 0, "creating child failed err %u\n", GetLastError());
3289  GetWindowRect( hwnd, &orig );
3290  SetRect( &rect, 0, 0, 0, 0 );
3291  pAdjustWindowRectExForDpi( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0, pGetDpiForWindow( hwnd ));
3292  SetRect( &client, orig.left - rect.left, orig.top - rect.top,
3293  orig.right - rect.right, orig.bottom - rect.bottom );
3296  GetWindowPlacement( hwnd, &wpl_orig );
3298 
3300  {
3301  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3302  /* test window rect */
3303  GetWindowRect( hwnd, &rect );
3304  expect = orig;
3306  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong window rect %s expected %s\n",
3308  /* test client rect */
3309  GetClientRect( hwnd, &rect );
3310  expect = client;
3311  OffsetRect( &expect, -expect.left, -expect.top );
3313  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong client rect %s expected %s\n",
3315  /* test window placement */
3316  GetWindowPlacement( hwnd, &wpl );
3317  point = wpl_orig.ptMinPosition;
3318  if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
3319  ok( wpl.ptMinPosition.x == point.x && wpl.ptMinPosition.y == point.y,
3320  "%lu/%lu: wrong placement min pos %d,%d expected %d,%d\n", i, j,
3321  wpl.ptMinPosition.x, wpl.ptMinPosition.y, point.x, point.y );
3322  point = wpl_orig.ptMaxPosition;
3323  if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
3324  ok( wpl.ptMaxPosition.x == point.x && wpl.ptMaxPosition.y == point.y,
3325  "%lu/%lu: wrong placement max pos %d,%d expected %d,%d\n", i, j,
3326  wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, point.x, point.y );
3327  expect = wpl_orig.rcNormalPosition;
3329  ok( EqualRect( &wpl.rcNormalPosition, &expect ),
3330  "%lu/%lu: wrong placement rect %s expect %s\n", i, j,
3332  /* test DC rect */
3333  hdc = GetDC( hwnd );
3334  GetClipBox( hdc, &rect );
3335  SetRect( &expect, 0, 0, client.right - client.left, client.bottom - client.top );
3336  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box %s expected %s\n",
3338  /* test DC resolution */
3340  expect = desktop;
3342  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong DC resolution %s expected %s\n",
3345  ok( EqualRect( &desktop, &rect ), "%lu/%lu: wrong desktop resolution %s expected %s\n",
3346  i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
3347  ReleaseDC( hwnd, hdc );
3348  /* test DC win rect */
3349  hdc = GetWindowDC( hwnd );
3350  GetClipBox( hdc, &rect );
3351  SetRect( &expect, 0, 0, 295, 303 );
3352  todo_wine
3353  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box win DC %s expected %s\n",
3355  ReleaseDC( hwnd, hdc );
3356  /* test window invalidation */
3357  UpdateWindow( hwnd );
3358  update = CreateRectRgn( 0, 0, 0, 0 );
3359  ret = GetUpdateRgn( hwnd, update, FALSE );
3360  ok( ret == NULLREGION, "update region not empty\n" );
3361  rgn = CreateRectRgn( 20, 20, 25, 25 );
3363  {
3364  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
3365  RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
3366  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3367  GetUpdateRgn( hwnd, update, FALSE );
3368  GetRgnBox( update, &rect );
3369  SetRect( &expect, 20, 20, 25, 25 );
3370  ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
3372  GetUpdateRect( hwnd, &rect, FALSE );
3374  ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
3376  UpdateWindow( hwnd );
3377  }
3379  {
3380  RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
3381  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
3382  GetUpdateRgn( hwnd, update, FALSE );
3383  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3384  GetRgnBox( update, &rect );
3385  SetRect( &expect, 20, 20, 25, 25 );
3386  ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
3388  GetUpdateRect( hwnd, &rect, FALSE );
3390  ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
3392  UpdateWindow( hwnd );
3393  }
3394  /* test desktop window invalidation */
3395  pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3396  GetClientRect( hwnd, &rect );
3397  InflateRect( &rect, -50, -50 );
3398  expect = rect;
3399  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
3400  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3402  GetUpdateRgn( hwnd, update, TRUE );
3403  GetRgnBox( update, &rect );
3405  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update region %s expected %s\n",
3407  GetUpdateRect( hwnd, &rect, FALSE );
3409  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update rect %s expected %s\n",
3411  UpdateWindow( hwnd );
3412  DeleteObject( update );
3413  /* test dialog units */
3414  ret = GetDialogBaseUnits();
3415  point.x = LOWORD( units );
3416  point.y = HIWORD( units );
3418  ok( LOWORD(ret) == point.x && HIWORD(ret) == point.y, "%lu/%lu: wrong units %d,%d / %d,%d\n",
3419  i, j, LOWORD(ret), HIWORD(ret), point.x, point.y );
3420  /* test window points mapping */
3421  SetRect( &rect, 0, 0, 100, 100 );
3422  rect.right = rect.left + 100;
3423  rect.bottom = rect.top + 100;
3424  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
3425  expect = client;
3427  expect.right = expect.left + 100;
3428  expect.bottom = expect.top + 100;
3429  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints rect %s expected %s\n",
3431  SetRect( &rect, 50, 60, 70, 80 );
3432  scale_rect_dpi_aware( &rect, i, j );
3433  SetRect( &expect, 40, 30, 60, 80 );
3434  OffsetRect( &expect, -rect.left, -rect.top );
3435  SetRect( &rect, 40, 30, 60, 80 );
3436  MapWindowPoints( hwnd, child, (POINT *)&rect, 2 );
3437  ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints child rect %s expected %s\n",
3439  /* test logical<->physical coords mapping */
3440  win_dpi = pGetDpiForWindow( hwnd );
3441  if (i == DPI_AWARENESS_UNAWARE)
3442  ok( win_dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", win_dpi );
3443  else if (i == DPI_AWARENESS_SYSTEM_AWARE)
3444  ok( win_dpi == real_dpi, "wrong dpi %u / %u\n", win_dpi, real_dpi );
3445  point.x = 373;
3446  point.y = 377;
3447  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3448  ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3449  ok( point.x == MulDiv( 373, real_dpi, win_dpi ) &&
3450  point.y == MulDiv( 377, real_dpi, win_dpi ),
3451  "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
3452  point.x = 405;
3453  point.y = 423;
3454  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3455  ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3456  ok( point.x == MulDiv( 405, win_dpi, real_dpi ) &&
3457  point.y == MulDiv( 423, win_dpi, real_dpi ),
3458  "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
3459  /* point outside the window fails, but note that Windows (wrongly) checks against the
3460  * window rect transformed relative to the thread's awareness */
3461  GetWindowRect( hwnd, &rect );
3462  point.x = rect.left - 1;
3463  point.y = rect.top;
3464  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3465  ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3466  point.x++;
3467  point.y--;
3468  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3469  ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3470  point.y++;
3471  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3472  ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3473  point.x = rect.right;
3474  point.y = rect.bottom + 1;
3475  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3476  ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3477  point.x++;
3478  point.y--;
3479  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3480  ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
3481  point.x--;
3482  ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
3483  ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
3484  /* get physical window rect */
3485  pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
3486  GetWindowRect( hwnd, &rect );
3487  pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
3488  point.x = rect.left - 1;
3489  point.y = rect.top;
3490  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3491  ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3492  point.x++;
3493  point.y--;
3494  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3495  ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3496  point.y++;
3497  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3498  ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3499  point.x = rect.right;
3500  point.y = rect.bottom + 1;
3501  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3502  ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3503  point.x++;
3504  point.y--;
3505  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3506  ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
3507  point.x--;
3508  ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
3509  ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
3510  }
3511  DestroyWindow( hwnd );
3512  }
3513  pSetThreadDpiAwarenessContext( context );
3514 }
3515 
3516 static void test_dpi_aware(void)
3517 {
3518  BOOL ret;
3519 
3520  if (!pIsProcessDPIAware)
3521  {
3522  win_skip("IsProcessDPIAware not available\n");
3523  return;
3524  }
3525 
3526  ret = pSetProcessDPIAware();
3527  ok(ret, "got %d\n", ret);
3528 
3529  ret = pIsProcessDPIAware();
3530  ok(ret, "got %d\n", ret);
3531 
3532  dpi = real_dpi;
3534  test_metrics_for_dpi( 96 );
3535  test_metrics_for_dpi( 192 );
3536 }
3537 
3538 static void test_dpi_context(void)
3539 {
3540  DPI_AWARENESS awareness;
3542  ULONG_PTR i, flags;
3543  BOOL ret;
3544  UINT dpi;
3545  HDC hdc = GetDC( 0 );
3546 
3547  context = pGetThreadDpiAwarenessContext();
3548  /* Windows 10 >= 1709 adds extra 0x6000 flags */
3549  flags = (ULONG_PTR)context & 0x6000;
3550  todo_wine
3551  ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
3552  awareness = pGetAwarenessFromDpiAwarenessContext( context );
3553  todo_wine
3554  ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
3555  todo_wine
3556  ok( !pIsProcessDPIAware(), "already aware\n" );
3557  dpi = pGetDpiForSystem();
3559  ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3562  ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
3563  SetLastError( 0xdeadbeef );
3564  ret = pSetProcessDpiAwarenessContext( NULL );
3565  ok( !ret, "got %d\n", ret );
3566  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3567  SetLastError( 0xdeadbeef );
3568  ret = pSetProcessDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)-6 );
3569  ok( !ret, "got %d\n", ret );
3570  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
3571  ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
3572  todo_wine
3573  ok( ret, "got %d\n", ret );
3574  ok( pIsProcessDPIAware(), "not aware\n" );
3575  real_dpi = pGetDpiForSystem();
<