~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/user32/sysparams.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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