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