Implemented processing for actions SPI_SETMOUSEBUTTONSWAP,
[wine] / windows / sysparams.c
1 /*
2  * System parameters functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "windef.h"
13 #include "winbase.h"
14 #include "winnls.h"
15 #include "wingdi.h"
16 #include "winreg.h"
17 #include "wine/winuser16.h"
18 #include "winerror.h"
19
20 #include "controls.h"
21 #include "user.h"
22 #include "debugtools.h"
23 #include "sysmetrics.h"
24
25 DEFAULT_DEBUG_CHANNEL(system);
26
27 /* System parameter indexes */
28 #define SPI_SETBEEP_IDX                         0
29 #define SPI_SETMOUSE_IDX                        1
30 #define SPI_SETBORDER_IDX                       2
31 #define SPI_SETKEYBOARDSPEED_IDX                3
32 #define SPI_ICONHORIZONTALSPACING_IDX           4
33 #define SPI_SETSCREENSAVETIMEOUT_IDX            5
34 #define SPI_SETGRIDGRANULARITY_IDX              6
35 #define SPI_SETKEYBOARDDELAY_IDX                7
36 #define SPI_ICONVERTICALSPACING_IDX             8
37 #define SPI_SETICONTITLEWRAP_IDX                9
38 #define SPI_SETMENUDROPALIGNMENT_IDX            10
39 #define SPI_SETDOUBLECLKWIDTH_IDX               11
40 #define SPI_SETDOUBLECLKHEIGHT_IDX              12
41 #define SPI_SETDOUBLECLICKTIME_IDX              13
42 #define SPI_SETMOUSEBUTTONSWAP_IDX              14
43 #define SPI_SETFASTTASKSWITCH_IDX               15
44 #define SPI_SETDRAGFULLWINDOWS_IDX              16
45 #define SPI_SETWORKAREA_IDX                     17
46 #define SPI_SETSHOWSOUNDS_IDX                   18
47 #define SPI_SETSCREENSAVERRUNNING_IDX           19
48 #define SPI_WINE_IDX                            SPI_SETSCREENSAVERRUNNING_IDX
49
50 /**
51  * Names of the registry subkeys of HKEY_CURRENT_USER key and value names
52  * for the system parameters.
53  * Names of the keys are created by adding string "_REGKEY" to
54  * "SET" action names, value names are created by adding "_REG_NAME"
55  * to the "SET" action name.
56  */
57 #define SPI_SETBEEP_REGKEY              "Control Panel\\Sound"
58 #define SPI_SETBEEP_VALNAME             "Beep"
59 #define SPI_SETMOUSE_REGKEY             "Control Panel\\Mouse"
60 #define SPI_SETMOUSE_VALNAME1           "MouseThreshold1"
61 #define SPI_SETMOUSE_VALNAME2           "MouseThreshold2"
62 #define SPI_SETMOUSE_VALNAME3           "MouseSpeed"
63 #define SPI_SETBORDER_REGKEY            "Control Panel\\Desktop"
64 #define SPI_SETBORDER_VALNAME           "BorderWidth"
65 #define SPI_SETKEYBOARDSPEED_REGKEY             "Control Panel\\Keyboard"
66 #define SPI_SETKEYBOARDSPEED_VALNAME            "KeyboardSpeed"
67 #define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop"
68 #define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
69 #define SPI_SETSCREENSAVETIMEOUT_REGKEY         "Control Panel\\Desktop"
70 #define SPI_SETSCREENSAVETIMEOUT_VALNAME        "ScreenSaveTimeOut"
71 #define SPI_SETGRIDGRANULARITY_REGKEY           "Control Panel\\Desktop"
72 #define SPI_SETGRIDGRANULARITY_VALNAME          "GridGranularity"
73 #define SPI_SETKEYBOARDDELAY_REGKEY             "Control Panel\\Keyboard"
74 #define SPI_SETKEYBOARDDELAY_VALNAME            "KeyboardDelay"
75 #define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop"
76 #define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
77 #define SPI_SETICONTITLEWRAP_REGKEY             "Control Panel\\Desktop"
78 #define SPI_SETICONTITLEWRAP_VALNAME            "IconTitleWrap"
79 #define SPI_SETMENUDROPALIGNMENT_REGKEY         "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
80 #define SPI_SETMENUDROPALIGNMENT_VALNAME        "MenuDropAlignment"
81 #define SPI_SETDOUBLECLKWIDTH_REGKEY            "Control Panel\\Mouse"
82 #define SPI_SETDOUBLECLKWIDTH_VALNAME           "DoubleClickWidth"
83 #define SPI_SETDOUBLECLKHEIGHT_REGKEY           "Control Panel\\Mouse"
84 #define SPI_SETDOUBLECLKHEIGHT_VALNAME          "DoubleClickHeight"
85 #define SPI_SETDOUBLECLICKTIME_REGKEY           "Control Panel\\Mouse"
86 #define SPI_SETDOUBLECLICKTIME_VALNAME          "DoubleClickSpeed"
87 #define SPI_SETMOUSEBUTTONSWAP_REGKEY           "Control Panel\\Mouse"
88 #define SPI_SETMOUSEBUTTONSWAP_VALNAME          "SwapMouseButtons"
89 #define SPI_SETFASTTASKSWITCH_REGKEY            "Control Panel\\Desktop"
90 #define SPI_SETFASTTASKSWITCH_VALNAME           "CoolSwitch"
91 #define SPI_SETDRAGFULLWINDOWS_REGKEY           "Control Panel\\Desktop"
92 #define SPI_SETDRAGFULLWINDOWS_VALNAME          "DragFullWindows"
93 #define SPI_SETWORKAREA_REGKEY                  "Control Panel\\Desktop"
94 #define SPI_SETWORKAREA_VALNAME                 "WINE_WorkArea"
95 #define SPI_SETSHOWSOUNDS_REGKEY        "Control Panel\\Accessibility\\ShowSounds"
96 #define SPI_SETSHOWSOUNDS_VALNAME       "On"
97 #define SPI_SETSCREENSAVERRUNNING_REGKEY        "Control Panel\\Desktop"
98 #define SPI_SETSCREENSAVERRUNNING_VALNAME       "WINE_ScreenSaverRunning"
99
100 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
101 #define WINE_CURRENT_USER_REGKEY     "Wine"
102
103 /* Indicators whether system parameter value is loaded */
104 static char spi_loaded[SPI_WINE_IDX + 1];
105
106 static BOOL notify_change = TRUE;
107
108 /* System parameters storage */
109 static BOOL beep_active = TRUE;
110 static int mouse_threshold1 = 6;
111 static int mouse_threshold2 = 10;
112 static int mouse_speed = 1;
113 static int border = 1;
114 static int keyboard_speed = 31;
115 static int screensave_timeout = 300;
116 static int grid_granularity = 0;
117 static int keyboard_delay = 1;
118 static BOOL icon_title_wrap = TRUE;
119 static int double_click_time = 500;
120 static BOOL fast_task_switch = TRUE;
121 static BOOL drag_full_windows = FALSE;
122 static RECT work_area;
123 static BOOL screensaver_running = FALSE;
124
125 /***********************************************************************
126  *              GetTimerResolution (USER.14)
127  */
128 LONG WINAPI GetTimerResolution16(void)
129 {
130         return (1000);
131 }
132
133 /***********************************************************************
134  *              ControlPanelInfo (USER.273)
135  */
136 void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer )
137 {
138         FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer);
139 }
140
141 /* This function is a copy of the one in objects/font.c */
142 static void SYSPARAMS_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
143 {
144     font16->lfHeight = font32->lfHeight;
145     font16->lfWidth = font32->lfWidth;
146     font16->lfEscapement = font32->lfEscapement;
147     font16->lfOrientation = font32->lfOrientation;
148     font16->lfWeight = font32->lfWeight;
149     font16->lfItalic = font32->lfItalic;
150     font16->lfUnderline = font32->lfUnderline;
151     font16->lfStrikeOut = font32->lfStrikeOut;
152     font16->lfCharSet = font32->lfCharSet;
153     font16->lfOutPrecision = font32->lfOutPrecision;
154     font16->lfClipPrecision = font32->lfClipPrecision;
155     font16->lfQuality = font32->lfQuality;
156     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
157     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
158 }
159
160 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA* font32A, LPLOGFONTW font32W )
161 {
162     font32W->lfHeight = font32A->lfHeight;
163     font32W->lfWidth = font32A->lfWidth;
164     font32W->lfEscapement = font32A->lfEscapement;
165     font32W->lfOrientation = font32A->lfOrientation;
166     font32W->lfWeight = font32A->lfWeight;
167     font32W->lfItalic = font32A->lfItalic;
168     font32W->lfUnderline = font32A->lfUnderline;
169     font32W->lfStrikeOut = font32A->lfStrikeOut;
170     font32W->lfCharSet = font32A->lfCharSet;
171     font32W->lfOutPrecision = font32A->lfOutPrecision;
172     font32W->lfClipPrecision = font32A->lfClipPrecision;
173     font32W->lfQuality = font32A->lfQuality;
174     font32W->lfPitchAndFamily = font32A->lfPitchAndFamily;
175     MultiByteToWideChar( CP_ACP, 0, font32A->lfFaceName, -1, font32W->lfFaceName, LF_FACESIZE );
176     font32W->lfFaceName[LF_FACESIZE-1] = 0;
177 }
178
179 static void SYSPARAMS_NonClientMetrics32ATo16( const NONCLIENTMETRICSA* lpnm32, LPNONCLIENTMETRICS16 lpnm16 )
180 {
181     lpnm16->iBorderWidth        = lpnm32->iBorderWidth;
182     lpnm16->iScrollWidth        = lpnm32->iScrollWidth;
183     lpnm16->iScrollHeight       = lpnm32->iScrollHeight;
184     lpnm16->iCaptionWidth       = lpnm32->iCaptionWidth;
185     lpnm16->iCaptionHeight      = lpnm32->iCaptionHeight;
186     SYSPARAMS_LogFont32ATo16( &lpnm32->lfCaptionFont,   &lpnm16->lfCaptionFont );
187     lpnm16->iSmCaptionWidth     = lpnm32->iSmCaptionWidth;
188     lpnm16->iSmCaptionHeight    = lpnm32->iSmCaptionHeight;
189     SYSPARAMS_LogFont32ATo16( &lpnm32->lfSmCaptionFont, &lpnm16->lfSmCaptionFont );
190     lpnm16->iMenuWidth          = lpnm32->iMenuWidth;
191     lpnm16->iMenuHeight         = lpnm32->iMenuHeight;
192     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMenuFont,      &lpnm16->lfMenuFont );
193     SYSPARAMS_LogFont32ATo16( &lpnm32->lfStatusFont,    &lpnm16->lfStatusFont );
194     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMessageFont,   &lpnm16->lfMessageFont );
195 }
196
197 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA* lpnm32A, LPNONCLIENTMETRICSW lpnm32W )
198 {
199     lpnm32W->iBorderWidth       = lpnm32A->iBorderWidth;
200     lpnm32W->iScrollWidth       = lpnm32A->iScrollWidth;
201     lpnm32W->iScrollHeight      = lpnm32A->iScrollHeight;
202     lpnm32W->iCaptionWidth      = lpnm32A->iCaptionWidth;
203     lpnm32W->iCaptionHeight     = lpnm32A->iCaptionHeight;
204     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfCaptionFont,         &lpnm32W->lfCaptionFont );
205     lpnm32W->iSmCaptionWidth    = lpnm32A->iSmCaptionWidth;
206     lpnm32W->iSmCaptionHeight   = lpnm32A->iSmCaptionHeight;
207     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfSmCaptionFont,       &lpnm32W->lfSmCaptionFont );
208     lpnm32W->iMenuWidth         = lpnm32A->iMenuWidth;
209     lpnm32W->iMenuHeight        = lpnm32A->iMenuHeight;
210     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMenuFont,            &lpnm32W->lfMenuFont );
211     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfStatusFont,          &lpnm32W->lfStatusFont );
212     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMessageFont,         &lpnm32W->lfMessageFont );
213 }
214
215 /***********************************************************************
216  *           SYSPARAMS_Reset
217  *
218  * Sets the system parameter which should be always loaded to
219  * current value stored in registry.
220  * Invalidates lazy loaded parameter, so it will be loaded the next time
221  * it is requested.
222  *
223  * Parameters:
224  * uiAction - system parameter to reload value for.
225  *      Note, only "SET" values can be used for this parameter.
226  *      If uiAction is 0 all system parameters are reset.
227  */
228 void SYSPARAMS_Reset( UINT uiAction )
229 {
230 #define WINE_RELOAD_SPI(x) \
231     case x: \
232         spi_loaded[x##_IDX] = FALSE; \
233         SystemParametersInfoA( x, 0, dummy_buf, 0 );\
234         if (uiAction) \
235             break
236
237 #define WINE_IGNORE_SPI(x) \
238     case x: \
239         if (uiAction) \
240             break
241
242 #define WINE_INVALIDATE_SPI(x) \
243     case x: \
244         spi_loaded[x##_IDX] = FALSE; \
245         break
246
247     BOOL not_all_processed = TRUE;
248     char dummy_buf[10];
249
250     /* Execution falls through all the branches for uiAction == 0 */
251     switch (uiAction)
252     {
253     case 0:
254         memset( spi_loaded, 0, sizeof(spi_loaded) );
255
256     WINE_RELOAD_SPI(SPI_SETBORDER);
257     WINE_RELOAD_SPI(SPI_ICONHORIZONTALSPACING);
258     WINE_RELOAD_SPI(SPI_ICONVERTICALSPACING);
259     WINE_IGNORE_SPI(SPI_SETSCREENSAVEACTIVE);
260     WINE_RELOAD_SPI(SPI_SETDOUBLECLKWIDTH);
261     WINE_RELOAD_SPI(SPI_SETDOUBLECLKHEIGHT);
262     WINE_RELOAD_SPI(SPI_SETMOUSEBUTTONSWAP);
263     WINE_RELOAD_SPI(SPI_SETSHOWSOUNDS);
264     WINE_RELOAD_SPI(SPI_SETMENUDROPALIGNMENT);
265
266     default:
267         if (uiAction)
268         {
269             /* lazy loaded parameters */
270             switch (uiAction)
271             {
272             WINE_INVALIDATE_SPI(SPI_SETBEEP);
273             WINE_INVALIDATE_SPI(SPI_SETMOUSE);
274             WINE_INVALIDATE_SPI(SPI_SETKEYBOARDSPEED);
275             WINE_INVALIDATE_SPI(SPI_SETSCREENSAVETIMEOUT);
276             WINE_INVALIDATE_SPI(SPI_SETGRIDGRANULARITY);
277             WINE_INVALIDATE_SPI(SPI_SETKEYBOARDDELAY);
278             WINE_INVALIDATE_SPI(SPI_SETICONTITLEWRAP);
279             WINE_INVALIDATE_SPI(SPI_SETDOUBLECLICKTIME);
280             WINE_INVALIDATE_SPI(SPI_SETFASTTASKSWITCH);
281             WINE_INVALIDATE_SPI(SPI_SETDRAGFULLWINDOWS);
282             WINE_INVALIDATE_SPI(SPI_SETWORKAREA);
283             WINE_INVALIDATE_SPI(SPI_SETSCREENSAVERRUNNING);
284             default:
285                 FIXME( "Unknown action reset: %u\n", uiAction );
286                 break;
287             }
288         }
289         else
290             not_all_processed = FALSE;
291         break;
292     }
293
294     if (!uiAction && not_all_processed)
295         ERR( "Incorrect implementation of SYSPARAMS_Reset. "
296              "Not all params are reloaded.\n" );
297 #undef WINE_INVALIDATE_SPI
298 #undef WINE_IGNORE_SPI
299 #undef WINE_RELOAD_SPI
300 }
301
302 /***********************************************************************
303  *           get_volatile_regkey
304  *
305  * Return a handle to the volatile registry key used to store
306  * non-permanently modified parameters.
307  */
308 static HKEY get_volatile_regkey(void)
309 {
310     static HKEY volatile_key;
311
312     if (!volatile_key)
313     {
314         if (RegCreateKeyExA( HKEY_CURRENT_USER, WINE_CURRENT_USER_REGKEY,
315                              0, 0, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 0,
316                              &volatile_key, 0 ) != ERROR_SUCCESS)
317             ERR("Can't create wine configuration registry branch");
318     }
319     return volatile_key;
320 }
321
322 /***********************************************************************
323  *           SYSPARAMS_NotifyChange
324  *
325  * Sends notification about system parameter update.
326  */
327 void SYSPARAMS_NotifyChange( UINT uiAction, UINT fWinIni )
328 {
329     if (notify_change)
330     {
331         if (fWinIni & SPIF_UPDATEINIFILE)
332         {
333             if (fWinIni & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE))
334                 SendMessageA(HWND_BROADCAST, WM_SETTINGCHANGE,
335                              uiAction, (LPARAM) "");
336         }
337         else 
338         {
339             /* FIXME notify other wine processes with internal message */
340         }
341     }
342 }
343
344
345 /***********************************************************************
346  * Loads system parameter from user profile.
347  */
348 BOOL SYSPARAMS_Load( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpBuf )
349 {
350     BOOL ret = FALSE;
351     DWORD type;
352     HKEY hKey;
353     DWORD count;
354
355     if ((RegOpenKeyA( get_volatile_regkey(), lpRegKey,
356                      &hKey ) == ERROR_SUCCESS) ||
357         (RegOpenKeyA( HKEY_CURRENT_USER, lpRegKey,
358                       &hKey ) == ERROR_SUCCESS))
359     {
360         ret = !RegQueryValueExA( hKey, lpValName, NULL, &type, lpBuf, &count );
361         RegCloseKey( hKey );
362     }
363     return ret;
364 }
365
366 /***********************************************************************
367  * Saves system parameter to user profile.
368  */
369 BOOL SYSPARAMS_Save( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpValue,
370                      UINT fWinIni )
371 {
372     HKEY hKey;
373     HKEY hBaseKey;
374     DWORD dwOptions;
375     BOOL ret = FALSE;
376
377     if (fWinIni & SPIF_UPDATEINIFILE)
378     {
379         hBaseKey = HKEY_CURRENT_USER;
380         dwOptions = 0;
381     }
382     else
383     {
384         hBaseKey = get_volatile_regkey();
385         dwOptions = REG_OPTION_VOLATILE;
386     }
387
388     if (RegCreateKeyExA( hBaseKey, lpRegKey,
389                          0, 0, dwOptions, KEY_ALL_ACCESS,
390                          0, &hKey, 0 ) == ERROR_SUCCESS)
391     {
392         if (RegSetValueExA( hKey, lpValName, 0, REG_SZ,
393                             lpValue, strlen(lpValue) + 1 ) == ERROR_SUCCESS)
394         {
395             ret = TRUE;
396             if (hBaseKey == HKEY_CURRENT_USER)
397                 RegDeleteKeyA( get_volatile_regkey(), lpRegKey );
398         }
399         RegCloseKey( hKey );
400     }
401     return ret;
402 }
403
404
405 /***********************************************************************
406  *           SYSPARAMS_GetDoubleClickSize
407  *
408  * There is no SPI_GETDOUBLECLK* so we export this function instead.
409  */
410 void SYSPARAMS_GetDoubleClickSize( INT *width, INT *height )
411 {
412     char buf[10];
413
414     if (!spi_loaded[SPI_SETDOUBLECLKWIDTH_IDX])
415     {
416         char buf[10];
417
418         if (SYSPARAMS_Load( SPI_SETDOUBLECLKWIDTH_REGKEY,
419                             SPI_SETDOUBLECLKWIDTH_VALNAME, buf ))
420         {
421             SYSMETRICS_Set( SM_CXDOUBLECLK, atoi( buf ) );
422         }
423         spi_loaded[SPI_SETDOUBLECLKWIDTH_IDX] = TRUE;
424     }
425     if (!spi_loaded[SPI_SETDOUBLECLKHEIGHT_IDX])
426     {
427         if (SYSPARAMS_Load( SPI_SETDOUBLECLKHEIGHT_REGKEY,
428                             SPI_SETDOUBLECLKHEIGHT_VALNAME, buf ))
429         {
430             SYSMETRICS_Set( SM_CYDOUBLECLK, atoi( buf ) );
431         }
432         spi_loaded[SPI_SETDOUBLECLKHEIGHT_IDX] = TRUE;
433     }
434     *width  = GetSystemMetrics( SM_CXDOUBLECLK );
435     *height = GetSystemMetrics( SM_CYDOUBLECLK );
436 }
437
438
439 /***********************************************************************
440  *           SYSPARAMS_GetMouseButtonSwap
441  *
442  * There is no SPI_GETMOUSEBUTTONSWAP so we export this function instead.
443  */
444 INT SYSPARAMS_GetMouseButtonSwap( void )
445 {
446         int spi_idx = SPI_SETMOUSEBUTTONSWAP_IDX;
447
448         if (!spi_loaded[spi_idx])
449         {
450             char buf[5];
451
452             if (SYSPARAMS_Load( SPI_SETMOUSEBUTTONSWAP_REGKEY,
453                                 SPI_SETMOUSEBUTTONSWAP_VALNAME, buf ))
454             {
455                 SYSMETRICS_Set( SM_SWAPBUTTON, atoi( buf ) );
456             }
457             spi_loaded[spi_idx] = TRUE;
458         }
459
460         return GetSystemMetrics( SM_SWAPBUTTON );
461 }
462
463 /***********************************************************************
464  *              SystemParametersInfoA (USER32.@)
465  *
466  *     Each system parameter has flag which shows whether the parameter
467  * is loaded or not. Parameters, stored directly in SysParametersInfo are
468  * loaded from registry only when they are requested and the flag is
469  * "false", after the loading the flag is set to "true". On interprocess
470  * notification of the parameter change the corresponding parameter flag is
471  * set to "false". The parameter value will be reloaded when it is requested
472  * the next time.
473  *     Parameters, backed by or depend on GetSystemMetrics are processed
474  * differently. These parameters are always loaded. They are reloaded right
475  * away on interprocess change notification. We can't do lazy loading because
476  * we don't want to complicate GetSystemMetrics.
477  *     Parameters, backed by X settings are read from corresponding setting.
478  * On the parameter change request the setting is changed. Interprocess change
479  * notifications are ignored.
480  *     When parameter value is updated the changed value is stored in permanent
481  * registry branch if saving is requested. Otherwise it is stored
482  * in temporary branch
483  *
484  */
485 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
486                                    PVOID pvParam, UINT fWinIni )
487 {
488 #define WINE_SPI_FIXME(x) \
489     case x: \
490         FIXME( "Unimplemented action: %u (%s)\n", x, #x ); \
491         SetLastError( ERROR_INVALID_SPI_VALUE ); \
492         ret = FALSE; \
493         break
494 #define WINE_SPI_WARN(x) \
495     case x: \
496         WARN( "Ignored action: %u (%s)\n", x, #x ); \
497         break
498
499     BOOL ret = TRUE;
500     unsigned spi_idx = 0;
501     
502     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fWinIni);
503     
504     switch (uiAction)
505     {
506     case SPI_GETBEEP:                           /*      1 */
507         spi_idx = SPI_SETBEEP_IDX;
508         if (!spi_loaded[spi_idx])
509         {
510             char buf[5];
511             
512             if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf ))
513                 beep_active  = !strcasecmp( "Yes", buf );
514             spi_loaded[spi_idx] = TRUE;
515         }
516         
517         *(BOOL *)pvParam = beep_active;
518         break;
519
520     case SPI_SETBEEP:                           /*      2 */
521         spi_idx = SPI_SETBEEP_IDX;
522         if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
523                             (uiParam ? "Yes" : "No"), fWinIni ))
524         {
525             beep_active = uiParam;
526             spi_loaded[spi_idx] = TRUE;
527         }
528         else
529             ret = FALSE;
530         break;
531
532     case SPI_GETMOUSE:                          /*      3 */
533         spi_idx = SPI_SETMOUSE_IDX;
534         if (!spi_loaded[spi_idx])
535         {
536             char buf[10];
537
538             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
539                                 buf ))
540                 mouse_threshold1 = atoi( buf );
541             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
542                                 buf ))
543                 mouse_threshold2 = atoi( buf );
544             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
545                                 buf ))
546                 mouse_speed = atoi( buf );
547             spi_loaded[spi_idx] = TRUE;
548         }
549         ((INT *)pvParam)[0] = mouse_threshold1;
550         ((INT *)pvParam)[1] = mouse_threshold2;
551         ((INT *)pvParam)[2] = mouse_speed;
552         break;
553         
554     case SPI_SETMOUSE:                          /*      4 */
555     {
556         char buf[10];
557
558         spi_idx = SPI_SETMOUSE_IDX;
559         sprintf(buf, "%d", ((INT *)pvParam)[0]);
560
561         if (SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
562                             buf, fWinIni ))
563         {
564             mouse_threshold1 = ((INT *)pvParam)[0];
565             spi_loaded[spi_idx] = TRUE;
566
567             sprintf(buf, "%d", ((INT *)pvParam)[1]);
568             SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
569                             buf, fWinIni );
570             mouse_threshold2 = ((INT *)pvParam)[1];
571
572             sprintf(buf, "%d", ((INT *)pvParam)[2]);
573             SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
574                             buf, fWinIni );
575             mouse_speed = ((INT *)pvParam)[2];
576         }
577         else
578             ret = FALSE;
579         break;
580     }
581
582     case SPI_GETBORDER:                         /*      5 */
583         spi_idx = SPI_SETBORDER_IDX;
584         if (!spi_loaded[spi_idx])
585         {
586             char buf[10];
587
588             if (SYSPARAMS_Load( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
589                                 buf ))
590             {
591                 int i = atoi( buf );
592                 if (i > 0) border = i;
593             }
594             spi_loaded[spi_idx] = TRUE;
595             if (TWEAK_WineLook > WIN31_LOOK)
596             {
597                 SYSMETRICS_Set( SM_CXFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
598                 SYSMETRICS_Set( SM_CYFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
599             }
600         }
601         *(INT *)pvParam = border;
602         break;
603
604     case SPI_SETBORDER:                         /*      6 */
605     {
606         char buf[10];
607
608         spi_idx = SPI_SETBORDER_IDX;
609         sprintf(buf, "%u", uiParam);
610
611         if (SYSPARAMS_Save( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
612                             buf, fWinIni ))
613         {
614             if (uiParam > 0) 
615             {
616                 border = uiParam;
617                 spi_loaded[spi_idx] = TRUE;
618                 if (TWEAK_WineLook > WIN31_LOOK)
619                 {
620                     SYSMETRICS_Set( SM_CXFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
621                     SYSMETRICS_Set( SM_CYFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
622                 }
623             }
624         }
625         else
626             ret = FALSE;
627         break;
628     }
629
630     case SPI_GETKEYBOARDSPEED:                  /*     10 */
631         spi_idx = SPI_SETKEYBOARDSPEED_IDX;
632         if (!spi_loaded[spi_idx])
633         {
634             char buf[10];
635
636             if (SYSPARAMS_Load( SPI_SETKEYBOARDSPEED_REGKEY,
637                                 SPI_SETKEYBOARDSPEED_VALNAME,
638                                 buf ))
639                 keyboard_speed = atoi( buf );
640             spi_loaded[spi_idx] = TRUE;
641         }
642         *(INT *)pvParam = keyboard_speed;
643         break;
644
645     case SPI_SETKEYBOARDSPEED:                  /*     11 */
646     {
647         char buf[10];
648
649         spi_idx = SPI_SETKEYBOARDSPEED_IDX;
650         if (uiParam > 31)
651             uiParam = 31;
652         sprintf(buf, "%u", uiParam);
653
654         if (SYSPARAMS_Save( SPI_SETKEYBOARDSPEED_REGKEY,
655                             SPI_SETKEYBOARDSPEED_VALNAME,
656                             buf, fWinIni ))
657         {
658             keyboard_speed = uiParam;
659             spi_loaded[spi_idx] = TRUE;
660         }
661         else
662             ret = FALSE;
663         break;
664     }
665
666     /* not implemented in Windows */
667     WINE_SPI_WARN(SPI_LANGDRIVER);              /*     12 */
668
669     case SPI_ICONHORIZONTALSPACING:             /*     13 */
670         spi_idx = SPI_ICONHORIZONTALSPACING_IDX;
671         if (pvParam != NULL)
672         {
673             if (!spi_loaded[spi_idx])
674             {
675                 char buf[10];
676             
677                 if (SYSPARAMS_Load( SPI_ICONHORIZONTALSPACING_REGKEY,
678                                     SPI_ICONHORIZONTALSPACING_VALNAME, buf ))
679                 {
680                     SYSMETRICS_Set( SM_CXICONSPACING, atoi( buf ) );
681                 }
682                 spi_loaded[spi_idx] = TRUE;
683             }
684
685             *(INT *)pvParam = GetSystemMetrics( SM_CXICONSPACING );
686         }
687         else
688         {
689             char buf[10];
690
691             if (uiParam < 32) uiParam = 32;
692
693             sprintf(buf, "%u", uiParam);
694             if (SYSPARAMS_Save( SPI_ICONHORIZONTALSPACING_REGKEY,
695                                 SPI_ICONHORIZONTALSPACING_VALNAME,
696                                 buf, fWinIni ))
697             {
698                 SYSMETRICS_Set( SM_CXICONSPACING, uiParam );
699                 spi_loaded[spi_idx] = TRUE;
700             }
701             else
702                 ret = FALSE;
703         }
704         break;
705
706     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
707         spi_idx = SPI_SETSCREENSAVETIMEOUT_IDX;
708         if (!spi_loaded[spi_idx])
709         {
710             char buf[10];
711
712             if (SYSPARAMS_Load( SPI_SETSCREENSAVETIMEOUT_REGKEY,
713                                 SPI_SETSCREENSAVETIMEOUT_VALNAME,
714                                 buf ))
715                 screensave_timeout = atoi( buf );
716
717             spi_loaded[spi_idx] = TRUE;
718         }
719         *(INT *)pvParam = screensave_timeout;
720         break;
721
722     case SPI_SETSCREENSAVETIMEOUT:              /*     15 */
723     {
724         char buf[10];
725
726         spi_idx = SPI_SETSCREENSAVETIMEOUT_IDX;
727         sprintf(buf, "%u", uiParam);
728
729         if (SYSPARAMS_Save( SPI_SETSCREENSAVETIMEOUT_REGKEY,
730                             SPI_SETSCREENSAVETIMEOUT_VALNAME,
731                             buf, fWinIni ))
732         {
733             screensave_timeout = uiParam;
734             spi_loaded[spi_idx] = TRUE;
735         }
736         else
737             ret = FALSE;
738         break;
739     }
740         
741     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
742         *(BOOL *)pvParam = USER_Driver.pGetScreenSaveActive();
743         break;
744
745     case SPI_SETSCREENSAVEACTIVE:               /*     17 */
746     {
747         char buf[5];
748
749         sprintf(buf, "%u", uiParam);
750         USER_Driver.pSetScreenSaveActive( uiParam );
751         break;
752     }
753         
754     case SPI_GETGRIDGRANULARITY:                /*     18 */
755         spi_idx = SPI_SETGRIDGRANULARITY_IDX;
756         if (!spi_loaded[spi_idx])
757         {
758             char buf[10];
759
760             if (SYSPARAMS_Load( SPI_SETGRIDGRANULARITY_REGKEY,
761                                 SPI_SETGRIDGRANULARITY_VALNAME,
762                                 buf ))
763                 grid_granularity = atoi( buf );
764             
765             spi_loaded[spi_idx] = TRUE;
766         }
767         *(INT *)pvParam = grid_granularity;
768         break;
769
770     case SPI_SETGRIDGRANULARITY:                /*     19 */
771     {
772         char buf[10];
773
774         spi_idx = SPI_SETGRIDGRANULARITY_IDX;
775         sprintf(buf, "%u", uiParam);
776
777         if (SYSPARAMS_Save( SPI_SETGRIDGRANULARITY_REGKEY,
778                             SPI_SETGRIDGRANULARITY_VALNAME,
779                             buf, fWinIni ))
780         {
781             grid_granularity = uiParam;
782             spi_loaded[spi_idx] = TRUE;
783         }
784         else
785             ret = FALSE;
786         break;
787     }
788
789     case SPI_SETDESKWALLPAPER:                  /*     20 */
790         ret = SetDeskWallPaper( (LPSTR)pvParam );
791         break;
792     case SPI_SETDESKPATTERN:                    /*     21 */
793         /* FIXME: the ability to specify a pattern in pvParam
794            doesn't seem to be documented for Win32 */
795         if ((INT16)uiParam == -1)
796         {
797             char buffer[256];
798             GetProfileStringA( "Desktop", "Pattern", 
799                                "170 85 170 85 170 85 170 85", 
800                                buffer, sizeof(buffer) );
801             ret = DESKTOP_SetPattern( (LPSTR)buffer );
802         } else
803             ret = DESKTOP_SetPattern( (LPSTR)pvParam );
804         break;
805
806     case SPI_GETKEYBOARDDELAY:                  /*     22 */
807         spi_idx = SPI_SETKEYBOARDDELAY_IDX;
808         if (!spi_loaded[spi_idx])
809         {
810             char buf[10];
811
812             if (SYSPARAMS_Load( SPI_SETKEYBOARDDELAY_REGKEY,
813                                 SPI_SETKEYBOARDDELAY_VALNAME,
814                                 buf ))
815             {
816                 int i = atoi( buf );
817                 if ( (i >= 0) && (i <= 3)) keyboard_delay = i;
818             }
819             
820             spi_loaded[spi_idx] = TRUE;
821         }
822         *(INT *)pvParam = keyboard_delay;
823         break;
824
825     case SPI_SETKEYBOARDDELAY:                  /*     23 */
826     {
827         char buf[10];
828
829         spi_idx = SPI_SETKEYBOARDDELAY_IDX;
830         sprintf(buf, "%u", uiParam);
831
832         if (SYSPARAMS_Save( SPI_SETKEYBOARDDELAY_REGKEY,
833                             SPI_SETKEYBOARDDELAY_VALNAME,
834                             buf, fWinIni ))
835         {
836             if (uiParam <= 3)
837                 keyboard_delay = uiParam;
838             spi_loaded[spi_idx] = TRUE;
839         }
840         else
841             ret = FALSE;
842         break;
843     }
844
845     case SPI_ICONVERTICALSPACING:               /*     24 */
846         spi_idx = SPI_ICONVERTICALSPACING_IDX;
847         if (pvParam != NULL)
848         {
849             if (!spi_loaded[spi_idx])
850             {
851                 char buf[10];
852             
853                 if (SYSPARAMS_Load( SPI_ICONVERTICALSPACING_REGKEY,
854                                     SPI_ICONVERTICALSPACING_VALNAME, buf ))
855                 {
856                     SYSMETRICS_Set( SM_CYICONSPACING, atoi( buf ) );
857                 }
858                 spi_loaded[spi_idx] = TRUE;
859             }
860
861             *(INT *)pvParam = GetSystemMetrics( SM_CYICONSPACING );
862         }
863         else
864         {
865             char buf[10];
866
867             if (uiParam < 32) uiParam = 32;
868
869             sprintf(buf, "%u", uiParam);
870             if (SYSPARAMS_Save( SPI_ICONVERTICALSPACING_REGKEY,
871                                 SPI_ICONVERTICALSPACING_VALNAME,
872                                 buf, fWinIni ))
873             {
874                 SYSMETRICS_Set( SM_CYICONSPACING, uiParam );
875                 spi_loaded[spi_idx] = TRUE;
876             }
877             else
878                 ret = FALSE;
879         }
880         
881         break;
882
883     case SPI_GETICONTITLEWRAP:                  /*     25 */
884         spi_idx = SPI_SETICONTITLEWRAP_IDX;
885         if (!spi_loaded[spi_idx])
886         {
887             char buf[5];
888
889             if (SYSPARAMS_Load( SPI_SETICONTITLEWRAP_REGKEY,
890                                 SPI_SETICONTITLEWRAP_VALNAME, buf ))
891                 icon_title_wrap  = atoi(buf);
892             spi_loaded[spi_idx] = TRUE;
893         }
894         
895         *(BOOL *)pvParam = icon_title_wrap;
896         break;
897
898     case SPI_SETICONTITLEWRAP:                  /*     26 */
899     {
900         char buf[5];
901
902         spi_idx = SPI_SETICONTITLEWRAP_IDX;
903         sprintf(buf, "%u", uiParam);
904         if (SYSPARAMS_Save( SPI_SETICONTITLEWRAP_REGKEY,
905                             SPI_SETICONTITLEWRAP_VALNAME,
906                             buf, fWinIni ))
907         {
908             icon_title_wrap = uiParam;
909             spi_loaded[spi_idx] = TRUE;
910         }
911         else
912             ret = FALSE;
913         break;
914     }
915     
916     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
917         spi_idx = SPI_SETMENUDROPALIGNMENT_IDX;
918
919         if (!spi_loaded[spi_idx])
920         {
921             char buf[5];
922             
923             if (SYSPARAMS_Load( SPI_SETMENUDROPALIGNMENT_REGKEY,
924                                 SPI_SETMENUDROPALIGNMENT_VALNAME, buf ))
925             {
926                 SYSMETRICS_Set( SM_MENUDROPALIGNMENT, atoi( buf ) );
927             }
928             spi_loaded[spi_idx] = TRUE;
929         }
930         
931
932         *(BOOL *)pvParam = GetSystemMetrics( SM_MENUDROPALIGNMENT );
933         break;
934
935     case SPI_SETMENUDROPALIGNMENT:              /*     28 */
936     {
937         char buf[5];
938         spi_idx = SPI_SETMENUDROPALIGNMENT_IDX;
939
940         sprintf(buf, "%u", uiParam);
941         if (SYSPARAMS_Save( SPI_SETMENUDROPALIGNMENT_REGKEY,
942                             SPI_SETMENUDROPALIGNMENT_VALNAME,
943                             buf, fWinIni ))
944         {
945             SYSMETRICS_Set( SM_MENUDROPALIGNMENT, uiParam );
946             spi_loaded[spi_idx] = TRUE;
947         }
948         else
949             ret = FALSE;
950         break;
951     }
952
953     case SPI_SETDOUBLECLKWIDTH:                 /*     29 */
954     {
955         char buf[10];
956         spi_idx = SPI_SETDOUBLECLKWIDTH_IDX;
957
958         sprintf(buf, "%u", uiParam);
959         if (SYSPARAMS_Save( SPI_SETDOUBLECLKWIDTH_REGKEY,
960                             SPI_SETDOUBLECLKWIDTH_VALNAME,
961                             buf, fWinIni ))
962         {
963             SYSMETRICS_Set( SM_CXDOUBLECLK, uiParam );
964             spi_loaded[spi_idx] = TRUE;
965         }
966         else
967             ret = FALSE;
968         break;
969     }
970
971     case SPI_SETDOUBLECLKHEIGHT:                /*     30 */
972     {
973         char buf[10];
974         spi_idx = SPI_SETDOUBLECLKHEIGHT_IDX;
975
976         sprintf(buf, "%u", uiParam);
977         if (SYSPARAMS_Save( SPI_SETDOUBLECLKHEIGHT_REGKEY,
978                             SPI_SETDOUBLECLKHEIGHT_VALNAME,
979                             buf, fWinIni ))
980         {
981             SYSMETRICS_Set( SM_CYDOUBLECLK, uiParam );
982             spi_loaded[spi_idx] = TRUE;
983         }
984         else
985             ret = FALSE;
986         break;
987     }
988
989     case SPI_GETICONTITLELOGFONT:               /*     31 */
990     {
991         LPLOGFONTA lpLogFont = (LPLOGFONTA)pvParam;
992
993         /* from now on we always have an alias for MS Sans Serif */
994
995         GetProfileStringA( "Desktop", "IconTitleFaceName", "MS Sans Serif", 
996                            lpLogFont->lfFaceName, LF_FACESIZE );
997         lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "IconTitleSize", 13 );
998         lpLogFont->lfWidth = 0;
999         lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1000         lpLogFont->lfWeight = FW_NORMAL;
1001         lpLogFont->lfItalic = FALSE;
1002         lpLogFont->lfStrikeOut = FALSE;
1003         lpLogFont->lfUnderline = FALSE;
1004         lpLogFont->lfCharSet = ANSI_CHARSET;
1005         lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1006         lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1007         lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1008         break;
1009     }
1010
1011     case SPI_SETDOUBLECLICKTIME:                /*     32 */
1012     {
1013         char buf[10];
1014
1015         spi_idx = SPI_SETDOUBLECLICKTIME_IDX;
1016         sprintf(buf, "%u", uiParam);
1017
1018         if (SYSPARAMS_Save( SPI_SETDOUBLECLICKTIME_REGKEY,
1019                             SPI_SETDOUBLECLICKTIME_VALNAME,
1020                             buf, fWinIni ))
1021         {
1022             if (!uiParam)
1023                 uiParam = 500;
1024             double_click_time = uiParam;
1025             spi_loaded[spi_idx] = TRUE;
1026         }
1027         else
1028             ret = FALSE;
1029         break;
1030     }
1031
1032     case SPI_SETMOUSEBUTTONSWAP:                /*     33 */
1033     {
1034         char buf[5];
1035         spi_idx = SPI_SETMOUSEBUTTONSWAP_IDX;
1036
1037         sprintf(buf, "%u", uiParam);
1038         if (SYSPARAMS_Save( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1039                             SPI_SETMOUSEBUTTONSWAP_VALNAME,
1040                             buf, fWinIni ))
1041         {
1042             SYSMETRICS_Set( SM_SWAPBUTTON, uiParam );
1043             spi_loaded[spi_idx] = TRUE;
1044         }
1045         else
1046             ret = FALSE;
1047         break;
1048     }
1049
1050     WINE_SPI_FIXME(SPI_SETICONTITLELOGFONT);    /*     34 */
1051
1052     case SPI_GETFASTTASKSWITCH:                 /*     35 */
1053         spi_idx = SPI_SETFASTTASKSWITCH_IDX;
1054         if (!spi_loaded[spi_idx])
1055         {
1056             char buf[5];
1057
1058             if (SYSPARAMS_Load( SPI_SETFASTTASKSWITCH_REGKEY,
1059                                 SPI_SETFASTTASKSWITCH_VALNAME, buf ))
1060                 fast_task_switch  = atoi(buf);
1061             spi_loaded[spi_idx] = TRUE;
1062         }
1063         
1064         *(BOOL *)pvParam = fast_task_switch;
1065         break;
1066
1067     case SPI_SETFASTTASKSWITCH:                 /*     36 */
1068     {
1069         char buf[5];
1070
1071         spi_idx = SPI_SETFASTTASKSWITCH_IDX;
1072         sprintf(buf, "%u", uiParam);
1073         if (SYSPARAMS_Save( SPI_SETFASTTASKSWITCH_REGKEY,
1074                             SPI_SETFASTTASKSWITCH_VALNAME,
1075                             buf, fWinIni ))
1076         {
1077             fast_task_switch = uiParam;
1078             spi_loaded[spi_idx] = TRUE;
1079         }
1080         else
1081             ret = FALSE;
1082         break;
1083     }
1084     
1085     case SPI_SETDRAGFULLWINDOWS:                /*     37  WINVER >= 0x0400 */
1086     {
1087         char buf[5];
1088
1089         spi_idx = SPI_SETDRAGFULLWINDOWS_IDX;
1090         sprintf(buf, "%u", uiParam);
1091         if (SYSPARAMS_Save( SPI_SETDRAGFULLWINDOWS_REGKEY,
1092                             SPI_SETDRAGFULLWINDOWS_VALNAME,
1093                             buf, fWinIni ))
1094         {
1095             drag_full_windows = uiParam;
1096             spi_loaded[spi_idx] = TRUE;
1097         }
1098         else
1099             ret = FALSE;
1100         break;
1101     }
1102
1103     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
1104         spi_idx = SPI_SETDRAGFULLWINDOWS_IDX;
1105         if (!spi_loaded[spi_idx])
1106         {
1107             char buf[5];
1108
1109             if (SYSPARAMS_Load( SPI_SETDRAGFULLWINDOWS_REGKEY,
1110                                 SPI_SETDRAGFULLWINDOWS_VALNAME, buf ))
1111                 drag_full_windows  = atoi(buf);
1112             spi_loaded[spi_idx] = TRUE;
1113         }
1114         
1115         *(BOOL *)pvParam = drag_full_windows;
1116         break;
1117
1118     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1119     {
1120         LPNONCLIENTMETRICSA lpnm = (LPNONCLIENTMETRICSA)pvParam;
1121                 
1122         if (lpnm->cbSize == sizeof(NONCLIENTMETRICSA))
1123         {
1124             LPLOGFONTA lpLogFont = &(lpnm->lfMenuFont);
1125             
1126             /* clear the struct, so we have 'sane' members */
1127             memset(
1128                 (char *)pvParam + sizeof(lpnm->cbSize),
1129                 0,
1130                 lpnm->cbSize - sizeof(lpnm->cbSize)
1131                 );
1132
1133             /* FIXME: initialize geometry entries */
1134             /* FIXME: As these values are presumably in device units,
1135              *  we should calculate the defaults based on the screen dpi
1136              */
1137             /* caption */
1138             lpnm->iCaptionWidth = ((TWEAK_WineLook > WIN31_LOOK)  ? 32 : 20);
1139             lpnm->iCaptionHeight = lpnm->iCaptionWidth;
1140             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfCaptionFont), 0 );
1141             lpnm->lfCaptionFont.lfWeight = FW_BOLD;
1142
1143             /* small caption */
1144             lpnm->iSmCaptionWidth = ((TWEAK_WineLook > WIN31_LOOK)  ? 32 : 17);
1145             lpnm->iSmCaptionHeight = lpnm->iSmCaptionWidth;
1146             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfSmCaptionFont), 0 );
1147
1148             /* menus, FIXME: names of wine.conf entries are bogus */
1149
1150             lpnm->iMenuWidth = GetProfileIntA( "Desktop", "MenuWidth", 13 );    /* size of the menu buttons*/
1151             lpnm->iMenuHeight = GetProfileIntA( "Desktop", "MenuHeight", 
1152                                                 (TWEAK_WineLook > WIN31_LOOK) ? 13 : 27 );
1153
1154             GetProfileStringA( "Desktop", "MenuFont", 
1155                                (TWEAK_WineLook > WIN31_LOOK) ? "MS Sans Serif": "System", 
1156                                lpLogFont->lfFaceName, LF_FACESIZE );
1157
1158             lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "MenuFontSize", 13 );
1159             lpLogFont->lfWidth = 0;
1160             lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1161             lpLogFont->lfWeight = (TWEAK_WineLook > WIN31_LOOK) ? FW_NORMAL : FW_BOLD;
1162             lpLogFont->lfItalic = FALSE;
1163             lpLogFont->lfStrikeOut = FALSE;
1164             lpLogFont->lfUnderline = FALSE;
1165             lpLogFont->lfCharSet = ANSI_CHARSET;
1166             lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1167             lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1168             lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1169
1170             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1171                                    (LPVOID)&(lpnm->lfStatusFont), 0 );
1172             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1173                                    (LPVOID)&(lpnm->lfMessageFont), 0 );
1174         }
1175         else
1176         {
1177             WARN("size mismatch !! (is %d; should be %d)\n", lpnm->cbSize, sizeof(NONCLIENTMETRICSA));
1178             /* FIXME: SetLastError? */
1179             ret = FALSE;
1180         }
1181         break;
1182     }
1183     WINE_SPI_FIXME(SPI_SETNONCLIENTMETRICS);    /*     42  WINVER >= 0x400 */
1184
1185     WINE_SPI_FIXME(SPI_GETMINIMIZEDMETRICS);    /*     43  WINVER >= 0x400 */
1186     WINE_SPI_FIXME(SPI_SETMINIMIZEDMETRICS);    /*     44  WINVER >= 0x400 */
1187
1188     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
1189     {
1190         LPICONMETRICSA lpIcon = pvParam;
1191         if(lpIcon && lpIcon->cbSize == sizeof(*lpIcon))
1192         {
1193             SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0,
1194                                    &lpIcon->iHorzSpacing, FALSE );
1195             SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0,
1196                                    &lpIcon->iVertSpacing, FALSE );
1197             SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0,
1198                                    &lpIcon->iTitleWrap, FALSE );
1199             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1200                                    &lpIcon->lfFont, FALSE );
1201         }
1202         else
1203         {
1204             ret = FALSE;
1205         }
1206         break;
1207     }
1208     WINE_SPI_FIXME(SPI_SETICONMETRICS);         /*     46  WINVER >= 0x400 */
1209
1210     case SPI_SETWORKAREA:                       /*     47  WINVER >= 0x400 */
1211     {
1212         char buf[20];
1213         RECT *pr = (RECT *) pvParam;
1214
1215         spi_idx = SPI_SETWORKAREA_IDX;
1216         sprintf(buf, "%d %d %d %d",
1217                 pr->left, pr->top,
1218                 pr->right, pr->bottom );
1219
1220         if (SYSPARAMS_Save( SPI_SETWORKAREA_REGKEY,
1221                             SPI_SETWORKAREA_VALNAME,
1222                             buf, fWinIni ))
1223         {
1224             CopyRect( &work_area, (RECT *)pvParam );
1225             spi_loaded[spi_idx] = TRUE;
1226         }
1227         else
1228             ret = FALSE;
1229         break;
1230     }
1231
1232     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1233       spi_idx = SPI_SETWORKAREA_IDX;
1234       if (!spi_loaded[spi_idx])
1235       {
1236           char buf[20];
1237
1238           SetRect( &work_area, 0, 0,
1239                    GetSystemMetrics( SM_CXSCREEN ),
1240                    GetSystemMetrics( SM_CYSCREEN ) );
1241           
1242           if (SYSPARAMS_Load( SPI_SETWORKAREA_REGKEY,
1243                               SPI_SETWORKAREA_VALNAME,
1244                               buf ))
1245           {
1246               sscanf( buf, "%d %d %d %d",
1247                       &work_area.left, &work_area.top,
1248                       &work_area.right, &work_area.bottom );
1249           }
1250           spi_loaded[spi_idx] = TRUE;
1251       }
1252       CopyRect( (RECT *)pvParam, &work_area );
1253
1254       break;
1255
1256     WINE_SPI_FIXME(SPI_SETPENWINDOWS);          /*     49  WINVER >= 0x400 */
1257
1258     WINE_SPI_FIXME(SPI_GETFILTERKEYS);          /*     50 */
1259     WINE_SPI_FIXME(SPI_SETFILTERKEYS);          /*     51 */
1260     WINE_SPI_FIXME(SPI_GETTOGGLEKEYS);          /*     52 */
1261     WINE_SPI_FIXME(SPI_SETTOGGLEKEYS);          /*     53 */
1262     WINE_SPI_FIXME(SPI_GETMOUSEKEYS);           /*     54 */
1263     WINE_SPI_FIXME(SPI_SETMOUSEKEYS);           /*     55 */
1264     case SPI_GETSHOWSOUNDS:                     /*     56 */
1265         spi_idx = SPI_SETSHOWSOUNDS_IDX;
1266
1267         if (!spi_loaded[spi_idx])
1268         {
1269             char buf[10];
1270             
1271             if (SYSPARAMS_Load( SPI_SETSHOWSOUNDS_REGKEY,
1272                                 SPI_SETSHOWSOUNDS_VALNAME, buf ))
1273             {
1274                 SYSMETRICS_Set( SM_SHOWSOUNDS, atoi( buf ) );
1275             }
1276             spi_loaded[spi_idx] = TRUE;
1277         }
1278         
1279
1280         *(INT *)pvParam = GetSystemMetrics( SM_SHOWSOUNDS );
1281         break;
1282
1283     case SPI_SETSHOWSOUNDS:                     /*     57 */
1284     {
1285         char buf[10];
1286         spi_idx = SPI_SETSHOWSOUNDS_IDX;
1287
1288         sprintf(buf, "%u", uiParam);
1289         if (SYSPARAMS_Save( SPI_SETSHOWSOUNDS_REGKEY,
1290                             SPI_SETSHOWSOUNDS_VALNAME,
1291                             buf, fWinIni ))
1292         {
1293             SYSMETRICS_Set( SM_SHOWSOUNDS, uiParam );
1294             spi_loaded[spi_idx] = TRUE;
1295         }
1296         else
1297             ret = FALSE;
1298         break;
1299     }
1300     WINE_SPI_FIXME(SPI_GETSTICKYKEYS);          /*     58 */
1301     WINE_SPI_FIXME(SPI_SETSTICKYKEYS);          /*     59 */
1302     WINE_SPI_FIXME(SPI_GETACCESSTIMEOUT);       /*     60 */
1303     WINE_SPI_FIXME(SPI_SETACCESSTIMEOUT);       /*     61 */
1304
1305     WINE_SPI_FIXME(SPI_GETSERIALKEYS);          /*     62  WINVER >= 0x400 */
1306     WINE_SPI_FIXME(SPI_SETSERIALKEYS);          /*     63  WINVER >= 0x400 */
1307
1308     WINE_SPI_FIXME(SPI_GETSOUNDSENTRY);         /*     64 */
1309     WINE_SPI_FIXME(SPI_SETSOUNDSENTRY);         /*     65 */
1310     
1311     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1312     {
1313         LPHIGHCONTRASTA lpHighContrastA = (LPHIGHCONTRASTA)pvParam;
1314         WARN("SPI_GETHIGHCONTRAST not fully implemented\n");
1315         if (lpHighContrastA->cbSize == sizeof(HIGHCONTRASTA))
1316         {
1317             /* Indicate that there is no high contrast available */
1318             lpHighContrastA->dwFlags = 0;
1319             lpHighContrastA->lpszDefaultScheme = NULL;
1320         }
1321         else
1322         {
1323             ret = FALSE;
1324         }
1325         break;
1326     }
1327     WINE_SPI_FIXME(SPI_SETHIGHCONTRAST);        /*     67  WINVER >= 0x400 */
1328
1329     WINE_SPI_FIXME(SPI_GETKEYBOARDPREF);        /*     68  WINVER >= 0x400 */
1330     WINE_SPI_FIXME(SPI_SETKEYBOARDPREF);        /*     69  WINVER >= 0x400 */
1331
1332     case SPI_GETSCREENREADER:
1333     {
1334        LPBOOL   bool = (LPBOOL)pvParam;
1335        *bool = FALSE;
1336        break;
1337     }
1338
1339     WINE_SPI_FIXME(SPI_SETSCREENREADER);        /*     71  WINVER >= 0x400 */
1340
1341     case SPI_GETANIMATION:                      /*     72  WINVER >= 0x400 */
1342     {
1343         LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)pvParam;
1344  
1345         /* Tell it "disabled" */
1346         if (lpAnimInfo->cbSize == sizeof(ANIMATIONINFO))
1347             lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
1348         else
1349             ret = FALSE;
1350         break;
1351     }
1352     WINE_SPI_WARN(SPI_SETANIMATION);            /*     73  WINVER >= 0x400 */
1353
1354     WINE_SPI_FIXME(SPI_GETFONTSMOOTHING);       /*     74  WINVER >= 0x400 */
1355     WINE_SPI_FIXME(SPI_SETFONTSMOOTHING);       /*     75  WINVER >= 0x400 */
1356
1357     WINE_SPI_FIXME(SPI_SETDRAGWIDTH);           /*     76  WINVER >= 0x400 */
1358     WINE_SPI_FIXME(SPI_SETDRAGHEIGHT);          /*     77  WINVER >= 0x400 */
1359
1360     WINE_SPI_FIXME(SPI_SETHANDHELD);            /*     78  WINVER >= 0x400 */
1361
1362     WINE_SPI_FIXME(SPI_GETLOWPOWERTIMEOUT);     /*     79  WINVER >= 0x400 */
1363     WINE_SPI_FIXME(SPI_GETPOWEROFFTIMEOUT);     /*     80  WINVER >= 0x400 */
1364     WINE_SPI_FIXME(SPI_SETLOWPOWERTIMEOUT);     /*     81  WINVER >= 0x400 */
1365     WINE_SPI_FIXME(SPI_SETPOWEROFFTIMEOUT);     /*     82  WINVER >= 0x400 */
1366     WINE_SPI_FIXME(SPI_GETLOWPOWERACTIVE);      /*     83  WINVER >= 0x400 */
1367     WINE_SPI_FIXME(SPI_GETPOWEROFFACTIVE);      /*     84  WINVER >= 0x400 */
1368     WINE_SPI_FIXME(SPI_SETLOWPOWERACTIVE);      /*     85  WINVER >= 0x400 */
1369     WINE_SPI_FIXME(SPI_SETPOWEROFFACTIVE);      /*     86  WINVER >= 0x400 */
1370     
1371     WINE_SPI_FIXME(SPI_SETCURSORS);             /*     87  WINVER >= 0x400 */
1372     WINE_SPI_FIXME(SPI_SETICONS);               /*     88  WINVER >= 0x400 */
1373
1374     WINE_SPI_FIXME(SPI_GETDEFAULTINPUTLANG);    /*     89  WINVER >= 0x400 */
1375     WINE_SPI_FIXME(SPI_SETDEFAULTINPUTLANG);    /*     90  WINVER >= 0x400 */
1376
1377     WINE_SPI_FIXME(SPI_SETLANGTOGGLE);          /*     91  WINVER >= 0x400 */
1378
1379     case SPI_GETWINDOWSEXTENSION:               /*     92  WINVER >= 0x400 */
1380         WARN("pretend no support for Win9x Plus! for now.\n");
1381         ret = FALSE; /* yes, this is the result value */
1382         break;
1383
1384     WINE_SPI_FIXME(SPI_SETMOUSETRAILS);         /*     93  WINVER >= 0x400 */
1385     WINE_SPI_FIXME(SPI_GETMOUSETRAILS);         /*     94  WINVER >= 0x400 */
1386         
1387     case SPI_SETSCREENSAVERRUNNING:             /*     97  WINVER >= 0x400 */
1388         {
1389         /* SPI_SCREENSAVERRUNNING is an alias for SPI_SETSCREENSAVERRUNNING */
1390         char buf[5];
1391
1392         spi_idx = SPI_SETSCREENSAVERRUNNING_IDX;
1393         sprintf(buf, "%u", uiParam);
1394
1395         /* save only temporarily */
1396         if (SYSPARAMS_Save( SPI_SETSCREENSAVERRUNNING_REGKEY,
1397                             SPI_SETSCREENSAVERRUNNING_VALNAME,
1398                             buf, 0 ))
1399         {
1400             screensaver_running = uiParam;
1401             spi_loaded[spi_idx] = TRUE;
1402         }
1403         else
1404             ret = FALSE;
1405         break;
1406     }
1407
1408     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1409         *(UINT *)pvParam = 4;
1410         break;
1411     WINE_SPI_FIXME(SPI_SETMOUSEHOVERWIDTH);     /*     99  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1412
1413     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1414         *(UINT *)pvParam = 4;
1415         break;
1416     WINE_SPI_FIXME(SPI_SETMOUSEHOVERHEIGHT);    /*    101  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1417
1418     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1419         *(UINT *)pvParam = 400; /* default for menu dropdowns */
1420         break;
1421     WINE_SPI_FIXME(SPI_SETMOUSEHOVERTIME);      /*    103  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1422               
1423     case SPI_GETWHEELSCROLLLINES:               /*    104  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1424         *(UINT *)pvParam = 3; /* default for num scroll lines */  
1425         break;
1426
1427     WINE_SPI_FIXME(SPI_SETWHEELSCROLLLINES);    /*    105  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1428
1429     case SPI_GETMENUSHOWDELAY:                  /*    106  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1430         *(UINT *)pvParam = 400; /* Tested against Windows NT 4.0 and Windows 2000 */
1431         break;
1432
1433     WINE_SPI_FIXME(SPI_GETSHOWIMEUI);           /*    110  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1434     WINE_SPI_FIXME(SPI_SETSHOWIMEUI);           /*    111  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1435
1436     case SPI_GETSCREENSAVERRUNNING:             /*    114  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1437         spi_idx = SPI_SETSCREENSAVERRUNNING_IDX;
1438         if (!spi_loaded[spi_idx])
1439         {
1440             char buf[5];
1441             
1442             if (SYSPARAMS_Load( SPI_SETSCREENSAVERRUNNING_REGKEY,
1443                                 SPI_SETSCREENSAVERRUNNING_VALNAME, buf ))
1444                 screensaver_running  = atoi( buf );
1445             spi_loaded[spi_idx] = TRUE;
1446         }
1447         
1448         *(BOOL *)pvParam = screensaver_running;
1449         break;
1450
1451     default:
1452         FIXME( "Unknown action: %u\n", uiAction );
1453         SetLastError( ERROR_INVALID_SPI_VALUE );
1454         ret = FALSE;
1455         break;
1456     }
1457
1458     if (ret)
1459         SYSPARAMS_NotifyChange( uiAction, fWinIni );
1460     return ret;
1461     
1462 #undef WINE_SPI_FIXME
1463 #undef WINE_SPI_WARN
1464 }
1465
1466
1467 /***********************************************************************
1468  *              SystemParametersInfo (USER.483)
1469  */
1470 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
1471                                       LPVOID lpvParam, UINT16 fuWinIni )
1472 {
1473     BOOL16 ret;
1474
1475     TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
1476     
1477     switch (uAction)
1478     {
1479     case SPI_GETBEEP:                           /*      1 */
1480     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
1481     case SPI_GETICONTITLEWRAP:                  /*     25 */
1482     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
1483     case SPI_GETFASTTASKSWITCH:                 /*     35 */
1484     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
1485     {
1486         BOOL tmp;
1487         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1488         if (ret && lpvParam)
1489             *(BOOL16 *)lpvParam = tmp;
1490         break;
1491     }
1492
1493     case SPI_GETBORDER:                         /*      5 */
1494     case SPI_ICONHORIZONTALSPACING:             /*     13 */
1495     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
1496     case SPI_GETGRIDGRANULARITY:                /*     18 */
1497     case SPI_GETKEYBOARDDELAY:                  /*     22 */
1498     case SPI_ICONVERTICALSPACING:               /*     24 */
1499     {
1500         INT tmp;
1501         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1502         if (ret && lpvParam)
1503             *(INT16 *)lpvParam = tmp;
1504         break;
1505     }
1506
1507     case SPI_GETKEYBOARDSPEED:                  /*     10 */
1508     {
1509         DWORD tmp;
1510         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1511         if (ret && lpvParam)
1512             *(WORD *)lpvParam = tmp;
1513         break;
1514     }
1515
1516     case SPI_GETICONTITLELOGFONT:               /*     31 */
1517     {
1518         LOGFONTA tmp;
1519         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1520         if (ret && lpvParam)
1521             SYSPARAMS_LogFont32ATo16( &tmp, (LPLOGFONT16)lpvParam );
1522         break;
1523     }
1524
1525     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1526     {
1527         NONCLIENTMETRICSA tmp;
1528         LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
1529         if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
1530         {
1531             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
1532             ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
1533             if (ret)
1534                 SYSPARAMS_NonClientMetrics32ATo16( &tmp, lpnm16 );
1535         }
1536         else /* winfile 95 sets cbSize to 340 */
1537             ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1538         break;
1539     }
1540     
1541     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1542     {
1543         RECT tmp;
1544         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1545         if (ret && lpvParam)
1546             CONV_RECT32TO16( &tmp, (RECT16 *)lpvParam );
1547         break;
1548     }
1549         
1550     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1551     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1552     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1553     {
1554         UINT tmp;
1555         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1556         if (ret && lpvParam)
1557             *(UINT16 *)lpvParam = tmp;
1558         break;
1559     }
1560
1561     default:
1562         ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1563     }
1564
1565     return ret;
1566 }
1567
1568 /***********************************************************************
1569  *              SystemParametersInfoW (USER32.@)
1570  */
1571 BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam,
1572                                    PVOID pvParam, UINT fuWinIni )
1573 {
1574     BOOL ret;
1575
1576     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
1577     
1578     switch (uiAction)
1579     {
1580     case SPI_SETDESKWALLPAPER:                  /*     20 */
1581     case SPI_SETDESKPATTERN:                    /*     21 */
1582     {
1583         char buffer[256];
1584         if (pvParam)
1585             if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)pvParam, -1,
1586                                       buffer, sizeof(buffer), NULL, NULL ))
1587                 buffer[sizeof(buffer)-1] = 0;
1588         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
1589         break;
1590     }
1591
1592     case SPI_GETICONTITLELOGFONT:               /*     31 */
1593     {
1594         LOGFONTA tmp;
1595         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
1596         if (ret && pvParam)
1597             SYSPARAMS_LogFont32ATo32W( &tmp, (LPLOGFONTW)pvParam );
1598         break;
1599     }
1600
1601     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1602     {
1603         NONCLIENTMETRICSA tmp;
1604         LPNONCLIENTMETRICSW lpnmW = (LPNONCLIENTMETRICSW)pvParam;
1605         if (lpnmW && lpnmW->cbSize == sizeof(NONCLIENTMETRICSW))
1606         {
1607             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
1608             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1609             if (ret)
1610                 SYSPARAMS_NonClientMetrics32ATo32W( &tmp, lpnmW );
1611         }
1612         else
1613             ret = FALSE;
1614         break;
1615     }
1616
1617     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
1618     {
1619         ICONMETRICSA tmp;
1620         LPICONMETRICSW lpimW = (LPICONMETRICSW)pvParam;
1621         if (lpimW && lpimW->cbSize == sizeof(ICONMETRICSW))
1622         {
1623             tmp.cbSize = sizeof(ICONMETRICSA);
1624             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1625             if (ret)
1626             {
1627                 lpimW->iHorzSpacing = tmp.iHorzSpacing;
1628                 lpimW->iVertSpacing = tmp.iVertSpacing;
1629                 lpimW->iTitleWrap   = tmp.iTitleWrap;
1630                 SYSPARAMS_LogFont32ATo32W( &tmp.lfFont, &lpimW->lfFont );
1631             }
1632         }
1633         else
1634             ret = FALSE;
1635         break;
1636     }
1637
1638     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1639     {
1640         HIGHCONTRASTA tmp;
1641         LPHIGHCONTRASTW lphcW = (LPHIGHCONTRASTW)pvParam;
1642         if (lphcW && lphcW->cbSize == sizeof(HIGHCONTRASTW))
1643         {
1644             tmp.cbSize = sizeof(HIGHCONTRASTA);
1645             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1646             if (ret)
1647             {
1648                 lphcW->dwFlags = tmp.dwFlags;
1649                 lphcW->lpszDefaultScheme = NULL;  /* FIXME? */
1650             }
1651         }
1652         else
1653             ret = FALSE;
1654         break;
1655     }
1656     
1657     default:
1658         ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fuWinIni );
1659         break;
1660     }
1661     return ret;
1662 }
1663
1664
1665 /**********************************************************************
1666  *              SetDoubleClickTime (USER32.@)
1667  */
1668 BOOL WINAPI SetDoubleClickTime( UINT interval )
1669 {
1670     return SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
1671 }
1672
1673
1674 /**********************************************************************
1675  *              GetDoubleClickTime (USER32.@)
1676  */
1677 UINT WINAPI GetDoubleClickTime(void)
1678 {
1679     char buf[10];
1680
1681     if (!spi_loaded[SPI_SETDOUBLECLICKTIME_IDX])
1682     {
1683         if (SYSPARAMS_Load( SPI_SETDOUBLECLICKTIME_REGKEY,
1684                             SPI_SETDOUBLECLICKTIME_VALNAME,
1685                             buf ))
1686         {
1687             double_click_time = atoi( buf );
1688             if (!double_click_time) double_click_time = 500;
1689         }
1690         spi_loaded[SPI_SETDOUBLECLICKTIME_IDX] = TRUE;
1691     }
1692     return double_click_time;
1693 }