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