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