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