sysparams.c 132 KB
Newer Older
1 2 3 4
/*
 * System parameters functions
 *
 * Copyright 1994 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 22
 */

#include "config.h"

23
#include <assert.h>
24
#include <stdarg.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28 29 30 31

#define NONAMELESSUNION
#define NONAMELESSSTRUCT

32 33
#include "windef.h"
#include "winbase.h"
34
#include "winnls.h"
35
#include "wingdi.h"
36
#include "winreg.h"
37 38 39
#include "wine/winuser16.h"
#include "winerror.h"

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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
enum spi_index
{
    SPI_SETBEEP_IDX,
    SPI_SETMOUSE_IDX,
    SPI_SETBORDER_IDX,
    SPI_SETKEYBOARDSPEED_IDX,
    SPI_ICONHORIZONTALSPACING_IDX,
    SPI_SETSCREENSAVETIMEOUT_IDX,
    SPI_SETGRIDGRANULARITY_IDX,
    SPI_SETKEYBOARDDELAY_IDX,
    SPI_ICONVERTICALSPACING_IDX,
    SPI_SETICONTITLEWRAP_IDX,
    SPI_SETMENUDROPALIGNMENT_IDX,
    SPI_SETDOUBLECLKWIDTH_IDX,
    SPI_SETDOUBLECLKHEIGHT_IDX,
    SPI_SETDOUBLECLICKTIME_IDX,
    SPI_SETMOUSEBUTTONSWAP_IDX,
    SPI_SETDRAGFULLWINDOWS_IDX,
    SPI_SETWORKAREA_IDX,
    SPI_SETSHOWSOUNDS_IDX,
    SPI_SETKEYBOARDPREF_IDX,
    SPI_SETSCREENREADER_IDX,
    SPI_SETSCREENSAVERRUNNING_IDX,
    SPI_SETFONTSMOOTHING_IDX,
    SPI_SETLISTBOXSMOOTHSCROLLING_IDX,
    SPI_SETMOUSEHOVERWIDTH_IDX,
    SPI_SETMOUSEHOVERHEIGHT_IDX,
    SPI_SETMOUSEHOVERTIME_IDX,
76
    SPI_SETMOUSESCROLLCHARS_IDX,
77 78 79 80
    SPI_SETMOUSESCROLLLINES_IDX,
    SPI_SETMENUSHOWDELAY_IDX,
    SPI_SETICONTITLELOGFONT_IDX,
    SPI_SETLOWPOWERACTIVE_IDX,
81
    SPI_SETSNAPTODEFBUTTON_IDX,
82 83
    SPI_SETPOWEROFFACTIVE_IDX,
    SPI_USERPREFERENCEMASK_IDX,
84
    SPI_NONCLIENTMETRICS_IDX,
85
    SPI_MINIMIZEDMETRICS_IDX,
86
    SPI_SETFOREGROUNDLOCKTIMEOUT_IDX,
87
    SPI_CARETWIDTH_IDX,
88
    SPI_SETMOUSESPEED_IDX,
89 90 91
    SPI_SETFONTSMOOTHINGTYPE_IDX,
    SPI_SETFONTSMOOTHINGCONTRAST_IDX,
    SPI_SETFONTSMOOTHINGORIENTATION_IDX,
92 93
    SPI_INDEX_COUNT
};
94

95 96
static const char * const DefSysColors[] =
{
97
    "Scrollbar", "212 208 200",              /* COLOR_SCROLLBAR */
98 99
    "Background", "58 110 165",              /* COLOR_BACKGROUND */
    "ActiveTitle", "10 36 106",              /* COLOR_ACTIVECAPTION */
100
    "InactiveTitle", "128 128 128",          /* COLOR_INACTIVECAPTION */
101
    "Menu", "212 208 200",                   /* COLOR_MENU */
102 103 104 105 106
    "Window", "255 255 255",                 /* COLOR_WINDOW */
    "WindowFrame", "0 0 0",                  /* COLOR_WINDOWFRAME */
    "MenuText", "0 0 0",                     /* COLOR_MENUTEXT */
    "WindowText", "0 0 0",                   /* COLOR_WINDOWTEXT */
    "TitleText", "255 255 255",              /* COLOR_CAPTIONTEXT */
107 108
    "ActiveBorder", "212 208 200",           /* COLOR_ACTIVEBORDER */
    "InactiveBorder", "212 208 200",         /* COLOR_INACTIVEBORDER */
109
    "AppWorkSpace", "128 128 128",           /* COLOR_APPWORKSPACE */
110
    "Hilight", "10 36 106",                  /* COLOR_HIGHLIGHT */
111
    "HilightText", "255 255 255",            /* COLOR_HIGHLIGHTTEXT */
112
    "ButtonFace", "212 208 200",             /* COLOR_BTNFACE */
113 114 115
    "ButtonShadow", "128 128 128",           /* COLOR_BTNSHADOW */
    "GrayText", "128 128 128",               /* COLOR_GRAYTEXT */
    "ButtonText", "0 0 0",                   /* COLOR_BTNTEXT */
116
    "InactiveTitleText", "212 208 200",      /* COLOR_INACTIVECAPTIONTEXT */
117
    "ButtonHilight", "255 255 255",          /* COLOR_BTNHIGHLIGHT */
118 119
    "ButtonDkShadow", "64 64 64",            /* COLOR_3DDKSHADOW */
    "ButtonLight", "212 208 200",            /* COLOR_3DLIGHT */
120 121
    "InfoText", "0 0 0",                     /* COLOR_INFOTEXT */
    "InfoWindow", "255 255 225",             /* COLOR_INFOBK */
122 123
    "ButtonAlternateFace", "181 181 181",    /* COLOR_ALTERNATEBTNFACE */
    "HotTrackingColor", "0 0 128",           /* COLOR_HOTLIGHT */
124 125
    "GradientActiveTitle", "166 202 240",    /* COLOR_GRADIENTACTIVECAPTION */
    "GradientInactiveTitle", "192 192 192",  /* COLOR_GRADIENTINACTIVECAPTION */
126
    "MenuHilight", "10 36 106",              /* COLOR_MENUHILIGHT */
127
    "MenuBar", "212 208 200"                 /* COLOR_MENUBAR */
128 129
};

130 131 132 133 134 135 136
/**
 * Names of the registry subkeys of HKEY_CURRENT_USER key and value names
 * for the system parameters.
 * Names of the keys are created by adding string "_REGKEY" to
 * "SET" action names, value names are created by adding "_REG_NAME"
 * to the "SET" action name.
 */
137 138 139 140 141 142
static const WCHAR SPI_SETBEEP_REGKEY[]=                      {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','S','o','u','n','d',0};
static const WCHAR SPI_SETBEEP_VALNAME[]=                     {'B','e','e','p',0};
static const WCHAR SPI_SETMOUSE_REGKEY[]=                     {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSE_VALNAME1[]=                   {'M','o','u','s','e','T','h','r','e','s','h','o','l','d','1',0};
static const WCHAR SPI_SETMOUSE_VALNAME2[]=                   {'M','o','u','s','e','T','h','r','e','s','h','o','l','d','2',0};
static const WCHAR SPI_SETMOUSE_VALNAME3[]=                   {'M','o','u','s','e','S','p','e','e','d',0};
143 144
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','\\',
                                                               'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
static const WCHAR SPI_SETBORDER_VALNAME[]=                   {'B','o','r','d','e','r','W','i','d','t','h',0};
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};
static const WCHAR SPI_SETKEYBOARDSPEED_VALNAME[]=            {'K','e','y','b','o','a','r','d','S','p','e','e','d',0};
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','\\',
                                                               'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
static const WCHAR SPI_ICONHORIZONTALSPACING_VALNAME[]=       {'I','c','o','n','S','p','a','c','i','n','g',0};
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};
static const WCHAR SPI_SETSCREENSAVETIMEOUT_VALNAME[]=        {'S','c','r','e','e','n','S','a','v','e','T','i','m','e','O','u','t',0};
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};
static const WCHAR SPI_SETSCREENSAVEACTIVE_VALNAME[]=         {'S','c','r','e','e','n','S','a','v','e','A','c','t','i','v','e',0};
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};
static const WCHAR SPI_SETGRIDGRANULARITY_VALNAME[]=          {'G','r','i','d','G','r','a','n','u','l','a','r','i','t','y',0};
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};
static const WCHAR SPI_SETKEYBOARDDELAY_VALNAME[]=            {'K','e','y','b','o','a','r','d','D','e','l','a','y',0};
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','\\',
                                                               'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
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};
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','\\',
                                                               'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
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};
static const WCHAR SPI_SETICONTITLEWRAP_VALNAME[]=            {'I','c','o','n','T','i','t','l','e','W','r','a','p',0};
166 167 168
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','\\',
                                                               'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
static const WCHAR SPI_SETICONTITLELOGFONT_VALNAME[]=         {'I','c','o','n','F','o','n','t',0};
169 170 171 172 173 174 175
static const WCHAR SPI_SETMENUDROPALIGNMENT_REGKEY1[]=        {'S','o','f','t','w','a','r','e','\\',
                                                               'M','i','c','r','o','s','o','f','t','\\',
                                                               'W','i','n','d','o','w','s',' ','N','T','\\',
                                                               'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
                                                               'W','i','n','d','o','w','s',0};
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};
static const WCHAR SPI_SETMENUDROPALIGNMENT_VALNAME[]=        {'M','e','n','u','D','r','o','p','A','l','i','g','n','m','e','n','t',0};
176 177
static const WCHAR SPI_SETSNAPTODEFBUTTON_REGKEY[]=           {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
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};
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
static const WCHAR SPI_SETDOUBLECLKWIDTH_REGKEY1[]=           {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
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};
static const WCHAR SPI_SETDOUBLECLKWIDTH_VALNAME[]=           {'D','o','u','b','l','e','C','l','i','c','k','W','i','d','t','h',0};
static const WCHAR SPI_SETDOUBLECLKHEIGHT_REGKEY1[]=          {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
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};
static const WCHAR SPI_SETDOUBLECLKHEIGHT_VALNAME[]=          {'D','o','u','b','l','e','C','l','i','c','k','H','e','i','g','h','t',0};
static const WCHAR SPI_SETDOUBLECLICKTIME_REGKEY[]=           {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETDOUBLECLICKTIME_VALNAME[]=          {'D','o','u','b','l','e','C','l','i','c','k','S','p','e','e','d',0};
static const WCHAR SPI_SETMOUSEBUTTONSWAP_REGKEY[]=           {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSEBUTTONSWAP_VALNAME[]=          {'S','w','a','p','M','o','u','s','e','B','u','t','t','o','n','s',0};
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};
static const WCHAR SPI_SETDRAGFULLWINDOWS_VALNAME[]=          {'D','r','a','g','F','u','l','l','W','i','n','d','o','w','s',0};
static const WCHAR SPI_SETSHOWSOUNDS_REGKEY[]=                {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
                                                               'A','c','c','e','s','s','i','b','i','l','i','t','y','\\',
                                                               'S','h','o','w','S','o','u','n','d','s',0};
static const WCHAR SPI_SETSHOWSOUNDS_VALNAME[]=               {'O','n',0};
194 195 196 197 198 199 200 201
static const WCHAR SPI_SETKEYBOARDPREF_REGKEY[]=              {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
                                                               'A','c','c','e','s','s','i','b','i','l','i','t','y','\\',
                                                               'K','e','y','b','o','a','r','d',' ','P','r','e','f','e','r','e','n','c','e',0};
static const WCHAR SPI_SETKEYBOARDPREF_VALNAME[]=             {'O','n',0};
static const WCHAR SPI_SETSCREENREADER_REGKEY[]=              {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
                                                               'A','c','c','e','s','s','i','b','i','l','i','t','y','\\',
                                                               'B','l','i','n','d',' ','A','c','c','e','s','s',0};
static const WCHAR SPI_SETSCREENREADER_VALNAME[]=             {'O','n',0};
202 203 204 205
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};
static const WCHAR SPI_SETDESKWALLPAPER_VALNAME[]=            {'W','a','l','l','p','a','p','e','r',0};
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};
static const WCHAR SPI_SETFONTSMOOTHING_VALNAME[]=            {'F','o','n','t','S','m','o','o','t','h','i','n','g',0};
206 207 208 209
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};
static const WCHAR SPI_SETLOWPOWERACTIVE_VALNAME[]=           {'L','o','w','P','o','w','e','r','A','c','t','i','v','e',0};
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};
static const WCHAR SPI_SETPOWEROFFACTIVE_VALNAME[]=           {'P','o','w','e','r','O','f','f','A','c','t','i','v','e',0};
210 211
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};
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};
212 213 214 215 216 217
static const WCHAR SPI_SETMOUSEHOVERWIDTH_REGKEY[]=           {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSEHOVERWIDTH_VALNAME[]=          {'M','o','u','s','e','H','o','v','e','r','W','i','d','t','h',0};
static const WCHAR SPI_SETMOUSEHOVERHEIGHT_REGKEY[]=          {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSEHOVERHEIGHT_VALNAME[]=         {'M','o','u','s','e','H','o','v','e','r','H','e','i','g','h','t',0};
static const WCHAR SPI_SETMOUSEHOVERTIME_REGKEY[]=            {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSEHOVERTIME_VALNAME[]=           {'M','o','u','s','e','H','o','v','e','r','T','i','m','e',0};
218 219
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};
static const WCHAR SPI_SETMOUSESCROLLCHARS_VALNAME[]=         {'W','h','e','e','l','S','c','r','o','l','l','C','h','a','r','s',0};
220 221 222 223
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};
static const WCHAR SPI_SETMOUSESCROLLLINES_VALNAME[]=         {'W','h','e','e','l','S','c','r','o','l','l','L','i','n','e','s',0};
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};
static const WCHAR SPI_SETMENUSHOWDELAY_VALNAME[]=            {'M','e','n','u','S','h','o','w','D','e','l','a','y',0};
224 225
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};
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};
226 227
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};
static const WCHAR SPI_CARETWIDTH_VALNAME[]=                  {'C','a','r','e','t','W','i','d','t','h',0};
228 229
static const WCHAR SPI_SETMOUSESPEED_REGKEY[]=                {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0};
static const WCHAR SPI_SETMOUSESPEED_VALNAME[]=               {'M','o','u','s','e','S','e','n','s','i','t','i','v','i','t','y',0};
230 231 232 233 234 235
static const WCHAR SPI_SETFONTSMOOTHINGTYPE_REGKEY[]=         {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0};
static const WCHAR SPI_SETFONTSMOOTHINGTYPE_VALNAME[]=        {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0};
static const WCHAR SPI_SETFONTSMOOTHINGCONTRAST_REGKEY[]=     {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0};
static const WCHAR SPI_SETFONTSMOOTHINGCONTRAST_VALNAME[]=    {'F','o','n','t','S','m','o','o','t','h','i','n','g','G','a','m','m','a',0};
static const WCHAR SPI_SETFONTSMOOTHINGORIENTATION_REGKEY[]=  {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0};
static const WCHAR SPI_SETFONTSMOOTHINGORIENTATION_VALNAME[]= {'F','o','n','t','S','m','o','o','t','h','i','n','g','O','r','i','e','n','t','a','t','i','o','n',0};
236

237
/* FIXME - real values */
238 239
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};
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};
240

241 242 243 244 245 246 247 248 249 250
static const WCHAR METRICS_REGKEY[]=                  {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p','\\',
                                                       'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
static const WCHAR METRICS_SCROLLWIDTH_VALNAME[]=     {'S','c','r','o','l','l','W','i','d','t','h',0};
static const WCHAR METRICS_SCROLLHEIGHT_VALNAME[]=    {'S','c','r','o','l','l','H','e','i','g','h','t',0};
static const WCHAR METRICS_CAPTIONWIDTH_VALNAME[]=    {'C','a','p','t','i','o','n','W','i','d','t','h',0};
static const WCHAR METRICS_CAPTIONHEIGHT_VALNAME[]=   {'C','a','p','t','i','o','n','H','e','i','g','h','t',0};
static const WCHAR METRICS_SMCAPTIONWIDTH_VALNAME[]=  {'S','m','C','a','p','t','i','o','n','W','i','d','t','h',0};
static const WCHAR METRICS_SMCAPTIONHEIGHT_VALNAME[]= {'S','m','C','a','p','t','i','o','n','H','e','i','g','h','t',0};
static const WCHAR METRICS_MENUWIDTH_VALNAME[]=       {'M','e','n','u','W','i','d','t','h',0};
static const WCHAR METRICS_MENUHEIGHT_VALNAME[]=      {'M','e','n','u','H','e','i','g','h','t',0};
251 252
static const WCHAR METRICS_ICONSIZE_VALNAME[]=        {'S','h','e','l','l',' ','I','c','o','n',' ','S','i','z','e',0};
static const WCHAR METRICS_BORDERWIDTH_VALNAME[]=     {'B','o','r','d','e','r','W','i','d','t','h',0};
253 254 255 256 257
static const WCHAR METRICS_CAPTIONLOGFONT_VALNAME[]=  {'C','a','p','t','i','o','n','F','o','n','t',0};
static const WCHAR METRICS_SMCAPTIONLOGFONT_VALNAME[]={'S','m','C','a','p','t','i','o','n','F','o','n','t',0};
static const WCHAR METRICS_MENULOGFONT_VALNAME[]=     {'M','e','n','u','F','o','n','t',0};
static const WCHAR METRICS_MESSAGELOGFONT_VALNAME[]=  {'M','e','s','s','a','g','e','F','o','n','t',0};
static const WCHAR METRICS_STATUSLOGFONT_VALNAME[]=   {'S','t','a','t','u','s','F','o','n','t',0};
258 259 260 261 262
/* minimized metrics */
static const WCHAR METRICS_MINWIDTH_VALNAME[] =   {'M','i','n','W','i','d','t','h','\0'}; 
static const WCHAR METRICS_MINHORZGAP_VALNAME[] = {'M','i','n','H','o','r','z','G','a','p','\0'};
static const WCHAR METRICS_MINVERTGAP_VALNAME[] = {'M','i','n','V','e','r','t','G','a','p','\0'};
static const WCHAR METRICS_MINARRANGE_VALNAME[] = {'M','i','n','A','r','r','a','n','g','e','\0'}; 
263

264
static const WCHAR WINE_CURRENT_USER_REGKEY[] = {'S','o','f','t','w','a','r','e','\\',
265
                                                 'W','i','n','e',0};
266

267 268 269 270
/* volatile registry branch under WINE_CURRENT_USER_REGKEY for temporary values storage */
static const WCHAR WINE_CURRENT_USER_REGKEY_TEMP_PARAMS[] = {'T','e','m','p','o','r','a','r','y',' ',
                                                             'S','y','s','t','e','m',' ',
                                                             'P','a','r','a','m','e','t','e','r','s',0};
271 272 273 274 275 276 277

static const WCHAR Yes[]=                                    {'Y','e','s',0};
static const WCHAR No[]=                                     {'N','o',0};
static const WCHAR Desktop[]=                                {'D','e','s','k','t','o','p',0};
static const WCHAR Pattern[]=                                {'P','a','t','t','e','r','n',0};
static const WCHAR MenuFont[]=                               {'M','e','n','u','F','o','n','t',0};
static const WCHAR MenuFontSize[]=                           {'M','e','n','u','F','o','n','t','S','i','z','e',0};
278 279 280 281
static const WCHAR StatusFont[]=                             {'S','t','a','t','u','s','F','o','n','t',0};
static const WCHAR StatusFontSize[]=                         {'S','t','a','t','u','s','F','o','n','t','S','i','z','e',0};
static const WCHAR MessageFont[]=                            {'M','e','s','s','a','g','e','F','o','n','t',0};
static const WCHAR MessageFontSize[]=                        {'M','e','s','s','a','g','e','F','o','n','t','S','i','z','e',0};
282 283 284
static const WCHAR System[]=                                 {'S','y','s','t','e','m',0};
static const WCHAR IconTitleSize[]=                          {'I','c','o','n','T','i','t','l','e','S','i','z','e',0};
static const WCHAR IconTitleFaceName[]=                      {'I','c','o','n','T','i','t','l','e','F','a','c','e','N','a','m','e',0};
285
static const WCHAR defPattern[]=                             {'0',' ','0',' ','0',' ','0',' ','0',' ','0',' ','0',' ','0',0};
286 287
static const WCHAR CSu[]=                                    {'%','u',0};
static const WCHAR CSd[]=                                    {'%','d',0};
288 289

/* Indicators whether system parameter value is loaded */
290
static char spi_loaded[SPI_INDEX_COUNT];
291 292 293 294

static BOOL notify_change = TRUE;

/* System parameters storage */
295
static BOOL beep_active = TRUE;
296 297 298
static int mouse_threshold1 = 6;
static int mouse_threshold2 = 10;
static int mouse_speed = 1;
299 300 301 302 303
static UINT border = 1;
static UINT keyboard_speed = 31;
static UINT screensave_timeout = 300;
static UINT grid_granularity = 0;
static UINT keyboard_delay = 1;
304 305
static UINT double_click_width = 4;
static UINT double_click_height = 4;
306
static UINT double_click_time = 500;
307 308
static BOOL drag_full_windows = FALSE;
static RECT work_area;
309 310
static BOOL keyboard_pref = TRUE;
static BOOL screen_reader = FALSE;
311 312 313
static UINT mouse_hover_width = 4;
static UINT mouse_hover_height = 4;
static UINT mouse_hover_time = 400;
314
static UINT mouse_scroll_chars = 3;
315 316
static UINT mouse_scroll_lines = 3;
static UINT menu_show_delay = 400;
317
static UINT menu_drop_alignment = 0;
318
static BOOL screensaver_running = FALSE;
319
static UINT font_smoothing = 0;  /* 0x01 for 95/98/NT, 0x02 for 98/ME/2k/XP */
320
static BOOL lowpoweractive = FALSE;
321
static BOOL poweroffactive = FALSE;
322
static BOOL show_sounds = FALSE;
323
static BOOL snap_to_default_button = FALSE;
324
static BOOL swap_buttons = FALSE;
325
static UINT foreground_lock_timeout = 0;
326
static UINT caret_width = 1;
327
static UINT mouse_sensitivity = 10;
328 329 330
static UINT font_smoothing_type = 0;
static UINT font_smoothing_contrast = 0;
static UINT font_smoothing_orientation = 0;
331
static BYTE user_prefs[4];
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347

static MINIMIZEDMETRICS minimized_metrics =
{
    sizeof(MINIMIZEDMETRICS),
    154,      /* iWidth */
    0,        /* iHorzGap */
    0,        /* iVertGap */
    ARW_HIDE  /* iArrange */
};

static ICONMETRICSW icon_metrics =
{
    sizeof(ICONMETRICSW),
    75,   /* iHorzSpacing */
    75,   /* iVertSpacing */
    TRUE, /* iTitleWrap */
348
    { -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
      OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH }   /* lfFont */
};

static NONCLIENTMETRICSW nonclient_metrics =
{
    sizeof(NONCLIENTMETRICSW),
    1,     /* iBorderWidth */
    16,    /* iScrollWidth */
    16,    /* iScrollHeight */
    18,    /* iCaptionWidth */
    18,    /* iCaptionHeight */
    { 0 }, /* lfCaptionFont */
    13,    /* iSmCaptionWidth */
    15,    /* iSmCaptionHeight */
    { 0 }, /* lfSmCaptionFont */
    18,    /* iMenuWidth */
    18,    /* iMenuHeight */
    { 0 }, /* lfMenuFont */
    { 0 }, /* lfStatusFont */
    { 0 }  /* lfMessageFont */
};

371 372 373 374
/* some additional non client metric info */
static TEXTMETRICW tmMenuFont;
static UINT CaptionFontAvCharWidth;

375
static SIZE icon_size = { 32, 32 };
376

377 378 379 380 381 382 383 384 385 386
#define NUM_SYS_COLORS     (COLOR_MENUBAR+1)

static COLORREF SysColors[NUM_SYS_COLORS];
static HBRUSH SysColorBrushes[NUM_SYS_COLORS];
static HPEN   SysColorPens[NUM_SYS_COLORS];

static const WORD wPattern55AA[] = { 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa };

HBRUSH SYSCOLOR_55AABrush = 0;

387
extern void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set );
388

389

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
/* This function is a copy of the one in objects/font.c */
static void SYSPARAMS_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
{
    font16->lfHeight = font32->lfHeight;
    font16->lfWidth = font32->lfWidth;
    font16->lfEscapement = font32->lfEscapement;
    font16->lfOrientation = font32->lfOrientation;
    font16->lfWeight = font32->lfWeight;
    font16->lfItalic = font32->lfItalic;
    font16->lfUnderline = font32->lfUnderline;
    font16->lfStrikeOut = font32->lfStrikeOut;
    font16->lfCharSet = font32->lfCharSet;
    font16->lfOutPrecision = font32->lfOutPrecision;
    font16->lfClipPrecision = font32->lfClipPrecision;
    font16->lfQuality = font32->lfQuality;
    font16->lfPitchAndFamily = font32->lfPitchAndFamily;
    lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
}

Rein Klazes's avatar
Rein Klazes committed
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
static void SYSPARAMS_LogFont16To32W( const LOGFONT16 *font16, LPLOGFONTW font32 )
{
    font32->lfHeight = font16->lfHeight;
    font32->lfWidth = font16->lfWidth;
    font32->lfEscapement = font16->lfEscapement;
    font32->lfOrientation = font16->lfOrientation;
    font32->lfWeight = font16->lfWeight;
    font32->lfItalic = font16->lfItalic;
    font32->lfUnderline = font16->lfUnderline;
    font32->lfStrikeOut = font16->lfStrikeOut;
    font32->lfCharSet = font16->lfCharSet;
    font32->lfOutPrecision = font16->lfOutPrecision;
    font32->lfClipPrecision = font16->lfClipPrecision;
    font32->lfQuality = font16->lfQuality;
    font32->lfPitchAndFamily = font16->lfPitchAndFamily;
    MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
    font32->lfFaceName[LF_FACESIZE-1] = 0;
}

428
static void SYSPARAMS_LogFont32WTo32A( const LOGFONTW* font32W, LPLOGFONTA font32A )
429
{
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
    font32A->lfHeight = font32W->lfHeight;
    font32A->lfWidth = font32W->lfWidth;
    font32A->lfEscapement = font32W->lfEscapement;
    font32A->lfOrientation = font32W->lfOrientation;
    font32A->lfWeight = font32W->lfWeight;
    font32A->lfItalic = font32W->lfItalic;
    font32A->lfUnderline = font32W->lfUnderline;
    font32A->lfStrikeOut = font32W->lfStrikeOut;
    font32A->lfCharSet = font32W->lfCharSet;
    font32A->lfOutPrecision = font32W->lfOutPrecision;
    font32A->lfClipPrecision = font32W->lfClipPrecision;
    font32A->lfQuality = font32W->lfQuality;
    font32A->lfPitchAndFamily = font32W->lfPitchAndFamily;
    WideCharToMultiByte( CP_ACP, 0, font32W->lfFaceName, -1, font32A->lfFaceName, LF_FACESIZE, NULL, NULL );
    font32A->lfFaceName[LF_FACESIZE-1] = 0;
445 446
}

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA* font32A, LPLOGFONTW font32W )
{
    font32W->lfHeight = font32A->lfHeight;
    font32W->lfWidth = font32A->lfWidth;
    font32W->lfEscapement = font32A->lfEscapement;
    font32W->lfOrientation = font32A->lfOrientation;
    font32W->lfWeight = font32A->lfWeight;
    font32W->lfItalic = font32A->lfItalic;
    font32W->lfUnderline = font32A->lfUnderline;
    font32W->lfStrikeOut = font32A->lfStrikeOut;
    font32W->lfCharSet = font32A->lfCharSet;
    font32W->lfOutPrecision = font32A->lfOutPrecision;
    font32W->lfClipPrecision = font32A->lfClipPrecision;
    font32W->lfQuality = font32A->lfQuality;
    font32W->lfPitchAndFamily = font32A->lfPitchAndFamily;
    MultiByteToWideChar( CP_ACP, 0, font32A->lfFaceName, -1, font32W->lfFaceName, LF_FACESIZE );
    font32W->lfFaceName[LF_FACESIZE-1] = 0;
}

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
static void SYSPARAMS_NonClientMetrics32ATo16( const NONCLIENTMETRICSA* lpnm32, LPNONCLIENTMETRICS16 lpnm16 )
{
    lpnm16->iBorderWidth	= lpnm32->iBorderWidth;
    lpnm16->iScrollWidth	= lpnm32->iScrollWidth;
    lpnm16->iScrollHeight	= lpnm32->iScrollHeight;
    lpnm16->iCaptionWidth	= lpnm32->iCaptionWidth;
    lpnm16->iCaptionHeight	= lpnm32->iCaptionHeight;
    SYSPARAMS_LogFont32ATo16( &lpnm32->lfCaptionFont,	&lpnm16->lfCaptionFont );
    lpnm16->iSmCaptionWidth	= lpnm32->iSmCaptionWidth;
    lpnm16->iSmCaptionHeight	= lpnm32->iSmCaptionHeight;
    SYSPARAMS_LogFont32ATo16( &lpnm32->lfSmCaptionFont,	&lpnm16->lfSmCaptionFont );
    lpnm16->iMenuWidth		= lpnm32->iMenuWidth;
    lpnm16->iMenuHeight		= lpnm32->iMenuHeight;
    SYSPARAMS_LogFont32ATo16( &lpnm32->lfMenuFont,	&lpnm16->lfMenuFont );
    SYSPARAMS_LogFont32ATo16( &lpnm32->lfStatusFont,	&lpnm16->lfStatusFont );
    SYSPARAMS_LogFont32ATo16( &lpnm32->lfMessageFont,	&lpnm16->lfMessageFont );
}

484
static void SYSPARAMS_NonClientMetrics32WTo32A( const NONCLIENTMETRICSW* lpnm32W, LPNONCLIENTMETRICSA lpnm32A )
485
{
486 487 488 489 490 491 492 493 494 495 496 497 498 499
    lpnm32A->iBorderWidth	= lpnm32W->iBorderWidth;
    lpnm32A->iScrollWidth	= lpnm32W->iScrollWidth;
    lpnm32A->iScrollHeight	= lpnm32W->iScrollHeight;
    lpnm32A->iCaptionWidth	= lpnm32W->iCaptionWidth;
    lpnm32A->iCaptionHeight	= lpnm32W->iCaptionHeight;
    SYSPARAMS_LogFont32WTo32A(  &lpnm32W->lfCaptionFont,	&lpnm32A->lfCaptionFont );
    lpnm32A->iSmCaptionWidth	= lpnm32W->iSmCaptionWidth;
    lpnm32A->iSmCaptionHeight	= lpnm32W->iSmCaptionHeight;
    SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfSmCaptionFont,	&lpnm32A->lfSmCaptionFont );
    lpnm32A->iMenuWidth		= lpnm32W->iMenuWidth;
    lpnm32A->iMenuHeight	= lpnm32W->iMenuHeight;
    SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfMenuFont,		&lpnm32A->lfMenuFont );
    SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfStatusFont,		&lpnm32A->lfStatusFont );
    SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfMessageFont,		&lpnm32A->lfMessageFont );
500 501
}

502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA* lpnm32A, LPNONCLIENTMETRICSW lpnm32W )
{
    lpnm32W->iBorderWidth	= lpnm32A->iBorderWidth;
    lpnm32W->iScrollWidth	= lpnm32A->iScrollWidth;
    lpnm32W->iScrollHeight	= lpnm32A->iScrollHeight;
    lpnm32W->iCaptionWidth	= lpnm32A->iCaptionWidth;
    lpnm32W->iCaptionHeight	= lpnm32A->iCaptionHeight;
    SYSPARAMS_LogFont32ATo32W(  &lpnm32A->lfCaptionFont,	&lpnm32W->lfCaptionFont );
    lpnm32W->iSmCaptionWidth	= lpnm32A->iSmCaptionWidth;
    lpnm32W->iSmCaptionHeight	= lpnm32A->iSmCaptionHeight;
    SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfSmCaptionFont,	&lpnm32W->lfSmCaptionFont );
    lpnm32W->iMenuWidth		= lpnm32A->iMenuWidth;
    lpnm32W->iMenuHeight	= lpnm32A->iMenuHeight;
    SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMenuFont,		&lpnm32W->lfMenuFont );
    SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfStatusFont,		&lpnm32W->lfStatusFont );
    SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMessageFont,		&lpnm32W->lfMessageFont );
}

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544

/* Helper functions to retrieve monitors info */

struct monitor_info
{
    int count;
    RECT virtual_rect;
};

static BOOL CALLBACK monitor_info_proc( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
{
    struct monitor_info *info = (struct monitor_info *)lp;
    info->count++;
    UnionRect( &info->virtual_rect, &info->virtual_rect, rect );
    return TRUE;
}

static void get_monitors_info( struct monitor_info *info )
{
    info->count = 0;
    SetRectEmpty( &info->virtual_rect );
    EnumDisplayMonitors( 0, NULL, monitor_info_proc, (LPARAM)info );
}


545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
/* get text metrics and/or "average" char width of the specified logfont 
 * for the specified dc */
static void get_text_metr_size( HDC hdc, LOGFONTW *plf, TEXTMETRICW * ptm, UINT *psz)
{
    HFONT hfont, hfontsav;
    TEXTMETRICW tm;
    if( !ptm) ptm = &tm;
    hfont = CreateFontIndirectW( plf);
    if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
        ptm->tmHeight = -1;
        if( psz) *psz = 10;
        if( hfont) DeleteObject( hfont);
        return;
    }
    GetTextMetricsW( hdc, ptm);
    if( psz)
        if( !(*psz = GdiGetCharDimensions( hdc, ptm, NULL)))
            *psz = 10;
    SelectObject( hdc, hfontsav);
    DeleteObject( hfont);
}
566 567 568 569 570 571 572 573 574 575 576 577 578

/***********************************************************************
 *           get_volatile_regkey
 *
 * Return a handle to the volatile registry key used to store
 * non-permanently modified parameters.
 */
static HKEY get_volatile_regkey(void)
{
    static HKEY volatile_key;

    if (!volatile_key)
    {
579 580
        HKEY key;
        /* This must be non-volatile! */
581
        if (RegCreateKeyExW( HKEY_CURRENT_USER, WINE_CURRENT_USER_REGKEY,
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
                             0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0,
                             &key, 0 ) != ERROR_SUCCESS)
        {
            ERR("Can't create wine registry branch\n");
        }
        else
        {
            /* @@ Wine registry key: HKCU\Software\Wine\Temporary System Parameters */
            if (RegCreateKeyExW( key, WINE_CURRENT_USER_REGKEY_TEMP_PARAMS,
                                 0, 0, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 0,
                                 &volatile_key, 0 ) != ERROR_SUCCESS)
                ERR("Can't create non-permanent wine registry branch\n");

            RegCloseKey(key);
        }
597 598 599 600 601 602 603 604 605
    }
    return volatile_key;
}

/***********************************************************************
 *           SYSPARAMS_NotifyChange
 *
 * Sends notification about system parameter update.
 */
606
static void SYSPARAMS_NotifyChange( UINT uiAction, UINT fWinIni )
607
{
608 609
    static const WCHAR emptyW[1];

610 611 612 613 614
    if (notify_change)
    {
        if (fWinIni & SPIF_UPDATEINIFILE)
        {
            if (fWinIni & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE))
615 616 617
                SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE,
                                    uiAction, (LPARAM) emptyW,
                                    SMTO_ABORTIFHUNG, 2000, NULL );
618
        }
619
        else
620 621 622 623 624 625 626 627 628 629
        {
            /* FIXME notify other wine processes with internal message */
        }
    }
}


/***********************************************************************
 * Loads system parameter from user profile.
 */
630
static BOOL SYSPARAMS_LoadRaw( LPCWSTR lpRegKey, LPCWSTR lpValName, LPBYTE lpBuf, DWORD count )
631 632 633 634 635
{
    BOOL ret = FALSE;
    DWORD type;
    HKEY hKey;

636
    memset( lpBuf, 0, count );
637 638
    if ((RegOpenKeyW( get_volatile_regkey(), lpRegKey, &hKey ) == ERROR_SUCCESS) ||
        (RegOpenKeyW( HKEY_CURRENT_USER, lpRegKey, &hKey ) == ERROR_SUCCESS))
639
    {
640
        ret = !RegQueryValueExW( hKey, lpValName, NULL, &type, lpBuf, &count);
641 642 643 644 645
        RegCloseKey( hKey );
    }
    return ret;
}

646 647 648 649 650
static BOOL SYSPARAMS_Load( LPCWSTR lpRegKey, LPCWSTR lpValName, LPWSTR lpBuf, DWORD count )
{
  return SYSPARAMS_LoadRaw( lpRegKey, lpValName, (LPBYTE)lpBuf, count );
}

651 652 653
/***********************************************************************
 * Saves system parameter to user profile.
 */
654 655 656 657 658

/* Save data as-is */
static BOOL SYSPARAMS_SaveRaw( LPCWSTR lpRegKey, LPCWSTR lpValName, 
                               const BYTE* lpValue, DWORD valueSize, 
                               DWORD type, UINT fWinIni )
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
{
    HKEY hKey;
    HKEY hBaseKey;
    DWORD dwOptions;
    BOOL ret = FALSE;

    if (fWinIni & SPIF_UPDATEINIFILE)
    {
        hBaseKey = HKEY_CURRENT_USER;
        dwOptions = 0;
    }
    else
    {
        hBaseKey = get_volatile_regkey();
        dwOptions = REG_OPTION_VOLATILE;
    }

676
    if (RegCreateKeyExW( hBaseKey, lpRegKey,
677 678 679
                         0, 0, dwOptions, KEY_ALL_ACCESS,
                         0, &hKey, 0 ) == ERROR_SUCCESS)
    {
680 681
        if (RegSetValueExW( hKey, lpValName, 0, type,
                            lpValue, valueSize) == ERROR_SUCCESS)
682 683 684
        {
            ret = TRUE;
            if (hBaseKey == HKEY_CURRENT_USER)
685
                RegDeleteKeyW( get_volatile_regkey(), lpRegKey );
686 687 688 689 690 691
        }
        RegCloseKey( hKey );
    }
    return ret;
}

692 693 694 695 696 697 698 699
/* Convenience function to save strings */
static BOOL SYSPARAMS_Save( LPCWSTR lpRegKey, LPCWSTR lpValName, LPCWSTR lpValue,
                            UINT fWinIni )
{
    return SYSPARAMS_SaveRaw( lpRegKey, lpValName, (const BYTE*)lpValue, 
        (strlenW(lpValue) + 1)*sizeof(WCHAR), REG_SZ, fWinIni );
}

700 701 702 703 704 705 706 707
/* Convenience function to save logical fonts */
static BOOL SYSPARAMS_SaveLogFont( LPCWSTR lpRegKey, LPCWSTR lpValName,
                                    LPLOGFONTW plf, UINT fWinIni )
{
    return SYSPARAMS_SaveRaw( lpRegKey, lpValName, (const BYTE*)plf, 
        sizeof( LOGFONTW), REG_BINARY, fWinIni );
}

708

709 710 711 712
static inline HDC get_display_dc(void)
{
    static const WCHAR DISPLAY[] = {'D','I','S','P','L','A','Y',0};
    static HDC display_dc;
713 714 715 716 717
    if (!display_dc)
    {
        display_dc = CreateICW( DISPLAY, NULL, NULL, NULL );
        __wine_make_gdi_object_system( display_dc, TRUE );
    }
718 719 720 721 722 723 724 725 726 727
    return display_dc;
}

static inline int get_display_dpi(void)
{
    static int display_dpi;
    if (!display_dpi) display_dpi = GetDeviceCaps( get_display_dc(), LOGPIXELSY );
    return display_dpi;
}

728
/***********************************************************************
729
 * SYSPARAMS_Twips2Pixels
730
 *
731 732
 * Convert a dimension value that was obtained from the registry.  These are
 * quoted as being "twips" values if negative and pixels if positive.
733 734
 * One inch is 1440 twips. So to convert, divide by 1440 to get inches and
 * multiply that by the dots-per-inch to get the size in pixels. 
735 736 737 738 739
 * See for example
 *   MSDN Library - April 2001 -> Resource Kits ->
 *       Windows 2000 Resource Kit Reference ->
 *       Technical Reference to the Windows 2000 Registry ->
 *       HKEY_CURRENT_USER -> Control Panel -> Desktop -> WindowMetrics
740
 */
741
static inline int SYSPARAMS_Twips2Pixels(int x)
742
{
743
    if (x < 0)
744
        x = (-x * get_display_dpi() + 720) / 1440;
745
    return x;
746 747
}

748
/***********************************************************************
749
 * get_reg_metric
750
 *
751 752 753 754 755
 * Get a registry entry from the already open key.  This allows us to open the
 * section once and read several values.
 *
 * Of course this function belongs somewhere more usable but here will do
 * for now.
756
 */
757
static int get_reg_metric( HKEY hkey, LPCWSTR lpValName, int default_value )
758
{
759 760 761
    int value = default_value;
    if (hkey)
    {
762
        WCHAR buffer[128];
763
        DWORD type, count = sizeof(buffer);
764
        if(!RegQueryValueExW( hkey, lpValName, NULL, &type, (LPBYTE)buffer, &count) )
765
        {
766
            if (type != REG_SZ)
767
            {
768 769 770 771
                /* Are there any utilities for converting registry entries
                 * between formats?
                 */
                /* FIXME_(reg)("We need reg format converter\n"); */
772
            }
773
            else
774
                value = atoiW(buffer);
775
        }
776
    }
777
    return SYSPARAMS_Twips2Pixels(value);
778 779
}

780

781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
/*************************************************************************
 *             SYSPARAMS_SetSysColor
 */
static void SYSPARAMS_SetSysColor( int index, COLORREF color )
{
    if (index < 0 || index >= NUM_SYS_COLORS) return;
    SysColors[index] = color;
    if (SysColorBrushes[index])
    {
        __wine_make_gdi_object_system( SysColorBrushes[index], FALSE);
        DeleteObject( SysColorBrushes[index] );
    }
    SysColorBrushes[index] = CreateSolidBrush( color );
    __wine_make_gdi_object_system( SysColorBrushes[index], TRUE);

    if (SysColorPens[index])
    {
        __wine_make_gdi_object_system( SysColorPens[index], FALSE);
        DeleteObject( SysColorPens[index] );
    }
    SysColorPens[index] = CreatePen( PS_SOLID, 1, color );
    __wine_make_gdi_object_system( SysColorPens[index], TRUE);
}

805 806 807 808 809 810 811
/* load a uint parameter from the registry */
static BOOL get_uint_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                            UINT *value_ptr, UINT *ret_ptr )
{
    if (!ret_ptr) return FALSE;
    if (!spi_loaded[idx])
    {
812
        WCHAR buf[12];
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827

        if (SYSPARAMS_Load( regkey, value, buf, sizeof(buf) )) *value_ptr = atoiW( buf );
        spi_loaded[idx] = TRUE;
    }
    *ret_ptr = *value_ptr;
    return TRUE;
}

/* load a twips parameter from the registry */
static BOOL get_twips_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                             UINT *value_ptr, UINT *ret_ptr )
{
    if (!ret_ptr) return FALSE;
    if (!spi_loaded[idx])
    {
828
        WCHAR buf[12];
829 830

        if (SYSPARAMS_Load( regkey, value, buf, sizeof(buf) ))
831
            *value_ptr = SYSPARAMS_Twips2Pixels( atoiW(buf) );
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
        spi_loaded[idx] = TRUE;
    }
    *ret_ptr = *value_ptr;
    return TRUE;
}

/* load a boolean parameter from the registry */
static inline BOOL get_bool_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                                   BOOL *value_ptr, BOOL *ret_ptr )
{
    return get_uint_param( idx, regkey, value, (UINT *)value_ptr, (UINT *)ret_ptr );
}

/* set a uint parameter that is mirrored in two different registry locations */
static BOOL set_uint_param_mirrored( unsigned int idx, LPCWSTR regkey, LPCWSTR regkey_mirror,
                                     LPCWSTR value, UINT *value_ptr, UINT new_val, UINT fWinIni )
{
849
    WCHAR buf[12];
850 851 852 853 854 855 856 857 858

    wsprintfW(buf, CSu, new_val);
    if (!SYSPARAMS_Save( regkey, value, buf, fWinIni )) return FALSE;
    if (regkey_mirror) SYSPARAMS_Save( regkey_mirror, value, buf, fWinIni );
    *value_ptr = new_val;
    spi_loaded[idx] = TRUE;
    return TRUE;
}

859 860 861 862
/* save an int parameter in registry */
static BOOL save_int_param( LPCWSTR regkey, LPCWSTR value, INT *value_ptr,
                            INT new_val, UINT fWinIni )
{
863
    WCHAR buf[12];
864 865 866

    wsprintfW(buf, CSd, new_val);
    if (!SYSPARAMS_Save( regkey, value, buf, fWinIni )) return FALSE;
867
    if( value_ptr) *value_ptr = new_val;
868 869 870 871 872 873 874 875 876 877 878 879
    return TRUE;
}

/* set an int parameter in the registry */
static inline BOOL set_int_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                                  INT *value_ptr, INT new_val, UINT fWinIni )
{
    BOOL ret = save_int_param( regkey, value, value_ptr, new_val, fWinIni );
    if (ret) spi_loaded[idx] = TRUE;
    return ret;
}

880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
/* set a uint parameter in the registry */
static inline BOOL set_uint_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                                   UINT *value_ptr, UINT new_val, UINT fWinIni )
{
    return set_uint_param_mirrored( idx, regkey, NULL, value, value_ptr, new_val, fWinIni );
}

/* set a boolean parameter that is mirrored in two different registry locations */
static inline BOOL set_bool_param_mirrored( unsigned int idx, LPCWSTR regkey, LPCWSTR regkey_mirror,
                                            LPCWSTR value, BOOL *value_ptr, BOOL new_val, UINT fWinIni )
{
    return set_uint_param_mirrored( idx, regkey, regkey_mirror, value,
                                    (UINT *)value_ptr, new_val, fWinIni );
}

/* set a boolean parameter in the registry */
static inline BOOL set_bool_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                                   BOOL *value_ptr, BOOL new_val, UINT fWinIni )
{
    return set_uint_param( idx, regkey, value, (UINT *)value_ptr, new_val, fWinIni );
}

/* load a boolean parameter from the user preference key */
static BOOL get_user_pref_param( UINT offset, UINT mask, BOOL *ret_ptr )
{
    if (!ret_ptr) return FALSE;

    if (!spi_loaded[SPI_USERPREFERENCEMASK_IDX])
    {
        SYSPARAMS_LoadRaw( SPI_USERPREFERENCEMASK_REGKEY,
                           SPI_USERPREFERENCEMASK_VALNAME,
                           user_prefs, sizeof(user_prefs) );
        spi_loaded[SPI_USERPREFERENCEMASK_IDX] = TRUE;
    }
    *ret_ptr = (user_prefs[offset] & mask) != 0;
    return TRUE;
}

/* set a boolean parameter in the user preference key */
static BOOL set_user_pref_param( UINT offset, UINT mask, BOOL value, BOOL fWinIni )
{
    SYSPARAMS_LoadRaw( SPI_USERPREFERENCEMASK_REGKEY,
                       SPI_USERPREFERENCEMASK_VALNAME,
                       user_prefs, sizeof(user_prefs) );
    spi_loaded[SPI_USERPREFERENCEMASK_IDX] = TRUE;

    if (value) user_prefs[offset] |= mask;
    else user_prefs[offset] &= ~mask;

    SYSPARAMS_SaveRaw( SPI_USERPREFERENCEMASK_REGKEY,
                       SPI_USERPREFERENCEMASK_VALNAME,
                       user_prefs, sizeof(user_prefs), REG_BINARY, fWinIni );
    return TRUE;
}
934

935
/***********************************************************************
936 937 938
 *           SYSPARAMS_Init
 *
 * Initialisation of the system metrics array.
939
 */
940
void SYSPARAMS_Init(void)
941
{
942
    HKEY hkey; /* key to the window metrics area of the registry */
943
    int i, r, g, b;
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
    char buffer[100];
    HBITMAP h55AABitmap;

    /* initialize system colors */

    if (RegCreateKeyExA(HKEY_CURRENT_USER, "Control Panel\\Colors", 0, 0, 0, KEY_ALL_ACCESS, 0, &hkey, 0))
        hkey = 0;
    for (i = 0; i < NUM_SYS_COLORS; i++)
    {
        BOOL bOk = FALSE;

        /* first try, registry */
        if (hkey)
        {
            DWORD dwDataSize = sizeof(buffer);
959
            if (!(RegQueryValueExA(hkey,DefSysColors[i*2], 0, 0, (LPBYTE) buffer, &dwDataSize)))
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
                if (sscanf( buffer, "%d %d %d", &r, &g, &b ) == 3) bOk = TRUE;
        }

        /* second try, win.ini */
        if (!bOk)
        {
            GetProfileStringA( "colors", DefSysColors[i*2], DefSysColors[i*2+1], buffer, 100 );
            if (sscanf( buffer, " %d %d %d", &r, &g, &b ) == 3) bOk = TRUE;
        }

        /* last chance, take the default */
        if (!bOk)
        {
            int iNumColors = sscanf( DefSysColors[i*2+1], " %d %d %d", &r, &g, &b );
            assert (iNumColors==3);
        }

        SYSPARAMS_SetSysColor( i, RGB(r,g,b) );
    }
    if (hkey) RegCloseKey( hkey );

    /* create 55AA bitmap */

    h55AABitmap = CreateBitmap( 8, 8, 1, 1, wPattern55AA );
    SYSCOLOR_55AABrush = CreatePatternBrush( h55AABitmap );
    __wine_make_gdi_object_system( SYSCOLOR_55AABrush, TRUE );
986 987
}

988

989 990 991 992 993
/***********************************************************************
 *              reg_get_logfont
 *
 *  Tries to retrieve logfont info from the specified key and value
 */
994
static BOOL reg_get_logfont(LPCWSTR key, LPCWSTR value, LOGFONTW *lf)
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
{
    HKEY hkey;
    LOGFONTW lfbuf;
    DWORD type, size;
    BOOL found = FALSE;
    HKEY base_keys[2];
    int i;

    base_keys[0] = get_volatile_regkey();
    base_keys[1] = HKEY_CURRENT_USER;

    for(i = 0; i < 2 && !found; i++)
    {
        if(RegOpenKeyW(base_keys[i], key, &hkey) == ERROR_SUCCESS)
        {
            size = sizeof(lfbuf);
            if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)&lfbuf, &size) == ERROR_SUCCESS &&
Rein Klazes's avatar
Rein Klazes committed
1012
                    type == REG_BINARY)
1013
            {
Rein Klazes's avatar
Rein Klazes committed
1014 1015 1016 1017 1018 1019 1020 1021 1022
                if( size == sizeof(lfbuf))
                {
                    found = TRUE;
                    memcpy(lf, &lfbuf, size);
                } else if( size == sizeof( LOGFONT16))
                {    /* win9x-winME format */
                    found = TRUE;
                    SYSPARAMS_LogFont16To32W( (LOGFONT16*) &lfbuf, lf);
                } else
1023
                    WARN("Unknown format in key %s value %s, size is %d\n",
Rein Klazes's avatar
Rein Klazes committed
1024
                            debugstr_w( key), debugstr_w( value), size);
1025 1026 1027 1028
            }
            RegCloseKey(hkey);
        }
    }
Rein Klazes's avatar
Rein Klazes committed
1029 1030
    if( found && lf->lfHeight > 0) { 
        /* positive height value means points ( inch/72 ) */
1031
        lf->lfHeight = -MulDiv( lf->lfHeight, get_display_dpi(), 72);
Rein Klazes's avatar
Rein Klazes committed
1032
    }
1033 1034 1035
    return found;
}

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
/* load all the minimized metrics */
static void load_minimized_metrics(void)
{
    HKEY hkey;
    if (RegOpenKeyExW (HKEY_CURRENT_USER, METRICS_REGKEY,
                       0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) hkey = 0;

    minimized_metrics.iWidth = max( get_reg_metric(hkey,
            METRICS_MINWIDTH_VALNAME, minimized_metrics.iWidth), 0);
    minimized_metrics.iHorzGap = max( get_reg_metric(hkey,
            METRICS_MINHORZGAP_VALNAME, minimized_metrics.iHorzGap), 0);
    minimized_metrics.iVertGap = max( get_reg_metric(hkey,
            METRICS_MINVERTGAP_VALNAME, minimized_metrics.iVertGap), 0);
    minimized_metrics.iArrange = 0x0f & get_reg_metric(hkey,
            METRICS_MINARRANGE_VALNAME, minimized_metrics.iArrange);

    if (hkey) RegCloseKey( hkey );
    spi_loaded[SPI_MINIMIZEDMETRICS_IDX] = TRUE;
}

1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
/* adjust some of the raw values found in the registry */
static void normalize_nonclientmetrics( NONCLIENTMETRICSW *pncm)
{
    TEXTMETRICW tm;
    if( pncm->iBorderWidth < 1) pncm->iBorderWidth = 1;
    if( pncm->iCaptionWidth < 8) pncm->iCaptionWidth = 8;
    if( pncm->iScrollWidth < 8) pncm->iScrollWidth = 8;
    if( pncm->iScrollHeight < 8) pncm->iScrollHeight = 8;

    /* get some extra metrics */
    get_text_metr_size( get_display_dc(), &pncm->lfMenuFont,
            &tmMenuFont, NULL);
    get_text_metr_size( get_display_dc(), &pncm->lfCaptionFont,
            NULL, &CaptionFontAvCharWidth);

    /* adjust some heights to the corresponding font */
    pncm->iMenuHeight = max( pncm->iMenuHeight,
            2 + tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading);
    get_text_metr_size( get_display_dc(), &pncm->lfCaptionFont, &tm, NULL);
    pncm->iCaptionHeight = max( pncm->iCaptionHeight, 2 + tm.tmHeight);
    get_text_metr_size( get_display_dc(), &pncm->lfSmCaptionFont, &tm, NULL);
    pncm->iSmCaptionHeight = max( pncm->iSmCaptionHeight, 2 + tm.tmHeight);
}

1080 1081 1082 1083
/* load all the non-client metrics */
static void load_nonclient_metrics(void)
{
    HKEY hkey;
1084
    NONCLIENTMETRICSW ncm;
1085
    INT r;
1086

1087
    ncm.cbSize = sizeof (ncm);
1088 1089 1090 1091
    if (RegOpenKeyExW (HKEY_CURRENT_USER, METRICS_REGKEY,
                       0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) hkey = 0;

    /* initialize geometry entries */
1092 1093 1094
    ncm.iBorderWidth =  get_reg_metric(hkey, METRICS_BORDERWIDTH_VALNAME, 1);
    ncm.iScrollWidth = get_reg_metric(hkey, METRICS_SCROLLWIDTH_VALNAME, 16);
    ncm.iScrollHeight = get_reg_metric(hkey, METRICS_SCROLLHEIGHT_VALNAME, 16);
1095 1096

    /* size of the normal caption buttons */
1097 1098
    ncm.iCaptionHeight = get_reg_metric(hkey, METRICS_CAPTIONHEIGHT_VALNAME, 18);
    ncm.iCaptionWidth = get_reg_metric(hkey, METRICS_CAPTIONWIDTH_VALNAME, ncm.iCaptionHeight);
1099 1100

    /* caption font metrics */
1101
    if (!reg_get_logfont(METRICS_REGKEY, METRICS_CAPTIONLOGFONT_VALNAME, &ncm.lfCaptionFont))
1102
    {
1103 1104
        SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &ncm.lfCaptionFont, 0 );
        ncm.lfCaptionFont.lfWeight = FW_BOLD;
1105 1106 1107
    }

    /* size of the small caption buttons */
1108 1109
    ncm.iSmCaptionWidth = get_reg_metric(hkey, METRICS_SMCAPTIONWIDTH_VALNAME, 13);
    ncm.iSmCaptionHeight = get_reg_metric(hkey, METRICS_SMCAPTIONHEIGHT_VALNAME, 15);
1110 1111

    /* small caption font metrics */
1112 1113
    if (!reg_get_logfont(METRICS_REGKEY, METRICS_SMCAPTIONLOGFONT_VALNAME, &ncm.lfSmCaptionFont))
        SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &ncm.lfSmCaptionFont, 0 );
1114 1115 1116 1117

    /* menus, FIXME: names of wine.conf entries are bogus */

    /* size of the menu (MDI) buttons */
1118 1119
    ncm.iMenuHeight = get_reg_metric(hkey, METRICS_MENUHEIGHT_VALNAME, 18);
    ncm.iMenuWidth = get_reg_metric(hkey, METRICS_MENUWIDTH_VALNAME, ncm.iMenuHeight);
1120 1121

    /* menu font metrics */
1122
    if (!reg_get_logfont(METRICS_REGKEY, METRICS_MENULOGFONT_VALNAME, &ncm.lfMenuFont))
1123
    {
1124 1125 1126
        SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &ncm.lfMenuFont, 0 );
        GetProfileStringW( Desktop, MenuFont, ncm.lfCaptionFont.lfFaceName,
                           ncm.lfMenuFont.lfFaceName, LF_FACESIZE );
1127 1128 1129
        r = GetProfileIntW( Desktop, MenuFontSize, 0 );
        if (r)
            ncm.lfMenuFont.lfHeight = -r;
1130
        ncm.lfMenuFont.lfWeight = FW_NORMAL;
1131 1132 1133
    }

    /* status bar font metrics */
1134
    if (!reg_get_logfont(METRICS_REGKEY, METRICS_STATUSLOGFONT_VALNAME, &ncm.lfStatusFont))
1135
    {
1136 1137 1138
        SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &ncm.lfStatusFont, 0 );
        GetProfileStringW( Desktop, StatusFont, ncm.lfCaptionFont.lfFaceName,
                           ncm.lfStatusFont.lfFaceName, LF_FACESIZE );
1139 1140 1141
        r = GetProfileIntW( Desktop, StatusFontSize, 0 );
        if (r)
            ncm.lfStatusFont.lfHeight = -r;
1142
        ncm.lfStatusFont.lfWeight = FW_NORMAL;
1143 1144 1145
    }

    /* message font metrics */
1146
    if (!reg_get_logfont(METRICS_REGKEY, METRICS_MESSAGELOGFONT_VALNAME, &ncm.lfMessageFont))
1147
    {
1148 1149 1150
        SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &ncm.lfMessageFont, 0 );
        GetProfileStringW( Desktop, MessageFont, ncm.lfCaptionFont.lfFaceName,
                           ncm.lfMessageFont.lfFaceName, LF_FACESIZE );
1151 1152 1153
        r = GetProfileIntW( Desktop, MessageFontSize, 0 );
        if (r)
            ncm.lfMessageFont.lfHeight = -r;
1154
        ncm.lfMessageFont.lfWeight = FW_NORMAL;
1155 1156 1157 1158 1159 1160
    }

    /* some extra fields not in the nonclient structure */
    icon_size.cx = icon_size.cy = get_reg_metric( hkey, METRICS_ICONSIZE_VALNAME, 32 );

    if (hkey) RegCloseKey( hkey );
1161
    normalize_nonclientmetrics( &ncm);
1162
    nonclient_metrics = ncm;
1163 1164 1165
    spi_loaded[SPI_NONCLIENTMETRICS_IDX] = TRUE;
}

1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
static BOOL CALLBACK enum_monitors( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
{
    MONITORINFO mi;

    mi.cbSize = sizeof(mi);
    if (GetMonitorInfoW( monitor, &mi ) && (mi.dwFlags & MONITORINFOF_PRIMARY))
    {
        LPRECT work = (LPRECT)lp;
        *work = mi.rcWork;
        return FALSE;
    }
    return TRUE;
}
1179

1180
/***********************************************************************
1181
 *		SystemParametersInfoW (USER32.@)
1182
 *
1183
 *     Each system parameter has flag which shows whether the parameter
1184 1185 1186 1187 1188 1189
 * is loaded or not. Parameters, stored directly in SysParametersInfo are
 * loaded from registry only when they are requested and the flag is
 * "false", after the loading the flag is set to "true". On interprocess
 * notification of the parameter change the corresponding parameter flag is
 * set to "false". The parameter value will be reloaded when it is requested
 * the next time.
1190
 *     Parameters, backed by or depend on GetSystemMetrics are processed
1191 1192 1193
 * differently. These parameters are always loaded. They are reloaded right
 * away on interprocess change notification. We can't do lazy loading because
 * we don't want to complicate GetSystemMetrics.
1194 1195 1196 1197
 *     Parameters, backed by X settings are read from corresponding setting.
 * On the parameter change request the setting is changed. Interprocess change
 * notifications are ignored.
 *     When parameter value is updated the changed value is stored in permanent
1198 1199 1200
 * registry branch if saving is requested. Otherwise it is stored
 * in temporary branch
 *
1201 1202
 * Some SPI values can also be stored as Twips values in the registry,
 * don't forget the conversion!
1203
 */
1204
BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam,
1205
				   PVOID pvParam, UINT fWinIni )
1206
{
1207 1208
#define WINE_SPI_FIXME(x) \
    case x: \
1209 1210 1211 1212 1213 1214 1215 1216
        { \
            static BOOL warn = TRUE; \
            if (warn) \
            { \
                warn = FALSE; \
                FIXME( "Unimplemented action: %u (%s)\n", x, #x ); \
            } \
        } \
1217 1218 1219 1220 1221 1222 1223 1224 1225
        SetLastError( ERROR_INVALID_SPI_VALUE ); \
        ret = FALSE; \
        break
#define WINE_SPI_WARN(x) \
    case x: \
        WARN( "Ignored action: %u (%s)\n", x, #x ); \
        break

    BOOL ret = TRUE;
1226
    unsigned spi_idx = 0;
1227

1228 1229 1230
    switch (uiAction)
    {
    case SPI_GETBEEP:				/*      1 */
1231 1232
        if (!pvParam) return FALSE;

1233 1234 1235
        spi_idx = SPI_SETBEEP_IDX;
        if (!spi_loaded[spi_idx])
        {
1236
            WCHAR buf[5];
1237

1238
            if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf, sizeof(buf) ))
1239
                beep_active  = !lstrcmpiW( Yes, buf );
1240 1241
            spi_loaded[spi_idx] = TRUE;
        }
1242

1243
	*(BOOL *)pvParam = beep_active;
1244
        break;
1245

1246
    case SPI_SETBEEP:				/*      2 */
1247 1248
        spi_idx = SPI_SETBEEP_IDX;
        if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
1249
                            (uiParam ? Yes : No), fWinIni ))
1250 1251 1252 1253 1254 1255 1256
        {
            beep_active = uiParam;
            spi_loaded[spi_idx] = TRUE;
        }
        else
            ret = FALSE;
        break;
1257

1258
    case SPI_GETMOUSE:                          /*      3 */
1259 1260
        if (!pvParam) return FALSE;

1261 1262 1263
        spi_idx = SPI_SETMOUSE_IDX;
        if (!spi_loaded[spi_idx])
        {
1264
            WCHAR buf[12];
1265 1266

            if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
1267
                                buf, sizeof(buf) ))
1268
                mouse_threshold1 = atoiW( buf );
1269
            if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
1270
                                buf, sizeof(buf) ))
1271
                mouse_threshold2 = atoiW( buf );
1272
            if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
1273
                                buf, sizeof(buf) ))
1274
                mouse_speed = atoiW( buf );
1275 1276 1277 1278 1279 1280
            spi_loaded[spi_idx] = TRUE;
        }
        ((INT *)pvParam)[0] = mouse_threshold1;
        ((INT *)pvParam)[1] = mouse_threshold2;
        ((INT *)pvParam)[2] = mouse_speed;
        break;
1281

1282 1283
    case SPI_SETMOUSE:                          /*      4 */
    {
1284
        if (!pvParam) return FALSE;
1285 1286 1287 1288 1289 1290 1291
        ret = set_int_param( SPI_SETMOUSE_IDX, SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
                             &mouse_threshold1, ((INT *)pvParam)[0], fWinIni);
        if( ret) {
            save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
                            &mouse_threshold2, ((INT *)pvParam)[1], fWinIni);
            save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
                            &mouse_speed, ((INT *)pvParam)[2], fWinIni);
1292 1293 1294
        }
        break;
    }
1295

1296 1297 1298 1299 1300
    case SPI_GETBORDER:
        ret = get_twips_param( SPI_SETBORDER_IDX,
                               SPI_SETBORDER_REGKEY,
                               SPI_SETBORDER_VALNAME,
                               &border, pvParam );
1301
        if( *(INT*)pvParam < 1) *(INT*)pvParam = 1; 
1302
        break;
1303

1304
    case SPI_SETBORDER:
1305 1306
        nonclient_metrics.iBorderWidth = uiParam > 0 ? uiParam : 1;
        /* raw value goes to registry */
1307 1308 1309 1310
        ret = set_uint_param( SPI_SETBORDER_IDX,
                              SPI_SETBORDER_REGKEY,
                              SPI_SETBORDER_VALNAME,
                              &border, uiParam, fWinIni );
1311
        break;
1312

1313 1314 1315 1316 1317 1318
    case SPI_GETKEYBOARDSPEED:
        ret = get_uint_param( SPI_SETKEYBOARDSPEED_IDX,
                              SPI_SETKEYBOARDSPEED_REGKEY,
                              SPI_SETKEYBOARDSPEED_VALNAME,
                              &keyboard_speed, pvParam );
        break;
1319

1320 1321 1322 1323 1324 1325
    case SPI_SETKEYBOARDSPEED:
        if (uiParam > 31) uiParam = 31;
        ret = set_uint_param( SPI_SETKEYBOARDSPEED_IDX,
                              SPI_SETKEYBOARDSPEED_REGKEY,
                              SPI_SETKEYBOARDSPEED_VALNAME,
                              &keyboard_speed, uiParam, fWinIni );
1326
        break;
1327

1328 1329
    /* not implemented in Windows */
    WINE_SPI_WARN(SPI_LANGDRIVER);              /*     12 */
1330

1331 1332
    case SPI_ICONHORIZONTALSPACING:
        if (pvParam != NULL)
1333
        {
1334 1335 1336
            ret = get_twips_param( SPI_ICONHORIZONTALSPACING_IDX,
                                   SPI_ICONHORIZONTALSPACING_REGKEY,
                                   SPI_ICONHORIZONTALSPACING_VALNAME,
1337
                                   (UINT*)&icon_metrics.iHorzSpacing, pvParam );
1338
        }
1339
        else
1340 1341
        {
            if (uiParam < 32) uiParam = 32;
1342 1343 1344
            ret = set_uint_param( SPI_ICONHORIZONTALSPACING_IDX,
                                  SPI_ICONHORIZONTALSPACING_REGKEY,
                                  SPI_ICONHORIZONTALSPACING_VALNAME,
1345
                                  (UINT*)&icon_metrics.iHorzSpacing, uiParam, fWinIni );
1346
        }
1347
        break;
1348

1349 1350 1351 1352 1353 1354
    case SPI_GETSCREENSAVETIMEOUT:
        ret = get_uint_param( SPI_SETSCREENSAVETIMEOUT_IDX,
                              SPI_SETSCREENSAVETIMEOUT_REGKEY,
                              SPI_SETSCREENSAVETIMEOUT_VALNAME,
                              &screensave_timeout, pvParam );
        break;
1355

1356 1357 1358 1359 1360
    case SPI_SETSCREENSAVETIMEOUT:
        ret = set_uint_param( SPI_SETSCREENSAVETIMEOUT_IDX,
                              SPI_SETSCREENSAVETIMEOUT_REGKEY,
                              SPI_SETSCREENSAVETIMEOUT_VALNAME,
                              &screensave_timeout, uiParam, fWinIni );
1361
        break;
1362

1363
    case SPI_GETSCREENSAVEACTIVE:               /*     16 */
1364
        if (!pvParam) return FALSE;
1365
        *(BOOL *)pvParam = USER_Driver->pGetScreenSaveActive();
1366 1367 1368 1369
        break;

    case SPI_SETSCREENSAVEACTIVE:               /*     17 */
    {
1370
        WCHAR buf[12];
1371

1372
        wsprintfW(buf, CSu, uiParam);
1373
        USER_Driver->pSetScreenSaveActive( uiParam );
1374 1375 1376 1377
        /* saved value does not affect Wine */
        SYSPARAMS_Save( SPI_SETSCREENSAVEACTIVE_REGKEY,
                        SPI_SETSCREENSAVEACTIVE_VALNAME,
                        buf, fWinIni );
1378 1379
        break;
    }
1380

1381 1382 1383 1384 1385 1386
    case SPI_GETGRIDGRANULARITY:
        ret = get_uint_param( SPI_SETGRIDGRANULARITY_IDX,
                              SPI_SETGRIDGRANULARITY_REGKEY,
                              SPI_SETGRIDGRANULARITY_VALNAME,
                              &grid_granularity, pvParam );
        break;
1387

1388 1389 1390 1391 1392
    case SPI_SETGRIDGRANULARITY:
        ret = set_uint_param( SPI_SETGRIDGRANULARITY_IDX,
                              SPI_SETGRIDGRANULARITY_REGKEY,
                              SPI_SETGRIDGRANULARITY_VALNAME,
                              &grid_granularity, uiParam, fWinIni );
1393
        break;
1394 1395

    case SPI_SETDESKWALLPAPER:			/*     20 */
1396
        if (!pvParam || !SetDeskWallPaper( pvParam )) return FALSE;
1397
        SYSPARAMS_Save(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, pvParam, fWinIni);
1398
	break;
1399
	
1400 1401 1402 1403 1404
    case SPI_SETDESKPATTERN:			/*     21 */
	/* FIXME: the ability to specify a pattern in pvParam
	   doesn't seem to be documented for Win32 */
	if ((INT16)uiParam == -1)
	{
1405 1406 1407 1408 1409 1410
            WCHAR buf[256];
            GetProfileStringW( Desktop, Pattern,
                               defPattern,
                               buf, sizeof(buf)/sizeof(WCHAR) );
            ret = DESKTOP_SetPattern( buf );
        } else
1411
            ret = DESKTOP_SetPattern( pvParam );
1412 1413
	break;

1414 1415 1416 1417 1418 1419
    case SPI_GETKEYBOARDDELAY:
        ret = get_uint_param( SPI_SETKEYBOARDDELAY_IDX,
                              SPI_SETKEYBOARDDELAY_REGKEY,
                              SPI_SETKEYBOARDDELAY_VALNAME,
                              &keyboard_delay, pvParam );
        break;
1420

1421 1422 1423 1424 1425 1426
    case SPI_SETKEYBOARDDELAY:
        ret = set_uint_param( SPI_SETKEYBOARDDELAY_IDX,
                              SPI_SETKEYBOARDDELAY_REGKEY,
                              SPI_SETKEYBOARDDELAY_VALNAME,
                              &keyboard_delay, uiParam, fWinIni );
        break;
1427

1428 1429 1430 1431 1432 1433
    case SPI_ICONVERTICALSPACING:
        if (pvParam != NULL)
        {
            ret = get_twips_param( SPI_ICONVERTICALSPACING_IDX,
                                   SPI_ICONVERTICALSPACING_REGKEY,
                                   SPI_ICONVERTICALSPACING_VALNAME,
1434
                                   (UINT*)&icon_metrics.iVertSpacing, pvParam );
1435 1436
            if( icon_metrics.iVertSpacing < 32) 
                icon_metrics.iVertSpacing = 32;
1437
        }
1438 1439 1440 1441 1442 1443
        else
        {
            if (uiParam < 32) uiParam = 32;
            ret = set_uint_param( SPI_ICONVERTICALSPACING_IDX,
                                  SPI_ICONVERTICALSPACING_REGKEY,
                                  SPI_ICONVERTICALSPACING_VALNAME,
1444
                                  (UINT*)&icon_metrics.iVertSpacing, uiParam, fWinIni );
1445 1446
        }
        break;
1447

1448 1449 1450 1451
    case SPI_GETICONTITLEWRAP:
        ret = get_bool_param( SPI_SETICONTITLEWRAP_IDX,
                              SPI_SETICONTITLEWRAP_REGKEY1,
                              SPI_SETICONTITLEWRAP_VALNAME,
1452
                              &icon_metrics.iTitleWrap, pvParam );
1453
        break;
1454

1455 1456 1457 1458 1459
    case SPI_SETICONTITLEWRAP:
        ret = set_bool_param_mirrored( SPI_SETICONTITLEWRAP_IDX,
                                       SPI_SETICONTITLEWRAP_REGKEY1,
                                       SPI_SETICONTITLEWRAP_REGKEY2,
                                       SPI_SETICONTITLEWRAP_VALNAME,
1460
                                       &icon_metrics.iTitleWrap, uiParam, fWinIni );
1461
        break;
1462

1463 1464 1465 1466
    case SPI_GETMENUDROPALIGNMENT:
        ret = get_uint_param( SPI_SETMENUDROPALIGNMENT_IDX,
                              SPI_SETMENUDROPALIGNMENT_REGKEY1,
                              SPI_SETMENUDROPALIGNMENT_VALNAME,
1467
                              &menu_drop_alignment, pvParam );
1468
        break;
1469

1470 1471 1472 1473 1474
    case SPI_SETMENUDROPALIGNMENT:
        ret = set_uint_param_mirrored( SPI_SETMENUDROPALIGNMENT_IDX,
                                       SPI_SETMENUDROPALIGNMENT_REGKEY1,
                                       SPI_SETMENUDROPALIGNMENT_REGKEY2,
                                       SPI_SETMENUDROPALIGNMENT_VALNAME,
1475
                                       &menu_drop_alignment, uiParam, fWinIni );
1476
        break;
1477

1478 1479 1480 1481 1482
    case SPI_SETDOUBLECLKWIDTH:
        ret = set_uint_param_mirrored( SPI_SETDOUBLECLKWIDTH_IDX,
                                       SPI_SETDOUBLECLKWIDTH_REGKEY1,
                                       SPI_SETDOUBLECLKWIDTH_REGKEY2,
                                       SPI_SETDOUBLECLKWIDTH_VALNAME,
1483
                                       &double_click_width, uiParam, fWinIni );
1484
        break;
1485

1486 1487 1488 1489 1490
    case SPI_SETDOUBLECLKHEIGHT:
        ret = set_uint_param_mirrored( SPI_SETDOUBLECLKHEIGHT_IDX,
                                       SPI_SETDOUBLECLKHEIGHT_REGKEY1,
                                       SPI_SETDOUBLECLKHEIGHT_REGKEY2,
                                       SPI_SETDOUBLECLKHEIGHT_VALNAME,
1491
                                       &double_click_height, uiParam, fWinIni );
1492
        break;
1493

1494
    case SPI_GETICONTITLELOGFONT:
1495
    {
1496
        LOGFONTW lfDefault;
1497 1498

        if (!pvParam) return FALSE;
1499

1500 1501
        spi_idx = SPI_SETICONTITLELOGFONT_IDX;
        if (!spi_loaded[spi_idx])
1502 1503 1504
        {
            if (!reg_get_logfont( SPI_SETICONTITLELOGFONT_REGKEY,
                                  SPI_SETICONTITLELOGFONT_VALNAME, &icon_metrics.lfFont ))
1505
            {
1506 1507
                INT r;

1508 1509 1510 1511 1512 1513 1514 1515 1516
                /*
                 * The 'default GDI fonts' seems to be returned.
                 * If a returned font is not a correct font in your environment,
                 * please try to fix objects/gdiobj.c at first.
                 */
                GetObjectW( GetStockObject( DEFAULT_GUI_FONT ), sizeof(LOGFONTW), &lfDefault );

                GetProfileStringW( Desktop, IconTitleFaceName,
                                   lfDefault.lfFaceName,
1517
                                   icon_metrics.lfFont.lfFaceName,
1518
                                   LF_FACESIZE );
1519 1520 1521 1522 1523 1524 1525
                
                r = GetProfileIntW( Desktop, IconTitleSize, 0 );
                if (r)
                    icon_metrics.lfFont.lfHeight = -r;
                else
                    icon_metrics.lfFont.lfHeight = lfDefault.lfHeight;

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
                icon_metrics.lfFont.lfWidth = 0;
                icon_metrics.lfFont.lfEscapement = icon_metrics.lfFont.lfOrientation = 0;
                icon_metrics.lfFont.lfWeight = FW_NORMAL;
                icon_metrics.lfFont.lfItalic = FALSE;
                icon_metrics.lfFont.lfStrikeOut = FALSE;
                icon_metrics.lfFont.lfUnderline = FALSE;
                icon_metrics.lfFont.lfCharSet = lfDefault.lfCharSet; /* at least 'charset' should not be hard-coded */
                icon_metrics.lfFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
                icon_metrics.lfFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
                icon_metrics.lfFont.lfQuality = DEFAULT_QUALITY;
                icon_metrics.lfFont.lfPitchAndFamily = DEFAULT_PITCH;
1537 1538 1539
                spi_loaded[spi_idx] = TRUE;
            }
        }
1540 1541
        *(LOGFONTW *)pvParam = icon_metrics.lfFont;
        break;
1542
    }
1543

1544 1545 1546 1547 1548 1549
    case SPI_SETDOUBLECLICKTIME:
        ret = set_uint_param( SPI_SETDOUBLECLICKTIME_IDX,
                              SPI_SETDOUBLECLICKTIME_REGKEY,
                              SPI_SETDOUBLECLICKTIME_VALNAME,
                              &double_click_time, uiParam, fWinIni );
        break;
1550

1551
    case SPI_SETMOUSEBUTTONSWAP:
1552
        ret = set_bool_param( SPI_SETMOUSEBUTTONSWAP_IDX,
1553 1554
                              SPI_SETMOUSEBUTTONSWAP_REGKEY,
                              SPI_SETMOUSEBUTTONSWAP_VALNAME,
1555
                              &swap_buttons, uiParam, fWinIni );
1556
        break;
1557

1558
    case SPI_SETICONTITLELOGFONT:       	/*     34 */
1559
        if( uiParam == sizeof(LOGFONTW)) {
1560
            ret = SYSPARAMS_SaveLogFont( SPI_SETICONTITLELOGFONT_REGKEY,
1561
                    SPI_SETICONTITLELOGFONT_VALNAME, pvParam, fWinIni);
1562 1563 1564 1565 1566 1567 1568
            if( ret) {
                icon_metrics.lfFont = *(LOGFONTW *)pvParam;
                spi_loaded[SPI_SETICONTITLELOGFONT_IDX] = TRUE;
            }
        } else
            ret = FALSE;
        break;
1569

1570 1571 1572
    case SPI_GETFASTTASKSWITCH:			/*     35 */
        if (!pvParam) return FALSE;
	*(BOOL *)pvParam = 1;
1573 1574 1575
        break;

    case SPI_SETFASTTASKSWITCH:                 /*     36 */
1576
        /* the action is disabled */
1577
        ret = FALSE;
1578
        break;
1579

1580 1581 1582 1583 1584
    case SPI_SETDRAGFULLWINDOWS:
        ret = set_bool_param( SPI_SETDRAGFULLWINDOWS_IDX,
                              SPI_SETDRAGFULLWINDOWS_REGKEY,
                              SPI_SETDRAGFULLWINDOWS_VALNAME,
                              &drag_full_windows, uiParam, fWinIni );
1585
        break;
1586

1587 1588 1589 1590 1591
    case SPI_GETDRAGFULLWINDOWS:
        ret = get_bool_param( SPI_SETDRAGFULLWINDOWS_IDX,
                              SPI_SETDRAGFULLWINDOWS_REGKEY,
                              SPI_SETDRAGFULLWINDOWS_VALNAME,
                              &drag_full_windows, pvParam );
1592
        break;
1593

1594
    case SPI_GETNONCLIENTMETRICS:
1595
    {
1596
        LPNONCLIENTMETRICSW lpnm = pvParam;
1597

1598
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
1599

1600
        if (lpnm && lpnm->cbSize == sizeof(NONCLIENTMETRICSW))
1601
            *lpnm = nonclient_metrics;
1602 1603 1604 1605
        else
            ret = FALSE;
        break;
    }
1606

1607 1608 1609
    case SPI_SETNONCLIENTMETRICS:
    {
        LPNONCLIENTMETRICSW lpnm = pvParam;
1610

1611 1612
        if (lpnm && lpnm->cbSize == sizeof(NONCLIENTMETRICSW))
        {
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
            NONCLIENTMETRICSW ncm;
            ret = set_uint_param( SPI_SETBORDER_IDX,
                    SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
                    &border, lpnm->iBorderWidth, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_SCROLLWIDTH_VALNAME, NULL,
                    lpnm->iScrollWidth, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_SCROLLHEIGHT_VALNAME, NULL,
                    lpnm->iScrollHeight, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_CAPTIONWIDTH_VALNAME, NULL,
                    lpnm->iCaptionWidth, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_CAPTIONHEIGHT_VALNAME, NULL,
                    lpnm->iCaptionHeight, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_SMCAPTIONWIDTH_VALNAME, NULL,
                    lpnm->iSmCaptionWidth, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_SMCAPTIONHEIGHT_VALNAME, NULL,
                    lpnm->iSmCaptionHeight, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_MENUWIDTH_VALNAME, NULL,
                    lpnm->iMenuWidth, fWinIni );
            if( ret) ret = save_int_param( METRICS_REGKEY,
                    METRICS_MENUHEIGHT_VALNAME, NULL,
                    lpnm->iMenuHeight, fWinIni );
            if( ret) ret = SYSPARAMS_SaveLogFont(
                    METRICS_REGKEY, METRICS_MENULOGFONT_VALNAME,
                    &lpnm->lfMenuFont, fWinIni);
            if( ret) ret = SYSPARAMS_SaveLogFont(
                    METRICS_REGKEY, METRICS_CAPTIONLOGFONT_VALNAME,
                    &lpnm->lfCaptionFont, fWinIni);
            if( ret) ret = SYSPARAMS_SaveLogFont(
                    METRICS_REGKEY, METRICS_SMCAPTIONLOGFONT_VALNAME,
                    &lpnm->lfSmCaptionFont, fWinIni);
            if( ret) ret = SYSPARAMS_SaveLogFont(
                    METRICS_REGKEY, METRICS_STATUSLOGFONT_VALNAME,
                    &lpnm->lfStatusFont, fWinIni);
            if( ret) ret = SYSPARAMS_SaveLogFont(
                    METRICS_REGKEY, METRICS_MESSAGELOGFONT_VALNAME,
                    &lpnm->lfMessageFont, fWinIni);
            if( ret) {
1657
                ncm = *lpnm;
1658
                normalize_nonclientmetrics( &ncm);
1659
                nonclient_metrics = ncm;
1660 1661
                spi_loaded[SPI_NONCLIENTMETRICS_IDX] = TRUE;
            }
1662 1663
        }
        break;
1664 1665
    }

1666
    case SPI_GETMINIMIZEDMETRICS:
1667 1668
    {
        MINIMIZEDMETRICS * lpMm = pvParam;
1669 1670
        if (lpMm && lpMm->cbSize == sizeof(*lpMm)) {
            if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
1671
            *lpMm = minimized_metrics;
1672
        } else
1673 1674
            ret = FALSE;
        break;
1675
    }
1676 1677

    case SPI_SETMINIMIZEDMETRICS:
1678 1679
    {
        MINIMIZEDMETRICS * lpMm = pvParam;
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
        if (lpMm && lpMm->cbSize == sizeof(*lpMm)) {
            ret = save_int_param( METRICS_REGKEY, METRICS_MINWIDTH_VALNAME,
                                  &minimized_metrics.iWidth, max( lpMm->iWidth, 0), fWinIni);
            if( ret) ret = save_int_param( METRICS_REGKEY,
                                           METRICS_MINHORZGAP_VALNAME, &minimized_metrics.iHorzGap,
                                           max( lpMm->iHorzGap, 0), fWinIni);
            if( ret) ret = save_int_param( METRICS_REGKEY,
                                           METRICS_MINVERTGAP_VALNAME, &minimized_metrics.iVertGap,
                                           max( lpMm->iVertGap, 0), fWinIni);
            if( ret) ret = save_int_param( METRICS_REGKEY,
                                           METRICS_MINARRANGE_VALNAME, &minimized_metrics.iArrange,
                                           0x0f & lpMm->iArrange, fWinIni);
            if( ret) spi_loaded[SPI_MINIMIZEDMETRICS_IDX] = TRUE;
        } else
1694 1695
            ret = FALSE;
        break;
1696
    }
1697

1698
    case SPI_GETICONMETRICS:
1699
    {
1700
	LPICONMETRICSW lpIcon = pvParam;
1701 1702
	if(lpIcon && lpIcon->cbSize == sizeof(*lpIcon))
	{
1703
	    SystemParametersInfoW( SPI_ICONHORIZONTALSPACING, 0,
1704
				   &lpIcon->iHorzSpacing, FALSE );
1705
	    SystemParametersInfoW( SPI_ICONVERTICALSPACING, 0,
1706
				   &lpIcon->iVertSpacing, FALSE );
1707
	    SystemParametersInfoW( SPI_GETICONTITLEWRAP, 0,
1708
				   &lpIcon->iTitleWrap, FALSE );
1709
	    SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0,
1710 1711
				   &lpIcon->lfFont, FALSE );
	}
1712 1713 1714 1715 1716 1717
	else
	{
	    ret = FALSE;
	}
	break;
    }
1718

1719
    case SPI_SETICONMETRICS:
1720
    {
1721
        LPICONMETRICSW lpIcon = pvParam;
1722
        if (lpIcon && lpIcon->cbSize == sizeof(*lpIcon)) {
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736
            ret = set_int_param( SPI_ICONVERTICALSPACING_IDX,
                                 SPI_ICONVERTICALSPACING_REGKEY,
                                 SPI_ICONVERTICALSPACING_VALNAME,
                                 &icon_metrics.iVertSpacing,
                                 lpIcon->iVertSpacing, fWinIni);
            if( ret) {
                ret = set_int_param( SPI_ICONHORIZONTALSPACING_IDX,
                                     SPI_ICONHORIZONTALSPACING_REGKEY,
                                     SPI_ICONHORIZONTALSPACING_VALNAME,
                                     &icon_metrics.iHorzSpacing,
                                     lpIcon->iHorzSpacing, fWinIni );
            }
            if( ret) {
                ret = set_bool_param_mirrored( SPI_SETICONTITLEWRAP_IDX,
1737 1738 1739
                    SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_REGKEY2,
                    SPI_SETICONTITLEWRAP_VALNAME, &icon_metrics.iTitleWrap,
                    lpIcon->iTitleWrap, fWinIni );
1740
            }
1741 1742 1743 1744 1745 1746 1747
            if( ret) ret = SYSPARAMS_SaveLogFont( SPI_SETICONTITLELOGFONT_REGKEY,
                    SPI_SETICONTITLELOGFONT_VALNAME, &lpIcon->lfFont, fWinIni);
            if( ret) {
                icon_metrics.lfFont = lpIcon->lfFont;
                spi_loaded[SPI_SETICONTITLELOGFONT_IDX] = TRUE;
            }
        } else
1748 1749
            ret = FALSE;
        break;
1750
    }
1751

1752 1753
    case SPI_SETWORKAREA:                       /*     47  WINVER >= 0x400 */
    {
1754 1755
        if (!pvParam) return FALSE;

1756
        spi_idx = SPI_SETWORKAREA_IDX;
1757
        CopyRect( &work_area, pvParam );
1758
        spi_loaded[spi_idx] = TRUE;
1759 1760 1761 1762
        break;
    }

    case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1763
    {
1764 1765
        if (!pvParam) return FALSE;

1766 1767 1768 1769 1770 1771
        spi_idx = SPI_SETWORKAREA_IDX;
        if (!spi_loaded[spi_idx])
        {
            SetRect( &work_area, 0, 0,
                     GetSystemMetrics( SM_CXSCREEN ),
                     GetSystemMetrics( SM_CYSCREEN ) );
1772
            EnumDisplayMonitors( 0, NULL, enum_monitors, (LPARAM)&work_area );
1773 1774
            spi_loaded[spi_idx] = TRUE;
        }
1775
        CopyRect( pvParam, &work_area );
1776
        TRACE("work area %s\n", wine_dbgstr_rect( &work_area ));
1777 1778
        break;
    }
1779

1780 1781
    WINE_SPI_FIXME(SPI_SETPENWINDOWS);		/*     49  WINVER >= 0x400 */

1782 1783
    case SPI_GETFILTERKEYS:                     /*     50 */
    {
1784
        LPFILTERKEYS lpFilterKeys = pvParam;
1785
        WARN("SPI_GETFILTERKEYS not fully implemented\n");
1786
        if (lpFilterKeys && lpFilterKeys->cbSize == sizeof(FILTERKEYS))
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
        {
            /* Indicate that no FilterKeys feature available */
            lpFilterKeys->dwFlags = 0;
            lpFilterKeys->iWaitMSec = 0;
            lpFilterKeys->iDelayMSec = 0;
            lpFilterKeys->iRepeatMSec = 0;
            lpFilterKeys->iBounceMSec = 0;
         }
        else
        {
            ret = FALSE;
        }
        break;
    }
1801
    WINE_SPI_FIXME(SPI_SETFILTERKEYS);		/*     51 */
1802 1803 1804

    case SPI_GETTOGGLEKEYS:                     /*     52 */
    {
1805
        LPTOGGLEKEYS lpToggleKeys = pvParam;
1806
        WARN("SPI_GETTOGGLEKEYS not fully implemented\n");
1807
        if (lpToggleKeys && lpToggleKeys->cbSize == sizeof(TOGGLEKEYS))
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
        {
            /* Indicate that no ToggleKeys feature available */
            lpToggleKeys->dwFlags = 0;
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1818
    WINE_SPI_FIXME(SPI_SETTOGGLEKEYS);		/*     53 */
1819 1820 1821

    case SPI_GETMOUSEKEYS:                      /*     54 */
    {
1822
        LPMOUSEKEYS lpMouseKeys = pvParam;
1823
        WARN("SPI_GETMOUSEKEYS not fully implemented\n");
1824
        if (lpMouseKeys && lpMouseKeys->cbSize == sizeof(MOUSEKEYS))
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
        {
            /* Indicate that no MouseKeys feature available */
            lpMouseKeys->dwFlags = 0;
            lpMouseKeys->iMaxSpeed = 360;
            lpMouseKeys->iTimeToMaxSpeed = 1000;
            lpMouseKeys->iCtrlSpeed = 0;
            lpMouseKeys->dwReserved1 = 0;
            lpMouseKeys->dwReserved2 = 0;
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1840
    WINE_SPI_FIXME(SPI_SETMOUSEKEYS);		/*     55 */
1841

1842
    case SPI_GETSHOWSOUNDS:
1843
        ret = get_bool_param( SPI_SETSHOWSOUNDS_IDX,
1844 1845
                              SPI_SETSHOWSOUNDS_REGKEY,
                              SPI_SETSHOWSOUNDS_VALNAME,
1846
                              &show_sounds, pvParam );
1847
        break;
1848

1849
    case SPI_SETSHOWSOUNDS:
1850
        ret = set_bool_param( SPI_SETSHOWSOUNDS_IDX,
1851 1852
                              SPI_SETSHOWSOUNDS_REGKEY,
                              SPI_SETSHOWSOUNDS_VALNAME,
1853
                              &show_sounds, uiParam, fWinIni );
1854
        break;
1855 1856 1857

    case SPI_GETSTICKYKEYS:                     /*     58 */
    {
1858
        LPSTICKYKEYS lpStickyKeys = pvParam;
1859
        WARN("SPI_GETSTICKYKEYS not fully implemented\n");
1860
        if (lpStickyKeys && lpStickyKeys->cbSize == sizeof(STICKYKEYS))
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
        {
            /* Indicate that no StickyKeys feature available */
            lpStickyKeys->dwFlags = 0;
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1871
    WINE_SPI_FIXME(SPI_SETSTICKYKEYS);		/*     59 */
1872 1873 1874

    case SPI_GETACCESSTIMEOUT:                  /*     60 */
    {
1875
        LPACCESSTIMEOUT lpAccessTimeout = pvParam;
1876
        WARN("SPI_GETACCESSTIMEOUT not fully implemented\n");
1877
        if (lpAccessTimeout && lpAccessTimeout->cbSize == sizeof(ACCESSTIMEOUT))
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888
        {
            /* Indicate that no accessibility features timeout is available */
            lpAccessTimeout->dwFlags = 0;
            lpAccessTimeout->iTimeOutMSec = 0;
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1889 1890
    WINE_SPI_FIXME(SPI_SETACCESSTIMEOUT);	/*     61 */

1891 1892
    case SPI_GETSERIALKEYS:                     /*     62  WINVER >= 0x400 */
    {
1893
        LPSERIALKEYSW lpSerialKeysW = pvParam;
1894
        WARN("SPI_GETSERIALKEYS not fully implemented\n");
1895
        if (lpSerialKeysW && lpSerialKeysW->cbSize == sizeof(SERIALKEYSW))
1896 1897
        {
            /* Indicate that no SerialKeys feature available */
1898 1899 1900 1901 1902
            lpSerialKeysW->dwFlags = 0;
            lpSerialKeysW->lpszActivePort = NULL;
            lpSerialKeysW->lpszPort = NULL;
            lpSerialKeysW->iBaudRate = 0;
            lpSerialKeysW->iPortState = 0;
1903 1904 1905 1906 1907 1908 1909
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1910 1911
    WINE_SPI_FIXME(SPI_SETSERIALKEYS);		/*     63  WINVER >= 0x400 */

1912 1913
    case SPI_GETSOUNDSENTRY:                    /*     64 */
    {
1914
        LPSOUNDSENTRYW lpSoundSentryW = pvParam;
1915
        WARN("SPI_GETSOUNDSENTRY not fully implemented\n");
1916
        if (lpSoundSentryW && lpSoundSentryW->cbSize == sizeof(SOUNDSENTRYW))
1917 1918
        {
            /* Indicate that no SoundSentry feature available */
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929
            lpSoundSentryW->dwFlags = 0;
            lpSoundSentryW->iFSTextEffect = 0;
            lpSoundSentryW->iFSTextEffectMSec = 0;
            lpSoundSentryW->iFSTextEffectColorBits = 0;
            lpSoundSentryW->iFSGrafEffect = 0;
            lpSoundSentryW->iFSGrafEffectMSec = 0;
            lpSoundSentryW->iFSGrafEffectColor = 0;
            lpSoundSentryW->iWindowsEffect = 0;
            lpSoundSentryW->iWindowsEffectMSec = 0;
            lpSoundSentryW->lpszWindowsEffectDLL = 0;
            lpSoundSentryW->iWindowsEffectOrdinal = 0;
1930 1931 1932 1933 1934 1935 1936
        }
        else
        {
            ret = FALSE;
        }
        break;
    }
1937
    WINE_SPI_FIXME(SPI_SETSOUNDSENTRY);		/*     65 */
1938

1939 1940
    case SPI_GETHIGHCONTRAST:			/*     66  WINVER >= 0x400 */
    {
1941
        LPHIGHCONTRASTW lpHighContrastW = pvParam;
1942
	WARN("SPI_GETHIGHCONTRAST not fully implemented\n");
1943
	if (lpHighContrastW && lpHighContrastW->cbSize == sizeof(HIGHCONTRASTW))
1944
	{
1945
	    /* Indicate that no high contrast feature available */
1946 1947
	    lpHighContrastW->dwFlags = 0;
	    lpHighContrastW->lpszDefaultScheme = NULL;
1948
	}
1949 1950 1951 1952 1953 1954 1955 1956
	else
	{
	    ret = FALSE;
	}
	break;
    }
    WINE_SPI_FIXME(SPI_SETHIGHCONTRAST);	/*     67  WINVER >= 0x400 */

1957 1958 1959 1960 1961
    case SPI_GETKEYBOARDPREF:
        ret = get_bool_param( SPI_SETKEYBOARDPREF_IDX,
                              SPI_SETKEYBOARDPREF_REGKEY,
                              SPI_SETKEYBOARDPREF_VALNAME,
                              &keyboard_pref, pvParam );
1962
        break;
1963

1964 1965 1966 1967 1968
    case SPI_SETKEYBOARDPREF:
        ret = set_bool_param( SPI_SETKEYBOARDPREF_IDX,
                              SPI_SETKEYBOARDPREF_REGKEY,
                              SPI_SETKEYBOARDPREF_VALNAME,
                              &keyboard_pref, uiParam, fWinIni );
1969
        break;
1970

1971 1972 1973 1974 1975
    case SPI_GETSCREENREADER:
        ret = get_bool_param( SPI_SETSCREENREADER_IDX,
                              SPI_SETSCREENREADER_REGKEY,
                              SPI_SETSCREENREADER_VALNAME,
                              &screen_reader, pvParam );
1976 1977
        break;

1978 1979 1980 1981 1982
    case SPI_SETSCREENREADER:
        ret = set_bool_param( SPI_SETSCREENREADER_IDX,
                              SPI_SETSCREENREADER_REGKEY,
                              SPI_SETSCREENREADER_VALNAME,
                              &screen_reader, uiParam, fWinIni );
1983
        break;
1984 1985 1986

    case SPI_GETANIMATION:			/*     72  WINVER >= 0x400 */
    {
1987
        LPANIMATIONINFO lpAnimInfo = pvParam;
1988

1989
	/* Tell it "disabled" */
1990
	if (lpAnimInfo && lpAnimInfo->cbSize == sizeof(ANIMATIONINFO))
1991 1992 1993 1994 1995 1996 1997
	    lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
	else
	    ret = FALSE;
	break;
    }
    WINE_SPI_WARN(SPI_SETANIMATION);		/*     73  WINVER >= 0x400 */

1998
    case SPI_GETFONTSMOOTHING:
1999 2000
    {
        UINT tmpval;
2001 2002 2003
        ret = get_uint_param( SPI_SETFONTSMOOTHING_IDX,
                              SPI_SETFONTSMOOTHING_REGKEY,
                              SPI_SETFONTSMOOTHING_VALNAME,
2004
                              &font_smoothing, &tmpval );
2005 2006 2007 2008
        if (!pvParam) ret = FALSE;

        if (ret)
            *(UINT *) pvParam = ( tmpval != 0);
2009
        break;
2010
    }
2011
    case SPI_SETFONTSMOOTHING:
2012
        uiParam = uiParam ? 2 : 0; /* Win NT4/2k/XP behavior */
2013 2014 2015 2016 2017
        ret = set_uint_param( SPI_SETFONTSMOOTHING_IDX,
                              SPI_SETFONTSMOOTHING_REGKEY,
                              SPI_SETFONTSMOOTHING_VALNAME,
                              &font_smoothing, uiParam, fWinIni );
        break;
2018 2019 2020 2021 2022 2023 2024 2025 2026 2027

    WINE_SPI_FIXME(SPI_SETDRAGWIDTH);		/*     76  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_SETDRAGHEIGHT);		/*     77  WINVER >= 0x400 */

    WINE_SPI_FIXME(SPI_SETHANDHELD);		/*     78  WINVER >= 0x400 */

    WINE_SPI_FIXME(SPI_GETLOWPOWERTIMEOUT);	/*     79  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_GETPOWEROFFTIMEOUT);	/*     80  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_SETLOWPOWERTIMEOUT);	/*     81  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_SETPOWEROFFTIMEOUT);	/*     82  WINVER >= 0x400 */
2028

2029 2030 2031 2032 2033
    case SPI_GETLOWPOWERACTIVE:
        ret = get_bool_param( SPI_SETLOWPOWERACTIVE_IDX,
                              SPI_SETLOWPOWERACTIVE_REGKEY,
                              SPI_SETLOWPOWERACTIVE_VALNAME,
                              &lowpoweractive, pvParam );
2034 2035
        break;

2036 2037 2038 2039 2040
    case SPI_GETPOWEROFFACTIVE:
        ret = get_bool_param( SPI_SETPOWEROFFACTIVE_IDX,
                              SPI_SETPOWEROFFACTIVE_REGKEY,
                              SPI_SETPOWEROFFACTIVE_VALNAME,
                              &poweroffactive, pvParam );
2041 2042
        break;

2043 2044 2045 2046 2047
    case SPI_SETLOWPOWERACTIVE:
        ret = set_bool_param( SPI_SETLOWPOWERACTIVE_IDX,
                              SPI_SETLOWPOWERACTIVE_REGKEY,
                              SPI_SETLOWPOWERACTIVE_VALNAME,
                              &lowpoweractive, uiParam, fWinIni );
2048 2049
        break;

2050 2051 2052 2053 2054
    case SPI_SETPOWEROFFACTIVE:
        ret = set_bool_param( SPI_SETPOWEROFFACTIVE_IDX,
                              SPI_SETPOWEROFFACTIVE_REGKEY,
                              SPI_SETPOWEROFFACTIVE_VALNAME,
                              &poweroffactive, uiParam, fWinIni );
2055
        break;
2056

2057 2058 2059
    WINE_SPI_FIXME(SPI_SETCURSORS);		/*     87  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_SETICONS);		/*     88  WINVER >= 0x400 */

2060
    case SPI_GETDEFAULTINPUTLANG: 	/*     89  WINVER >= 0x400 */
2061
        ret = GetKeyboardLayout(0) ? TRUE : FALSE;
2062 2063
        break;

2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074
    WINE_SPI_FIXME(SPI_SETDEFAULTINPUTLANG);	/*     90  WINVER >= 0x400 */

    WINE_SPI_FIXME(SPI_SETLANGTOGGLE);		/*     91  WINVER >= 0x400 */

    case SPI_GETWINDOWSEXTENSION:		/*     92  WINVER >= 0x400 */
	WARN("pretend no support for Win9x Plus! for now.\n");
	ret = FALSE; /* yes, this is the result value */
	break;

    WINE_SPI_FIXME(SPI_SETMOUSETRAILS);		/*     93  WINVER >= 0x400 */
    WINE_SPI_FIXME(SPI_GETMOUSETRAILS);		/*     94  WINVER >= 0x400 */
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088

    case SPI_GETSNAPTODEFBUTTON:		/*     95  WINVER >= 0x400 */
        ret = get_bool_param( SPI_SETSNAPTODEFBUTTON_IDX,
                              SPI_SETSNAPTODEFBUTTON_REGKEY,
                              SPI_SETSNAPTODEFBUTTON_VALNAME,
                              &snap_to_default_button, pvParam );
        break;

    case SPI_SETSNAPTODEFBUTTON:		/*     96  WINVER >= 0x400 */
        ret = set_bool_param( SPI_SETSNAPTODEFBUTTON_IDX,
                              SPI_SETSNAPTODEFBUTTON_REGKEY,
                              SPI_SETSNAPTODEFBUTTON_VALNAME,
                              &snap_to_default_button, uiParam, fWinIni );
        break;
2089

2090 2091 2092 2093 2094
    case SPI_SETSCREENSAVERRUNNING:
        ret = set_bool_param( SPI_SETSCREENSAVERRUNNING_IDX,
                              SPI_SETSCREENSAVERRUNNING_REGKEY,
                              SPI_SETSCREENSAVERRUNNING_VALNAME,
                              &screensaver_running, uiParam, fWinIni );
2095
        break;
2096

2097 2098 2099 2100 2101
    case SPI_GETMOUSEHOVERWIDTH:
        ret = get_uint_param( SPI_SETMOUSEHOVERWIDTH_IDX,
                              SPI_SETMOUSEHOVERWIDTH_REGKEY,
                              SPI_SETMOUSEHOVERWIDTH_VALNAME,
                              &mouse_hover_width, pvParam );
2102 2103
        break;

2104 2105 2106 2107 2108
    case SPI_SETMOUSEHOVERWIDTH:
        ret = set_uint_param( SPI_SETMOUSEHOVERWIDTH_IDX,
                              SPI_SETMOUSEHOVERWIDTH_REGKEY,
                              SPI_SETMOUSEHOVERWIDTH_VALNAME,
                              &mouse_hover_width, uiParam, fWinIni );
2109 2110
        break;

2111 2112 2113 2114 2115
    case SPI_GETMOUSEHOVERHEIGHT:
        ret = get_uint_param( SPI_SETMOUSEHOVERHEIGHT_IDX,
                              SPI_SETMOUSEHOVERHEIGHT_REGKEY,
                              SPI_SETMOUSEHOVERHEIGHT_VALNAME,
                              &mouse_hover_height, pvParam );
2116 2117
        break;

2118 2119 2120 2121 2122
    case SPI_SETMOUSEHOVERHEIGHT:
        ret = set_uint_param( SPI_SETMOUSEHOVERHEIGHT_IDX,
                              SPI_SETMOUSEHOVERHEIGHT_REGKEY,
                              SPI_SETMOUSEHOVERHEIGHT_VALNAME,
                              &mouse_hover_height, uiParam, fWinIni );
2123
        break;
2124

2125 2126 2127 2128 2129 2130
    case SPI_GETMOUSEHOVERTIME:
        ret = get_uint_param( SPI_SETMOUSEHOVERTIME_IDX,
                              SPI_SETMOUSEHOVERTIME_REGKEY,
                              SPI_SETMOUSEHOVERTIME_VALNAME,
                              &mouse_hover_time, pvParam );
        break;
2131

2132 2133 2134 2135 2136 2137
    case SPI_SETMOUSEHOVERTIME:
        ret = set_uint_param( SPI_SETMOUSEHOVERTIME_IDX,
                              SPI_SETMOUSEHOVERTIME_REGKEY,
                              SPI_SETMOUSEHOVERTIME_VALNAME,
                              &mouse_hover_time, uiParam, fWinIni );
        break;
2138

2139 2140 2141 2142 2143 2144
    case SPI_GETWHEELSCROLLLINES:
        ret = get_uint_param( SPI_SETMOUSESCROLLLINES_IDX,
                              SPI_SETMOUSESCROLLLINES_REGKEY,
                              SPI_SETMOUSESCROLLLINES_VALNAME,
                              &mouse_scroll_lines, pvParam );
        break;
2145

2146 2147 2148 2149 2150 2151
    case SPI_SETWHEELSCROLLLINES:
        ret = set_uint_param( SPI_SETMOUSESCROLLLINES_IDX,
                              SPI_SETMOUSESCROLLLINES_REGKEY,
                              SPI_SETMOUSESCROLLLINES_VALNAME,
                              &mouse_scroll_lines, uiParam, fWinIni );
        break;
2152

2153 2154 2155 2156 2157 2158
    case SPI_GETMENUSHOWDELAY:
        ret = get_uint_param( SPI_SETMENUSHOWDELAY_IDX,
                              SPI_SETMENUSHOWDELAY_REGKEY,
                              SPI_SETMENUSHOWDELAY_VALNAME,
                              &menu_show_delay, pvParam );
        break;
2159

2160 2161 2162 2163 2164
    case SPI_SETMENUSHOWDELAY:
        ret = set_uint_param( SPI_SETMENUSHOWDELAY_IDX,
                              SPI_SETMENUSHOWDELAY_REGKEY,
                              SPI_SETMENUSHOWDELAY_VALNAME,
                              &menu_show_delay, uiParam, fWinIni );
2165
        break;
2166

2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
    case SPI_GETWHEELSCROLLCHARS:			/*    108  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
        ret = get_uint_param( SPI_SETMOUSESCROLLCHARS_IDX,
                              SPI_SETMOUSESCROLLCHARS_REGKEY,
                              SPI_SETMOUSESCROLLCHARS_VALNAME,
                              &mouse_scroll_chars, pvParam );
        break;

    case SPI_SETWHEELSCROLLCHARS:			/*    109  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
        ret = set_uint_param( SPI_SETMOUSESCROLLCHARS_IDX,
                              SPI_SETMOUSESCROLLCHARS_REGKEY,
                              SPI_SETMOUSESCROLLCHARS_VALNAME,
                              &mouse_scroll_chars, uiParam, fWinIni );
        break;

2181 2182
    WINE_SPI_FIXME(SPI_GETSHOWIMEUI);		/*    110  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETSHOWIMEUI);		/*    111  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
2183 2184

    case SPI_GETMOUSESPEED:             /*    112  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2185 2186 2187 2188
        ret = get_uint_param( SPI_SETMOUSESPEED_IDX,
                              SPI_SETMOUSESPEED_REGKEY,
                              SPI_SETMOUSESPEED_VALNAME,
                              &mouse_sensitivity, pvParam );
2189 2190
        break;

2191
    case SPI_SETMOUSESPEED:                     /*    113  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2192 2193 2194
        ret = set_uint_param( SPI_SETMOUSESPEED_IDX,
                              SPI_SETMOUSESPEED_REGKEY,
                              SPI_SETMOUSESPEED_VALNAME,
2195
                              &mouse_sensitivity, PtrToInt(pvParam), fWinIni );
2196 2197

        break;
2198

2199 2200 2201 2202 2203
    case SPI_GETSCREENSAVERRUNNING:
        ret = get_bool_param( SPI_SETSCREENSAVERRUNNING_IDX,
                              SPI_SETSCREENSAVERRUNNING_REGKEY,
                              SPI_SETSCREENSAVERRUNNING_VALNAME,
                              &screensaver_running, pvParam );
2204 2205
        break;

2206 2207
    case SPI_GETDESKWALLPAPER:                  /*    115  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    {
2208
	WCHAR buf[MAX_PATH];
2209

2210 2211
        if (!pvParam) return FALSE;

2212 2213 2214 2215 2216
        if (uiParam > MAX_PATH)
	{
	    uiParam = MAX_PATH;
	}

2217
        if (SYSPARAMS_Load(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, buf, sizeof(buf)))
2218
	{
2219
            lstrcpynW(pvParam, buf, uiParam);
2220 2221 2222 2223
	}
	else
	{
	    /* Return an empty string */
2224
            memset(pvParam, 0, uiParam);
2225 2226 2227 2228 2229
	}

	break;
    }

2230 2231
    WINE_SPI_FIXME(SPI_GETACTIVEWINDOWTRACKING);/* 0x1000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETACTIVEWINDOWTRACKING);/* 0x1001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2232 2233 2234 2235 2236
    case SPI_GETMENUANIMATION:             /* 0x1002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 0, 0x02, pvParam );
        break;

    case SPI_SETMENUANIMATION:             /* 0x1003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2237
        ret = set_user_pref_param( 0, 0x02, PtrToUlong(pvParam), fWinIni );
2238 2239
        break;

2240 2241 2242 2243 2244
    case SPI_GETCOMBOBOXANIMATION:         /* 0x1004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 0, 0x04, pvParam );
        break;

    case SPI_SETCOMBOBOXANIMATION:         /* 0x1005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2245
        ret = set_user_pref_param( 0, 0x04, PtrToUlong(pvParam), fWinIni );
2246
        break;
2247 2248

    case SPI_GETLISTBOXSMOOTHSCROLLING:    /* 0x1006  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2249
        ret = get_user_pref_param( 0, 0x08, pvParam );
2250 2251
        break;

2252
    case SPI_SETLISTBOXSMOOTHSCROLLING:    /* 0x1007  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2253
        ret = set_user_pref_param( 0, 0x08, PtrToUlong(pvParam), fWinIni );
2254
        break;
2255

2256 2257
    case SPI_GETGRADIENTCAPTIONS:
        ret = get_user_pref_param( 0, 0x10, pvParam );
2258 2259
        break;

2260
    case SPI_SETGRADIENTCAPTIONS:
2261
        ret = set_user_pref_param( 0, 0x10, PtrToUlong(pvParam), fWinIni );
2262
        break;
2263

2264 2265 2266
    case SPI_GETKEYBOARDCUES:
        ret = get_user_pref_param( 0, 0x20, pvParam );
        break;
2267

2268
    case SPI_SETKEYBOARDCUES:
2269
        ret = set_user_pref_param( 0, 0x20, PtrToUlong(pvParam), fWinIni );
2270 2271
        break;

2272 2273
    WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKZORDER);  /* 0x100C  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKZORDER);  /* 0x100D  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2274 2275 2276
    case SPI_GETHOTTRACKING:
        ret = get_user_pref_param( 0, 0x80, pvParam );
        break;
2277

2278
    case SPI_SETHOTTRACKING:
2279
        ret = set_user_pref_param( 0, 0x80, PtrToUlong(pvParam), fWinIni );
2280 2281
        break;

2282 2283
    WINE_SPI_FIXME(SPI_GETMENUFADE);            /* 0x1012  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETMENUFADE);            /* 0x1013  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2284 2285 2286 2287 2288
    case SPI_GETSELECTIONFADE:                  /* 0x1014  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 1, 0x04, pvParam );
        break;

    case SPI_SETSELECTIONFADE:                  /* 0x1015  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2289
        ret = set_user_pref_param( 1, 0x04, PtrToUlong(pvParam), fWinIni );
2290 2291
        break;

2292 2293 2294 2295 2296
    case SPI_GETTOOLTIPANIMATION:               /* 0x1016  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 1, 0x08, pvParam );
        break;

    case SPI_SETTOOLTIPANIMATION:               /* 0x1017  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2297
        ret = set_user_pref_param( 1, 0x08, PtrToUlong(pvParam), fWinIni );
2298 2299 2300 2301 2302 2303 2304
        break;

    case SPI_GETTOOLTIPFADE:                    /* 0x1018  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 1, 0x10, pvParam );
        break;

    case SPI_SETTOOLTIPFADE:                    /* 0x1019  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2305
        ret = set_user_pref_param( 1, 0x10, PtrToUlong(pvParam), fWinIni );
2306 2307
        break;

2308 2309 2310 2311 2312
    case SPI_GETCURSORSHADOW:                   /* 0x101A  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_user_pref_param( 1, 0x20, pvParam );
        break;

    case SPI_SETCURSORSHADOW:                   /* 0x101B  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2313
        ret = set_user_pref_param( 1, 0x20, PtrToUlong(pvParam), fWinIni );
2314 2315
        break;

2316 2317 2318 2319 2320 2321
    WINE_SPI_FIXME(SPI_GETMOUSESONAR);          /* 0x101C  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
    WINE_SPI_FIXME(SPI_SETMOUSESONAR);          /* 0x101D  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
    WINE_SPI_FIXME(SPI_GETMOUSECLICKLOCK);      /* 0x101E  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
    WINE_SPI_FIXME(SPI_SETMOUSECLICKLOCK);      /* 0x101F  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
    WINE_SPI_FIXME(SPI_GETMOUSEVANISH);         /* 0x1020  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
    WINE_SPI_FIXME(SPI_SETMOUSEVANISH);         /* 0x1021  _WIN32_WINNT >= 0x510 || _WIN32_WINDOW >= 0x490*/
2322 2323
    case SPI_GETFLATMENU:
        ret = get_user_pref_param( 2, 0x02, pvParam );
2324 2325
        break;

2326
    case SPI_SETFLATMENU:
2327
        ret = set_user_pref_param( 2, 0x02, PtrToUlong(pvParam), fWinIni );
2328 2329
        break;

2330 2331
    WINE_SPI_FIXME(SPI_GETDROPSHADOW);          /* 0x1024  _WIN32_WINNT >= 0x510 */
    WINE_SPI_FIXME(SPI_SETDROPSHADOW);          /* 0x1025  _WIN32_WINNT >= 0x510 */
2332 2333
    WINE_SPI_FIXME(SPI_GETBLOCKSENDINPUTRESETS);
    WINE_SPI_FIXME(SPI_SETBLOCKSENDINPUTRESETS);
2334 2335 2336 2337 2338 2339
    case SPI_GETUIEFFECTS:
        ret = get_user_pref_param( 3, 0x80, pvParam );
        break;

    case SPI_SETUIEFFECTS:
        /* FIXME: this probably should mask other UI effect values when unset */
2340
        ret = set_user_pref_param( 3, 0x80, PtrToUlong(pvParam), fWinIni );
2341 2342
        break;

2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358
    case SPI_GETFOREGROUNDLOCKTIMEOUT:          /* 0x2000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_uint_param( SPI_SETFOREGROUNDLOCKTIMEOUT_IDX,
                              SPI_SETFOREGROUNDLOCKTIMEOUT_REGKEY,
                              SPI_SETFOREGROUNDLOCKTIMEOUT_VALNAME,
                              &foreground_lock_timeout, pvParam );
        break;

    case SPI_SETFOREGROUNDLOCKTIMEOUT:          /* 0x2001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        /* FIXME: this should check that the calling thread
         * is able to change the foreground window */
        ret = set_uint_param( SPI_SETFOREGROUNDLOCKTIMEOUT_IDX,
                              SPI_SETFOREGROUNDLOCKTIMEOUT_REGKEY,
                              SPI_SETFOREGROUNDLOCKTIMEOUT_VALNAME,
                              &foreground_lock_timeout, PtrToUlong(pvParam), fWinIni );
        break;

2359 2360 2361 2362
    WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKTIMEOUT); /* 0x2002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKTIMEOUT); /* 0x2003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_GETFOREGROUNDFLASHCOUNT);/* 0x2004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETFOREGROUNDFLASHCOUNT);/* 0x2005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376
    case SPI_GETCARETWIDTH:          /* 0x2006  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = get_uint_param( SPI_CARETWIDTH_IDX,
                              SPI_CARETWIDTH_REGKEY,
                              SPI_CARETWIDTH_VALNAME,
                              &caret_width, pvParam );
        break;

    case SPI_SETCARETWIDTH:          /* 0x2007  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        ret = set_uint_param( SPI_CARETWIDTH_IDX,
                              SPI_CARETWIDTH_REGKEY,
                              SPI_CARETWIDTH_VALNAME,
                              &caret_width, uiParam, fWinIni );
        break;

2377 2378
    WINE_SPI_FIXME(SPI_GETMOUSECLICKLOCKTIME);  /* 0x2008  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
    WINE_SPI_FIXME(SPI_SETMOUSECLICKLOCKTIME);  /* 0x2009  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
    case SPI_GETFONTSMOOTHINGTYPE:              /* 0x200A  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        spi_idx = SPI_SETFONTSMOOTHINGTYPE_IDX;
        if (!spi_loaded[spi_idx])
        {
            ret = SYSPARAMS_Load( SPI_SETFONTSMOOTHINGTYPE_REGKEY,
                                  SPI_SETFONTSMOOTHINGTYPE_VALNAME,
                                  (LPWSTR)&font_smoothing_type,
                                  sizeof(font_smoothing_type) );
            if ( ret) spi_loaded[spi_idx] = TRUE;
        }
        if (!pvParam) ret = FALSE;

        if (ret)
            *(UINT *)pvParam = font_smoothing_type;
        break;

    case SPI_SETFONTSMOOTHINGTYPE:              /* 0x200B  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
        spi_idx = SPI_SETFONTSMOOTHINGTYPE_IDX;
        if (SYSPARAMS_SaveRaw( SPI_SETFONTSMOOTHINGTYPE_REGKEY,
                               SPI_SETFONTSMOOTHINGTYPE_VALNAME,
                               (LPBYTE)&pvParam, sizeof(UINT), REG_DWORD, fWinIni ))
        {
2401
            font_smoothing_type = PtrToUlong(pvParam);
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430
            spi_loaded[spi_idx] = TRUE;
        }
        else
            ret = FALSE;
        break;

    case SPI_GETFONTSMOOTHINGCONTRAST:          /* 0x200C  _WIN32_WINNT >= 0x510 */
        spi_idx = SPI_SETFONTSMOOTHINGCONTRAST_IDX;
        if (!spi_loaded[spi_idx])
        {
            ret = SYSPARAMS_Load( SPI_SETFONTSMOOTHINGCONTRAST_REGKEY,
                                  SPI_SETFONTSMOOTHINGCONTRAST_VALNAME,
                                  (LPWSTR)&font_smoothing_contrast,
                                  sizeof(font_smoothing_contrast) );
            if (ret)
                spi_loaded[spi_idx] = TRUE;
        }
        if (!pvParam) ret = FALSE;

	if (ret)
            *(UINT *)pvParam = font_smoothing_contrast;
        break;

    case SPI_SETFONTSMOOTHINGCONTRAST:          /* 0x200D  _WIN32_WINNT >= 0x510 */
        spi_idx = SPI_SETFONTSMOOTHINGCONTRAST_IDX;
        if (SYSPARAMS_SaveRaw( SPI_SETFONTSMOOTHINGCONTRAST_REGKEY,
                               SPI_SETFONTSMOOTHINGCONTRAST_VALNAME,
                               (LPBYTE)&pvParam, sizeof(UINT), REG_DWORD, fWinIni ))
        {
2431
            font_smoothing_contrast = PtrToUlong(pvParam);
2432 2433 2434 2435 2436 2437
            spi_loaded[spi_idx] = TRUE;
        }
        else
            ret = FALSE;
        break;

2438 2439 2440 2441 2442 2443 2444 2445 2446
    case SPI_GETFOCUSBORDERWIDTH: /* 0x200E  _WIN32_WINNT >= 0x510 */
    case SPI_GETFOCUSBORDERHEIGHT: /* 0x200F  _WIN32_WINNT >= 0x510 */
        if (!pvParam)
            ret = FALSE;
        else
            *(UINT *)pvParam = 1;
        break;

    WINE_SPI_FIXME(SPI_SETFOCUSBORDERWIDTH);     /* 0x2010  _WIN32_WINNT >= 0x510 */
2447
    WINE_SPI_FIXME(SPI_SETFOCUSBORDERHEIGHT);    /* 0x2011  _WIN32_WINNT >= 0x510 */
2448

2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471
    case SPI_GETFONTSMOOTHINGORIENTATION:       /* 0x2012 */
        spi_idx = SPI_SETFONTSMOOTHINGORIENTATION_IDX;
        if (!spi_loaded[spi_idx])
        {
            ret = SYSPARAMS_Load( SPI_SETFONTSMOOTHINGORIENTATION_REGKEY,
                                  SPI_SETFONTSMOOTHINGORIENTATION_VALNAME,
                                  (LPWSTR)&font_smoothing_orientation,
                                  sizeof(font_smoothing_orientation) );
            if (ret)
                spi_loaded[spi_idx] = TRUE;
        }
        if (!pvParam) ret = FALSE;

        if (ret)
            *(UINT *)pvParam = font_smoothing_orientation;
        break;

    case SPI_SETFONTSMOOTHINGORIENTATION:       /* 0x2013 */
        spi_idx = SPI_SETFONTSMOOTHINGORIENTATION_IDX;
        if (SYSPARAMS_SaveRaw( SPI_SETFONTSMOOTHINGORIENTATION_REGKEY,
                               SPI_SETFONTSMOOTHINGORIENTATION_VALNAME,
                               (LPBYTE)&pvParam, sizeof(UINT), REG_DWORD, fWinIni ))
        {
2472
            font_smoothing_orientation = PtrToUlong(pvParam);
2473 2474 2475 2476 2477
            spi_loaded[spi_idx] = TRUE;
        }
        else
            ret = FALSE;
        break;
2478

2479 2480 2481 2482 2483 2484 2485
    default:
	FIXME( "Unknown action: %u\n", uiAction );
	SetLastError( ERROR_INVALID_SPI_VALUE );
	ret = FALSE;
	break;
    }

2486 2487
    if (ret)
        SYSPARAMS_NotifyChange( uiAction, fWinIni );
2488 2489
    TRACE("(%u, %u, %p, %u) ret %d\n",
            uiAction, uiParam, pvParam, fWinIni, ret);
2490
    return ret;
2491

2492 2493
#undef WINE_SPI_FIXME
#undef WINE_SPI_WARN
2494 2495 2496 2497
}


/***********************************************************************
2498
 *		SystemParametersInfo (USER.483)
2499 2500 2501 2502
 */
BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
                                      LPVOID lpvParam, UINT16 fuWinIni )
{
2503
    BOOL16 ret;
2504

2505
    TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
2506

2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564
    switch (uAction)
    {
    case SPI_GETBEEP:				/*      1 */
    case SPI_GETSCREENSAVEACTIVE:		/*     16 */
    case SPI_GETICONTITLEWRAP:			/*     25 */
    case SPI_GETMENUDROPALIGNMENT:		/*     27 */
    case SPI_GETFASTTASKSWITCH:			/*     35 */
    case SPI_GETDRAGFULLWINDOWS:		/*     38  WINVER >= 0x0400 */
    {
	BOOL tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
	    *(BOOL16 *)lpvParam = tmp;
	break;
    }

    case SPI_GETBORDER:				/*      5 */
    case SPI_ICONHORIZONTALSPACING:		/*     13 */
    case SPI_GETSCREENSAVETIMEOUT:		/*     14 */
    case SPI_GETGRIDGRANULARITY:		/*     18 */
    case SPI_GETKEYBOARDDELAY:			/*     22 */
    case SPI_ICONVERTICALSPACING:		/*     24 */
    {
	INT tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
	    *(INT16 *)lpvParam = tmp;
	break;
    }

    case SPI_GETKEYBOARDSPEED:			/*     10 */
    {
	DWORD tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
	    *(WORD *)lpvParam = tmp;
	break;
    }

    case SPI_GETICONTITLELOGFONT:		/*     31 */
    {
	LOGFONTA tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
	    SYSPARAMS_LogFont32ATo16( &tmp, (LPLOGFONT16)lpvParam );
	break;
    }

    case SPI_GETNONCLIENTMETRICS: 		/*     41  WINVER >= 0x400 */
    {
	NONCLIENTMETRICSA tmp;
	LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
	if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
	{
	    tmp.cbSize = sizeof(NONCLIENTMETRICSA);
	    ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
	    if (ret)
		SYSPARAMS_NonClientMetrics32ATo16( &tmp, lpnm16 );
2565
	}
2566 2567 2568 2569
	else /* winfile 95 sets cbSize to 340 */
	    ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
	break;
    }
2570

2571 2572 2573 2574 2575
    case SPI_GETWORKAREA:			/*     48  WINVER >= 0x400 */
    {
	RECT tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
2576
        {
2577
            RECT16 *r16 = lpvParam;
2578 2579 2580 2581 2582
            r16->left   = tmp.left;
            r16->top    = tmp.top;
            r16->right  = tmp.right;
            r16->bottom = tmp.bottom;
        }
2583 2584
	break;
    }
2585

2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601
    case SPI_GETMOUSEHOVERWIDTH:		/*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
    case SPI_GETMOUSEHOVERHEIGHT:		/*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
    case SPI_GETMOUSEHOVERTIME:			/*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
    {
	UINT tmp;
	ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
	if (ret && lpvParam)
	    *(UINT16 *)lpvParam = tmp;
	break;
    }

    default:
	ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
    }

    return ret;
2602 2603 2604
}

/***********************************************************************
2605
 *		SystemParametersInfoA (USER32.@)
2606
 */
2607
BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
2608
				   PVOID pvParam, UINT fuWinIni )
2609
{
2610
    BOOL ret;
2611

2612
    TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
2613

2614
    switch (uiAction)
2615
    {
2616 2617 2618
    case SPI_SETDESKWALLPAPER:			/*     20 */
    case SPI_SETDESKPATTERN:			/*     21 */
    {
2619
	WCHAR buffer[256];
2620
	if (pvParam)
2621 2622
            if (!MultiByteToWideChar( CP_ACP, 0, pvParam, -1, buffer,
                                      sizeof(buffer)/sizeof(WCHAR) ))
2623 2624
                buffer[sizeof(buffer)/sizeof(WCHAR)-1] = 0;
	ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
2625 2626
	break;
    }
2627

2628 2629
    case SPI_GETICONTITLELOGFONT:		/*     31 */
    {
2630 2631
	LOGFONTW tmp;
	ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
2632
	if (ret && pvParam)
2633
            SYSPARAMS_LogFont32WTo32A( &tmp, pvParam );
2634 2635 2636
	break;
    }

2637
    case SPI_GETNONCLIENTMETRICS: 		/*     41  WINVER >= 0x400 */
2638
    {
2639
	NONCLIENTMETRICSW tmp;
2640
        LPNONCLIENTMETRICSA lpnmA = pvParam;
2641
	if (lpnmA && lpnmA->cbSize == sizeof(NONCLIENTMETRICSA))
2642
	{
2643 2644
	    tmp.cbSize = sizeof(NONCLIENTMETRICSW);
	    ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2645
	    if (ret)
2646
		SYSPARAMS_NonClientMetrics32WTo32A( &tmp, lpnmA );
2647 2648 2649 2650
	}
	else
	    ret = FALSE;
	break;
2651 2652
    }

2653 2654 2655
    case SPI_SETNONCLIENTMETRICS: 		/*     42  WINVER >= 0x400 */
    {
        NONCLIENTMETRICSW tmp;
2656
        LPNONCLIENTMETRICSA lpnmA = pvParam;
2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
        if (lpnmA && lpnmA->cbSize == sizeof(NONCLIENTMETRICSA))
        {
            tmp.cbSize = sizeof(NONCLIENTMETRICSW);
            SYSPARAMS_NonClientMetrics32ATo32W( lpnmA, &tmp );
            ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
        }
        else
            ret = FALSE;
        break;
    }

2668 2669
    case SPI_GETICONMETRICS:			/*     45  WINVER >= 0x400 */
    {
2670
	ICONMETRICSW tmp;
2671
        LPICONMETRICSA lpimA = pvParam;
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690
	if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
	{
	    tmp.cbSize = sizeof(ICONMETRICSW);
	    ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
	    if (ret)
	    {
		lpimA->iHorzSpacing = tmp.iHorzSpacing;
		lpimA->iVertSpacing = tmp.iVertSpacing;
		lpimA->iTitleWrap   = tmp.iTitleWrap;
		SYSPARAMS_LogFont32WTo32A( &tmp.lfFont, &lpimA->lfFont );
	    }
	}
	else
	    ret = FALSE;
	break;
    }

    case SPI_SETICONMETRICS:			/*     46  WINVER >= 0x400 */
    {
2691
        ICONMETRICSW tmp;
2692
        LPICONMETRICSA lpimA = pvParam;
2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704
        if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
        {
            tmp.cbSize = sizeof(ICONMETRICSW);
            tmp.iHorzSpacing = lpimA->iHorzSpacing;
            tmp.iVertSpacing = lpimA->iVertSpacing;
            tmp.iTitleWrap = lpimA->iTitleWrap;
            SYSPARAMS_LogFont32ATo32W(  &lpimA->lfFont, &tmp.lfFont);
            ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
        }
        else
            ret = FALSE;
        break;
2705 2706 2707 2708
    }

    case SPI_GETHIGHCONTRAST:			/*     66  WINVER >= 0x400 */
    {
2709
	HIGHCONTRASTW tmp;
2710
        LPHIGHCONTRASTA lphcA = pvParam;
2711
	if (lphcA && lphcA->cbSize == sizeof(HIGHCONTRASTA))
2712
	{
2713 2714
	    tmp.cbSize = sizeof(HIGHCONTRASTW);
	    ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
2715 2716
	    if (ret)
	    {
2717 2718
		lphcA->dwFlags = tmp.dwFlags;
		lphcA->lpszDefaultScheme = NULL;  /* FIXME? */
2719 2720 2721 2722 2723 2724
	    }
	}
	else
	    ret = FALSE;
	break;
    }
2725

2726 2727 2728 2729 2730 2731 2732 2733
    case SPI_GETDESKWALLPAPER:                  /*     115 */
    {
        WCHAR buffer[MAX_PATH];
        ret = (SystemParametersInfoW( SPI_GETDESKWALLPAPER, uiParam, buffer, fuWinIni ) &&
               WideCharToMultiByte(CP_ACP, 0, buffer, -1, pvParam, uiParam, NULL, NULL));
        break;
    }

2734
    default:
2735
        ret = SystemParametersInfoW( uiAction, uiParam, pvParam, fuWinIni );
2736
        break;
2737
    }
2738
    return ret;
2739
}
2740 2741


2742 2743 2744 2745 2746
/***********************************************************************
 *		GetSystemMetrics (USER32.@)
 */
INT WINAPI GetSystemMetrics( INT index )
{
2747 2748
    UINT ret;

2749 2750 2751 2752
    /* some metrics are dynamic */
    switch (index)
    {
    case SM_CXSCREEN:
2753
        return GetDeviceCaps( get_display_dc(), HORZRES );
2754
    case SM_CYSCREEN:
2755 2756 2757 2758 2759
        return GetDeviceCaps( get_display_dc(), VERTRES );
    case SM_CXVSCROLL:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iScrollWidth;
    case SM_CYHSCROLL:
2760
        return GetSystemMetrics(SM_CXVSCROLL);
2761 2762
    case SM_CYCAPTION:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2763
        return nonclient_metrics.iCaptionHeight + 1;
2764 2765 2766 2767 2768 2769 2770 2771
    case SM_CXBORDER:
    case SM_CYBORDER:
        /* SM_C{X,Y}BORDER always returns 1 regardless of 'BorderWidth' value in registry */
        return 1;
    case SM_CXDLGFRAME:
    case SM_CYDLGFRAME:
        return 3;
    case SM_CYVTHUMB:
2772 2773
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iScrollHeight;
2774
    case SM_CXHTHUMB:
2775
        return GetSystemMetrics(SM_CYVTHUMB);
2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
    case SM_CXICON:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return icon_size.cx;
    case SM_CYICON:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return icon_size.cy;
    case SM_CXCURSOR:
    case SM_CYCURSOR:
        return 32;
    case SM_CYMENU:
        return GetSystemMetrics(SM_CYMENUSIZE) + 1;
    case SM_CXFULLSCREEN:
2788 2789 2790
        /* see the remark for SM_CXMAXIMIZED, at least this formulation is
         * correct */
        return GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME);
2791
    case SM_CYFULLSCREEN:
2792 2793 2794
        /* see the remark for SM_CYMAXIMIZED, at least this formulation is
         * correct */
        return GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN);
2795 2796 2797 2798 2799 2800
    case SM_CYKANJIWINDOW:
        return 0;
    case SM_MOUSEPRESENT:
        return 1;
    case SM_CYVSCROLL:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2801
        return nonclient_metrics.iScrollHeight;
2802 2803
    case SM_CXHSCROLL:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2804
        return nonclient_metrics.iScrollHeight;
2805 2806 2807
    case SM_DEBUG:
        return 0;
    case SM_SWAPBUTTON:
2808
        get_bool_param( SPI_SETMOUSEBUTTONSWAP_IDX, SPI_SETMOUSEBUTTONSWAP_REGKEY,
Mike McCormack's avatar
Mike McCormack committed
2809
                        SPI_SETMOUSEBUTTONSWAP_VALNAME, &swap_buttons, (BOOL*)&ret );
2810 2811 2812 2813 2814 2815 2816
        return ret;
    case SM_RESERVED1:
    case SM_RESERVED2:
    case SM_RESERVED3:
    case SM_RESERVED4:
        return 0;
    case SM_CXMIN:
2817 2818 2819
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return 3 * nonclient_metrics.iCaptionWidth + GetSystemMetrics( SM_CYSIZE) +
            4 * CaptionFontAvCharWidth + 2 * GetSystemMetrics( SM_CXFRAME) + 4;
2820
    case SM_CYMIN:
2821
        return GetSystemMetrics( SM_CYCAPTION) + 2 * GetSystemMetrics( SM_CYFRAME);
2822 2823 2824 2825 2826 2827 2828
    case SM_CXSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iCaptionWidth;
    case SM_CYSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iCaptionHeight;
    case SM_CXFRAME:
2829 2830
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return GetSystemMetrics(SM_CXDLGFRAME) + nonclient_metrics.iBorderWidth;
2831
    case SM_CYFRAME:
2832
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
2833
        return GetSystemMetrics(SM_CYDLGFRAME) + nonclient_metrics.iBorderWidth;
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871
    case SM_CXMINTRACK:
        return GetSystemMetrics(SM_CXMIN);
    case SM_CYMINTRACK:
        return GetSystemMetrics(SM_CYMIN);
    case SM_CXDOUBLECLK:
        get_uint_param( SPI_SETDOUBLECLKWIDTH_IDX, SPI_SETDOUBLECLKWIDTH_REGKEY1,
                        SPI_SETDOUBLECLKWIDTH_VALNAME, &double_click_width, &ret );
        return ret;
    case SM_CYDOUBLECLK:
        get_uint_param( SPI_SETDOUBLECLKHEIGHT_IDX, SPI_SETDOUBLECLKHEIGHT_REGKEY1,
                        SPI_SETDOUBLECLKHEIGHT_VALNAME, &double_click_height, &ret );
        return ret;
    case SM_CXICONSPACING:
        SystemParametersInfoW( SPI_ICONHORIZONTALSPACING, 0, &ret, 0 );
        return ret;
    case SM_CYICONSPACING:
        SystemParametersInfoW( SPI_ICONVERTICALSPACING, 0, &ret, 0 );
        return ret;
    case SM_MENUDROPALIGNMENT:
        SystemParametersInfoW( SPI_GETMENUDROPALIGNMENT, 0, &ret, 0 );
        return ret;
    case SM_PENWINDOWS:
        return 0;
    case SM_DBCSENABLED:
    {
        CPINFO cpinfo;
        GetCPInfo( CP_ACP, &cpinfo );
        return (cpinfo.MaxCharSize > 1);
    }
    case SM_CMOUSEBUTTONS:
        return 3;
    case SM_SECURE:
        return 0;
    case SM_CXEDGE:
        return GetSystemMetrics(SM_CXBORDER) + 1;
    case SM_CYEDGE:
        return GetSystemMetrics(SM_CYBORDER) + 1;
    case SM_CXMINSPACING:
2872
        if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2873 2874
        return GetSystemMetrics(SM_CXMINIMIZED) + minimized_metrics.iHorzGap;
    case SM_CYMINSPACING:
2875
        if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894
        return GetSystemMetrics(SM_CYMINIMIZED) + minimized_metrics.iVertGap;
    case SM_CXSMICON:
    case SM_CYSMICON:
        return 16;
    case SM_CYSMCAPTION:
        return GetSystemMetrics(SM_CYSMSIZE) + 1;
    case SM_CXSMSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iSmCaptionWidth;
    case SM_CYSMSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iSmCaptionHeight;
    case SM_CXMENUSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iMenuWidth;
    case SM_CYMENUSIZE:
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iMenuHeight;
    case SM_ARRANGE:
2895
        if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2896 2897
        return minimized_metrics.iArrange;
    case SM_CXMINIMIZED:
2898
        if( spi_loaded[SPI_MINIMIZEDMETRICS_IDX]) load_minimized_metrics();
2899 2900
        return minimized_metrics.iWidth + 6;
    case SM_CYMINIMIZED:
2901 2902
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return nonclient_metrics.iCaptionHeight + 6;
2903
    case SM_CXMAXTRACK:
2904
        return GetSystemMetrics(SM_CXVIRTUALSCREEN) + 4 + 2 * GetSystemMetrics(SM_CXFRAME);
2905
    case SM_CYMAXTRACK:
2906
        return GetSystemMetrics(SM_CYVIRTUALSCREEN) + 4 + 2 * GetSystemMetrics(SM_CYFRAME);
2907
    case SM_CXMAXIMIZED:
2908
        /* FIXME: subtract the width of any vertical application toolbars*/
2909
        return GetSystemMetrics(SM_CXSCREEN) + 2 * GetSystemMetrics(SM_CXFRAME);
2910
    case SM_CYMAXIMIZED:
2911 2912
        /* FIXME: subtract the width of any horizontal application toolbars*/
        return GetSystemMetrics(SM_CYSCREEN) + 2 * GetSystemMetrics(SM_CYCAPTION);
2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
    case SM_NETWORK:
        return 3;  /* FIXME */
    case SM_CLEANBOOT:
        return 0; /* 0 = ok, 1 = failsafe, 2 = failsafe + network */
    case SM_CXDRAG:
    case SM_CYDRAG:
        return 4;
    case SM_SHOWSOUNDS:
        SystemParametersInfoW( SPI_GETSHOWSOUNDS, 0, &ret, 0 );
        return ret;
    case SM_CXMENUCHECK:
    case SM_CYMENUCHECK:
2925 2926 2927
        if (!spi_loaded[SPI_NONCLIENTMETRICS_IDX]) load_nonclient_metrics();
        return tmMenuFont.tmHeight <= 0 ? 13 :
        ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading + 1) / 2) * 2 - 1;
2928
    case SM_SLOWMACHINE:
Juan Lang's avatar
Juan Lang committed
2929
        return 0;  /* Never true */
2930 2931 2932 2933 2934
    case SM_MIDEASTENABLED:
        return 0;  /* FIXME */
    case SM_MOUSEWHEELPRESENT:
        return 1;
    case SM_XVIRTUALSCREEN:
2935 2936 2937 2938 2939
    {
        struct monitor_info info;
        get_monitors_info( &info );
        return info.virtual_rect.left;
    }
2940
    case SM_YVIRTUALSCREEN:
2941 2942 2943 2944 2945
    {
        struct monitor_info info;
        get_monitors_info( &info );
        return info.virtual_rect.top;
    }
2946
    case SM_CXVIRTUALSCREEN:
2947 2948 2949 2950 2951
    {
        struct monitor_info info;
        get_monitors_info( &info );
        return info.virtual_rect.right - info.virtual_rect.left;
    }
2952
    case SM_CYVIRTUALSCREEN:
2953 2954 2955 2956 2957
    {
        struct monitor_info info;
        get_monitors_info( &info );
        return info.virtual_rect.bottom - info.virtual_rect.top;
    }
2958
    case SM_CMONITORS:
2959 2960 2961 2962 2963
    {
        struct monitor_info info;
        get_monitors_info( &info );
        return info.count;
    }
2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
    case SM_SAMEDISPLAYFORMAT:
        return 1;
    case SM_IMMENABLED:
        return 0;  /* FIXME */
    case SM_CXFOCUSBORDER:
    case SM_CYFOCUSBORDER:
        return 1;
    case SM_TABLETPC:
    case SM_MEDIACENTER:
        return 0;
    case SM_CMETRICS:
        return SM_CMETRICS;
2976
    default:
2977
        return 0;
2978 2979 2980 2981
    }
}


2982 2983
/***********************************************************************
 *		SwapMouseButton (USER32.@)
2984 2985 2986 2987
 *  Reverse or restore the meaning of the left and right mouse buttons
 *  fSwap  [I ] TRUE - reverse, FALSE - original
 * RETURN
 *   previous state 
2988 2989 2990
 */
BOOL WINAPI SwapMouseButton( BOOL fSwap )
{
2991 2992 2993
    BOOL prev = GetSystemMetrics(SM_SWAPBUTTON);
    SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP, fSwap, 0, 0);
    return prev;
2994 2995 2996
}


2997 2998 2999 3000 3001
/**********************************************************************
 *		SetDoubleClickTime (USER32.@)
 */
BOOL WINAPI SetDoubleClickTime( UINT interval )
{
3002
    return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
3003 3004 3005 3006 3007 3008 3009 3010
}


/**********************************************************************
 *		GetDoubleClickTime (USER32.@)
 */
UINT WINAPI GetDoubleClickTime(void)
{
3011 3012 3013 3014 3015 3016 3017 3018
    UINT time = 0;

    get_uint_param( SPI_SETDOUBLECLICKTIME_IDX,
                    SPI_SETDOUBLECLICKTIME_REGKEY,
                    SPI_SETDOUBLECLICKTIME_VALNAME,
                    &double_click_time, &time );
    if (!time) time = 500;
    return time;
3019
}
3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090


/*************************************************************************
 *		GetSysColor (USER32.@)
 */
COLORREF WINAPI GetSysColor( INT nIndex )
{
    if (nIndex >= 0 && nIndex < NUM_SYS_COLORS)
        return SysColors[nIndex];
    else
        return 0;
}


/*************************************************************************
 *		SetSysColors (USER32.@)
 */
BOOL WINAPI SetSysColors( INT nChanges, const INT *lpSysColor,
                              const COLORREF *lpColorValues )
{
    int i;

    for (i = 0; i < nChanges; i++) SYSPARAMS_SetSysColor( lpSysColor[i], lpColorValues[i] );

    /* Send WM_SYSCOLORCHANGE message to all windows */

    SendMessageTimeoutW( HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0, SMTO_ABORTIFHUNG, 2000, NULL );

    /* Repaint affected portions of all visible windows */

    RedrawWindow( GetDesktopWindow(), NULL, 0,
                RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN );
    return TRUE;
}


/*************************************************************************
 *		SetSysColorsTemp (USER32.@)
 *
 * UNDOCUMENTED !!
 *
 * Called by W98SE desk.cpl Control Panel Applet:
 * handle = SetSysColorsTemp(ptr, ptr, nCount);     ("set" call)
 * result = SetSysColorsTemp(NULL, NULL, handle);   ("restore" call)
 *
 * pPens is an array of COLORREF values, which seems to be used
 * to indicate the color values to create new pens with.
 *
 * pBrushes is an array of solid brush handles (returned by a previous
 * CreateSolidBrush), which seems to contain the brush handles to set
 * for the system colors.
 *
 * n seems to be used for
 *   a) indicating the number of entries to operate on (length of pPens,
 *      pBrushes)
 *   b) passing the handle that points to the previously used color settings.
 *      I couldn't figure out in hell what kind of handle this is on
 *      Windows. I just use a heap handle instead. Shouldn't matter anyway.
 *
 * RETURNS
 *     heap handle of our own copy of the current syscolors in case of
 *                 "set" call, i.e. pPens, pBrushes != NULL.
 *     TRUE (unconditionally !) in case of "restore" call,
 *          i.e. pPens, pBrushes == NULL.
 *     FALSE in case of either pPens != NULL and pBrushes == NULL
 *          or pPens == NULL and pBrushes != NULL.
 *
 * I'm not sure whether this implementation is 100% correct. [AM]
 */
DWORD WINAPI SetSysColorsTemp( const COLORREF *pPens, const HBRUSH *pBrushes, DWORD n)
{
3091
    DWORD i;
3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107

    if (pPens && pBrushes) /* "set" call */
    {
        /* allocate our structure to remember old colors */
        LPVOID pOldCol = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD)+n*sizeof(HPEN)+n*sizeof(HBRUSH));
        LPVOID p = pOldCol;
        *(DWORD *)p = n; p = (char*)p + sizeof(DWORD);
        memcpy(p, SysColorPens, n*sizeof(HPEN)); p = (char*)p + n*sizeof(HPEN);
        memcpy(p, SysColorBrushes, n*sizeof(HBRUSH)); p = (char*)p + n*sizeof(HBRUSH);

        for (i=0; i < n; i++)
        {
            SysColorPens[i] = CreatePen( PS_SOLID, 1, pPens[i] );
            SysColorBrushes[i] = pBrushes[i];
        }

3108
        return (DWORD)pOldCol; /* FIXME: pointer truncation */
3109 3110 3111
    }
    if (!pPens && !pBrushes) /* "restore" call */
    {
3112
        LPVOID pOldCol = (LPVOID)n; /* FIXME: not 64-bit safe */
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154
        LPVOID p = pOldCol;
        DWORD nCount = *(DWORD *)p;
        p = (char*)p + sizeof(DWORD);

        for (i=0; i < nCount; i++)
        {
            DeleteObject(SysColorPens[i]);
            SysColorPens[i] = *(HPEN *)p; p = (char*)p + sizeof(HPEN);
        }
        for (i=0; i < nCount; i++)
        {
            SysColorBrushes[i] = *(HBRUSH *)p; p = (char*)p + sizeof(HBRUSH);
        }
        /* get rid of storage structure */
        HeapFree(GetProcessHeap(), 0, pOldCol);

        return TRUE;
    }
    return FALSE;
}


/***********************************************************************
 *		GetSysColorBrush (USER32.@)
 */
HBRUSH WINAPI GetSysColorBrush( INT index )
{
    if (0 <= index && index < NUM_SYS_COLORS) return SysColorBrushes[index];
    WARN("Unknown index(%d)\n", index );
    return GetStockObject(LTGRAY_BRUSH);
}


/***********************************************************************
 *		SYSCOLOR_GetPen
 */
HPEN SYSCOLOR_GetPen( INT index )
{
    /* We can assert here, because this function is internal to Wine */
    assert (0 <= index && index < NUM_SYS_COLORS);
    return SysColorPens[index];
}
3155 3156 3157 3158 3159 3160 3161


/***********************************************************************
 *		ChangeDisplaySettingsA (USER32.@)
 */
LONG WINAPI ChangeDisplaySettingsA( LPDEVMODEA devmode, DWORD flags )
{
3162 3163
    if (devmode) devmode->dmDriverExtra = 0;

3164 3165 3166 3167 3168 3169 3170 3171 3172
    return ChangeDisplaySettingsExA(NULL,devmode,NULL,flags,NULL);
}


/***********************************************************************
 *		ChangeDisplaySettingsW (USER32.@)
 */
LONG WINAPI ChangeDisplaySettingsW( LPDEVMODEW devmode, DWORD flags )
{
3173 3174
    if (devmode) devmode->dmDriverExtra = 0;

3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192
    return ChangeDisplaySettingsExW(NULL,devmode,NULL,flags,NULL);
}


/***********************************************************************
 *		ChangeDisplaySettingsExA (USER32.@)
 */
LONG WINAPI ChangeDisplaySettingsExA( LPCSTR devname, LPDEVMODEA devmode, HWND hwnd,
                                      DWORD flags, LPVOID lparam )
{
    LONG ret;
    UNICODE_STRING nameW;

    if (devname) RtlCreateUnicodeStringFromAsciiz(&nameW, devname);
    else nameW.Buffer = NULL;

    if (devmode)
    {
3193 3194 3195
        DEVMODEW *devmodeW;

        devmodeW = GdiConvertToDevmodeW(devmode);
3196 3197 3198 3199 3200 3201 3202
        if (devmodeW)
        {
            ret = ChangeDisplaySettingsExW(nameW.Buffer, devmodeW, hwnd, flags, lparam);
            HeapFree(GetProcessHeap(), 0, devmodeW);
        }
        else
            ret = DISP_CHANGE_SUCCESSFUL;
3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219
    }
    else
    {
        ret = ChangeDisplaySettingsExW(nameW.Buffer, NULL, hwnd, flags, lparam);
    }

    if (devname) RtlFreeUnicodeString(&nameW);
    return ret;
}


/***********************************************************************
 *		ChangeDisplaySettingsExW (USER32.@)
 */
LONG WINAPI ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd,
                                      DWORD flags, LPVOID lparam )
{
3220 3221 3222
    /* make sure the desktop window is created before mode changing */
    GetDesktopWindow();

3223
    return USER_Driver->pChangeDisplaySettingsEx( devname, devmode, hwnd, flags, lparam );
3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264
}


/***********************************************************************
 *		EnumDisplaySettingsW (USER32.@)
 *
 * RETURNS
 *	TRUE if nth setting exists found (described in the LPDEVMODEW struct)
 *	FALSE if we do not have the nth setting
 */
BOOL WINAPI EnumDisplaySettingsW( LPCWSTR name, DWORD n, LPDEVMODEW devmode )
{
    return EnumDisplaySettingsExW(name, n, devmode, 0);
}


/***********************************************************************
 *		EnumDisplaySettingsA (USER32.@)
 */
BOOL WINAPI EnumDisplaySettingsA(LPCSTR name,DWORD n,LPDEVMODEA devmode)
{
    return EnumDisplaySettingsExA(name, n, devmode, 0);
}


/***********************************************************************
 *		EnumDisplaySettingsExA (USER32.@)
 */
BOOL WINAPI EnumDisplaySettingsExA(LPCSTR lpszDeviceName, DWORD iModeNum,
                                   LPDEVMODEA lpDevMode, DWORD dwFlags)
{
    DEVMODEW devmodeW;
    BOOL ret;
    UNICODE_STRING nameW;

    if (lpszDeviceName) RtlCreateUnicodeStringFromAsciiz(&nameW, lpszDeviceName);
    else nameW.Buffer = NULL;

    ret = EnumDisplaySettingsExW(nameW.Buffer,iModeNum,&devmodeW,dwFlags);
    if (ret)
    {
3265
        lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod);
3266 3267 3268 3269 3270
        lpDevMode->dmSpecVersion = devmodeW.dmSpecVersion;
        lpDevMode->dmDriverVersion = devmodeW.dmDriverVersion;
        WideCharToMultiByte(CP_ACP, 0, devmodeW.dmDeviceName, -1,
                            (LPSTR)lpDevMode->dmDeviceName, CCHDEVICENAME, NULL, NULL);
        lpDevMode->dmDriverExtra      = 0; /* FIXME */
3271 3272 3273
        lpDevMode->dmBitsPerPel       = devmodeW.dmBitsPerPel;
        lpDevMode->dmPelsHeight       = devmodeW.dmPelsHeight;
        lpDevMode->dmPelsWidth        = devmodeW.dmPelsWidth;
3274
        lpDevMode->u2.dmDisplayFlags  = devmodeW.u2.dmDisplayFlags;
3275 3276
        lpDevMode->dmDisplayFrequency = devmodeW.dmDisplayFrequency;
        lpDevMode->dmFields           = devmodeW.dmFields;
3277

3278 3279 3280 3281
        lpDevMode->u1.s2.dmPosition.x = devmodeW.u1.s2.dmPosition.x;
        lpDevMode->u1.s2.dmPosition.y = devmodeW.u1.s2.dmPosition.y;
        lpDevMode->u1.s2.dmDisplayOrientation = devmodeW.u1.s2.dmDisplayOrientation;
        lpDevMode->u1.s2.dmDisplayFixedOutput = devmodeW.u1.s2.dmDisplayFixedOutput;
3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293
    }
    if (lpszDeviceName) RtlFreeUnicodeString(&nameW);
    return ret;
}


/***********************************************************************
 *		EnumDisplaySettingsExW (USER32.@)
 */
BOOL WINAPI EnumDisplaySettingsExW(LPCWSTR lpszDeviceName, DWORD iModeNum,
                                   LPDEVMODEW lpDevMode, DWORD dwFlags)
{
3294 3295 3296
    /* make sure the desktop window is created before mode enumeration */
    GetDesktopWindow();

3297
    return USER_Driver->pEnumDisplaySettingsEx(lpszDeviceName, iModeNum, lpDevMode, dwFlags);
3298
}
3299 3300 3301 3302 3303 3304 3305 3306 3307 3308

/***********************************************************************
 *              SetProcessDPIAware   (USER32.@)
 */
BOOL WINAPI SetProcessDPIAware( VOID )
{
    FIXME( "stub!\n");

    return TRUE;
}