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