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