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