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