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