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