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