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