janitorial: Remove remaining NULL checks before free() (found by Smatch).
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #undef _WIN32_WINNT
26 #define _WIN32_WINNT 0x0500 /* For SPI_GETMOUSEHOVERWIDTH and more */
27
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winreg.h"
33 #include "winuser.h"
34 #include "winnls.h"
35
36 #ifndef SPI_GETDESKWALLPAPER
37 # define SPI_GETDESKWALLPAPER 0x0073
38 #endif
39
40 static int strict;
41 static int dpi;
42 static int iswin9x;
43 static HDC hdc;
44
45 #define eq(received, expected, label, type) \
46         ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
47
48
49 #define SPI_SETBEEP_REGKEY                      "Control Panel\\Sound"
50 #define SPI_SETBEEP_VALNAME                     "Beep"
51 #define SPI_SETMOUSE_REGKEY                     "Control Panel\\Mouse"
52 #define SPI_SETMOUSE_VALNAME1                   "MouseThreshold1"
53 #define SPI_SETMOUSE_VALNAME2                   "MouseThreshold2"
54 #define SPI_SETMOUSE_VALNAME3                   "MouseSpeed"
55 #define SPI_SETBORDER_REGKEY                    "Control Panel\\Desktop\\WindowMetrics"
56 #define SPI_SETBORDER_REGKEY2                   "Control Panel\\Desktop"
57 #define SPI_SETBORDER_VALNAME                   "BorderWidth"
58 #define SPI_METRIC_REGKEY                       "Control Panel\\Desktop\\WindowMetrics"
59 #define SPI_SCROLLWIDTH_VALNAME                 "ScrollWidth"
60 #define SPI_SCROLLHEIGHT_VALNAME                "ScrollHeight"
61 #define SPI_CAPTIONWIDTH_VALNAME                "CaptionWidth"
62 #define SPI_CAPTIONHEIGHT_VALNAME               "CaptionHeight"
63 #define SPI_CAPTIONFONT_VALNAME                 "CaptionFont"
64 #define SPI_SMCAPTIONWIDTH_VALNAME              "SmCaptionWidth"
65 #define SPI_SMCAPTIONHEIGHT_VALNAME             "SmCaptionHeight"
66 #define SPI_SMCAPTIONFONT_VALNAME               "SmCaptionFont"
67 #define SPI_MENUWIDTH_VALNAME                   "MenuWidth"
68 #define SPI_MENUHEIGHT_VALNAME                  "MenuHeight"
69 #define SPI_MENUFONT_VALNAME                    "MenuFont"
70 #define SPI_STATUSFONT_VALNAME                  "StatusFont"
71 #define SPI_MESSAGEFONT_VALNAME                 "MessageFont"
72
73 #define SPI_SETKEYBOARDSPEED_REGKEY             "Control Panel\\Keyboard"
74 #define SPI_SETKEYBOARDSPEED_VALNAME            "KeyboardSpeed"
75 #define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop\\WindowMetrics"
76 #define SPI_ICONHORIZONTALSPACING_REGKEY2       "Control Panel\\Desktop"
77 #define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
78 #define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop\\WindowMetrics"
79 #define SPI_ICONVERTICALSPACING_REGKEY2         "Control Panel\\Desktop"
80 #define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
81 #define SPI_MINIMIZEDMETRICS_REGKEY             "Control Panel\\Desktop\\WindowMetrics"
82 #define SPI_MINWIDTH_VALNAME                    "MinWidth"
83 #define SPI_MINHORZGAP_VALNAME                  "MinHorzGap"
84 #define SPI_MINVERTGAP_VALNAME                  "MinVertGap"
85 #define SPI_MINARRANGE_VALNAME                  "MinArrange"
86 #define SPI_SETSCREENSAVETIMEOUT_REGKEY         "Control Panel\\Desktop"
87 #define SPI_SETSCREENSAVETIMEOUT_VALNAME        "ScreenSaveTimeOut"
88 #define SPI_SETSCREENSAVEACTIVE_REGKEY          "Control Panel\\Desktop"
89 #define SPI_SETSCREENSAVEACTIVE_VALNAME         "ScreenSaveActive"
90 #define SPI_SETGRIDGRANULARITY_REGKEY           "Control Panel\\Desktop"
91 #define SPI_SETGRIDGRANULARITY_VALNAME          "GridGranularity"
92 #define SPI_SETKEYBOARDDELAY_REGKEY             "Control Panel\\Keyboard"
93 #define SPI_SETKEYBOARDDELAY_VALNAME            "KeyboardDelay"
94 #define SPI_SETICONTITLEWRAP_REGKEY1            "Control Panel\\Desktop\\WindowMetrics"
95 #define SPI_SETICONTITLEWRAP_REGKEY2            "Control Panel\\Desktop"
96 #define SPI_SETICONTITLEWRAP_VALNAME            "IconTitleWrap"
97 #define SPI_SETMENUDROPALIGNMENT_REGKEY1        "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
98 #define SPI_SETMENUDROPALIGNMENT_REGKEY2        "Control Panel\\Desktop"
99 #define SPI_SETMENUDROPALIGNMENT_VALNAME        "MenuDropAlignment"
100 #define SPI_SETDOUBLECLKWIDTH_REGKEY1           "Control Panel\\Mouse"
101 #define SPI_SETDOUBLECLKWIDTH_REGKEY2           "Control Panel\\Desktop"
102 #define SPI_SETDOUBLECLKWIDTH_VALNAME           "DoubleClickWidth"
103 #define SPI_SETDOUBLECLKHEIGHT_REGKEY1          "Control Panel\\Mouse"
104 #define SPI_SETDOUBLECLKHEIGHT_REGKEY2          "Control Panel\\Desktop"
105 #define SPI_SETDOUBLECLKHEIGHT_VALNAME          "DoubleClickHeight"
106 #define SPI_SETDOUBLECLICKTIME_REGKEY           "Control Panel\\Mouse"
107 #define SPI_SETDOUBLECLICKTIME_VALNAME          "DoubleClickSpeed"
108 #define SPI_SETMOUSEBUTTONSWAP_REGKEY           "Control Panel\\Mouse"
109 #define SPI_SETMOUSEBUTTONSWAP_VALNAME          "SwapMouseButtons"
110 #define SPI_SETWORKAREA_REGKEY                  "Control Panel\\Desktop"
111 #define SPI_SETWORKAREA_VALNAME                 "WINE_WorkArea"
112 #define SPI_SETSHOWSOUNDS_REGKEY                "Control Panel\\Accessibility\\ShowSounds"
113 #define SPI_SETSHOWSOUNDS_VALNAME               "On"
114 #define SPI_SETKEYBOARDPREF_REGKEY              "Control Panel\\Accessibility\\Keyboard Preference"
115 #define SPI_SETKEYBOARDPREF_VALNAME             "On"
116 #define SPI_SETKEYBOARDPREF_REGKEY_LEGACY       "Control Panel\\Accessibility"
117 #define SPI_SETKEYBOARDPREF_VALNAME_LEGACY      "Keyboard Preference"
118 #define SPI_SETSCREENREADER_REGKEY              "Control Panel\\Accessibility\\Blind Access"
119 #define SPI_SETSCREENREADER_VALNAME             "On"
120 #define SPI_SETSCREENREADER_REGKEY_LEGACY       "Control Panel\\Accessibility"
121 #define SPI_SETSCREENREADER_VALNAME_LEGACY      "Blind Access"
122 #define SPI_SETFONTSMOOTHING_REGKEY             "Control Panel\\Desktop"
123 #define SPI_SETFONTSMOOTHING_VALNAME            "FontSmoothing"
124 #define SPI_SETLOWPOWERACTIVE_REGKEY            "Control Panel\\Desktop"
125 #define SPI_SETLOWPOWERACTIVE_VALNAME           "LowPowerActive"
126 #define SPI_SETPOWEROFFACTIVE_REGKEY            "Control Panel\\Desktop"
127 #define SPI_SETPOWEROFFACTIVE_VALNAME           "PowerOffActive"
128 #define SPI_SETDRAGFULLWINDOWS_REGKEY           "Control Panel\\Desktop"
129 #define SPI_SETDRAGFULLWINDOWS_VALNAME          "DragFullWindows"
130 #define SPI_SETMOUSEHOVERWIDTH_REGKEY           "Control Panel\\Mouse"
131 #define SPI_SETMOUSEHOVERWIDTH_VALNAME          "MouseHoverWidth"
132 #define SPI_SETMOUSEHOVERHEIGHT_REGKEY          "Control Panel\\Mouse"
133 #define SPI_SETMOUSEHOVERHEIGHT_VALNAME         "MouseHoverHeight"
134 #define SPI_SETMOUSEHOVERTIME_REGKEY            "Control Panel\\Mouse"
135 #define SPI_SETMOUSEHOVERTIME_VALNAME           "MouseHoverTime"
136 #define SPI_SETMOUSESCROLLLINES_REGKEY          "Control Panel\\Desktop"
137 #define SPI_SETMOUSESCROLLLINES_VALNAME         "WheelScrollLines"
138 #define SPI_SETMENUSHOWDELAY_REGKEY             "Control Panel\\Desktop"
139 #define SPI_SETMENUSHOWDELAY_VALNAME            "MenuShowDelay"
140 #define SPI_SETDESKWALLPAPER_REGKEY             "Control Panel\\Desktop"
141 #define SPI_SETDESKWALLPAPER_VALNAME            "Wallpaper"
142
143 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
144 #define WINE_CURRENT_USER_REGKEY     "Wine"
145
146 static HWND ghTestWnd;
147
148 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam );
149 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
150                                               LPARAM lParam );
151 static int change_counter;
152 static int change_last_param;
153
154 static LRESULT CALLBACK SysParamsTestWndProc( HWND hWnd, UINT msg, WPARAM wParam,
155                                               LPARAM lParam )
156 {
157     switch (msg) {
158
159     case WM_SETTINGCHANGE:
160         if (change_counter>0) { 
161             /* ignore these messages caused by resizing of toolbars */
162             if( wParam == SPI_SETWORKAREA) break;
163             if( change_last_param == SPI_SETWORKAREA) {
164                 change_last_param = wParam;
165                 break;
166             }
167             ok(0,"too many changes counter=%d last change=%d\n",
168                change_counter,change_last_param);
169         }
170         change_counter++;
171         change_last_param = wParam;
172         break;
173
174     case WM_DESTROY:
175         PostQuitMessage( 0 );
176         break;
177
178     default:
179         return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
180     }
181
182     return 0;
183 }
184
185 /*
186 Performs testing for system parameters messages
187 params:
188  - system parameter id
189  - supposed value of the registry key
190 */
191 static void test_change_message( int action, int optional )
192 {
193     if (change_counter==0 && optional==1)
194         return;
195     ok( 1 == change_counter,
196         "Missed a message: change_counter=%d\n", change_counter );
197     change_counter = 0;
198     ok( action == change_last_param,
199         "Wrong action got %d expected %d\n", change_last_param, action );
200     change_last_param = 0;
201 }
202
203 static BOOL test_error_msg ( int rc, const char *name )
204 {
205     DWORD last_error = GetLastError();
206
207     if (rc==0)
208     {
209         if (last_error==0xdeadbeef || last_error==ERROR_INVALID_SPI_VALUE)
210         {
211             trace("%s not supported on this platform. Skipping test\n", name);
212         }
213         else if (last_error==ERROR_ACCESS_DENIED)
214         {
215             trace("%s does not have privileges to run. Skipping test\n", name);
216         }
217         else
218         {
219             trace("%s failed for reason: %d. Indicating test failure and skipping remainder of test\n",name,last_error);
220             ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
221         }
222         return FALSE;
223     }
224     else
225     {
226         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,last_error);
227         return TRUE;
228     }
229 }
230
231 /*
232  * Tests the HKEY_CURRENT_USER subkey value.
233  * The value should contain string value.
234  *
235  * Params:
236  * lpsSubKey - subkey name
237  * lpsRegName - registry entry name
238  * lpsTestValue - value to test
239  */
240 static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName1, LPCSTR valName2, LPCSTR testValue )
241 {
242     CHAR  value[MAX_PATH];
243     DWORD valueLen;
244     DWORD type;
245     HKEY hKey;
246     LONG rc;
247     int found=0;
248
249     *value='\0';
250     valueLen=sizeof(value);
251     RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
252     rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
253     RegCloseKey( hKey );
254     if (rc==ERROR_SUCCESS)
255     {
256         ok( !strcmp( testValue, value ),
257             "Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
258             subKey1, valName1, testValue, value );
259         found++;
260     }
261     else if (strict)
262     {
263         ok(0,"Missing registry entry: subKey=%s, valName=%s\n",
264            subKey1, valName1);
265     }
266     if (valName2)
267     {
268         *value='\0';
269         valueLen=sizeof(value);
270         RegOpenKeyA( HKEY_CURRENT_USER, subKey1, &hKey );
271         rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
272         RegCloseKey( hKey );
273         if (rc==ERROR_SUCCESS)
274         {
275             ok( !strcmp( testValue, value ),
276                 "Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
277                 subKey1, valName2, testValue, value );
278             found++;
279         }
280         else if (strict)
281         {
282             ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
283                 subKey1, valName2 );
284         }
285     }
286     if (subKey2 && !strict)
287     {
288         *value='\0';
289         valueLen=sizeof(value);
290         RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
291         rc=RegQueryValueExA( hKey, valName1, NULL, &type, (LPBYTE)value, &valueLen );
292         RegCloseKey( hKey );
293         if (rc==ERROR_SUCCESS)
294         {
295             ok( !strcmp( testValue, value ),
296                 "Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
297                 subKey2, valName1, testValue, value );
298             found++;
299         }
300         else if (strict)
301         {
302             ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
303                 subKey2, valName1 );
304         }
305         if (valName2)
306         {
307             *value='\0';
308             valueLen=sizeof(value);
309             RegOpenKeyA( HKEY_CURRENT_USER, subKey2, &hKey );
310             rc=RegQueryValueExA( hKey, valName2, NULL, &type, (LPBYTE)value, &valueLen );
311             RegCloseKey( hKey );
312             if (rc==ERROR_SUCCESS)
313             {
314                 ok( !strcmp( testValue, value ),
315                     "Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
316                     subKey2, valName2, testValue, value );
317                 found++;
318             }
319             else if (strict)
320             {
321                 ok( 0,"Missing registry entry: subKey=%s, valName=%s\n",
322                     subKey2, valName2 );
323             }
324          }
325     }
326     ok(found,"Missing registry values: %s or %s in keys: %s or %s\n",
327        valName1, (valName2?valName2:"<n/a>"), subKey1, (subKey2?subKey2:"<n/a>") );
328 }
329
330 #define test_reg_key( subKey, valName, testValue ) \
331     _test_reg_key( subKey, NULL, valName, NULL, testValue )
332 #define test_reg_key_ex( subKey1, subKey2, valName, testValue ) \
333     _test_reg_key( subKey1, subKey2, valName, NULL, testValue )
334 #define test_reg_key_ex2( subKey1, subKey2, valName1, valName2, testValue ) \
335     _test_reg_key( subKey1, subKey2, valName1, valName2, testValue )
336
337 /* get a metric from the registry. If the value is negative
338  * it is assumed to be in twips and converted to pixels */
339 static UINT metricfromreg( const char *keyname, const char *valname, int dpi)
340 {
341     HKEY hkey;
342     char buf[64];
343     DWORD ret;
344     DWORD size, type;
345     int value;
346
347     RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
348     size = sizeof(buf);
349     ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)buf, &size );
350     RegCloseKey( hkey );
351     if( ret != ERROR_SUCCESS) return -1;
352     value = atoi( buf);
353     if( value < 0)
354         value = ( -value * dpi + 720) / 1440;
355     return value;
356 }
357
358 typedef struct
359 {
360     INT16  lfHeight;
361     INT16  lfWidth;
362     INT16  lfEscapement;
363     INT16  lfOrientation;
364     INT16  lfWeight;
365     BYTE   lfItalic;
366     BYTE   lfUnderline;
367     BYTE   lfStrikeOut;
368     BYTE   lfCharSet;
369     BYTE   lfOutPrecision;
370     BYTE   lfClipPrecision;
371     BYTE   lfQuality;
372     BYTE   lfPitchAndFamily;
373     CHAR   lfFaceName[LF_FACESIZE];
374 } LOGFONT16, *LPLOGFONT16;
375
376 /* get logfont from the registry */
377 static int lffromreg( const char *keyname, const char *valname, LOGFONTA *plf)
378 {
379     HKEY hkey;
380     LOGFONTW lfw;
381     DWORD ret, size, type;
382
383     RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey ); 
384     size = sizeof( lfw);
385     ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)&lfw, &size );
386     RegCloseKey( hkey );
387     ok( ret == ERROR_SUCCESS, "Key \"%s\" value \"%s\" not found\n", keyname, valname);
388     if( ret != ERROR_SUCCESS) 
389         return FALSE;
390     if( size <= sizeof( LOGFONT16)) {
391         LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
392         plf->lfHeight = plf16->lfHeight;
393         plf->lfWidth = plf16->lfWidth;
394         plf->lfEscapement = plf16->lfEscapement;
395         plf->lfOrientation = plf16->lfOrientation;
396         plf->lfWeight = plf16->lfWeight;
397         plf->lfItalic = plf16->lfItalic;
398         plf->lfUnderline = plf16->lfUnderline;
399         plf->lfStrikeOut = plf16->lfStrikeOut;
400         plf->lfCharSet = plf16->lfCharSet;
401         plf->lfOutPrecision = plf16->lfOutPrecision;
402         plf->lfClipPrecision = plf16->lfClipPrecision;
403         plf->lfQuality = plf16->lfQuality;
404         plf->lfPitchAndFamily = plf16->lfPitchAndFamily;
405         memcpy( plf->lfFaceName, plf16->lfFaceName, LF_FACESIZE );
406     } else if( size <= sizeof( LOGFONTA)) {
407         plf = (LOGFONTA*) &lfw;
408     } else {
409         plf->lfHeight = lfw.lfHeight;
410         plf->lfWidth = lfw.lfWidth;
411         plf->lfEscapement = lfw.lfEscapement;
412         plf->lfOrientation = lfw.lfOrientation;
413         plf->lfWeight = lfw.lfWeight;
414         plf->lfItalic = lfw.lfItalic;
415         plf->lfUnderline = lfw.lfUnderline;
416         plf->lfStrikeOut = lfw.lfStrikeOut;
417         plf->lfCharSet = lfw.lfCharSet;
418         plf->lfOutPrecision = lfw.lfOutPrecision;
419         plf->lfClipPrecision = lfw.lfClipPrecision;
420         plf->lfQuality = lfw.lfQuality;
421         plf->lfPitchAndFamily = lfw.lfPitchAndFamily;
422         WideCharToMultiByte( CP_ACP, 0, lfw.lfFaceName, -1, plf->lfFaceName,
423             LF_FACESIZE, NULL, NULL);
424
425     }
426     return TRUE;
427 }
428
429 static void test_SPI_SETBEEP( void )                   /*      2 */
430 {
431     BOOL rc;
432     BOOL old_b;
433     BOOL b;
434     BOOL curr_val;
435
436     trace("testing SPI_{GET,SET}BEEP\n");
437     SetLastError(0xdeadbeef);
438     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &old_b, 0 );
439     if (!test_error_msg(rc,"SPI_{GET,SET}BEEP"))
440         return;
441
442     curr_val = TRUE;
443     rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
444     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
445     test_change_message( SPI_SETBEEP, 0 );
446     test_reg_key( SPI_SETBEEP_REGKEY,
447                   SPI_SETBEEP_VALNAME,
448                   curr_val ? "Yes" : "No" );
449     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
450     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
451     eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
452     rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
453     if (rc!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED)
454     {
455         ok(rc!=0,"SystemParametersInfoW: rc=%d err=%d\n",rc,GetLastError());
456         eq( b, curr_val, "SystemParametersInfoW", "%d" );
457     }
458
459     /* is a message sent for the second change? */
460     rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
461     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
462     test_change_message( SPI_SETBEEP, 0 );
463
464     curr_val = FALSE;
465     rc=SystemParametersInfoW( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
466     if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
467         rc=SystemParametersInfoA( SPI_SETBEEP, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
468     ok(rc!=0,"SystemParametersInfo: rc=%d err=%d\n",rc,GetLastError());
469     test_change_message( SPI_SETBEEP, 0 );
470     test_reg_key( SPI_SETBEEP_REGKEY,
471                   SPI_SETBEEP_VALNAME,
472                   curr_val ? "Yes" : "No" );
473     rc=SystemParametersInfoA( SPI_GETBEEP, 0, &b, 0 );
474     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
475     eq( b, curr_val, "SPI_{GET,SET}BEEP", "%d" );
476     rc=SystemParametersInfoW( SPI_GETBEEP, 0, &b, 0 );
477     if (rc!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED)
478     {
479         ok(rc!=0,"SystemParametersInfoW: rc=%d err=%d\n",rc,GetLastError());
480         eq( b, curr_val, "SystemParametersInfoW", "%d" );
481     }
482     ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled\n" );
483
484     rc=SystemParametersInfoA( SPI_SETBEEP, old_b, 0, SPIF_UPDATEINIFILE );
485     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
486 }
487
488 static const char *setmouse_valuenames[3] = {
489     SPI_SETMOUSE_VALNAME1,
490     SPI_SETMOUSE_VALNAME2,
491     SPI_SETMOUSE_VALNAME3
492 };
493
494 /*
495  * Runs check for one setting of spi_setmouse.
496  */
497 static void run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *proj_change,
498                                    int nchange )
499 {
500     BOOL rc;
501     INT mi[3];
502     static int aw_turn = 0;
503     static BOOL w_implemented = 1;
504
505     char buf[20];
506     int i;
507
508     aw_turn++;
509     rc=0;
510     if ((aw_turn % 2!=0) && (w_implemented))
511     {
512         /* call unicode on odd (non even) calls */ 
513         SetLastError(0xdeadbeef);
514         rc=SystemParametersInfoW( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
515         if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
516         {
517             w_implemented = 0;
518             trace("SystemParametersInfoW not supported on this platform\n");
519         }
520     }
521
522     if ((aw_turn % 2==0) || (!w_implemented))
523     {
524         /* call ascii version on even calls or if unicode is not available */
525         rc=SystemParametersInfoA( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
526     }
527
528     ok(rc!=0,"SystemParametersInfo: rc=%d err=%d\n",rc,GetLastError());
529     test_change_message( SPI_SETMOUSE, 0 );
530     for (i = 0; i < 3; i++)
531     {
532         sprintf( buf, "%d", curr_val[i] );
533         test_reg_key( SPI_SETMOUSE_REGKEY, setmouse_valuenames[i], buf );
534     }
535
536     rc=SystemParametersInfoA( SPI_GETMOUSE, 0, mi, 0 );
537     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
538     for (i = 0; i < 3; i++)
539     {
540         ok(mi[i] == curr_val[i],
541            "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
542     }
543
544     if (w_implemented)
545     { 
546         rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
547         ok(rc!=0,"SystemParametersInfoW: rc=%d err=%d\n",rc,GetLastError());
548         for (i = 0; i < 3; i++)
549         {
550             ok(mi[i] == curr_val[i],
551                "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
552         }
553     }
554
555 #if 0  /* FIXME: this always fails for me  - AJ */
556     for (i = 0; i < nchange; i++)
557     {
558         POINT mv;
559         mouse_event( MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
560         mouse_event( MOUSEEVENTF_MOVE, req_change[i].x, req_change[i].y, 0, 0 );
561         GetCursorPos( &mv );
562         ok( proj_change[i].x == mv.x, "Projected dx and real dx comparison. May fail under high load.\n" );
563         ok( proj_change[i].y == mv.y, "Projected dy equals real dy. May fail under high load.\n" );
564     }
565 #endif
566 }
567
568 static void test_SPI_SETMOUSE( void )                  /*      4 */
569 {
570     BOOL rc;
571     INT old_mi[3];
572
573     /* win nt default values - 6, 10, 1 */
574     INT curr_val[3] = {6, 10, 1};
575
576     /* requested and projected mouse movements */
577     POINT req_change[] =   { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
578     POINT proj_change1[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
579     POINT proj_change2[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {44, 20}, {400, 400} };
580     POINT proj_change3[] = { {6, 6}, {14, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
581     POINT proj_change4[] = { {6, 6}, { 7, 6}, { 8, 6}, {10, 10}, {11, 10}, {100, 100} };
582     POINT proj_change5[] = { {6, 6}, { 7, 6}, {16, 6}, {20, 20}, {22, 20}, {200, 200} };
583     POINT proj_change6[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
584     POINT proj_change7[] = { {6, 6}, {14, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
585     POINT proj_change8[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
586
587     int nchange = sizeof( req_change ) / sizeof( POINT );
588
589     trace("testing SPI_{GET,SET}MOUSE\n");
590     SetLastError(0xdeadbeef);
591     rc=SystemParametersInfoA( SPI_GETMOUSE, 0, old_mi, 0 );
592     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSE"))
593         return;
594
595     run_spi_setmouse_test( curr_val, req_change, proj_change1, nchange );
596
597     /* acceleration change */
598     curr_val[2] = 2;
599     run_spi_setmouse_test( curr_val, req_change, proj_change2, nchange );
600
601     /* acceleration change */
602     curr_val[2] = 3;
603     run_spi_setmouse_test( curr_val, req_change, proj_change3, nchange );
604
605     /* acceleration change */
606     curr_val[2] = 0;
607     run_spi_setmouse_test( curr_val, req_change, proj_change4, nchange );
608
609     /* threshold change */
610     curr_val[2] = 1;
611     curr_val[0] = 7;
612     run_spi_setmouse_test( curr_val, req_change, proj_change5, nchange );
613
614     /* threshold change */
615     curr_val[2] = 2;
616     curr_val[0] = 6;
617     curr_val[1] = 6;
618     run_spi_setmouse_test( curr_val, req_change, proj_change6, nchange );
619
620     /* threshold change */
621     curr_val[1] = 7;
622     run_spi_setmouse_test( curr_val, req_change, proj_change7, nchange );
623
624     /* threshold change */
625     curr_val[1] = 5;
626     run_spi_setmouse_test( curr_val, req_change, proj_change8, nchange );
627
628     rc=SystemParametersInfoA( SPI_SETMOUSE, 0, old_mi, SPIF_UPDATEINIFILE );
629     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
630 }
631
632 static void test_setborder(UINT curr_val, int usesetborder, int dpi)
633 {
634     BOOL rc;
635     UINT border, regval;
636     INT frame;
637     NONCLIENTMETRICSA ncm;
638
639     ncm.cbSize = sizeof( ncm);
640     rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
641     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
642     if( usesetborder) {
643             rc=SystemParametersInfoA( SPI_SETBORDER, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
644         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
645         test_change_message( SPI_SETBORDER, 1 );
646     } else { /* set non client metrics */
647         ncm.iBorderWidth = curr_val;
648         rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
649                 SPIF_SENDCHANGE);
650         ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
651         test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
652     }
653     if( curr_val) { /* skip if 0, some windows versions return 0 others 1 */
654         regval = metricfromreg( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_VALNAME, dpi);
655         if( regval != curr_val)
656             regval = metricfromreg( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, dpi);
657         ok( regval==curr_val, "wrong value in registry %d, expected %d\n", regval, curr_val);
658     }
659     /* minimum border width is 1 */
660     if (curr_val == 0) curr_val = 1;
661     /* should be the same as the non client metrics */
662     rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
663     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
664     eq( (UINT)ncm.iBorderWidth, curr_val, "NonClientMetric.iBorderWidth", "%d");
665     /* and from SPI_GETBORDER */ 
666     rc=SystemParametersInfoA( SPI_GETBORDER, 0, &border, 0 );
667     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
668     eq( border, curr_val, "SPI_{GET,SET}BORDER", "%d");
669     /* test some SystemMetrics */
670     frame = curr_val + GetSystemMetrics( SM_CXDLGFRAME );
671     eq( frame, GetSystemMetrics( SM_CXFRAME ), "SM_CXFRAME", "%d" );
672     eq( frame, GetSystemMetrics( SM_CYFRAME ), "SM_CYFRAME", "%d" );
673     eq( frame, GetSystemMetrics( SM_CXSIZEFRAME ), "SM_CXSIZEFRAME", "%d" );
674     eq( frame, GetSystemMetrics( SM_CYSIZEFRAME ), "SM_CYSIZEFRAME", "%d" );
675 }
676
677 static void test_SPI_SETBORDER( void )                 /*      6 */
678 {
679     BOOL rc;
680     UINT old_border;
681     NONCLIENTMETRICSA ncmsave;
682     INT CaptionWidth;
683
684     ncmsave.cbSize = sizeof( ncmsave);
685     rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncmsave, 0);
686     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
687     /* CaptionWidth from the registry may have different value of iCaptionWidth
688      * from the non client metrics (observed on WinXP).
689      * Fix this so we can safely restore settings with the nonclientmetrics */
690     CaptionWidth = metricfromreg(
691             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
692     ncmsave.iCaptionWidth = CaptionWidth;
693
694     /* These tests hang when XFree86 4.0 for Windows is running (tested on
695      *  WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
696      * running.
697      */
698     if (FindWindowA( NULL, "Cygwin/XFree86" ))
699         return;
700
701     trace("testing SPI_{GET,SET}BORDER\n");
702
703     SetLastError(0xdeadbeef);
704     rc=SystemParametersInfoA( SPI_GETBORDER, 0, &old_border, 0 );
705     if (!test_error_msg(rc,"SPI_{GET,SET}BORDER"))
706         return;
707     /* This will restore sane values if the test hang previous run. */
708     if ( old_border == 7 || old_border == 20 )
709         old_border = 1;
710
711     /* The SPI_SETBORDER seems to be buggy on Win9x/ME (looks like you need to
712      * do it twice to make the intended change). So skip parts of the tests on
713      * those platforms */
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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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=%d\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 %d, %d\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=%d\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=%d\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=%d\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=%d\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=%d\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. Note that it is perfectly valid for some fields to
1470      * not be set.
1471      */
1472     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1473     ok( regval == -1 || regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
1474         regval, lpMm_orig.iWidth);
1475     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1476     ok( regval == -1 || regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
1477         regval, lpMm_orig.iHorzGap);
1478     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1479     ok( regval == -1 || regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
1480         regval, lpMm_orig.iVertGap);
1481     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1482     ok( regval == -1 || regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
1483         regval, lpMm_orig.iArrange);
1484     /* set some new values */
1485     lpMm_cur.iWidth = 180;
1486     lpMm_cur.iHorzGap = 1;
1487     lpMm_cur.iVertGap = 1;
1488     lpMm_cur.iArrange = 5;
1489     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1490         &lpMm_cur, SPIF_UPDATEINIFILE );
1491     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1492     /* read them back */
1493     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1494     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1495     /* and compare */
1496     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
1497     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
1498     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
1499     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
1500     /* test registry */
1501     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1502     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1503         regval, lpMm_new.iWidth);
1504     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1505     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1506         regval, lpMm_new.iHorzGap);
1507     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1508     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1509         regval, lpMm_new.iVertGap);
1510     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1511     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1512         regval, lpMm_new.iArrange);
1513     /* test some system metrics */
1514     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1515         lpMm_new.iWidth,   "iWidth",   "%d" );
1516     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1517         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1518     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1519         lpMm_new.iVertGap, "iVertGap", "%d" );
1520     eq( GetSystemMetrics( SM_ARRANGE ),
1521         lpMm_new.iArrange, "iArrange", "%d" );
1522     /* now some realy invalid settings */
1523     lpMm_cur.iWidth = -1;
1524     lpMm_cur.iHorzGap = -1;
1525     lpMm_cur.iVertGap = -1;
1526     lpMm_cur.iArrange = - 1;
1527     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1528         &lpMm_cur, SPIF_UPDATEINIFILE );
1529     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1530     /* read back */
1531     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1532     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1533     /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
1534     eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
1535     eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
1536     eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
1537     eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
1538     /* test registry */
1539 #if 0 /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
1540     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
1541     ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
1542         regval, lpMm_new.iWidth);
1543     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
1544     ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
1545         regval, lpMm_new.iHorzGap);
1546     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
1547     ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
1548         regval, lpMm_new.iVertGap);
1549     regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
1550     ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
1551         regval, lpMm_new.iArrange);
1552 #endif
1553     /* test some system metrics */
1554     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
1555         lpMm_new.iWidth,   "iWidth",   "%d" );
1556     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
1557         lpMm_new.iHorzGap, "iHorzGap", "%d" );
1558     eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
1559         lpMm_new.iVertGap, "iVertGap", "%d" );
1560     eq( GetSystemMetrics( SM_ARRANGE ),
1561         lpMm_new.iArrange, "iArrange", "%d" );
1562     /* restore */
1563     rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
1564         &lpMm_orig, SPIF_UPDATEINIFILE );
1565     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1566     /* check that */
1567     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
1568     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1569     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
1570     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
1571     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
1572     eq( lpMm_new.iArrange, lpMm_orig.iArrange, "iArrange", "%d" );
1573 }
1574
1575 static void test_SPI_SETICONMETRICS( void )               /*     46 */
1576 {
1577     BOOL rc, wrap;
1578     INT spacing;
1579     ICONMETRICSA im_orig;
1580     ICONMETRICSA im_new;
1581     ICONMETRICSA im_cur;
1582     INT regval;
1583         
1584     im_orig.cbSize = sizeof(ICONMETRICSA);
1585     im_new.cbSize = sizeof(ICONMETRICSA);
1586     im_cur.cbSize = sizeof(ICONMETRICSA);
1587
1588     trace("testing SPI_{GET,SET}ICONMETRICS\n");
1589     SetLastError(0xdeadbeef);
1590     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
1591     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
1592         return;
1593    /* check some registry values */ 
1594     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1595     ok( regval==im_orig.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
1596     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1597     ok( regval==im_orig.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
1598     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1599     if( regval != im_orig.iTitleWrap)
1600         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1601     ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
1602
1603     /* change everything without creating something invalid ( Win9x would ignore
1604      * an invalid font for instance) */
1605     im_cur = im_orig;
1606     im_cur.iHorzSpacing += 10;
1607     im_cur.iVertSpacing += 6;
1608     im_cur.iTitleWrap = !im_cur.iTitleWrap;
1609     im_cur.lfFont.lfHeight += 1;
1610     im_cur.lfFont.lfWidth += 2;
1611     im_cur.lfFont.lfEscapement = 1;
1612     im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
1613     im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
1614     im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
1615     im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
1616     im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
1617     im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
1618                                 OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
1619     im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
1620     im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
1621     im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ? 
1622                                 DRAFT_QUALITY : DEFAULT_QUALITY;
1623     if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
1624         strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
1625     else
1626         strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
1627
1628     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
1629     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1630
1631     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1632     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1633     /* test GET <-> SETICONMETRICS */ 
1634     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
1635     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
1636     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
1637     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%d" );
1638     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%d" );
1639     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%d" );
1640     eq( im_new.lfFont.lfWeight,         im_cur.lfFont.lfWeight,         "lfWeight",         "%d" );
1641     eq( im_new.lfFont.lfItalic,         im_cur.lfFont.lfItalic,         "lfItalic",         "%d" );
1642     eq( im_new.lfFont.lfStrikeOut,      im_cur.lfFont.lfStrikeOut,      "lfStrikeOut",      "%d" );
1643     eq( im_new.lfFont.lfUnderline,      im_cur.lfFont.lfUnderline,      "lfUnderline",      "%d" );
1644     eq( im_new.lfFont.lfCharSet,        im_cur.lfFont.lfCharSet,        "lfCharSet",        "%d" );
1645     eq( im_new.lfFont.lfOutPrecision,   im_cur.lfFont.lfOutPrecision,   "lfOutPrecision",   "%d" );
1646     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
1647     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
1648     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
1649     ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
1650         "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
1651         im_cur.lfFont.lfFaceName);
1652     /* test some system metrics */
1653     eq( GetSystemMetrics( SM_CXICONSPACING ),
1654         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
1655     eq( GetSystemMetrics( SM_CYICONSPACING ),
1656         im_new.iVertSpacing, "iVertSpacing", "%d" );
1657    /* check some registry values */ 
1658     regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
1659     ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
1660     regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
1661     ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
1662     regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1663     if( regval != im_cur.iTitleWrap)
1664         regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
1665     ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
1666     /* test some values from other SPI_GETxxx calls */
1667     rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
1668     ok( rc && spacing == im_cur.iHorzSpacing,
1669         "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
1670         spacing, im_cur.iHorzSpacing);
1671     rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
1672     ok( rc && spacing == im_cur.iVertSpacing,
1673         "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
1674         spacing, im_cur.iVertSpacing);
1675     rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
1676     ok( rc && wrap == im_cur.iTitleWrap,
1677         "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
1678         wrap, im_cur.iTitleWrap);
1679     /* restore old values */
1680     rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
1681     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1682     
1683     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
1684     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1685     
1686     eq( im_new.iHorzSpacing, im_orig.iHorzSpacing, "iHorzSpacing", "%d" );
1687     eq( im_new.iVertSpacing, im_orig.iVertSpacing, "iVertSpacing", "%d" );
1688     eq( im_new.iTitleWrap,   im_orig.iTitleWrap,   "iTitleWrap",   "%d" );
1689 }
1690
1691 static void test_SPI_SETWORKAREA( void )               /*     47 */
1692 {
1693     BOOL rc;
1694     RECT old_area;
1695     RECT area;
1696     RECT curr_val;
1697
1698     trace("testing SPI_{GET,SET}WORKAREA\n");
1699     SetLastError(0xdeadbeef);
1700     rc=SystemParametersInfoA(SPI_GETWORKAREA, 0, &old_area, 0);
1701     if (!test_error_msg(rc,"SPI_{GET,SET}WORKAREA"))
1702         return;
1703
1704     /* Modify the work area only minimally as this causes the icons that
1705      * fall outside it to be moved around thus requiring the user to
1706      * reposition them manually one by one.
1707      * Changing the work area by just one pixel should make this occurrence
1708      * reasonably unlikely.
1709      */
1710     curr_val.left = old_area.left;
1711     curr_val.top = old_area.top;
1712     curr_val.right = old_area.right-1;
1713     curr_val.bottom = old_area.bottom-1;
1714     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &curr_val,
1715                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1716     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1717     test_change_message( SPI_SETWORKAREA, 0 );
1718     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1719     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1720     eq( area.left,   curr_val.left,   "left",   "%d" );
1721     eq( area.top,    curr_val.top,    "top",    "%d" );
1722     eq( area.right,  curr_val.right,  "right",  "%d" );
1723     eq( area.bottom, curr_val.bottom, "bottom", "%d" );
1724
1725     rc=SystemParametersInfoA( SPI_SETWORKAREA, 0, &old_area,
1726                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1727     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1728     test_change_message( SPI_SETWORKAREA, 0 );
1729     rc=SystemParametersInfoA( SPI_GETWORKAREA, 0, &area, 0 );
1730     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
1731     eq( area.left,   old_area.left,   "left",   "%d" );
1732     eq( area.top,    old_area.top,    "top",    "%d" );
1733     eq( area.right,  old_area.right,  "right",  "%d" );
1734     eq( area.bottom, old_area.bottom, "bottom", "%d" );
1735 }
1736
1737 static void test_SPI_SETSHOWSOUNDS( void )             /*     57 */
1738 {
1739     BOOL rc;
1740     BOOL old_b;
1741     const UINT vals[]={TRUE,FALSE};
1742     unsigned int i;
1743
1744     trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
1745     SetLastError(0xdeadbeef);
1746     rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
1747     /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
1748     if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
1749         return;
1750
1751     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1752     {
1753         UINT v;
1754
1755         rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0,
1756                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1757         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1758         test_change_message( SPI_SETSHOWSOUNDS, 0 );
1759         test_reg_key( SPI_SETSHOWSOUNDS_REGKEY,
1760                       SPI_SETSHOWSOUNDS_VALNAME,
1761                       vals[i] ? "1" : "0" );
1762
1763         rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &v, 0 );
1764         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1765         eq( v, vals[i], "SPI_GETSHOWSOUNDS", "%d" );
1766         eq( GetSystemMetrics( SM_SHOWSOUNDS ), (int)vals[i],
1767             "SM_SHOWSOUNDS", "%d" );
1768     }
1769
1770     rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, old_b, 0, SPIF_UPDATEINIFILE );
1771     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1772 }
1773
1774 static void test_SPI_SETKEYBOARDPREF( void )           /*     69 */
1775 {
1776     BOOL rc;
1777     BOOL old_b;
1778     const UINT vals[]={TRUE,FALSE};
1779     unsigned int i;
1780
1781     trace("testing SPI_{GET,SET}KEYBOARDPREF\n");
1782     SetLastError(0xdeadbeef);
1783     rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &old_b, 0 );
1784     if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
1785         return;
1786
1787     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1788     {
1789         BOOL v;
1790
1791         rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0,
1792                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1793         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1794         test_change_message( SPI_SETKEYBOARDPREF, 0 );
1795         test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY,
1796                           SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY,
1797                           vals[i] ? "1" : "0" );
1798
1799         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
1800         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1801         eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
1802     }
1803
1804     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
1805     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1806 }
1807
1808 static void test_SPI_SETSCREENREADER( void )           /*     71 */
1809 {
1810     BOOL rc;
1811     BOOL old_b;
1812     const UINT vals[]={TRUE,FALSE};
1813     unsigned int i;
1814
1815     trace("testing SPI_{GET,SET}SCREENREADER\n");
1816     SetLastError(0xdeadbeef);
1817     rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &old_b, 0 );
1818     if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
1819         return;
1820
1821     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1822     {
1823         BOOL v;
1824
1825         rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0,
1826                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1827         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1828         test_change_message( SPI_SETSCREENREADER, 0 );
1829         test_reg_key_ex2( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY,
1830                       SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY,
1831                       vals[i] ? "1" : "0" );
1832
1833         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
1834         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1835         eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
1836     }
1837
1838     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
1839     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1840 }
1841
1842 static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
1843 {
1844     BOOL rc;
1845     BOOL old_b;
1846     const UINT vals[]={0xffffffff,0,1,2};
1847     unsigned int i;
1848
1849     trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
1850     if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */ 
1851     SetLastError(0xdeadbeef);
1852     rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
1853     if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
1854         return;
1855
1856     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1857     {
1858         UINT v;
1859
1860         rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
1861                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1862         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1863         test_change_message( SPI_SETFONTSMOOTHING, 0 );
1864         test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
1865                       SPI_SETFONTSMOOTHING_VALNAME,
1866                       vals[i] ? "2" : "0" );
1867
1868         rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
1869         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1870         eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
1871     }
1872
1873     rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
1874     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1875 }
1876
1877 static void test_SPI_SETLOWPOWERACTIVE( void )         /*     85 */
1878 {
1879     BOOL rc;
1880     BOOL old_b;
1881     const UINT vals[]={TRUE,FALSE};
1882     unsigned int i;
1883
1884     trace("testing SPI_{GET,SET}LOWPOWERACTIVE\n");
1885     SetLastError(0xdeadbeef);
1886     rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &old_b, 0 );
1887     if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
1888         return;
1889
1890     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1891     {
1892         UINT v;
1893
1894         rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0,
1895                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1896         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1897         test_change_message( SPI_SETLOWPOWERACTIVE, 0 );
1898         test_reg_key( SPI_SETLOWPOWERACTIVE_REGKEY,
1899                       SPI_SETLOWPOWERACTIVE_VALNAME,
1900                       vals[i] ? "1" : "0" );
1901
1902         rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
1903         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1904         eq( v, vals[i], "SPI_GETLOWPOWERACTIVE", "%d" );
1905     }
1906
1907     rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1908     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1909 }
1910
1911 static void test_SPI_SETPOWEROFFACTIVE( void )         /*     86 */
1912 {
1913     BOOL rc;
1914     BOOL old_b;
1915     const UINT vals[]={TRUE,FALSE};
1916     unsigned int i;
1917
1918     trace("testing SPI_{GET,SET}POWEROFFACTIVE\n");
1919     SetLastError(0xdeadbeef);
1920     rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &old_b, 0 );
1921     if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
1922         return;
1923
1924     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1925     {
1926         UINT v;
1927
1928         rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0,
1929                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1930         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1931         test_change_message( SPI_SETPOWEROFFACTIVE, 0 );
1932         test_reg_key( SPI_SETPOWEROFFACTIVE_REGKEY,
1933                       SPI_SETPOWEROFFACTIVE_VALNAME,
1934                       vals[i] ? "1" : "0" );
1935
1936         rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
1937         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1938         eq( v, vals[i], "SPI_GETPOWEROFFACTIVE", "%d" );
1939     }
1940
1941     rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE );
1942     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1943 }
1944
1945 static void test_SPI_SETMOUSEHOVERWIDTH( void )      /*     99 */
1946 {
1947     BOOL rc;
1948     UINT old_width;
1949     const UINT vals[]={0,32767};
1950     unsigned int i;
1951
1952     trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
1953     SetLastError(0xdeadbeef);
1954     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
1955     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
1956     * what MSDN states (Verified on Win98SE)
1957     */
1958     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
1959         return;
1960     
1961     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
1962     {
1963         UINT v;
1964         char buf[10];
1965
1966         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, vals[i], 0,
1967                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
1968         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1969         test_change_message( SPI_SETMOUSEHOVERWIDTH, 0 );
1970         sprintf( buf, "%d", vals[i] );
1971         test_reg_key( SPI_SETMOUSEHOVERWIDTH_REGKEY,
1972                       SPI_SETMOUSEHOVERWIDTH_VALNAME, buf );
1973
1974         SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &v, 0 );
1975         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
1976         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERWIDTH", "%d" );
1977     }
1978
1979     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERWIDTH, old_width, 0,
1980                               SPIF_UPDATEINIFILE );
1981     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
1982 }
1983
1984 static void test_SPI_SETMOUSEHOVERHEIGHT( void )      /*     101 */
1985 {
1986     BOOL rc;
1987     UINT old_height;
1988     const UINT vals[]={0,32767};
1989     unsigned int i;
1990
1991     trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
1992     SetLastError(0xdeadbeef);
1993     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
1994     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
1995      * what MSDN states (Verified on Win98SE)
1996      */
1997     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
1998         return;
1999     
2000     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2001     {
2002         UINT v;
2003         char buf[10];
2004
2005         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, vals[i], 0,
2006                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2007         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2008         test_change_message( SPI_SETMOUSEHOVERHEIGHT, 0 );
2009         sprintf( buf, "%d", vals[i] );
2010         test_reg_key( SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2011                       SPI_SETMOUSEHOVERHEIGHT_VALNAME, buf );
2012
2013         SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &v, 0 );
2014         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2015         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERHEIGHT", "%d" );
2016     }
2017
2018     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERHEIGHT, old_height, 0,
2019                               SPIF_UPDATEINIFILE );
2020     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2021 }
2022
2023 static void test_SPI_SETMOUSEHOVERTIME( void )      /*     103 */
2024 {
2025     BOOL rc;
2026     UINT old_time;
2027
2028     /* Windows XP accepts 10 as the minimum hover time. Any value below will be
2029      * defaulted to a value of 10 automatically.
2030      */
2031     const UINT vals[]={10,32767};
2032     unsigned int i;
2033
2034     trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
2035     SetLastError(0xdeadbeef);
2036     rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
2037     /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
2038      * what MSDN states (Verified on Win98SE)
2039      */    
2040     if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
2041         return;
2042     
2043     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2044     {
2045         UINT v;
2046         char buf[10];
2047
2048         rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, vals[i], 0,
2049                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2050         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2051         test_change_message( SPI_SETMOUSEHOVERTIME, 0 );
2052         sprintf( buf, "%d", vals[i] );
2053         test_reg_key( SPI_SETMOUSEHOVERTIME_REGKEY,
2054                       SPI_SETMOUSEHOVERTIME_VALNAME, buf );
2055
2056         SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &v, 0 );
2057         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2058         eq( v, vals[i], "SPI_{GET,SET}MOUSEHOVERTIME", "%d" );
2059     }
2060
2061     rc=SystemParametersInfoA( SPI_SETMOUSEHOVERTIME, old_time, 0,
2062                               SPIF_UPDATEINIFILE );
2063     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2064 }
2065
2066 static void test_SPI_SETWHEELSCROLLLINES( void )      /*     105 */
2067 {
2068     BOOL rc;
2069     UINT old_lines;
2070     const UINT vals[]={0,32767};
2071     unsigned int i;
2072
2073     trace("testing SPI_{GET,SET}WHEELSCROLLLINES\n");
2074     SetLastError(0xdeadbeef);
2075     rc=SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &old_lines, 0 );
2076
2077     /* SPI_{GET,SET}WHEELSCROLLLINES not supported on Windows 95 */
2078     if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
2079         return;
2080
2081     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2082     {
2083         UINT v;
2084         char buf[10];
2085
2086         rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, vals[i], 0,
2087                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2088         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2089         test_change_message( SPI_SETWHEELSCROLLLINES, 0 );
2090         sprintf( buf, "%d", vals[i] );
2091         test_reg_key( SPI_SETMOUSESCROLLLINES_REGKEY,
2092                       SPI_SETMOUSESCROLLLINES_VALNAME, buf );
2093
2094         SystemParametersInfoA( SPI_GETWHEELSCROLLLINES, 0, &v, 0 );
2095         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2096         eq( v, vals[i], "SPI_{GET,SET}WHEELSCROLLLINES", "%d" );
2097     }
2098
2099     rc=SystemParametersInfoA( SPI_SETWHEELSCROLLLINES, old_lines, 0,
2100                               SPIF_UPDATEINIFILE );
2101     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2102 }
2103
2104 static void test_SPI_SETMENUSHOWDELAY( void )      /*     107 */
2105 {
2106     BOOL rc;
2107     UINT old_delay;
2108     const UINT vals[]={0,32767};
2109     unsigned int i;
2110
2111     trace("testing SPI_{GET,SET}MENUSHOWDELAY\n");
2112     SetLastError(0xdeadbeef);
2113     rc=SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &old_delay, 0 );
2114
2115     /* SPI_{GET,SET}MENUSHOWDELAY not supported on Windows 95 */
2116     if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
2117         return;
2118
2119     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
2120     {
2121         UINT v;
2122         char buf[10];
2123
2124         rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, vals[i], 0,
2125                                SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
2126         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2127         test_change_message( SPI_SETMENUSHOWDELAY, 0 );
2128         sprintf( buf, "%d", vals[i] );
2129         test_reg_key( SPI_SETMENUSHOWDELAY_REGKEY,
2130                       SPI_SETMENUSHOWDELAY_VALNAME, buf );
2131
2132         SystemParametersInfoA( SPI_GETMENUSHOWDELAY, 0, &v, 0 );
2133         ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError());
2134         eq( v, vals[i], "SPI_{GET,SET}MENUSHOWDELAY", "%d" );
2135     }
2136
2137     rc=SystemParametersInfoA( SPI_SETMENUSHOWDELAY, old_delay, 0,
2138                               SPIF_UPDATEINIFILE );
2139     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2140 }
2141
2142 static void test_SPI_SETWALLPAPER( void )              /*   115 */
2143 {
2144     BOOL rc;
2145     char oldval[260];
2146     char newval[260];
2147
2148     trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
2149     SetLastError(0xdeadbeef);
2150     rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
2151     /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
2152      * unimplemented on NT4
2153      */
2154     if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
2155         return;
2156
2157     strcpy(newval, "");
2158     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, newval, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
2159     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%d\n",rc,GetLastError());
2160     test_change_message(SPI_SETDESKWALLPAPER, 0);
2161
2162     rc=SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, oldval, SPIF_UPDATEINIFILE);
2163     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError());
2164
2165     test_reg_key(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, oldval);
2166 }
2167
2168 /*
2169  * Registry entries for the system parameters.
2170  * Names are created by 'SET' flags names.
2171  * We assume that corresponding 'GET' entries use the same registry keys.
2172  */
2173 static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam )
2174 {
2175     test_SPI_SETBEEP();                         /*      1 */
2176     test_SPI_SETMOUSE();                        /*      4 */
2177     test_SPI_SETBORDER();                       /*      6 */
2178     test_SPI_SETKEYBOARDSPEED();                /*     10 */
2179     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
2180     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
2181     test_SPI_SETSCREENSAVEACTIVE();             /*     17 */
2182     test_SPI_SETGRIDGRANULARITY();              /*     19 */
2183     test_SPI_SETKEYBOARDDELAY();                /*     23 */
2184     test_SPI_ICONVERTICALSPACING();             /*     24 */
2185     test_SPI_SETICONTITLEWRAP();                /*     26 */
2186     test_SPI_SETMENUDROPALIGNMENT();            /*     28 */
2187     test_SPI_SETDOUBLECLKWIDTH();               /*     29 */
2188     test_SPI_SETDOUBLECLKHEIGHT();              /*     30 */
2189     test_SPI_SETDOUBLECLICKTIME();              /*     32 */
2190     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
2191     test_SPI_SETFASTTASKSWITCH();               /*     36 */
2192     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
2193     test_SPI_SETNONCLIENTMETRICS();             /*     42 */
2194     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
2195     test_SPI_SETICONMETRICS();                  /*     46 */
2196     test_SPI_SETWORKAREA();                     /*     47 */
2197     test_SPI_SETSHOWSOUNDS();                   /*     57 */
2198     test_SPI_SETKEYBOARDPREF();                 /*     69 */
2199     test_SPI_SETSCREENREADER();                 /*     71 */
2200     test_SPI_SETFONTSMOOTHING();                /*     75 */
2201     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
2202     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
2203     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
2204     test_SPI_SETMOUSEHOVERHEIGHT();             /*    101 */
2205     test_SPI_SETMOUSEHOVERTIME();               /*    103 */
2206     test_SPI_SETWHEELSCROLLLINES();             /*    105 */
2207     test_SPI_SETMENUSHOWDELAY();                /*    107 */
2208     test_SPI_SETWALLPAPER();                    /*    115 */
2209     SendMessageA( ghTestWnd, WM_DESTROY, 0, 0 );
2210     return 0;
2211 }
2212
2213 /* test calculation of GetSystemMetrics values (mostly) from non client metrics,
2214  * icon metrics and minimized metrics. 
2215  */
2216
2217 /* copied from wine's GdiGetCharDimensions, which is not available on most
2218  * windows versions */
2219 static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
2220 {
2221     SIZE sz;
2222     static const CHAR alphabet[] = {
2223         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2224         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2225         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2226
2227     if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
2228
2229     if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
2230
2231     if (height) *height = sz.cy;
2232     return (sz.cx / 26 + 1) / 2;
2233 }
2234
2235 /* get text metrics and/or "average" char width of the specified logfont
2236  * for the specified dc */
2237 void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
2238 {
2239     HFONT hfont, hfontsav;
2240     TEXTMETRICA tm;
2241     if( !ptm) ptm = &tm;
2242     hfont = CreateFontIndirectA( plf);
2243     if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
2244         ptm->tmHeight = -1;
2245         if( psz) *psz = 10;
2246         if( hfont) DeleteObject( hfont);
2247         return;
2248     }
2249     GetTextMetricsA( hdc, ptm);
2250     if( psz)
2251         if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
2252             *psz = 10;
2253     SelectObject( hdc, hfontsav);
2254     DeleteObject( hfont);
2255 }
2256
2257 static int gsm_error_ctr;
2258 static UINT smcxsmsize = 999999999;
2259
2260 #define ok_gsm( i, e)\
2261 {\
2262     int exp = (e);\
2263     int act = GetSystemMetrics( (i));\
2264     if( exp != act) gsm_error_ctr++;\
2265     ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
2266 }
2267 #define ok_gsm_2( i, e1, e2)\
2268 {\
2269     int exp1 = (e1);\
2270     int exp2 = (e2);\
2271     int act = GetSystemMetrics( (i));\
2272     if( exp1 != act && exp2 != act) gsm_error_ctr++;\
2273     ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
2274 }
2275 #define ok_gsm_3( i, e1, e2, e3)\
2276 {\
2277     int exp1 = (e1);\
2278     int exp2 = (e2);\
2279     int exp3 = (e3);\
2280     int act = GetSystemMetrics( (i));\
2281     if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
2282     ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
2283 }
2284
2285 void test_GetSystemMetrics( void)
2286 {
2287     TEXTMETRICA tmMenuFont;
2288     UINT IconSpacing, IconVerticalSpacing;
2289
2290     HDC hdc = CreateIC( "Display", 0, 0, 0);
2291     UINT avcwCaption;
2292     INT CaptionWidth;
2293     MINIMIZEDMETRICS minim;
2294     NONCLIENTMETRICS ncm;
2295     minim.cbSize = sizeof( minim);
2296     ncm.cbSize = sizeof( ncm);
2297     SystemParametersInfo( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
2298     SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
2299
2300     /* CaptionWidth from the registry may have different value of iCaptionWidth
2301      * from the non client metrics (observed on WinXP) */
2302     CaptionWidth = metricfromreg(
2303             "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
2304     get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
2305     get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
2306     /* FIXME: use icon metric */
2307     if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
2308         IconVerticalSpacing = 0;
2309     if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
2310         IconSpacing = 0;
2311     /* reset error counters */
2312     gsm_error_ctr = 0;
2313
2314     /* the tests: */
2315
2316     /* SM_CXSCREEN, cannot test these two */
2317     /* SM_CYSCREEN */
2318     ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
2319     ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
2320     ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
2321     ok_gsm( SM_CXBORDER, 1);
2322     ok_gsm( SM_CYBORDER, 1);
2323     ok_gsm( SM_CXDLGFRAME, 3);
2324     ok_gsm( SM_CYDLGFRAME, 3);
2325     ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
2326     ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
2327     /* SM_CXICON */
2328     /* SM_CYICON */
2329     /* SM_CXCURSOR */
2330     /* SM_CYCURSOR */
2331     ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
2332     ok_gsm( SM_CXFULLSCREEN,
2333             GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
2334     ok_gsm( SM_CYFULLSCREEN,
2335             GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
2336     /* SM_CYKANJIWINDOW */
2337     /* SM_MOUSEPRESENT */
2338     ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
2339     ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
2340     /* SM_DEBUG */
2341     /* SM_SWAPBUTTON */
2342     /* SM_RESERVED1 */
2343     /* SM_RESERVED2 */
2344     /* SM_RESERVED3 */
2345     /* SM_RESERVED4 */
2346     ok_gsm( SM_CXMIN, 3 * max( CaptionWidth, 8) + GetSystemMetrics( SM_CYSIZE) +
2347             4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
2348     ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
2349             2 * GetSystemMetrics( SM_CYFRAME));
2350     ok_gsm_2( SM_CXSIZE,
2351         ncm.iCaptionWidth,  /* classic/standard windows style */
2352         GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
2353         );
2354     ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
2355     ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
2356     ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
2357     ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
2358     ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
2359     /* SM_CXDOUBLECLK */
2360     /* SM_CYDOUBLECLK */
2361     if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
2362     if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
2363     /* SM_MENUDROPALIGNMENT */
2364     /* SM_PENWINDOWS */
2365     /* SM_DBCSENABLED */
2366     /* SM_CMOUSEBUTTONS */
2367     /* SM_SECURE */
2368     ok_gsm( SM_CXEDGE, 2);
2369     ok_gsm( SM_CYEDGE, 2);
2370     ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + minim.iHorzGap );
2371     ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + minim.iVertGap );
2372     /* SM_CXSMICON */
2373     /* SM_CYSMICON */
2374     ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
2375     ok_gsm_3( SM_CXSMSIZE,
2376         ncm.iSmCaptionWidth, /* classic/standard windows style */
2377         GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
2378         smcxsmsize /* winXP seems to cache this value: setnonclientmetric
2379                       does not change it */
2380         );
2381     ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
2382     ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
2383     ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
2384     /* SM_ARRANGE */
2385     ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
2386     ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
2387     ok_gsm( SM_CXMAXTRACK, GetSystemMetrics( SM_CXSCREEN) +
2388             4 + 2 * GetSystemMetrics( SM_CXFRAME));
2389     ok_gsm( SM_CYMAXTRACK, GetSystemMetrics( SM_CYSCREEN) +
2390             4 + 2 * GetSystemMetrics( SM_CYFRAME));
2391     /* the next two cannot really be tested as they depend on (application)
2392      * toolbars */
2393     /* SM_CXMAXIMIZED */
2394     /* SM_CYMAXIMIZED */
2395     /* SM_NETWORK */
2396     /* */
2397     /* */
2398     /* */
2399     /* SM_CLEANBOOT */
2400     /* SM_CXDRAG */
2401     /* SM_CYDRAG */
2402     /* SM_SHOWSOUNDS */
2403     ok_gsm( SM_CXMENUCHECK,
2404             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2405     ok_gsm( SM_CYMENUCHECK,
2406             ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
2407     /* SM_SLOWMACHINE */
2408     /* SM_MIDEASTENABLED */
2409     /* SM_MOUSEWHEELPRESENT */
2410     /* SM_XVIRTUALSCREEN */
2411     /* SM_YVIRTUALSCREEN */
2412     /* SM_CXVIRTUALSCREEN */
2413     /* SM_CYVIRTUALSCREEN */
2414     /* SM_CMONITORS */
2415     /* SM_SAMEDISPLAYFORMAT */
2416     /* SM_IMMENABLED */
2417     /* SM_CXFOCUSBORDER */
2418     /* SM_CYFOCUSBORDER */
2419     /* SM_TABLETPC */
2420     /* SM_MEDIACENTER */
2421     /* SM_CMETRICS */
2422     /* end of tests */
2423     if( gsm_error_ctr ) { /* if any errors where found */
2424         trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
2425                 ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
2426         trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
2427                 ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
2428         trace( "Captionfontchar width %d  MenuFont %d,%d CaptionWidth from registry: %d\n",
2429                 avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidth);
2430     }
2431     ReleaseDC( 0, hdc);
2432 }
2433
2434 START_TEST(sysparams)
2435 {
2436     int argc;
2437     char** argv;
2438     WNDCLASSA wc;
2439     MSG msg;
2440     HANDLE hThread;
2441     DWORD dwThreadId;
2442     HANDLE hInstance = GetModuleHandleA( NULL );
2443
2444     hdc = GetDC(0);
2445     dpi = GetDeviceCaps( hdc, LOGPIXELSY);
2446     iswin9x = GetVersion() & 0x80000000;
2447
2448     /* This test requires interactivity, if we don't have it, give up */
2449     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
2450         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
2451
2452     argc = winetest_get_mainargs(&argv);
2453     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
2454     trace("strict=%d\n",strict);
2455
2456     trace("testing GetSystemMetrics with your current desktop settings\n");
2457     test_GetSystemMetrics( );
2458
2459     change_counter = 0;
2460     change_last_param = 0;
2461
2462     wc.lpszClassName = "SysParamsTestClass";
2463     wc.lpfnWndProc = SysParamsTestWndProc;
2464     wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
2465     wc.hInstance = hInstance;
2466     wc.hIcon = LoadIconA( 0, (LPSTR)IDI_APPLICATION );
2467     wc.hCursor = LoadCursorA( 0, (LPSTR)IDC_ARROW );
2468     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
2469     wc.lpszMenuName = 0;
2470     wc.cbClsExtra = 0;
2471     wc.cbWndExtra = 0;
2472     RegisterClassA( &wc );
2473
2474     ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
2475                                WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
2476
2477     hThread = CreateThread( NULL, 0, SysParamsThreadFunc, 0, 0, &dwThreadId );
2478     assert( hThread );
2479     CloseHandle( hThread );
2480
2481     while( GetMessageA( &msg, 0, 0, 0 )) {
2482         TranslateMessage( &msg );
2483         DispatchMessageA( &msg );
2484     }
2485     ReleaseDC( 0, hdc);
2486
2487 }