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