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