user32/tests: Make some sysparams registry key optional, and fix some other failures...
[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         eq( v, vals[i], "SPI_{GET,SET}SCREENSAVEACTIVE", "%d" );
946     }
947
948     rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
949     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
950 }
951
952 static void test_SPI_SETGRIDGRANULARITY( void )        /*     19 */
953 {
954     /* ??? */;
955 }
956
957 static void test_SPI_SETKEYBOARDDELAY( void )          /*     23 */
958 {
959     BOOL rc;
960     UINT old_delay;
961     const UINT vals[]={0,3};
962     unsigned int i;
963
964     trace("testing SPI_{GET,SET}KEYBOARDDELAY\n");
965     SetLastError(0xdeadbeef);
966     rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &old_delay, 0 );
967     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
968         return;
969
970     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
971     {
972         UINT delay;
973         char buf[10];
974
975         rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, vals[i], 0,
976                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
977         if (!test_error_msg(rc,"SPI_SETKEYBOARDDELAY")) return;
978         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
979         test_change_message( SPI_SETKEYBOARDDELAY, 0 );
980         sprintf( buf, "%d", vals[i] );
981         test_reg_key( SPI_SETKEYBOARDDELAY_REGKEY,
982                       SPI_SETKEYBOARDDELAY_VALNAME, buf );
983
984         rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &delay, 0 );
985         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
986         eq( delay, vals[i], "SPI_{GET,SET}KEYBOARDDELAY", "%d" );
987     }
988
989     rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, old_delay, 0, SPIF_UPDATEINIFILE );
990     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
991 }
992
993
994 /* test_SPI_ICONVERTICALSPACING helper */
995 static BOOL dotest_spi_iconverticalspacing( INT curr_val)
996 {
997     BOOL rc;
998     INT spacing, regval;
999     ICONMETRICSA im;
1000
1001     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
1002                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1003     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING")) return FALSE;
1004     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1005     test_change_message( SPI_ICONVERTICALSPACING, 0 );
1006     if( curr_val < 32) curr_val = 32;
1007     /* The registry keys depend on the Windows version and the values too
1008      * let's test (works on win95,ME,NT4,2k,XP)
1009      */
1010     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY2, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1011     if( regval != curr_val)
1012         regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1013     ok( curr_val == regval,
1014         "wrong value in registry %d, expected %d\n", regval, curr_val);
1015     /* compare with what SPI_ICONVERTICALSPACING returns */
1016     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1017     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1018     eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
1019     /* and with a system metrics */
1020     eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
1021     /* and with what SPI_GETICONMETRICS returns */
1022     im.cbSize = sizeof(ICONMETRICSA);
1023     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1024     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1025     eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
1026     return TRUE;
1027 }
1028
1029 static void test_SPI_ICONVERTICALSPACING( void )       /*     24 */
1030 {
1031     BOOL rc;
1032     INT old_spacing;
1033
1034     trace("testing SPI_ICONVERTICALSPACING\n");
1035     SetLastError(0xdeadbeef);
1036     /* default value: 75 */
1037     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
1038     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
1039         return;
1040     /* do not increase the value as it would upset the user's icon layout */
1041     if (!dotest_spi_iconverticalspacing( old_spacing - 1)) return;
1042     /* same tests with a value less than the minimum 32 */
1043     dotest_spi_iconverticalspacing( 10);
1044     /* restore */
1045     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
1046                               SPIF_UPDATEINIFILE );
1047     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",
1048         rc,GetLastError());
1049 }
1050
1051 static void test_SPI_SETICONTITLEWRAP( void )          /*     26 */
1052 {
1053     BOOL rc;
1054     BOOL old_b;
1055     const UINT vals[]={TRUE,FALSE};
1056     unsigned int i;
1057     ICONMETRICSA im;
1058
1059     /* These tests hang when XFree86 4.0 for Windows is running (tested on
1060      * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
1061      * running.
1062      */
1063     if (FindWindowA( NULL, "Cygwin/XFree86" ))
1064         return;
1065
1066     trace("testing SPI_{GET,SET}ICONTITLEWRAP\n");
1067     SetLastError(0xdeadbeef);
1068     rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &old_b, 0 );
1069     if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
1070         return;
1071
1072     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1073     {
1074         UINT v;
1075         UINT regval;
1076
1077         rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, vals[i], 0,
1078                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1079         if (!test_error_msg(rc,"SPI_SETICONTITLEWRAP")) return;
1080         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1081         test_change_message( SPI_SETICONTITLEWRAP, 1 );
1082         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2,
1083                 SPI_SETICONTITLEWRAP_VALNAME, dpi);
1084         if( regval != vals[i])
1085             regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
1086                     SPI_SETICONTITLEWRAP_VALNAME, dpi);
1087         ok( regval == vals[i] || broken(regval == -1), /* win9x */
1088                 "wrong value in registry %d, expected %d\n", regval, vals[i] );
1089
1090         rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
1091         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1092         eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
1093         /* and test with what SPI_GETICONMETRICS returns */
1094         im.cbSize = sizeof(ICONMETRICSA);
1095         rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1096         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1097         eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
1098     }
1099
1100     rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, old_b, 0, SPIF_UPDATEINIFILE );
1101     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1102 }
1103
1104 static void test_SPI_SETMENUDROPALIGNMENT( void )      /*     28 */
1105 {
1106     BOOL rc;
1107     BOOL old_b;
1108     const UINT vals[]={TRUE,FALSE};
1109     unsigned int i;
1110
1111     trace("testing SPI_{GET,SET}MENUDROPALIGNMENT\n");
1112     SetLastError(0xdeadbeef);
1113     rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &old_b, 0 );
1114     if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
1115         return;
1116
1117     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1118     {
1119         UINT v;
1120
1121         rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, vals[i], 0,
1122                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1123         if (!test_error_msg(rc,"SPI_SETMENUDROPALIGNMENT")) return;
1124         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1125         test_change_message( SPI_SETMENUDROPALIGNMENT, 0 );
1126         test_reg_key_ex( SPI_SETMENUDROPALIGNMENT_REGKEY1,
1127                          SPI_SETMENUDROPALIGNMENT_REGKEY2,
1128                          SPI_SETMENUDROPALIGNMENT_VALNAME,
1129                          vals[i] ? "1" : "0" );
1130
1131         rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &v, 0 );
1132         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1133         eq( v, vals[i], "SPI_{GET,SET}MENUDROPALIGNMENT", "%d" );
1134         eq( GetSystemMetrics( SM_MENUDROPALIGNMENT ), (int)vals[i],
1135             "SM_MENUDROPALIGNMENT", "%d" );
1136     }
1137
1138     rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, old_b, 0,
1139                               SPIF_UPDATEINIFILE );
1140     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1141 }
1142
1143 static void test_SPI_SETDOUBLECLKWIDTH( void )         /*     29 */
1144 {
1145     BOOL rc;
1146     INT old_width;
1147     const UINT vals[]={0,10000};
1148     unsigned int i;
1149
1150     trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
1151     old_width = GetSystemMetrics( SM_CXDOUBLECLK );
1152
1153     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1154     {
1155         char buf[10];
1156
1157         SetLastError(0xdeadbeef);
1158         rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, vals[i], 0,
1159                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1160         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKWIDTH"))
1161             return;
1162
1163         test_change_message( SPI_SETDOUBLECLKWIDTH, 0 );
1164         sprintf( buf, "%d", vals[i] );
1165         test_reg_key_ex( SPI_SETDOUBLECLKWIDTH_REGKEY1,
1166                          SPI_SETDOUBLECLKWIDTH_REGKEY2,
1167                          SPI_SETDOUBLECLKWIDTH_VALNAME, buf );
1168         eq( GetSystemMetrics( SM_CXDOUBLECLK ), (int)vals[i],
1169             "SM_CXDOUBLECLK", "%d" );
1170     }
1171
1172     rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, old_width, 0,
1173                               SPIF_UPDATEINIFILE );
1174     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1175 }
1176
1177 static void test_SPI_SETDOUBLECLKHEIGHT( void )        /*     30 */
1178 {
1179     BOOL rc;
1180     INT old_height;
1181     const UINT vals[]={0,10000};
1182     unsigned int i;
1183
1184     trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
1185     old_height = GetSystemMetrics( SM_CYDOUBLECLK );
1186
1187     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1188     {
1189         char buf[10];
1190
1191         SetLastError(0xdeadbeef);
1192         rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, vals[i], 0,
1193                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1194         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKHEIGHT"))
1195             return;
1196
1197         test_change_message( SPI_SETDOUBLECLKHEIGHT, 0 );
1198         sprintf( buf, "%d", vals[i] );
1199         test_reg_key_ex( SPI_SETDOUBLECLKHEIGHT_REGKEY1,
1200                          SPI_SETDOUBLECLKHEIGHT_REGKEY2,
1201                          SPI_SETDOUBLECLKHEIGHT_VALNAME, buf );
1202         eq( GetSystemMetrics( SM_CYDOUBLECLK ), (int)vals[i],
1203             "SM_CYDOUBLECLK", "%d" );
1204     }
1205
1206     rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, old_height, 0,
1207                               SPIF_UPDATEINIFILE );
1208     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1209 }
1210
1211 static void test_SPI_SETDOUBLECLICKTIME( void )        /*     32 */
1212 {
1213     BOOL rc;
1214     UINT curr_val;
1215     UINT saved_val;
1216     UINT old_time;
1217     char buf[10];
1218
1219     trace("testing SPI_{GET,SET}DOUBLECLICKTIME\n");
1220     old_time = GetDoubleClickTime();
1221
1222     curr_val = 0;
1223     SetLastError(0xdeadbeef);
1224     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1225                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1226     if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLICKTIME"))
1227         return;
1228
1229     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1230     sprintf( buf, "%d", curr_val );
1231     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1232                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1233     curr_val = 500; /* used value for 0 */
1234     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1235
1236     curr_val = 1000;
1237     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1238                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1239     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1240     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1241     sprintf( buf, "%d", curr_val );
1242     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1243                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1244     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1245
1246     saved_val = curr_val;
1247
1248     curr_val = 0;
1249     SetDoubleClickTime( curr_val );
1250     sprintf( buf, "%d", saved_val );
1251     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1252                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1253     curr_val = 500; /* used value for 0 */
1254     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1255
1256     curr_val = 1000;
1257     SetDoubleClickTime( curr_val );
1258     sprintf( buf, "%d", saved_val );
1259     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1260                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1261     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1262
1263     rc=SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, old_time, 0, SPIF_UPDATEINIFILE);
1264     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1265 }
1266
1267 static void test_SPI_SETMOUSEBUTTONSWAP( void )        /*     33 */
1268 {
1269     BOOL rc;
1270     BOOL old_b;
1271     const UINT vals[]={TRUE,FALSE};
1272     unsigned int i;
1273
1274     trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
1275     old_b = GetSystemMetrics( SM_SWAPBUTTON );
1276
1277     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1278     {
1279         SetLastError(0xdeadbeef);
1280         rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
1281                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1282         if (!test_error_msg(rc,"SPI_SETMOUSEBUTTONSWAP")) return;
1283
1284         test_change_message( SPI_SETMOUSEBUTTONSWAP, 0 );
1285         test_reg_key( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1286                       SPI_SETMOUSEBUTTONSWAP_VALNAME,
1287                       vals[i] ? "1" : "0" );
1288         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
1289             "SM_SWAPBUTTON", "%d" );
1290         rc=SwapMouseButton((BOOL)vals[i^1]);
1291         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
1292             "SwapMouseButton", "%d" );
1293         ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
1294     }
1295
1296     rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, old_b, 0,
1297                               SPIF_UPDATEINIFILE );
1298     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1299 }
1300
1301 static void test_SPI_SETFASTTASKSWITCH( void )         /*     36 */
1302 {
1303     BOOL rc;
1304     BOOL v;
1305
1306     trace("testing SPI_GETFASTTASKSWITCH\n");
1307     SetLastError(0xdeadbeef);
1308     rc=SystemParametersInfoA( SPI_GETFASTTASKSWITCH, 0, &v, 0 );
1309     if (!test_error_msg(rc,"SPI_{GET,SET}FASTTASKSWITCH"))
1310         return;
1311
1312     /* there is not a single Windows platform on which SPI_GETFASTTASKSWITCH
1313      * works. That sure simplifies testing!
1314      */
1315 }
1316
1317 static void test_SPI_SETDRAGFULLWINDOWS( void )        /*     37 */
1318 {
1319     BOOL rc;
1320     BOOL old_b;
1321     const UINT vals[]={TRUE,FALSE};
1322     unsigned int i;
1323
1324     trace("testing SPI_{GET,SET}DRAGFULLWINDOWS\n");
1325     SetLastError(0xdeadbeef);
1326     rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &old_b, 0 );
1327
1328     /* SPI_{GET,SET}DRAGFULLWINDOWS is not implemented on Win95 */
1329     if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
1330         return;
1331
1332     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1333     {
1334         UINT v;
1335
1336         rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, vals[i], 0,
1337                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1338         if (!test_error_msg(rc,"SPI_SETDRAGFULLWINDOWS")) return;
1339         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1340         test_change_message( SPI_SETDRAGFULLWINDOWS, 0 );
1341         test_reg_key( SPI_SETDRAGFULLWINDOWS_REGKEY,
1342                       SPI_SETDRAGFULLWINDOWS_VALNAME,
1343                       vals[i] ? "1" : "0" );
1344
1345         rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &v, 0 );
1346         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1347         eq( v, vals[i], "SPI_{GET,SET}DRAGFULLWINDOWS", "%d" );
1348     }
1349
1350     rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, old_b, 0, SPIF_UPDATEINIFILE );
1351     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1352 }
1353
1354 #define test_reg_metric( KEY, VAL, val) \
1355 {   INT regval;\
1356     regval = metricfromreg( KEY, VAL, dpi);\
1357     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1358 }
1359  
1360 #define test_reg_metric2( KEY1, KEY2, VAL, val) \
1361 {   INT regval;\
1362     regval = metricfromreg( KEY1, VAL, dpi);\
1363     if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
1364     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1365 }
1366
1367 #define test_reg_font( KEY, VAL, LF) \
1368 {   LOGFONTA lfreg;\
1369     lffromreg( KEY, VAL, &lfreg);\
1370     ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == lfreg.lfHeight :\
1371                 MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
1372         (LF).lfWidth == lfreg.lfWidth &&\
1373         (LF).lfWeight == lfreg.lfWeight &&\
1374         !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
1375         , "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
1376 }
1377
1378 #define TEST_NONCLIENTMETRICS_REG( ncm) \
1379 /*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
1380 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
1381 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
1382 /*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
1383 test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
1384 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
1385 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
1386 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
1387 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
1388 test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
1389 test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
1390 test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
1391 test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
1392 test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont);
1393
1394 /* get text metric height value for the specified logfont */
1395 static int get_tmheight( LOGFONTA *plf, int flag)
1396 {
1397     TEXTMETRICA tm;
1398     HFONT hfont = CreateFontIndirectA( plf);
1399     hfont = SelectObject( hdc, hfont);
1400     GetTextMetricsA( hdc, &tm);
1401     hfont = SelectObject( hdc, hfont);
1402     return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1403 }
1404
1405 static void test_GetSystemMetrics( void);
1406 static UINT smcxsmsize = 999999999;
1407
1408 static void test_SPI_SETNONCLIENTMETRICS( void )               /*     44 */
1409 {
1410     BOOL rc;
1411     INT expect;
1412     NONCLIENTMETRICSA Ncmorig;
1413     NONCLIENTMETRICSA Ncmnew;
1414     NONCLIENTMETRICSA Ncmcur;
1415     NONCLIENTMETRICSA Ncmstart;
1416
1417     Ncmorig.cbSize = sizeof(NONCLIENTMETRICSA);
1418     Ncmnew.cbSize = sizeof(NONCLIENTMETRICSA);
1419     Ncmcur.cbSize = sizeof(NONCLIENTMETRICSA);
1420     Ncmstart.cbSize = sizeof(NONCLIENTMETRICSA);
1421
1422     trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1423     change_counter = 0;
1424     SetLastError(0xdeadbeef);
1425     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmorig, FALSE );
1426     if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1427         return;
1428     Ncmstart = Ncmorig;
1429     smcxsmsize = Ncmstart.iSmCaptionWidth;
1430     /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if 
1431        the caption font height is higher than the CaptionHeight field,
1432        the latter is adjusted accordingly. To be able to restore these setting
1433        accurately be restore the raw values. */
1434     Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, dpi);
1435     Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1436     Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1437     Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1438     /* test registry entries */
1439     TEST_NONCLIENTMETRICS_REG( Ncmorig)
1440     /* make small changes */
1441     Ncmnew = Ncmstart;
1442     Ncmnew.iBorderWidth += 1;
1443     Ncmnew.iScrollWidth += 1;
1444     Ncmnew.iScrollHeight -= 1;
1445     Ncmnew.iCaptionWidth -= 2;
1446     Ncmnew.iCaptionHeight += 2;
1447     Ncmnew.lfCaptionFont.lfHeight +=1;
1448     Ncmnew.lfCaptionFont.lfWidth +=2;
1449     Ncmnew.lfCaptionFont.lfWeight +=1;
1450     Ncmnew.iSmCaptionWidth += 1;
1451     Ncmnew.iSmCaptionHeight += 2;
1452     Ncmnew.lfSmCaptionFont.lfHeight +=3;
1453     Ncmnew.lfSmCaptionFont.lfWidth -=1;
1454     Ncmnew.lfSmCaptionFont.lfWeight +=3;
1455     Ncmnew.iMenuWidth += 1;
1456     Ncmnew.iMenuHeight += 2;
1457     Ncmnew.lfMenuFont.lfHeight +=1;
1458     Ncmnew.lfMenuFont.lfWidth +=1;
1459     Ncmnew.lfMenuFont.lfWeight +=2;
1460     Ncmnew.lfStatusFont.lfHeight -=1;
1461     Ncmnew.lfStatusFont.lfWidth -=1;
1462     Ncmnew.lfStatusFont.lfWeight +=3;
1463     Ncmnew.lfMessageFont.lfHeight -=2;
1464     Ncmnew.lfMessageFont.lfWidth -=1;
1465     Ncmnew.lfMessageFont.lfWeight +=4;
1466
1467     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1468             SPIF_SENDCHANGE);
1469     if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return;
1470     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1471     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1472     /* get them back */
1473     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1474     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1475     /* test registry entries */
1476     TEST_NONCLIENTMETRICS_REG( Ncmcur)
1477     /* test the system metrics with these settings */
1478     test_GetSystemMetrics();
1479     /* now for something invalid: increase the {menu|caption|smcaption} fonts
1480        by a large amount will increase the {menu|caption|smcaption} height*/
1481     Ncmnew = Ncmstart;
1482     Ncmnew.lfMenuFont.lfHeight -= 8;
1483     Ncmnew.lfCaptionFont.lfHeight =-4;
1484     Ncmnew.lfSmCaptionFont.lfHeight -=10;
1485     /* also show that a few values are lo limited */
1486     Ncmnew.iCaptionWidth = 0;
1487     Ncmnew.iCaptionHeight = 0;
1488     Ncmnew.iScrollHeight = 0;
1489     Ncmnew.iScrollWidth  = 0;
1490
1491     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1492             SPIF_SENDCHANGE);
1493     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1494     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1495     /* raw values are in registry */
1496     TEST_NONCLIENTMETRICS_REG( Ncmnew)
1497     /* get them back */
1498     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1499     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1500     /* cooked values are returned */
1501     expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1502     ok( Ncmcur.iMenuHeight == expect,
1503         "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1504     expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1505     ok( Ncmcur.iCaptionHeight == expect,
1506         "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1507     expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1508     ok( Ncmcur.iSmCaptionHeight == expect,
1509         "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1510
1511     ok( Ncmcur.iCaptionWidth == 8 ||
1512         Ncmcur.iCaptionWidth == 12 || /* Vista, W7b */
1513         Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme,  the value never changes */
1514         "CaptionWidth: %d expected 8, 12 or %d\n", Ncmcur.iCaptionWidth, Ncmstart.iCaptionWidth);
1515     ok( Ncmcur.iScrollWidth == 8,
1516         "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1517     ok( Ncmcur.iScrollHeight == 8,
1518         "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1519     /* test the system metrics with these settings */
1520     test_GetSystemMetrics();
1521     /* restore */
1522     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
1523         &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1524     test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1525     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1526     /* test the system metrics with these settings */
1527     test_GetSystemMetrics();
1528 }
1529
1530 static void test_SPI_SETMINIMIZEDMETRICS( void )               /*     44 */
1531 {
1532     BOOL rc;
1533     INT regval;
1534     MINIMIZEDMETRICS lpMm_orig;
1535     MINIMIZEDMETRICS lpMm_new;
1536     MINIMIZEDMETRICS lpMm_cur;
1537
1538     lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1539     lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1540     lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1541
1542     trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1543     SetLastError(0xdeadbeef);
1544     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1545     if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1546         return;
1547     /* Test registry. Note that it is perfectly valid for some fields to
1548      * not be set.
1549      */
1550     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1551     ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1552         regval, lpMm_orig.iWidth);
1553     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1554     ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1555         regval, lpMm_orig.iHorzGap);
1556     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1557     ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1558         regval, lpMm_orig.iVertGap);
1559     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1560     ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1561         regval, lpMm_orig.iArrange);
1562     /* set some new values */
1563     lpMm_cur.iWidth = 180;
1564     lpMm_cur.iHorzGap = 1;
1565     lpMm_cur.iVertGap = 1;
1566     lpMm_cur.iArrange = 5;
1567     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1568         &lpMm_cur, SPIF_UPDATEINIFILE );
1569     if (!test_error_msg(rc,"SPI_SETMINIMIZEDMETRICS")) return;
1570     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1571     /* read them back */
1572     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1573     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1574     /* and compare */
1575     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
1576     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1577     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1578     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1579     /* test registry */
1580     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1581     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1582         regval, lpMm_new.iWidth);
1583     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1584     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1585         regval, lpMm_new.iHorzGap);
1586     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1587     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1588         regval, lpMm_new.iVertGap);
1589     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1590     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1591         regval, lpMm_new.iArrange);
1592     /* test some system metrics */
1593     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1594         lpMm_new.iWidth,   "iWidth",   "%d" );
1595     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1596         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1597     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1598         lpMm_new.iVertGap, "iVertGap", "%d" );
1599     eq( GetSystemMetrics( SM_ARRANGE ),
1600         lpMm_new.iArrange, "iArrange", "%d" );
1601     /* now some really invalid settings */
1602     lpMm_cur.iWidth = -1;
1603     lpMm_cur.iHorzGap = -1;
1604     lpMm_cur.iVertGap = -1;
1605     lpMm_cur.iArrange = - 1;
1606     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1607         &lpMm_cur, SPIF_UPDATEINIFILE );
1608     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1609     /* read back */
1610     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1611     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1612     /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1613     eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
1614     eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1615     eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1616     eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1617     /* test registry */
1618     if (0)
1619     {
1620     /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1621     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1622     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1623         regval, lpMm_new.iWidth);
1624     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1625     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1626         regval, lpMm_new.iHorzGap);
1627     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1628     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1629         regval, lpMm_new.iVertGap);
1630     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1631     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1632         regval, lpMm_new.iArrange);
1633     }
1634     /* test some system metrics */
1635     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1636         lpMm_new.iWidth,   "iWidth",   "%d" );
1637     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1638         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1639     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1640         lpMm_new.iVertGap, "iVertGap", "%d" );
1641     eq( GetSystemMetrics( SM_ARRANGE ),
1642         lpMm_new.iArrange, "iArrange", "%d" );
1643     /* restore */
1644     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1645         &lpMm_orig, SPIF_UPDATEINIFILE );
1646     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1647     /* check that */
1648     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1649     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1650     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
1651     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1652     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1653     eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1654 }
1655
1656 static void test_SPI_SETICONMETRICS( void )               /*     46 */
1657 {
1658     BOOL rc, wrap;
1659     INT spacing;
1660     ICONMETRICSA im_orig;
1661     ICONMETRICSA im_new;
1662     ICONMETRICSA im_cur;
1663     INT regval;
1664         
1665     im_orig.cbSize = sizeof(ICONMETRICSA);
1666     im_new.cbSize = sizeof(ICONMETRICSA);
1667     im_cur.cbSize = sizeof(ICONMETRICSA);
1668
1669     trace("testing SPI_{GET,SET}ICONMETRICS\n");
1670     SetLastError(0xdeadbeef);
1671     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1672     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1673         return;
1674    /* check some registry values */ 
1675     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1676     ok( regval==im_orig.iHorzSpacing || broken(regval == -1), /* nt4 */
1677         "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1678     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1679     ok( regval==im_orig.iVertSpacing || broken(regval == -1), /* nt4 */
1680         "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1681     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1682     if( regval != im_orig.iTitleWrap)
1683         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1684     ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1685
1686     /* change everything without creating something invalid ( Win9x would ignore
1687      * an invalid font for instance) */
1688     im_cur = im_orig;
1689     im_cur.iHorzSpacing += 10;
1690     im_cur.iVertSpacing += 6;
1691     im_cur.iTitleWrap = !im_cur.iTitleWrap;
1692     im_cur.lfFont.lfHeight += 1;
1693     im_cur.lfFont.lfWidth += 2;
1694     im_cur.lfFont.lfEscapement = 1;
1695     im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1696     im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1697     im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1698     im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1699     im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1700     im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1701                                 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1702     im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1703     im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1704     im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ? 
1705                                 DRAFT_QUALITY : DEFAULT_QUALITY;
1706     if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1707         strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1708     else
1709         strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1710
1711     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1712     if (!test_error_msg(rc,"SPI_SETICONMETRICS")) return;
1713     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1714
1715     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1716     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1717     /* test GET <-> SETICONMETRICS */ 
1718     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1719     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1720     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
1721     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%d" );
1722     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%d" );
1723     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%d" );
1724     eq( im_new.lfFont.lfWeight,         im_cur.lfFont.lfWeight,         "lfWeight",         "%d" );
1725     eq( im_new.lfFont.lfItalic,         im_cur.lfFont.lfItalic,         "lfItalic",         "%d" );
1726     eq( im_new.lfFont.lfStrikeOut,      im_cur.lfFont.lfStrikeOut,      "lfStrikeOut",      "%d" );
1727     eq( im_new.lfFont.lfUnderline,      im_cur.lfFont.lfUnderline,      "lfUnderline",      "%d" );
1728     eq( im_new.lfFont.lfCharSet,        im_cur.lfFont.lfCharSet,        "lfCharSet",        "%d" );
1729     eq( im_new.lfFont.lfOutPrecision,   im_cur.lfFont.lfOutPrecision,   "lfOutPrecision",   "%d" );
1730     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
1731     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1732     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
1733     ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1734         "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1735         im_cur.lfFont.lfFaceName);
1736     /* test some system metrics */
1737     eq( GetSystemMetrics( SM_CXICONSPACING ),
1738         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1739     eq( GetSystemMetrics( SM_CYICONSPACING ),
1740         im_new.iVertSpacing, "iVertSpacing", "%d" );
1741    /* check some registry values */ 
1742     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1743     ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1744     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1745     ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1746     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1747     if( regval != im_cur.iTitleWrap)
1748         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1749     ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1750     /* test some values from other SPI_GETxxx calls */
1751     rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1752     ok( rc && spacing == im_cur.iHorzSpacing,
1753         "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1754         spacing, im_cur.iHorzSpacing);
1755     rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1756     ok( rc && spacing == im_cur.iVertSpacing,
1757         "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1758         spacing, im_cur.iVertSpacing);
1759     rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1760     ok( rc && wrap == im_cur.iTitleWrap,
1761         "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1762         wrap, im_cur.iTitleWrap);
1763     /* restore old values */
1764     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1765     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1766     
1767     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1768     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1769     
1770     eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1771     eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1772     eq( im_new.iTitleWrap,   im_orig.iTitleWrap,   "iTitleWrap",   "%d" );
1773 }
1774
1775 static void test_SPI_SETWORKAREA( void )               /*     47 */
1776 {
1777     BOOL rc;
1778     RECT old_area;
1779     RECT area;
1780     RECT curr_val;
1781
1782     trace("testing SPI_{GET,SET}WORKAREA\n");
1783     SetLastError(0xdeadbeef);
1784     rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1785     if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1786         return;
1787
1788     /* Modify the work area only minimally as this causes the icons that
1789      * fall outside it to be moved around thus requiring the user to
1790      * reposition them manually one by one.
1791      * Changing the work area by just one pixel should make this occurrence
1792      * reasonably unlikely.
1793      */
1794     curr_val.left = old_area.left;
1795     curr_val.top = old_area.top;
1796     curr_val.right = old_area.right-1;
1797     curr_val.bottom = old_area.bottom-1;
1798     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1799                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1800     if (!test_error_msg(rc,"SPI_SETWORKAREA")) return;
1801     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1802     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1803     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1804     if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1805         test_change_message( SPI_SETWORKAREA, 0);
1806     eq( area.left,   curr_val.left,   "left",   "%d" );
1807     eq( area.top,    curr_val.top,    "top",    "%d" );
1808     /* size may be rounded */
1809     ok( area.right >= curr_val.right - 16 && area.right < curr_val.right + 16,
1810         "right: got %d instead of %d\n", area.right, curr_val.right );
1811     ok( area.bottom >= curr_val.bottom - 16 && area.bottom < curr_val.bottom + 16,
1812         "bottom: got %d instead of %d\n", area.bottom, curr_val.bottom );
1813     curr_val = area;
1814     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1815                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1816     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1817     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1818     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1819     if( !EqualRect( &area, &curr_val)) /* no message if rect has not changed */
1820         test_change_message( SPI_SETWORKAREA, 0 );
1821     eq( area.left,   old_area.left,   "left",   "%d" );
1822     eq( area.top,    old_area.top,    "top",    "%d" );
1823     /* size may be rounded */
1824     ok( area.right >= old_area.right - 16 && area.right < old_area.right + 16,
1825         "right: got %d instead of %d\n", area.right, old_area.right );
1826     ok( area.bottom >= old_area.bottom - 16 && area.bottom < old_area.bottom + 16,
1827         "bottom: got %d instead of %d\n", area.bottom, old_area.bottom );
1828 }
1829
1830 static void test_SPI_SETSHOWSOUNDS( void )             /*     57 */
1831 {
1832     BOOL rc;
1833     BOOL old_b;
1834     const UINT vals[]={TRUE,FALSE};
1835     unsigned int i;
1836
1837     trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1838     SetLastError(0xdeadbeef);
1839     rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1840     /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
1841     if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1842         return;
1843
1844     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1845     {
1846         UINT v;
1847
1848         rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1849                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1850         if (!test_error_msg(rc,"SPI_SETSHOWSOUNDS")) return;
1851         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1852         test_change_message( SPI_SETSHOWSOUNDS, 1 );
1853         test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1854                       SPI_SETSHOWSOUNDS_VALNAME,
1855                       vals[i] ? "1" : "0" );
1856
1857         rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1858         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1859         eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1860         eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1861             "SM_SHOWSOUNDS", "%d" );
1862     }
1863
1864     rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1865     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1866 }
1867
1868 static void test_SPI_SETKEYBOARDPREF( void )           /*     69 */
1869 {
1870     BOOL rc;
1871     BOOL old_b;
1872     const UINT vals[]={TRUE,FALSE};
1873     unsigned int i;
1874
1875     trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1876     SetLastError(0xdeadbeef);
1877     rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1878     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1879         return;
1880
1881     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1882     {
1883         BOOL v;
1884
1885         rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1886                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1887         if (!test_error_msg(rc,"SPI_SETKEYBOARDPREF")) return;
1888         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1889         test_change_message( SPI_SETKEYBOARDPREF, 1 );
1890         test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1891                           SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1892                           vals[i] ? "1" : "0" );
1893
1894         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1895         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1896         eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1897     }
1898
1899     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1900     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1901 }
1902
1903 static void test_SPI_SETSCREENREADER( void )           /*     71 */
1904 {
1905     BOOL rc;
1906     BOOL old_b;
1907     const UINT vals[]={TRUE,FALSE};
1908     unsigned int i;
1909
1910     trace("testing SPI_{GET,SET}SCREENREADER\n");
1911     SetLastError(0xdeadbeef);
1912     rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
1913     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
1914         return;
1915
1916     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1917     {
1918         BOOL v;
1919
1920         rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
1921                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1922         if (!test_error_msg(rc,"SPI_SETSCREENREADER")) return;
1923         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1924         test_change_message( SPI_SETSCREENREADER, 1 );
1925         test_reg_key_ex2_optional( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
1926                                    SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
1927                                    vals[i] ? "1" : "0" );
1928
1929         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
1930         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1931         eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
1932     }
1933
1934     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
1935     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1936 }
1937
1938 static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
1939 {
1940     BOOL rc;
1941     BOOL old_b;
1942     const UINT vals[]={0xffffffff,0,1,2};
1943     unsigned int i;
1944
1945     trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
1946     if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */ 
1947     SetLastError(0xdeadbeef);
1948     rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
1949     if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
1950         return;
1951
1952     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1953     {
1954         UINT v;
1955
1956         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
1957                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1958         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHING")) return;
1959         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1960         test_change_message( SPI_SETFONTSMOOTHING, 0 );
1961         test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
1962                       SPI_SETFONTSMOOTHING_VALNAME,
1963                       vals[i] ? "2" : "0" );
1964
1965         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
1966         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1967         eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
1968     }
1969
1970     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
1971     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1972 }
1973
1974 static void test_SPI_SETLOWPOWERACTIVE( void )         /*     85 */
1975 {
1976     BOOL rc;
1977     BOOL old_b;
1978     const UINT vals[]={TRUE,FALSE};
1979     unsigned int i;
1980
1981     trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
1982     SetLastError(0xdeadbeef);
1983     rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
1984     if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
1985         return;
1986
1987     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1988     {
1989         UINT v;
1990
1991         rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
1992                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1993         if (!test_error_msg(rc,"SPI_SETLOWPOWERACTIVE")) return;
1994         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1995         test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
1996         test_reg_key_optional( SPI_SETLOWPOWERACTIVE_REGKEY,
1997                                SPI_SETLOWPOWERACTIVE_VALNAME,
1998                                vals[i] ? "1" : "0" );
1999
2000         /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
2001         v = 0xdeadbeef;
2002         rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
2003         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2004         ok(v == vals[i] ||
2005            broken(v == (0xdead0000 | vals[i])) ||  /* win98 only sets the low word */
2006            v == 0, /* win2k3 */
2007            "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2008     }
2009
2010     rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2011     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2012 }
2013
2014 static void test_SPI_SETPOWEROFFACTIVE( void )         /*     86 */
2015 {
2016     BOOL rc;
2017     BOOL old_b;
2018     const UINT vals[]={TRUE,FALSE};
2019     unsigned int i;
2020
2021     trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
2022     SetLastError(0xdeadbeef);
2023     rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
2024     if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
2025         return;
2026
2027     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2028     {
2029         UINT v;
2030
2031         rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
2032                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2033         if (!test_error_msg(rc,"SPI_SETPOWEROFFACTIVE")) return;
2034         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2035         test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
2036         test_reg_key_optional( SPI_SETPOWEROFFACTIVE_REGKEY,
2037                                SPI_SETPOWEROFFACTIVE_VALNAME,
2038                                vals[i] ? "1" : "0" );
2039
2040         /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
2041         v = 0xdeadbeef;
2042         rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
2043         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2044         ok(v == vals[i] ||
2045            broken(v == (0xdead0000 | vals[i])) ||  /* win98 only sets the low word */
2046            v == 0, /* win2k3 */
2047            "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2048     }
2049
2050     rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2051     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2052 }
2053
2054 static void test_SPI_SETSNAPTODEFBUTTON( void )         /*     95 */
2055 {
2056     BOOL rc;
2057     BOOL old_b;
2058     const UINT vals[]={TRUE,FALSE};
2059     unsigned int i;
2060
2061     trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
2062     SetLastError(0xdeadbeef);
2063     rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
2064     if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
2065         return;
2066
2067     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2068     {
2069         UINT v;
2070
2071         rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
2072                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2073         if (!test_error_msg(rc,"SPI_SETSNAPTODEFBUTTON")) return;
2074         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2075         test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
2076         test_reg_key_optional( SPI_SETSNAPTODEFBUTTON_REGKEY,
2077                                SPI_SETSNAPTODEFBUTTON_VALNAME,
2078                                vals[i] ? "1" : "0" );
2079
2080         rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2081         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2082         eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2083     }
2084
2085     rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2086     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2087 }
2088
2089 static void test_SPI_SETMOUSEHOVERWIDTH( void )      /*     99 */
2090 {
2091     BOOL rc;
2092     UINT old_width;
2093     const UINT vals[]={0,32767};
2094     unsigned int i;
2095
2096     trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2097     SetLastError(0xdeadbeef);
2098     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2099     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2100     * what MSDN states (Verified on Win98SE)
2101     */
2102     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2103         return;
2104     
2105     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2106     {
2107         UINT v;
2108         char buf[10];
2109
2110         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2111                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2112         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERWIDTH")) return;
2113         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2114         test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2115         sprintf( buf, "%d", vals[i] );
2116         test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
2117                       SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
2118
2119         SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2120         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2121         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2122     }
2123
2124     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2125                               SPIF_UPDATEINIFILE );
2126     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2127 }
2128
2129 static void test_SPI_SETMOUSEHOVERHEIGHT( void )      /*     101 */
2130 {
2131     BOOL rc;
2132     UINT old_height;
2133     const UINT vals[]={0,32767};
2134     unsigned int i;
2135
2136     trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2137     SetLastError(0xdeadbeef);
2138     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2139     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2140      * what MSDN states (Verified on Win98SE)
2141      */
2142     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2143         return;
2144     
2145     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2146     {
2147         UINT v;
2148         char buf[10];
2149
2150         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2151                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2152         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERHEIGHT")) return;
2153         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2154         test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2155         sprintf( buf, "%d", vals[i] );
2156         test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2157                       SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2158
2159         SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2160         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2161         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2162     }
2163
2164     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2165                               SPIF_UPDATEINIFILE );
2166     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2167 }
2168
2169 static void test_SPI_SETMOUSEHOVERTIME( void )      /*     103 */
2170 {
2171     BOOL rc;
2172     UINT old_time;
2173
2174     /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2175      * defaulted to a value of 10 automatically.
2176      */
2177     const UINT vals[]={10,32767};
2178     unsigned int i;
2179
2180     trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2181     SetLastError(0xdeadbeef);
2182     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2183     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2184      * what MSDN states (Verified on Win98SE)
2185      */    
2186     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2187         return;
2188     
2189     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2190     {
2191         UINT v;
2192         char buf[10];
2193
2194         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2195                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2196         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERTIME")) return;
2197         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2198         test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2199         sprintf( buf, "%d", vals[i] );
2200         test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2201                       SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2202
2203         SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2204         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2205         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2206     }
2207
2208     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2209                               SPIF_UPDATEINIFILE );
2210     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2211 }
2212
2213 static void test_SPI_SETWHEELSCROLLLINES( void )      /*     105 */
2214 {
2215     BOOL rc;
2216     UINT old_lines;
2217     const UINT vals[]={0,32767};
2218     unsigned int i;
2219
2220     trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2221     SetLastError(0xdeadbeef);
2222     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2223
2224     /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2225     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2226         return;
2227
2228     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2229     {
2230         UINT v;
2231         char buf[10];
2232
2233         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2234                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2235         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLLINES")) return;
2236         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2237         test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2238         sprintf( buf, "%d", vals[i] );
2239         test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2240                       SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2241
2242         SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2243         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2244         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2245     }
2246
2247     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2248                               SPIF_UPDATEINIFILE );
2249     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2250 }
2251
2252 static void test_SPI_SETMENUSHOWDELAY( void )      /*     107 */
2253 {
2254     BOOL rc;
2255     UINT old_delay;
2256     const UINT vals[]={0,32767};
2257     unsigned int i;
2258
2259     trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2260     SetLastError(0xdeadbeef);
2261     rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2262
2263     /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2264     if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2265         return;
2266
2267     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2268     {
2269         UINT v;
2270         char buf[10];
2271
2272         rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2273                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2274         if (!test_error_msg(rc,"SPI_SETMENUSHOWDELAY")) return;
2275         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2276         test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2277         sprintf( buf, "%d", vals[i] );
2278         test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2279                       SPI_SETMENUSHOWDELAY_VALNAME, buf );
2280
2281         SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2282         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2283         eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2284     }
2285
2286     rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2287                               SPIF_UPDATEINIFILE );
2288     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2289 }
2290
2291 static void test_SPI_SETWHEELSCROLLCHARS( void )      /*     108 */
2292 {
2293     BOOL rc;
2294     UINT old_chars;
2295     const UINT vals[]={32767,0};
2296     unsigned int i;
2297
2298     trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2299     SetLastError(0xdeadbeef);
2300     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2301
2302     /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2303     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2304         return;
2305
2306     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2307     {
2308         UINT v;
2309         char buf[10];
2310
2311         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2312                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2313         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2314         test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2315         sprintf( buf, "%d", vals[i] );
2316         test_reg_key( SPI_SETMOUSESCROLLCHARS_REGKEY,
2317                       SPI_SETMOUSESCROLLCHARS_VALNAME, buf );
2318
2319         SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2320         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2321         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2322     }
2323
2324     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2325                               SPIF_UPDATEINIFILE );
2326     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2327 }
2328
2329 static void test_SPI_SETWALLPAPER( void )              /*   115 */
2330 {
2331     BOOL rc;
2332     char oldval[260];
2333     char newval[260];
2334
2335     trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2336     SetLastError(0xdeadbeef);
2337     rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2338     /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
2339      * unimplemented on NT4
2340      */
2341     if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2342         return;
2343
2344     strcpy(newval, "");
2345     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2346     if (!test_error_msg(rc,"SPI_SETDESKWALLPAPER")) return;
2347     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
2348     test_change_message(SPI_SETDESKWALLPAPER, 0);
2349
2350     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2351     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2352
2353     test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2354 }
2355
2356 static void test_WM_DISPLAYCHANGE(void)
2357 {
2358     DEVMODE mode, startmode;
2359     int start_bpp, last_set_bpp = 0;
2360     int test_bpps[] = {8, 16, 24, 32}, i;
2361     LONG change_ret;
2362     DWORD wait_ret;
2363
2364     if (!pChangeDisplaySettingsExA)
2365     {
2366         win_skip("ChangeDisplaySettingsExA is not available\n");
2367         return;
2368     }
2369
2370     displaychange_test_active = TRUE;
2371
2372     memset(&startmode, 0, sizeof(startmode));
2373     startmode.dmSize = sizeof(startmode);
2374     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &startmode);
2375     start_bpp = startmode.dmBitsPerPel;
2376
2377     displaychange_sem = CreateSemaphore(NULL, 0, 1, NULL);
2378
2379     for(i = 0; i < sizeof(test_bpps)/sizeof(test_bpps[0]); i++) {
2380         last_bpp = -1;
2381
2382         memset(&mode, 0, sizeof(mode));
2383         mode.dmSize = sizeof(mode);
2384         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2385         mode.dmBitsPerPel = test_bpps[i];
2386         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2387         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2388
2389         change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2390         displaychange_ok = TRUE;
2391         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2392         /* Wait quite long for the message, screen setting changes can take some time */
2393         if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2394             wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2395             /* we may not get a notification if nothing changed */
2396             if (wait_ret == WAIT_TIMEOUT && !last_set_bpp && start_bpp == test_bpps[i])
2397                 continue;
2398             ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2399         }
2400         displaychange_ok = FALSE;
2401
2402         if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2403             skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2404             ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despite mode change failure\n", last_bpp);
2405             continue;
2406         }
2407
2408         if(start_bpp != test_bpps[i]) {
2409             todo_wine ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2410         } else {
2411             ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2412         }
2413         last_set_bpp = test_bpps[i];
2414     }
2415
2416     if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2417         memset(&mode, 0, sizeof(mode));
2418         mode.dmSize = sizeof(mode);
2419         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2420         mode.dmBitsPerPel = start_bpp;
2421         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2422         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2423
2424         displaychange_ok = TRUE;
2425         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2426         WaitForSingleObject(displaychange_sem, 10000);
2427         displaychange_ok = FALSE;
2428         CloseHandle(displaychange_sem);
2429         displaychange_sem = 0;
2430     }
2431
2432     displaychange_test_active = FALSE;
2433 }
2434
2435 /*
2436  * Registry entries for the system parameters.
2437  * Names are created by 'SET' flags names.
2438  * We assume that corresponding 'GET' entries use the same registry keys.
2439  */
2440 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2441 {
2442     test_SPI_SETBEEP();                         /*      1 */
2443     test_SPI_SETMOUSE();                        /*      4 */
2444     test_SPI_SETBORDER();                       /*      6 */
2445     test_SPI_SETKEYBOARDSPEED();                /*     10 */
2446     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
2447     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
2448     test_SPI_SETSCREENSAVEACTIVE();             /*     17 */
2449     test_SPI_SETGRIDGRANULARITY();              /*     19 */
2450     test_SPI_SETKEYBOARDDELAY();                /*     23 */
2451     test_SPI_ICONVERTICALSPACING();             /*     24 */
2452     test_SPI_SETICONTITLEWRAP();                /*     26 */
2453     test_SPI_SETMENUDROPALIGNMENT();            /*     28 */
2454     test_SPI_SETDOUBLECLKWIDTH();               /*     29 */
2455     test_SPI_SETDOUBLECLKHEIGHT();              /*     30 */
2456     test_SPI_SETDOUBLECLICKTIME();              /*     32 */
2457     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
2458     test_SPI_SETFASTTASKSWITCH();               /*     36 */
2459     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
2460     /* test_WM_DISPLAYCHANGE seems to be somewhat buggy on
2461      * some versions of Windows (Vista, Win2k8, Win7B) in that
2462      * not all metrics are properly restored. Problems are
2463      * SM_CXMAXTRACK, SM_CYMAXTRACK
2464      * Fortunately setting the Non-Client metrics like in
2465      * test_SPI_SETNONCLIENTMETRICS will corect this. That is why
2466      * we do the DISPLAY change now... */
2467     test_WM_DISPLAYCHANGE();
2468     test_SPI_SETNONCLIENTMETRICS();             /*     42 */
2469     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
2470     test_SPI_SETICONMETRICS();                  /*     46 */
2471     test_SPI_SETWORKAREA();                     /*     47 */
2472     test_SPI_SETSHOWSOUNDS();                   /*     57 */
2473     test_SPI_SETKEYBOARDPREF();                 /*     69 */
2474     test_SPI_SETSCREENREADER();                 /*     71 */
2475     test_SPI_SETFONTSMOOTHING();                /*     75 */
2476     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
2477     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
2478     test_SPI_SETSNAPTODEFBUTTON();              /*     95 */
2479     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
2480     test_SPI_SETMOUSEHOVERHEIGHT();             /*    101 */
2481     test_SPI_SETMOUSEHOVERTIME();               /*    103 */
2482     test_SPI_SETWHEELSCROLLLINES();             /*    105 */
2483     test_SPI_SETMENUSHOWDELAY();                /*    107 */
2484     test_SPI_SETWHEELSCROLLCHARS();             /*    108 */
2485     test_SPI_SETWALLPAPER();                    /*    115 */
2486
2487
2488     SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2489     return 0;
2490 }
2491
2492 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2493  * icon metrics and minimized metrics. 
2494  */
2495
2496 /* copied from wine's GdiGetCharDimensions, which is not available on most
2497  * windows versions */
2498 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2499 {
2500     SIZE sz;
2501     static const CHAR alphabet[] = {
2502         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2503         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2504         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2505
2506     if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2507
2508     if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2509
2510     if (height) *height = sz.cy;
2511     return (sz.cx / 26 + 1) / 2;
2512 }
2513
2514 /* get text metrics and/or "average" char width of the specified logfont
2515  * for the specified dc */
2516 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2517 {
2518     HFONT hfont, hfontsav;
2519     TEXTMETRICA tm;
2520     if( !ptm) ptm = &tm;
2521     hfont = CreateFontIndirectA( plf);
2522     if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2523         ptm->tmHeight = -1;
2524         if( psz) *psz = 10;
2525         if( hfont) DeleteObject( hfont);
2526         return;
2527     }
2528     GetTextMetricsA( hdc, ptm);
2529     if( psz)
2530         if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2531             *psz = 10;
2532     SelectObject( hdc, hfontsav);
2533     DeleteObject( hfont);
2534 }
2535
2536 static int gsm_error_ctr;
2537
2538 #define ok_gsm( i, e)\
2539 {\
2540     int exp = (e);\
2541     int act = GetSystemMetrics( (i));\
2542     if( exp != act) gsm_error_ctr++;\
2543     ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2544 }
2545 #define ok_gsm_2( i, e1, e2)\
2546 {\
2547     int exp1 = (e1);\
2548     int exp2 = (e2);\
2549     int act = GetSystemMetrics( (i));\
2550     if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2551     ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2552 }
2553 #define ok_gsm_3( i, e1, e2, e3)\
2554 {\
2555     int exp1 = (e1);\
2556     int exp2 = (e2);\
2557     int exp3 = (e3);\
2558     int act = GetSystemMetrics( (i));\
2559     if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2560     ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2561 }
2562
2563 static void test_GetSystemMetrics( void)
2564 {
2565     TEXTMETRICA tmMenuFont;
2566     UINT IconSpacing, IconVerticalSpacing;
2567     BOOL rc;
2568
2569     HDC hdc = CreateIC( "Display", 0, 0, 0);
2570     UINT avcwCaption;
2571     INT CaptionWidthfromreg;
2572     MINIMIZEDMETRICS minim;
2573     NONCLIENTMETRICS ncm;
2574     SIZE screen;
2575
2576     minim.cbSize = sizeof( minim);
2577     ncm.cbSize = sizeof( ncm);
2578     SystemParametersInfo( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2579     rc = SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2580     if( !rc) {
2581         win_skip("SPI_GETNONCLIENTMETRICS is not available\n");
2582         return;
2583     }
2584     /* CaptionWidth from the registry may have different value of iCaptionWidth
2585      * from the non client metrics (observed on WinXP) */
2586     CaptionWidthfromreg = metricfromreg(
2587             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2588     get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2589     get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2590     /* FIXME: use icon metric */
2591     if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2592         IconVerticalSpacing = 0;
2593     if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2594         IconSpacing = 0;
2595     /* reset error counters */
2596     gsm_error_ctr = 0;
2597
2598     /* the tests: */
2599
2600     /* SM_CXSCREEN, cannot test these two */
2601     /* SM_CYSCREEN */
2602     ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
2603     ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
2604     ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2605     ok_gsm( SM_CXBORDER, 1);
2606     ok_gsm( SM_CYBORDER, 1);
2607     ok_gsm( SM_CXDLGFRAME, 3);
2608     ok_gsm( SM_CYDLGFRAME, 3);
2609     ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
2610     ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
2611     /* SM_CXICON */
2612     /* SM_CYICON */
2613     /* SM_CXCURSOR */
2614     /* SM_CYCURSOR */
2615     ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2616     ok_gsm( SM_CXFULLSCREEN,
2617             GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2618     ok_gsm( SM_CYFULLSCREEN,
2619             GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2620     /* SM_CYKANJIWINDOW */
2621     /* SM_MOUSEPRESENT */
2622     ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2623     ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2624     /* SM_DEBUG */
2625     /* SM_SWAPBUTTON */
2626     /* SM_RESERVED1 */
2627     /* SM_RESERVED2 */
2628     /* SM_RESERVED3 */
2629     /* SM_RESERVED4 */
2630     ok_gsm( SM_CXMIN, 3 * max( CaptionWidthfromreg >= 0 ? CaptionWidthfromreg : ncm.iCaptionWidth, 8) +
2631             GetSystemMetrics( SM_CYSIZE) + 4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2632     ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2633             2 * GetSystemMetrics( SM_CYFRAME));
2634     ok_gsm_2( SM_CXSIZE,
2635         ncm.iCaptionWidth,  /* classic/standard windows style */
2636         GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2637         );
2638     ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
2639     ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2640     ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2641     ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
2642     ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
2643     /* SM_CXDOUBLECLK */
2644     /* SM_CYDOUBLECLK */
2645     if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2646     if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2647     /* SM_MENUDROPALIGNMENT */
2648     /* SM_PENWINDOWS */
2649     /* SM_DBCSENABLED */
2650     /* SM_CMOUSEBUTTONS */
2651     /* SM_SECURE */
2652     ok_gsm( SM_CXEDGE, 2);
2653     ok_gsm( SM_CYEDGE, 2);
2654     /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2655     ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + (short)minim.iHorzGap );
2656     ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + (short)minim.iVertGap );
2657     /* SM_CXSMICON */
2658     /* SM_CYSMICON */
2659     ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2660     ok_gsm_3( SM_CXSMSIZE,
2661         ncm.iSmCaptionWidth, /* classic/standard windows style */
2662         GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2663         smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2664                       does not change it */
2665         );
2666     ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2667     ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2668     ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2669     /* SM_ARRANGE */
2670     ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2671     ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2672     screen.cx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
2673     screen.cy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
2674     if (!screen.cx || !screen.cy)  /* not supported on NT4 */
2675     {
2676         screen.cx = GetSystemMetrics( SM_CXSCREEN );
2677         screen.cy = GetSystemMetrics( SM_CYSCREEN );
2678     }
2679     ok_gsm_2( SM_CXMAXTRACK, screen.cx + 4 + 2 * GetSystemMetrics(SM_CXFRAME),
2680               screen.cx - 4 + 2 * GetSystemMetrics(SM_CXFRAME)); /* Vista */
2681     ok_gsm_2( SM_CYMAXTRACK, screen.cy + 4 + 2 * GetSystemMetrics(SM_CYFRAME),
2682               screen.cy - 4 + 2 * GetSystemMetrics(SM_CYFRAME)); /* Vista */
2683     /* the next two cannot really be tested as they depend on (application)
2684      * toolbars */
2685     /* SM_CXMAXIMIZED */
2686     /* SM_CYMAXIMIZED */
2687     /* SM_NETWORK */
2688     /* */
2689     /* */
2690     /* */
2691     /* SM_CLEANBOOT */
2692     /* SM_CXDRAG */
2693     /* SM_CYDRAG */
2694     /* SM_SHOWSOUNDS */
2695     ok_gsm( SM_CXMENUCHECK,
2696             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2697     ok_gsm( SM_CYMENUCHECK,
2698             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2699     /* SM_SLOWMACHINE */
2700     /* SM_MIDEASTENABLED */
2701     /* SM_MOUSEWHEELPRESENT */
2702     /* SM_XVIRTUALSCREEN */
2703     /* SM_YVIRTUALSCREEN */
2704     /* SM_CXVIRTUALSCREEN */
2705     /* SM_CYVIRTUALSCREEN */
2706     /* SM_CMONITORS */
2707     /* SM_SAMEDISPLAYFORMAT */
2708     /* SM_IMMENABLED */
2709     /* SM_CXFOCUSBORDER */
2710     /* SM_CYFOCUSBORDER */
2711     /* SM_TABLETPC */
2712     /* SM_MEDIACENTER */
2713     /* SM_CMETRICS */
2714     /* end of tests */
2715     if( gsm_error_ctr ) { /* if any errors where found */
2716         trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2717                 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2718         trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2719                 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2720         trace( "Captionfontchar width %d  MenuFont %d,%d CaptionWidth from registry: %d screen %d,%d\n",
2721                 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidthfromreg, screen.cx, screen.cy);
2722     }
2723     ReleaseDC( 0, hdc);
2724 }
2725
2726 static void test_EnumDisplaySettings(void)
2727 {
2728     DEVMODE devmode;
2729     DWORD val;
2730     HDC hdc;
2731     DWORD num;
2732
2733     memset(&devmode, 0, sizeof(devmode));
2734     devmode.dmSize = sizeof(devmode);
2735     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2736
2737     hdc = GetDC(0);
2738     val = GetDeviceCaps(hdc, BITSPIXEL);
2739     ok(devmode.dmBitsPerPel == val, "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
2740         val, devmode.dmBitsPerPel);
2741
2742     val = GetDeviceCaps(hdc, NUMCOLORS);
2743     if(devmode.dmBitsPerPel <= 8) {
2744         ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2745     } else {
2746         ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2747     }
2748
2749     ReleaseDC(0, hdc);
2750
2751     num = 1;
2752     while (1) {
2753         SetLastError (0xdeadbeef);
2754         if (!EnumDisplaySettings(NULL, num++, &devmode)) {
2755             DWORD le = GetLastError();
2756             ok(le == ERROR_NO_MORE_FILES ||
2757                le == 0xdeadbeef, /* XP, 2003 */
2758                "Expected ERROR_NO_MORE_FILES or 0xdeadbeef, got %d\n", le);
2759             break;
2760         }
2761     }
2762 }
2763
2764 START_TEST(sysparams)
2765 {
2766     int argc;
2767     char** argv;
2768     WNDCLASSA wc;
2769     MSG msg;
2770     HANDLE hThread;
2771     DWORD dwThreadId;
2772     HANDLE hInstance, hdll;
2773
2774     hdll = GetModuleHandleA("user32.dll");
2775     pChangeDisplaySettingsExA=(void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
2776
2777     hInstance = GetModuleHandleA( NULL );
2778     hdc = GetDC(0);
2779     dpi = GetDeviceCaps( hdc, LOGPIXELSY);
2780     iswin9x = GetVersion() & 0x80000000;
2781
2782     /* This test requires interactivity, if we don't have it, give up */
2783     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
2784         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
2785
2786     argc = winetest_get_mainargs(&argv);
2787     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
2788     trace("strict=%d\n",strict);
2789
2790     trace("testing GetSystemMetrics with your current desktop settings\n");
2791     test_GetSystemMetrics( );
2792     trace("testing EnumDisplaySettings vs GetDeviceCaps\n");
2793     test_EnumDisplaySettings( );
2794
2795     change_counter = 0;
2796     change_last_param = 0;
2797
2798     wc.lpszClassName = "SysParamsTestClass";
2799     wc.lpfnWndProc = SysParamsTestWndProc;
2800     wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
2801     wc.hInstance = hInstance;
2802     wc.hIcon = LoadIconA( 0, IDI_APPLICATION );
2803     wc.hCursor = LoadCursorA( 0, IDC_ARROW );
2804     wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
2805     wc.lpszMenuName = 0;
2806     wc.cbClsExtra = 0;
2807     wc.cbWndExtra = 0;
2808     RegisterClassA( &wc );
2809
2810     ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
2811                                WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
2812
2813     hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
2814     assert( hThread );
2815     CloseHandle( hThread );
2816
2817     while( GetMessageA( &msg, 0, 0, 0 )) {
2818         TranslateMessage( &msg );
2819         DispatchMessageA( &msg );
2820     }
2821     ReleaseDC( 0, hdc);
2822
2823 }