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 #undef _WIN32_WINNT
20 #define _WIN32_WINNT 0x0600 /* For SPI_GETMOUSEHOVERWIDTH and more */
21 //#define _WIN32_IE 0x0700
22 #undef WINVER
23 #define WINVER 0x0600 /* For COLOR_MENUBAR, NONCLIENTMETRICS with padding */
24 
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 
30 #include "wine/test.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winreg.h"
35 #include "winuser.h"
36 #include "winnls.h"
37 
38 #ifndef SPI_GETDESKWALLPAPER
39 # define SPI_GETDESKWALLPAPER 0x0073
40 #endif
41 
42 static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
43 static BOOL (WINAPI *pIsProcessDPIAware)(void);
44 static BOOL (WINAPI *pSetProcessDPIAware)(void);
45 static LONG (WINAPI *pGetAutoRotationState)(PAR_STATE);
46 
47 static BOOL strict;
48 static int dpi, real_dpi;
49 static BOOL iswin9x;
50 static HDC hdc;
51 
52 #define eq(received, expected, label, type) \
53         ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
54 
55 
56 #define SPI_SETBEEP_REGKEY                      "Control Panel\\Sound"
57 #define SPI_SETBEEP_VALNAME                     "Beep"
58 #define SPI_SETMOUSE_REGKEY                     "Control Panel\\Mouse"
59 #define SPI_SETMOUSE_VALNAME1                   "MouseThreshold1"
60 #define SPI_SETMOUSE_VALNAME2                   "MouseThreshold2"
61 #define SPI_SETMOUSE_VALNAME3                   "MouseSpeed"
62 #define SPI_SETBORDER_REGKEY                    "Control Panel\\Desktop\\WindowMetrics"
63 #define SPI_SETBORDER_REGKEY2                   "Control Panel\\Desktop"
64 #define SPI_SETBORDER_VALNAME                   "BorderWidth"
65 #define SPI_METRIC_REGKEY                       "Control Panel\\Desktop\\WindowMetrics"
66 #define SPI_SCROLLWIDTH_VALNAME                 "ScrollWidth"
67 #define SPI_SCROLLHEIGHT_VALNAME                "ScrollHeight"
68 #define SPI_CAPTIONWIDTH_VALNAME                "CaptionWidth"
69 #define SPI_CAPTIONHEIGHT_VALNAME               "CaptionHeight"
70 #define SPI_CAPTIONFONT_VALNAME                 "CaptionFont"
71 #define SPI_SMCAPTIONWIDTH_VALNAME              "SmCaptionWidth"
72 #define SPI_SMCAPTIONHEIGHT_VALNAME             "SmCaptionHeight"
73 #define SPI_SMCAPTIONFONT_VALNAME               "SmCaptionFont"
74 #define SPI_MENUWIDTH_VALNAME                   "MenuWidth"
75 #define SPI_MENUHEIGHT_VALNAME                  "MenuHeight"
76 #define SPI_MENUFONT_VALNAME                    "MenuFont"
77 #define SPI_STATUSFONT_VALNAME                  "StatusFont"
78 #define SPI_MESSAGEFONT_VALNAME                 "MessageFont"
79 
80 #define SPI_SETKEYBOARDSPEED_REGKEY             "Control Panel\\Keyboard"
81 #define SPI_SETKEYBOARDSPEED_VALNAME            "KeyboardSpeed"
82 #define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop\\WindowMetrics"
83 #define SPI_ICONHORIZONTALSPACING_REGKEY2       "Control Panel\\Desktop"
84 #define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
85 #define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop\\WindowMetrics"
86 #define SPI_ICONVERTICALSPACING_REGKEY2         "Control Panel\\Desktop"
87 #define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
88 #define SPI_MINIMIZEDMETRICS_REGKEY             "Control Panel\\Desktop\\WindowMetrics"
89 #define SPI_MINWIDTH_VALNAME                    "MinWidth"
90 #define SPI_MINHORZGAP_VALNAME                  "MinHorzGap"
91 #define SPI_MINVERTGAP_VALNAME                  "MinVertGap"
92 #define SPI_MINARRANGE_VALNAME                  "MinArrange"
93 #define SPI_SETSCREENSAVETIMEOUT_REGKEY         "Control Panel\\Desktop"
94 #define SPI_SETSCREENSAVETIMEOUT_VALNAME        "ScreenSaveTimeOut"
95 #define SPI_SETSCREENSAVEACTIVE_REGKEY          "Control Panel\\Desktop"
96 #define SPI_SETSCREENSAVEACTIVE_VALNAME         "ScreenSaveActive"
97 #define SPI_SETGRIDGRANULARITY_REGKEY           "Control Panel\\Desktop"
98 #define SPI_SETGRIDGRANULARITY_VALNAME          "GridGranularity"
99 #define SPI_SETKEYBOARDDELAY_REGKEY             "Control Panel\\Keyboard"
100 #define SPI_SETKEYBOARDDELAY_VALNAME            "KeyboardDelay"
101 #define SPI_SETICONTITLEWRAP_REGKEY1            "Control Panel\\Desktop\\WindowMetrics"
102 #define SPI_SETICONTITLEWRAP_REGKEY2            "Control Panel\\Desktop"
103 #define SPI_SETICONTITLEWRAP_VALNAME            "IconTitleWrap"
104 #define SPI_SETMENUDROPALIGNMENT_REGKEY1        "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
105 #define SPI_SETMENUDROPALIGNMENT_REGKEY2        "Control Panel\\Desktop"
106 #define SPI_SETMENUDROPALIGNMENT_VALNAME        "MenuDropAlignment"
107 #define SPI_SETDOUBLECLKWIDTH_REGKEY1           "Control Panel\\Mouse"
108 #define SPI_SETDOUBLECLKWIDTH_REGKEY2           "Control Panel\\Desktop"
109 #define SPI_SETDOUBLECLKWIDTH_VALNAME           "DoubleClickWidth"
110 #define SPI_SETDOUBLECLKHEIGHT_REGKEY1          "Control Panel\\Mouse"
111 #define SPI_SETDOUBLECLKHEIGHT_REGKEY2          "Control Panel\\Desktop"
112 #define SPI_SETDOUBLECLKHEIGHT_VALNAME          "DoubleClickHeight"
113 #define SPI_SETDOUBLECLICKTIME_REGKEY           "Control Panel\\Mouse"
114 #define SPI_SETDOUBLECLICKTIME_VALNAME          "DoubleClickSpeed"
115 #define SPI_SETMOUSEBUTTONSWAP_REGKEY           "Control Panel\\Mouse"
116 #define SPI_SETMOUSEBUTTONSWAP_VALNAME          "SwapMouseButtons"
117 #define SPI_SETWORKAREA_REGKEY                  "Control Panel\\Desktop"
118 #define SPI_SETWORKAREA_VALNAME                 "WINE_WorkArea"
119 #define SPI_SETSHOWSOUNDS_REGKEY                "Control Panel\\Accessibility\\ShowSounds"
120 #define SPI_SETSHOWSOUNDS_VALNAME               "On"
121 #define SPI_SETKEYBOARDPREF_REGKEY              "Control Panel\\Accessibility\\Keyboard Preference"
122 #define SPI_SETKEYBOARDPREF_VALNAME             "On"
123 #define SPI_SETKEYBOARDPREF_REGKEY_LEGACY       "Control Panel\\Accessibility"
124 #define SPI_SETKEYBOARDPREF_VALNAME_LEGACY      "Keyboard Preference"
125 #define SPI_SETSCREENREADER_REGKEY              "Control Panel\\Accessibility\\Blind Access"
126 #define SPI_SETSCREENREADER_VALNAME             "On"
127 #define SPI_SETSCREENREADER_REGKEY_LEGACY       "Control Panel\\Accessibility"
128 #define SPI_SETSCREENREADER_VALNAME_LEGACY      "Blind Access"
129 #define SPI_SETFONTSMOOTHING_REGKEY             "Control Panel\\Desktop"
130 #define SPI_SETFONTSMOOTHING_VALNAME            "FontSmoothing"
131 #define SPI_SETFONTSMOOTHINGTYPE_VALNAME        "FontSmoothingType"
132 #define SPI_SETFONTSMOOTHINGCONTRAST_VALNAME    "FontSmoothingGamma"
133 #define SPI_SETFONTSMOOTHINGORIENTATION_VALNAME "FontSmoothingOrientation"
134 #define SPI_SETLOWPOWERACTIVE_REGKEY            "Control Panel\\Desktop"
135 #define SPI_SETLOWPOWERACTIVE_VALNAME           "LowPowerActive"
136 #define SPI_SETPOWEROFFACTIVE_REGKEY            "Control Panel\\Desktop"
137 #define SPI_SETPOWEROFFACTIVE_VALNAME           "PowerOffActive"
138 #define SPI_SETDRAGFULLWINDOWS_REGKEY           "Control Panel\\Desktop"
139 #define SPI_SETDRAGFULLWINDOWS_VALNAME          "DragFullWindows"
140 #define SPI_SETSNAPTODEFBUTTON_REGKEY           "Control Panel\\Mouse"
141 #define SPI_SETSNAPTODEFBUTTON_VALNAME          "SnapToDefaultButton"
142 #define SPI_SETMOUSEHOVERWIDTH_REGKEY           "Control Panel\\Mouse"
143 #define SPI_SETMOUSEHOVERWIDTH_VALNAME          "MouseHoverWidth"
144 #define SPI_SETMOUSEHOVERHEIGHT_REGKEY          "Control Panel\\Mouse"
145 #define SPI_SETMOUSEHOVERHEIGHT_VALNAME         "MouseHoverHeight"
146 #define SPI_SETMOUSEHOVERTIME_REGKEY            "Control Panel\\Mouse"
147 #define SPI_SETMOUSEHOVERTIME_VALNAME           "MouseHoverTime"
148 #define SPI_SETMOUSESCROLLCHARS_REGKEY          "Control Panel\\Desktop"
149 #define SPI_SETMOUSESCROLLCHARS_VALNAME         "WheelScrollChars"
150 #define SPI_SETMOUSESCROLLLINES_REGKEY          "Control Panel\\Desktop"
151 #define SPI_SETMOUSESCROLLLINES_VALNAME         "WheelScrollLines"
152 #define SPI_SETMENUSHOWDELAY_REGKEY             "Control Panel\\Desktop"
153 #define SPI_SETMENUSHOWDELAY_VALNAME            "MenuShowDelay"
154 #define SPI_SETDESKWALLPAPER_REGKEY             "Control Panel\\Desktop"
155 #define SPI_SETDESKWALLPAPER_VALNAME            "Wallpaper"
156 
157 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
158 #define WINE_CURRENT_USER_REGKEY     "Wine"
159 
160 static HWND ghTestWnd;
161 
162 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam );
163 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
164                                               LPARAM lParam );
165 static int change_counter;
166 static int change_setworkarea_param, change_iconverticalspacing_param;
167 static int change_last_param;
168 static int last_bpp;
169 static BOOL displaychange_ok = FALSE, displaychange_test_active = FALSE;
170 static HANDLE displaychange_sem = 0;
171 
172 static BOOL get_reg_dword(HKEY base, const char *key_name, const char *value_name, DWORD *value)
173 {
174     HKEY key;
175     DWORD type, data, size = sizeof(data);
176     BOOL ret = FALSE;
177 
178     if (RegOpenKeyA(base, key_name, &key) == ERROR_SUCCESS)
179     {
180         if (RegQueryValueExA(key, value_name, NULL, &type, (void *)&data, &size) == ERROR_SUCCESS &&
181             type == REG_DWORD)
182         {
183             *value = data;
184             ret = TRUE;
185         }
186         RegCloseKey(key);
187     }
188     return ret;
189 }
190 
191 static DWORD get_real_dpi(void)
192 {
193     DWORD dpi;
194 
195     if (get_reg_dword(HKEY_CURRENT_USER, "Control Panel\\Desktop", "LogPixels", &dpi))
196         return dpi;
197     if (get_reg_dword(HKEY_CURRENT_CONFIG, "Software\\Fonts", "LogPixels", &dpi))
198         return dpi;
199     return USER_DEFAULT_SCREEN_DPI;
200 }
201 
202 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
203                                               LPARAM lParam )
204 {
205     switch (msg) {
206 
207     case WM_DISPLAYCHANGE:
208         ok(displaychange_ok, "Unexpected WM_DISPLAYCHANGE message\n");
209         last_bpp = wParam;
210         displaychange_ok = FALSE;
211         ReleaseSemaphore(displaychange_sem, 1, 0);
212         break;
213 
214     case WM_SETTINGCHANGE:
215         if (change_counter>0) {
216             /* ignore these messages caused by resizing of toolbars */
217             if( wParam == SPI_SETWORKAREA){
218                 change_setworkarea_param = 1;
219                 break;
220             } else if( wParam == SPI_ICONVERTICALSPACING) {
221                 change_iconverticalspacing_param = 1;
222                 break;
223             } else if( displaychange_test_active)
224                 break;
225             if( !change_last_param){
226                 change_last_param = wParam;
227                 break;
228             }
229             ok(0,"too many changes counter=%d last change=%d\n",
230                change_counter,change_last_param);
231             change_counter++;
232             change_last_param = wParam;
233             break;
234         }
235         change_counter++;
236         change_last_param = change_setworkarea_param = change_iconverticalspacing_param =0;
237         if( wParam == SPI_SETWORKAREA)
238             change_setworkarea_param = 1;
239         else if( wParam == SPI_ICONVERTICALSPACING)
240             change_iconverticalspacing_param = 1;
241         else
242             change_last_param = wParam;
243         break;
244 
245     case WM_DESTROY:
246         PostQuitMessage( 0 );
247         break;
248 
249     /* drop through */
250     default:
251         return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
252     }
253 
254     return 0;
255 }
256 
257 /*
258 Performs testing for system parameters messages
259 params:
260  - system parameter id
261  - supposed value of the registry key
262 */
263 static void test_change_message( int action, int optional )
264 {
265     if (change_counter==0 && optional==1)
266         return;
267     ok( 1 == change_counter,
268         "Missed a message: change_counter=%d\n", change_counter );
269     change_counter = 0;
270     ok( action == change_last_param ||
271         ( change_setworkarea_param && action == SPI_SETWORKAREA) ||
272         ( change_iconverticalspacing_param && action == SPI_ICONVERTICALSPACING),
273         "Wrong action got %d expected %d\n", change_last_param, action );
274     change_last_param = 0;
275 }
276 
277 static BOOL test_error_msg ( int rc, const char *name )
278 {
279     DWORD last_error = GetLastError();
280 
281     if (rc==0)
282     {
283         if (last_error==0xdeadbeef || last_error==ERROR_INVALID_SPI_VALUE || last_error==ERROR_INVALID_PARAMETER)
284         {
285             skip("%s not supported on this platform\n", name);
286         }
287         else if (last_error==ERROR_ACCESS_DENIED)
288         {
289             skip("%s does not have privileges to run\n", name);
290         }
291         else
292         {
293             trace("%s failed for reason: %d. Indicating test failure and skipping remainder of test\n",name,last_error);
294             ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
295         }
296         return FALSE;
297     }
298     else
299     {
300         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
301         return TRUE;
302     }
303 }
304 
305 /*
306  * Tests the HKEY_CURRENT_USER subkey value.
307  * The value should contain string value.
308  */
309 static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName1, LPCSTR valName2,
310                            const void *exp_value, DWORD exp_type, BOOL optional )
311 {
312     CHAR  value[MAX_PATH];
313     DWORD valueLen;
314     DWORD type;
315     HKEY hKey;
316     LONG rc;
317     int found=0;
318 
319     *value='\0';
320     valueLen=sizeof(value);
321     RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
322     rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
323     RegCloseKey( hKey );
324     if (rc==ERROR_SUCCESS)
325     {
326         ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
327         switch (exp_type)
328         {
329         case REG_DWORD:
330             ok( *(DWORD *)value == *(DWORD *)exp_value,
331                 "Wrong value in registry: %s %s %08x/%08x\n",
332                 subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
333             break;
334         case REG_SZ:
335             ok( !strcmp( exp_value, value ),
336                 "Wrong value in registry: %s %s '%s' instead of '%s'\n",
337                 subKey1, valName1, value, (const char *)exp_value );
338             break;
339         }
340         found++;
341     }
342     else if (strict)
343     {
344         ok(0,"Missing registry entry: subKey=%s, valName=%s\n",
345            subKey1, valName1);
346     }
347     if (valName2)
348     {
349         *value='\0';
350         valueLen=sizeof(value);
351         RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
352         rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
353         RegCloseKey( hKey );
354         if (rc==ERROR_SUCCESS)
355         {
356             ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
357             switch (exp_type)
358             {
359             case REG_DWORD:
360                 ok( *(DWORD *)value == *(DWORD *)exp_value,
361                     "Wrong value in registry: %s %s %08x/%08x\n",
362                     subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
363                 break;
364             case REG_SZ:
365                 ok( !strcmp( exp_value, value ),
366                     "Wrong value in registry: %s %s '%s' instead of '%s'\n",
367                     subKey1, valName1, value, (const char *)exp_value );
368                 break;
369             }
370             found++;
371         }
372         else if (strict)
373         {
374             ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
375                 subKey1, valName2 );
376         }
377     }
378     if (subKey2 && !strict)
379     {
380         *value='\0';
381         valueLen=sizeof(value);
382         RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
383         rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
384         RegCloseKey( hKey );
385         if (rc==ERROR_SUCCESS)
386         {
387             ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
388             switch (exp_type)
389             {
390             case REG_DWORD:
391                 ok( *(DWORD *)value == *(DWORD *)exp_value,
392                     "Wrong value in registry: %s %s %08x/%08x\n",
393                     subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
394                 break;
395             case REG_SZ:
396                 ok( !strcmp( exp_value, value ),
397                     "Wrong value in registry: %s %s '%s' instead of '%s'\n",
398                     subKey1, valName1, value, (const char *)exp_value );
399                 break;
400             }
401             found++;
402         }
403         else if (strict)
404         {
405             ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
406                 subKey2, valName1 );
407         }
408         if (valName2)
409         {
410             *value='\0';
411             valueLen=sizeof(value);
412             RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
413             rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
414             RegCloseKey( hKey );
415             if (rc==ERROR_SUCCESS)
416             {
417                 ok( type == exp_type, "wrong type %u/%u\n", type, exp_type );
418                 switch (exp_type)
419                 {
420                 case REG_DWORD:
421                     ok( *(DWORD *)value == *(DWORD *)exp_value,
422                         "Wrong value in registry: %s %s %08x/%08x\n",
423                         subKey1, valName1, *(DWORD *)value, *(DWORD *)exp_value );
424                     break;
425                 case REG_SZ:
426                     ok( !strcmp( exp_value, value ),
427                         "Wrong value in registry: %s %s '%s' instead of '%s'\n",
428                         subKey1, valName1, value, (const char *)exp_value );
429                     break;
430                 }
431                 found++;
432             }
433             else if (strict)
434             {
435                 ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
436                     subKey2, valName2 );
437             }
438          }
439     }
440     ok(found || optional,
441        "Missing registry values: %s or %s in keys: %s or %s\n",
442        valName1, (valName2?valName2:"<n/a>"), subKey1, (subKey2?subKey2:"<n/a>") );
443 }
444 
445 #define test_reg_key( subKey, valName, testValue ) \
446     _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, FALSE )
447 #define test_reg_key_optional( subKey, valName, testValue ) \
448     _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_SZ, TRUE )
449 #define test_reg_key_ex( subKey1, subKey2, valName, testValue ) \
450     _test_reg_key( subKey1, subKey2, valName, NULL, testValue, REG_SZ, FALSE )
451 #define test_reg_key_ex2( subKey1, subKey2, valName1, valName2, testValue ) \
452     _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, FALSE )
453 #define test_reg_key_ex2_optional( subKey1, subKey2, valName1, valName2, testValue ) \
454     _test_reg_key( subKey1, subKey2, valName1, valName2, testValue, REG_SZ, TRUE )
455 #define test_reg_key_dword( subKey, valName, testValue ) \
456     _test_reg_key( subKey, NULL, valName, NULL, testValue, REG_DWORD, FALSE )
457 
458 /* get a metric from the registry. If the value is negative
459  * it is assumed to be in twips and converted to pixels */
460 static UINT metricfromreg( const char *keyname, const char *valname, int dpi)
461 {
462     HKEY hkey;
463     char buf[64];
464     DWORD ret;
465     DWORD size, type;
466     int value;
467 
468     RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
469     size = sizeof(buf);
470     ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)buf, &size );
471     RegCloseKey( hkey );
472     if( ret != ERROR_SUCCESS) return -1;
473     value = atoi( buf);
474     if( value < 0)
475         value = ( -value * dpi + 720) / 1440;
476     return value;
477 }
478 
479 typedef struct
480 {
481     INT16  lfHeight;
482     INT16  lfWidth;
483     INT16  lfEscapement;
484     INT16  lfOrientation;
485     INT16  lfWeight;
486     BYTE   lfItalic;
487     BYTE   lfUnderline;
488     BYTE   lfStrikeOut;
489     BYTE   lfCharSet;
490     BYTE   lfOutPrecision;
491     BYTE   lfClipPrecision;
492     BYTE   lfQuality;
493     BYTE   lfPitchAndFamily;
494     CHAR   lfFaceName[LF_FACESIZE];
495 } LOGFONT16, *LPLOGFONT16;
496 
497 /* get logfont from the registry */
498 static int lffromreg( const char *keyname, const char *valname, LOGFONTA *plf)
499 {
500     HKEY hkey;
501     LOGFONTW lfw;
502     DWORD ret, size, type;
503 
504     RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
505     size = sizeof( lfw);
506     ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)&lfw, &size );
507     RegCloseKey( hkey );
508     ok( ret == ERROR_SUCCESS, "Key \"%s\" value \"%s\" not found\n", keyname, valname);
509     if( ret != ERROR_SUCCESS)
510         return FALSE;
511     if( size <= sizeof( LOGFONT16)) {
512         LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
513         plf->lfHeight = plf16->lfHeight;
514         plf->lfWidth = plf16->lfWidth;
515         plf->lfEscapement = plf16->lfEscapement;
516         plf->lfOrientation = plf16->lfOrientation;
517         plf->lfWeight = plf16->lfWeight;
518         plf->lfItalic = plf16->lfItalic;
519         plf->lfUnderline = plf16->lfUnderline;
520         plf->lfStrikeOut = plf16->lfStrikeOut;
521         plf->lfCharSet = plf16->lfCharSet;
522         plf->lfOutPrecision = plf16->lfOutPrecision;
523         plf->lfClipPrecision = plf16->lfClipPrecision;
524         plf->lfQuality = plf16->lfQuality;
525         plf->lfPitchAndFamily = plf16->lfPitchAndFamily;
526         memcpy( plf->lfFaceName, plf16->lfFaceName, LF_FACESIZE );
527     } else if( size <= sizeof( LOGFONTA)) {
528         plf = (LOGFONTA*) &lfw;
529     } else {
530         plf->lfHeight = lfw.lfHeight;
531         plf->lfWidth = lfw.lfWidth;
532         plf->lfEscapement = lfw.lfEscapement;
533         plf->lfOrientation = lfw.lfOrientation;
534         plf->lfWeight = lfw.lfWeight;
535         plf->lfItalic = lfw.lfItalic;
536         plf->lfUnderline = lfw.lfUnderline;
537         plf->lfStrikeOut = lfw.lfStrikeOut;
538         plf->lfCharSet = lfw.lfCharSet;
539         plf->lfOutPrecision = lfw.lfOutPrecision;
540         plf->lfClipPrecision = lfw.lfClipPrecision;
541         plf->lfQuality = lfw.lfQuality;
542         plf->lfPitchAndFamily = lfw.lfPitchAndFamily;
543         WideCharToMultiByte( CP_ACP, 0, lfw.lfFaceName, -1, plf->lfFaceName,
544             LF_FACESIZE, NULL, NULL);
545 
546     }
547     return TRUE;
548 }
549 
550 static void test_SPI_SETBEEP( void )                   /*      2 */
551 {
552     BOOL rc;
553     BOOL old_b;
554     BOOL b;
555     BOOL curr_val;
556 
557     trace("testing SPI_{GET,SET}BEEP\n");
558     SetLastError(0xdeadbeef);
559     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &old_b, 0 );
560     if (!test_error_msg(rc,"SPI_{GET,SET}BEEP"))
561         return;
562 
563     curr_val = TRUE;
564     rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
565     if (!test_error_msg(rc,"SPI_SETBEEP")) return;
566     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
567     test_change_message( SPI_SETBEEP, 0 );
568     test_reg_key( SPI_SETBEEP_REGKEY,
569                   SPI_SETBEEP_VALNAME,
570                   curr_val ? "Yes" : "No" );
571     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
572     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
573     eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
574     rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
575     if (rc || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
576     {
577         ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
578         eq( b, curr_val, "SystemParametersInfoW", "%d" );
579     }
580 
581     /* is a message sent for the second change? */
582     rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
583     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
584     test_change_message( SPI_SETBEEP, 0 );
585 
586     curr_val = FALSE;
587     rc=SystemParametersInfoW( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
588     if (rc == FALSE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
589         rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
590     ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
591     test_change_message( SPI_SETBEEP, 0 );
592     test_reg_key( SPI_SETBEEP_REGKEY,
593                   SPI_SETBEEP_VALNAME,
594                   curr_val ? "Yes" : "No" );
595     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
596     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
597     eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
598     rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
599     if (rc || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
600     {
601         ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
602         eq( b, curr_val, "SystemParametersInfoW", "%d" );
603     }
604     ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled\n" );
605 
606     rc=SystemParametersInfoA( SPI_SETBEEP, old_b, 0, SPIF_UPDATEINIFILE );
607     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
608 }
609 
610 static const char *setmouse_valuenames[3] = {
611     SPI_SETMOUSE_VALNAME1,
612     SPI_SETMOUSE_VALNAME2,
613     SPI_SETMOUSE_VALNAME3
614 };
615 
616 /*
617  * Runs check for one setting of spi_setmouse.
618  */
619 static BOOL run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *proj_change, int nchange )
620 {
621     BOOL rc;
622     INT mi[3];
623     static int aw_turn = 0;
624     static BOOL w_implemented = TRUE;
625 
626     char buf[20];
627     int i;
628 
629     aw_turn++;
630     rc = FALSE;
631     if ((aw_turn % 2!=0) && (w_implemented))
632     {
633         /* call unicode on odd (non even) calls */
634         SetLastError(0xdeadbeef);
635         rc=SystemParametersInfoW( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
636         if (rc == FALSE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
637         {
638             w_implemented = FALSE;
639             trace("SystemParametersInfoW not supported on this platform\n");
640         }
641     }
642 
643     if ((aw_turn % 2==0) || (!w_implemented))
644     {
645         /* call ascii version on even calls or if unicode is not available */
646         rc=SystemParametersInfoA( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
647     }
648     if (!test_error_msg(rc,"SPI_SETMOUSE")) return FALSE;
649 
650     ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
651     test_change_message( SPI_SETMOUSE, 0 );
652     for (i = 0; i < 3; i++)
653     {
654         sprintf( buf, "%d", curr_val[i] );
655         test_reg_key( SPI_SETMOUSE_REGKEY, setmouse_valuenames[i], buf );
656     }
657 
658     rc=SystemParametersInfoA( SPI_GETMOUSE, 0, mi, 0 );
659     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
660     for (i = 0; i < 3; i++)
661     {
662         ok(mi[i] == curr_val[i],
663            "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
664     }
665 
666     if (w_implemented)
667     {
668         rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
669         ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
670         for (i = 0; i < 3; i++)
671         {
672             ok(mi[i] == curr_val[i],
673                "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
674         }
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;
683         mouse_event( MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
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 = sizeof( req_change ) / sizeof( POINT );
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 
753     rc=SystemParametersInfoA( SPI_SETMOUSE, 0, old_mi, SPIF_UPDATEINIFILE );
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) {
768         rc=SystemParametersInfoA( SPI_SETBORDER, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
769         if (!test_error_msg(rc,"SPI_SETBORDER")) return FALSE;
770         ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
771         test_change_message( SPI_SETBORDER, 1 );
772     } else { /* set non client metrics */
773         ncm.iBorderWidth = curr_val;
774         rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
775                 SPIF_SENDCHANGE);
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 */
781         regval = metricfromreg( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_VALNAME, dpi);
782         if( regval != curr_val)
783             regval = metricfromreg( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, dpi);
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 */
793     rc=SystemParametersInfoA( SPI_GETBORDER, 0, &border, 0 );
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     /* The SPI_SETBORDER seems to be buggy on Win9x/ME (looks like you need to
851      * do it twice to make the intended change). So skip parts of the tests on
852      * those platforms */
853     if( !iswin9x) {
854         /* win2k3 fails if you set the same border twice, or if size is 0 */
855         if (!test_setborder(2,  1, dpi)) return;
856         test_setborder(1,  1, dpi);
857         test_setborder(3,  1, dpi);
858     }
859     if (!test_setborder(1, 0, dpi)) return;
860     test_setborder(0, 0, dpi);
861     test_setborder(3, 0, dpi);
862 
863     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncmsave,
864             SPIF_UPDATEINIFILE| SPIF_SENDCHANGE);
865     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
866     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
867 }
868 
869 static void test_SPI_SETKEYBOARDSPEED( void )          /*     10 */
870 {
871     BOOL rc;
872     UINT old_speed;
873     const UINT vals[]={0,20,31};
874     unsigned int i;
875 
876     trace("testing SPI_{GET,SET}KEYBOARDSPEED\n");
877     SetLastError(0xdeadbeef);
878     rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &old_speed, 0 );
879     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDSPEED"))
880         return;
881 
882     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
883     {
884         UINT v;
885         char buf[10];
886 
887         rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, vals[i], 0,
888                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
889         if (!test_error_msg(rc,"SPI_SETKEYBOARDSPEED")) return;
890         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
891         test_change_message( SPI_SETKEYBOARDSPEED, 0 );
892         sprintf( buf, "%d", vals[i] );
893         test_reg_key( SPI_SETKEYBOARDSPEED_REGKEY, SPI_SETKEYBOARDSPEED_VALNAME, buf );
894 
895         rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &v, 0 );
896         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
897         eq( v, vals[i], "SPI_{GET,SET}KEYBOARDSPEED", "%d" );
898     }
899 
900     rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, old_speed, 0, SPIF_UPDATEINIFILE );
901     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
902 }
903 
904 /* test_SPI_ICONHORIZONTALSPACING helper */
905 static BOOL dotest_spi_iconhorizontalspacing( INT curr_val)
906 {
907     BOOL rc;
908     INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
909     ICONMETRICSA im;
910 
911     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
912                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
913     if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING")) return FALSE;
914     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
915     test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
916     curr_val = max( curr_val, min_val );
917     /* The registry keys depend on the Windows version and the values too
918      * let's test (works on win95,ME,NT4,2k,XP)
919      */
920     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY2, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
921     if( regval != curr_val)
922         regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
923     ok( curr_val == regval,
924         "wrong value in registry %d, expected %d\n", regval, curr_val);
925     /* compare with what SPI_ICONHORIZONTALSPACING returns */
926     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
927     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
928     eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
929     /* and with a system metrics */
930     eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
931     /* and with what SPI_GETICONMETRICS returns */
932     im.cbSize = sizeof(ICONMETRICSA);
933     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
934     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
935     eq( im.iHorzSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
936     return TRUE;
937 }
938 
939 static void test_SPI_ICONHORIZONTALSPACING( void )     /*     13 */
940 {
941     BOOL rc;
942     INT old_spacing;
943 
944     trace("testing SPI_ICONHORIZONTALSPACING\n");
945     SetLastError(0xdeadbeef);
946     /* default value: 75 */
947     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &old_spacing, 0 );
948     if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING"))
949         return;
950     /* do not increase the value as it would upset the user's icon layout */
951     if (!dotest_spi_iconhorizontalspacing( old_spacing - 1)) return;
952     dotest_spi_iconhorizontalspacing( 10); /* minimum is 32 */
953     /* restore */
954     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, old_spacing, 0, SPIF_UPDATEINIFILE );
955     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
956 }
957 
958 static void test_SPI_SETSCREENSAVETIMEOUT( void )      /*     14 */
959 {
960     BOOL rc;
961     UINT old_timeout;
962     const UINT vals[]={0,32767};
963     unsigned int i;
964 
965     trace("testing SPI_{GET,SET}SCREENSAVETIMEOUT\n");
966     SetLastError(0xdeadbeef);
967     rc=SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &old_timeout, 0 );
968     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVETIMEOUT"))
969         return;
970 
971     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
972     {
973         UINT v;
974         char buf[10];
975 
976         rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, vals[i], 0,
977                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
978         if (!test_error_msg(rc,"SPI_SETSCREENSAVETIMEOUT")) return;
979         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
980         test_change_message( SPI_SETSCREENSAVETIMEOUT, 0 );
981         sprintf( buf, "%d", vals[i] );
982         test_reg_key( SPI_SETSCREENSAVETIMEOUT_REGKEY,
983                       SPI_SETSCREENSAVETIMEOUT_VALNAME, buf );
984 
985         rc = SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &v, 0 );
986         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
987         eq( v, vals[i], "SPI_{GET,SET}SCREENSAVETIMEOUT", "%d" );
988     }
989 
990     rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, old_timeout, 0,
991                               SPIF_UPDATEINIFILE );
992     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
993 }
994 
995 static void test_SPI_SETSCREENSAVEACTIVE( void )       /*     17 */
996 {
997     BOOL rc;
998     BOOL old_b;
999     const UINT vals[]={TRUE,FALSE};
1000     unsigned int i;
1001 
1002     trace("testing SPI_{GET,SET}SCREENSAVEACTIVE\n");
1003     SetLastError(0xdeadbeef);
1004     rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &old_b, 0 );
1005     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVEACTIVE"))
1006         return;
1007 
1008     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1009     {
1010         UINT v;
1011 
1012         rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, vals[i], 0,
1013                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1014         if (!test_error_msg(rc,"SPI_SETSCREENSAVEACTIVE")) return;
1015         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1016         test_change_message( SPI_SETSCREENSAVEACTIVE, 0 );
1017         test_reg_key( SPI_SETSCREENSAVEACTIVE_REGKEY,
1018                       SPI_SETSCREENSAVEACTIVE_VALNAME,
1019                       vals[i] ? "1" : "0" );
1020 
1021         rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &v, 0 );
1022         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1023         ok(v == vals[i] || broken(! v) /* Win 7 */,
1024            "SPI_{GET,SET}SCREENSAVEACTIVE: got %d instead of %d\n", v, vals[i]);
1025     }
1026 
1027     rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1028     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1029 }
1030 
1031 static void test_SPI_SETGRIDGRANULARITY( void )        /*     19 */
1032 {
1033     /* ??? */;
1034 }
1035 
1036 static void test_SPI_SETKEYBOARDDELAY( void )          /*     23 */
1037 {
1038     BOOL rc;
1039     UINT old_delay;
1040     const UINT vals[]={0,3};
1041     unsigned int i;
1042 
1043     trace("testing SPI_{GET,SET}KEYBOARDDELAY\n");
1044     SetLastError(0xdeadbeef);
1045     rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &old_delay, 0 );
1046     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
1047         return;
1048 
1049     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1050     {
1051         UINT delay;
1052         char buf[10];
1053 
1054         rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, vals[i], 0,
1055                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1056         if (!test_error_msg(rc,"SPI_SETKEYBOARDDELAY")) return;
1057         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1058         test_change_message( SPI_SETKEYBOARDDELAY, 0 );
1059         sprintf( buf, "%d", vals[i] );
1060         test_reg_key( SPI_SETKEYBOARDDELAY_REGKEY,
1061                       SPI_SETKEYBOARDDELAY_VALNAME, buf );
1062 
1063         rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &delay, 0 );
1064         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1065         eq( delay, vals[i], "SPI_{GET,SET}KEYBOARDDELAY", "%d" );
1066     }
1067 
1068     rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, old_delay, 0, SPIF_UPDATEINIFILE );
1069     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1070 }
1071 
1072 
1073 /* test_SPI_ICONVERTICALSPACING helper */
1074 static BOOL dotest_spi_iconverticalspacing( INT curr_val)
1075 {
1076     BOOL rc;
1077     INT spacing, regval, min_val = MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI );
1078     ICONMETRICSA im;
1079 
1080     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
1081                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1082     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING")) return FALSE;
1083     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1084     test_change_message( SPI_ICONVERTICALSPACING, 0 );
1085     curr_val = max( curr_val, min_val );
1086     /* The registry keys depend on the Windows version and the values too
1087      * let's test (works on win95,ME,NT4,2k,XP)
1088      */
1089     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY2, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1090     if( regval != curr_val)
1091         regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1092     ok( curr_val == regval,
1093         "wrong value in registry %d, expected %d\n", regval, curr_val);
1094     /* compare with what SPI_ICONVERTICALSPACING returns */
1095     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1096     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1097     eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
1098     /* and with a system metrics */
1099     eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
1100     /* and with what SPI_GETICONMETRICS returns */
1101     im.cbSize = sizeof(ICONMETRICSA);
1102     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1103     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1104     eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
1105     return TRUE;
1106 }
1107 
1108 static void test_SPI_ICONVERTICALSPACING( void )       /*     24 */
1109 {
1110     BOOL rc;
1111     INT old_spacing;
1112 
1113     trace("testing SPI_ICONVERTICALSPACING\n");
1114     SetLastError(0xdeadbeef);
1115     /* default value: 75 */
1116     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
1117     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
1118         return;
1119     /* do not increase the value as it would upset the user's icon layout */
1120     if (!dotest_spi_iconverticalspacing( old_spacing - 1)) return;
1121     /* same tests with a value less than the minimum 32 */
1122     dotest_spi_iconverticalspacing( 10);
1123     /* restore */
1124     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
1125                               SPIF_UPDATEINIFILE );
1126     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1127 }
1128 
1129 static void test_SPI_SETICONTITLEWRAP( void )          /*     26 */
1130 {
1131     BOOL rc;
1132     BOOL old_b;
1133     const UINT vals[]={TRUE,FALSE};
1134     unsigned int i;
1135     ICONMETRICSA im;
1136 
1137     /* These tests hang when XFree86 4.0 for Windows is running (tested on
1138      * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
1139      * running.
1140      */
1141     if (FindWindowA( NULL, "Cygwin/XFree86" ))
1142         return;
1143 
1144     trace("testing SPI_{GET,SET}ICONTITLEWRAP\n");
1145     SetLastError(0xdeadbeef);
1146     rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &old_b, 0 );
1147     if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
1148         return;
1149 
1150     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1151     {
1152         UINT v;
1153         UINT regval;
1154 
1155         rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, vals[i], 0,
1156                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1157         if (!test_error_msg(rc,"SPI_SETICONTITLEWRAP")) return;
1158         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1159         test_change_message( SPI_SETICONTITLEWRAP, 1 );
1160         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2,
1161                 SPI_SETICONTITLEWRAP_VALNAME, dpi);
1162         if( regval != vals[i])
1163             regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
1164                     SPI_SETICONTITLEWRAP_VALNAME, dpi);
1165         ok( regval == vals[i] || broken(regval == -1), /* win9x */
1166                 "wrong value in registry %d, expected %d\n", regval, vals[i] );
1167 
1168         rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
1169         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1170         eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
1171         /* and test with what SPI_GETICONMETRICS returns */
1172         im.cbSize = sizeof(ICONMETRICSA);
1173         rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1174         ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1175         eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
1176     }
1177 
1178     rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, old_b, 0, SPIF_UPDATEINIFILE );
1179     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1180 }
1181 
1182 static void test_SPI_SETMENUDROPALIGNMENT( void )      /*     28 */
1183 {
1184     BOOL rc;
1185     BOOL old_b;
1186     const UINT vals[]={TRUE,FALSE};
1187     unsigned int i;
1188 
1189     trace("testing SPI_{GET,SET}MENUDROPALIGNMENT\n");
1190     SetLastError(0xdeadbeef);
1191     rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &old_b, 0 );
1192     if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
1193         return;
1194 
1195     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1196     {
1197         UINT v;
1198 
1199         rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, vals[i], 0,
1200                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1201         if (!test_error_msg(rc,"SPI_SETMENUDROPALIGNMENT")) return;
1202         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1203         test_change_message( SPI_SETMENUDROPALIGNMENT, 0 );
1204         test_reg_key_ex( SPI_SETMENUDROPALIGNMENT_REGKEY1,
1205                          SPI_SETMENUDROPALIGNMENT_REGKEY2,
1206                          SPI_SETMENUDROPALIGNMENT_VALNAME,
1207                          vals[i] ? "1" : "0" );
1208 
1209         rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &v, 0 );
1210         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1211         eq( v, vals[i], "SPI_{GET,SET}MENUDROPALIGNMENT", "%d" );
1212         eq( GetSystemMetrics( SM_MENUDROPALIGNMENT ), (int)vals[i],
1213             "SM_MENUDROPALIGNMENT", "%d" );
1214     }
1215 
1216     rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, old_b, 0,
1217                               SPIF_UPDATEINIFILE );
1218     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1219 }
1220 
1221 static void test_SPI_SETDOUBLECLKWIDTH( void )         /*     29 */
1222 {
1223     BOOL rc;
1224     INT old_width;
1225     const UINT vals[]={0,10000};
1226     unsigned int i;
1227 
1228     trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
1229     old_width = GetSystemMetrics( SM_CXDOUBLECLK );
1230 
1231     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1232     {
1233         char buf[10];
1234 
1235         SetLastError(0xdeadbeef);
1236         rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, vals[i], 0,
1237                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1238         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKWIDTH"))
1239             return;
1240 
1241         test_change_message( SPI_SETDOUBLECLKWIDTH, 0 );
1242         sprintf( buf, "%d", vals[i] );
1243         test_reg_key_ex( SPI_SETDOUBLECLKWIDTH_REGKEY1,
1244                          SPI_SETDOUBLECLKWIDTH_REGKEY2,
1245                          SPI_SETDOUBLECLKWIDTH_VALNAME, buf );
1246         eq( GetSystemMetrics( SM_CXDOUBLECLK ), (int)vals[i],
1247             "SM_CXDOUBLECLK", "%d" );
1248     }
1249 
1250     rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, old_width, 0,
1251                               SPIF_UPDATEINIFILE );
1252     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1253 }
1254 
1255 static void test_SPI_SETDOUBLECLKHEIGHT( void )        /*     30 */
1256 {
1257     BOOL rc;
1258     INT old_height;
1259     const UINT vals[]={0,10000};
1260     unsigned int i;
1261 
1262     trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
1263     old_height = GetSystemMetrics( SM_CYDOUBLECLK );
1264 
1265     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1266     {
1267         char buf[10];
1268 
1269         SetLastError(0xdeadbeef);
1270         rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, vals[i], 0,
1271                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1272         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKHEIGHT"))
1273             return;
1274 
1275         test_change_message( SPI_SETDOUBLECLKHEIGHT, 0 );
1276         sprintf( buf, "%d", vals[i] );
1277         test_reg_key_ex( SPI_SETDOUBLECLKHEIGHT_REGKEY1,
1278                          SPI_SETDOUBLECLKHEIGHT_REGKEY2,
1279                          SPI_SETDOUBLECLKHEIGHT_VALNAME, buf );
1280         eq( GetSystemMetrics( SM_CYDOUBLECLK ), (int)vals[i],
1281             "SM_CYDOUBLECLK", "%d" );
1282     }
1283 
1284     rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, old_height, 0,
1285                               SPIF_UPDATEINIFILE );
1286     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1287 }
1288 
1289 static void test_SPI_SETDOUBLECLICKTIME( void )        /*     32 */
1290 {
1291     BOOL rc;
1292     UINT curr_val;
1293     UINT saved_val;
1294     UINT old_time;
1295     char buf[10];
1296 
1297     trace("testing SPI_{GET,SET}DOUBLECLICKTIME\n");
1298     old_time = GetDoubleClickTime();
1299 
1300     curr_val = 0;
1301     SetLastError(0xdeadbeef);
1302     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1303                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1304     if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLICKTIME"))
1305         return;
1306 
1307     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1308     sprintf( buf, "%d", curr_val );
1309     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1310                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1311     curr_val = 500; /* used value for 0 */
1312     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1313 
1314     curr_val = 1000;
1315     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1316                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1317     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1318     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1319     sprintf( buf, "%d", curr_val );
1320     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1321                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1322     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1323 
1324     saved_val = curr_val;
1325 
1326     curr_val = 0;
1327     SetDoubleClickTime( curr_val );
1328     sprintf( buf, "%d", saved_val );
1329     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1330                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1331     curr_val = 500; /* used value for 0 */
1332     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1333 
1334     curr_val = 1000;
1335     SetDoubleClickTime( curr_val );
1336     sprintf( buf, "%d", saved_val );
1337     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1338                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1339     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1340 
1341     rc=SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, old_time, 0, SPIF_UPDATEINIFILE);
1342     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1343 }
1344 
1345 static void test_SPI_SETMOUSEBUTTONSWAP( void )        /*     33 */
1346 {
1347     BOOL rc;
1348     BOOL old_b;
1349     const UINT vals[]={TRUE,FALSE};
1350     unsigned int i;
1351 
1352     trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
1353     old_b = GetSystemMetrics( SM_SWAPBUTTON );
1354 
1355     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1356     {
1357         SetLastError(0xdeadbeef);
1358         rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
1359                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1360         if (!test_error_msg(rc,"SPI_SETMOUSEBUTTONSWAP")) return;
1361 
1362         test_change_message( SPI_SETMOUSEBUTTONSWAP, 0 );
1363         test_reg_key( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1364                       SPI_SETMOUSEBUTTONSWAP_VALNAME,
1365                       vals[i] ? "1" : "0" );
1366         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
1367             "SM_SWAPBUTTON", "%d" );
1368         rc=SwapMouseButton((BOOL)vals[i^1]);
1369         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
1370             "SwapMouseButton", "%d" );
1371         ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
1372     }
1373 
1374     rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, old_b, 0,
1375                               SPIF_UPDATEINIFILE );
1376     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1377 }
1378 
1379 static void test_SPI_SETFASTTASKSWITCH( void )         /*     36 */
1380 {
1381     BOOL rc;
1382     BOOL v;
1383 
1384     trace("testing SPI_GETFASTTASKSWITCH\n");
1385     SetLastError(0xdeadbeef);
1386     rc=SystemParametersInfoA( SPI_GETFASTTASKSWITCH, 0, &v, 0 );
1387     if (!test_error_msg(rc,"SPI_{GET,SET}FASTTASKSWITCH"))
1388         return;
1389 
1390     /* there is not a single Windows platform on which SPI_GETFASTTASKSWITCH
1391      * works. That sure simplifies testing!
1392      */
1393 }
1394 
1395 static void test_SPI_SETDRAGFULLWINDOWS( void )        /*     37 */
1396 {
1397     BOOL rc;
1398     BOOL old_b;
1399     const UINT vals[]={TRUE,FALSE};
1400     unsigned int i;
1401 
1402     trace("testing SPI_{GET,SET}DRAGFULLWINDOWS\n");
1403     SetLastError(0xdeadbeef);
1404     rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &old_b, 0 );
1405 
1406     /* SPI_{GET,SET}DRAGFULLWINDOWS is not implemented on Win95 */
1407     if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
1408         return;
1409 
1410     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1411     {
1412         UINT v;
1413 
1414         rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, vals[i], 0,
1415                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1416         if (!test_error_msg(rc,"SPI_SETDRAGFULLWINDOWS")) return;
1417         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1418         test_change_message( SPI_SETDRAGFULLWINDOWS, 0 );
1419         test_reg_key( SPI_SETDRAGFULLWINDOWS_REGKEY,
1420                       SPI_SETDRAGFULLWINDOWS_VALNAME,
1421                       vals[i] ? "1" : "0" );
1422 
1423         rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &v, 0 );
1424         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1425         eq( v, vals[i], "SPI_{GET,SET}DRAGFULLWINDOWS", "%d" );
1426     }
1427 
1428     rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, old_b, 0, SPIF_UPDATEINIFILE );
1429     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1430 }
1431 
1432 #define test_reg_metric( KEY, VAL, val) \
1433 {   INT regval;\
1434     regval = metricfromreg( KEY, VAL, dpi);\
1435     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1436 }
1437 
1438 #define test_reg_metric2( KEY1, KEY2, VAL, val) \
1439 {   INT regval;\
1440     regval = metricfromreg( KEY1, VAL, dpi);\
1441     if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
1442     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1443 }
1444 
1445 #define test_reg_font( KEY, VAL, LF) \
1446 {   LOGFONTA lfreg;\
1447     lffromreg( KEY, VAL, &lfreg);\
1448     ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == MulDiv( lfreg.lfHeight, dpi, real_dpi ) : \
1449                 MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
1450         (LF).lfWidth == lfreg.lfWidth &&\
1451         (LF).lfWeight == lfreg.lfWeight &&\
1452         !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
1453         , "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
1454 }
1455 
1456 #define TEST_NONCLIENTMETRICS_REG( ncm) \
1457 /*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
1458 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
1459 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
1460 /*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
1461 test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
1462 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
1463 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
1464 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
1465 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
1466 test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
1467 test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
1468 test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
1469 test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
1470 test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont);
1471 
1472 /* get text metric height value for the specified logfont */
1473 static int get_tmheight( LOGFONTA *plf, int flag)
1474 {
1475     TEXTMETRICA tm;
1476     HFONT hfont = CreateFontIndirectA( plf);
1477     hfont = SelectObject( hdc, hfont);
1478     GetTextMetricsA( hdc, &tm);
1479     hfont = SelectObject( hdc, hfont);
1480     return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1481 }
1482 
1483 static void test_GetSystemMetrics( void);
1484 static UINT smcxsmsize = 999999999;
1485 
1486 static void test_SPI_SETNONCLIENTMETRICS( void )               /*     44 */
1487 {
1488     BOOL rc;
1489     INT expect;
1490     NONCLIENTMETRICSA Ncmorig;
1491     NONCLIENTMETRICSA Ncmnew;
1492     NONCLIENTMETRICSA Ncmcur;
1493     NONCLIENTMETRICSA Ncmstart;
1494 
1495     Ncmorig.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1496     Ncmnew.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1497     Ncmcur.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1498     Ncmstart.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
1499 
1500     trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1501     change_counter = 0;
1502     SetLastError(0xdeadbeef);
1503     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmorig, FALSE );
1504     if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1505         return;
1506     Ncmstart = Ncmorig;
1507     smcxsmsize = Ncmstart.iSmCaptionWidth;
1508     /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if
1509        the caption font height is higher than the CaptionHeight field,
1510        the latter is adjusted accordingly. To be able to restore these setting
1511        accurately be restore the raw values. */
1512     Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, real_dpi);
1513     Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1514     Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1515     Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1516     /* test registry entries */
1517     TEST_NONCLIENTMETRICS_REG( Ncmorig)
1518     Ncmorig.lfCaptionFont.lfHeight = MulDiv( Ncmorig.lfCaptionFont.lfHeight, real_dpi, dpi );
1519 
1520     /* make small changes */
1521     Ncmnew = Ncmstart;
1522     Ncmnew.iBorderWidth += 1;
1523     Ncmnew.iScrollWidth += 1;
1524     Ncmnew.iScrollHeight -= 1;
1525     Ncmnew.iCaptionWidth -= 2;
1526     Ncmnew.iCaptionHeight += 2;
1527     Ncmnew.lfCaptionFont.lfHeight +=1;
1528     Ncmnew.lfCaptionFont.lfWidth +=2;
1529     Ncmnew.lfCaptionFont.lfWeight +=1;
1530     Ncmnew.iSmCaptionWidth += 1;
1531     Ncmnew.iSmCaptionHeight += 2;
1532     Ncmnew.lfSmCaptionFont.lfHeight +=3;
1533     Ncmnew.lfSmCaptionFont.lfWidth -=1;
1534     Ncmnew.lfSmCaptionFont.lfWeight +=3;
1535     Ncmnew.iMenuWidth += 1;
1536     Ncmnew.iMenuHeight += 2;
1537     Ncmnew.lfMenuFont.lfHeight +=1;
1538     Ncmnew.lfMenuFont.lfWidth +=1;
1539     Ncmnew.lfMenuFont.lfWeight +=2;
1540     Ncmnew.lfStatusFont.lfHeight -=1;
1541     Ncmnew.lfStatusFont.lfWidth -=1;
1542     Ncmnew.lfStatusFont.lfWeight +=3;
1543     Ncmnew.lfMessageFont.lfHeight -=2;
1544     Ncmnew.lfMessageFont.lfWidth -=1;
1545     Ncmnew.lfMessageFont.lfWeight +=4;
1546 
1547     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1548             SPIF_SENDCHANGE);
1549     if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return;
1550     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1551     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1552     /* get them back */
1553     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1554     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1555     /* test registry entries */
1556     TEST_NONCLIENTMETRICS_REG( Ncmcur)
1557     /* test the system metrics with these settings */
1558     test_GetSystemMetrics();
1559     /* now for something invalid: increase the {menu|caption|smcaption} fonts
1560        by a large amount will increase the {menu|caption|smcaption} height*/
1561     Ncmnew = Ncmstart;
1562     Ncmnew.lfMenuFont.lfHeight -= 8;
1563     Ncmnew.lfCaptionFont.lfHeight =-4;
1564     Ncmnew.lfSmCaptionFont.lfHeight -=10;
1565     /* also show that a few values are lo limited */
1566     Ncmnew.iCaptionWidth = 0;
1567     Ncmnew.iCaptionHeight = 0;
1568     Ncmnew.iScrollHeight = 0;
1569     Ncmnew.iScrollWidth  = 0;
1570 
1571     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1572             SPIF_SENDCHANGE);
1573     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1574     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1575     /* raw values are in registry */
1576     TEST_NONCLIENTMETRICS_REG( Ncmnew)
1577     /* get them back */
1578     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
1579     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1580     /* cooked values are returned */
1581     expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1582     ok( Ncmcur.iMenuHeight == expect,
1583         "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1584     expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1585     ok( Ncmcur.iCaptionHeight == expect,
1586         "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1587     expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1588     ok( Ncmcur.iSmCaptionHeight == expect,
1589         "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1590 
1591     /* iCaptionWidth depends on a version, could be 8, 12 (Vista, Win7), 13 */
1592     ok( (Ncmcur.iCaptionWidth >= 8 && Ncmcur.iCaptionWidth <= 13) ||
1593         Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme,  the value never changes */
1594         "CaptionWidth: %d expected from [8, 13] or %d\n", Ncmcur.iCaptionWidth, Ncmstart.iCaptionWidth);
1595     ok( Ncmcur.iScrollWidth == 8,
1596         "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1597     ok( Ncmcur.iScrollHeight == 8,
1598         "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1599     /* test the system metrics with these settings */
1600     test_GetSystemMetrics();
1601     /* restore */
1602     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA),
1603         &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1604     test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1605     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1606     /* test the system metrics with these settings */
1607     test_GetSystemMetrics();
1608 }
1609 
1610 static void test_SPI_SETMINIMIZEDMETRICS( void )               /*     44 */
1611 {
1612     BOOL rc;
1613     INT regval;
1614     MINIMIZEDMETRICS lpMm_orig;
1615     MINIMIZEDMETRICS lpMm_new;
1616     MINIMIZEDMETRICS lpMm_cur;
1617 
1618     lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1619     lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1620     lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1621 
1622     trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1623     SetLastError(0xdeadbeef);
1624     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1625     if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1626         return;
1627     /* Test registry. Note that it is perfectly valid for some fields to
1628      * not be set.
1629      */
1630     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1631     ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1632         regval, lpMm_orig.iWidth);
1633     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1634     ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1635         regval, lpMm_orig.iHorzGap);
1636     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1637     ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1638         regval, lpMm_orig.iVertGap);
1639     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1640     ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1641         regval, lpMm_orig.iArrange);
1642     /* set some new values */
1643     lpMm_cur.iWidth = 180;
1644     lpMm_cur.iHorzGap = 1;
1645     lpMm_cur.iVertGap = 1;
1646     lpMm_cur.iArrange = 5;
1647     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1648         &lpMm_cur, SPIF_UPDATEINIFILE );
1649     if (!test_error_msg(rc,"SPI_SETMINIMIZEDMETRICS")) return;
1650     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1651     /* read them back */
1652     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1653     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1654     /* and compare */
1655     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
1656     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1657     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1658     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1659     /* test registry */
1660     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1661     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1662         regval, lpMm_new.iWidth);
1663     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1664     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1665         regval, lpMm_new.iHorzGap);
1666     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1667     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1668         regval, lpMm_new.iVertGap);
1669     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1670     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1671         regval, lpMm_new.iArrange);
1672     /* test some system metrics */
1673     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1674         lpMm_new.iWidth,   "iWidth",   "%d" );
1675     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1676         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1677     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1678         lpMm_new.iVertGap, "iVertGap", "%d" );
1679     eq( GetSystemMetrics( SM_ARRANGE ),
1680         lpMm_new.iArrange, "iArrange", "%d" );
1681     /* now some really invalid settings */
1682     lpMm_cur.iWidth = -1;
1683     lpMm_cur.iHorzGap = -1;
1684     lpMm_cur.iVertGap = -1;
1685     lpMm_cur.iArrange = - 1;
1686     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1687         &lpMm_cur, SPIF_UPDATEINIFILE );
1688     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1689     /* read back */
1690     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1691     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1692     /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1693     eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
1694     eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1695     eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1696     eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1697     /* test registry */
1698     if (0)
1699     {
1700     /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1701     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1702     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1703         regval, lpMm_new.iWidth);
1704     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1705     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1706         regval, lpMm_new.iHorzGap);
1707     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1708     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1709         regval, lpMm_new.iVertGap);
1710     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1711     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1712         regval, lpMm_new.iArrange);
1713     }
1714     /* test some system metrics */
1715     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1716         lpMm_new.iWidth,   "iWidth",   "%d" );
1717     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1718         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1719     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1720         lpMm_new.iVertGap, "iVertGap", "%d" );
1721     eq( GetSystemMetrics( SM_ARRANGE ),
1722         lpMm_new.iArrange, "iArrange", "%d" );
1723     /* restore */
1724     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1725         &lpMm_orig, SPIF_UPDATEINIFILE );
1726     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1727     /* check that */
1728     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1729     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1730     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
1731     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1732     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1733     eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1734 }
1735 
1736 static void test_SPI_SETICONMETRICS( void )               /*     46 */
1737 {
1738     BOOL rc, wrap;
1739     INT spacing;
1740     ICONMETRICSA im_orig;
1741     ICONMETRICSA im_new;
1742     ICONMETRICSA im_cur;
1743     INT regval;
1744 
1745     im_orig.cbSize = sizeof(ICONMETRICSA);
1746     im_new.cbSize = sizeof(ICONMETRICSA);
1747     im_cur.cbSize = sizeof(ICONMETRICSA);
1748 
1749     trace("testing SPI_{GET,SET}ICONMETRICS\n");
1750     SetLastError(0xdeadbeef);
1751     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1752     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1753         return;
1754    /* check some registry values */
1755     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1756     ok( regval==im_orig.iHorzSpacing || broken(regval == -1), /* nt4 */
1757         "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1758     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1759     ok( regval==im_orig.iVertSpacing || broken(regval == -1), /* nt4 */
1760         "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1761     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1762     if( regval != im_orig.iTitleWrap)
1763         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1764     ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1765 
1766     /* change everything without creating something invalid ( Win9x would ignore
1767      * an invalid font for instance) */
1768     im_cur = im_orig;
1769     im_cur.iHorzSpacing += 10;
1770     im_cur.iVertSpacing += 6;
1771     im_cur.iTitleWrap = !im_cur.iTitleWrap;
1772     im_cur.lfFont.lfHeight += 1;
1773     im_cur.lfFont.lfWidth += 2;
1774     im_cur.lfFont.lfEscapement = 1;
1775     im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1776     im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1777     im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1778     im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1779     im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1780     im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1781                                 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1782     im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1783     im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1784     im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ?
1785                                 DRAFT_QUALITY : DEFAULT_QUALITY;
1786     if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1787         strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1788     else
1789         strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1790 
1791     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1792     if (!test_error_msg(rc,"SPI_SETICONMETRICS")) return;
1793     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1794 
1795     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1796     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1797     /* test GET <-> SETICONMETRICS */
1798     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1799     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1800     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
1801     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%d" );
1802     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%d" );
1803     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%d" );
1804     eq( im_new.lfFont.lfWeight,         im_cur.lfFont.lfWeight,         "lfWeight",         "%d" );
1805     eq( im_new.lfFont.lfItalic,         im_cur.lfFont.lfItalic,         "lfItalic",         "%d" );
1806     eq( im_new.lfFont.lfStrikeOut,      im_cur.lfFont.lfStrikeOut,      "lfStrikeOut",      "%d" );
1807     eq( im_new.lfFont.lfUnderline,      im_cur.lfFont.lfUnderline,      "lfUnderline",      "%d" );
1808     eq( im_new.lfFont.lfCharSet,        im_cur.lfFont.lfCharSet,        "lfCharSet",        "%d" );
1809     eq( im_new.lfFont.lfOutPrecision,   im_cur.lfFont.lfOutPrecision,   "lfOutPrecision",   "%d" );
1810     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
1811     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1812     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
1813     ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1814         "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1815         im_cur.lfFont.lfFaceName);
1816     /* test some system metrics */
1817     eq( GetSystemMetrics( SM_CXICONSPACING ),
1818         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1819     eq( GetSystemMetrics( SM_CYICONSPACING ),
1820         im_new.iVertSpacing, "iVertSpacing", "%d" );
1821    /* check some registry values */
1822     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1823     ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1824     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1825     ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1826     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1827     if( regval != im_cur.iTitleWrap)
1828         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1829     ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1830     /* test some values from other SPI_GETxxx calls */
1831     rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1832     ok( rc && spacing == im_cur.iHorzSpacing,
1833         "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1834         spacing, im_cur.iHorzSpacing);
1835     rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1836     ok( rc && spacing == im_cur.iVertSpacing,
1837         "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1838         spacing, im_cur.iVertSpacing);
1839     rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1840     ok( rc && wrap == im_cur.iTitleWrap,
1841         "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1842         wrap, im_cur.iTitleWrap);
1843     /* restore old values */
1844     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1845     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1846 
1847     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1848     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1849 
1850     eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1851     eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1852     eq( im_new.iTitleWrap,   im_orig.iTitleWrap,   "iTitleWrap",   "%d" );
1853 }
1854 
1855 static void test_SPI_SETWORKAREA( void )               /*     47 */
1856 {
1857     BOOL rc;
1858     RECT old_area;
1859     RECT area;
1860     RECT curr_val;
1861 
1862     trace("testing SPI_{GET,SET}WORKAREA\n");
1863     SetLastError(0xdeadbeef);
1864     rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1865     if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1866         return;
1867 
1868     /* Modify the work area only minimally as this causes the icons that
1869      * fall outside it to be moved around thus requiring the user to
1870      * reposition them manually one by one.
1871      * Changing the work area by just one pixel should make this occurrence
1872      * reasonably unlikely.
1873      */
1874     SetRect(&curr_val, old_area.left, old_area.top, old_area.right - 1, old_area.bottom - 1);
1875     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1876                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1877     if (!test_error_msg(rc,"SPI_SETWORKAREA")) return;
1878     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1879     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1880     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1881     if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1882         test_change_message( SPI_SETWORKAREA, 0);
1883     eq( area.left,   curr_val.left,   "left",   "%d" );
1884     eq( area.top,    curr_val.top,    "top",    "%d" );
1885     /* size may be rounded */
1886     ok( area.right >= curr_val.right - 16 && area.right < curr_val.right + 16,
1887         "right: got %d instead of %d\n", area.right, curr_val.right );
1888     ok( area.bottom >= curr_val.bottom - 16 && area.bottom < curr_val.bottom + 16,
1889         "bottom: got %d instead of %d\n", area.bottom, curr_val.bottom );
1890     curr_val = area;
1891     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1892                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1893     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1894     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1895     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
1896     if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1897         test_change_message( SPI_SETWORKAREA, 0 );
1898     eq( area.left,   old_area.left,   "left",   "%d" );
1899     eq( area.top,    old_area.top,    "top",    "%d" );
1900     /* size may be rounded */
1901     ok( area.right >= old_area.right - 16 && area.right < old_area.right + 16,
1902         "right: got %d instead of %d\n", area.right, old_area.right );
1903     ok( area.bottom >= old_area.bottom - 16 && area.bottom < old_area.bottom + 16,
1904         "bottom: got %d instead of %d\n", area.bottom, old_area.bottom );
1905 }
1906 
1907 static void test_SPI_SETSHOWSOUNDS( void )             /*     57 */
1908 {
1909     BOOL rc;
1910     BOOL old_b;
1911     const UINT vals[]={TRUE,FALSE};
1912     unsigned int i;
1913 
1914     trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1915     SetLastError(0xdeadbeef);
1916     rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1917     /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
1918     if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1919         return;
1920 
1921     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1922     {
1923         UINT v;
1924 
1925         rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1926                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1927         if (!test_error_msg(rc,"SPI_SETSHOWSOUNDS")) return;
1928         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1929         test_change_message( SPI_SETSHOWSOUNDS, 1 );
1930         test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1931                       SPI_SETSHOWSOUNDS_VALNAME,
1932                       vals[i] ? "1" : "0" );
1933 
1934         rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1935         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1936         eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1937         eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1938             "SM_SHOWSOUNDS", "%d" );
1939     }
1940 
1941     rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1942     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1943 }
1944 
1945 static void test_SPI_SETKEYBOARDPREF( void )           /*     69 */
1946 {
1947     BOOL rc;
1948     BOOL old_b;
1949     const UINT vals[]={TRUE,FALSE};
1950     unsigned int i;
1951 
1952     trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1953     SetLastError(0xdeadbeef);
1954     rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1955     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1956         return;
1957 
1958     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1959     {
1960         BOOL v;
1961 
1962         rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1963                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1964         if (!test_error_msg(rc,"SPI_SETKEYBOARDPREF")) return;
1965         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1966         test_change_message( SPI_SETKEYBOARDPREF, 1 );
1967         test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1968                           SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1969                           vals[i] ? "1" : "0" );
1970 
1971         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1972         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
1973         eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1974     }
1975 
1976     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1977     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
1978 }
1979 
1980 static void test_SPI_SETSCREENREADER( void )           /*     71 */
1981 {
1982     BOOL rc;
1983     BOOL old_b;
1984     const UINT vals[]={TRUE,FALSE};
1985     unsigned int i;
1986 
1987     trace("testing SPI_{GET,SET}SCREENREADER\n");
1988     SetLastError(0xdeadbeef);
1989     rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
1990     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
1991         return;
1992 
1993     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1994     {
1995         BOOL v;
1996 
1997         rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
1998                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1999         if (!test_error_msg(rc,"SPI_SETSCREENREADER")) return;
2000         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2001         test_change_message( SPI_SETSCREENREADER, 1 );
2002         test_reg_key_ex2_optional( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
2003                                    SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
2004                                    vals[i] ? "1" : "0" );
2005 
2006         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
2007         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2008         eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
2009     }
2010 
2011     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
2012     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2013 }
2014 
2015 static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
2016 {
2017     BOOL rc;
2018     BOOL old_b;
2019     DWORD old_type, old_contrast, old_orient;
2020     const UINT vals[]={0xffffffff,0,1,2};
2021     unsigned int i;
2022 
2023     trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
2024     if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */
2025     SetLastError(0xdeadbeef);
2026     rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
2027     if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
2028         return;
2029     SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &old_type, 0 );
2030     SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &old_contrast, 0 );
2031     SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &old_orient, 0 );
2032 
2033     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2034     {
2035         UINT v;
2036 
2037         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
2038                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2039         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHING")) return;
2040         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2041         test_change_message( SPI_SETFONTSMOOTHING, 0 );
2042         test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
2043                       SPI_SETFONTSMOOTHING_VALNAME,
2044                       vals[i] ? "2" : "0" );
2045 
2046         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, 0, UlongToPtr(vals[i]),
2047                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2048         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGTYPE")) return;
2049         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2050         test_change_message( SPI_SETFONTSMOOTHINGTYPE, 0 );
2051         test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2052                             SPI_SETFONTSMOOTHINGTYPE_VALNAME, &vals[i] );
2053 
2054         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, 0, UlongToPtr(vals[i]),
2055                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2056         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGCONTRAST")) return;
2057         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2058         test_change_message( SPI_SETFONTSMOOTHINGCONTRAST, 0 );
2059         test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2060                             SPI_SETFONTSMOOTHINGCONTRAST_VALNAME, &vals[i] );
2061 
2062         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, 0, UlongToPtr(vals[i]),
2063                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2064         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHINGORIENTATION")) return;
2065         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2066         test_change_message( SPI_SETFONTSMOOTHINGORIENTATION, 0 );
2067         test_reg_key_dword( SPI_SETFONTSMOOTHING_REGKEY,
2068                             SPI_SETFONTSMOOTHINGORIENTATION_VALNAME, &vals[i] );
2069 
2070         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
2071         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2072         eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
2073 
2074         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &v, 0 );
2075         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2076         ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2077 
2078         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &v, 0 );
2079         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2080         ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2081 
2082         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &v, 0 );
2083         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2084         ok( v == vals[i], "wrong value %x/%x\n", v, vals[i] );
2085     }
2086 
2087     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
2088     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2089     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, old_type, 0, SPIF_UPDATEINIFILE );
2090     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2091     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGCONTRAST, old_contrast, 0, SPIF_UPDATEINIFILE );
2092     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2093     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHINGORIENTATION, old_orient, 0, SPIF_UPDATEINIFILE );
2094     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2095 }
2096 
2097 static void test_SPI_SETLOWPOWERACTIVE( void )         /*     85 */
2098 {
2099     BOOL rc;
2100     BOOL old_b;
2101     const UINT vals[]={TRUE,FALSE};
2102     unsigned int i;
2103 
2104     trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
2105     SetLastError(0xdeadbeef);
2106     rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
2107     if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
2108         return;
2109 
2110     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2111     {
2112         UINT v;
2113 
2114         rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
2115                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2116         if (!test_error_msg(rc,"SPI_SETLOWPOWERACTIVE")) return;
2117         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2118         test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
2119         test_reg_key_optional( SPI_SETLOWPOWERACTIVE_REGKEY,
2120                                SPI_SETLOWPOWERACTIVE_VALNAME,
2121                                vals[i] ? "1" : "0" );
2122 
2123         /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
2124         v = 0xdeadbeef;
2125         rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
2126         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2127         ok(v == vals[i] ||
2128            broken(v == (0xdead0000 | vals[i])) ||  /* win98 only sets the low word */
2129            v == 0, /* win2k3 */
2130            "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2131     }
2132 
2133     rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2134     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2135 }
2136 
2137 static void test_SPI_SETPOWEROFFACTIVE( void )         /*     86 */
2138 {
2139     BOOL rc;
2140     BOOL old_b;
2141     const UINT vals[]={TRUE,FALSE};
2142     unsigned int i;
2143 
2144     trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
2145     SetLastError(0xdeadbeef);
2146     rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
2147     if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
2148         return;
2149 
2150     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2151     {
2152         UINT v;
2153 
2154         rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
2155                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2156         if (!test_error_msg(rc,"SPI_SETPOWEROFFACTIVE")) return;
2157         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2158         test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
2159         test_reg_key_optional( SPI_SETPOWEROFFACTIVE_REGKEY,
2160                                SPI_SETPOWEROFFACTIVE_VALNAME,
2161                                vals[i] ? "1" : "0" );
2162 
2163         /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
2164         v = 0xdeadbeef;
2165         rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
2166         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2167         ok(v == vals[i] ||
2168            broken(v == (0xdead0000 | vals[i])) ||  /* win98 only sets the low word */
2169            v == 0, /* win2k3 */
2170            "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2171     }
2172 
2173     rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2174     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2175 }
2176 
2177 static void test_SPI_SETSNAPTODEFBUTTON( void )         /*     95 */
2178 {
2179     BOOL rc;
2180     BOOL old_b;
2181     const UINT vals[]={TRUE,FALSE};
2182     unsigned int i;
2183 
2184     trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
2185     SetLastError(0xdeadbeef);
2186     rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
2187     if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
2188         return;
2189 
2190     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2191     {
2192         UINT v;
2193 
2194         rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
2195                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2196         if (!test_error_msg(rc,"SPI_SETSNAPTODEFBUTTON")) return;
2197         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2198         test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
2199         test_reg_key_optional( SPI_SETSNAPTODEFBUTTON_REGKEY,
2200                                SPI_SETSNAPTODEFBUTTON_VALNAME,
2201                                vals[i] ? "1" : "0" );
2202 
2203         rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2204         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2205         eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2206     }
2207 
2208     rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2209     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2210 }
2211 
2212 static void test_SPI_SETMOUSEHOVERWIDTH( void )      /*     99 */
2213 {
2214     BOOL rc;
2215     UINT old_width;
2216     const UINT vals[]={0,32767};
2217     unsigned int i;
2218 
2219     trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2220     SetLastError(0xdeadbeef);
2221     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2222     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2223     * what MSDN states (Verified on Win98SE)
2224     */
2225     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2226         return;
2227 
2228     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2229     {
2230         UINT v;
2231         char buf[10];
2232 
2233         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2234                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2235         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERWIDTH")) return;
2236         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2237         test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2238         sprintf( buf, "%d", vals[i] );
2239         test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
2240                       SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
2241 
2242         SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2243         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2244         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2245     }
2246 
2247     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2248                               SPIF_UPDATEINIFILE );
2249     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2250 }
2251 
2252 static void test_SPI_SETMOUSEHOVERHEIGHT( void )      /*     101 */
2253 {
2254     BOOL rc;
2255     UINT old_height;
2256     const UINT vals[]={0,32767};
2257     unsigned int i;
2258 
2259     trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2260     SetLastError(0xdeadbeef);
2261     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2262     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2263      * what MSDN states (Verified on Win98SE)
2264      */
2265     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2266         return;
2267 
2268     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2269     {
2270         UINT v;
2271         char buf[10];
2272 
2273         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2274                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2275         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERHEIGHT")) return;
2276         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2277         test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2278         sprintf( buf, "%d", vals[i] );
2279         test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2280                       SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2281 
2282         SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2283         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2284         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2285     }
2286 
2287     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2288                               SPIF_UPDATEINIFILE );
2289     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2290 }
2291 
2292 static void test_SPI_SETMOUSEHOVERTIME( void )      /*     103 */
2293 {
2294     BOOL rc;
2295     UINT old_time;
2296 
2297     /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2298      * defaulted to a value of 10 automatically.
2299      */
2300     const UINT vals[]={10,32767};
2301     unsigned int i;
2302 
2303     trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2304     SetLastError(0xdeadbeef);
2305     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2306     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2307      * what MSDN states (Verified on Win98SE)
2308      */
2309     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2310         return;
2311 
2312     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2313     {
2314         UINT v;
2315         char buf[10];
2316 
2317         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2318                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2319         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERTIME")) return;
2320         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2321         test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2322         sprintf( buf, "%d", vals[i] );
2323         test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2324                       SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2325 
2326         SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2327         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2328         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2329     }
2330 
2331     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2332                               SPIF_UPDATEINIFILE );
2333     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2334 }
2335 
2336 static void test_SPI_SETWHEELSCROLLLINES( void )      /*     105 */
2337 {
2338     BOOL rc;
2339     UINT old_lines;
2340     const UINT vals[]={0,32767};
2341     unsigned int i;
2342 
2343     trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2344     SetLastError(0xdeadbeef);
2345     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2346 
2347     /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2348     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2349         return;
2350 
2351     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2352     {
2353         UINT v;
2354         char buf[10];
2355 
2356         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2357                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2358         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLLINES")) return;
2359         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2360         test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2361         sprintf( buf, "%d", vals[i] );
2362         test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2363                       SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2364 
2365         SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2366         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2367         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2368     }
2369 
2370     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2371                               SPIF_UPDATEINIFILE );
2372     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2373 }
2374 
2375 static void test_SPI_SETMENUSHOWDELAY( void )      /*     107 */
2376 {
2377     BOOL rc;
2378     UINT old_delay;
2379     const UINT vals[]={0,32767};
2380     unsigned int i;
2381 
2382     trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2383     SetLastError(0xdeadbeef);
2384     rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2385 
2386     /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2387     if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2388         return;
2389 
2390     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2391     {
2392         UINT v;
2393         char buf[10];
2394 
2395         rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2396                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2397         if (!test_error_msg(rc,"SPI_SETMENUSHOWDELAY")) return;
2398         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2399         test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2400         sprintf( buf, "%d", vals[i] );
2401         test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2402                       SPI_SETMENUSHOWDELAY_VALNAME, buf );
2403 
2404         SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2405         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2406         eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2407     }
2408 
2409     rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2410                               SPIF_UPDATEINIFILE );
2411     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2412 }
2413 
2414 static void test_SPI_SETWHEELSCROLLCHARS( void )      /*     108 */
2415 {
2416     BOOL rc;
2417     UINT old_chars;
2418     const UINT vals[]={32767,0};
2419     unsigned int i;
2420 
2421     trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2422     SetLastError(0xdeadbeef);
2423     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2424 
2425     /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2426     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2427         return;
2428 
2429     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2430     {
2431         UINT v;
2432         char buf[10];
2433 
2434         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2435                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2436         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2437         test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2438         sprintf( buf, "%d", vals[i] );
2439         test_reg_key( SPI_SETMOUSESCROLLCHARS_REGKEY,
2440                       SPI_SETMOUSESCROLLCHARS_VALNAME, buf );
2441 
2442         SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2443         ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
2444         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2445     }
2446 
2447     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2448                               SPIF_UPDATEINIFILE );
2449     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2450 }
2451 
2452 static void test_SPI_SETWALLPAPER( void )              /*   115 */
2453 {
2454     BOOL rc;
2455     char oldval[260];
2456     char newval[260];
2457 
2458     trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2459     SetLastError(0xdeadbeef);
2460     rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2461     /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
2462      * unimplemented on NT4
2463      */
2464     if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2465         return;
2466 
2467     strcpy(newval, "");
2468     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2469     if (!test_error_msg(rc,"SPI_SETDESKWALLPAPER")) return;
2470     ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
2471     test_change_message(SPI_SETDESKWALLPAPER, 0);
2472 
2473     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2474     ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
2475 
2476     test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2477 }
2478 
2479 static void test_WM_DISPLAYCHANGE(void)
2480 {
2481     DEVMODEA mode, startmode;
2482     int start_bpp, last_set_bpp = 0;
2483     int test_bpps[] = {8, 16, 24, 32}, i;
2484     LONG change_ret;
2485     DWORD wait_ret;
2486 
2487     if (!pChangeDisplaySettingsExA)
2488     {
2489         win_skip("ChangeDisplaySettingsExA is not available\n");
2490         return;
2491     }
2492 
2493     displaychange_test_active = TRUE;
2494 
2495     memset(&startmode, 0, sizeof(startmode));
2496     startmode.dmSize = sizeof(startmode);
2497     EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &startmode);
2498     start_bpp = startmode.dmBitsPerPel;
2499 
2500     displaychange_sem = CreateSemaphoreW(NULL, 0, 1, NULL);
2501 
2502     for(i = 0; i < sizeof(test_bpps)/sizeof(test_bpps[0]); i++) {
2503         last_bpp = -1;
2504 
2505         memset(&mode, 0, sizeof(mode));
2506         mode.dmSize = sizeof(mode);
2507         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2508         mode.dmBitsPerPel = test_bpps[i];
2509         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2510         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2511 
2512         change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2513         displaychange_ok = TRUE;
2514         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2515         /* Wait quite long for the message, screen setting changes can take some time */
2516         if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2517             wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2518             /* we may not get a notification if nothing changed */
2519             if (wait_ret == WAIT_TIMEOUT && !last_set_bpp && start_bpp == test_bpps[i])
2520                 continue;
2521             ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2522         }
2523         displaychange_ok = FALSE;
2524 
2525         if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2526             skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2527             ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despite mode change failure\n", last_bpp);
2528             continue;
2529         }
2530 
2531         todo_wine_if(start_bpp != test_bpps[i]) {
2532             ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2533         }
2534         last_set_bpp = test_bpps[i];
2535     }
2536 
2537     if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2538         memset(&mode, 0, sizeof(mode));
2539         mode.dmSize = sizeof(mode);
2540         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2541         mode.dmBitsPerPel = start_bpp;
2542         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2543         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2544 
2545         displaychange_ok = TRUE;
2546         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2547         WaitForSingleObject(displaychange_sem, 10000);
2548         displaychange_ok = FALSE;
2549         CloseHandle(displaychange_sem);
2550         displaychange_sem = 0;
2551     }
2552 
2553     displaychange_test_active = FALSE;
2554 }
2555 
2556 /*
2557  * Registry entries for the system parameters.
2558  * Names are created by 'SET' flags names.
2559  * We assume that corresponding 'GET' entries use the same registry keys.
2560  */
2561 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2562 {
2563     test_SPI_SETBEEP();                         /*      1 */
2564     test_SPI_SETMOUSE();                        /*      4 */
2565     test_SPI_SETBORDER();                       /*      6 */
2566     test_SPI_SETKEYBOARDSPEED();                /*     10 */
2567     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
2568     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
2569     test_SPI_SETSCREENSAVEACTIVE();             /*     17 */
2570     test_SPI_SETGRIDGRANULARITY();              /*     19 */
2571     test_SPI_SETKEYBOARDDELAY();                /*     23 */
2572     test_SPI_ICONVERTICALSPACING();             /*     24 */
2573     test_SPI_SETICONTITLEWRAP();                /*     26 */
2574     test_SPI_SETMENUDROPALIGNMENT();            /*     28 */
2575     test_SPI_SETDOUBLECLKWIDTH();               /*     29 */
2576     test_SPI_SETDOUBLECLKHEIGHT();              /*     30 */
2577     test_SPI_SETDOUBLECLICKTIME();              /*     32 */
2578     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
2579     test_SPI_SETFASTTASKSWITCH();               /*     36 */
2580     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
2581     /* test_WM_DISPLAYCHANGE seems to be somewhat buggy on
2582      * some versions of Windows (Vista, Win2k8, Win7B) in that
2583      * not all metrics are properly restored. Problems are
2584      * SM_CXMAXTRACK, SM_CYMAXTRACK
2585      * Fortunately setting the Non-Client metrics like in
2586      * test_SPI_SETNONCLIENTMETRICS will correct this. That is why
2587      * we do the DISPLAY change now... */
2588     test_WM_DISPLAYCHANGE();
2589     test_SPI_SETNONCLIENTMETRICS();             /*     42 */
2590     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
2591     test_SPI_SETICONMETRICS();                  /*     46 */
2592     test_SPI_SETWORKAREA();                     /*     47 */
2593     test_SPI_SETSHOWSOUNDS();                   /*     57 */
2594     test_SPI_SETKEYBOARDPREF();                 /*     69 */
2595     test_SPI_SETSCREENREADER();                 /*     71 */
2596     test_SPI_SETFONTSMOOTHING();                /*     75 */
2597     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
2598     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
2599     test_SPI_SETSNAPTODEFBUTTON();              /*     95 */
2600     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
2601     test_SPI_SETMOUSEHOVERHEIGHT();             /*    101 */
2602     test_SPI_SETMOUSEHOVERTIME();               /*    103 */
2603     test_SPI_SETWHEELSCROLLLINES();             /*    105 */
2604     test_SPI_SETMENUSHOWDELAY();                /*    107 */
2605     test_SPI_SETWHEELSCROLLCHARS();             /*    108 */
2606     test_SPI_SETWALLPAPER();                    /*    115 */
2607 
2608 
2609     SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2610     return 0;
2611 }
2612 
2613 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2614  * icon metrics and minimized metrics.
2615  */
2616 
2617 /* copied from wine's GdiGetCharDimensions, which is not available on most
2618  * windows versions */
2619 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2620 {
2621     SIZE sz;
2622     static const CHAR alphabet[] = {
2623         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2624         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2625         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2626 
2627     if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2628 
2629     if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2630 
2631     if (height) *height = sz.cy;
2632     return (sz.cx / 26 + 1) / 2;
2633 }
2634 
2635 /* get text metrics and/or "average" char width of the specified logfont
2636  * for the specified dc */
2637 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2638 {
2639     HFONT hfont, hfontsav;
2640     TEXTMETRICA tm;
2641     if( !ptm) ptm = &tm;
2642     hfont = CreateFontIndirectA( plf);
2643     if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2644         ptm->tmHeight = -1;
2645         if( psz) *psz = 10;
2646         if( hfont) DeleteObject( hfont);
2647         return;
2648     }
2649     GetTextMetricsA( hdc, ptm);
2650     if( psz)
2651         if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2652             *psz = 10;
2653     SelectObject( hdc, hfontsav);
2654     DeleteObject( hfont);
2655 }
2656 
2657 static int gsm_error_ctr;
2658 
2659 #define ok_gsm( i, e)\
2660 {\
2661     int exp = (e);\
2662     int act = GetSystemMetrics( (i));\
2663     if( exp != act) gsm_error_ctr++;\
2664     ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2665 }
2666 #define ok_gsm_2( i, e1, e2)\
2667 {\
2668     int exp1 = (e1);\
2669     int exp2 = (e2);\
2670     int act = GetSystemMetrics( (i));\
2671     if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2672     ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2673 }
2674 #define ok_gsm_3( i, e1, e2, e3)\
2675 {\
2676     int exp1 = (e1);\
2677     int exp2 = (e2);\
2678     int exp3 = (e3);\
2679     int act = GetSystemMetrics( (i));\
2680     if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2681     ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2682 }
2683 
2684 static INT CALLBACK enum_all_fonts_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lparam)
2685 {
2686     return lstrcmpiA(elf->lfFaceName, (const char *)lparam);
2687 }
2688 
2689 static BOOL is_font_enumerated(const char *name)
2690 {
2691     HDC hdc = CreateCompatibleDC(0);
2692     BOOL ret = FALSE;
2693 
2694     if (!EnumFontFamiliesA(hdc, NULL, enum_all_fonts_proc, (LPARAM)name))
2695         ret = TRUE;
2696 
2697     DeleteDC(hdc);
2698     return ret;
2699 }
2700 
2701 static void test_GetSystemMetrics( void)
2702 {
2703     TEXTMETRICA tmMenuFont;
2704     UINT IconSpacing, IconVerticalSpacing;
2705     BOOL rc;
2706 
2707     HDC hdc = CreateICA( "Display", 0, 0, 0);
2708     UINT avcwCaption;
2709     INT CaptionWidthfromreg, smicon, broken_val;
2710     MINIMIZEDMETRICS minim;
2711     NONCLIENTMETRICSA ncm;
2712     SIZE screen;
2713 
2714     assert(sizeof(ncm) == 344);
2715 
2716     ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2717     rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2718     ok(rc, "SystemParametersInfoA failed\n");
2719 
2720     ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) - 1;
2721     rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2722     ok(!rc, "SystemParametersInfoA should fail\n");
2723 
2724     ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth) + 1;
2725     SetLastError(0xdeadbeef);
2726     rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2727     ok(!rc, "SystemParametersInfoA should fail\n");
2728 
2729     ncm.cbSize = sizeof(ncm); /* Vista added padding */
2730     SetLastError(0xdeadbeef);
2731     rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2732     ok(rc || broken(!rc) /* before Vista */, "SystemParametersInfoA failed\n");
2733 
2734     minim.cbSize = sizeof( minim);
2735     ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
2736     SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2737     rc = SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2738     if( !rc) {
2739         win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
2740         return;
2741     }
2742 
2743     ok(is_font_enumerated(ncm.lfCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfCaptionFont.lfFaceName);
2744     ok(is_font_enumerated(ncm.lfSmCaptionFont.lfFaceName), "font %s should be enumerated\n", ncm.lfSmCaptionFont.lfFaceName);
2745     ok(is_font_enumerated(ncm.lfMenuFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMenuFont.lfFaceName);
2746     ok(is_font_enumerated(ncm.lfStatusFont.lfFaceName), "font %s should be enumerated\n", ncm.lfStatusFont.lfFaceName);
2747     ok(is_font_enumerated(ncm.lfMessageFont.lfFaceName), "font %s should be enumerated\n", ncm.lfMessageFont.lfFaceName);
2748 
2749     /* CaptionWidth from the registry may have different value of iCaptionWidth
2750      * from the non client metrics (observed on WinXP) */
2751     CaptionWidthfromreg = metricfromreg(
2752             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2753     get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2754     get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2755     /* FIXME: use icon metric */
2756     if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2757         IconVerticalSpacing = 0;
2758     if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2759         IconSpacing = 0;
2760     /* reset error counters */
2761     gsm_error_ctr = 0;
2762 
2763     /* the tests: */
2764 
2765     /* SM_CXSCREEN, cannot test these two */
2766     /* SM_CYSCREEN */
2767     ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
2768     ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
2769     ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2770     ok_gsm( SM_CXBORDER, 1);
2771     ok_gsm( SM_CYBORDER, 1);
2772     ok_gsm( SM_CXDLGFRAME, 3);
2773     ok_gsm( SM_CYDLGFRAME, 3);
2774     ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
2775     ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
2776     /* These don't depend on the Shell Icon Size registry value */
2777     ok_gsm( SM_CXICON, MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI ) );
2778     ok_gsm( SM_CYICON, MulDiv( 32, dpi, USER_DEFAULT_SCREEN_DPI ) );
2779     /* SM_CXCURSOR */
2780     /* SM_CYCURSOR */
2781     ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2782     ok_gsm( SM_CXFULLSCREEN,
2783             GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2784     ok_gsm( SM_CYFULLSCREEN,
2785             GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2786     /* SM_CYKANJIWINDOW */
2787     /* SM_MOUSEPRESENT */
2788     ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2789     ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2790     /* SM_DEBUG */
2791     /* SM_SWAPBUTTON */
2792     /* SM_RESERVED1 */
2793     /* SM_RESERVED2 */
2794     /* SM_RESERVED3 */
2795     /* SM_RESERVED4 */
2796     ok_gsm( SM_CXMIN, 3 * max( CaptionWidthfromreg >= 0 ? CaptionWidthfromreg : ncm.iCaptionWidth, 8) +
2797             GetSystemMetrics( SM_CYSIZE) + 4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2798     ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2799             2 * GetSystemMetrics( SM_CYFRAME));
2800     ok_gsm_2( SM_CXSIZE,
2801         ncm.iCaptionWidth,  /* classic/standard windows style */
2802         GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2803         );
2804     ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
2805     ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2806     ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2807     ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
2808     ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
2809     /* SM_CXDOUBLECLK */
2810     /* SM_CYDOUBLECLK */
2811     if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2812     if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2813     /* SM_MENUDROPALIGNMENT */
2814     /* SM_PENWINDOWS */
2815     /* SM_DBCSENABLED */
2816     /* SM_CMOUSEBUTTONS */
2817     /* SM_SECURE */
2818     ok_gsm( SM_CXEDGE, 2);
2819     ok_gsm( SM_CYEDGE, 2);
2820     /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2821     ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + (short)minim.iHorzGap );
2822     ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + (short)minim.iVertGap );
2823 
2824     smicon = MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI );
2825     if (!pIsProcessDPIAware || pIsProcessDPIAware())
2826         smicon = max( min( smicon, CaptionWidthfromreg - 2), 4 ) & ~1;
2827     todo_wine_if( real_dpi == dpi && smicon != (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI) & ~1) )
2828     {
2829         broken_val = (min( ncm.iCaptionHeight, CaptionWidthfromreg ) - 2) & ~1;
2830         broken_val = min( broken_val, 20 );
2831 
2832         if (smicon == 4)
2833         {
2834             ok_gsm_2( SM_CXSMICON, smicon, 6 );
2835             ok_gsm_2( SM_CYSMICON, smicon, 6 );
2836         }
2837         else if (smicon < broken_val)
2838         {
2839             ok_gsm_2( SM_CXSMICON, smicon, broken_val );
2840             ok_gsm_2( SM_CYSMICON, smicon, broken_val );
2841         }
2842         else
2843         {
2844             ok_gsm( SM_CXSMICON, smicon );
2845             ok_gsm( SM_CYSMICON, smicon );
2846         }
2847     }
2848 
2849     ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2850     ok_gsm_3( SM_CXSMSIZE,
2851         ncm.iSmCaptionWidth, /* classic/standard windows style */
2852         GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2853         smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2854                       does not change it */
2855         );
2856     ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2857     ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2858     ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2859     /* SM_ARRANGE */
2860     ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2861     ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2862     screen.cx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
2863     screen.cy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
2864     if (!screen.cx || !screen.cy)  /* not supported on NT4 */
2865     {
2866         screen.cx = GetSystemMetrics( SM_CXSCREEN );
2867         screen.cy = GetSystemMetrics( SM_CYSCREEN );
2868     }
2869     ok_gsm_3( SM_CXMAXTRACK, screen.cx + 4 + 2 * GetSystemMetrics(SM_CXFRAME),
2870               screen.cx - 4 + 2 * GetSystemMetrics(SM_CXFRAME), /* Vista */
2871               screen.cx + 2 * GetSystemMetrics(SM_CXFRAME)); /* Win8 */
2872     ok_gsm_3( SM_CYMAXTRACK, screen.cy + 4 + 2 * GetSystemMetrics(SM_CYFRAME),
2873               screen.cy - 4 + 2 * GetSystemMetrics(SM_CYFRAME), /* Vista */
2874               screen.cy + 2 * GetSystemMetrics(SM_CYFRAME)); /* Win8 */
2875     /* the next two cannot really be tested as they depend on (application)
2876      * toolbars */
2877     /* SM_CXMAXIMIZED */
2878     /* SM_CYMAXIMIZED */
2879     /* SM_NETWORK */
2880     /* */
2881     /* */
2882     /* */
2883     /* SM_CLEANBOOT */
2884     /* SM_CXDRAG */
2885     /* SM_CYDRAG */
2886     /* SM_SHOWSOUNDS */
2887     ok_gsm( SM_CXMENUCHECK,
2888             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2889     ok_gsm( SM_CYMENUCHECK,
2890             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2891     /* SM_SLOWMACHINE */
2892     /* SM_MIDEASTENABLED */
2893     /* SM_MOUSEWHEELPRESENT */
2894     /* SM_XVIRTUALSCREEN */
2895     /* SM_YVIRTUALSCREEN */
2896     /* SM_CXVIRTUALSCREEN */
2897     /* SM_CYVIRTUALSCREEN */
2898     /* SM_CMONITORS */
2899     /* SM_SAMEDISPLAYFORMAT */
2900     /* SM_IMMENABLED */
2901     /* SM_CXFOCUSBORDER */
2902     /* SM_CYFOCUSBORDER */
2903     /* SM_TABLETPC */
2904     /* SM_MEDIACENTER */
2905     /* SM_CMETRICS */
2906     /* end of tests */
2907     if( gsm_error_ctr ) { /* if any errors where found */
2908         trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2909                 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2910         trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2911                 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2912         trace( "Captionfontchar width %d  MenuFont %d,%d CaptionWidth from registry: %d screen %d,%d\n",
2913                 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidthfromreg, screen.cx, screen.cy);
2914     }
2915     ReleaseDC( 0, hdc);
2916 }
2917 
2918 static void test_EnumDisplaySettings(void)
2919 {
2920     DEVMODEA devmode;
2921     DWORD val;
2922     HDC hdc;
2923     DWORD num;
2924 
2925     memset(&devmode, 0, sizeof(devmode));
2926     /* Win95 doesn't handle ENUM_CURRENT_SETTINGS correctly */
2927     EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2928 
2929     hdc = GetDC(0);
2930     val = GetDeviceCaps(hdc, BITSPIXEL);
2931     ok(devmode.dmBitsPerPel == val ||
2932         broken(devmode.dmDeviceName[0] == 0), /* Win95 */
2933         "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
2934         val, devmode.dmBitsPerPel);
2935 
2936     val = GetDeviceCaps(hdc, NUMCOLORS);
2937     if(devmode.dmBitsPerPel <= 8) {
2938         ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2939     } else {
2940         ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2941     }
2942 
2943     ReleaseDC(0, hdc);
2944 
2945     num = 1;
2946     while (1) {
2947         SetLastError (0xdeadbeef);
2948         if (!EnumDisplaySettingsA(NULL, num, &devmode)) {
2949             DWORD le = GetLastError();
2950             ok(le == ERROR_NO_MORE_FILES ||
2951                le == ERROR_MOD_NOT_FOUND /* Win8 */ ||
2952                le == 0xdeadbeef, /* XP, 2003 */
2953                "Expected ERROR_NO_MORE_FILES, ERROR_MOD_NOT_FOUND or 0xdeadbeef, got %d for %d\n", le, num);
2954             break;
2955 	}
2956 	num++;
2957     }
2958 }
2959 
2960 static void test_GetSysColorBrush(void)
2961 {
2962     HBRUSH hbr;
2963 
2964     SetLastError(0xdeadbeef);
2965     hbr = GetSysColorBrush(-1);
2966     ok(hbr == NULL, "Expected NULL brush\n");
2967     ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
2968     /* greater than max index */
2969     hbr = GetSysColorBrush(COLOR_MENUBAR);
2970     if (hbr)
2971     {
2972         SetLastError(0xdeadbeef);
2973         hbr = GetSysColorBrush(COLOR_MENUBAR + 1);
2974         ok(hbr == NULL, "Expected NULL brush\n");
2975         ok(GetLastError() == 0xdeadbeef, "Expected last error not set, got %x\n", GetLastError());
2976     }
2977     else
2978         win_skip("COLOR_MENUBAR unsupported\n");
2979 }
2980 
2981 static void test_dpi_aware(void)
2982 {
2983     BOOL ret;
2984 
2985     if (!pIsProcessDPIAware)
2986     {
2987         win_skip("IsProcessDPIAware not available\n");
2988         return;
2989     }
2990 
2991     ret = pSetProcessDPIAware();
2992     ok(ret, "got %d\n", ret);
2993 
2994     ret = pIsProcessDPIAware();
2995     ok(ret, "got %d\n", ret);
2996 
2997     dpi = real_dpi;
2998     test_GetSystemMetrics();
2999 }
3000 
3001 static void test_GetAutoRotationState(void)
3002 {
3003     AR_STATE state;
3004     BOOL ret;
3005 
3006     if (!pGetAutoRotationState)
3007     {
3008         win_skip("GetAutoRotationState not supported\n");
3009         return;
3010     }
3011 
3012     SetLastError(0xdeadbeef);
3013     ret = pGetAutoRotationState(NULL);
3014     ok(!ret, "Expected GetAutoRotationState to fail\n");
3015     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3016 
3017     state = 0;
3018     ret = pGetAutoRotationState(&state);
3019     ok(ret, "Expected GetAutoRotationState to succeed, error %d\n", GetLastError());
3020     ok((state & AR_NOSENSOR) != 0, "Expected AR_NOSENSOR, got %d\n", state);
3021 }
3022 
3023 START_TEST(sysparams)
3024 {
3025     int argc;
3026     char** argv;
3027     WNDCLASSA wc;
3028     MSG msg;
3029     HANDLE hThread;
3030     DWORD dwThreadId;
3031     HANDLE hInstance, hdll;
3032 
3033     hdll = GetModuleHandleA("user32.dll");
3034     pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
3035     pIsProcessDPIAware = (void*)GetProcAddress(hdll, "IsProcessDPIAware");
3036     pSetProcessDPIAware = (void*)GetProcAddress(hdll, "SetProcessDPIAware");
3037     pGetAutoRotationState = (void*)GetProcAddress(hdll, "GetAutoRotationState");
3038 
3039     hInstance = GetModuleHandleA( NULL );
3040     hdc = GetDC(0);
3041     dpi = GetDeviceCaps( hdc, LOGPIXELSY);
3042     real_dpi = get_real_dpi();
3043     trace("dpi %d real_dpi %d\n", dpi, real_dpi);
3044     iswin9x = GetVersion() & 0x80000000;
3045 
3046     /* This test requires interactivity, if we don't have it, give up */
3047     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
3048         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
3049 
3050     argc = winetest_get_mainargs(&argv);
3051     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
3052     trace("strict=%d\n",strict);
3053 
3054     trace("testing GetSystemMetrics with your current desktop settings\n");
3055     test_GetSystemMetrics( );
3056     trace("testing EnumDisplaySettings vs GetDeviceCaps\n");
3057     test_EnumDisplaySettings( );
3058     test_GetSysColorBrush( );
3059     test_GetAutoRotationState( );
3060 
3061     change_counter = 0;
3062     change_last_param = 0;
3063 
3064     wc.lpszClassName = "SysParamsTestClass";
3065     wc.lpfnWndProc = SysParamsTestWndProc;
3066     wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
3067     wc.hInstance = hInstance;
3068     wc.hIcon = LoadIconA( 0, (LPCSTR)IDI_APPLICATION );
3069     wc.hCursor = LoadCursorA( 0, (LPCSTR)IDC_ARROW );
3070     wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
3071     wc.lpszMenuName = 0;
3072     wc.cbClsExtra = 0;
3073     wc.cbWndExtra = 0;
3074     RegisterClassA( &wc );
3075 
3076     ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
3077                                WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
3078 
3079     hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
3080     assert( hThread );
3081     CloseHandle( hThread );
3082 
3083     while( GetMessageA( &msg, 0, 0, 0 )) {
3084         TranslateMessage( &msg );
3085         DispatchMessageA( &msg );
3086     }
3087     ReleaseDC( 0, hdc);
3088 
3089     test_dpi_aware();
3090 }
3091