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