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