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