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