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