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