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