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