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