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