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