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