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