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