Implemented SPI_ICONHORIZONTALSPACING, SPI_ICONVERTICALSPACING system
[wine] / windows / sysparams.c
1 /*
2  * System parameters functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "windef.h"
13 #include "winbase.h"
14 #include "winnls.h"
15 #include "wingdi.h"
16 #include "winreg.h"
17 #include "wine/winuser16.h"
18 #include "winerror.h"
19
20 #include "controls.h"
21 #include "user.h"
22 #include "debugtools.h"
23 #include "sysmetrics.h"
24
25 DEFAULT_DEBUG_CHANNEL(system);
26
27 /* System parameter indexes */
28 #define SPI_SETBEEP_IDX                         0
29 #define SPI_SETBORDER_IDX                       1
30 #define SPI_ICONHORIZONTALSPACING_IDX           2
31 #define SPI_ICONVERTICALSPACING_IDX             3
32 #define SPI_SETSHOWSOUNDS_IDX                   4
33 #define SPI_WINE_IDX                            SPI_SETSHOWSOUNDS_IDX
34
35 /**
36  * Names of the registry subkeys of HKEY_CURRENT_USER key and value names
37  * for the system parameters.
38  * Names of the keys are created by adding string "_REGKEY" to
39  * "SET" action names, value names are created by adding "_REG_NAME"
40  * to the "SET" action name.
41  */
42 #define SPI_SETBEEP_REGKEY           "Control Panel\\Sound"
43 #define SPI_SETBEEP_VALNAME          "Beep"
44 #define SPI_SETBORDER_REGKEY         "Control Panel\\Desktop"
45 #define SPI_SETBORDER_VALNAME        "BorderWidth"
46 #define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop"
47 #define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
48 #define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop"
49 #define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
50 #define SPI_SETSHOWSOUNDS_REGKEY     "Control Panel\\Accessibility\\ShowSounds"
51 #define SPI_SETSHOWSOUNDS_VALNAME    "On"
52
53 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
54 #define WINE_CURRENT_USER_REGKEY     "Wine"
55
56 /* Indicators whether system parameter value is loaded */
57 static char spi_loaded[SPI_WINE_IDX + 1];
58
59 static BOOL notify_change = TRUE;
60
61 /* System parameters storage */
62 static BOOL beep_active = TRUE;
63 static int border = 1;
64
65
66 /***********************************************************************
67  *              GetTimerResolution (USER.14)
68  */
69 LONG WINAPI GetTimerResolution16(void)
70 {
71         return (1000);
72 }
73
74 /***********************************************************************
75  *              ControlPanelInfo (USER.273)
76  */
77 void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer )
78 {
79         FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer);
80 }
81
82 /* This function is a copy of the one in objects/font.c */
83 static void SYSPARAMS_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
84 {
85     font16->lfHeight = font32->lfHeight;
86     font16->lfWidth = font32->lfWidth;
87     font16->lfEscapement = font32->lfEscapement;
88     font16->lfOrientation = font32->lfOrientation;
89     font16->lfWeight = font32->lfWeight;
90     font16->lfItalic = font32->lfItalic;
91     font16->lfUnderline = font32->lfUnderline;
92     font16->lfStrikeOut = font32->lfStrikeOut;
93     font16->lfCharSet = font32->lfCharSet;
94     font16->lfOutPrecision = font32->lfOutPrecision;
95     font16->lfClipPrecision = font32->lfClipPrecision;
96     font16->lfQuality = font32->lfQuality;
97     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
98     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
99 }
100
101 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA* font32A, LPLOGFONTW font32W )
102 {
103     font32W->lfHeight = font32A->lfHeight;
104     font32W->lfWidth = font32A->lfWidth;
105     font32W->lfEscapement = font32A->lfEscapement;
106     font32W->lfOrientation = font32A->lfOrientation;
107     font32W->lfWeight = font32A->lfWeight;
108     font32W->lfItalic = font32A->lfItalic;
109     font32W->lfUnderline = font32A->lfUnderline;
110     font32W->lfStrikeOut = font32A->lfStrikeOut;
111     font32W->lfCharSet = font32A->lfCharSet;
112     font32W->lfOutPrecision = font32A->lfOutPrecision;
113     font32W->lfClipPrecision = font32A->lfClipPrecision;
114     font32W->lfQuality = font32A->lfQuality;
115     font32W->lfPitchAndFamily = font32A->lfPitchAndFamily;
116     MultiByteToWideChar( CP_ACP, 0, font32A->lfFaceName, -1, font32W->lfFaceName, LF_FACESIZE );
117     font32W->lfFaceName[LF_FACESIZE-1] = 0;
118 }
119
120 static void SYSPARAMS_NonClientMetrics32ATo16( const NONCLIENTMETRICSA* lpnm32, LPNONCLIENTMETRICS16 lpnm16 )
121 {
122     lpnm16->iBorderWidth        = lpnm32->iBorderWidth;
123     lpnm16->iScrollWidth        = lpnm32->iScrollWidth;
124     lpnm16->iScrollHeight       = lpnm32->iScrollHeight;
125     lpnm16->iCaptionWidth       = lpnm32->iCaptionWidth;
126     lpnm16->iCaptionHeight      = lpnm32->iCaptionHeight;
127     SYSPARAMS_LogFont32ATo16( &lpnm32->lfCaptionFont,   &lpnm16->lfCaptionFont );
128     lpnm16->iSmCaptionWidth     = lpnm32->iSmCaptionWidth;
129     lpnm16->iSmCaptionHeight    = lpnm32->iSmCaptionHeight;
130     SYSPARAMS_LogFont32ATo16( &lpnm32->lfSmCaptionFont, &lpnm16->lfSmCaptionFont );
131     lpnm16->iMenuWidth          = lpnm32->iMenuWidth;
132     lpnm16->iMenuHeight         = lpnm32->iMenuHeight;
133     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMenuFont,      &lpnm16->lfMenuFont );
134     SYSPARAMS_LogFont32ATo16( &lpnm32->lfStatusFont,    &lpnm16->lfStatusFont );
135     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMessageFont,   &lpnm16->lfMessageFont );
136 }
137
138 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA* lpnm32A, LPNONCLIENTMETRICSW lpnm32W )
139 {
140     lpnm32W->iBorderWidth       = lpnm32A->iBorderWidth;
141     lpnm32W->iScrollWidth       = lpnm32A->iScrollWidth;
142     lpnm32W->iScrollHeight      = lpnm32A->iScrollHeight;
143     lpnm32W->iCaptionWidth      = lpnm32A->iCaptionWidth;
144     lpnm32W->iCaptionHeight     = lpnm32A->iCaptionHeight;
145     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfCaptionFont,         &lpnm32W->lfCaptionFont );
146     lpnm32W->iSmCaptionWidth    = lpnm32A->iSmCaptionWidth;
147     lpnm32W->iSmCaptionHeight   = lpnm32A->iSmCaptionHeight;
148     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfSmCaptionFont,       &lpnm32W->lfSmCaptionFont );
149     lpnm32W->iMenuWidth         = lpnm32A->iMenuWidth;
150     lpnm32W->iMenuHeight        = lpnm32A->iMenuHeight;
151     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMenuFont,            &lpnm32W->lfMenuFont );
152     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfStatusFont,          &lpnm32W->lfStatusFont );
153     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMessageFont,         &lpnm32W->lfMessageFont );
154 }
155
156 /***********************************************************************
157  *           SYSPARAMS_Reset
158  *
159  * Sets the system parameter which should be always loaded to
160  * current value stored in registry.
161  * Invalidates lazy loaded parameter, so it will be loaded the next time
162  * it is requested.
163  *
164  * Parameters:
165  * uiAction - system parameter to reload value for.
166  *      Note, only "SET" values can be used for this parameter.
167  *      If uiAction is 0 all system parameters are reset.
168  */
169 void SYSPARAMS_Reset( UINT uiAction )
170 {
171 #define WINE_RELOAD_SPI(x) \
172     case x: \
173         spi_loaded[x##_IDX] = FALSE; \
174         SystemParametersInfoA( x, 0, dummy_buf, 0 );\
175         if (uiAction) \
176             break
177
178 #define WINE_INVALIDATE_SPI(x) \
179     case x: \
180         spi_loaded[x##_IDX] = FALSE; \
181         break
182
183     BOOL not_all_processed = TRUE;
184     char dummy_buf[10];
185
186     /* Execution falls through all the branches for uiAction == 0 */
187     switch (uiAction)
188     {
189     case 0:
190         memset( spi_loaded, 0, sizeof(spi_loaded) );
191
192     WINE_RELOAD_SPI(SPI_SETBORDER);
193     WINE_RELOAD_SPI(SPI_ICONHORIZONTALSPACING);
194     WINE_RELOAD_SPI(SPI_ICONVERTICALSPACING);
195     WINE_RELOAD_SPI(SPI_SETSHOWSOUNDS);
196
197     default:
198         if (uiAction)
199         {
200             /* lazy loaded parameters */
201             switch (uiAction)
202             {
203             WINE_INVALIDATE_SPI(SPI_SETBEEP);
204             default:
205                 FIXME( "Unknown action reset: %u\n", uiAction );
206                 break;
207             }
208         }
209         else
210             not_all_processed = FALSE;
211         break;
212     }
213
214     if (!uiAction && not_all_processed)
215         ERR( "Incorrect implementation of SYSPARAMS_Reset. "
216              "Not all params are reloaded.\n" );
217 #undef WINE_INVALIDATE_SPI
218 #undef WINE_RELOAD_SPI
219 }
220
221 /***********************************************************************
222  *           get_volatile_regkey
223  *
224  * Return a handle to the volatile registry key used to store
225  * non-permanently modified parameters.
226  */
227 static HKEY get_volatile_regkey(void)
228 {
229     static HKEY volatile_key;
230
231     if (!volatile_key)
232     {
233         /* FIXME - check whether the key exists
234           notify_change = FALSE;
235           if (WINE_CURRENT_USER_REGKEY does not exist)
236           {
237             initialize system parameters info which take values from X settings,
238             if(current settings differ from X)
239               change current setting and save it;
240           }
241           notify_change = TRUE;
242         */
243
244         if (RegCreateKeyExA( HKEY_CURRENT_USER, WINE_CURRENT_USER_REGKEY,
245                              0, 0, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 0,
246                              &volatile_key, 0 ) != ERROR_SUCCESS)
247             ERR("Can't create wine configuration registry branch");
248     }
249     return volatile_key;
250 }
251
252 /***********************************************************************
253  *           SYSPARAMS_NotifyChange
254  *
255  * Sends notification about system parameter update.
256  */
257 void SYSPARAMS_NotifyChange( UINT uiAction, UINT fWinIni )
258 {
259     if (notify_change)
260     {
261         if (fWinIni & SPIF_UPDATEINIFILE)
262         {
263             if (fWinIni & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE))
264                 SendMessageA(HWND_BROADCAST, WM_SETTINGCHANGE,
265                              uiAction, (LPARAM) "");
266         }
267         else 
268         {
269             /* FIXME notify other wine processes with internal message */
270         }
271     }
272 }
273
274
275 /***********************************************************************
276  * Loads system parameter from user profile.
277  */
278 BOOL SYSPARAMS_Load( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpBuf )
279 {
280     BOOL ret = FALSE;
281     DWORD type;
282     HKEY hKey;
283     DWORD count;
284
285     if ((RegOpenKeyA( get_volatile_regkey(), lpRegKey,
286                      &hKey ) == ERROR_SUCCESS) ||
287         (RegOpenKeyA( HKEY_CURRENT_USER, lpRegKey,
288                       &hKey ) == ERROR_SUCCESS))
289     {
290         ret = !RegQueryValueExA( hKey, lpValName, NULL, &type, lpBuf, &count );
291         RegCloseKey( hKey );
292     }
293     return ret;
294 }
295
296 /***********************************************************************
297  * Saves system parameter to user profile.
298  */
299 BOOL SYSPARAMS_Save( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpValue,
300                      UINT fWinIni )
301 {
302     HKEY hKey;
303     HKEY hBaseKey;
304     DWORD dwOptions;
305     BOOL ret = FALSE;
306
307     if (fWinIni & SPIF_UPDATEINIFILE)
308     {
309         hBaseKey = HKEY_CURRENT_USER;
310         dwOptions = 0;
311     }
312     else
313     {
314         hBaseKey = get_volatile_regkey();
315         dwOptions = REG_OPTION_VOLATILE;
316     }
317
318     if (RegCreateKeyExA( hBaseKey, lpRegKey,
319                          0, 0, dwOptions, KEY_ALL_ACCESS,
320                          0, &hKey, 0 ) == ERROR_SUCCESS)
321     {
322         if (RegSetValueExA( hKey, lpValName, 0, REG_SZ,
323                             lpValue, strlen(lpValue) + 1 ) == ERROR_SUCCESS)
324         {
325             ret = TRUE;
326             if (hBaseKey == HKEY_CURRENT_USER)
327                 RegDeleteKeyA( get_volatile_regkey(), lpRegKey );
328         }
329         RegCloseKey( hKey );
330     }
331     return ret;
332 }
333
334 /***********************************************************************
335  *              SystemParametersInfoA (USER32.@)
336  *
337  * Each system parameter has flag which shows whether the parameter
338  * is loaded or not. Parameters, stored directly in SysParametersInfo are
339  * loaded from registry only when they are requested and the flag is
340  * "false", after the loading the flag is set to "true". On interprocess
341  * notification of the parameter change the corresponding parameter flag is
342  * set to "false". The parameter value will be reloaded when it is requested
343  * the next time.
344  * Parameters, backed by or depend on GetSystemMetrics are processed
345  * differently. These parameters are always loaded. They are reloaded right
346  * away on interprocess change notification. We can't do lazy loading because
347  * we don't want to complicate GetSystemMetrics.
348  * When parameter value is updated the changed value is stored in permanent
349  * registry branch if saving is requested. Otherwise it is stored
350  * in temporary branch
351  *
352  */
353 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
354                                    PVOID pvParam, UINT fWinIni )
355 {
356 #define WINE_SPI_FIXME(x) \
357     case x: \
358         FIXME( "Unimplemented action: %u (%s)\n", x, #x ); \
359         SetLastError( ERROR_INVALID_SPI_VALUE ); \
360         ret = FALSE; \
361         break
362 #define WINE_SPI_WARN(x) \
363     case x: \
364         WARN( "Ignored action: %u (%s)\n", x, #x ); \
365         break
366
367     BOOL ret = TRUE;
368     unsigned spi_idx = 0;
369     
370     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fWinIni);
371     
372     switch (uiAction)
373     {
374     case SPI_GETBEEP:                           /*      1 */
375         spi_idx = SPI_SETBEEP_IDX;
376         if (!spi_loaded[spi_idx])
377         {
378             char buf[5];
379             
380             if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf ))
381                 beep_active  = !strcasecmp( "Yes", buf );
382             spi_loaded[spi_idx] = TRUE;
383         }
384         
385         *(BOOL *)pvParam = beep_active;
386         break;
387     case SPI_SETBEEP:                           /*      2 */
388         spi_idx = SPI_SETBEEP_IDX;
389         if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
390                             (uiParam ? "Yes" : "No"), fWinIni ))
391         {
392             beep_active = uiParam;
393             spi_loaded[spi_idx] = TRUE;
394         }
395         else
396             ret = FALSE;
397         break;
398
399     WINE_SPI_FIXME(SPI_GETMOUSE);               /*      3 */
400     WINE_SPI_FIXME(SPI_SETMOUSE);               /*      4 */
401
402     case SPI_GETBORDER:                         /*      5 */
403         spi_idx = SPI_SETBORDER_IDX;
404         if (!spi_loaded[spi_idx])
405         {
406             char buf[10];
407
408             if (SYSPARAMS_Load( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
409                                 buf ))
410             {
411                 int i = atoi( buf );
412                 if (i > 0) border = i;
413             }
414             spi_loaded[spi_idx] = TRUE;
415             if (TWEAK_WineLook > WIN31_LOOK)
416             {
417                 SYSMETRICS_Set( SM_CXFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
418                 SYSMETRICS_Set( SM_CYFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
419             }
420         }
421         *(INT *)pvParam = border;
422         break;
423
424     case SPI_SETBORDER:                         /*      6 */
425     {
426         char buf[10];
427
428         spi_idx = SPI_SETBORDER_IDX;
429         sprintf(buf, "%u", uiParam);
430
431         if (SYSPARAMS_Save( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
432                             buf, fWinIni ))
433         {
434             if (uiParam > 0) 
435             {
436                 border = uiParam;
437                 spi_loaded[spi_idx] = TRUE;
438                 if (TWEAK_WineLook > WIN31_LOOK)
439                 {
440                     SYSMETRICS_Set( SM_CXFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
441                     SYSMETRICS_Set( SM_CYFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
442                 }
443             }
444         }
445         else
446             ret = FALSE;
447         break;
448     }
449
450     case SPI_GETKEYBOARDSPEED:                  /*     10 */
451         *(DWORD *)pvParam = GetProfileIntA( "keyboard", "KeyboardSpeed", 30 );
452         break;
453     WINE_SPI_WARN(SPI_SETKEYBOARDSPEED);        /*     11 */
454
455     WINE_SPI_WARN(SPI_LANGDRIVER);              /*     12 */
456
457     case SPI_ICONHORIZONTALSPACING:             /*     13 */
458         spi_idx = SPI_ICONHORIZONTALSPACING_IDX;
459         if (pvParam != NULL)
460         {
461             if (!spi_loaded[spi_idx])
462             {
463                 char buf[10];
464             
465                 if (SYSPARAMS_Load( SPI_ICONHORIZONTALSPACING_REGKEY,
466                                     SPI_ICONHORIZONTALSPACING_VALNAME, buf ))
467                 {
468                     SYSMETRICS_Set( SM_CXICONSPACING, atoi( buf ) );
469                 }
470                 spi_loaded[spi_idx] = TRUE;
471             }
472
473             *(INT *)pvParam = GetSystemMetrics( SM_CXICONSPACING );
474         }
475         else
476         {
477             char buf[10];
478
479             if (uiParam < 32) uiParam = 32;
480
481             sprintf(buf, "%u", uiParam);
482             if (SYSPARAMS_Save( SPI_ICONHORIZONTALSPACING_REGKEY,
483                                 SPI_ICONHORIZONTALSPACING_VALNAME,
484                                 buf, fWinIni ))
485             {
486                 SYSMETRICS_Set( SM_CXICONSPACING, uiParam );
487                 spi_loaded[spi_idx] = TRUE;
488             }
489             else
490                 ret = FALSE;
491         }
492         
493         break;
494
495     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
496     {
497         int     timeout;
498         timeout = USER_Driver.pGetScreenSaveTimeout();
499         if (!timeout)
500             timeout = GetProfileIntA( "windows", "ScreenSaveTimeout", 300 );
501         *(INT *)pvParam = timeout;
502         break;
503     }
504     case SPI_SETSCREENSAVETIMEOUT:              /*     15 */
505         USER_Driver.pSetScreenSaveTimeout( uiParam );
506         break;
507         
508     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
509         if (USER_Driver.pGetScreenSaveActive() ||
510             GetProfileIntA( "windows", "ScreenSaveActive", 1 ) == 1)
511             *(BOOL *)pvParam = TRUE;
512         else
513             *(BOOL *)pvParam = FALSE;
514         break;
515     case SPI_SETSCREENSAVEACTIVE:               /*     17 */
516         USER_Driver.pSetScreenSaveActive( uiParam );
517         break;
518         
519     case SPI_GETGRIDGRANULARITY:                /*     18 */
520         *(INT *)pvParam = GetProfileIntA( "desktop", "GridGranularity", 1 );
521         break;
522     WINE_SPI_FIXME(SPI_SETGRIDGRANULARITY);     /*     19 */
523
524     case SPI_SETDESKWALLPAPER:                  /*     20 */
525         ret = SetDeskWallPaper( (LPSTR)pvParam );
526         break;
527     case SPI_SETDESKPATTERN:                    /*     21 */
528         /* FIXME: the ability to specify a pattern in pvParam
529            doesn't seem to be documented for Win32 */
530         if ((INT16)uiParam == -1)
531         {
532             char buffer[256];
533             GetProfileStringA( "Desktop", "Pattern", 
534                                "170 85 170 85 170 85 170 85", 
535                                buffer, sizeof(buffer) );
536             ret = DESKTOP_SetPattern( (LPSTR)buffer );
537         } else
538             ret = DESKTOP_SetPattern( (LPSTR)pvParam );
539         break;
540
541     case SPI_GETKEYBOARDDELAY:                  /*     22 */
542         *(INT *)pvParam = GetProfileIntA( "keyboard", "KeyboardDelay", 1 );
543         break;
544     WINE_SPI_WARN(SPI_SETKEYBOARDDELAY);        /*     23 */
545
546     case SPI_ICONVERTICALSPACING:               /*     24 */
547         spi_idx = SPI_ICONVERTICALSPACING_IDX;
548         if (pvParam != NULL)
549         {
550             if (!spi_loaded[spi_idx])
551             {
552                 char buf[10];
553             
554                 if (SYSPARAMS_Load( SPI_ICONVERTICALSPACING_REGKEY,
555                                     SPI_ICONVERTICALSPACING_VALNAME, buf ))
556                 {
557                     SYSMETRICS_Set( SM_CYICONSPACING, atoi( buf ) );
558                 }
559                 spi_loaded[spi_idx] = TRUE;
560             }
561
562             *(INT *)pvParam = GetSystemMetrics( SM_CYICONSPACING );
563         }
564         else
565         {
566             char buf[10];
567
568             if (uiParam < 32) uiParam = 32;
569
570             sprintf(buf, "%u", uiParam);
571             if (SYSPARAMS_Save( SPI_ICONVERTICALSPACING_REGKEY,
572                                 SPI_ICONVERTICALSPACING_VALNAME,
573                                 buf, fWinIni ))
574             {
575                 SYSMETRICS_Set( SM_CYICONSPACING, uiParam );
576                 spi_loaded[spi_idx] = TRUE;
577             }
578             else
579                 ret = FALSE;
580         }
581         
582         break;
583
584     case SPI_GETICONTITLEWRAP:                  /*     25 */
585         *(BOOL *)pvParam = GetProfileIntA( "desktop", "IconTitleWrap", TRUE );
586         break;
587     WINE_SPI_FIXME(SPI_SETICONTITLEWRAP);       /*     26 */
588
589     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
590         *(BOOL *)pvParam = GetSystemMetrics( SM_MENUDROPALIGNMENT ); /* XXX check this */
591         break;
592     WINE_SPI_FIXME(SPI_SETMENUDROPALIGNMENT);   /*     28 */
593
594     WINE_SPI_WARN(SPI_SETDOUBLECLKWIDTH);       /*     29 */
595     WINE_SPI_WARN(SPI_SETDOUBLECLKHEIGHT);      /*     30 */
596
597     case SPI_GETICONTITLELOGFONT:               /*     31 */
598     {
599         LPLOGFONTA lpLogFont = (LPLOGFONTA)pvParam;
600
601         /* from now on we always have an alias for MS Sans Serif */
602
603         GetProfileStringA( "Desktop", "IconTitleFaceName", "MS Sans Serif", 
604                            lpLogFont->lfFaceName, LF_FACESIZE );
605         lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "IconTitleSize", 13 );
606         lpLogFont->lfWidth = 0;
607         lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
608         lpLogFont->lfWeight = FW_NORMAL;
609         lpLogFont->lfItalic = FALSE;
610         lpLogFont->lfStrikeOut = FALSE;
611         lpLogFont->lfUnderline = FALSE;
612         lpLogFont->lfCharSet = ANSI_CHARSET;
613         lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
614         lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
615         lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
616         break;
617     }
618
619     WINE_SPI_WARN(SPI_SETDOUBLECLICKTIME);      /*     32 */
620     
621     WINE_SPI_FIXME(SPI_SETMOUSEBUTTONSWAP);     /*     33 */
622     WINE_SPI_FIXME(SPI_SETICONTITLELOGFONT);    /*     34 */
623
624     case SPI_GETFASTTASKSWITCH:                 /*     35 */
625         if (GetProfileIntA( "windows", "CoolSwitch", 1 ) == 1)
626             *(BOOL *)pvParam = TRUE;
627         else
628             *(BOOL *)pvParam = FALSE;
629         break;
630     WINE_SPI_WARN(SPI_SETFASTTASKSWITCH);       /*     36 */
631
632     WINE_SPI_WARN(SPI_SETDRAGFULLWINDOWS);      /*     37  WINVER >= 0x0400 */
633     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
634     {
635         HKEY hKey;
636         char buffer[20];
637         DWORD dwBufferSize = sizeof(buffer);
638
639         *(BOOL *)pvParam = FALSE;
640         if (RegOpenKeyExA( HKEY_CURRENT_USER,
641                            "Control Panel\\desktop",
642                            0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS)
643         {
644             if (RegQueryValueExA( hKey, "DragFullWindows", NULL,
645                                   0, buffer, &dwBufferSize ) == ERROR_SUCCESS)
646                 *(BOOL *)pvParam = atoi( buffer ) != 0;
647             
648             RegCloseKey( hKey );
649         }
650         break;
651     }
652
653     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
654     {
655         LPNONCLIENTMETRICSA lpnm = (LPNONCLIENTMETRICSA)pvParam;
656                 
657         if (lpnm->cbSize == sizeof(NONCLIENTMETRICSA))
658         {
659             LPLOGFONTA lpLogFont = &(lpnm->lfMenuFont);
660             
661             /* clear the struct, so we have 'sane' members */
662             memset(
663                 (char *)pvParam + sizeof(lpnm->cbSize),
664                 0,
665                 lpnm->cbSize - sizeof(lpnm->cbSize)
666                 );
667
668             /* FIXME: initialize geometry entries */
669             /* FIXME: As these values are presumably in device units,
670              *  we should calculate the defaults based on the screen dpi
671              */
672             /* caption */
673             lpnm->iCaptionWidth = ((TWEAK_WineLook > WIN31_LOOK)  ? 32 : 20);
674             lpnm->iCaptionHeight = lpnm->iCaptionWidth;
675             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfCaptionFont), 0 );
676             lpnm->lfCaptionFont.lfWeight = FW_BOLD;
677
678             /* small caption */
679             lpnm->iSmCaptionWidth = ((TWEAK_WineLook > WIN31_LOOK)  ? 32 : 17);
680             lpnm->iSmCaptionHeight = lpnm->iSmCaptionWidth;
681             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfSmCaptionFont), 0 );
682
683             /* menus, FIXME: names of wine.conf entries are bogus */
684
685             lpnm->iMenuWidth = GetProfileIntA( "Desktop", "MenuWidth", 13 );    /* size of the menu buttons*/
686             lpnm->iMenuHeight = GetProfileIntA( "Desktop", "MenuHeight", 
687                                                 (TWEAK_WineLook > WIN31_LOOK) ? 13 : 27 );
688
689             GetProfileStringA( "Desktop", "MenuFont", 
690                                (TWEAK_WineLook > WIN31_LOOK) ? "MS Sans Serif": "System", 
691                                lpLogFont->lfFaceName, LF_FACESIZE );
692
693             lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "MenuFontSize", 13 );
694             lpLogFont->lfWidth = 0;
695             lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
696             lpLogFont->lfWeight = (TWEAK_WineLook > WIN31_LOOK) ? FW_NORMAL : FW_BOLD;
697             lpLogFont->lfItalic = FALSE;
698             lpLogFont->lfStrikeOut = FALSE;
699             lpLogFont->lfUnderline = FALSE;
700             lpLogFont->lfCharSet = ANSI_CHARSET;
701             lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
702             lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
703             lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
704
705             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
706                                    (LPVOID)&(lpnm->lfStatusFont), 0 );
707             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
708                                    (LPVOID)&(lpnm->lfMessageFont), 0 );
709         }
710         else
711         {
712             WARN("size mismatch !! (is %d; should be %d)\n", lpnm->cbSize, sizeof(NONCLIENTMETRICSA));
713             /* FIXME: SetLastError? */
714             ret = FALSE;
715         }
716         break;
717     }
718     WINE_SPI_FIXME(SPI_SETNONCLIENTMETRICS);    /*     42  WINVER >= 0x400 */
719
720     WINE_SPI_FIXME(SPI_GETMINIMIZEDMETRICS);    /*     43  WINVER >= 0x400 */
721     WINE_SPI_FIXME(SPI_SETMINIMIZEDMETRICS);    /*     44  WINVER >= 0x400 */
722
723     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
724     {
725         LPICONMETRICSA lpIcon = pvParam;
726         if(lpIcon && lpIcon->cbSize == sizeof(*lpIcon))
727         {
728             SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0,
729                                    &lpIcon->iHorzSpacing, FALSE );
730             SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0,
731                                    &lpIcon->iVertSpacing, FALSE );
732             SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0,
733                                    &lpIcon->iTitleWrap, FALSE );
734             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
735                                    &lpIcon->lfFont, FALSE );
736         }
737         else
738         {
739             ret = FALSE;
740         }
741         break;
742     }
743     WINE_SPI_FIXME(SPI_SETICONMETRICS);         /*     46  WINVER >= 0x400 */
744
745     WINE_SPI_FIXME(SPI_SETWORKAREA);            /*     47  WINVER >= 0x400 */
746     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
747         SetRect( (RECT *)pvParam, 0, 0,
748                  GetSystemMetrics( SM_CXSCREEN ),
749                  GetSystemMetrics( SM_CYSCREEN ) );
750         break;
751     
752     WINE_SPI_FIXME(SPI_SETPENWINDOWS);          /*     49  WINVER >= 0x400 */
753
754     WINE_SPI_FIXME(SPI_GETFILTERKEYS);          /*     50 */
755     WINE_SPI_FIXME(SPI_SETFILTERKEYS);          /*     51 */
756     WINE_SPI_FIXME(SPI_GETTOGGLEKEYS);          /*     52 */
757     WINE_SPI_FIXME(SPI_SETTOGGLEKEYS);          /*     53 */
758     WINE_SPI_FIXME(SPI_GETMOUSEKEYS);           /*     54 */
759     WINE_SPI_FIXME(SPI_SETMOUSEKEYS);           /*     55 */
760     case SPI_GETSHOWSOUNDS:                     /*     56 */
761         spi_idx = SPI_SETSHOWSOUNDS_IDX;
762
763         if (!spi_loaded[spi_idx])
764         {
765             char buf[10];
766             
767             if (SYSPARAMS_Load( SPI_SETSHOWSOUNDS_REGKEY,
768                                 SPI_SETSHOWSOUNDS_VALNAME, buf ))
769             {
770                 SYSMETRICS_Set( SM_SHOWSOUNDS, atoi( buf ) );
771             }
772             spi_loaded[spi_idx] = TRUE;
773         }
774         
775
776         *(INT *)pvParam = GetSystemMetrics( SM_SHOWSOUNDS );
777         break;
778
779     case SPI_SETSHOWSOUNDS:                     /*     57 */
780     {
781         char buf[10];
782         spi_idx = SPI_SETSHOWSOUNDS_IDX;
783
784         sprintf(buf, "%u", uiParam);
785         if (SYSPARAMS_Save( SPI_SETSHOWSOUNDS_REGKEY,
786                             SPI_SETSHOWSOUNDS_VALNAME,
787                             buf, fWinIni ))
788         {
789             SYSMETRICS_Set( SM_SHOWSOUNDS, uiParam );
790             spi_loaded[spi_idx] = TRUE;
791         }
792         else
793             ret = FALSE;
794         break;
795     }
796     WINE_SPI_FIXME(SPI_GETSTICKYKEYS);          /*     58 */
797     WINE_SPI_FIXME(SPI_SETSTICKYKEYS);          /*     59 */
798     WINE_SPI_FIXME(SPI_GETACCESSTIMEOUT);       /*     60 */
799     WINE_SPI_FIXME(SPI_SETACCESSTIMEOUT);       /*     61 */
800
801     WINE_SPI_FIXME(SPI_GETSERIALKEYS);          /*     62  WINVER >= 0x400 */
802     WINE_SPI_FIXME(SPI_SETSERIALKEYS);          /*     63  WINVER >= 0x400 */
803
804     WINE_SPI_FIXME(SPI_GETSOUNDSENTRY);         /*     64 */
805     WINE_SPI_FIXME(SPI_SETSOUNDSENTRY);         /*     65 */
806     
807     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
808     {
809         LPHIGHCONTRASTA lpHighContrastA = (LPHIGHCONTRASTA)pvParam;
810         WARN("SPI_GETHIGHCONTRAST not fully implemented\n");
811         if (lpHighContrastA->cbSize == sizeof(HIGHCONTRASTA))
812         {
813             /* Indicate that there is no high contrast available */
814             lpHighContrastA->dwFlags = 0;
815             lpHighContrastA->lpszDefaultScheme = NULL;
816         }
817         else
818         {
819             ret = FALSE;
820         }
821         break;
822     }
823     WINE_SPI_FIXME(SPI_SETHIGHCONTRAST);        /*     67  WINVER >= 0x400 */
824
825     WINE_SPI_FIXME(SPI_GETKEYBOARDPREF);        /*     68  WINVER >= 0x400 */
826     WINE_SPI_FIXME(SPI_SETKEYBOARDPREF);        /*     69  WINVER >= 0x400 */
827
828     case SPI_GETSCREENREADER:
829     {
830        LPBOOL   bool = (LPBOOL)pvParam;
831        *bool = FALSE;
832        break;
833     }
834
835     WINE_SPI_FIXME(SPI_SETSCREENREADER);        /*     71  WINVER >= 0x400 */
836
837     case SPI_GETANIMATION:                      /*     72  WINVER >= 0x400 */
838     {
839         LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)pvParam;
840  
841         /* Tell it "disabled" */
842         if (lpAnimInfo->cbSize == sizeof(ANIMATIONINFO))
843             lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
844         else
845             ret = FALSE;
846         break;
847     }
848     WINE_SPI_WARN(SPI_SETANIMATION);            /*     73  WINVER >= 0x400 */
849
850     WINE_SPI_FIXME(SPI_GETFONTSMOOTHING);       /*     74  WINVER >= 0x400 */
851     WINE_SPI_FIXME(SPI_SETFONTSMOOTHING);       /*     75  WINVER >= 0x400 */
852
853     WINE_SPI_FIXME(SPI_SETDRAGWIDTH);           /*     76  WINVER >= 0x400 */
854     WINE_SPI_FIXME(SPI_SETDRAGHEIGHT);          /*     77  WINVER >= 0x400 */
855
856     WINE_SPI_FIXME(SPI_SETHANDHELD);            /*     78  WINVER >= 0x400 */
857
858     WINE_SPI_FIXME(SPI_GETLOWPOWERTIMEOUT);     /*     79  WINVER >= 0x400 */
859     WINE_SPI_FIXME(SPI_GETPOWEROFFTIMEOUT);     /*     80  WINVER >= 0x400 */
860     WINE_SPI_FIXME(SPI_SETLOWPOWERTIMEOUT);     /*     81  WINVER >= 0x400 */
861     WINE_SPI_FIXME(SPI_SETPOWEROFFTIMEOUT);     /*     82  WINVER >= 0x400 */
862     WINE_SPI_FIXME(SPI_GETLOWPOWERACTIVE);      /*     83  WINVER >= 0x400 */
863     WINE_SPI_FIXME(SPI_GETPOWEROFFACTIVE);      /*     84  WINVER >= 0x400 */
864     WINE_SPI_FIXME(SPI_SETLOWPOWERACTIVE);      /*     85  WINVER >= 0x400 */
865     WINE_SPI_FIXME(SPI_SETPOWEROFFACTIVE);      /*     86  WINVER >= 0x400 */
866     
867     WINE_SPI_FIXME(SPI_SETCURSORS);             /*     87  WINVER >= 0x400 */
868     WINE_SPI_FIXME(SPI_SETICONS);               /*     88  WINVER >= 0x400 */
869
870     WINE_SPI_FIXME(SPI_GETDEFAULTINPUTLANG);    /*     89  WINVER >= 0x400 */
871     WINE_SPI_FIXME(SPI_SETDEFAULTINPUTLANG);    /*     90  WINVER >= 0x400 */
872
873     WINE_SPI_FIXME(SPI_SETLANGTOGGLE);          /*     91  WINVER >= 0x400 */
874
875     case SPI_GETWINDOWSEXTENSION:               /*     92  WINVER >= 0x400 */
876         WARN("pretend no support for Win9x Plus! for now.\n");
877         ret = FALSE; /* yes, this is the result value */
878         break;
879
880     WINE_SPI_FIXME(SPI_SETMOUSETRAILS);         /*     93  WINVER >= 0x400 */
881     WINE_SPI_FIXME(SPI_GETMOUSETRAILS);         /*     94  WINVER >= 0x400 */
882         
883     WINE_SPI_FIXME(SPI_SETSCREENSAVERRUNNING);  /*     97  WINVER >= 0x400 */
884     /* SPI_SCREENSAVERRUNNING is an alias for SPI_SETSCREENSAVERRUNNING */
885
886     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
887         *(UINT *)pvParam = 4;
888         break;
889     WINE_SPI_FIXME(SPI_SETMOUSEHOVERWIDTH);     /*     99  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
890
891     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
892         *(UINT *)pvParam = 4;
893         break;
894     WINE_SPI_FIXME(SPI_SETMOUSEHOVERHEIGHT);    /*    101  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
895
896     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
897         *(UINT *)pvParam = 400; /* default for menu dropdowns */
898         break;
899     WINE_SPI_FIXME(SPI_SETMOUSEHOVERTIME);      /*    103  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
900               
901     case SPI_GETWHEELSCROLLLINES:               /*    104  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
902         *(UINT *)pvParam = 3; /* default for num scroll lines */  
903         break;
904
905     WINE_SPI_FIXME(SPI_SETWHEELSCROLLLINES);    /*    105  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
906
907     case SPI_GETMENUSHOWDELAY:                  /*    106  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
908         *(UINT *)pvParam = 400; /* Tested against Windows NT 4.0 and Windows 2000 */
909         break;
910
911     WINE_SPI_FIXME(SPI_GETSHOWIMEUI);           /*    110  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
912     WINE_SPI_FIXME(SPI_SETSHOWIMEUI);           /*    111  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
913
914     default:
915         FIXME( "Unknown action: %u\n", uiAction );
916         SetLastError( ERROR_INVALID_SPI_VALUE );
917         ret = FALSE;
918         break;
919     }
920
921     if (ret)
922         SYSPARAMS_NotifyChange( uiAction, fWinIni );
923     return ret;
924     
925 #undef WINE_SPI_FIXME
926 #undef WINE_SPI_WARN
927 }
928
929
930 /***********************************************************************
931  *              SystemParametersInfo (USER.483)
932  */
933 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
934                                       LPVOID lpvParam, UINT16 fuWinIni )
935 {
936     BOOL16 ret;
937
938     TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
939     
940     switch (uAction)
941     {
942     case SPI_GETBEEP:                           /*      1 */
943     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
944     case SPI_GETICONTITLEWRAP:                  /*     25 */
945     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
946     case SPI_GETFASTTASKSWITCH:                 /*     35 */
947     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
948     {
949         BOOL tmp;
950         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
951         if (ret && lpvParam)
952             *(BOOL16 *)lpvParam = tmp;
953         break;
954     }
955
956     case SPI_GETBORDER:                         /*      5 */
957     case SPI_ICONHORIZONTALSPACING:             /*     13 */
958     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
959     case SPI_GETGRIDGRANULARITY:                /*     18 */
960     case SPI_GETKEYBOARDDELAY:                  /*     22 */
961     case SPI_ICONVERTICALSPACING:               /*     24 */
962     {
963         INT tmp;
964         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
965         if (ret && lpvParam)
966             *(INT16 *)lpvParam = tmp;
967         break;
968     }
969
970     case SPI_GETKEYBOARDSPEED:                  /*     10 */
971     {
972         DWORD tmp;
973         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
974         if (ret && lpvParam)
975             *(WORD *)lpvParam = tmp;
976         break;
977     }
978
979     case SPI_GETICONTITLELOGFONT:               /*     31 */
980     {
981         LOGFONTA tmp;
982         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
983         if (ret && lpvParam)
984             SYSPARAMS_LogFont32ATo16( &tmp, (LPLOGFONT16)lpvParam );
985         break;
986     }
987
988     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
989     {
990         NONCLIENTMETRICSA tmp;
991         LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
992         if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
993         {
994             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
995             ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
996             if (ret)
997                 SYSPARAMS_NonClientMetrics32ATo16( &tmp, lpnm16 );
998         }
999         else /* winfile 95 sets cbSize to 340 */
1000             ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1001         break;
1002     }
1003     
1004     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1005     {
1006         RECT tmp;
1007         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1008         if (ret && lpvParam)
1009             CONV_RECT32TO16( &tmp, (RECT16 *)lpvParam );
1010         break;
1011     }
1012         
1013     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1014     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1015     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1016     {
1017         UINT tmp;
1018         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1019         if (ret && lpvParam)
1020             *(UINT16 *)lpvParam = tmp;
1021         break;
1022     }
1023
1024     default:
1025         ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1026     }
1027
1028     return ret;
1029 }
1030
1031 /***********************************************************************
1032  *              SystemParametersInfoW (USER32.@)
1033  */
1034 BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam,
1035                                    PVOID pvParam, UINT fuWinIni )
1036 {
1037     BOOL ret;
1038
1039     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
1040     
1041     switch (uiAction)
1042     {
1043     case SPI_SETDESKWALLPAPER:                  /*     20 */
1044     case SPI_SETDESKPATTERN:                    /*     21 */
1045     {
1046         char buffer[256];
1047         if (pvParam)
1048             if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)pvParam, -1,
1049                                       buffer, sizeof(buffer), NULL, NULL ))
1050                 buffer[sizeof(buffer)-1] = 0;
1051         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
1052         break;
1053     }
1054
1055     case SPI_GETICONTITLELOGFONT:               /*     31 */
1056     {
1057         LOGFONTA tmp;
1058         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
1059         if (ret && pvParam)
1060             SYSPARAMS_LogFont32ATo32W( &tmp, (LPLOGFONTW)pvParam );
1061         break;
1062     }
1063
1064     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1065     {
1066         NONCLIENTMETRICSA tmp;
1067         LPNONCLIENTMETRICSW lpnmW = (LPNONCLIENTMETRICSW)pvParam;
1068         if (lpnmW && lpnmW->cbSize == sizeof(NONCLIENTMETRICSW))
1069         {
1070             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
1071             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1072             if (ret)
1073                 SYSPARAMS_NonClientMetrics32ATo32W( &tmp, lpnmW );
1074         }
1075         else
1076             ret = FALSE;
1077         break;
1078     }
1079
1080     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
1081     {
1082         ICONMETRICSA tmp;
1083         LPICONMETRICSW lpimW = (LPICONMETRICSW)pvParam;
1084         if (lpimW && lpimW->cbSize == sizeof(ICONMETRICSW))
1085         {
1086             tmp.cbSize = sizeof(ICONMETRICSA);
1087             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1088             if (ret)
1089             {
1090                 lpimW->iHorzSpacing = tmp.iHorzSpacing;
1091                 lpimW->iVertSpacing = tmp.iVertSpacing;
1092                 lpimW->iTitleWrap   = tmp.iTitleWrap;
1093                 SYSPARAMS_LogFont32ATo32W( &tmp.lfFont, &lpimW->lfFont );
1094             }
1095         }
1096         else
1097             ret = FALSE;
1098         break;
1099     }
1100
1101     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1102     {
1103         HIGHCONTRASTA tmp;
1104         LPHIGHCONTRASTW lphcW = (LPHIGHCONTRASTW)pvParam;
1105         if (lphcW && lphcW->cbSize == sizeof(HIGHCONTRASTW))
1106         {
1107             tmp.cbSize = sizeof(HIGHCONTRASTA);
1108             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1109             if (ret)
1110             {
1111                 lphcW->dwFlags = tmp.dwFlags;
1112                 lphcW->lpszDefaultScheme = NULL;  /* FIXME? */
1113             }
1114         }
1115         else
1116             ret = FALSE;
1117         break;
1118     }
1119     
1120     default:
1121         ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fuWinIni );
1122         break;
1123     }
1124     return ret;
1125 }