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