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