~ [ 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         FIXME( "Unimplemented action: %u (%s)\n", x, #x ); \
1190         SetLastError( ERROR_INVALID_SPI_VALUE ); \
1191         ret = FALSE; \
1192         break
1193 #define WINE_SPI_WARN(x) \
1194     case x: \
1195         WARN( "Ignored action: %u (%s)\n", x, #x ); \
1196         break
1197 
1198     BOOL ret = TRUE;
1199     unsigned spi_idx = 0;
1200 
1201     switch (uiAction)
1202     {
1203     case SPI_GETBEEP:                           /*      1 */
1204         if (!pvParam) return FALSE;
1205 
1206         spi_idx = SPI_SETBEEP_IDX;
1207         if (!spi_loaded[spi_idx])
1208         {
1209             WCHAR buf[5];
1210 
1211             if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf, sizeof(buf) ))
1212                 beep_active  = !lstrcmpiW( Yes, buf );
1213             spi_loaded[spi_idx] = TRUE;
1214         }
1215 
1216         *(BOOL *)pvParam = beep_active;
1217         break;
1218 
1219     case SPI_SETBEEP:                           /*      2 */
1220         spi_idx = SPI_SETBEEP_IDX;
1221         if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
1222                             (uiParam ? Yes : No), fWinIni ))
1223         {
1224             beep_active = uiParam;
1225             spi_loaded[spi_idx] = TRUE;
1226         }
1227         else
1228             ret = FALSE;
1229         break;
1230 
1231     case SPI_GETMOUSE:                          /*      3 */
1232         if (!pvParam) return FALSE;
1233 
1234         spi_idx = SPI_SETMOUSE_IDX;
1235         if (!spi_loaded[spi_idx])
1236         {
1237             WCHAR buf[12];
1238 
1239             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
1240                                 buf, sizeof(buf) ))
1241                 mouse_threshold1 = atoiW( buf );
1242             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
1243                                 buf, sizeof(buf) ))
1244                 mouse_threshold2 = atoiW( buf );
1245             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
1246                                 buf, sizeof(buf) ))
1247                 mouse_speed = atoiW( buf );
1248             spi_loaded[spi_idx] = TRUE;
1249         }
1250         ((INT *)pvParam)[0] = mouse_threshold1;
1251         ((INT *)pvParam)[1] = mouse_threshold2;
1252         ((INT *)pvParam)[2] = mouse_speed;
1253         break;
1254 
1255     case SPI_SETMOUSE:                          /*      4 */
1256     {
1257         if (!pvParam) return FALSE;
1258         ret = set_int_param( SPI_SETMOUSE_IDX, SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
1259                              &mouse_threshold1, ((INT *)pvParam)[0], fWinIni);
1260         if( ret) {
1261             save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
1262                             &mouse_threshold2, ((INT *)pvParam)[1], fWinIni);
1263             save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
1264                             &mouse_speed, ((INT *)pvParam)[2], fWinIni);
1265         }
1266         break;
1267     }
1268 
1269     case SPI_GETBORDER:
1270         ret = get_twips_param( SPI_SETBORDER_IDX,
1271                                SPI_SETBORDER_REGKEY,
1272                                SPI_SETBORDER_VALNAME,
1273                                &border, pvParam );
1274         if( *(INT*)pvParam < 1) *(INT*)pvParam = 1; 
1275         break;
1276 
1277     case SPI_SETBORDER:
1278         nonclient_metrics.iBorderWidth = uiParam > 0 ? uiParam : 1;
1279         /* raw value goes to registry */
1280         ret = set_uint_param( SPI_SETBORDER_IDX,
1281                               SPI_SETBORDER_REGKEY,
1282                               SPI_SETBORDER_VALNAME,
1283                               &border, uiParam, fWinIni );
1284         break;
1285 
1286     case SPI_GETKEYBOARDSPEED:
1287         ret = get_uint_param( SPI_SETKEYBOARDSPEED_IDX,
1288                               SPI_SETKEYBOARDSPEED_REGKEY,
1289                               SPI_SETKEYBOARDSPEED_VALNAME,
1290                               &keyboard_speed, pvParam );
1291         break;
1292 
1293     case SPI_SETKEYBOARDSPEED:
1294         if (uiParam > 31) uiParam = 31;
1295         ret = set_uint_param( SPI_SETKEYBOARDSPEED_IDX,
1296                               SPI_SETKEYBOARDSPEED_REGKEY,
1297                               SPI_SETKEYBOARDSPEED_VALNAME,
1298                               &keyboard_speed, uiParam, fWinIni );
1299         break;
1300 
1301     /* not implemented in Windows */
1302     WINE_SPI_WARN(SPI_LANGDRIVER);              /*     12 */
1303 
1304     case SPI_ICONHORIZONTALSPACING:
1305         if (pvParam != NULL)
1306         {
1307             ret = get_twips_param( SPI_ICONHORIZONTALSPACING_IDX,
1308                                    SPI_ICONHORIZONTALSPACING_REGKEY,
1309                                    SPI_ICONHORIZONTALSPACING_VALNAME,
1310                                    (UINT*)&icon_metrics.iHorzSpacing, pvParam );
1311         }
1312         else
1313         {
1314             if (uiParam < 32) uiParam = 32;
1315             ret = set_uint_param( SPI_ICONHORIZONTALSPACING_IDX,
1316                                   SPI_ICONHORIZONTALSPACING_REGKEY,
1317                                   SPI_ICONHORIZONTALSPACING_VALNAME,
1318                                   (UINT*)&icon_metrics.iHorzSpacing, uiParam, fWinIni );
1319         }
1320         break;
1321 
1322     case SPI_GETSCREENSAVETIMEOUT:
1323         ret = get_uint_param( SPI_SETSCREENSAVETIMEOUT_IDX,
1324                               SPI_SETSCREENSAVETIMEOUT_REGKEY,
1325                               SPI_SETSCREENSAVETIMEOUT_VALNAME,
1326                               &screensave_timeout, pvParam );
1327         break;
1328 
1329     case SPI_SETSCREENSAVETIMEOUT:
1330         ret = set_uint_param( SPI_SETSCREENSAVETIMEOUT_IDX,
1331                               SPI_SETSCREENSAVETIMEOUT_REGKEY,
1332                               SPI_SETSCREENSAVETIMEOUT_VALNAME,
1333                               &screensave_timeout, uiParam, fWinIni );
1334         break;
1335 
1336     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
1337         if (!pvParam) return FALSE;
1338         *(BOOL *)pvParam = USER_Driver->pGetScreenSaveActive();
1339         break;
1340 
1341     case SPI_SETSCREENSAVEACTIVE:               /*     17 */
1342     {
1343         WCHAR buf[12];
1344 
1345         wsprintfW(buf, CSu, uiParam);
1346         USER_Driver->pSetScreenSaveActive( uiParam );
1347         /* saved value does not affect Wine */
1348         SYSPARAMS_Save( SPI_SETSCREENSAVEACTIVE_REGKEY,
1349                         SPI_SETSCREENSAVEACTIVE_VALNAME,
1350                         buf, fWinIni );
1351         break;
1352     }
1353 
1354     case SPI_GETGRIDGRANULARITY:
1355         ret = get_uint_param( SPI_SETGRIDGRANULARITY_IDX,
1356                               SPI_SETGRIDGRANULARITY_REGKEY,
1357                               SPI_SETGRIDGRANULARITY_VALNAME,
1358                               &grid_granularity, pvParam );
1359         break;
1360 
1361     case SPI_SETGRIDGRANULARITY:
1362         ret = set_uint_param( SPI_SETGRIDGRANULARITY_IDX,
1363                               SPI_SETGRIDGRANULARITY_REGKEY,
1364                               SPI_SETGRIDGRANULARITY_VALNAME,
1365                               &grid_granularity, uiParam, fWinIni );
1366         break;
1367 
1368     case SPI_SETDESKWALLPAPER:                  /*     20 */
1369         if (!pvParam || !SetDeskWallPaper( (LPSTR)pvParam )) return FALSE;
1370         SYSPARAMS_Save(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, pvParam, fWinIni);
1371         break;
1372         
1373     case SPI_SETDESKPATTERN:                    /*     21 */
1374         /* FIXME: the ability to specify a pattern in pvParam
1375            doesn't seem to be documented for Win32 */
1376         if ((INT16)uiParam == -1)
1377         {
1378             WCHAR buf[256];
1379             GetProfileStringW( Desktop, Pattern,
1380                                defPattern,
1381                                buf, sizeof(buf)/sizeof(WCHAR) );
1382             ret = DESKTOP_SetPattern( buf );
1383         } else
1384             ret = DESKTOP_SetPattern( (LPWSTR)pvParam );
1385         break;
1386 
1387     case SPI_GETKEYBOARDDELAY:
1388         ret = get_uint_param( SPI_SETKEYBOARDDELAY_IDX,
1389                               SPI_SETKEYBOARDDELAY_REGKEY,
1390                               SPI_SETKEYBOARDDELAY_VALNAME,
1391                               &keyboard_delay, pvParam );
1392         break;
1393 
1394     case SPI_SETKEYBOARDDELAY:
1395         ret = set_uint_param( SPI_SETKEYBOARDDELAY_IDX,
1396                               SPI_SETKEYBOARDDELAY_REGKEY,
1397                               SPI_SETKEYBOARDDELAY_VALNAME,
1398                               &keyboard_delay, uiParam, fWinIni );
1399         break;
1400 
1401     case SPI_ICONVERTICALSPACING:
1402         if (pvParam != NULL)
1403         {
1404             ret = get_twips_param( SPI_ICONVERTICALSPACING_IDX,
1405                                    SPI_ICONVERTICALSPACING_REGKEY,
1406                                    SPI_ICONVERTICALSPACING_VALNAME,
1407                                    (UINT*)&icon_metrics.iVertSpacing, pvParam );
1408             if( icon_metrics.iVertSpacing < 32) 
1409                 icon_metrics.iVertSpacing = 32;
1410         }
1411         else
1412         {
1413             if (uiParam < 32) uiParam = 32;
1414             ret = set_uint_param( SPI_ICONVERTICALSPACING_IDX,
1415                                   SPI_ICONVERTICALSPACING_REGKEY,
1416                                   SPI_ICONVERTICALSPACING_VALNAME,
1417                                   (UINT*)&icon_metrics.iVertSpacing, uiParam, fWinIni );
1418         }
1419         break;
1420 
1421     case SPI_GETICONTITLEWRAP:
1422         ret = get_bool_param( SPI_SETICONTITLEWRAP_IDX,
1423                               SPI_SETICONTITLEWRAP_REGKEY1,
1424                               SPI_SETICONTITLEWRAP_VALNAME,
1425                               &icon_metrics.iTitleWrap, pvParam );
1426         break;
1427 
1428     case SPI_SETICONTITLEWRAP:
1429         ret = set_bool_param_mirrored( SPI_SETICONTITLEWRAP_IDX,
1430                                        SPI_SETICONTITLEWRAP_REGKEY1,
1431                                        SPI_SETICONTITLEWRAP_REGKEY2,
1432                                        SPI_SETICONTITLEWRAP_VALNAME,
1433                                        &icon_metrics.iTitleWrap, uiParam, fWinIni );
1434         break;
1435 
1436     case SPI_GETMENUDROPALIGNMENT:
1437         ret = get_uint_param( SPI_SETMENUDROPALIGNMENT_IDX,
1438                               SPI_SETMENUDROPALIGNMENT_REGKEY1,
1439                               SPI_SETMENUDROPALIGNMENT_VALNAME,
1440                               &menu_drop_alignment, pvParam );
1441         break;
1442 
1443     case SPI_SETMENUDROPALIGNMENT:
1444         ret = set_uint_param_mirrored( SPI_SETMENUDROPALIGNMENT_IDX,
1445                                        SPI_SETMENUDROPALIGNMENT_REGKEY1,
1446                                        SPI_SETMENUDROPALIGNMENT_REGKEY2,
1447                                        SPI_SETMENUDROPALIGNMENT_VALNAME,
1448                                        &menu_drop_alignment, uiParam, fWinIni );
1449         break;
1450 
1451     case SPI_SETDOUBLECLKWIDTH:
1452         ret = set_uint_param_mirrored( SPI_SETDOUBLECLKWIDTH_IDX,
1453                                        SPI_SETDOUBLECLKWIDTH_REGKEY1,
1454                                        SPI_SETDOUBLECLKWIDTH_REGKEY2,
1455                                        SPI_SETDOUBLECLKWIDTH_VALNAME,
1456                                        &double_click_width, uiParam, fWinIni );
1457         break;
1458 
1459     case SPI_SETDOUBLECLKHEIGHT:
1460         ret = set_uint_param_mirrored( SPI_SETDOUBLECLKHEIGHT_IDX,
1461                                        SPI_SETDOUBLECLKHEIGHT_REGKEY1,
1462                                        SPI_SETDOUBLECLKHEIGHT_REGKEY2,
1463                                        SPI_SETDOUBLECLKHEIGHT_VALNAME,
1464                                        &double_click_height, uiParam, fWinIni );
1465         break;
1466 
1467     case SPI_GETICONTITLELOGFONT:
1468     {
1469         LOGFONTW lfDefault;
1470 
1471         if (!pvParam) return FALSE;
1472 
1473         spi_idx = SPI_SETICONTITLELOGFONT_IDX;
1474         if (!spi_loaded[spi_idx])
1475         {
1476             if (!reg_get_logfont( SPI_SETICONTITLELOGFONT_REGKEY,
1477                                   SPI_SETICONTITLELOGFONT_VALNAME, &icon_metrics.lfFont ))
1478             {
1479                 INT r;
1480 
1481                 /*
1482                  * The 'default GDI fonts' seems to be returned.
1483                  * If a returned font is not a correct font in your environment,
1484                  * please try to fix objects/gdiobj.c at first.
1485                  */
1486                 GetObjectW( GetStockObject( DEFAULT_GUI_FONT ), sizeof(LOGFONTW), &lfDefault );
1487 
1488                 GetProfileStringW( Desktop, IconTitleFaceName,
1489                                    lfDefault.lfFaceName,
1490                                    icon_metrics.lfFont.lfFaceName,
1491                                    LF_FACESIZE );
1492                 
1493                 r = GetProfileIntW( Desktop, IconTitleSize, 0 );
1494                 if (r)
1495                     icon_metrics.lfFont.lfHeight = -r;
1496                 else
1497                     icon_metrics.lfFont.lfHeight = lfDefault.lfHeight;
1498 
1499                 icon_metrics.lfFont.lfWidth = 0;
1500                 icon_metrics.lfFont.lfEscapement = icon_metrics.lfFont.lfOrientation = 0;
1501                 icon_metrics.lfFont.lfWeight = FW_NORMAL;
1502                 icon_metrics.lfFont.lfItalic = FALSE;
1503                 icon_metrics.lfFont.lfStrikeOut = FALSE;
1504                 icon_metrics.lfFont.lfUnderline = FALSE;
1505                 icon_metrics.lfFont.lfCharSet = lfDefault.lfCharSet; /* at least 'charset' should not be hard-coded */
1506                 icon_metrics.lfFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
1507                 icon_metrics.lfFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1508                 icon_metrics.lfFont.lfQuality = DEFAULT_QUALITY;
1509                 icon_metrics.lfFont.lfPitchAndFamily = DEFAULT_PITCH;
1510                 spi_loaded[spi_idx] = TRUE;
1511             }
1512         }
1513         *(LOGFONTW *)pvParam = icon_metrics.lfFont;
1514         break;
1515     }
1516 
1517     case SPI_SETDOUBLECLICKTIME:
1518         ret = set_uint_param( SPI_SETDOUBLECLICKTIME_IDX,
1519                               SPI_SETDOUBLECLICKTIME_REGKEY,
1520                               SPI_SETDOUBLECLICKTIME_VALNAME,
1521                               &double_click_time, uiParam, fWinIni );
1522         break;
1523 
1524     case SPI_SETMOUSEBUTTONSWAP:
1525         ret = set_bool_param( SPI_SETMOUSEBUTTONSWAP_IDX,
1526                               SPI_SETMOUSEBUTTONSWAP_REGKEY,
1527                               SPI_SETMOUSEBUTTONSWAP_VALNAME,
1528                               &swap_buttons, uiParam, fWinIni );
1529         break;
1530 
1531     case SPI_SETICONTITLELOGFONT:               /*     34 */
1532         if( uiParam == sizeof(LOGFONTW)) {
1533             ret = SYSPARAMS_SaveLogFont( SPI_SETICONTITLELOGFONT_REGKEY,
1534                     SPI_SETICONTITLELOGFONT_VALNAME, (LOGFONTW *)pvParam, fWinIni);
1535             if( ret) {
1536                 icon_metrics.lfFont = *(LOGFONTW *)pvParam;
1537                 spi_loaded[SPI_SETICONTITLELOGFONT_IDX] = TRUE;
1538             }
1539         } else
1540             ret = FALSE;
1541         break;
1542 
1543     case SPI_GETFASTTASKSWITCH:                 /*     35 */
1544         if (!pvParam) return FALSE;
1545         *(BOOL *)pvParam = 1;
1546         break;
1547 
1548     case SPI_SETFASTTASKSWITCH:                 /*     36 */
1549         /* the action is disabled */
1550         ret = FALSE;
1551         break;
1552 
1553     case SPI_SETDRAGFULLWINDOWS:
1554         ret = set_bool_param( SPI_SETDRAGFULLWINDOWS_IDX,
1555                               SPI_SETDRAGFULLWINDOWS_REGKEY,
1556                               SPI_SETDRAGFULLWINDOWS_VALNAME,
1557                               &drag_full_windows, uiParam, fWinIni );
1558         break;
1559 
1560     case SPI_GETDRAGFULLWINDOWS:
1561         ret = get_bool_param( SPI_SETDRAGFULLWINDOWS_IDX,
1562                               SPI_SETDRAGFULLWINDOWS_REGKEY,
1563                               SPI_SETDRAGFULLWINDOWS_VALNAME,
1564                               &drag_full_windows, pvParam );
1565         break;
1566 
1567     case SPI_GETNONCLIENTMETRICS:
1568     {
1569         LPNONCLIENTMETRICSW lpnm = pvParam;
1570 
1571         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
1572 
1573         if (lpnm && lpnm->cbSize == sizeof(NONCLIENTMETRICSW))
1574             *lpnm = nonclient_metrics;
1575         else
1576             ret = FALSE;
1577         break;
1578     }
1579 
1580     case SPI_SETNONCLIENTMETRICS:
1581     {
1582         LPNONCLIENTMETRICSW lpnm = pvParam;
1583 
1584         if (lpnm && lpnm->cbSize == sizeof(NONCLIENTMETRICSW))
1585         {
1586             NONCLIENTMETRICSW ncm;
1587             ret = set_uint_param( SPI_SETBORDER_IDX,
1588                     SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
1589                     &border, lpnm->iBorderWidth, fWinIni );
1590             if( ret) ret = save_int_param( METRICS_REGKEY,
1591                     METRICS_SCROLLWIDTH_VALNAME, NULL,
1592                     lpnm->iScrollWidth, fWinIni );
1593             if( ret) ret = save_int_param( METRICS_REGKEY,
1594                     METRICS_SCROLLHEIGHT_VALNAME, NULL,
1595                     lpnm->iScrollHeight, fWinIni );
1596             if( ret) ret = save_int_param( METRICS_REGKEY,
1597                     METRICS_CAPTIONWIDTH_VALNAME, NULL,
1598                     lpnm->iCaptionWidth, fWinIni );
1599             if( ret) ret = save_int_param( METRICS_REGKEY,
1600                     METRICS_CAPTIONHEIGHT_VALNAME, NULL,
1601                     lpnm->iCaptionHeight, fWinIni );
1602             if( ret) ret = save_int_param( METRICS_REGKEY,
1603                     METRICS_SMCAPTIONWIDTH_VALNAME, NULL,
1604                     lpnm->iSmCaptionWidth, fWinIni );
1605             if( ret) ret = save_int_param( METRICS_REGKEY,
1606                     METRICS_SMCAPTIONHEIGHT_VALNAME, NULL,
1607                     lpnm->iSmCaptionHeight, fWinIni );
1608             if( ret) ret = save_int_param( METRICS_REGKEY,
1609                     METRICS_MENUWIDTH_VALNAME, NULL,
1610                     lpnm->iMenuWidth, fWinIni );
1611             if( ret) ret = save_int_param( METRICS_REGKEY,
1612                     METRICS_MENUHEIGHT_VALNAME, NULL,
1613                     lpnm->iMenuHeight, fWinIni );
1614             if( ret) ret = SYSPARAMS_SaveLogFont(
1615                     METRICS_REGKEY, METRICS_MENULOGFONT_VALNAME,
1616                     &lpnm->lfMenuFont, fWinIni);
1617             if( ret) ret = SYSPARAMS_SaveLogFont(
1618                     METRICS_REGKEY, METRICS_CAPTIONLOGFONT_VALNAME,
1619                     &lpnm->lfCaptionFont, fWinIni);
1620             if( ret) ret = SYSPARAMS_SaveLogFont(
1621                     METRICS_REGKEY, METRICS_SMCAPTIONLOGFONT_VALNAME,
1622                     &lpnm->lfSmCaptionFont, fWinIni);
1623             if( ret) ret = SYSPARAMS_SaveLogFont(
1624                     METRICS_REGKEY, METRICS_STATUSLOGFONT_VALNAME,
1625                     &lpnm->lfStatusFont, fWinIni);
1626             if( ret) ret = SYSPARAMS_SaveLogFont(
1627                     METRICS_REGKEY, METRICS_MESSAGELOGFONT_VALNAME,
1628                     &lpnm->lfMessageFont, fWinIni);
1629             if( ret) {
1630                 ncm = *lpnm;
1631                 normalize_nonclientmetrics( &ncm);
1632                 nonclient_metrics = ncm;
1633                 spi_loaded[SPI_NONCLIENTMETRICS_IDX] = TRUE;
1634             }
1635         }
1636         break;
1637     }
1638 
1639     case SPI_GETMINIMIZEDMETRICS:
1640     {
1641         MINIMIZEDMETRICS * lpMm = pvParam;
1642         if (lpMm && lpMm->cbSize == sizeof(*lpMm)) {
1643             if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
1644             *lpMm = minimized_metrics;
1645         } else
1646             ret = FALSE;
1647         break;
1648     }
1649 
1650     case SPI_SETMINIMIZEDMETRICS:
1651     {
1652         MINIMIZEDMETRICS * lpMm = pvParam;
1653         if (lpMm && lpMm->cbSize == sizeof(*lpMm)) {
1654             ret = save_int_param( METRICS_REGKEY, METRICS_MINWIDTH_VALNAME,
1655                                   &minimized_metrics.iWidth, max( lpMm->iWidth, 0), fWinIni);
1656             if( ret) ret = save_int_param( METRICS_REGKEY,
1657                                            METRICS_MINHORZGAP_VALNAME, &minimized_metrics.iHorzGap,
1658                                            max( lpMm->iHorzGap, 0), fWinIni);
1659             if( ret) ret = save_int_param( METRICS_REGKEY,
1660                                            METRICS_MINVERTGAP_VALNAME, &minimized_metrics.iVertGap,
1661                                            max( lpMm->iVertGap, 0), fWinIni);
1662             if( ret) ret = save_int_param( METRICS_REGKEY,
1663                                            METRICS_MINARRANGE_VALNAME, &minimized_metrics.iArrange,
1664                                            0x0f & lpMm->iArrange, fWinIni);
1665             if( ret) spi_loaded[SPI_MINIMIZEDMETRICS_IDX] = TRUE;
1666         } else
1667             ret = FALSE;
1668         break;
1669     }
1670 
1671     case SPI_GETICONMETRICS:
1672     {
1673         LPICONMETRICSW lpIcon = pvParam;
1674         if(lpIcon && lpIcon->cbSize == sizeof(*lpIcon))
1675         {
1676             SystemParametersInfoW( SPI_ICONHORIZONTALSPACING, 0,
1677                                    &lpIcon->iHorzSpacing, FALSE );
1678             SystemParametersInfoW( SPI_ICONVERTICALSPACING, 0,
1679                                    &lpIcon->iVertSpacing, FALSE );
1680             SystemParametersInfoW( SPI_GETICONTITLEWRAP, 0,
1681                                    &lpIcon->iTitleWrap, FALSE );
1682             SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0,
1683                                    &lpIcon->lfFont, FALSE );
1684         }
1685         else
1686         {
1687             ret = FALSE;
1688         }
1689         break;
1690     }
1691 
1692     case SPI_SETICONMETRICS:
1693     {
1694         LPICONMETRICSW lpIcon = pvParam;
1695         if (lpIcon && lpIcon->cbSize == sizeof(*lpIcon)) {
1696             ret = set_int_param( SPI_ICONVERTICALSPACING_IDX,
1697                                  SPI_ICONVERTICALSPACING_REGKEY,
1698                                  SPI_ICONVERTICALSPACING_VALNAME,
1699                                  &icon_metrics.iVertSpacing,
1700                                  lpIcon->iVertSpacing, fWinIni);
1701             if( ret) {
1702                 ret = set_int_param( SPI_ICONHORIZONTALSPACING_IDX,
1703                                      SPI_ICONHORIZONTALSPACING_REGKEY,
1704                                      SPI_ICONHORIZONTALSPACING_VALNAME,
1705                                      &icon_metrics.iHorzSpacing,
1706                                      lpIcon->iHorzSpacing, fWinIni );
1707             }
1708             if( ret) {
1709                 ret = set_bool_param_mirrored( SPI_SETICONTITLEWRAP_IDX,
1710                     SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_REGKEY2,
1711                     SPI_SETICONTITLEWRAP_VALNAME, &icon_metrics.iTitleWrap,
1712                     lpIcon->iTitleWrap, fWinIni );
1713             }
1714             if( ret) ret = SYSPARAMS_SaveLogFont( SPI_SETICONTITLELOGFONT_REGKEY,
1715                     SPI_SETICONTITLELOGFONT_VALNAME, &lpIcon->lfFont, fWinIni);
1716             if( ret) {
1717                 icon_metrics.lfFont = lpIcon->lfFont;
1718                 spi_loaded[SPI_SETICONTITLELOGFONT_IDX] = TRUE;
1719             }
1720         } else
1721             ret = FALSE;
1722         break;
1723     }
1724 
1725     case SPI_SETWORKAREA:                       /*     47  WINVER >= 0x400 */
1726     {
1727         if (!pvParam) return FALSE;
1728 
1729         spi_idx = SPI_SETWORKAREA_IDX;
1730         CopyRect( &work_area, (RECT *)pvParam );
1731         spi_loaded[spi_idx] = TRUE;
1732         break;
1733     }
1734 
1735     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1736     {
1737         if (!pvParam) return FALSE;
1738 
1739         spi_idx = SPI_SETWORKAREA_IDX;
1740         if (!spi_loaded[spi_idx])
1741         {
1742             SetRect( &work_area, 0, 0,
1743                      GetSystemMetrics( SM_CXSCREEN ),
1744                      GetSystemMetrics( SM_CYSCREEN ) );
1745             EnumDisplayMonitors( 0, NULL, enum_monitors, (LPARAM)&work_area );
1746             spi_loaded[spi_idx] = TRUE;
1747         }
1748         CopyRect( (RECT *)pvParam, &work_area );
1749         TRACE("work area %s\n", wine_dbgstr_rect( &work_area ));
1750         break;
1751     }
1752 
1753     WINE_SPI_FIXME(SPI_SETPENWINDOWS);          /*     49  WINVER >= 0x400 */
1754 
1755     case SPI_GETFILTERKEYS:                     /*     50 */
1756     {
1757         LPFILTERKEYS lpFilterKeys = (LPFILTERKEYS)pvParam;
1758         WARN("SPI_GETFILTERKEYS not fully implemented\n");
1759         if (lpFilterKeys && lpFilterKeys->cbSize == sizeof(FILTERKEYS))
1760         {
1761             /* Indicate that no FilterKeys feature available */
1762             lpFilterKeys->dwFlags = 0;
1763             lpFilterKeys->iWaitMSec = 0;
1764             lpFilterKeys->iDelayMSec = 0;
1765             lpFilterKeys->iRepeatMSec = 0;
1766             lpFilterKeys->iBounceMSec = 0;
1767          }
1768         else
1769         {
1770             ret = FALSE;
1771         }
1772         break;
1773     }
1774     WINE_SPI_FIXME(SPI_SETFILTERKEYS);          /*     51 */
1775 
1776     case SPI_GETTOGGLEKEYS:                     /*     52 */
1777     {
1778         LPTOGGLEKEYS lpToggleKeys = (LPTOGGLEKEYS)pvParam;
1779         WARN("SPI_GETTOGGLEKEYS not fully implemented\n");
1780         if (lpToggleKeys && lpToggleKeys->cbSize == sizeof(TOGGLEKEYS))
1781         {
1782             /* Indicate that no ToggleKeys feature available */
1783             lpToggleKeys->dwFlags = 0;
1784         }
1785         else
1786         {
1787             ret = FALSE;
1788         }
1789         break;
1790     }
1791     WINE_SPI_FIXME(SPI_SETTOGGLEKEYS);          /*     53 */
1792 
1793     case SPI_GETMOUSEKEYS:                      /*     54 */
1794     {
1795         LPMOUSEKEYS lpMouseKeys = (LPMOUSEKEYS)pvParam;
1796         WARN("SPI_GETMOUSEKEYS not fully implemented\n");
1797         if (lpMouseKeys && lpMouseKeys->cbSize == sizeof(MOUSEKEYS))
1798         {
1799             /* Indicate that no MouseKeys feature available */
1800             lpMouseKeys->dwFlags = 0;
1801             lpMouseKeys->iMaxSpeed = 360;
1802             lpMouseKeys->iTimeToMaxSpeed = 1000;
1803             lpMouseKeys->iCtrlSpeed = 0;
1804             lpMouseKeys->dwReserved1 = 0;
1805             lpMouseKeys->dwReserved2 = 0;
1806         }
1807         else
1808         {
1809             ret = FALSE;
1810         }
1811         break;
1812     }
1813     WINE_SPI_FIXME(SPI_SETMOUSEKEYS);           /*     55 */
1814 
1815     case SPI_GETSHOWSOUNDS:
1816         ret = get_bool_param( SPI_SETSHOWSOUNDS_IDX,
1817                               SPI_SETSHOWSOUNDS_REGKEY,
1818                               SPI_SETSHOWSOUNDS_VALNAME,
1819                               &show_sounds, pvParam );
1820         break;
1821 
1822     case SPI_SETSHOWSOUNDS:
1823         ret = set_bool_param( SPI_SETSHOWSOUNDS_IDX,
1824                               SPI_SETSHOWSOUNDS_REGKEY,
1825                               SPI_SETSHOWSOUNDS_VALNAME,
1826                               &show_sounds, uiParam, fWinIni );
1827         break;
1828 
1829     case SPI_GETSTICKYKEYS:                     /*     58 */
1830     {
1831         LPSTICKYKEYS lpStickyKeys = (LPSTICKYKEYS)pvParam;
1832         WARN("SPI_GETSTICKYKEYS not fully implemented\n");
1833         if (lpStickyKeys && lpStickyKeys->cbSize == sizeof(STICKYKEYS))
1834         {
1835             /* Indicate that no StickyKeys feature available */
1836             lpStickyKeys->dwFlags = 0;
1837         }
1838         else
1839         {
1840             ret = FALSE;
1841         }
1842         break;
1843     }
1844     WINE_SPI_FIXME(SPI_SETSTICKYKEYS);          /*     59 */
1845 
1846     case SPI_GETACCESSTIMEOUT:                  /*     60 */
1847     {
1848         LPACCESSTIMEOUT lpAccessTimeout = (LPACCESSTIMEOUT)pvParam;
1849         WARN("SPI_GETACCESSTIMEOUT not fully implemented\n");
1850         if (lpAccessTimeout && lpAccessTimeout->cbSize == sizeof(ACCESSTIMEOUT))
1851         {
1852             /* Indicate that no accessibility features timeout is available */
1853             lpAccessTimeout->dwFlags = 0;
1854             lpAccessTimeout->iTimeOutMSec = 0;
1855         }
1856         else
1857         {
1858             ret = FALSE;
1859         }
1860         break;
1861     }
1862     WINE_SPI_FIXME(SPI_SETACCESSTIMEOUT);       /*     61 */
1863 
1864     case SPI_GETSERIALKEYS:                     /*     62  WINVER >= 0x400 */
1865     {
1866         LPSERIALKEYSW lpSerialKeysW = (LPSERIALKEYSW)pvParam;
1867         WARN("SPI_GETSERIALKEYS not fully implemented\n");
1868         if (lpSerialKeysW && lpSerialKeysW->cbSize == sizeof(SERIALKEYSW))
1869         {
1870             /* Indicate that no SerialKeys feature available */
1871             lpSerialKeysW->dwFlags = 0;
1872             lpSerialKeysW->lpszActivePort = NULL;
1873             lpSerialKeysW->lpszPort = NULL;
1874             lpSerialKeysW->iBaudRate = 0;
1875             lpSerialKeysW->iPortState = 0;
1876         }
1877         else
1878         {
1879             ret = FALSE;
1880         }
1881         break;
1882     }
1883     WINE_SPI_FIXME(SPI_SETSERIALKEYS);          /*     63  WINVER >= 0x400 */
1884 
1885     case SPI_GETSOUNDSENTRY:                    /*     64 */
1886     {
1887         LPSOUNDSENTRYW lpSoundSentryW = (LPSOUNDSENTRYW)pvParam;
1888         WARN("SPI_GETSOUNDSENTRY not fully implemented\n");
1889         if (lpSoundSentryW && lpSoundSentryW->cbSize == sizeof(SOUNDSENTRYW))
1890         {
1891             /* Indicate that no SoundSentry feature available */
1892             lpSoundSentryW->dwFlags = 0;
1893             lpSoundSentryW->iFSTextEffect = 0;
1894             lpSoundSentryW->iFSTextEffectMSec = 0;
1895             lpSoundSentryW->iFSTextEffectColorBits = 0;
1896             lpSoundSentryW->iFSGrafEffect = 0;
1897             lpSoundSentryW->iFSGrafEffectMSec = 0;
1898             lpSoundSentryW->iFSGrafEffectColor = 0;
1899             lpSoundSentryW->iWindowsEffect = 0;
1900             lpSoundSentryW->iWindowsEffectMSec = 0;
1901             lpSoundSentryW->lpszWindowsEffectDLL = 0;
1902             lpSoundSentryW->iWindowsEffectOrdinal = 0;
1903         }
1904         else
1905         {
1906             ret = FALSE;
1907         }
1908         break;
1909     }
1910     WINE_SPI_FIXME(SPI_SETSOUNDSENTRY);         /*     65 */
1911 
1912     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1913     {
1914         LPHIGHCONTRASTW lpHighContrastW = (LPHIGHCONTRASTW)pvParam;
1915         WARN("SPI_GETHIGHCONTRAST not fully implemented\n");
1916         if (lpHighContrastW && lpHighContrastW->cbSize == sizeof(HIGHCONTRASTW))
1917         {
1918             /* Indicate that no high contrast feature available */
1919             lpHighContrastW->dwFlags = 0;
1920             lpHighContrastW->lpszDefaultScheme = NULL;
1921         }
1922         else
1923         {
1924             ret = FALSE;
1925         }
1926         break;
1927     }
1928     WINE_SPI_FIXME(SPI_SETHIGHCONTRAST);        /*     67  WINVER >= 0x400 */
1929 
1930     case SPI_GETKEYBOARDPREF:
1931         ret = get_bool_param( SPI_SETKEYBOARDPREF_IDX,
1932                               SPI_SETKEYBOARDPREF_REGKEY,
1933                               SPI_SETKEYBOARDPREF_VALNAME,
1934                               &keyboard_pref, pvParam );
1935         break;
1936 
1937     case SPI_SETKEYBOARDPREF:
1938         ret = set_bool_param( SPI_SETKEYBOARDPREF_IDX,
1939                               SPI_SETKEYBOARDPREF_REGKEY,
1940                               SPI_SETKEYBOARDPREF_VALNAME,
1941                               &keyboard_pref, uiParam, fWinIni );
1942         break;
1943 
1944     case SPI_GETSCREENREADER:
1945         ret = get_bool_param( SPI_SETSCREENREADER_IDX,
1946                               SPI_SETSCREENREADER_REGKEY,
1947                               SPI_SETSCREENREADER_VALNAME,
1948                               &screen_reader, pvParam );
1949         break;
1950 
1951     case SPI_SETSCREENREADER:
1952         ret = set_bool_param( SPI_SETSCREENREADER_IDX,
1953                               SPI_SETSCREENREADER_REGKEY,
1954                               SPI_SETSCREENREADER_VALNAME,
1955                               &screen_reader, uiParam, fWinIni );
1956         break;
1957 
1958     case SPI_GETANIMATION:                      /*     72  WINVER >= 0x400 */
1959     {
1960         LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)pvParam;
1961 
1962         /* Tell it "disabled" */
1963         if (lpAnimInfo && lpAnimInfo->cbSize == sizeof(ANIMATIONINFO))
1964             lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
1965         else
1966             ret = FALSE;
1967         break;
1968     }
1969     WINE_SPI_WARN(SPI_SETANIMATION);            /*     73  WINVER >= 0x400 */
1970 
1971     case SPI_GETFONTSMOOTHING:
1972     {
1973         UINT tmpval;
1974         ret = get_uint_param( SPI_SETFONTSMOOTHING_IDX,
1975                               SPI_SETFONTSMOOTHING_REGKEY,
1976                               SPI_SETFONTSMOOTHING_VALNAME,
1977                               &font_smoothing, &tmpval );
1978         *(UINT *) pvParam = ( tmpval != 0);
1979         break;
1980     }
1981     case SPI_SETFONTSMOOTHING:
1982         uiParam = uiParam ? 2 : 0; /* Win NT4/2k/XP behavior */
1983         ret = set_uint_param( SPI_SETFONTSMOOTHING_IDX,
1984                               SPI_SETFONTSMOOTHING_REGKEY,
1985                               SPI_SETFONTSMOOTHING_VALNAME,
1986                               &font_smoothing, uiParam, fWinIni );
1987         break;
1988 
1989     WINE_SPI_FIXME(SPI_SETDRAGWIDTH);           /*     76  WINVER >= 0x400 */
1990     WINE_SPI_FIXME(SPI_SETDRAGHEIGHT);          /*     77  WINVER >= 0x400 */
1991 
1992     WINE_SPI_FIXME(SPI_SETHANDHELD);            /*     78  WINVER >= 0x400 */
1993 
1994     WINE_SPI_FIXME(SPI_GETLOWPOWERTIMEOUT);     /*     79  WINVER >= 0x400 */
1995     WINE_SPI_FIXME(SPI_GETPOWEROFFTIMEOUT);     /*     80  WINVER >= 0x400 */
1996     WINE_SPI_FIXME(SPI_SETLOWPOWERTIMEOUT);     /*     81  WINVER >= 0x400 */
1997     WINE_SPI_FIXME(SPI_SETPOWEROFFTIMEOUT);     /*     82  WINVER >= 0x400 */
1998 
1999     case SPI_GETLOWPOWERACTIVE:
2000         ret = get_bool_param( SPI_SETLOWPOWERACTIVE_IDX,
2001                               SPI_SETLOWPOWERACTIVE_REGKEY,
2002                               SPI_SETLOWPOWERACTIVE_VALNAME,
2003                               &lowpoweractive, pvParam );
2004         break;
2005 
2006     case SPI_GETPOWEROFFACTIVE:
2007         ret = get_bool_param( SPI_SETPOWEROFFACTIVE_IDX,
2008                               SPI_SETPOWEROFFACTIVE_REGKEY,
2009                               SPI_SETPOWEROFFACTIVE_VALNAME,
2010                               &poweroffactive, pvParam );
2011         break;
2012 
2013     case SPI_SETLOWPOWERACTIVE:
2014         ret = set_bool_param( SPI_SETLOWPOWERACTIVE_IDX,
2015                               SPI_SETLOWPOWERACTIVE_REGKEY,
2016                               SPI_SETLOWPOWERACTIVE_VALNAME,
2017                               &lowpoweractive, uiParam, fWinIni );
2018         break;
2019 
2020     case SPI_SETPOWEROFFACTIVE:
2021         ret = set_bool_param( SPI_SETPOWEROFFACTIVE_IDX,
2022                               SPI_SETPOWEROFFACTIVE_REGKEY,
2023                               SPI_SETPOWEROFFACTIVE_VALNAME,
2024                               &poweroffactive, uiParam, fWinIni );
2025         break;
2026 
2027     WINE_SPI_FIXME(SPI_SETCURSORS);             /*     87  WINVER >= 0x400 */
2028     WINE_SPI_FIXME(SPI_SETICONS);               /*     88  WINVER >= 0x400 */
2029 
2030     case SPI_GETDEFAULTINPUTLANG:       /*     89  WINVER >= 0x400 */
2031         ret = GetKeyboardLayout(0) ? TRUE : FALSE;
2032         break;
2033 
2034     WINE_SPI_FIXME(SPI_SETDEFAULTINPUTLANG);    /*     90  WINVER >= 0x400 */
2035 
2036     WINE_SPI_FIXME(SPI_SETLANGTOGGLE);          /*     91  WINVER >= 0x400 */
2037 
2038     case SPI_GETWINDOWSEXTENSION:               /*     92  WINVER >= 0x400 */
2039         WARN("pretend no support for Win9x Plus! for now.\n");
2040         ret = FALSE; /* yes, this is the result value */
2041         break;
2042 
2043     WINE_SPI_FIXME(SPI_SETMOUSETRAILS);         /*     93  WINVER >= 0x400 */
2044     WINE_SPI_FIXME(SPI_GETMOUSETRAILS);         /*     94  WINVER >= 0x400 */
2045 
2046     case SPI_GETSNAPTODEFBUTTON:                /*     95  WINVER >= 0x400 */
2047         ret = get_bool_param( SPI_SETSNAPTODEFBUTTON_IDX,
2048                               SPI_SETSNAPTODEFBUTTON_REGKEY,
2049                               SPI_SETSNAPTODEFBUTTON_VALNAME,
2050                               &snap_to_default_button, pvParam );
2051         break;
2052 
2053     case SPI_SETSNAPTODEFBUTTON:                /*     96  WINVER >= 0x400 */
2054         ret = set_bool_param( SPI_SETSNAPTODEFBUTTON_IDX,
2055                               SPI_SETSNAPTODEFBUTTON_REGKEY,
2056                               SPI_SETSNAPTODEFBUTTON_VALNAME,
2057                               &snap_to_default_button, uiParam, fWinIni );
2058         break;
2059 
2060     case SPI_SETSCREENSAVERRUNNING:
2061         ret = set_bool_param( SPI_SETSCREENSAVERRUNNING_IDX,
2062                               SPI_SETSCREENSAVERRUNNING_REGKEY,
2063                               SPI_SETSCREENSAVERRUNNING_VALNAME,
2064                               &screensaver_running, uiParam, fWinIni );
2065         break;
2066 
2067     case SPI_GETMOUSEHOVERWIDTH:
2068         ret = get_uint_param( SPI_SETMOUSEHOVERWIDTH_IDX,
2069                               SPI_SETMOUSEHOVERWIDTH_REGKEY,
2070                               SPI_SETMOUSEHOVERWIDTH_VALNAME,
2071                               &mouse_hover_width, pvParam );
2072         break;
2073 
2074     case SPI_SETMOUSEHOVERWIDTH:
2075         ret = set_uint_param( SPI_SETMOUSEHOVERWIDTH_IDX,
2076                               SPI_SETMOUSEHOVERWIDTH_REGKEY,
2077                               SPI_SETMOUSEHOVERWIDTH_VALNAME,
2078                               &mouse_hover_width, uiParam, fWinIni );
2079         break;
2080 
2081     case SPI_GETMOUSEHOVERHEIGHT:
2082         ret = get_uint_param( SPI_SETMOUSEHOVERHEIGHT_IDX,
2083                               SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2084                               SPI_SETMOUSEHOVERHEIGHT_VALNAME,
2085                               &mouse_hover_height, pvParam );
2086         break;
2087 
2088     case SPI_SETMOUSEHOVERHEIGHT:
2089         ret = set_uint_param( SPI_SETMOUSEHOVERHEIGHT_IDX,
2090                               SPI_SETMOUSEHOVERHEIGHT_REGKEY,
2091                               SPI_SETMOUSEHOVERHEIGHT_VALNAME,
2092                               &mouse_hover_height, uiParam, fWinIni );
2093         break;
2094 
2095     case SPI_GETMOUSEHOVERTIME:
2096         ret = get_uint_param( SPI_SETMOUSEHOVERTIME_IDX,
2097                               SPI_SETMOUSEHOVERTIME_REGKEY,
2098                               SPI_SETMOUSEHOVERTIME_VALNAME,
2099                               &mouse_hover_time, pvParam );
2100         break;
2101 
2102     case SPI_SETMOUSEHOVERTIME:
2103         ret = set_uint_param( SPI_SETMOUSEHOVERTIME_IDX,
2104                               SPI_SETMOUSEHOVERTIME_REGKEY,
2105                               SPI_SETMOUSEHOVERTIME_VALNAME,
2106                               &mouse_hover_time, uiParam, fWinIni );
2107         break;
2108 
2109     case SPI_GETWHEELSCROLLLINES:
2110         ret = get_uint_param( SPI_SETMOUSESCROLLLINES_IDX,
2111                               SPI_SETMOUSESCROLLLINES_REGKEY,
2112                               SPI_SETMOUSESCROLLLINES_VALNAME,
2113                               &mouse_scroll_lines, pvParam );
2114         break;
2115 
2116     case SPI_SETWHEELSCROLLLINES:
2117         ret = set_uint_param( SPI_SETMOUSESCROLLLINES_IDX,
2118                               SPI_SETMOUSESCROLLLINES_REGKEY,
2119                               SPI_SETMOUSESCROLLLINES_VALNAME,
2120                               &mouse_scroll_lines, uiParam, fWinIni );
2121         break;
2122 
2123     case SPI_GETMENUSHOWDELAY:
2124         ret = get_uint_param( SPI_SETMENUSHOWDELAY_IDX,
2125                               SPI_SETMENUSHOWDELAY_REGKEY,
2126                               SPI_SETMENUSHOWDELAY_VALNAME,
2127                               &menu_show_delay, pvParam );
2128         break;
2129 
2130     case SPI_SETMENUSHOWDELAY:
2131         ret = set_uint_param( SPI_SETMENUSHOWDELAY_IDX,
2132                               SPI_SETMENUSHOWDELAY_REGKEY,
2133                               SPI_SETMENUSHOWDELAY_VALNAME,
2134                               &menu_show_delay, uiParam, fWinIni );
2135         break;
2136 
2137     case SPI_GETWHEELSCROLLCHARS:                       /*    108  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2138         ret = get_uint_param( SPI_SETMOUSESCROLLCHARS_IDX,
2139                               SPI_SETMOUSESCROLLCHARS_REGKEY,
2140                               SPI_SETMOUSESCROLLCHARS_VALNAME,
2141                               &mouse_scroll_chars, pvParam );
2142         break;
2143 
2144     case SPI_SETWHEELSCROLLCHARS:                       /*    109  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2145         ret = set_uint_param( SPI_SETMOUSESCROLLCHARS_IDX,
2146                               SPI_SETMOUSESCROLLCHARS_REGKEY,
2147                               SPI_SETMOUSESCROLLCHARS_VALNAME,
2148                               &mouse_scroll_chars, uiParam, fWinIni );
2149         break;
2150 
2151     WINE_SPI_FIXME(SPI_GETSHOWIMEUI);           /*    110  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2152     WINE_SPI_FIXME(SPI_SETSHOWIMEUI);           /*    111  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2153 
2154     case SPI_GETMOUSESPEED:             /*    112  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2155     {
2156         int buf[3];
2157         ret = SystemParametersInfoW (SPI_GETMOUSE, 0, buf, fWinIni);
2158         *(INT *)pvParam = buf[2];
2159         break;
2160     }
2161 
2162     case SPI_SETMOUSESPEED:                     /*    113  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2163     {
2164         ret = save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
2165                               &mouse_speed, PtrToInt(pvParam), fWinIni);
2166 
2167         break;
2168     }
2169 
2170     case SPI_GETSCREENSAVERRUNNING:
2171         ret = get_bool_param( SPI_SETSCREENSAVERRUNNING_IDX,
2172                               SPI_SETSCREENSAVERRUNNING_REGKEY,
2173                               SPI_SETSCREENSAVERRUNNING_VALNAME,
2174                               &screensaver_running, pvParam );
2175         break;
2176 
2177     case SPI_GETDESKWALLPAPER:                  /*    115  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2178     {
2179         WCHAR buf[MAX_PATH];
2180 
2181         if (!pvParam) return FALSE;
2182 
2183         if (uiParam > MAX_PATH)
2184         {
2185             uiParam = MAX_PATH;
2186         }
2187 
2188         if (SYSPARAMS_Load(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, buf, sizeof(buf)))
2189         {
2190             lstrcpynW((WCHAR*)pvParam, buf, uiParam);
2191         }
2192         else
2193         {
2194             /* Return an empty string */
2195             memset((WCHAR*)pvParam, 0, uiParam);
2196         }
2197 
2198         break;
2199     }
2200 
2201     WINE_SPI_FIXME(SPI_GETACTIVEWINDOWTRACKING);/* 0x1000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2202     WINE_SPI_FIXME(SPI_SETACTIVEWINDOWTRACKING);/* 0x1001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2203     case SPI_GETMENUANIMATION:             /* 0x1002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2204         ret = get_user_pref_param( 0, 0x02, pvParam );
2205         break;
2206 
2207     case SPI_SETMENUANIMATION:             /* 0x1003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2208         ret = set_user_pref_param( 0, 0x02, PtrToUlong(pvParam), fWinIni );
2209         break;
2210 
2211     case SPI_GETCOMBOBOXANIMATION:         /* 0x1004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2212         ret = get_user_pref_param( 0, 0x04, pvParam );
2213         break;
2214 
2215     case SPI_SETCOMBOBOXANIMATION:         /* 0x1005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2216         ret = set_user_pref_param( 0, 0x04, PtrToUlong(pvParam), fWinIni );
2217         break;
2218 
2219     case SPI_GETLISTBOXSMOOTHSCROLLING:    /* 0x1006  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2220         ret = get_user_pref_param( 0, 0x08, pvParam );
2221         break;
2222 
2223     case SPI_SETLISTBOXSMOOTHSCROLLING:    /* 0x1007  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2224         ret = set_user_pref_param( 0, 0x08, PtrToUlong(pvParam), fWinIni );
2225         break;
2226 
2227     case SPI_GETGRADIENTCAPTIONS:
2228         ret = get_user_pref_param( 0, 0x10, pvParam );
2229         break;
2230 
2231     case SPI_SETGRADIENTCAPTIONS:
2232         ret = set_user_pref_param( 0, 0x10, PtrToUlong(pvParam), fWinIni );
2233         break;
2234 
2235     case SPI_GETKEYBOARDCUES:
2236         ret = get_user_pref_param( 0, 0x20, pvParam );
2237         break;
2238 
2239     case SPI_SETKEYBOARDCUES:
2240         ret = set_user_pref_param( 0, 0x20, PtrToUlong(pvParam), fWinIni );
2241         break;
2242 
2243     WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKZORDER);  /* 0x100C  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2244     WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKZORDER);  /* 0x100D  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2245     case SPI_GETHOTTRACKING:
2246         ret = get_user_pref_param( 0, 0x80, pvParam );
2247         break;
2248 
2249     case SPI_SETHOTTRACKING:
2250         ret = set_user_pref_param( 0, 0x80, PtrToUlong(pvParam), fWinIni );
2251         break;
2252 
2253     WINE_SPI_FIXME(SPI_GETMENUFADE);            /* 0x1012  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2254     WINE_SPI_FIXME(SPI_SETMENUFADE);            /* 0x1013  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2255     case SPI_GETSELECTIONFADE:                  /* 0x1014  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2256         ret = get_user_pref_param( 1, 0x04, pvParam );
2257         break;
2258 
2259     case SPI_SETSELECTIONFADE:                  /* 0x1015  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2260         ret = set_user_pref_param( 1, 0x04, PtrToUlong(pvParam), fWinIni );
2261         break;
2262 
2263     case SPI_GETTOOLTIPANIMATION:               /* 0x1016  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2264         ret = get_user_pref_param( 1, 0x08, pvParam );
2265         break;
2266 
2267     case SPI_SETTOOLTIPANIMATION:               /* 0x1017  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2268         ret = set_user_pref_param( 1, 0x08, PtrToUlong(pvParam), fWinIni );
2269         break;
2270 
2271     case SPI_GETTOOLTIPFADE:                    /* 0x1018  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2272         ret = get_user_pref_param( 1, 0x10, pvParam );
2273         break;
2274 
2275     case SPI_SETTOOLTIPFADE:                    /* 0x1019  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2276         ret = set_user_pref_param( 1, 0x10, PtrToUlong(pvParam), fWinIni );
2277         break;
2278 
2279     case SPI_GETCURSORSHADOW:                   /* 0x101A  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2280         ret = get_user_pref_param( 1, 0x20, pvParam );
2281         break;
2282 
2283     case SPI_SETCURSORSHADOW:                   /* 0x101B  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2284         ret = set_user_pref_param( 1, 0x20, PtrToUlong(pvParam), fWinIni );
2285         break;
2286 
2287     WINE_SPI_FIXME(SPI_GETMOUSESONAR);          /* 0x101C  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2288     WINE_SPI_FIXME(SPI_SETMOUSESONAR);          /* 0x101D  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2289     WINE_SPI_FIXME(SPI_GETMOUSECLICKLOCK);      /* 0x101E  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2290     WINE_SPI_FIXME(SPI_SETMOUSECLICKLOCK);      /* 0x101F  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2291     WINE_SPI_FIXME(SPI_GETMOUSEVANISH);         /* 0x1020  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2292     WINE_SPI_FIXME(SPI_SETMOUSEVANISH);         /* 0x1021  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2293     case SPI_GETFLATMENU:
2294         ret = get_user_pref_param( 2, 0x02, pvParam );
2295         break;
2296 
2297     case SPI_SETFLATMENU:
2298         ret = set_user_pref_param( 2, 0x02, PtrToUlong(pvParam), fWinIni );
2299         break;
2300 
2301     WINE_SPI_FIXME(SPI_GETDROPSHADOW);          /* 0x1024  _WIN32_WINNT >= 0x510 */
2302     WINE_SPI_FIXME(SPI_SETDROPSHADOW);          /* 0x1025  _WIN32_WINNT >= 0x510 */
2303     WINE_SPI_FIXME(SPI_GETBLOCKSENDINPUTRESETS);
2304     WINE_SPI_FIXME(SPI_SETBLOCKSENDINPUTRESETS);
2305     case SPI_GETUIEFFECTS:
2306         ret = get_user_pref_param( 3, 0x80, pvParam );
2307         break;
2308 
2309     case SPI_SETUIEFFECTS:
2310         /* FIXME: this probably should mask other UI effect values when unset */
2311         ret = set_user_pref_param( 3, 0x80, PtrToUlong(pvParam), fWinIni );
2312         break;
2313 
2314     case SPI_GETFOREGROUNDLOCKTIMEOUT:          /* 0x2000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2315         ret = get_uint_param( SPI_SETFOREGROUNDLOCKTIMEOUT_IDX,
2316                               SPI_SETFOREGROUNDLOCKTIMEOUT_REGKEY,
2317                               SPI_SETFOREGROUNDLOCKTIMEOUT_VALNAME,
2318                               &foreground_lock_timeout, pvParam );
2319         break;
2320 
2321     case SPI_SETFOREGROUNDLOCKTIMEOUT:          /* 0x2001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2322         /* FIXME: this should check that the calling thread
2323          * is able to change the foreground window */
2324         ret = set_uint_param( SPI_SETFOREGROUNDLOCKTIMEOUT_IDX,
2325                               SPI_SETFOREGROUNDLOCKTIMEOUT_REGKEY,
2326                               SPI_SETFOREGROUNDLOCKTIMEOUT_VALNAME,
2327                               &foreground_lock_timeout, PtrToUlong(pvParam), fWinIni );
2328         break;
2329 
2330     WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKTIMEOUT); /* 0x2002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2331     WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKTIMEOUT); /* 0x2003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2332     WINE_SPI_FIXME(SPI_GETFOREGROUNDFLASHCOUNT);/* 0x2004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2333     WINE_SPI_FIXME(SPI_SETFOREGROUNDFLASHCOUNT);/* 0x2005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2334     case SPI_GETCARETWIDTH:          /* 0x2006  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2335         ret = get_uint_param( SPI_CARETWIDTH_IDX,
2336                               SPI_CARETWIDTH_REGKEY,
2337                               SPI_CARETWIDTH_VALNAME,
2338                               &caret_width, pvParam );
2339         break;
2340 
2341     case SPI_SETCARETWIDTH:          /* 0x2007  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2342         ret = set_uint_param( SPI_CARETWIDTH_IDX,
2343                               SPI_CARETWIDTH_REGKEY,
2344                               SPI_CARETWIDTH_VALNAME,
2345                               &caret_width, uiParam, fWinIni );
2346         break;
2347 
2348     WINE_SPI_FIXME(SPI_GETMOUSECLICKLOCKTIME);  /* 0x2008  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2349     WINE_SPI_FIXME(SPI_SETMOUSECLICKLOCKTIME);  /* 0x2009  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2350     WINE_SPI_FIXME(SPI_GETFONTSMOOTHINGTYPE);   /* 0x200A  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2351     WINE_SPI_FIXME(SPI_SETFONTSMOOTHINGTYPE);   /* 0x200B  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2352     WINE_SPI_FIXME(SPI_GETFONTSMOOTHINGCONTRAST);/* 0x200C  _WIN32_WINNT >= 0x510 */
2353     WINE_SPI_FIXME(SPI_SETFONTSMOOTHINGCONTRAST);/* 0x200D  _WIN32_WINNT >= 0x510 */
2354     WINE_SPI_FIXME(SPI_GETFOCUSBORDERWIDTH);    /* 0x200E  _WIN32_WINNT >= 0x510 */
2355     WINE_SPI_FIXME(SPI_SETFOCUSBORDERWIDTH);    /* 0x200F  _WIN32_WINNT >= 0x510 */
2356     WINE_SPI_FIXME(SPI_GETFOCUSBORDERHEIGHT);    /* 0x2010  _WIN32_WINNT >= 0x510 */
2357     WINE_SPI_FIXME(SPI_SETFOCUSBORDERHEIGHT);    /* 0x2011  _WIN32_WINNT >= 0x510 */
2358     WINE_SPI_FIXME(SPI_GETFONTSMOOTHINGORIENTATION);    /* 0x2012 */
2359     WINE_SPI_FIXME(SPI_SETFONTSMOOTHINGORIENTATION);    /* 0x2013 */
2360 
2361     default:
2362         FIXME( "Unknown action: %u\n", uiAction );
2363         SetLastError( ERROR_INVALID_SPI_VALUE );
2364         ret = FALSE;
2365         break;
2366     }
2367 
2368     if (ret)
2369         SYSPARAMS_NotifyChange( uiAction, fWinIni );
2370     TRACE("(%u, %u, %p, %u) ret %d\n",
2371             uiAction, uiParam, pvParam, fWinIni, ret);
2372     return ret;
2373 
2374 #undef WINE_SPI_FIXME
2375 #undef WINE_SPI_WARN
2376 }
2377 
2378 
2379 /***********************************************************************
2380  *              SystemParametersInfo (USER.483)
2381  */
2382 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
2383                                       LPVOID lpvParam, UINT16 fuWinIni )
2384 {
2385     BOOL16 ret;
2386 
2387     TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
2388 
2389     switch (uAction)
2390     {
2391     case SPI_GETBEEP:                           /*      1 */
2392     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
2393     case SPI_GETICONTITLEWRAP:                  /*     25 */
2394     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
2395     case SPI_GETFASTTASKSWITCH:                 /*     35 */
2396     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
2397     {
2398         BOOL tmp;
2399         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2400         if (ret && lpvParam)
2401             *(BOOL16 *)lpvParam = tmp;
2402         break;
2403     }
2404 
2405     case SPI_GETBORDER:                         /*      5 */
2406     case SPI_ICONHORIZONTALSPACING:             /*     13 */
2407     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
2408     case SPI_GETGRIDGRANULARITY:                /*     18 */
2409     case SPI_GETKEYBOARDDELAY:                  /*     22 */
2410     case SPI_ICONVERTICALSPACING:               /*     24 */
2411     {
2412         INT tmp;
2413         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2414         if (ret && lpvParam)
2415             *(INT16 *)lpvParam = tmp;
2416         break;
2417     }
2418 
2419     case SPI_GETKEYBOARDSPEED:                  /*     10 */
2420     {
2421         DWORD tmp;
2422         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2423         if (ret && lpvParam)
2424             *(WORD *)lpvParam = tmp;
2425         break;
2426     }
2427 
2428     case SPI_GETICONTITLELOGFONT:               /*     31 */
2429     {
2430         LOGFONTA tmp;
2431         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2432         if (ret && lpvParam)
2433             SYSPARAMS_LogFont32ATo16( &tmp, (LPLOGFONT16)lpvParam );
2434         break;
2435     }
2436 
2437     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
2438     {
2439         NONCLIENTMETRICSA tmp;
2440         LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
2441         if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
2442         {
2443             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
2444             ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
2445             if (ret)
2446                 SYSPARAMS_NonClientMetrics32ATo16( &tmp, lpnm16 );
2447         }
2448         else /* winfile 95 sets cbSize to 340 */
2449             ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
2450         break;
2451     }
2452 
2453     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
2454     {
2455         RECT tmp;
2456         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2457         if (ret && lpvParam)
2458         {
2459             RECT16 *r16 = (RECT16 *)lpvParam;
2460             r16->left   = tmp.left;
2461             r16->top    = tmp.top;
2462             r16->right  = tmp.right;
2463             r16->bottom = tmp.bottom;
2464         }
2465         break;
2466     }
2467 
2468     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2469     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2470     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2471     {
2472         UINT tmp;
2473         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2474         if (ret && lpvParam)
2475             *(UINT16 *)lpvParam = tmp;
2476         break;
2477     }
2478 
2479     default:
2480         ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
2481     }
2482 
2483     return ret;
2484 }
2485 
2486 /***********************************************************************
2487  *              SystemParametersInfoA (USER32.@)
2488  */
2489 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
2490                                    PVOID pvParam, UINT fuWinIni )
2491 {
2492     BOOL ret;
2493 
2494     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
2495 
2496     switch (uiAction)
2497     {
2498     case SPI_SETDESKWALLPAPER:                  /*     20 */
2499     case SPI_SETDESKPATTERN:                    /*     21 */
2500     {
2501         WCHAR buffer[256];
2502         if (pvParam)
2503             if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)pvParam, -1,
2504                                       buffer, sizeof(buffer)/sizeof(WCHAR) ))
2505                 buffer[sizeof(buffer)/sizeof(WCHAR)-1] = 0;
2506         ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
2507         break;
2508     }
2509 
2510     case SPI_GETICONTITLELOGFONT:               /*     31 */
2511     {
2512         LOGFONTW tmp;
2513         ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
2514         if (ret && pvParam)
2515             SYSPARAMS_LogFont32WTo32A( &tmp, (LPLOGFONTA)pvParam );
2516         break;
2517     }
2518 
2519     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
2520     {
2521         NONCLIENTMETRICSW tmp;
2522         LPNONCLIENTMETRICSA lpnmA = (LPNONCLIENTMETRICSA)pvParam;
2523         if (lpnmA && lpnmA->cbSize == sizeof(NONCLIENTMETRICSA))
2524         {
2525             tmp.cbSize = sizeof(NONCLIENTMETRICSW);
2526             ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2527             if (ret)
2528                 SYSPARAMS_NonClientMetrics32WTo32A( &tmp, lpnmA );
2529         }
2530         else
2531             ret = FALSE;
2532         break;
2533     }
2534 
2535     case SPI_SETNONCLIENTMETRICS:               /*     42  WINVER >= 0x400 */
2536     {
2537         NONCLIENTMETRICSW tmp;
2538         LPNONCLIENTMETRICSA lpnmA = (LPNONCLIENTMETRICSA)pvParam;
2539         if (lpnmA && lpnmA->cbSize == sizeof(NONCLIENTMETRICSA))
2540         {
2541             tmp.cbSize = sizeof(NONCLIENTMETRICSW);
2542             SYSPARAMS_NonClientMetrics32ATo32W( lpnmA, &tmp );
2543             ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2544         }
2545         else
2546             ret = FALSE;
2547         break;
2548     }
2549 
2550     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
2551     {
2552         ICONMETRICSW tmp;
2553         LPICONMETRICSA lpimA = (LPICONMETRICSA)pvParam;
2554         if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
2555         {
2556             tmp.cbSize = sizeof(ICONMETRICSW);
2557             ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2558             if (ret)
2559             {
2560                 lpimA->iHorzSpacing = tmp.iHorzSpacing;
2561                 lpimA->iVertSpacing = tmp.iVertSpacing;
2562                 lpimA->iTitleWrap   = tmp.iTitleWrap;
2563                 SYSPARAMS_LogFont32WTo32A( &tmp.lfFont, &lpimA->lfFont );
2564             }
2565         }
2566         else
2567             ret = FALSE;
2568         break;
2569     }
2570 
2571     case SPI_SETICONMETRICS:                    /*     46  WINVER >= 0x400 */
2572     {
2573         ICONMETRICSW tmp;
2574         LPICONMETRICSA lpimA = (LPICONMETRICSA)pvParam;
2575         if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
2576         {
2577             tmp.cbSize = sizeof(ICONMETRICSW);
2578             tmp.iHorzSpacing = lpimA->iHorzSpacing;
2579             tmp.iVertSpacing = lpimA->iVertSpacing;
2580             tmp.iTitleWrap = lpimA->iTitleWrap;
2581             SYSPARAMS_LogFont32ATo32W(  &lpimA->lfFont, &tmp.lfFont);
2582             ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2583         }
2584         else
2585             ret = FALSE;
2586         break;
2587     }
2588 
2589     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
2590     {
2591         HIGHCONTRASTW tmp;
2592         LPHIGHCONTRASTA lphcA = (LPHIGHCONTRASTA)pvParam;
2593         if (lphcA && lphcA->cbSize == sizeof(HIGHCONTRASTA))
2594         {
2595             tmp.cbSize = sizeof(HIGHCONTRASTW);
2596             ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2597             if (ret)
2598             {
2599                 lphcA->dwFlags = tmp.dwFlags;
2600                 lphcA->lpszDefaultScheme = NULL;  /* FIXME? */
2601             }
2602         }
2603         else
2604             ret = FALSE;
2605         break;
2606     }
2607 
2608     case SPI_GETDESKWALLPAPER:                  /*     115 */
2609     {
2610         WCHAR buffer[MAX_PATH];
2611         ret = (SystemParametersInfoW( SPI_GETDESKWALLPAPER, uiParam, buffer, fuWinIni ) &&
2612                WideCharToMultiByte(CP_ACP, 0, buffer, -1, pvParam, uiParam, NULL, NULL));
2613         break;
2614     }
2615 
2616     default:
2617         ret = SystemParametersInfoW( uiAction, uiParam, pvParam, fuWinIni );
2618         break;
2619     }
2620     return ret;
2621 }
2622 
2623 
2624 /***********************************************************************
2625  *              GetSystemMetrics (USER32.@)
2626  */
2627 INT WINAPI GetSystemMetrics( INT index )
2628 {
2629     UINT ret;
2630 
2631     /* some metrics are dynamic */
2632     switch (index)
2633     {
2634     case SM_CXSCREEN:
2635         return GetDeviceCaps( get_display_dc(), HORZRES );
2636     case SM_CYSCREEN:
2637         return GetDeviceCaps( get_display_dc(), VERTRES );
2638     case SM_CXVSCROLL:
2639         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2640         return nonclient_metrics.iScrollWidth;
2641     case SM_CYHSCROLL:
2642         return GetSystemMetrics(SM_CXVSCROLL);
2643     case SM_CYCAPTION:
2644         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2645         return nonclient_metrics.iCaptionHeight + 1;
2646     case SM_CXBORDER:
2647     case SM_CYBORDER:
2648         /* SM_C{X,Y}BORDER always returns 1 regardless of 'BorderWidth' value in registry */
2649         return 1;
2650     case SM_CXDLGFRAME:
2651     case SM_CYDLGFRAME:
2652         return 3;
2653     case SM_CYVTHUMB:
2654         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2655         return nonclient_metrics.iScrollHeight;
2656     case SM_CXHTHUMB:
2657         return GetSystemMetrics(SM_CYVTHUMB);
2658     case SM_CXICON:
2659         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2660         return icon_size.cx;
2661     case SM_CYICON:
2662         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2663         return icon_size.cy;
2664     case SM_CXCURSOR:
2665     case SM_CYCURSOR:
2666         return 32;
2667     case SM_CYMENU:
2668         return GetSystemMetrics(SM_CYMENUSIZE) + 1;
2669     case SM_CXFULLSCREEN:
2670         /* see the remark for SM_CXMAXIMIZED, at least this formulation is
2671          * correct */
2672         return GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME);
2673     case SM_CYFULLSCREEN:
2674         /* see the remark for SM_CYMAXIMIZED, at least this formulation is
2675          * correct */
2676         return GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN);
2677     case SM_CYKANJIWINDOW:
2678         return 0;
2679     case SM_MOUSEPRESENT:
2680         return 1;
2681     case SM_CYVSCROLL:
2682         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2683         return nonclient_metrics.iScrollHeight;
2684     case SM_CXHSCROLL:
2685         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2686         return nonclient_metrics.iScrollHeight;
2687     case SM_DEBUG:
2688         return 0;
2689     case SM_SWAPBUTTON:
2690         get_bool_param( SPI_SETMOUSEBUTTONSWAP_IDX, SPI_SETMOUSEBUTTONSWAP_REGKEY,
2691                         SPI_SETMOUSEBUTTONSWAP_VALNAME, &swap_buttons, (BOOL*)&ret );
2692         return ret;
2693     case SM_RESERVED1:
2694     case SM_RESERVED2:
2695     case SM_RESERVED3:
2696     case SM_RESERVED4:
2697         return 0;
2698     case SM_CXMIN:
2699         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2700         return 3 * nonclient_metrics.iCaptionWidth + GetSystemMetrics( SM_CYSIZE) +
2701             4 * CaptionFontAvCharWidth + 2 * GetSystemMetrics( SM_CXFRAME) + 4;
2702     case SM_CYMIN:
2703         return GetSystemMetrics( SM_CYCAPTION) + 2 * GetSystemMetrics( SM_CYFRAME);
2704     case SM_CXSIZE:
2705         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2706         return nonclient_metrics.iCaptionWidth;
2707     case SM_CYSIZE:
2708         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2709         return nonclient_metrics.iCaptionHeight;
2710     case SM_CXFRAME:
2711         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2712         return GetSystemMetrics(SM_CXDLGFRAME) + nonclient_metrics.iBorderWidth;
2713     case SM_CYFRAME:
2714         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2715         return GetSystemMetrics(SM_CYDLGFRAME) + nonclient_metrics.iBorderWidth;
2716     case SM_CXMINTRACK:
2717         return GetSystemMetrics(SM_CXMIN);
2718     case SM_CYMINTRACK:
2719         return GetSystemMetrics(SM_CYMIN);
2720     case SM_CXDOUBLECLK:
2721         get_uint_param( SPI_SETDOUBLECLKWIDTH_IDX, SPI_SETDOUBLECLKWIDTH_REGKEY1,
2722                         SPI_SETDOUBLECLKWIDTH_VALNAME, &double_click_width, &ret );
2723         return ret;
2724     case SM_CYDOUBLECLK:
2725         get_uint_param( SPI_SETDOUBLECLKHEIGHT_IDX, SPI_SETDOUBLECLKHEIGHT_REGKEY1,
2726                         SPI_SETDOUBLECLKHEIGHT_VALNAME, &double_click_height, &ret );
2727         return ret;
2728     case SM_CXICONSPACING:
2729         SystemParametersInfoW( SPI_ICONHORIZONTALSPACING, 0, &ret, 0 );
2730         return ret;
2731     case SM_CYICONSPACING:
2732         SystemParametersInfoW( SPI_ICONVERTICALSPACING, 0, &ret, 0 );
2733         return ret;
2734     case SM_MENUDROPALIGNMENT:
2735         SystemParametersInfoW( SPI_GETMENUDROPALIGNMENT, 0, &ret, 0 );
2736         return ret;
2737     case SM_PENWINDOWS:
2738         return 0;
2739     case SM_DBCSENABLED:
2740     {
2741         CPINFO cpinfo;
2742         GetCPInfo( CP_ACP, &cpinfo );
2743         return (cpinfo.MaxCharSize > 1);
2744     }
2745     case SM_CMOUSEBUTTONS:
2746         return 3;
2747     case SM_SECURE:
2748         return 0;
2749     case SM_CXEDGE:
2750         return GetSystemMetrics(SM_CXBORDER) + 1;
2751     case SM_CYEDGE:
2752         return GetSystemMetrics(SM_CYBORDER) + 1;
2753     case SM_CXMINSPACING:
2754         if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2755         return GetSystemMetrics(SM_CXMINIMIZED) + minimized_metrics.iHorzGap;
2756     case SM_CYMINSPACING:
2757         if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2758         return GetSystemMetrics(SM_CYMINIMIZED) + minimized_metrics.iVertGap;
2759     case SM_CXSMICON:
2760     case SM_CYSMICON:
2761         return 16;
2762     case SM_CYSMCAPTION:
2763         return GetSystemMetrics(SM_CYSMSIZE) + 1;
2764     case SM_CXSMSIZE:
2765         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2766         return nonclient_metrics.iSmCaptionWidth;
2767     case SM_CYSMSIZE:
2768         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2769         return nonclient_metrics.iSmCaptionHeight;
2770     case SM_CXMENUSIZE:
2771         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2772         return nonclient_metrics.iMenuWidth;
2773     case SM_CYMENUSIZE:
2774         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2775         return nonclient_metrics.iMenuHeight;
2776     case SM_ARRANGE:
2777         if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2778         return minimized_metrics.iArrange;
2779     case SM_CXMINIMIZED:
2780         if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2781         return minimized_metrics.iWidth + 6;
2782     case SM_CYMINIMIZED:
2783         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2784         return nonclient_metrics.iCaptionHeight + 6;
2785     case SM_CXMAXTRACK:
2786         return GetSystemMetrics(SM_CXVIRTUALSCREEN) + 4 + 2 * GetSystemMetrics(SM_CXFRAME);
2787     case SM_CYMAXTRACK:
2788         return GetSystemMetrics(SM_CYVIRTUALSCREEN) + 4 + 2 * GetSystemMetrics(SM_CYFRAME);
2789     case SM_CXMAXIMIZED:
2790         /* FIXME: subtract the width of any vertical application toolbars*/
2791         return GetSystemMetrics(SM_CXSCREEN) + 2 * GetSystemMetrics(SM_CXFRAME);
2792     case SM_CYMAXIMIZED:
2793         /* FIXME: subtract the width of any horizontal application toolbars*/
2794         return GetSystemMetrics(SM_CYSCREEN) + 2 * GetSystemMetrics(SM_CYCAPTION);
2795     case SM_NETWORK:
2796         return 3;  /* FIXME */
2797     case SM_CLEANBOOT:
2798         return 0; /* 0 = ok, 1 = failsafe, 2 = failsafe + network */
2799     case SM_CXDRAG:
2800     case SM_CYDRAG:
2801         return 4;
2802     case SM_SHOWSOUNDS:
2803         SystemParametersInfoW( SPI_GETSHOWSOUNDS, 0, &ret, 0 );
2804         return ret;
2805     case SM_CXMENUCHECK:
2806     case SM_CYMENUCHECK:
2807         if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2808         return tmMenuFont.tmHeight <= 0 ? 13 :
2809         ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading + 1) / 2) * 2 - 1;
2810     case SM_SLOWMACHINE:
2811         return 0;  /* Never true */
2812     case SM_MIDEASTENABLED:
2813         return 0;  /* FIXME */
2814     case SM_MOUSEWHEELPRESENT:
2815         return 1;
2816     case SM_XVIRTUALSCREEN:
2817     {
2818         struct monitor_info info;
2819         get_monitors_info( &info );
2820         return info.virtual_rect.left;
2821     }
2822     case SM_YVIRTUALSCREEN:
2823     {
2824         struct monitor_info info;
2825         get_monitors_info( &info );
2826         return info.virtual_rect.top;
2827     }
2828     case SM_CXVIRTUALSCREEN:
2829     {
2830         struct monitor_info info;
2831         get_monitors_info( &info );
2832         return info.virtual_rect.right - info.virtual_rect.left;
2833     }
2834     case SM_CYVIRTUALSCREEN:
2835     {
2836         struct monitor_info info;
2837         get_monitors_info( &info );
2838         return info.virtual_rect.bottom - info.virtual_rect.top;
2839     }
2840     case SM_CMONITORS:
2841     {
2842         struct monitor_info info;
2843         get_monitors_info( &info );
2844         return info.count;
2845     }
2846     case SM_SAMEDISPLAYFORMAT:
2847         return 1;
2848     case SM_IMMENABLED:
2849         return 0;  /* FIXME */
2850     case SM_CXFOCUSBORDER:
2851     case SM_CYFOCUSBORDER:
2852         return 1;
2853     case SM_TABLETPC:
2854     case SM_MEDIACENTER:
2855         return 0;
2856     case SM_CMETRICS:
2857         return SM_CMETRICS;
2858     default:
2859         return 0;
2860     }
2861 }
2862 
2863 
2864 /***********************************************************************
2865  *              SwapMouseButton (USER32.@)
2866  *  Reverse or restore the meaning of the left and right mouse buttons
2867  *  fSwap  [I ] TRUE - reverse, FALSE - original
2868  * RETURN
2869  *   previous state 
2870  */
2871 BOOL WINAPI SwapMouseButton( BOOL fSwap )
2872 {
2873     BOOL prev = GetSystemMetrics(SM_SWAPBUTTON);
2874     SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP, fSwap, 0, 0);
2875     return prev;
2876 }
2877 
2878 
2879 /**********************************************************************
2880  *              SetDoubleClickTime (USER32.@)
2881  */
2882 BOOL WINAPI SetDoubleClickTime( UINT interval )
2883 {
2884     return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
2885 }
2886 
2887 
2888 /**********************************************************************
2889  *              GetDoubleClickTime (USER32.@)
2890  */
2891 UINT WINAPI GetDoubleClickTime(void)
2892 {
2893     UINT time = 0;
2894 
2895     get_uint_param( SPI_SETDOUBLECLICKTIME_IDX,
2896                     SPI_SETDOUBLECLICKTIME_REGKEY,
2897                     SPI_SETDOUBLECLICKTIME_VALNAME,
2898                     &double_click_time, &time );
2899     if (!time) time = 500;
2900     return time;
2901 }
2902 
2903 
2904 /*************************************************************************
2905  *              GetSysColor (USER32.@)
2906  */
2907 COLORREF WINAPI GetSysColor( INT nIndex )
2908 {
2909     if (nIndex >= 0 && nIndex < NUM_SYS_COLORS)
2910         return SysColors[nIndex];
2911     else
2912         return 0;
2913 }
2914 
2915 
2916 /*************************************************************************
2917  *              SetSysColors (USER32.@)
2918  */
2919 BOOL WINAPI SetSysColors( INT nChanges, const INT *lpSysColor,
2920                               const COLORREF *lpColorValues )
2921 {
2922     int i;
2923 
2924     for (i = 0; i < nChanges; i++) SYSPARAMS_SetSysColor( lpSysColor[i], lpColorValues[i] );
2925 
2926     /* Send WM_SYSCOLORCHANGE message to all windows */
2927 
2928     SendMessageTimeoutW( HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0, SMTO_ABORTIFHUNG, 2000, NULL );
2929 
2930     /* Repaint affected portions of all visible windows */
2931 
2932     RedrawWindow( GetDesktopWindow(), NULL, 0,
2933                 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN );
2934     return TRUE;
2935 }
2936 
2937 
2938 /*************************************************************************
2939  *              SetSysColorsTemp (USER32.@)
2940  *
2941  * UNDOCUMENTED !!
2942  *
2943  * Called by W98SE desk.cpl Control Panel Applet:
2944  * handle = SetSysColorsTemp(ptr, ptr, nCount);     ("set" call)
2945  * result = SetSysColorsTemp(NULL, NULL, handle);   ("restore" call)
2946  *
2947  * pPens is an array of COLORREF values, which seems to be used
2948  * to indicate the color values to create new pens with.
2949  *
2950  * pBrushes is an array of solid brush handles (returned by a previous
2951  * CreateSolidBrush), which seems to contain the brush handles to set
2952  * for the system colors.
2953  *
2954  * n seems to be used for
2955  *   a) indicating the number of entries to operate on (length of pPens,
2956  *      pBrushes)
2957  *   b) passing the handle that points to the previously used color settings.
2958  *      I couldn't figure out in hell what kind of handle this is on
2959  *      Windows. I just use a heap handle instead. Shouldn't matter anyway.
2960  *
2961  * RETURNS
2962  *     heap handle of our own copy of the current syscolors in case of
2963  *                 "set" call, i.e. pPens, pBrushes != NULL.
2964  *     TRUE (unconditionally !) in case of "restore" call,
2965  *          i.e. pPens, pBrushes == NULL.
2966  *     FALSE in case of either pPens != NULL and pBrushes == NULL
2967  *          or pPens == NULL and pBrushes != NULL.
2968  *
2969  * I'm not sure whether this implementation is 100% correct. [AM]
2970  */
2971 DWORD WINAPI SetSysColorsTemp( const COLORREF *pPens, const HBRUSH *pBrushes, DWORD n)
2972 {
2973     DWORD i;
2974 
2975     if (pPens && pBrushes) /* "set" call */
2976     {
2977         /* allocate our structure to remember old colors */
2978         LPVOID pOldCol = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD)+n*sizeof(HPEN)+n*sizeof(HBRUSH));
2979         LPVOID p = pOldCol;
2980         *(DWORD *)p = n; p = (char*)p + sizeof(DWORD);
2981         memcpy(p, SysColorPens, n*sizeof(HPEN)); p = (char*)p + n*sizeof(HPEN);
2982         memcpy(p, SysColorBrushes, n*sizeof(HBRUSH)); p = (char*)p + n*sizeof(HBRUSH);
2983 
2984         for (i=0; i < n; i++)
2985         {
2986             SysColorPens[i] = CreatePen( PS_SOLID, 1, pPens[i] );
2987             SysColorBrushes[i] = pBrushes[i];
2988         }
2989 
2990         return (DWORD)pOldCol; /* FIXME: pointer truncation */
2991     }
2992     if (!pPens && !pBrushes) /* "restore" call */
2993     {
2994         LPVOID pOldCol = (LPVOID)n; /* FIXME: not 64-bit safe */
2995         LPVOID p = pOldCol;
2996         DWORD nCount = *(DWORD *)p;
2997         p = (char*)p + sizeof(DWORD);
2998 
2999         for (i=0; i < nCount; i++)
3000         {
3001             DeleteObject(SysColorPens[i]);
3002             SysColorPens[i] = *(HPEN *)p; p = (char*)p + sizeof(HPEN);
3003         }
3004         for (i=0; i < nCount; i++)
3005         {
3006             SysColorBrushes[i] = *(HBRUSH *)p; p = (char*)p + sizeof(HBRUSH);
3007         }
3008         /* get rid of storage structure */
3009         HeapFree(GetProcessHeap(), 0, pOldCol);
3010 
3011         return TRUE;
3012     }
3013     return FALSE;
3014 }
3015 
3016 
3017 /***********************************************************************
3018  *              GetSysColorBrush (USER32.@)
3019  */
3020 HBRUSH WINAPI GetSysColorBrush( INT index )
3021 {
3022     if (0 <= index && index < NUM_SYS_COLORS) return SysColorBrushes[index];
3023     WARN("Unknown index(%d)\n", index );
3024     return GetStockObject(LTGRAY_BRUSH);
3025 }
3026 
3027 
3028 /***********************************************************************
3029  *              SYSCOLOR_GetPen
3030  */
3031 HPEN SYSCOLOR_GetPen( INT index )
3032 {
3033     /* We can assert here, because this function is internal to Wine */
3034     assert (0 <= index && index < NUM_SYS_COLORS);
3035     return SysColorPens[index];
3036 }
3037 
3038 
3039 /***********************************************************************
3040  *              ChangeDisplaySettingsA (USER32.@)
3041  */
3042 LONG WINAPI