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