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