wnaspi32: Make winaspi.dll into a stand-alone 16-bit module.
[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     /* FIXME: include new PaddedBorderWidth parameter */
738     if( old_border != ncmsave.iBorderWidth){
739         win_skip( "Can not reliable restore border width yet\n");
740         return;
741     }
742     /* This will restore sane values if the test hang previous run. */
743     if ( old_border == 7 || old_border == 20 )
744         old_border = 1;
745
746     /* The SPI_SETBORDER seems to be buggy on Win9x/ME (looks like you need to
747      * do it twice to make the intended change). So skip parts of the tests on
748      * those platforms */
749     if( !iswin9x) {
750         /* win2k3 fails if you set the same border twice, or if size is 0 */
751         if (!test_setborder(2,  1, dpi)) return;
752         test_setborder(1,  1, dpi);
753         test_setborder(3,  1, dpi);
754     }
755     if (!test_setborder(1, 0, dpi)) return;
756     test_setborder(0, 0, dpi);
757     test_setborder(3, 0, dpi);
758
759     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncmsave,
760             SPIF_UPDATEINIFILE| SPIF_SENDCHANGE);
761     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
762     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",
763         rc,GetLastError());
764 }
765
766 static void test_SPI_SETKEYBOARDSPEED( void )          /*     10 */
767 {
768     BOOL rc;
769     UINT old_speed;
770     const UINT vals[]={0,20,31};
771     unsigned int i;
772
773     trace("testing SPI_{GET,SET}KEYBOARDSPEED\n");
774     SetLastError(0xdeadbeef);
775     rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &old_speed, 0 );
776     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDSPEED"))
777         return;
778
779     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
780     {
781         UINT v;
782         char buf[10];
783
784         rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, vals[i], 0,
785                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
786         if (!test_error_msg(rc,"SPI_SETKEYBOARDSPEED")) return;
787         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
788         test_change_message( SPI_SETKEYBOARDSPEED, 0 );
789         sprintf( buf, "%d", vals[i] );
790         test_reg_key( SPI_SETKEYBOARDSPEED_REGKEY, SPI_SETKEYBOARDSPEED_VALNAME, buf );
791
792         rc=SystemParametersInfoA( SPI_GETKEYBOARDSPEED, 0, &v, 0 );
793         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
794         eq( v, vals[i], "SPI_{GET,SET}KEYBOARDSPEED", "%d" );
795     }
796
797     rc=SystemParametersInfoA( SPI_SETKEYBOARDSPEED, old_speed, 0, SPIF_UPDATEINIFILE );
798     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
799 }
800
801 /* test_SPI_ICONHORIZONTALSPACING helper */
802 static BOOL dotest_spi_iconhorizontalspacing( INT curr_val)
803 {
804     BOOL rc;
805     INT spacing, regval;
806     ICONMETRICSA im;
807
808     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
809                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
810     if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING")) return FALSE;
811     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
812     test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
813     if( curr_val < 32) curr_val = 32;
814     /* The registry keys depend on the Windows version and the values too
815      * let's test (works on win95,ME,NT4,2k,XP)
816      */
817     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY2, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
818     if( regval != curr_val)
819         regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
820     ok( curr_val == regval,
821         "wrong value in registry %d, expected %d\n", regval, curr_val);
822     /* compare with what SPI_ICONHORIZONTALSPACING returns */
823     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
824     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
825     eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
826     /* and with a system metrics */
827     eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
828     /* and with what SPI_GETICONMETRICS returns */
829     im.cbSize = sizeof(ICONMETRICSA);
830     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
831     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
832     eq( im.iHorzSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
833     return TRUE;
834 }
835
836 static void test_SPI_ICONHORIZONTALSPACING( void )     /*     13 */
837 {
838     BOOL rc;
839     INT old_spacing;
840
841     trace("testing SPI_ICONHORIZONTALSPACING\n");
842     SetLastError(0xdeadbeef);
843     /* default value: 75 */
844     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &old_spacing, 0 );
845     if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING"))
846         return;
847     /* do not increase the value as it would upset the user's icon layout */
848     if (!dotest_spi_iconhorizontalspacing( old_spacing - 1)) return;
849     dotest_spi_iconhorizontalspacing( 10); /* minimum is 32 */
850     /* restore */
851     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, old_spacing, 0, SPIF_UPDATEINIFILE );
852     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
853 }
854
855 static void test_SPI_SETSCREENSAVETIMEOUT( void )      /*     14 */
856 {
857     BOOL rc;
858     UINT old_timeout;
859     const UINT vals[]={0,32767};
860     unsigned int i;
861
862     trace("testing SPI_{GET,SET}SCREENSAVETIMEOUT\n");
863     SetLastError(0xdeadbeef);
864     rc=SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &old_timeout, 0 );
865     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVETIMEOUT"))
866         return;
867
868     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
869     {
870         UINT v;
871         char buf[10];
872
873         rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, vals[i], 0,
874                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
875         if (!test_error_msg(rc,"SPI_SETSCREENSAVETIMEOUT")) return;
876         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
877         test_change_message( SPI_SETSCREENSAVETIMEOUT, 0 );
878         sprintf( buf, "%d", vals[i] );
879         test_reg_key( SPI_SETSCREENSAVETIMEOUT_REGKEY,
880                       SPI_SETSCREENSAVETIMEOUT_VALNAME, buf );
881
882         SystemParametersInfoA( SPI_GETSCREENSAVETIMEOUT, 0, &v, 0 );
883         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
884         eq( v, vals[i], "SPI_{GET,SET}SCREENSAVETIMEOUT", "%d" );
885     }
886
887     rc=SystemParametersInfoA( SPI_SETSCREENSAVETIMEOUT, old_timeout, 0,
888                               SPIF_UPDATEINIFILE );
889     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
890 }
891
892 static void test_SPI_SETSCREENSAVEACTIVE( void )       /*     17 */
893 {
894     BOOL rc;
895     BOOL old_b;
896     const UINT vals[]={TRUE,FALSE};
897     unsigned int i;
898
899     trace("testing SPI_{GET,SET}SCREENSAVEACTIVE\n");
900     SetLastError(0xdeadbeef);
901     rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &old_b, 0 );
902     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVEACTIVE"))
903         return;
904
905     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
906     {
907         UINT v;
908
909         rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, vals[i], 0,
910                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
911         if (!test_error_msg(rc,"SPI_SETSCREENSAVEACTIVE")) return;
912         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
913         test_change_message( SPI_SETSCREENSAVEACTIVE, 0 );
914         test_reg_key( SPI_SETSCREENSAVEACTIVE_REGKEY,
915                       SPI_SETSCREENSAVEACTIVE_VALNAME,
916                       vals[i] ? "1" : "0" );
917
918         rc=SystemParametersInfoA( SPI_GETSCREENSAVEACTIVE, 0, &v, 0 );
919         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
920         eq( v, vals[i], "SPI_{GET,SET}SCREENSAVEACTIVE", "%d" );
921     }
922
923     rc=SystemParametersInfoA( SPI_SETSCREENSAVEACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
924     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
925 }
926
927 static void test_SPI_SETGRIDGRANULARITY( void )        /*     19 */
928 {
929     /* ??? */;
930 }
931
932 static void test_SPI_SETKEYBOARDDELAY( void )          /*     23 */
933 {
934     BOOL rc;
935     UINT old_delay;
936     const UINT vals[]={0,3};
937     unsigned int i;
938
939     trace("testing SPI_{GET,SET}KEYBOARDDELAY\n");
940     SetLastError(0xdeadbeef);
941     rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &old_delay, 0 );
942     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
943         return;
944
945     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
946     {
947         UINT delay;
948         char buf[10];
949
950         rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, vals[i], 0,
951                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
952         if (!test_error_msg(rc,"SPI_SETKEYBOARDDELAY")) return;
953         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
954         test_change_message( SPI_SETKEYBOARDDELAY, 0 );
955         sprintf( buf, "%d", vals[i] );
956         test_reg_key( SPI_SETKEYBOARDDELAY_REGKEY,
957                       SPI_SETKEYBOARDDELAY_VALNAME, buf );
958
959         rc=SystemParametersInfoA( SPI_GETKEYBOARDDELAY, 0, &delay, 0 );
960         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
961         eq( delay, vals[i], "SPI_{GET,SET}KEYBOARDDELAY", "%d" );
962     }
963
964     rc=SystemParametersInfoA( SPI_SETKEYBOARDDELAY, old_delay, 0, SPIF_UPDATEINIFILE );
965     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
966 }
967
968
969 /* test_SPI_ICONVERTICALSPACING helper */
970 static BOOL dotest_spi_iconverticalspacing( INT curr_val)
971 {
972     BOOL rc;
973     INT spacing, regval;
974     ICONMETRICSA im;
975
976     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
977                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
978     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING")) return FALSE;
979     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
980     test_change_message( SPI_ICONVERTICALSPACING, 0 );
981     if( curr_val < 32) curr_val = 32;
982     /* The registry keys depend on the Windows version and the values too
983      * let's test (works on win95,ME,NT4,2k,XP)
984      */
985     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY2, SPI_ICONVERTICALSPACING_VALNAME, dpi);
986     if( regval != curr_val)
987         regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
988     ok( curr_val == regval,
989         "wrong value in registry %d, expected %d\n", regval, curr_val);
990     /* compare with what SPI_ICONVERTICALSPACING returns */
991     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
992     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
993     eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
994     /* and with a system metrics */
995     eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
996     /* and with what SPI_GETICONMETRICS returns */
997     im.cbSize = sizeof(ICONMETRICSA);
998     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
999     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1000     eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
1001     return TRUE;
1002 }
1003
1004 static void test_SPI_ICONVERTICALSPACING( void )       /*     24 */
1005 {
1006     BOOL rc;
1007     INT old_spacing;
1008
1009     trace("testing SPI_ICONVERTICALSPACING\n");
1010     SetLastError(0xdeadbeef);
1011     /* default value: 75 */
1012     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
1013     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
1014         return;
1015     /* do not increase the value as it would upset the user's icon layout */
1016     if (!dotest_spi_iconverticalspacing( old_spacing - 1)) return;
1017     /* same tests with a value less than the minimum 32 */
1018     dotest_spi_iconverticalspacing( 10);
1019     /* restore */
1020     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
1021                               SPIF_UPDATEINIFILE );
1022     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",
1023         rc,GetLastError());
1024 }
1025
1026 static void test_SPI_SETICONTITLEWRAP( void )          /*     26 */
1027 {
1028     BOOL rc;
1029     BOOL old_b;
1030     const UINT vals[]={TRUE,FALSE};
1031     unsigned int i;
1032     ICONMETRICSA im;
1033
1034     /* These tests hang when XFree86 4.0 for Windows is running (tested on
1035      * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
1036      * running.
1037      */
1038     if (FindWindowA( NULL, "Cygwin/XFree86" ))
1039         return;
1040
1041     trace("testing SPI_{GET,SET}ICONTITLEWRAP\n");
1042     SetLastError(0xdeadbeef);
1043     rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &old_b, 0 );
1044     if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
1045         return;
1046
1047     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1048     {
1049         UINT v;
1050         UINT regval;
1051
1052         rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, vals[i], 0,
1053                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1054         if (!test_error_msg(rc,"SPI_SETICONTITLEWRAP")) return;
1055         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1056         test_change_message( SPI_SETICONTITLEWRAP, 1 );
1057         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2,
1058                 SPI_SETICONTITLEWRAP_VALNAME, dpi);
1059         if( regval != vals[i])
1060             regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
1061                     SPI_SETICONTITLEWRAP_VALNAME, dpi);
1062         ok( regval == vals[i],
1063                 "wrong value in registry %d, expected %d\n", regval, vals[i] );
1064
1065         rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
1066         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1067         eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
1068         /* and test with what SPI_GETICONMETRICS returns */
1069         im.cbSize = sizeof(ICONMETRICSA);
1070         rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
1071         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1072         eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
1073     }
1074
1075     rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, old_b, 0, SPIF_UPDATEINIFILE );
1076     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1077 }
1078
1079 static void test_SPI_SETMENUDROPALIGNMENT( void )      /*     28 */
1080 {
1081     BOOL rc;
1082     BOOL old_b;
1083     const UINT vals[]={TRUE,FALSE};
1084     unsigned int i;
1085
1086     trace("testing SPI_{GET,SET}MENUDROPALIGNMENT\n");
1087     SetLastError(0xdeadbeef);
1088     rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &old_b, 0 );
1089     if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
1090         return;
1091
1092     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1093     {
1094         UINT v;
1095
1096         rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, vals[i], 0,
1097                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1098         if (!test_error_msg(rc,"SPI_SETMENUDROPALIGNMENT")) return;
1099         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1100         test_change_message( SPI_SETMENUDROPALIGNMENT, 0 );
1101         test_reg_key_ex( SPI_SETMENUDROPALIGNMENT_REGKEY1,
1102                          SPI_SETMENUDROPALIGNMENT_REGKEY2,
1103                          SPI_SETMENUDROPALIGNMENT_VALNAME,
1104                          vals[i] ? "1" : "0" );
1105
1106         rc=SystemParametersInfoA( SPI_GETMENUDROPALIGNMENT, 0, &v, 0 );
1107         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1108         eq( v, vals[i], "SPI_{GET,SET}MENUDROPALIGNMENT", "%d" );
1109         eq( GetSystemMetrics( SM_MENUDROPALIGNMENT ), (int)vals[i],
1110             "SM_MENUDROPALIGNMENT", "%d" );
1111     }
1112
1113     rc=SystemParametersInfoA( SPI_SETMENUDROPALIGNMENT, old_b, 0,
1114                               SPIF_UPDATEINIFILE );
1115     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1116 }
1117
1118 static void test_SPI_SETDOUBLECLKWIDTH( void )         /*     29 */
1119 {
1120     BOOL rc;
1121     INT old_width;
1122     const UINT vals[]={0,10000};
1123     unsigned int i;
1124
1125     trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
1126     old_width = GetSystemMetrics( SM_CXDOUBLECLK );
1127
1128     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1129     {
1130         char buf[10];
1131
1132         SetLastError(0xdeadbeef);
1133         rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, vals[i], 0,
1134                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1135         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKWIDTH"))
1136             return;
1137
1138         test_change_message( SPI_SETDOUBLECLKWIDTH, 0 );
1139         sprintf( buf, "%d", vals[i] );
1140         test_reg_key_ex( SPI_SETDOUBLECLKWIDTH_REGKEY1,
1141                          SPI_SETDOUBLECLKWIDTH_REGKEY2,
1142                          SPI_SETDOUBLECLKWIDTH_VALNAME, buf );
1143         eq( GetSystemMetrics( SM_CXDOUBLECLK ), (int)vals[i],
1144             "SM_CXDOUBLECLK", "%d" );
1145     }
1146
1147     rc=SystemParametersInfoA( SPI_SETDOUBLECLKWIDTH, old_width, 0,
1148                               SPIF_UPDATEINIFILE );
1149     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1150 }
1151
1152 static void test_SPI_SETDOUBLECLKHEIGHT( void )        /*     30 */
1153 {
1154     BOOL rc;
1155     INT old_height;
1156     const UINT vals[]={0,10000};
1157     unsigned int i;
1158
1159     trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
1160     old_height = GetSystemMetrics( SM_CYDOUBLECLK );
1161
1162     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1163     {
1164         char buf[10];
1165
1166         SetLastError(0xdeadbeef);
1167         rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, vals[i], 0,
1168                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1169         if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLKHEIGHT"))
1170             return;
1171
1172         test_change_message( SPI_SETDOUBLECLKHEIGHT, 0 );
1173         sprintf( buf, "%d", vals[i] );
1174         test_reg_key_ex( SPI_SETDOUBLECLKHEIGHT_REGKEY1,
1175                          SPI_SETDOUBLECLKHEIGHT_REGKEY2,
1176                          SPI_SETDOUBLECLKHEIGHT_VALNAME, buf );
1177         eq( GetSystemMetrics( SM_CYDOUBLECLK ), (int)vals[i],
1178             "SM_CYDOUBLECLK", "%d" );
1179     }
1180
1181     rc=SystemParametersInfoA( SPI_SETDOUBLECLKHEIGHT, old_height, 0,
1182                               SPIF_UPDATEINIFILE );
1183     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1184 }
1185
1186 static void test_SPI_SETDOUBLECLICKTIME( void )        /*     32 */
1187 {
1188     BOOL rc;
1189     UINT curr_val;
1190     UINT saved_val;
1191     UINT old_time;
1192     char buf[10];
1193
1194     trace("testing SPI_{GET,SET}DOUBLECLICKTIME\n");
1195     old_time = GetDoubleClickTime();
1196
1197     curr_val = 0;
1198     SetLastError(0xdeadbeef);
1199     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1200                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1201     if (!test_error_msg(rc,"SPI_{GET,SET}DOUBLECLICKTIME"))
1202         return;
1203
1204     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1205     sprintf( buf, "%d", curr_val );
1206     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1207                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1208     curr_val = 500; /* used value for 0 */
1209     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1210
1211     curr_val = 1000;
1212     rc=SystemParametersInfoA( SPI_SETDOUBLECLICKTIME, curr_val, 0,
1213                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1214     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1215     test_change_message( SPI_SETDOUBLECLICKTIME, 0 );
1216     sprintf( buf, "%d", curr_val );
1217     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1218                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1219     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1220
1221     saved_val = curr_val;
1222
1223     curr_val = 0;
1224     SetDoubleClickTime( curr_val );
1225     sprintf( buf, "%d", saved_val );
1226     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1227                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1228     curr_val = 500; /* used value for 0 */
1229     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1230
1231     curr_val = 1000;
1232     SetDoubleClickTime( curr_val );
1233     sprintf( buf, "%d", saved_val );
1234     test_reg_key( SPI_SETDOUBLECLICKTIME_REGKEY,
1235                   SPI_SETDOUBLECLICKTIME_VALNAME, buf );
1236     eq( GetDoubleClickTime(), curr_val, "GetDoubleClickTime", "%d" );
1237
1238     rc=SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, old_time, 0, SPIF_UPDATEINIFILE);
1239     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1240 }
1241
1242 static void test_SPI_SETMOUSEBUTTONSWAP( void )        /*     33 */
1243 {
1244     BOOL rc;
1245     BOOL old_b;
1246     const UINT vals[]={TRUE,FALSE};
1247     unsigned int i;
1248
1249     trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
1250     old_b = GetSystemMetrics( SM_SWAPBUTTON );
1251
1252     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1253     {
1254         SetLastError(0xdeadbeef);
1255         rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
1256                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1257         if (!test_error_msg(rc,"SPI_SETMOUSEBUTTONSWAP")) return;
1258
1259         test_change_message( SPI_SETMOUSEBUTTONSWAP, 0 );
1260         test_reg_key( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1261                       SPI_SETMOUSEBUTTONSWAP_VALNAME,
1262                       vals[i] ? "1" : "0" );
1263         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
1264             "SM_SWAPBUTTON", "%d" );
1265         rc=SwapMouseButton((BOOL)vals[i^1]);
1266         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
1267             "SwapMouseButton", "%d" );
1268         ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
1269     }
1270
1271     rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, old_b, 0,
1272                               SPIF_UPDATEINIFILE );
1273     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1274 }
1275
1276 static void test_SPI_SETFASTTASKSWITCH( void )         /*     36 */
1277 {
1278     BOOL rc;
1279     BOOL v;
1280
1281     trace("testing SPI_GETFASTTASKSWITCH\n");
1282     SetLastError(0xdeadbeef);
1283     rc=SystemParametersInfoA( SPI_GETFASTTASKSWITCH, 0, &v, 0 );
1284     if (!test_error_msg(rc,"SPI_{GET,SET}FASTTASKSWITCH"))
1285         return;
1286
1287     /* there is not a single Windows platform on which SPI_GETFASTTASKSWITCH
1288      * works. That sure simplifies testing!
1289      */
1290 }
1291
1292 static void test_SPI_SETDRAGFULLWINDOWS( void )        /*     37 */
1293 {
1294     BOOL rc;
1295     BOOL old_b;
1296     const UINT vals[]={TRUE,FALSE};
1297     unsigned int i;
1298
1299     trace("testing SPI_{GET,SET}DRAGFULLWINDOWS\n");
1300     SetLastError(0xdeadbeef);
1301     rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &old_b, 0 );
1302
1303     /* SPI_{GET,SET}DRAGFULLWINDOWS is not implemented on Win95 */
1304     if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
1305         return;
1306
1307     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1308     {
1309         UINT v;
1310
1311         rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, vals[i], 0,
1312                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1313         if (!test_error_msg(rc,"SPI_SETDRAGFULLWINDOWS")) return;
1314         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1315         test_change_message( SPI_SETDRAGFULLWINDOWS, 0 );
1316         test_reg_key( SPI_SETDRAGFULLWINDOWS_REGKEY,
1317                       SPI_SETDRAGFULLWINDOWS_VALNAME,
1318                       vals[i] ? "1" : "0" );
1319
1320         rc=SystemParametersInfoA( SPI_GETDRAGFULLWINDOWS, 0, &v, 0 );
1321         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1322         eq( v, vals[i], "SPI_{GET,SET}DRAGFULLWINDOWS", "%d" );
1323     }
1324
1325     rc=SystemParametersInfoA( SPI_SETDRAGFULLWINDOWS, old_b, 0, SPIF_UPDATEINIFILE );
1326     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1327 }
1328
1329 #define test_reg_metric( KEY, VAL, val) \
1330 {   INT regval;\
1331     regval = metricfromreg( KEY, VAL, dpi);\
1332     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1333 }
1334  
1335 #define test_reg_metric2( KEY1, KEY2, VAL, val) \
1336 {   INT regval;\
1337     regval = metricfromreg( KEY1, VAL, dpi);\
1338     if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
1339     ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
1340 }
1341
1342 #define test_reg_font( KEY, VAL, LF) \
1343 {   LOGFONTA lfreg;\
1344     lffromreg( KEY, VAL, &lfreg);\
1345     ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == lfreg.lfHeight :\
1346                 MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
1347         (LF).lfWidth == lfreg.lfWidth &&\
1348         (LF).lfWeight == lfreg.lfWeight &&\
1349         !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
1350         , "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
1351 }
1352
1353 #define TEST_NONCLIENTMETRICS_REG( ncm) \
1354 /*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
1355 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
1356 test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
1357 /*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
1358 test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
1359 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
1360 test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
1361 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
1362 test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
1363 test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
1364 test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
1365 test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
1366 test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
1367 test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont);
1368
1369 /* get text metric height value for the specified logfont */
1370 static int get_tmheight( LOGFONTA *plf, int flag)
1371 {
1372     TEXTMETRICA tm;
1373     HFONT hfont = CreateFontIndirectA( plf);
1374     hfont = SelectObject( hdc, hfont);
1375     GetTextMetricsA( hdc, &tm);
1376     hfont = SelectObject( hdc, hfont);
1377     return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
1378 }
1379
1380 static void test_GetSystemMetrics( void);
1381 static UINT smcxsmsize = 999999999;
1382
1383 static void test_SPI_SETNONCLIENTMETRICS( void )               /*     44 */
1384 {
1385     BOOL rc;
1386     INT expect;
1387     NONCLIENTMETRICSA Ncmorig;
1388     NONCLIENTMETRICSA Ncmnew;
1389     NONCLIENTMETRICSA Ncmcur;
1390     NONCLIENTMETRICSA Ncmstart;
1391
1392     Ncmorig.cbSize = sizeof(NONCLIENTMETRICSA);
1393     Ncmnew.cbSize = sizeof(NONCLIENTMETRICSA);
1394     Ncmcur.cbSize = sizeof(NONCLIENTMETRICSA);
1395     Ncmstart.cbSize = sizeof(NONCLIENTMETRICSA);
1396
1397     trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
1398     SetLastError(0xdeadbeef);
1399     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmorig, FALSE );
1400     if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
1401         return;
1402     Ncmstart = Ncmorig;
1403     smcxsmsize = Ncmstart.iSmCaptionWidth;
1404     /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if 
1405        the caption font height is higher than the CaptionHeight field,
1406        the latter is adjusted accordingly. To be able to restore these setting
1407        accurately be restore the raw values. */
1408     Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, dpi);
1409     Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
1410     Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
1411     Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
1412     /* test registry entries */
1413     TEST_NONCLIENTMETRICS_REG( Ncmorig)
1414     /* make small changes */
1415     Ncmnew = Ncmstart;
1416     Ncmnew.iBorderWidth += 1;
1417     Ncmnew.iScrollWidth += 1;
1418     Ncmnew.iScrollHeight -= 1;
1419     Ncmnew.iCaptionWidth -= 2;
1420     Ncmnew.iCaptionHeight += 2;
1421     Ncmnew.lfCaptionFont.lfHeight +=1;
1422     Ncmnew.lfCaptionFont.lfWidth +=2;
1423     Ncmnew.lfCaptionFont.lfWeight +=1;
1424     Ncmnew.iSmCaptionWidth += 1;
1425     Ncmnew.iSmCaptionHeight += 2;
1426     Ncmnew.lfSmCaptionFont.lfHeight +=3;
1427     Ncmnew.lfSmCaptionFont.lfWidth -=1;
1428     Ncmnew.lfSmCaptionFont.lfWeight +=3;
1429     Ncmnew.iMenuWidth += 1;
1430     Ncmnew.iMenuHeight += 2;
1431     Ncmnew.lfMenuFont.lfHeight +=1;
1432     Ncmnew.lfMenuFont.lfWidth +=1;
1433     Ncmnew.lfMenuFont.lfWeight +=2;
1434     Ncmnew.lfStatusFont.lfHeight -=1;
1435     Ncmnew.lfStatusFont.lfWidth -=1;
1436     Ncmnew.lfStatusFont.lfWeight +=3;
1437     Ncmnew.lfMessageFont.lfHeight -=2;
1438     Ncmnew.lfMessageFont.lfWidth -=1;
1439     Ncmnew.lfMessageFont.lfWeight +=4;
1440
1441     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1442             SPIF_SENDCHANGE);
1443     if (!test_error_msg(rc,"SPI_SETNONCLIENTMETRICS")) return;
1444     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1445     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1446     /* get them back */
1447     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1448     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1449     /* test registry entries */
1450     TEST_NONCLIENTMETRICS_REG( Ncmcur)
1451     /* test the systemm metrics with these settings */
1452     test_GetSystemMetrics();
1453     /* now for something invalid: increase the {menu|caption|smcaption} fonts
1454        by a large amount will increase the {menu|caption|smcaption} height*/
1455     Ncmnew = Ncmstart;
1456     Ncmnew.lfMenuFont.lfHeight -= 8;
1457     Ncmnew.lfCaptionFont.lfHeight =-4;
1458     Ncmnew.lfSmCaptionFont.lfHeight -=10;
1459     /* also show that a few values are lo limited */
1460     Ncmnew.iCaptionWidth = 0;
1461     Ncmnew.iCaptionHeight = 0;
1462     Ncmnew.iScrollHeight = 0;
1463     Ncmnew.iScrollWidth  = 0;
1464
1465     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
1466             SPIF_SENDCHANGE);
1467     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1468     test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
1469     /* raw values are in registry */
1470     TEST_NONCLIENTMETRICS_REG( Ncmnew)
1471     /* get them back */
1472     rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
1473     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1474     /* cooked values are returned */
1475     expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
1476     ok( Ncmcur.iMenuHeight == expect,
1477         "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
1478     expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
1479     ok( Ncmcur.iCaptionHeight == expect,
1480         "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
1481     expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
1482     ok( Ncmcur.iSmCaptionHeight == expect,
1483         "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
1484
1485     ok( Ncmcur.iCaptionWidth == 8 ||
1486         Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme,  the value never changes */
1487         "CaptionWidth: %d expected 8\n", Ncmcur.iCaptionWidth);
1488     ok( Ncmcur.iScrollWidth == 8,
1489         "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
1490     ok( Ncmcur.iScrollHeight == 8,
1491         "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
1492     /* test the systemm metrics with these settings */
1493     test_GetSystemMetrics();
1494     /* restore */
1495     rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
1496         &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
1497     test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
1498     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1499 }
1500
1501 static void test_SPI_SETMINIMIZEDMETRICS( void )               /*     44 */
1502 {
1503     BOOL rc;
1504     INT regval;
1505     MINIMIZEDMETRICS lpMm_orig;
1506     MINIMIZEDMETRICS lpMm_new;
1507     MINIMIZEDMETRICS lpMm_cur;
1508
1509     lpMm_orig.cbSize = sizeof(MINIMIZEDMETRICS);
1510     lpMm_new.cbSize = sizeof(MINIMIZEDMETRICS);
1511     lpMm_cur.cbSize = sizeof(MINIMIZEDMETRICS);
1512
1513     trace("testing SPI_{GET,SET}MINIMIZEDMETRICS\n");
1514     SetLastError(0xdeadbeef);
1515     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
1516     if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
1517         return;
1518     /* Test registry. Note that it is perfectly valid for some fields to
1519      * not be set.
1520      */
1521     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1522     ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1523         regval, lpMm_orig.iWidth);
1524     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1525     ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1526         regval, lpMm_orig.iHorzGap);
1527     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1528     ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1529         regval, lpMm_orig.iVertGap);
1530     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1531     ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1532         regval, lpMm_orig.iArrange);
1533     /* set some new values */
1534     lpMm_cur.iWidth = 180;
1535     lpMm_cur.iHorzGap = 1;
1536     lpMm_cur.iVertGap = 1;
1537     lpMm_cur.iArrange = 5;
1538     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1539         &lpMm_cur, SPIF_UPDATEINIFILE );
1540     if (!test_error_msg(rc,"SPI_SETMINIMIZEDMETRICS")) return;
1541     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1542     /* read them back */
1543     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1544     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1545     /* and compare */
1546     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
1547     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1548     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1549     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1550     /* test registry */
1551     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1552     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1553         regval, lpMm_new.iWidth);
1554     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1555     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1556         regval, lpMm_new.iHorzGap);
1557     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1558     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1559         regval, lpMm_new.iVertGap);
1560     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1561     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1562         regval, lpMm_new.iArrange);
1563     /* test some system metrics */
1564     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1565         lpMm_new.iWidth,   "iWidth",   "%d" );
1566     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1567         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1568     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1569         lpMm_new.iVertGap, "iVertGap", "%d" );
1570     eq( GetSystemMetrics( SM_ARRANGE ),
1571         lpMm_new.iArrange, "iArrange", "%d" );
1572     /* now some really invalid settings */
1573     lpMm_cur.iWidth = -1;
1574     lpMm_cur.iHorzGap = -1;
1575     lpMm_cur.iVertGap = -1;
1576     lpMm_cur.iArrange = - 1;
1577     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1578         &lpMm_cur, SPIF_UPDATEINIFILE );
1579     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1580     /* read back */
1581     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1582     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1583     /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1584     eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
1585     eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1586     eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1587     eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1588     /* test registry */
1589     if (0)
1590     {
1591     /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1592     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1593     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1594         regval, lpMm_new.iWidth);
1595     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1596     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1597         regval, lpMm_new.iHorzGap);
1598     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1599     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1600         regval, lpMm_new.iVertGap);
1601     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1602     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1603         regval, lpMm_new.iArrange);
1604     }
1605     /* test some system metrics */
1606     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1607         lpMm_new.iWidth,   "iWidth",   "%d" );
1608     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1609         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1610     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1611         lpMm_new.iVertGap, "iVertGap", "%d" );
1612     eq( GetSystemMetrics( SM_ARRANGE ),
1613         lpMm_new.iArrange, "iArrange", "%d" );
1614     /* restore */
1615     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1616         &lpMm_orig, SPIF_UPDATEINIFILE );
1617     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1618     /* check that */
1619     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1620     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1621     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
1622     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1623     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1624     eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1625 }
1626
1627 static void test_SPI_SETICONMETRICS( void )               /*     46 */
1628 {
1629     BOOL rc, wrap;
1630     INT spacing;
1631     ICONMETRICSA im_orig;
1632     ICONMETRICSA im_new;
1633     ICONMETRICSA im_cur;
1634     INT regval;
1635         
1636     im_orig.cbSize = sizeof(ICONMETRICSA);
1637     im_new.cbSize = sizeof(ICONMETRICSA);
1638     im_cur.cbSize = sizeof(ICONMETRICSA);
1639
1640     trace("testing SPI_{GET,SET}ICONMETRICS\n");
1641     SetLastError(0xdeadbeef);
1642     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1643     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1644         return;
1645    /* check some registry values */ 
1646     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1647     ok( regval==im_orig.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1648     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1649     ok( regval==im_orig.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1650     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1651     if( regval != im_orig.iTitleWrap)
1652         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1653     ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1654
1655     /* change everything without creating something invalid ( Win9x would ignore
1656      * an invalid font for instance) */
1657     im_cur = im_orig;
1658     im_cur.iHorzSpacing += 10;
1659     im_cur.iVertSpacing += 6;
1660     im_cur.iTitleWrap = !im_cur.iTitleWrap;
1661     im_cur.lfFont.lfHeight += 1;
1662     im_cur.lfFont.lfWidth += 2;
1663     im_cur.lfFont.lfEscapement = 1;
1664     im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1665     im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1666     im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1667     im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1668     im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1669     im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1670                                 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1671     im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1672     im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1673     im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ? 
1674                                 DRAFT_QUALITY : DEFAULT_QUALITY;
1675     if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1676         strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1677     else
1678         strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1679
1680     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1681     if (!test_error_msg(rc,"SPI_SETICONMETRICS")) return;
1682     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1683
1684     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1685     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1686     /* test GET <-> SETICONMETRICS */ 
1687     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1688     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1689     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
1690     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%d" );
1691     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%d" );
1692     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%d" );
1693     eq( im_new.lfFont.lfWeight,         im_cur.lfFont.lfWeight,         "lfWeight",         "%d" );
1694     eq( im_new.lfFont.lfItalic,         im_cur.lfFont.lfItalic,         "lfItalic",         "%d" );
1695     eq( im_new.lfFont.lfStrikeOut,      im_cur.lfFont.lfStrikeOut,      "lfStrikeOut",      "%d" );
1696     eq( im_new.lfFont.lfUnderline,      im_cur.lfFont.lfUnderline,      "lfUnderline",      "%d" );
1697     eq( im_new.lfFont.lfCharSet,        im_cur.lfFont.lfCharSet,        "lfCharSet",        "%d" );
1698     eq( im_new.lfFont.lfOutPrecision,   im_cur.lfFont.lfOutPrecision,   "lfOutPrecision",   "%d" );
1699     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
1700     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1701     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
1702     ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1703         "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1704         im_cur.lfFont.lfFaceName);
1705     /* test some system metrics */
1706     eq( GetSystemMetrics( SM_CXICONSPACING ),
1707         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1708     eq( GetSystemMetrics( SM_CYICONSPACING ),
1709         im_new.iVertSpacing, "iVertSpacing", "%d" );
1710    /* check some registry values */ 
1711     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1712     ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1713     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1714     ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1715     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1716     if( regval != im_cur.iTitleWrap)
1717         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1718     ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1719     /* test some values from other SPI_GETxxx calls */
1720     rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1721     ok( rc && spacing == im_cur.iHorzSpacing,
1722         "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1723         spacing, im_cur.iHorzSpacing);
1724     rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1725     ok( rc && spacing == im_cur.iVertSpacing,
1726         "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1727         spacing, im_cur.iVertSpacing);
1728     rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1729     ok( rc && wrap == im_cur.iTitleWrap,
1730         "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1731         wrap, im_cur.iTitleWrap);
1732     /* restore old values */
1733     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1734     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1735     
1736     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1737     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1738     
1739     eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1740     eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1741     eq( im_new.iTitleWrap,   im_orig.iTitleWrap,   "iTitleWrap",   "%d" );
1742 }
1743
1744 static void test_SPI_SETWORKAREA( void )               /*     47 */
1745 {
1746     BOOL rc;
1747     RECT old_area;
1748     RECT area;
1749     RECT curr_val;
1750
1751     trace("testing SPI_{GET,SET}WORKAREA\n");
1752     SetLastError(0xdeadbeef);
1753     rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1754     if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1755         return;
1756
1757     /* Modify the work area only minimally as this causes the icons that
1758      * fall outside it to be moved around thus requiring the user to
1759      * reposition them manually one by one.
1760      * Changing the work area by just one pixel should make this occurrence
1761      * reasonably unlikely.
1762      */
1763     curr_val.left = old_area.left;
1764     curr_val.top = old_area.top;
1765     curr_val.right = old_area.right-1;
1766     curr_val.bottom = old_area.bottom-1;
1767     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1768                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1769     if (!test_error_msg(rc,"SPI_SETWORKAREA")) return;
1770     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1771     test_change_message( SPI_SETWORKAREA, 0 );
1772     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1773     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1774     eq( area.left,   curr_val.left,   "left",   "%d" );
1775     eq( area.top,    curr_val.top,    "top",    "%d" );
1776     eq( area.right,  curr_val.right,  "right",  "%d" );
1777     eq( area.bottom, curr_val.bottom, "bottom", "%d" );
1778
1779     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1780                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1781     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1782     test_change_message( SPI_SETWORKAREA, 0 );
1783     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1784     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1785     eq( area.left,   old_area.left,   "left",   "%d" );
1786     eq( area.top,    old_area.top,    "top",    "%d" );
1787     eq( area.right,  old_area.right,  "right",  "%d" );
1788     eq( area.bottom, old_area.bottom, "bottom", "%d" );
1789 }
1790
1791 static void test_SPI_SETSHOWSOUNDS( void )             /*     57 */
1792 {
1793     BOOL rc;
1794     BOOL old_b;
1795     const UINT vals[]={TRUE,FALSE};
1796     unsigned int i;
1797
1798     trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1799     SetLastError(0xdeadbeef);
1800     rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1801     /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
1802     if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1803         return;
1804
1805     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1806     {
1807         UINT v;
1808
1809         rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1810                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1811         if (!test_error_msg(rc,"SPI_SETSHOWSOUNDS")) return;
1812         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1813         test_change_message( SPI_SETSHOWSOUNDS, 1 );
1814         test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1815                       SPI_SETSHOWSOUNDS_VALNAME,
1816                       vals[i] ? "1" : "0" );
1817
1818         rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1819         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1820         eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1821         eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1822             "SM_SHOWSOUNDS", "%d" );
1823     }
1824
1825     rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1826     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1827 }
1828
1829 static void test_SPI_SETKEYBOARDPREF( void )           /*     69 */
1830 {
1831     BOOL rc;
1832     BOOL old_b;
1833     const UINT vals[]={TRUE,FALSE};
1834     unsigned int i;
1835
1836     trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1837     SetLastError(0xdeadbeef);
1838     rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1839     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1840         return;
1841
1842     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1843     {
1844         BOOL v;
1845
1846         rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1847                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1848         if (!test_error_msg(rc,"SPI_SETKEYBOARDPREF")) return;
1849         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1850         test_change_message( SPI_SETKEYBOARDPREF, 1 );
1851         test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1852                           SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1853                           vals[i] ? "1" : "0" );
1854
1855         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1856         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1857         eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1858     }
1859
1860     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1861     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1862 }
1863
1864 static void test_SPI_SETSCREENREADER( void )           /*     71 */
1865 {
1866     BOOL rc;
1867     BOOL old_b;
1868     const UINT vals[]={TRUE,FALSE};
1869     unsigned int i;
1870
1871     trace("testing SPI_{GET,SET}SCREENREADER\n");
1872     SetLastError(0xdeadbeef);
1873     rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
1874     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
1875         return;
1876
1877     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1878     {
1879         BOOL v;
1880
1881         rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
1882                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1883         if (!test_error_msg(rc,"SPI_SETSCREENREADER")) return;
1884         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1885         test_change_message( SPI_SETSCREENREADER, 1 );
1886         test_reg_key_ex2( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
1887                       SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
1888                       vals[i] ? "1" : "0" );
1889
1890         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
1891         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1892         eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
1893     }
1894
1895     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
1896     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1897 }
1898
1899 static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
1900 {
1901     BOOL rc;
1902     BOOL old_b;
1903     const UINT vals[]={0xffffffff,0,1,2};
1904     unsigned int i;
1905
1906     trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
1907     if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */ 
1908     SetLastError(0xdeadbeef);
1909     rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
1910     if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
1911         return;
1912
1913     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1914     {
1915         UINT v;
1916
1917         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
1918                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1919         if (!test_error_msg(rc,"SPI_SETFONTSMOOTHING")) return;
1920         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1921         test_change_message( SPI_SETFONTSMOOTHING, 0 );
1922         test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
1923                       SPI_SETFONTSMOOTHING_VALNAME,
1924                       vals[i] ? "2" : "0" );
1925
1926         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
1927         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1928         eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
1929     }
1930
1931     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
1932     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1933 }
1934
1935 static void test_SPI_SETLOWPOWERACTIVE( void )         /*     85 */
1936 {
1937     BOOL rc;
1938     BOOL old_b;
1939     const UINT vals[]={TRUE,FALSE};
1940     unsigned int i;
1941
1942     trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
1943     SetLastError(0xdeadbeef);
1944     rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
1945     if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
1946         return;
1947
1948     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1949     {
1950         UINT v;
1951
1952         rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
1953                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1954         if (!test_error_msg(rc,"SPI_SETLOWPOWERACTIVE")) return;
1955         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1956         test_change_message( SPI_SETLOWPOWERACTIVE, 1 );
1957         test_reg_key( SPI_SETLOWPOWERACTIVE_REGKEY,
1958                       SPI_SETLOWPOWERACTIVE_VALNAME,
1959                       vals[i] ? "1" : "0" );
1960
1961         /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */
1962         rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
1963         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1964         ok(v == vals[i] ||
1965            v == 0, /* win2k3 */
1966            "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
1967     }
1968
1969     rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1970     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1971 }
1972
1973 static void test_SPI_SETPOWEROFFACTIVE( void )         /*     86 */
1974 {
1975     BOOL rc;
1976     BOOL old_b;
1977     const UINT vals[]={TRUE,FALSE};
1978     unsigned int i;
1979
1980     trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
1981     SetLastError(0xdeadbeef);
1982     rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
1983     if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
1984         return;
1985
1986     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1987     {
1988         UINT v;
1989
1990         rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
1991                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1992         if (!test_error_msg(rc,"SPI_SETPOWEROFFACTIVE")) return;
1993         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1994         test_change_message( SPI_SETPOWEROFFACTIVE, 1 );
1995         test_reg_key( SPI_SETPOWEROFFACTIVE_REGKEY,
1996                       SPI_SETPOWEROFFACTIVE_VALNAME,
1997                       vals[i] ? "1" : "0" );
1998
1999         /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */
2000         rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
2001         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2002         ok(v == vals[i] ||
2003            v == 0, /* win2k3 */
2004            "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
2005     }
2006
2007     rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
2008     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2009 }
2010
2011 static void test_SPI_SETSNAPTODEFBUTTON( void )         /*     95 */
2012 {
2013     BOOL rc;
2014     BOOL old_b;
2015     const UINT vals[]={TRUE,FALSE};
2016     unsigned int i;
2017
2018     trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n");
2019     SetLastError(0xdeadbeef);
2020     rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 );
2021     if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
2022         return;
2023
2024     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2025     {
2026         UINT v;
2027
2028         rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, vals[i], 0,
2029                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2030         if (!test_error_msg(rc,"SPI_SETSNAPTODEFBUTTON")) return;
2031         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2032         test_change_message( SPI_SETSNAPTODEFBUTTON, 0 );
2033         test_reg_key( SPI_SETSNAPTODEFBUTTON_REGKEY,
2034                       SPI_SETSNAPTODEFBUTTON_VALNAME,
2035                       vals[i] ? "1" : "0" );
2036
2037         rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &v, 0 );
2038         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2039         eq( v, vals[i], "SPI_GETSNAPTODEFBUTTON", "%d" );
2040     }
2041
2042     rc=SystemParametersInfoA( SPI_SETSNAPTODEFBUTTON, old_b, 0, SPIF_UPDATEINIFILE );
2043     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2044 }
2045
2046 static void test_SPI_SETMOUSEHOVERWIDTH( void )      /*     99 */
2047 {
2048     BOOL rc;
2049     UINT old_width;
2050     const UINT vals[]={0,32767};
2051     unsigned int i;
2052
2053     trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
2054     SetLastError(0xdeadbeef);
2055     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
2056     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2057     * what MSDN states (Verified on Win98SE)
2058     */
2059     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
2060         return;
2061     
2062     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2063     {
2064         UINT v;
2065         char buf[10];
2066
2067         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
2068                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2069         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERWIDTH")) return;
2070         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2071         test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
2072         sprintf( buf, "%d", vals[i] );
2073         test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
2074                       SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
2075
2076         SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
2077         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2078         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
2079     }
2080
2081     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
2082                               SPIF_UPDATEINIFILE );
2083     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2084 }
2085
2086 static void test_SPI_SETMOUSEHOVERHEIGHT( void )      /*     101 */
2087 {
2088     BOOL rc;
2089     UINT old_height;
2090     const UINT vals[]={0,32767};
2091     unsigned int i;
2092
2093     trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
2094     SetLastError(0xdeadbeef);
2095     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
2096     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2097      * what MSDN states (Verified on Win98SE)
2098      */
2099     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
2100         return;
2101     
2102     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2103     {
2104         UINT v;
2105         char buf[10];
2106
2107         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2108                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2109         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERHEIGHT")) return;
2110         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2111         test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2112         sprintf( buf, "%d", vals[i] );
2113         test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2114                       SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2115
2116         SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2117         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2118         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2119     }
2120
2121     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2122                               SPIF_UPDATEINIFILE );
2123     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2124 }
2125
2126 static void test_SPI_SETMOUSEHOVERTIME( void )      /*     103 */
2127 {
2128     BOOL rc;
2129     UINT old_time;
2130
2131     /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2132      * defaulted to a value of 10 automatically.
2133      */
2134     const UINT vals[]={10,32767};
2135     unsigned int i;
2136
2137     trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2138     SetLastError(0xdeadbeef);
2139     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2140     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2141      * what MSDN states (Verified on Win98SE)
2142      */    
2143     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2144         return;
2145     
2146     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2147     {
2148         UINT v;
2149         char buf[10];
2150
2151         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2152                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2153         if (!test_error_msg(rc,"SPI_SETMOUSEHOVERTIME")) return;
2154         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2155         test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2156         sprintf( buf, "%d", vals[i] );
2157         test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2158                       SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2159
2160         SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2161         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2162         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2163     }
2164
2165     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2166                               SPIF_UPDATEINIFILE );
2167     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2168 }
2169
2170 static void test_SPI_SETWHEELSCROLLLINES( void )      /*     105 */
2171 {
2172     BOOL rc;
2173     UINT old_lines;
2174     const UINT vals[]={0,32767};
2175     unsigned int i;
2176
2177     trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2178     SetLastError(0xdeadbeef);
2179     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2180
2181     /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2182     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2183         return;
2184
2185     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2186     {
2187         UINT v;
2188         char buf[10];
2189
2190         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2191                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2192         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLLINES")) return;
2193         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2194         test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2195         sprintf( buf, "%d", vals[i] );
2196         test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2197                       SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2198
2199         SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2200         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2201         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2202     }
2203
2204     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2205                               SPIF_UPDATEINIFILE );
2206     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2207 }
2208
2209 static void test_SPI_SETMENUSHOWDELAY( void )      /*     107 */
2210 {
2211     BOOL rc;
2212     UINT old_delay;
2213     const UINT vals[]={0,32767};
2214     unsigned int i;
2215
2216     trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2217     SetLastError(0xdeadbeef);
2218     rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2219
2220     /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2221     if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2222         return;
2223
2224     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2225     {
2226         UINT v;
2227         char buf[10];
2228
2229         rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2230                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2231         if (!test_error_msg(rc,"SPI_SETMENUSHOWDELAY")) return;
2232         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2233         test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2234         sprintf( buf, "%d", vals[i] );
2235         test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2236                       SPI_SETMENUSHOWDELAY_VALNAME, buf );
2237
2238         SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2239         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2240         eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2241     }
2242
2243     rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2244                               SPIF_UPDATEINIFILE );
2245     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2246 }
2247
2248 static void test_SPI_SETWHEELSCROLLCHARS( void )      /*     108 */
2249 {
2250     BOOL rc;
2251     UINT old_chars;
2252     const UINT vals[]={32767,0};
2253     unsigned int i;
2254
2255     trace("testing SPI_{GET,SET}WHEELSCROLLCHARS\n");
2256     SetLastError(0xdeadbeef);
2257     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &old_chars, 0 );
2258
2259     /* SPI_{GET,SET}WHEELSCROLLCHARS not supported on Windows 95 */
2260     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
2261         return;
2262
2263     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2264     {
2265         UINT v;
2266         char buf[10];
2267
2268         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, vals[i], 0,
2269                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2270         if (!test_error_msg(rc,"SPI_SETWHEELSCROLLCHARS")) return;
2271         test_change_message( SPI_SETWHEELSCROLLCHARS, 0 );
2272         sprintf( buf, "%d", vals[i] );
2273         test_reg_key( SPI_SETMOUSESCROLLCHARS_REGKEY,
2274                       SPI_SETMOUSESCROLLCHARS_VALNAME, buf );
2275
2276         SystemParametersInfoA( SPI_GETWHEELSCROLLCHARS, 0, &v, 0 );
2277         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2278         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLCHARS", "%d" );
2279     }
2280
2281     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLCHARS, old_chars, 0,
2282                               SPIF_UPDATEINIFILE );
2283     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2284 }
2285
2286 static void test_SPI_SETWALLPAPER( void )              /*   115 */
2287 {
2288     BOOL rc;
2289     char oldval[260];
2290     char newval[260];
2291
2292     trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2293     SetLastError(0xdeadbeef);
2294     rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2295     /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
2296      * unimplemented on NT4
2297      */
2298     if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2299         return;
2300
2301     strcpy(newval, "");
2302     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2303     if (!test_error_msg(rc,"SPI_SETDESKWALLPAPER")) return;
2304     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
2305     test_change_message(SPI_SETDESKWALLPAPER, 0);
2306
2307     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2308     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2309
2310     test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2311 }
2312
2313 static void test_WM_DISPLAYCHANGE(void)
2314 {
2315     DEVMODE mode, startmode;
2316     int start_bpp, last_set_bpp = 0;
2317     int test_bpps[] = {8, 16, 24, 32}, i;
2318     LONG change_ret;
2319     DWORD wait_ret;
2320
2321     if (!pChangeDisplaySettingsExA)
2322     {
2323         win_skip("ChangeDisplaySettingsExA is not available\n");
2324         return;
2325     }
2326
2327     displaychange_test_active = TRUE;
2328
2329     memset(&startmode, 0, sizeof(startmode));
2330     startmode.dmSize = sizeof(startmode);
2331     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &startmode);
2332     start_bpp = startmode.dmBitsPerPel;
2333
2334     displaychange_sem = CreateSemaphore(NULL, 0, 1, NULL);
2335
2336     for(i = 0; i < sizeof(test_bpps)/sizeof(test_bpps[0]); i++) {
2337         last_bpp = -1;
2338
2339         memset(&mode, 0, sizeof(mode));
2340         mode.dmSize = sizeof(mode);
2341         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2342         mode.dmBitsPerPel = test_bpps[i];
2343         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2344         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2345
2346         change_counter = 0; /* This sends a SETTINGSCHANGE message as well in which we aren't interested */
2347         displaychange_ok = TRUE;
2348         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2349         /* Wait quite long for the message, screen setting changes can take some time */
2350         if(change_ret == DISP_CHANGE_SUCCESSFUL) {
2351             wait_ret = WaitForSingleObject(displaychange_sem, 10000);
2352             /* we may not get a notification if nothing changed */
2353             if (wait_ret == WAIT_TIMEOUT && !last_set_bpp && start_bpp == test_bpps[i])
2354                 continue;
2355             ok(wait_ret == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
2356         }
2357         displaychange_ok = FALSE;
2358
2359         if(change_ret != DISP_CHANGE_SUCCESSFUL) {
2360             skip("Setting depth %d failed(ret = %d)\n", test_bpps[i], change_ret);
2361             ok(last_bpp == -1, "WM_DISPLAYCHANGE was sent with wParam %d despite mode change failure\n", last_bpp);
2362             continue;
2363         }
2364
2365         if(start_bpp != test_bpps[i]) {
2366             todo_wine ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2367         } else {
2368             ok(last_bpp == test_bpps[i], "Set bpp %d, but WM_DISPLAYCHANGE reported bpp %d\n", test_bpps[i], last_bpp);
2369         }
2370         last_set_bpp = test_bpps[i];
2371     }
2372
2373     if(start_bpp != last_set_bpp && last_set_bpp != 0) {
2374         memset(&mode, 0, sizeof(mode));
2375         mode.dmSize = sizeof(mode);
2376         mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2377         mode.dmBitsPerPel = start_bpp;
2378         mode.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
2379         mode.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
2380
2381         displaychange_ok = TRUE;
2382         change_ret = pChangeDisplaySettingsExA(NULL, &mode, NULL, 0, NULL);
2383         WaitForSingleObject(displaychange_sem, 10000);
2384         displaychange_ok = FALSE;
2385         CloseHandle(displaychange_sem);
2386         displaychange_sem = 0;
2387     }
2388
2389     displaychange_test_active = FALSE;
2390 }
2391
2392 /*
2393  * Registry entries for the system parameters.
2394  * Names are created by 'SET' flags names.
2395  * We assume that corresponding 'GET' entries use the same registry keys.
2396  */
2397 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2398 {
2399     test_SPI_SETBEEP();                         /*      1 */
2400     test_SPI_SETMOUSE();                        /*      4 */
2401     test_SPI_SETBORDER();                       /*      6 */
2402     test_SPI_SETKEYBOARDSPEED();                /*     10 */
2403     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
2404     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
2405     test_SPI_SETSCREENSAVEACTIVE();             /*     17 */
2406     test_SPI_SETGRIDGRANULARITY();              /*     19 */
2407     test_SPI_SETKEYBOARDDELAY();                /*     23 */
2408     test_SPI_ICONVERTICALSPACING();             /*     24 */
2409     test_SPI_SETICONTITLEWRAP();                /*     26 */
2410     test_SPI_SETMENUDROPALIGNMENT();            /*     28 */
2411     test_SPI_SETDOUBLECLKWIDTH();               /*     29 */
2412     test_SPI_SETDOUBLECLKHEIGHT();              /*     30 */
2413     test_SPI_SETDOUBLECLICKTIME();              /*     32 */
2414     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
2415     test_SPI_SETFASTTASKSWITCH();               /*     36 */
2416     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
2417     test_SPI_SETNONCLIENTMETRICS();             /*     42 */
2418     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
2419     test_SPI_SETICONMETRICS();                  /*     46 */
2420     test_SPI_SETWORKAREA();                     /*     47 */
2421     test_SPI_SETSHOWSOUNDS();                   /*     57 */
2422     test_SPI_SETKEYBOARDPREF();                 /*     69 */
2423     test_SPI_SETSCREENREADER();                 /*     71 */
2424     test_SPI_SETFONTSMOOTHING();                /*     75 */
2425     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
2426     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
2427     test_SPI_SETSNAPTODEFBUTTON();              /*     95 */
2428     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
2429     test_SPI_SETMOUSEHOVERHEIGHT();             /*    101 */
2430     test_SPI_SETMOUSEHOVERTIME();               /*    103 */
2431     test_SPI_SETWHEELSCROLLLINES();             /*    105 */
2432     test_SPI_SETMENUSHOWDELAY();                /*    107 */
2433     test_SPI_SETWHEELSCROLLCHARS();             /*    108 */
2434     test_SPI_SETWALLPAPER();                    /*    115 */
2435
2436     test_WM_DISPLAYCHANGE();
2437
2438     SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2439     return 0;
2440 }
2441
2442 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2443  * icon metrics and minimized metrics. 
2444  */
2445
2446 /* copied from wine's GdiGetCharDimensions, which is not available on most
2447  * windows versions */
2448 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2449 {
2450     SIZE sz;
2451     static const CHAR alphabet[] = {
2452         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2453         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2454         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2455
2456     if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2457
2458     if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2459
2460     if (height) *height = sz.cy;
2461     return (sz.cx / 26 + 1) / 2;
2462 }
2463
2464 /* get text metrics and/or "average" char width of the specified logfont
2465  * for the specified dc */
2466 static void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2467 {
2468     HFONT hfont, hfontsav;
2469     TEXTMETRICA tm;
2470     if( !ptm) ptm = &tm;
2471     hfont = CreateFontIndirectA( plf);
2472     if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2473         ptm->tmHeight = -1;
2474         if( psz) *psz = 10;
2475         if( hfont) DeleteObject( hfont);
2476         return;
2477     }
2478     GetTextMetricsA( hdc, ptm);
2479     if( psz)
2480         if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2481             *psz = 10;
2482     SelectObject( hdc, hfontsav);
2483     DeleteObject( hfont);
2484 }
2485
2486 static int gsm_error_ctr;
2487
2488 #define ok_gsm( i, e)\
2489 {\
2490     int exp = (e);\
2491     int act = GetSystemMetrics( (i));\
2492     if( exp != act) gsm_error_ctr++;\
2493     ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2494 }
2495 #define ok_gsm_2( i, e1, e2)\
2496 {\
2497     int exp1 = (e1);\
2498     int exp2 = (e2);\
2499     int act = GetSystemMetrics( (i));\
2500     if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2501     ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2502 }
2503 #define ok_gsm_3( i, e1, e2, e3)\
2504 {\
2505     int exp1 = (e1);\
2506     int exp2 = (e2);\
2507     int exp3 = (e3);\
2508     int act = GetSystemMetrics( (i));\
2509     if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2510     ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2511 }
2512
2513 static void test_GetSystemMetrics( void)
2514 {
2515     TEXTMETRICA tmMenuFont;
2516     UINT IconSpacing, IconVerticalSpacing;
2517
2518     HDC hdc = CreateIC( "Display", 0, 0, 0);
2519     UINT avcwCaption;
2520     INT CaptionWidth;
2521     MINIMIZEDMETRICS minim;
2522     NONCLIENTMETRICS ncm;
2523     SIZE screen;
2524
2525     minim.cbSize = sizeof( minim);
2526     ncm.cbSize = sizeof( ncm);
2527     SystemParametersInfo( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2528     SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2529
2530     /* CaptionWidth from the registry may have different value of iCaptionWidth
2531      * from the non client metrics (observed on WinXP) */
2532     CaptionWidth = metricfromreg(
2533             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2534     get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2535     get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2536     /* FIXME: use icon metric */
2537     if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2538         IconVerticalSpacing = 0;
2539     if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2540         IconSpacing = 0;
2541     /* reset error counters */
2542     gsm_error_ctr = 0;
2543
2544     /* the tests: */
2545
2546     /* SM_CXSCREEN, cannot test these two */
2547     /* SM_CYSCREEN */
2548     ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
2549     ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
2550     ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2551     ok_gsm( SM_CXBORDER, 1);
2552     ok_gsm( SM_CYBORDER, 1);
2553     ok_gsm( SM_CXDLGFRAME, 3);
2554     ok_gsm( SM_CYDLGFRAME, 3);
2555     ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
2556     ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
2557     /* SM_CXICON */
2558     /* SM_CYICON */
2559     /* SM_CXCURSOR */
2560     /* SM_CYCURSOR */
2561     ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2562     ok_gsm( SM_CXFULLSCREEN,
2563             GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2564     ok_gsm( SM_CYFULLSCREEN,
2565             GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2566     /* SM_CYKANJIWINDOW */
2567     /* SM_MOUSEPRESENT */
2568     ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2569     ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2570     /* SM_DEBUG */
2571     /* SM_SWAPBUTTON */
2572     /* SM_RESERVED1 */
2573     /* SM_RESERVED2 */
2574     /* SM_RESERVED3 */
2575     /* SM_RESERVED4 */
2576     ok_gsm( SM_CXMIN, 3 * max( CaptionWidth, 8) + GetSystemMetrics( SM_CYSIZE) +
2577             4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2578     ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2579             2 * GetSystemMetrics( SM_CYFRAME));
2580     ok_gsm_2( SM_CXSIZE,
2581         ncm.iCaptionWidth,  /* classic/standard windows style */
2582         GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2583         );
2584     ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
2585     ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2586     ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2587     ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
2588     ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
2589     /* SM_CXDOUBLECLK */
2590     /* SM_CYDOUBLECLK */
2591     if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2592     if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2593     /* SM_MENUDROPALIGNMENT */
2594     /* SM_PENWINDOWS */
2595     /* SM_DBCSENABLED */
2596     /* SM_CMOUSEBUTTONS */
2597     /* SM_SECURE */
2598     ok_gsm( SM_CXEDGE, 2);
2599     ok_gsm( SM_CYEDGE, 2);
2600     /* sign-extension for iHorzGap/iVertGap is broken on Win9x */
2601     ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + (short)minim.iHorzGap );
2602     ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + (short)minim.iVertGap );
2603     /* SM_CXSMICON */
2604     /* SM_CYSMICON */
2605     ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2606     ok_gsm_3( SM_CXSMSIZE,
2607         ncm.iSmCaptionWidth, /* classic/standard windows style */
2608         GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2609         smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2610                       does not change it */
2611         );
2612     ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2613     ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2614     ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2615     /* SM_ARRANGE */
2616     ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2617     ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2618     screen.cx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
2619     screen.cy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
2620     if (!screen.cx || !screen.cy)  /* not supported on NT4 */
2621     {
2622         screen.cx = GetSystemMetrics( SM_CXSCREEN );
2623         screen.cy = GetSystemMetrics( SM_CYSCREEN );
2624     }
2625     ok_gsm( SM_CXMAXTRACK, screen.cx + 4 + 2 * GetSystemMetrics(SM_CXFRAME));
2626     ok_gsm( SM_CYMAXTRACK, screen.cy + 4 + 2 * GetSystemMetrics(SM_CYFRAME));
2627     /* the next two cannot really be tested as they depend on (application)
2628      * toolbars */
2629     /* SM_CXMAXIMIZED */
2630     /* SM_CYMAXIMIZED */
2631     /* SM_NETWORK */
2632     /* */
2633     /* */
2634     /* */
2635     /* SM_CLEANBOOT */
2636     /* SM_CXDRAG */
2637     /* SM_CYDRAG */
2638     /* SM_SHOWSOUNDS */
2639     ok_gsm( SM_CXMENUCHECK,
2640             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2641     ok_gsm( SM_CYMENUCHECK,
2642             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2643     /* SM_SLOWMACHINE */
2644     /* SM_MIDEASTENABLED */
2645     /* SM_MOUSEWHEELPRESENT */
2646     /* SM_XVIRTUALSCREEN */
2647     /* SM_YVIRTUALSCREEN */
2648     /* SM_CXVIRTUALSCREEN */
2649     /* SM_CYVIRTUALSCREEN */
2650     /* SM_CMONITORS */
2651     /* SM_SAMEDISPLAYFORMAT */
2652     /* SM_IMMENABLED */
2653     /* SM_CXFOCUSBORDER */
2654     /* SM_CYFOCUSBORDER */
2655     /* SM_TABLETPC */
2656     /* SM_MEDIACENTER */
2657     /* SM_CMETRICS */
2658     /* end of tests */
2659     if( gsm_error_ctr ) { /* if any errors where found */
2660         trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2661                 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2662         trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2663                 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2664         trace( "Captionfontchar width %d  MenuFont %d,%d CaptionWidth from registry: %d\n",
2665                 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidth);
2666     }
2667     ReleaseDC( 0, hdc);
2668 }
2669
2670 static void test_EnumDisplaySettings(void)
2671 {
2672     DEVMODE devmode;
2673     DWORD val;
2674     HDC hdc;
2675     DWORD num;
2676
2677     memset(&devmode, 0, sizeof(devmode));
2678     devmode.dmSize = sizeof(devmode);
2679     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2680
2681     hdc = GetDC(0);
2682     val = GetDeviceCaps(hdc, BITSPIXEL);
2683     ok(devmode.dmBitsPerPel == val, "GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
2684         val, devmode.dmBitsPerPel);
2685
2686     val = GetDeviceCaps(hdc, NUMCOLORS);
2687     if(devmode.dmBitsPerPel <= 8) {
2688         ok(val == 256, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2689     } else {
2690         ok(val == -1, "Screen bpp is %d, NUMCOLORS returned %d\n", devmode.dmBitsPerPel, val);
2691     }
2692
2693     ReleaseDC(0, hdc);
2694
2695     num = 1;
2696     while (1) {
2697         SetLastError (0xdeadbeef);
2698         if (!EnumDisplaySettings(NULL, num++, &devmode)) {
2699             DWORD le = GetLastError();
2700             ok(le == ERROR_NO_MORE_FILES ||
2701                le == 0xdeadbeef, /* XP, 2003 */
2702                "Expected ERROR_NO_MORE_FILES or 0xdeadbeef, got %d\n", le);
2703             break;
2704         }
2705     }
2706 }
2707
2708 START_TEST(sysparams)
2709 {
2710     int argc;
2711     char** argv;
2712     WNDCLASSA wc;
2713     MSG msg;
2714     HANDLE hThread;
2715     DWORD dwThreadId;
2716     HANDLE hInstance, hdll;
2717
2718     hdll = GetModuleHandleA("user32.dll");
2719     pChangeDisplaySettingsExA=(void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
2720
2721     hInstance = GetModuleHandleA( NULL );
2722     hdc = GetDC(0);
2723     dpi = GetDeviceCaps( hdc, LOGPIXELSY);
2724     iswin9x = GetVersion() & 0x80000000;
2725
2726     /* This test requires interactivity, if we don't have it, give up */
2727     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
2728         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
2729
2730     argc = winetest_get_mainargs(&argv);
2731     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
2732     trace("strict=%d\n",strict);
2733
2734     trace("testing GetSystemMetrics with your current desktop settings\n");
2735     test_GetSystemMetrics( );
2736     trace("testing EnumDisplaySettings vs GetDeviceCaps\n");
2737     test_EnumDisplaySettings( );
2738
2739     change_counter = 0;
2740     change_last_param = 0;
2741
2742     wc.lpszClassName = "SysParamsTestClass";
2743     wc.lpfnWndProc = SysParamsTestWndProc;
2744     wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
2745     wc.hInstance = hInstance;
2746     wc.hIcon = LoadIconA( 0, IDI_APPLICATION );
2747     wc.hCursor = LoadCursorA( 0, IDC_ARROW );
2748     wc.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
2749     wc.lpszMenuName = 0;
2750     wc.cbClsExtra = 0;
2751     wc.cbWndExtra = 0;
2752     RegisterClassA( &wc );
2753
2754     ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
2755                                WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
2756
2757     hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
2758     assert( hThread );
2759     CloseHandle( hThread );
2760
2761     while( GetMessageA( &msg, 0, 0, 0 )) {
2762         TranslateMessage( &msg );
2763         DispatchMessageA( &msg );
2764     }
2765     ReleaseDC( 0, hdc);
2766
2767 }