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