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