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