mapi32/tests: Fix typo.
[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 static UINT smcxsmsize = 999999999;
1357
1358 static void test_SPI_SETNONCLIENTMETRICS( void )               /*     44 */
1359 {
1360     BOOL rc;
1361     INT expect;
1362     NONCLIENTMETRICSA Ncmorig;
1363     NONCLIENTMETRICSA Ncmnew;
1364     NONCLIENTMETRICSA Ncmcur;
1365     NONCLIENTMETRICSA Ncmstart;
1366
1367     Ncmorig.cbSize = sizeof(NONCLIENTMETRICSA);
1368     Ncmnew.cbSize = sizeof(NONCLIENTMETRICSA);
1369     Ncmcur.cbSize = sizeof(NONCLIENTMETRICSA);
1370     Ncmstart.cbSize = sizeof(NONCLIENTMETRICSA);
1371
1372     trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1373     SetLastError(0xdeadbeef);
1374     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmorig, FALSE );
1375     if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1376         return;
1377     Ncmstart = Ncmorig;
1378     smcxsmsize = Ncmstart.iSmCaptionWidth;
1379     /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if 
1380        the caption font height is higher than the CaptionHeight field,
1381        the latter is adjusted accordingly. To be able to restore these setting
1382        accurately be restore the raw values. */
1383     Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, dpi);
1384     Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1385     Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1386     Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1387     /* test registry entries */
1388     TEST_NONCLIENTMETRICS_REG( Ncmorig)
1389     /* make small changes */
1390     Ncmnew = Ncmstart;
1391     Ncmnew.iBorderWidth += 1;
1392     Ncmnew.iScrollWidth += 1;
1393     Ncmnew.iScrollHeight -= 1;
1394     Ncmnew.iCaptionWidth -= 2;
1395     Ncmnew.iCaptionHeight += 2;
1396     Ncmnew.lfCaptionFont.lfHeight +=1;
1397     Ncmnew.lfCaptionFont.lfWidth +=2;
1398     Ncmnew.lfCaptionFont.lfWeight +=1;
1399     Ncmnew.iSmCaptionWidth += 1;
1400     Ncmnew.iSmCaptionHeight += 2;
1401     Ncmnew.lfSmCaptionFont.lfHeight +=3;
1402     Ncmnew.lfSmCaptionFont.lfWidth -=1;
1403     Ncmnew.lfSmCaptionFont.lfWeight +=3;
1404     Ncmnew.iMenuWidth += 1;
1405     Ncmnew.iMenuHeight += 2;
1406     Ncmnew.lfMenuFont.lfHeight +=1;
1407     Ncmnew.lfMenuFont.lfWidth +=1;
1408     Ncmnew.lfMenuFont.lfWeight +=2;
1409     Ncmnew.lfStatusFont.lfHeight -=1;
1410     Ncmnew.lfStatusFont.lfWidth -=1;
1411     Ncmnew.lfStatusFont.lfWeight +=3;
1412     Ncmnew.lfMessageFont.lfHeight -=2;
1413     Ncmnew.lfMessageFont.lfWidth -=1;
1414     Ncmnew.lfMessageFont.lfWeight +=4;
1415
1416     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1417             SPIF_SENDCHANGE);
1418     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1419     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1420     /* get them back */
1421     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1422     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1423     /* test registry entries */
1424     TEST_NONCLIENTMETRICS_REG( Ncmcur)
1425     /* test the systemm metrics with these settings */
1426     test_GetSystemMetrics();
1427     /* now for something invalid: increase the {menu|caption|smcaption} fonts
1428        by a large amount will increase the {menu|caption|smcaption} height*/
1429     Ncmnew = Ncmstart;
1430     Ncmnew.lfMenuFont.lfHeight -= 8;
1431     Ncmnew.lfCaptionFont.lfHeight =-4;
1432     Ncmnew.lfSmCaptionFont.lfHeight -=10;
1433     /* also show that a few values are lo limited */
1434     Ncmnew.iCaptionWidth = 0;
1435     Ncmnew.iCaptionHeight = 0;
1436     Ncmnew.iScrollHeight = 0;
1437     Ncmnew.iScrollWidth  = 0;
1438
1439     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1440             SPIF_SENDCHANGE);
1441     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1442     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1443     /* raw values are in registry */
1444     TEST_NONCLIENTMETRICS_REG( Ncmnew)
1445     /* get them back */
1446     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1447     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1448     /* cooked values are returned */
1449     expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1450     ok( Ncmcur.iMenuHeight == expect,
1451         "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1452     expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1453     ok( Ncmcur.iCaptionHeight == expect,
1454         "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1455     expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1456     ok( Ncmcur.iSmCaptionHeight == expect,
1457         "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1458
1459     ok( Ncmcur.iCaptionWidth == 8 ||
1460         Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme,  the value never changes */
1461         "CaptionWidth: %d expected 8\n", Ncmcur.iCaptionWidth);
1462     ok( Ncmcur.iScrollWidth == 8,
1463         "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1464     ok( Ncmcur.iScrollHeight == 8,
1465         "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1466     /* test the systemm metrics with these settings */
1467     test_GetSystemMetrics();
1468     /* restore */
1469     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
1470         &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1471     test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1472     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1473 }
1474
1475 static void test_SPI_SETMINIMIZEDMETRICS( void )               /*     44 */
1476 {
1477     BOOL rc;
1478     INT regval;
1479     MINIMIZEDMETRICS lpMm_orig;
1480     MINIMIZEDMETRICS lpMm_new;
1481     MINIMIZEDMETRICS lpMm_cur;
1482
1483     lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1484     lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1485     lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1486
1487     trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1488     SetLastError(0xdeadbeef);
1489     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1490     if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1491         return;
1492     /* Test registry. Note that it is perfectly valid for some fields to
1493      * not be set.
1494      */
1495     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1496     ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1497         regval, lpMm_orig.iWidth);
1498     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1499     ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1500         regval, lpMm_orig.iHorzGap);
1501     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1502     ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1503         regval, lpMm_orig.iVertGap);
1504     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1505     ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1506         regval, lpMm_orig.iArrange);
1507     /* set some new values */
1508     lpMm_cur.iWidth = 180;
1509     lpMm_cur.iHorzGap = 1;
1510     lpMm_cur.iVertGap = 1;
1511     lpMm_cur.iArrange = 5;
1512     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1513         &lpMm_cur, SPIF_UPDATEINIFILE );
1514     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1515     /* read them back */
1516     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1517     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1518     /* and compare */
1519     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
1520     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1521     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1522     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1523     /* test registry */
1524     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1525     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1526         regval, lpMm_new.iWidth);
1527     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1528     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1529         regval, lpMm_new.iHorzGap);
1530     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1531     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1532         regval, lpMm_new.iVertGap);
1533     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1534     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1535         regval, lpMm_new.iArrange);
1536     /* test some system metrics */
1537     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1538         lpMm_new.iWidth,   "iWidth",   "%d" );
1539     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1540         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1541     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1542         lpMm_new.iVertGap, "iVertGap", "%d" );
1543     eq( GetSystemMetrics( SM_ARRANGE ),
1544         lpMm_new.iArrange, "iArrange", "%d" );
1545     /* now some really invalid settings */
1546     lpMm_cur.iWidth = -1;
1547     lpMm_cur.iHorzGap = -1;
1548     lpMm_cur.iVertGap = -1;
1549     lpMm_cur.iArrange = - 1;
1550     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1551         &lpMm_cur, SPIF_UPDATEINIFILE );
1552     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1553     /* read back */
1554     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1555     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1556     /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1557     eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
1558     eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1559     eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1560     eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1561     /* test registry */
1562     if (0)
1563     {
1564     /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1565     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1566     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1567         regval, lpMm_new.iWidth);
1568     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1569     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1570         regval, lpMm_new.iHorzGap);
1571     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1572     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1573         regval, lpMm_new.iVertGap);
1574     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1575     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1576         regval, lpMm_new.iArrange);
1577     }
1578     /* test some system metrics */
1579     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1580         lpMm_new.iWidth,   "iWidth",   "%d" );
1581     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1582         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1583     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1584         lpMm_new.iVertGap, "iVertGap", "%d" );
1585     eq( GetSystemMetrics( SM_ARRANGE ),
1586         lpMm_new.iArrange, "iArrange", "%d" );
1587     /* restore */
1588     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1589         &lpMm_orig, SPIF_UPDATEINIFILE );
1590     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1591     /* check that */
1592     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1593     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1594     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
1595     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1596     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1597     eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1598 }
1599
1600 static void test_SPI_SETICONMETRICS( void )               /*     46 */
1601 {
1602     BOOL rc, wrap;
1603     INT spacing;
1604     ICONMETRICSA im_orig;
1605     ICONMETRICSA im_new;
1606     ICONMETRICSA im_cur;
1607     INT regval;
1608         
1609     im_orig.cbSize = sizeof(ICONMETRICSA);
1610     im_new.cbSize = sizeof(ICONMETRICSA);
1611     im_cur.cbSize = sizeof(ICONMETRICSA);
1612
1613     trace("testing SPI_{GET,SET}ICONMETRICS\n");
1614     SetLastError(0xdeadbeef);
1615     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1616     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1617         return;
1618    /* check some registry values */ 
1619     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1620     ok( regval==im_orig.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1621     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1622     ok( regval==im_orig.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1623     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1624     if( regval != im_orig.iTitleWrap)
1625         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1626     ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1627
1628     /* change everything without creating something invalid ( Win9x would ignore
1629      * an invalid font for instance) */
1630     im_cur = im_orig;
1631     im_cur.iHorzSpacing += 10;
1632     im_cur.iVertSpacing += 6;
1633     im_cur.iTitleWrap = !im_cur.iTitleWrap;
1634     im_cur.lfFont.lfHeight += 1;
1635     im_cur.lfFont.lfWidth += 2;
1636     im_cur.lfFont.lfEscapement = 1;
1637     im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1638     im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1639     im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1640     im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1641     im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1642     im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1643                                 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1644     im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1645     im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1646     im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ? 
1647                                 DRAFT_QUALITY : DEFAULT_QUALITY;
1648     if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1649         strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1650     else
1651         strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1652
1653     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1654     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1655
1656     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1657     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1658     /* test GET <-> SETICONMETRICS */ 
1659     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1660     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1661     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
1662     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%d" );
1663     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%d" );
1664     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%d" );
1665     eq( im_new.lfFont.lfWeight,         im_cur.lfFont.lfWeight,         "lfWeight",         "%d" );
1666     eq( im_new.lfFont.lfItalic,         im_cur.lfFont.lfItalic,         "lfItalic",         "%d" );
1667     eq( im_new.lfFont.lfStrikeOut,      im_cur.lfFont.lfStrikeOut,      "lfStrikeOut",      "%d" );
1668     eq( im_new.lfFont.lfUnderline,      im_cur.lfFont.lfUnderline,      "lfUnderline",      "%d" );
1669     eq( im_new.lfFont.lfCharSet,        im_cur.lfFont.lfCharSet,        "lfCharSet",        "%d" );
1670     eq( im_new.lfFont.lfOutPrecision,   im_cur.lfFont.lfOutPrecision,   "lfOutPrecision",   "%d" );
1671     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
1672     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1673     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
1674     ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1675         "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1676         im_cur.lfFont.lfFaceName);
1677     /* test some system metrics */
1678     eq( GetSystemMetrics( SM_CXICONSPACING ),
1679         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1680     eq( GetSystemMetrics( SM_CYICONSPACING ),
1681         im_new.iVertSpacing, "iVertSpacing", "%d" );
1682    /* check some registry values */ 
1683     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1684     ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1685     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1686     ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1687     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1688     if( regval != im_cur.iTitleWrap)
1689         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1690     ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1691     /* test some values from other SPI_GETxxx calls */
1692     rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1693     ok( rc && spacing == im_cur.iHorzSpacing,
1694         "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1695         spacing, im_cur.iHorzSpacing);
1696     rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1697     ok( rc && spacing == im_cur.iVertSpacing,
1698         "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1699         spacing, im_cur.iVertSpacing);
1700     rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1701     ok( rc && wrap == im_cur.iTitleWrap,
1702         "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1703         wrap, im_cur.iTitleWrap);
1704     /* restore old values */
1705     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1706     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1707     
1708     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1709     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1710     
1711     eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1712     eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1713     eq( im_new.iTitleWrap,   im_orig.iTitleWrap,   "iTitleWrap",   "%d" );
1714 }
1715
1716 static void test_SPI_SETWORKAREA( void )               /*     47 */
1717 {
1718     BOOL rc;
1719     RECT old_area;
1720     RECT area;
1721     RECT curr_val;
1722
1723     trace("testing SPI_{GET,SET}WORKAREA\n");
1724     SetLastError(0xdeadbeef);
1725     rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1726     if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1727         return;
1728
1729     /* Modify the work area only minimally as this causes the icons that
1730      * fall outside it to be moved around thus requiring the user to
1731      * reposition them manually one by one.
1732      * Changing the work area by just one pixel should make this occurrence
1733      * reasonably unlikely.
1734      */
1735     curr_val.left = old_area.left;
1736     curr_val.top = old_area.top;
1737     curr_val.right = old_area.right-1;
1738     curr_val.bottom = old_area.bottom-1;
1739     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1740                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1741     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1742     test_change_message( SPI_SETWORKAREA, 0 );
1743     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1744     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1745     eq( area.left,   curr_val.left,   "left",   "%d" );
1746     eq( area.top,    curr_val.top,    "top",    "%d" );
1747     eq( area.right,  curr_val.right,  "right",  "%d" );
1748     eq( area.bottom, curr_val.bottom, "bottom", "%d" );
1749
1750     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1751                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1752     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1753     test_change_message( SPI_SETWORKAREA, 0 );
1754     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1755     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1756     eq( area.left,   old_area.left,   "left",   "%d" );
1757     eq( area.top,    old_area.top,    "top",    "%d" );
1758     eq( area.right,  old_area.right,  "right",  "%d" );
1759     eq( area.bottom, old_area.bottom, "bottom", "%d" );
1760 }
1761
1762 static void test_SPI_SETSHOWSOUNDS( void )             /*     57 */
1763 {
1764     BOOL rc;
1765     BOOL old_b;
1766     const UINT vals[]={TRUE,FALSE};
1767     unsigned int i;
1768
1769     trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1770     SetLastError(0xdeadbeef);
1771     rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1772     /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
1773     if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1774         return;
1775
1776     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1777     {
1778         UINT v;
1779
1780         rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1781                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1782         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1783         test_change_message( SPI_SETSHOWSOUNDS, 1 );
1784         test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1785                       SPI_SETSHOWSOUNDS_VALNAME,
1786                       vals[i] ? "1" : "0" );
1787
1788         rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1789         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1790         eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1791         eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1792             "SM_SHOWSOUNDS", "%d" );
1793     }
1794
1795     rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1796     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1797 }
1798
1799 static void test_SPI_SETKEYBOARDPREF( void )           /*     69 */
1800 {
1801     BOOL rc;
1802     BOOL old_b;
1803     const UINT vals[]={TRUE,FALSE};
1804     unsigned int i;
1805
1806     trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1807     SetLastError(0xdeadbeef);
1808     rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1809     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1810         return;
1811
1812     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1813     {
1814         BOOL v;
1815
1816         rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1817                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1818         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1819         test_change_message( SPI_SETKEYBOARDPREF, 1 );
1820         test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1821                           SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1822                           vals[i] ? "1" : "0" );
1823
1824         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1825         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1826         eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1827     }
1828
1829     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1830     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1831 }
1832
1833 static void test_SPI_SETSCREENREADER( void )           /*     71 */
1834 {
1835     BOOL rc;
1836     BOOL old_b;
1837     const UINT vals[]={TRUE,FALSE};
1838     unsigned int i;
1839
1840     trace("testing SPI_{GET,SET}SCREENREADER\n");
1841     SetLastError(0xdeadbeef);
1842     rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
1843     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
1844         return;
1845
1846     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1847     {
1848         BOOL v;
1849
1850         rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
1851                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1852         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1853         test_change_message( SPI_SETSCREENREADER, 1 );
1854         test_reg_key_ex2( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
1855                       SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
1856                       vals[i] ? "1" : "0" );
1857
1858         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
1859         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1860         eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
1861     }
1862
1863     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
1864     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1865 }
1866
1867 static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
1868 {
1869     BOOL rc;
1870     BOOL old_b;
1871     const UINT vals[]={0xffffffff,0,1,2};
1872     unsigned int i;
1873
1874     trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
1875     if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */ 
1876     SetLastError(0xdeadbeef);
1877     rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
1878     if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
1879         return;
1880
1881     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1882     {
1883         UINT v;
1884
1885         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
1886                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1887         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1888         test_change_message( SPI_SETFONTSMOOTHING, 0 );
1889         test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
1890                       SPI_SETFONTSMOOTHING_VALNAME,
1891                       vals[i] ? "2" : "0" );
1892
1893         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
1894         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1895         eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
1896     }
1897
1898     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
1899     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1900 }
1901
1902 static void test_SPI_SETLOWPOWERACTIVE( void )         /*     85 */
1903 {
1904     BOOL rc;
1905     BOOL old_b;
1906     const UINT vals[]={TRUE,FALSE};
1907     unsigned int i;
1908
1909     trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
1910     SetLastError(0xdeadbeef);
1911     rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
1912     if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
1913         return;
1914
1915     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1916     {
1917         UINT v;
1918
1919         rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
1920                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1921         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1922         test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
1923         test_reg_key( SPI_SETLOWPOWERACTIVE_REGKEY,
1924                       SPI_SETLOWPOWERACTIVE_VALNAME,
1925                       vals[i] ? "1" : "0" );
1926
1927         /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
1928         rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
1929         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1930         ok(v == vals[i] ||
1931            v == 0, /* win2k3 */
1932            "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
1933     }
1934
1935     rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1936     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1937 }
1938
1939 static void test_SPI_SETPOWEROFFACTIVE( void )         /*     86 */
1940 {
1941     BOOL rc;
1942     BOOL old_b;
1943     const UINT vals[]={TRUE,FALSE};
1944     unsigned int i;
1945
1946     trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
1947     SetLastError(0xdeadbeef);
1948     rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
1949     if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
1950         return;
1951
1952     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1953     {
1954         UINT v;
1955
1956         rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
1957                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1958         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1959         test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
1960         test_reg_key( SPI_SETPOWEROFFACTIVE_REGKEY,
1961                       SPI_SETPOWEROFFACTIVE_VALNAME,
1962                       vals[i] ? "1" : "0" );
1963
1964         /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
1965         rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
1966         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1967         ok(v == vals[i] ||
1968            v == 0, /* win2k3 */
1969            "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
1970     }
1971
1972     rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1973     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1974 }
1975
1976 static void test_SPI_SETSNAPTODEFBUTTON( void )         /*     95 */
1977 {
1978     BOOL rc;
1979     BOOL old_b;
1980     const UINT vals[]={TRUE,FALSE};
1981     unsigned int i;
1982
1983     trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
1984     SetLastError(0xdeadbeef);
1985     rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
1986     if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
1987         return;
1988
1989     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1990     {
1991         UINT v;
1992
1993         rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
1994                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1995         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1996         test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
1997         test_reg_key( SPI_SETSNAPTODEFBUTTON_REGKEY,
1998                       SPI_SETSNAPTODEFBUTTON_VALNAME,
1999                       vals[i] ? "1" : "0" );
2000
2001         rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2002         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2003         eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2004     }
2005
2006     rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2007     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2008 }
2009
2010 static void test_SPI_SETMOUSEHOVERWIDTH( void )      /*     99 */
2011 {
2012     BOOL rc;
2013     UINT old_width;
2014     const UINT vals[]={0,32767};
2015     unsigned int i;
2016
2017     trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2018     SetLastError(0xdeadbeef);
2019     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2020     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2021     * what MSDN states (Verified on Win98SE)
2022     */
2023     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2024         return;
2025     
2026     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2027     {
2028         UINT v;
2029         char buf[10];
2030
2031         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2032                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2033         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2034         test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2035         sprintf( buf, "%d", vals[i] );
2036         test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
2037                       SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
2038
2039         SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2040         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2041         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2042     }
2043
2044     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2045                               SPIF_UPDATEINIFILE );
2046     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2047 }
2048
2049 static void test_SPI_SETMOUSEHOVERHEIGHT( void )      /*     101 */
2050 {
2051     BOOL rc;
2052     UINT old_height;
2053     const UINT vals[]={0,32767};
2054     unsigned int i;
2055
2056     trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2057     SetLastError(0xdeadbeef);
2058     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2059     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2060      * what MSDN states (Verified on Win98SE)
2061      */
2062     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2063         return;
2064     
2065     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2066     {
2067         UINT v;
2068         char buf[10];
2069
2070         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2071                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2072         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2073         test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2074         sprintf( buf, "%d", vals[i] );
2075         test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2076                       SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2077
2078         SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2079         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2080         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2081     }
2082
2083     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2084                               SPIF_UPDATEINIFILE );
2085     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2086 }
2087
2088 static void test_SPI_SETMOUSEHOVERTIME( void )      /*     103 */
2089 {
2090     BOOL rc;
2091     UINT old_time;
2092
2093     /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2094      * defaulted to a value of 10 automatically.
2095      */
2096     const UINT vals[]={10,32767};
2097     unsigned int i;
2098
2099     trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2100     SetLastError(0xdeadbeef);
2101     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2102     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2103      * what MSDN states (Verified on Win98SE)
2104      */    
2105     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2106         return;
2107     
2108     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2109     {
2110         UINT v;
2111         char buf[10];
2112
2113         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2114                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2115         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2116         test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2117         sprintf( buf, "%d", vals[i] );
2118         test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2119                       SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2120
2121         SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2122         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2123         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2124     }
2125
2126     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2127                               SPIF_UPDATEINIFILE );
2128     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2129 }
2130
2131 static void test_SPI_SETWHEELSCROLLLINES( void )      /*     105 */
2132 {
2133     BOOL rc;
2134     UINT old_lines;
2135     const UINT vals[]={0,32767};
2136     unsigned int i;
2137
2138     trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2139     SetLastError(0xdeadbeef);
2140     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2141
2142     /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2143     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2144         return;
2145
2146     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2147     {
2148         UINT v;
2149         char buf[10];
2150
2151         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2152                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2153         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2154         test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2155         sprintf( buf, "%d", vals[i] );
2156         test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2157                       SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2158
2159         SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2160         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2161         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2162     }
2163
2164     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2165                               SPIF_UPDATEINIFILE );
2166     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2167 }
2168
2169 static void test_SPI_SETMENUSHOWDELAY( void )      /*     107 */
2170 {
2171     BOOL rc;
2172     UINT old_delay;
2173     const UINT vals[]={0,32767};
2174     unsigned int i;
2175
2176     trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2177     SetLastError(0xdeadbeef);
2178     rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2179
2180     /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2181     if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2182         return;
2183
2184     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2185     {
2186         UINT v;
2187         char buf[10];
2188
2189         rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2190                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2191         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2192         test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2193         sprintf( buf, "%d", vals[i] );
2194         test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2195                       SPI_SETMENUSHOWDELAY_VALNAME, buf );
2196
2197         SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2198         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2199         eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2200     }
2201
2202     rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2203                               SPIF_UPDATEINIFILE );
2204     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2205 }
2206
2207 static void test_SPI_SETWHEELSCROLLCHARS( void )      /*     108 */
2208 {
2209     BOOL rc;
2210     UINT old_chars;
2211     const UINT vals[]={32767,0};
2212     unsigned int i;
2213
2214     trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2215     SetLastError(0xdeadbeef);
2216     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2217
2218     /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2219     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2220         return;
2221
2222     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2223     {
2224         UINT v;
2225         char buf[10];
2226
2227         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2228                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2229         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2230         test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2231         sprintf( buf, "%d", vals[i] );
2232         test_reg_key( SPI_SETMOUSESCROLLCHARS_REGKEY,
2233                       SPI_SETMOUSESCROLLCHARS_VALNAME, buf );
2234
2235         SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2236         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2237         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2238     }
2239
2240     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2241                               SPIF_UPDATEINIFILE );
2242     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2243 }
2244
2245 static void test_SPI_SETWALLPAPER( void )              /*   115 */
2246 {
2247     BOOL rc;
2248     char oldval[260];
2249     char newval[260];
2250
2251     trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2252     SetLastError(0xdeadbeef);
2253     rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2254     /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
2255      * unimplemented on NT4
2256      */
2257     if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2258         return;
2259
2260     strcpy(newval, "");
2261     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2262     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
2263     test_change_message(SPI_SETDESKWALLPAPER, 0);
2264
2265     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2266     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2267
2268     test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2269 }
2270
2271 static void test_WM_DISPLAYCHANGE(void)
2272 {
2273     DEVMODE mode, startmode;
2274     int start_bpp, last_set_bpp = 0;
2275     int test_bpps[] = {8, 16, 24, 32}, i;
2276     LONG change_ret;
2277     DWORD wait_ret;
2278
2279     if (!pChangeDisplaySettingsExA)
2280     {
2281         skip("ChangeDisplaySettingsExA is not available\n");
2282         return;
2283     }
2284
2285     displaychange_test_active = TRUE;
2286
2287     memset(&startmode, 0, sizeof(startmode));
2288     startmode.dmSize = sizeof(startmode);
2289     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &startmode);
2290     start_bpp = startmode.dmBitsPerPel;
2291
2292     displaychange_sem = CreateSemaphore(NULL, 0, 1, NULL);
2293
2294     for(i = 0; i < sizeof(test_bpps)/sizeof(test_bpps[0]); i++) {
2295         last_bpp = -1;
2296
2297         memset(&mode, 0, sizeof(mode));
2298         mode.dmSize = sizeof(mode);
2299         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2300         mode.dmBitsPerPel = test_bpps[i];
2301         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2302         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2303
2304         change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2305         displaychange_ok = TRUE;
2306         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2307         /* Wait quite long for the message, screen setting changes can take some time */
2308         if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2309             wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2310             ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2311         }
2312         displaychange_ok = FALSE;
2313
2314         if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2315             skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2316             ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despide mode change failure\n", last_bpp);
2317             continue;
2318         }
2319
2320         if(start_bpp != test_bpps[i]) {
2321             todo_wine ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2322         } else {
2323             ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2324         }
2325         last_set_bpp = test_bpps[i];
2326     }
2327
2328     if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2329         memset(&mode, 0, sizeof(mode));
2330         mode.dmSize = sizeof(mode);
2331         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2332         mode.dmBitsPerPel = start_bpp;
2333         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2334         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2335
2336         displaychange_ok = TRUE;
2337         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2338         WaitForSingleObject(displaychange_sem, 10000);
2339         displaychange_ok = FALSE;
2340         CloseHandle(displaychange_sem);
2341         displaychange_sem = 0;
2342     }
2343
2344     displaychange_test_active = FALSE;
2345 }
2346
2347 /*
2348  * Registry entries for the system parameters.
2349  * Names are created by 'SET' flags names.
2350  * We assume that corresponding 'GET' entries use the same registry keys.
2351  */
2352 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2353 {
2354     test_SPI_SETBEEP();                         /*      1 */
2355     test_SPI_SETMOUSE();                        /*      4 */
2356     test_SPI_SETBORDER();                       /*      6 */
2357     test_SPI_SETKEYBOARDSPEED();                /*     10 */
2358     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
2359     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
2360     test_SPI_SETSCREENSAVEACTIVE();             /*     17 */
2361     test_SPI_SETGRIDGRANULARITY();              /*     19 */
2362     test_SPI_SETKEYBOARDDELAY();                /*     23 */
2363     test_SPI_ICONVERTICALSPACING();             /*     24 */
2364     test_SPI_SETICONTITLEWRAP();                /*     26 */
2365     test_SPI_SETMENUDROPALIGNMENT();            /*     28 */
2366     test_SPI_SETDOUBLECLKWIDTH();               /*     29 */
2367     test_SPI_SETDOUBLECLKHEIGHT();              /*     30 */
2368     test_SPI_SETDOUBLECLICKTIME();              /*     32 */
2369     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
2370     test_SPI_SETFASTTASKSWITCH();               /*     36 */
2371     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
2372     test_SPI_SETNONCLIENTMETRICS();             /*     42 */
2373     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
2374     test_SPI_SETICONMETRICS();                  /*     46 */
2375     test_SPI_SETWORKAREA();                     /*     47 */
2376     test_SPI_SETSHOWSOUNDS();                   /*     57 */
2377     test_SPI_SETKEYBOARDPREF();                 /*     69 */
2378     test_SPI_SETSCREENREADER();                 /*     71 */
2379     test_SPI_SETFONTSMOOTHING();                /*     75 */
2380     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
2381     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
2382     test_SPI_SETSNAPTODEFBUTTON();              /*     95 */
2383     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
2384     test_SPI_SETMOUSEHOVERHEIGHT();             /*    101 */
2385     test_SPI_SETMOUSEHOVERTIME();               /*    103 */
2386     test_SPI_SETWHEELSCROLLLINES();             /*    105 */
2387     test_SPI_SETMENUSHOWDELAY();                /*    107 */
2388     test_SPI_SETWHEELSCROLLCHARS();             /*    108 */
2389     test_SPI_SETWALLPAPER();                    /*    115 */
2390
2391     test_WM_DISPLAYCHANGE();
2392
2393     SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2394     return 0;
2395 }
2396
2397 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2398  * icon metrics and minimized metrics. 
2399  */
2400
2401 /* copied from wine's GdiGetCharDimensions, which is not available on most
2402  * windows versions */
2403 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2404 {
2405     SIZE sz;
2406     static const CHAR alphabet[] = {
2407         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2408         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2409         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2410
2411     if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2412
2413     if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2414
2415     if (height) *height = sz.cy;
2416     return (sz.cx / 26 + 1) / 2;
2417 }
2418
2419 /* get text metrics and/or "average" char width of the specified logfont
2420  * for the specified dc */
2421 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2422 {
2423     HFONT hfont, hfontsav;
2424     TEXTMETRICA tm;
2425     if( !ptm) ptm = &tm;
2426     hfont = CreateFontIndirectA( plf);
2427     if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2428         ptm->tmHeight = -1;
2429         if( psz) *psz = 10;
2430         if( hfont) DeleteObject( hfont);
2431         return;
2432     }
2433     GetTextMetricsA( hdc, ptm);
2434     if( psz)
2435         if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2436             *psz = 10;
2437     SelectObject( hdc, hfontsav);
2438     DeleteObject( hfont);
2439 }
2440
2441 static int gsm_error_ctr;
2442
2443 #define ok_gsm( i, e)\
2444 {\
2445     int exp = (e);\
2446     int act = GetSystemMetrics( (i));\
2447     if( exp != act) gsm_error_ctr++;\
2448     ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2449 }
2450 #define ok_gsm_2( i, e1, e2)\
2451 {\
2452     int exp1 = (e1);\
2453     int exp2 = (e2);\
2454     int act = GetSystemMetrics( (i));\
2455     if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2456     ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2457 }
2458 #define ok_gsm_3( i, e1, e2, e3)\
2459 {\
2460     int exp1 = (e1);\
2461     int exp2 = (e2);\
2462     int exp3 = (e3);\
2463     int act = GetSystemMetrics( (i));\
2464     if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2465     ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2466 }
2467
2468 static void test_GetSystemMetrics( void)
2469 {
2470     TEXTMETRICA tmMenuFont;
2471     UINT IconSpacing, IconVerticalSpacing;
2472
2473     HDC hdc = CreateIC( "Display", 0, 0, 0);
2474     UINT avcwCaption;
2475     INT CaptionWidth;
2476     MINIMIZEDMETRICS minim;
2477     NONCLIENTMETRICS ncm;
2478     SIZE screen;
2479
2480     minim.cbSize = sizeof( minim);
2481     ncm.cbSize = sizeof( ncm);
2482     SystemParametersInfo( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2483     SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2484
2485     /* CaptionWidth from the registry may have different value of iCaptionWidth
2486      * from the non client metrics (observed on WinXP) */
2487     CaptionWidth = metricfromreg(
2488             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2489     get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2490     get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2491     /* FIXME: use icon metric */
2492     if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2493         IconVerticalSpacing = 0;
2494     if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2495         IconSpacing = 0;
2496     /* reset error counters */
2497     gsm_error_ctr = 0;
2498
2499     /* the tests: */
2500
2501     /* SM_CXSCREEN, cannot test these two */
2502     /* SM_CYSCREEN */
2503     ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
2504     ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
2505     ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2506     ok_gsm( SM_CXBORDER, 1);
2507     ok_gsm( SM_CYBORDER, 1);
2508     ok_gsm( SM_CXDLGFRAME, 3);
2509     ok_gsm( SM_CYDLGFRAME, 3);
2510     ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
2511     ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
2512     /* SM_CXICON */
2513     /* SM_CYICON */
2514     /* SM_CXCURSOR */
2515     /* SM_CYCURSOR */
2516     ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2517     ok_gsm( SM_CXFULLSCREEN,
2518             GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2519     ok_gsm( SM_CYFULLSCREEN,
2520             GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2521     /* SM_CYKANJIWINDOW */
2522     /* SM_MOUSEPRESENT */
2523     ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2524     ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2525     /* SM_DEBUG */
2526     /* SM_SWAPBUTTON */
2527     /* SM_RESERVED1 */
2528     /* SM_RESERVED2 */
2529     /* SM_RESERVED3 */
2530     /* SM_RESERVED4 */
2531     ok_gsm( SM_CXMIN, 3 * max( CaptionWidth, 8) + GetSystemMetrics( SM_CYSIZE) +
2532             4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2533     ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2534             2 * GetSystemMetrics( SM_CYFRAME));
2535     ok_gsm_2( SM_CXSIZE,
2536         ncm.iCaptionWidth,  /* classic/standard windows style */
2537         GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2538         );
2539     ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
2540     ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2541     ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2542     ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
2543     ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
2544     /* SM_CXDOUBLECLK */
2545     /* SM_CYDOUBLECLK */
2546     if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2547     if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2548     /* SM_MENUDROPALIGNMENT */
2549     /* SM_PENWINDOWS */
2550     /* SM_DBCSENABLED */
2551     /* SM_CMOUSEBUTTONS */
2552     /* SM_SECURE */
2553     ok_gsm( SM_CXEDGE, 2);
2554     ok_gsm( SM_CYEDGE, 2);
2555     /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2556     ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + (short)minim.iHorzGap );
2557     ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + (short)minim.iVertGap );
2558     /* SM_CXSMICON */
2559     /* SM_CYSMICON */
2560     ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2561     ok_gsm_3( SM_CXSMSIZE,
2562         ncm.iSmCaptionWidth, /* classic/standard windows style */
2563         GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2564         smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2565                       does not change it */
2566         );
2567     ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2568     ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2569     ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2570     /* SM_ARRANGE */
2571     ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2572     ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2573     screen.cx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
2574     screen.cy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
2575     if (!screen.cx || !screen.cy)  /* not supported on NT4 */
2576     {
2577         screen.cx = GetSystemMetrics( SM_CXSCREEN );
2578         screen.cy = GetSystemMetrics( SM_CYSCREEN );
2579     }
2580     ok_gsm( SM_CXMAXTRACK, screen.cx + 4 + 2 * GetSystemMetrics(SM_CXFRAME));
2581     ok_gsm( SM_CYMAXTRACK, screen.cy + 4 + 2 * GetSystemMetrics(SM_CYFRAME));
2582     /* the next two cannot really be tested as they depend on (application)
2583      * toolbars */
2584     /* SM_CXMAXIMIZED */
2585     /* SM_CYMAXIMIZED */
2586     /* SM_NETWORK */
2587     /* */
2588     /* */
2589     /* */
2590     /* SM_CLEANBOOT */
2591     /* SM_CXDRAG */
2592     /* SM_CYDRAG */
2593     /* SM_SHOWSOUNDS */
2594     ok_gsm( SM_CXMENUCHECK,
2595             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2596     ok_gsm( SM_CYMENUCHECK,
2597             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2598     /* SM_SLOWMACHINE */
2599     /* SM_MIDEASTENABLED */
2600     /* SM_MOUSEWHEELPRESENT */
2601     /* SM_XVIRTUALSCREEN */
2602     /* SM_YVIRTUALSCREEN */
2603     /* SM_CXVIRTUALSCREEN */
2604     /* SM_CYVIRTUALSCREEN */
2605     /* SM_CMONITORS */
2606     /* SM_SAMEDISPLAYFORMAT */
2607     /* SM_IMMENABLED */
2608     /* SM_CXFOCUSBORDER */
2609     /* SM_CYFOCUSBORDER */
2610     /* SM_TABLETPC */
2611     /* SM_MEDIACENTER */
2612     /* SM_CMETRICS */
2613     /* end of tests */
2614     if( gsm_error_ctr ) { /* if any errors where found */
2615         trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2616                 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2617         trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2618                 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2619         trace( "Captionfontchar width %d  MenuFont %d,%d CaptionWidth from registry: %d\n",
2620                 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidth);
2621     }
2622     ReleaseDC( 0, hdc);
2623 }
2624
2625 static void test_EnumDisplaySettings(void)
2626 {
2627     DEVMODE devmode;
2628     DWORD val;
2629     HDC hdc;
2630     DWORD num;
2631
2632     memset(&devmode, 0, sizeof(devmode));
2633     devmode.dmSize = sizeof(devmode);
2634     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2635
2636     hdc = GetDC(0);
2637     val = GetDeviceCaps(hdc, BITSPIXEL);
2638     ok(devmode.dmBitsPerPel == val, "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
2639         val, devmode.dmBitsPerPel);
2640
2641     val = GetDeviceCaps(hdc, NUMCOLORS);
2642     if(devmode.dmBitsPerPel <= 8) {
2643         ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2644     } else {
2645         ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2646     }
2647
2648     ReleaseDC(0, hdc);
2649
2650     num = 1;
2651     while (1) {
2652         SetLastError (0xdeadbeef);
2653         if (!EnumDisplaySettings(NULL, num++, &devmode)) {
2654             DWORD le = GetLastError();
2655             ok(le == ERROR_NO_MORE_FILES ||
2656                le == 0xdeadbeef, /* XP, 2003 */
2657                "Expected ERROR_NO_MORE_FILES or 0xdeadbeef, got %d\n", le);
2658             break;
2659         }
2660     }
2661 }
2662
2663 START_TEST(sysparams)
2664 {
2665     int argc;
2666     char** argv;
2667     WNDCLASSA wc;
2668     MSG msg;
2669     HANDLE hThread;
2670     DWORD dwThreadId;
2671     HANDLE hInstance, hdll;
2672
2673     hdll = GetModuleHandleA("user32.dll");
2674     pChangeDisplaySettingsExA=(void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
2675
2676     hInstance = GetModuleHandleA( NULL );
2677     hdc = GetDC(0);
2678     dpi = GetDeviceCaps( hdc, LOGPIXELSY);
2679     iswin9x = GetVersion() & 0x80000000;
2680
2681     /* This test requires interactivity, if we don't have it, give up */
2682     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
2683         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
2684
2685     argc = winetest_get_mainargs(&argv);
2686     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
2687     trace("strict=%d\n",strict);
2688
2689     trace("testing GetSystemMetrics with your current desktop settings\n");
2690     test_GetSystemMetrics( );
2691     trace("testing EnumDisplaySettings vs GetDeviceCaps\n");
2692     test_EnumDisplaySettings( );
2693
2694     change_counter = 0;
2695     change_last_param = 0;
2696
2697     wc.lpszClassName = "SysParamsTestClass";
2698     wc.lpfnWndProc = SysParamsTestWndProc;
2699     wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
2700     wc.hInstance = hInstance;
2701     wc.hIcon = LoadIconA( 0, IDI_APPLICATION );
2702     wc.hCursor = LoadCursorA( 0, IDC_ARROW );
2703     wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
2704     wc.lpszMenuName = 0;
2705     wc.cbClsExtra = 0;
2706     wc.cbWndExtra = 0;
2707     RegisterClassA( &wc );
2708
2709     ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
2710                                WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
2711
2712     hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
2713     assert( hThread );
2714     CloseHandle( hThread );
2715
2716     while( GetMessageA( &msg, 0, 0, 0 )) {
2717         TranslateMessage( &msg );
2718         DispatchMessageA( &msg );
2719     }
2720     ReleaseDC( 0, hdc);
2721
2722 }