xref: /reactos/win32ss/user/ntuser/sysparams.c (revision 3c797b31)
1 /*
2  * COPYRIGHT:        GPL, see COPYING in the top level directory
3  * PROJECT:          ReactOS win32 kernel mode subsystem server
4  * PURPOSE:          System parameters functions
5  * FILE:             win32ss/user/ntuser/sysparams.c
6  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 // TODO:
10 // - Check all values that are in Winsta in ROS.
11 // - Does setting invalid fonts work?
12 // - Save appropriate text metrics.
13 
14 #include <win32k.h>
15 DBG_DEFAULT_CHANNEL(UserSysparams);
16 
17 SPIVALUES gspv;
18 BOOL gbSpiInitialized = FALSE;
19 BOOL g_PaintDesktopVersion = FALSE;
20 BOOL g_bWindowSnapEnabled = TRUE;
21 
22 // HACK! We initialize SPI before we have a proper surface to get this from.
23 #define dpi 96
24 //(pPrimarySurface->GDIInfo.ulLogPixelsY)
25 #define REG2METRIC(reg) (reg > 0 ? reg : ((-(reg) * dpi + 720) / 1440))
26 #define METRIC2REG(met) (-((((met) * 1440)- 0) / dpi))
27 
28 #define REQ_INTERACTIVE_WINSTA(err) \
29 do { \
30     if (GetW32ProcessInfo()->prpwinsta != InputWindowStation) \
31     { \
32         if (GetW32ProcessInfo()->prpwinsta == NULL) \
33         { \
34             ERR("NtUserSystemParametersInfo called without active window station, and it requires an interactive one\n"); \
35         } \
36         else \
37         { \
38             ERR("NtUserSystemParametersInfo requires interactive window station (current is '%wZ')\n", \
39                 &(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(GetW32ProcessInfo()->prpwinsta))->Name)); \
40         } \
41         EngSetLastError(err); \
42         return 0; \
43     } \
44 } while (0)
45 
46 static const WCHAR* KEY_MOUSE = L"Control Panel\\Mouse";
47 static const WCHAR* VAL_MOUSE1 = L"MouseThreshold1";
48 static const WCHAR* VAL_MOUSE2 = L"MouseThreshold2";
49 static const WCHAR* VAL_MOUSE3 = L"MouseSpeed";
50 static const WCHAR* VAL_MOUSETRAILS = L"MouseTrails";
51 static const WCHAR* VAL_DBLCLKWIDTH = L"DoubleClickWidth";
52 static const WCHAR* VAL_DBLCLKHEIGHT = L"DoubleClickHeight";
53 static const WCHAR* VAL_DBLCLKTIME = L"DoubleClickSpeed";
54 static const WCHAR* VAL_SNAPDEFBTN = L"SnapToDefaultButton";
55 static const WCHAR* VAL_SWAP = L"SwapMouseButtons";
56 static const WCHAR* VAL_HOVERTIME = L"MouseHoverTime";
57 static const WCHAR* VAL_HOVERWIDTH = L"MouseHoverWidth";
58 static const WCHAR* VAL_HOVERHEIGHT = L"MouseHoverHeight";
59 static const WCHAR* VAL_SENSITIVITY = L"MouseSensitivity";
60 
61 static const WCHAR* KEY_DESKTOP = L"Control Panel\\Desktop";
62 static const WCHAR* VAL_SCRTO = L"ScreenSaveTimeOut";
63 static const WCHAR* VAL_SCRNSV = L"SCRNSAVE.EXE";
64 static const WCHAR* VAL_SCRACT = L"ScreenSaveActive";
65 static const WCHAR* VAL_GRID = L"GridGranularity";
66 static const WCHAR* VAL_DRAG = L"DragFullWindows";
67 static const WCHAR* VAL_DRAGHEIGHT = L"DragHeight";
68 static const WCHAR* VAL_DRAGWIDTH = L"DragWidth";
69 static const WCHAR* VAL_FONTSMOOTHING = L"FontSmoothing";
70 static const WCHAR* VAL_FONTSMOOTHINGTYPE = L"FontSmoothingType";
71 static const WCHAR* VAL_FONTSMOOTHINGCONTRAST = L"FontSmoothingGamma";
72 static const WCHAR* VAL_FONTSMOOTHINGORIENTATION = L"FontSmoothingOrientation";
73 static const WCHAR* VAL_SCRLLLINES = L"WheelScrollLines";
74 static const WCHAR* VAL_CLICKLOCKTIME = L"ClickLockTime";
75 static const WCHAR* VAL_PAINTDESKVER = L"PaintDesktopVersion";
76 static const WCHAR* VAL_CARETRATE = L"CursorBlinkRate";
77 static const WCHAR* VAL_CARETWIDTH = L"CaretWidth";
78 #if (_WIN32_WINNT >= 0x0600)
79 static const WCHAR* VAL_SCRLLCHARS = L"WheelScrollChars";
80 #endif
81 static const WCHAR* VAL_USERPREFMASK = L"UserPreferencesMask";
82 
83 static const WCHAR* KEY_MDALIGN = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
84 static const WCHAR* VAL_MDALIGN = L"MenuDropAlignment";
85 
86 static const WCHAR* KEY_METRIC = L"Control Panel\\Desktop\\WindowMetrics";
87 static const WCHAR* VAL_BORDER = L"BorderWidth";
88 static const WCHAR* VAL_ICONSPC = L"IconSpacing";
89 static const WCHAR* VAL_ICONVSPC = L"IconVerticalspacing";
90 static const WCHAR* VAL_ITWRAP = L"IconTitleWrap";
91 
92 static const WCHAR* KEY_SOUND = L"Control Panel\\Sound";
93 static const WCHAR* VAL_BEEP = L"Beep";
94 
95 static const WCHAR* KEY_KBD = L"Control Panel\\Keyboard";
96 static const WCHAR* VAL_KBDSPD = L"KeyboardSpeed";
97 static const WCHAR* VAL_KBDDELAY = L"KeyboardDelay";
98 
99 static const WCHAR* KEY_SHOWSNDS = L"Control Panel\\Accessibility\\ShowSounds";
100 static const WCHAR* KEY_KDBPREF = L"Control Panel\\Accessibility\\Keyboard Preference";
101 static const WCHAR* KEY_SCRREAD = L"Control Panel\\Accessibility\\Blind Access";
102 static const WCHAR* VAL_ON = L"On";
103 
104 /** Loading the settings ******************************************************/
105 
106 static
107 INT
108 SpiLoadDWord(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
109 {
110     DWORD Result;
111     if (!RegReadUserSetting(pwszKey, pwszValue, REG_DWORD, &Result, sizeof(Result)))
112     {
113         return iValue;
114     }
115     return Result;
116 }
117 
118 static
119 INT
120 SpiLoadInt(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
121 {
122     WCHAR awcBuffer[12];
123     ULONG cbSize;
124 
125     cbSize = sizeof(awcBuffer);
126     if (!RegReadUserSetting(pwszKey, pwszValue, REG_SZ, awcBuffer, cbSize))
127     {
128         return iValue;
129     }
130     return _wtoi(awcBuffer);
131 }
132 
133 static
134 DWORD
135 SpiLoadUserPrefMask(DWORD dValue)
136 {
137     DWORD Result;
138     if (!RegReadUserSetting(KEY_DESKTOP, VAL_USERPREFMASK, REG_BINARY, &Result, sizeof(Result)))
139     {
140         return dValue;
141     }
142     return Result;
143 }
144 
145 static
146 DWORD
147 SpiLoadTimeOut(VOID)
148 {   // Must have the string!
149     WCHAR szApplicationName[MAX_PATH];
150     RtlZeroMemory(&szApplicationName, sizeof(szApplicationName));
151     if (!RegReadUserSetting(KEY_DESKTOP, VAL_SCRNSV, REG_SZ, &szApplicationName, sizeof(szApplicationName)))
152     {
153         return 0;
154     }
155     if (szApplicationName[0] == 0) return 0;
156     return SpiLoadInt(KEY_DESKTOP, VAL_SCRTO, 600);
157 }
158 
159 static
160 INT
161 SpiLoadMouse(PCWSTR pwszValue, INT iValue)
162 {
163     return SpiLoadInt(KEY_MOUSE, pwszValue, iValue);
164 }
165 
166 static
167 INT
168 SpiLoadMetric(PCWSTR pwszValue, INT iValue)
169 {
170     INT iRegVal;
171 
172     iRegVal = SpiLoadInt(KEY_METRIC, pwszValue, METRIC2REG(iValue));
173     TRACE("Loaded metric setting '%S', iValue=%d(reg:%d), ret=%d(reg:%d)\n",
174            pwszValue, iValue, METRIC2REG(iValue), REG2METRIC(iRegVal), iRegVal);
175     return REG2METRIC(iRegVal);
176 }
177 
178 static
179 VOID
180 SpiLoadFont(PLOGFONTW plfOut, LPWSTR pwszValueName, PLOGFONTW plfDefault)
181 {
182     BOOL bResult;
183 
184     bResult = RegReadUserSetting(KEY_METRIC,
185                                  pwszValueName,
186                                  REG_BINARY,
187                                  plfOut,
188                                  sizeof(LOGFONTW));
189     if (!bResult)
190         *plfOut = *plfDefault;
191 }
192 
193 static
194 VOID
195 SpiFixupValues(VOID)
196 {
197     /* Fixup values */
198     gspv.ncm.iCaptionWidth = max(gspv.ncm.iCaptionWidth, 8);
199     gspv.ncm.iBorderWidth = max(gspv.ncm.iBorderWidth, 1);
200     gspv.ncm.iScrollWidth = max(gspv.ncm.iScrollWidth, 8);
201     gspv.ncm.iScrollHeight = max(gspv.ncm.iScrollHeight, 8);
202 //    gspv.ncm.iMenuHeight = max(gspv.ncm.iMenuHeight, gspv.tmMenuFont.tmHeight);
203 //    gspv.ncm.iMenuHeight = max(gspv.ncm.iMenuHeight,
204 //                               2 + gspv.tmMenuFont.tmHeight +
205 //                               gspv.tmMenuFont.tmExternalLeading);
206     if (gspv.iDblClickTime == 0) gspv.iDblClickTime = 500;
207 
208     // FIXME: Hack!!!
209     gspv.tmMenuFont.tmHeight = 11;
210     gspv.tmMenuFont.tmExternalLeading = 2;
211 
212     gspv.tmCaptionFont.tmHeight = 11;
213     gspv.tmCaptionFont.tmExternalLeading = 2;
214 
215 }
216 
217 /* Is Window Snap enabled? */
218 static BOOL IntIsWindowSnapEnabled(VOID)
219 {
220     WCHAR szValue[2];
221     if (RegReadUserSetting(L"Control Panel\\Desktop", L"WindowArrangementActive",
222                            REG_SZ, szValue, sizeof(szValue)))
223     {
224         szValue[RTL_NUMBER_OF(szValue) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
225         return (_wtoi(szValue) != 0);
226     }
227     return TRUE;
228 }
229 
230 static
231 VOID
232 SpiUpdatePerUserSystemParameters(VOID)
233 {
234     static LOGFONTW lf1 = {-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
235                            FALSE, ANSI_CHARSET, 0, 0, DEFAULT_QUALITY,
236                            VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif"};
237     static LOGFONTW lf2 = {-11, 0, 0, 0, FW_BOLD, FALSE, FALSE,
238                            FALSE, ANSI_CHARSET, 0, 0, DEFAULT_QUALITY,
239                            VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif"};
240 
241     TRACE("Enter SpiUpdatePerUserSystemParameters\n");
242 
243     /* Clear the structure */
244     RtlZeroMemory(&gspv, sizeof(gspv));
245 
246     /* Load mouse settings */
247     gspv.caiMouse.FirstThreshold = SpiLoadMouse(VAL_MOUSE1, 6);
248     gspv.caiMouse.SecondThreshold = SpiLoadMouse(VAL_MOUSE2, 10);
249     gspv.caiMouse.Acceleration = SpiLoadMouse(VAL_MOUSE3, 1);
250     gspv.iMouseSpeed = SpiLoadMouse(VAL_SENSITIVITY, 10);
251     gspv.bMouseBtnSwap = SpiLoadMouse(VAL_SWAP, 0);
252     gspv.bSnapToDefBtn = SpiLoadMouse(VAL_SNAPDEFBTN, 0);
253     gspv.iMouseTrails = SpiLoadMouse(VAL_MOUSETRAILS, 0);
254     gspv.iDblClickTime = SpiLoadMouse(VAL_DBLCLKTIME, 500);
255     gspv.iDblClickWidth = SpiLoadMouse(VAL_DBLCLKWIDTH, 4);
256     gspv.iDblClickHeight = SpiLoadMouse(VAL_DBLCLKHEIGHT, 4);
257     gspv.iMouseHoverTime = SpiLoadMouse(VAL_HOVERTIME, 400);
258     gspv.iMouseHoverWidth = SpiLoadMouse(VAL_HOVERWIDTH, 4);
259     gspv.iMouseHoverHeight = SpiLoadMouse(VAL_HOVERHEIGHT, 4);
260 
261     /* Load keyboard settings */
262     gspv.dwKbdSpeed = SpiLoadInt(KEY_KBD, VAL_KBDSPD, 31);
263     gspv.iKbdDelay = SpiLoadInt(KEY_KBD, VAL_KBDDELAY, 1);
264 
265     /* Load NONCLIENTMETRICS */
266     gspv.ncm.cbSize = sizeof(NONCLIENTMETRICSW);
267     gspv.ncm.iBorderWidth = SpiLoadMetric(VAL_BORDER, 1);
268     gspv.ncm.iScrollWidth = SpiLoadMetric(L"ScrollWidth", 16);
269     gspv.ncm.iScrollHeight = SpiLoadMetric(L"ScrollHeight", 16);
270     gspv.ncm.iCaptionWidth = SpiLoadMetric(L"CaptionWidth", 19);
271     gspv.ncm.iCaptionHeight = SpiLoadMetric(L"CaptionHeight", 19);
272     gspv.ncm.iSmCaptionWidth = SpiLoadMetric(L"SmCaptionWidth", 12);
273     gspv.ncm.iSmCaptionHeight = SpiLoadMetric(L"SmCaptionHeight", 15);
274     gspv.ncm.iMenuWidth = SpiLoadMetric(L"MenuWidth", 18);
275     gspv.ncm.iMenuHeight = SpiLoadMetric(L"MenuHeight", 18);
276 #if (WINVER >= 0x0600)
277     gspv.ncm.iPaddedBorderWidth = SpiLoadMetric(L"PaddedBorderWidth", 18);
278 #endif
279     SpiLoadFont(&gspv.ncm.lfCaptionFont, L"CaptionFont", &lf2);
280     SpiLoadFont(&gspv.ncm.lfSmCaptionFont, L"SmCaptionFont", &lf1);
281     SpiLoadFont(&gspv.ncm.lfMenuFont, L"MenuFont", &lf1);
282     SpiLoadFont(&gspv.ncm.lfStatusFont, L"StatusFont", &lf1);
283     SpiLoadFont(&gspv.ncm.lfMessageFont, L"MessageFont", &lf1);
284 
285     /* Load MINIMIZEDMETRICS */
286     gspv.mm.cbSize = sizeof(MINIMIZEDMETRICS);
287     gspv.mm.iWidth = SpiLoadMetric(L"MinWidth", 160);
288     gspv.mm.iHorzGap = SpiLoadMetric(L"MinHorzGap", 160);
289     gspv.mm.iVertGap = SpiLoadMetric(L"MinVertGap", 24);
290     gspv.mm.iArrange = SpiLoadInt(KEY_METRIC, L"MinArrange", ARW_HIDE);
291 
292     /* Load ICONMETRICS */
293     gspv.im.cbSize = sizeof(ICONMETRICSW);
294     gspv.im.iHorzSpacing = SpiLoadMetric(VAL_ICONSPC, 64);
295     gspv.im.iVertSpacing = SpiLoadMetric(VAL_ICONVSPC, 64);
296     gspv.im.iTitleWrap = SpiLoadMetric(VAL_ITWRAP, 1);
297     SpiLoadFont(&gspv.im.lfFont, L"IconFont", &lf1);
298 
299     /* Load desktop settings */
300     gspv.bDragFullWindows = SpiLoadInt(KEY_DESKTOP, VAL_DRAG, 0);
301     gspv.iWheelScrollLines = SpiLoadInt(KEY_DESKTOP, VAL_SCRLLLINES, 3);
302     gspv.dwMouseClickLockTime = SpiLoadDWord(KEY_DESKTOP, VAL_CLICKLOCKTIME, 1200);
303     gpsi->dtCaretBlink = SpiLoadInt(KEY_DESKTOP, VAL_CARETRATE, 530);
304     gspv.dwCaretWidth = SpiLoadDWord(KEY_DESKTOP, VAL_CARETWIDTH, 1);
305     gspv.dwUserPrefMask = SpiLoadUserPrefMask(UPM_DEFAULT);
306     gspv.bMouseClickLock = (gspv.dwUserPrefMask & UPM_CLICKLOCK) != 0;
307     gspv.bMouseCursorShadow = (gspv.dwUserPrefMask & UPM_CURSORSHADOW) != 0;
308     gspv.bFontSmoothing = SpiLoadInt(KEY_DESKTOP, VAL_FONTSMOOTHING, 0) == 2;
309     gspv.uiFontSmoothingType = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGTYPE, 1);
310     gspv.uiFontSmoothingContrast = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGCONTRAST, 1400);
311     gspv.uiFontSmoothingOrientation = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGORIENTATION, 1);
312 #if (_WIN32_WINNT >= 0x0600)
313     gspv.uiWheelScrollChars = SpiLoadInt(KEY_DESKTOP, VAL_SCRLLCHARS, 3);
314 #endif
315 
316     /* Some hardcoded values for now */
317 
318     gspv.tmCaptionFont.tmAveCharWidth = 6;
319     gspv.bBeep = TRUE;
320     gspv.uiFocusBorderWidth = 1;
321     gspv.uiFocusBorderHeight = 1;
322     gspv.bMenuDropAlign = 0;
323     gspv.dwMenuShowDelay = SpiLoadInt(KEY_DESKTOP, L"MenuShowDelay", 400);
324     gspv.dwForegroundFlashCount = 3;
325 
326     gspv.iScrSaverTimeout = SpiLoadTimeOut();
327     gspv.bScrSaverActive = FALSE;
328     gspv.bScrSaverRunning = FALSE;
329 #if(WINVER >= 0x0600)
330     gspv.bScrSaverSecure = FALSE;
331 #endif
332 
333     gspv.bFastTaskSwitch = TRUE;
334 
335     gspv.accesstimeout.cbSize = sizeof(ACCESSTIMEOUT);
336     gspv.filterkeys.cbSize = sizeof(FILTERKEYS);
337     gspv.togglekeys.cbSize = sizeof(TOGGLEKEYS);
338     gspv.mousekeys.cbSize = sizeof(MOUSEKEYS);
339     gspv.stickykeys.cbSize = sizeof(STICKYKEYS);
340     gspv.serialkeys.cbSize = sizeof(SERIALKEYS);
341     gspv.soundsentry.cbSize = sizeof(SOUNDSENTRYW);
342     gspv.highcontrast.cbSize = sizeof(HIGHCONTRASTW);
343     gspv.animationinfo.cbSize = sizeof(ANIMATIONINFO);
344 
345     /* Make sure we don't use broken values */
346     SpiFixupValues();
347 
348     /* Update SystemMetrics */
349     InitMetrics();
350 
351     if (gbSpiInitialized && gpsi)
352     {
353        if (gspv.bKbdPref) gpsi->dwSRVIFlags |= SRVINFO_KBDPREF;
354        if (SPITESTPREF(UPM_KEYBOARDCUES)) gpsi->PUSIFlags |= PUSIF_KEYBOARDCUES;
355        if (SPITESTPREF(UPM_COMBOBOXANIMATION)) gpsi->PUSIFlags |= PUSIF_COMBOBOXANIMATION;
356        if (SPITESTPREF(UPM_LISTBOXSMOOTHSCROLLING)) gpsi->PUSIFlags |= PUSIF_LISTBOXSMOOTHSCROLLING;
357     }
358     gdwLanguageToggleKey = UserGetLanguageToggle();
359 
360     g_bWindowSnapEnabled = IntIsWindowSnapEnabled();
361 }
362 
363 BOOL
364 InitSysParams(VOID)
365 {
366     SpiUpdatePerUserSystemParameters();
367     gbSpiInitialized = TRUE;
368     return TRUE;
369 }
370 
371 
372 BOOL
373 APIENTRY
374 NtUserUpdatePerUserSystemParameters(
375     DWORD dwReserved,
376     BOOL bEnable)
377 {
378     BOOL bResult;
379 
380     TRACE("Enter NtUserUpdatePerUserSystemParameters\n");
381     UserEnterExclusive();
382 
383     SpiUpdatePerUserSystemParameters();
384     if(bEnable)
385         g_PaintDesktopVersion = SpiLoadDWord(KEY_DESKTOP, VAL_PAINTDESKVER, 0);
386     else
387         g_PaintDesktopVersion = FALSE;
388     bResult = TRUE;
389 
390     TRACE("Leave NtUserUpdatePerUserSystemParameters, returning %d\n", bResult);
391     UserLeave();
392 
393     return bResult;
394 }
395 
396 
397 /** Storing the settings ******************************************************/
398 
399 static
400 VOID
401 SpiStoreDWord(PCWSTR pwszKey, PCWSTR pwszValue, DWORD Value)
402 {
403     RegWriteUserSetting(pwszKey,
404                         pwszValue,
405                         REG_DWORD,
406                         &Value,
407                         sizeof(Value));
408 }
409 
410 static
411 VOID
412 SpiStoreSz(PCWSTR pwszKey, PCWSTR pwszValue, PCWSTR pwsz)
413 {
414     RegWriteUserSetting(pwszKey,
415                         pwszValue,
416                         REG_SZ,
417                         pwsz,
418                         (wcslen(pwsz) + 1) * sizeof(WCHAR));
419 }
420 
421 static
422 VOID
423 SpiStoreSzInt(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
424 {
425     WCHAR awcBuffer[15];
426 
427     _itow(iValue, awcBuffer, 10);
428     RegWriteUserSetting(pwszKey,
429                         pwszValue,
430                         REG_SZ,
431                         awcBuffer,
432                         (wcslen(awcBuffer) + 1) * sizeof(WCHAR));
433 }
434 
435 static
436 VOID
437 SpiStoreMetric(LPCWSTR pwszValue, INT iValue)
438 {
439     SpiStoreSzInt(KEY_METRIC, pwszValue, METRIC2REG(iValue));
440 }
441 
442 static
443 VOID
444 SpiStoreFont(PCWSTR pwszValue, LOGFONTW* plogfont)
445 {
446     RegWriteUserSetting(KEY_METRIC,
447                         pwszValue,
448                         REG_BINARY,
449                         plogfont,
450                         sizeof(LOGFONTW));
451 }
452 
453 
454 /** Get/Set value *************************************************************/
455 
456 // FIXME: get rid of the flags and only use this from um. kernel can access data directly.
457 static
458 UINT_PTR
459 SpiMemCopy(PVOID pvDst, PVOID pvSrc, ULONG cbSize, BOOL bProtect)
460 {
461     NTSTATUS Status = STATUS_SUCCESS;
462 
463     if (bProtect)
464     {
465         _SEH2_TRY
466         {
467             RtlCopyMemory(pvDst, pvSrc, cbSize);
468         }
469         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
470         {
471             Status = _SEH2_GetExceptionCode();
472         }
473         _SEH2_END;
474     }
475     else
476     {
477         RtlCopyMemory(pvDst, pvSrc, cbSize);
478     }
479 
480     if (!NT_SUCCESS(Status))
481     {
482         SetLastNtError(Status);
483         ERR("SpiMemCopy failed, pvDst=%p, pvSrc=%p, bProtect=%d\n", pvDst, pvSrc, bProtect);
484     }
485 
486     return NT_SUCCESS(Status);
487 }
488 
489 static inline
490 UINT_PTR
491 SpiGet(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
492 {
493     REQ_INTERACTIVE_WINSTA(ERROR_ACCESS_DENIED);
494     return SpiMemCopy(pvParam, pvData, cbSize, fl & SPIF_PROTECT);
495 }
496 
497 static inline
498 UINT_PTR
499 SpiSet(PVOID pvData, PVOID pvParam, ULONG cbSize, FLONG fl)
500 {
501     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
502     return SpiMemCopy(pvData, pvParam, cbSize, fl & SPIF_PROTECT);
503 }
504 
505 static inline
506 UINT_PTR
507 SpiGetEx(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
508 {
509     ULONG cbBufSize;
510     /* Get the cbSite member from UM memory */
511     if (!SpiSet(&cbBufSize, pvParam, sizeof(ULONG), fl))
512         return 0;
513     /* Verify the correct size */
514     if (cbBufSize != cbSize)
515         return 0;
516     return SpiGet(pvParam, pvData, cbSize, fl);
517 }
518 
519 static inline
520 UINT_PTR
521 SpiGetInt(PVOID pvParam, PVOID piValue, FLONG fl)
522 {
523     return SpiGet(pvParam, piValue, sizeof(INT), fl);
524 }
525 
526 static inline
527 UINT_PTR
528 SpiSetYesNo(BOOL *pbData, BOOL bValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
529 {
530     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
531     *pbData = bValue ? TRUE : FALSE;
532     if (fl & SPIF_UPDATEINIFILE)
533     {
534         SpiStoreSz(pwszKey, pwszValue, bValue ? L"Yes" : L"No");
535     }
536     return (UINT_PTR)pwszKey;
537 }
538 
539 static inline
540 UINT_PTR
541 SpiSetBool(BOOL *pbData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
542 {
543     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
544     *pbData = iValue ? TRUE : FALSE;
545     if (fl & SPIF_UPDATEINIFILE)
546     {
547         SpiStoreSzInt(pwszKey, pwszValue, iValue);
548     }
549     return (UINT_PTR)pwszKey;
550 }
551 
552 static inline
553 UINT_PTR
554 SpiSetDWord(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
555 {
556     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
557     *(INT*)pvData = iValue;
558     if (fl & SPIF_UPDATEINIFILE)
559     {
560         SpiStoreDWord(pwszKey, pwszValue, iValue);
561     }
562     return (UINT_PTR)pwszKey;
563 }
564 
565 static inline
566 UINT_PTR
567 SpiSetInt(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
568 {
569     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
570     *(INT*)pvData = iValue;
571     if (fl & SPIF_UPDATEINIFILE)
572     {
573         SpiStoreSzInt(pwszKey, pwszValue, iValue);
574     }
575     return (UINT_PTR)pwszKey;
576 }
577 
578 static inline
579 UINT_PTR
580 SpiSetMetric(PVOID pvData, INT iValue, PCWSTR pwszValue, FLONG fl)
581 {
582     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
583     *(INT*)pvData = iValue;
584     if (fl & SPIF_UPDATEINIFILE)
585     {
586         SpiStoreMetric(pwszValue, iValue);
587     }
588     return (UINT_PTR)KEY_METRIC;
589 }
590 
591 static inline
592 UINT_PTR
593 SpiSetUserPref(DWORD dwMask, PVOID pvValue, FLONG fl)
594 {
595     DWORD dwRegMask;
596     BOOL bValue = PtrToUlong(pvValue);
597 
598     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
599 
600     /* Set or clear bit according to bValue */
601     gspv.dwUserPrefMask = bValue ? gspv.dwUserPrefMask | dwMask :
602                                    gspv.dwUserPrefMask & ~dwMask;
603 
604     if (fl & SPIF_UPDATEINIFILE)
605     {
606         /* Read current value */
607         if (!RegReadUserSetting(KEY_DESKTOP,
608                                 VAL_USERPREFMASK,
609                                 REG_BINARY,
610                                 &dwRegMask,
611                                 sizeof(DWORD)))
612         {
613             WARN("Failed to read UserPreferencesMask setting\n");
614             dwRegMask = 0;
615         }
616 
617         /* Set or clear bit according to bValue */
618         dwRegMask = bValue ? (dwRegMask | dwMask) : (dwRegMask & ~dwMask);
619 
620         /* write back value */
621         RegWriteUserSetting(KEY_DESKTOP,
622                             VAL_USERPREFMASK,
623                             REG_BINARY,
624                             &dwRegMask,
625                             sizeof(DWORD));
626     }
627 
628     return (UINT_PTR)KEY_DESKTOP;
629 }
630 
631 static inline
632 UINT_PTR
633 SpiGetUserPref(DWORD dwMask, PVOID pvParam, FLONG fl)
634 {
635     INT iValue = gspv.dwUserPrefMask & dwMask ? 1 : 0;
636     return SpiGetInt(pvParam, &iValue, fl);
637 }
638 
639 static
640 UINT_PTR
641 SpiSetWallpaper(PVOID pvParam, FLONG fl)
642 {
643     UNICODE_STRING ustr;
644     WCHAR awc[MAX_PATH];
645     BOOL bResult;
646     HBITMAP hbmp, hOldBitmap;
647     SURFACE *psurfBmp;
648     ULONG ulTile, ulStyle;
649 
650     REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
651 
652     if (!pvParam)
653     {
654         /* FIXME: Reset Wallpaper to registry value */
655         return (UINT_PTR)KEY_DESKTOP;
656     }
657 
658     /* Capture UNICODE_STRING */
659     bResult = SpiMemCopy(&ustr, pvParam, sizeof(ustr), fl & SPIF_PROTECT);
660     if (!bResult)
661     {
662         return 0;
663     }
664     if (ustr.Length > MAX_PATH * sizeof(WCHAR))
665     {
666         return 0;
667     }
668 
669     /* Copy the string buffer name */
670     bResult = SpiMemCopy(gspv.awcWallpaper, ustr.Buffer, ustr.Length, fl & SPIF_PROTECT);
671     if (!bResult)
672     {
673         return 0;
674     }
675 
676     /* Update the UNICODE_STRING */
677     gspv.ustrWallpaper.Buffer = gspv.awcWallpaper;
678     gspv.ustrWallpaper.MaximumLength = MAX_PATH * sizeof(WCHAR);
679     gspv.ustrWallpaper.Length = ustr.Length;
680     gspv.awcWallpaper[ustr.Length / sizeof(WCHAR)] = 0;
681 
682     TRACE("SpiSetWallpaper, name=%S\n", gspv.awcWallpaper);
683 
684     /* Update registry */
685     if (fl & SPIF_UPDATEINIFILE)
686     {
687         SpiStoreSz(KEY_DESKTOP, L"Wallpaper", gspv.awcWallpaper);
688     }
689 
690     /* Got a filename? */
691     if (gspv.awcWallpaper[0] != 0)
692     {
693         /* Convert file name to nt file name */
694         ustr.Buffer = awc;
695         ustr.MaximumLength = MAX_PATH * sizeof(WCHAR);
696         ustr.Length = 0;
697         if (!W32kDosPathNameToNtPathName(gspv.awcWallpaper, &ustr))
698         {
699             ERR("RtlDosPathNameToNtPathName_U failed\n");
700             return 0;
701         }
702 
703         /* Load the Bitmap */
704         hbmp = UserLoadImage(ustr.Buffer);
705         if (!hbmp)
706         {
707             ERR("UserLoadImage failed\n");
708             return 0;
709         }
710 
711         /* Try to get the size of the wallpaper */
712         if (!(psurfBmp = SURFACE_ShareLockSurface(hbmp)))
713         {
714             GreDeleteObject(hbmp);
715             return 0;
716         }
717 
718         gspv.cxWallpaper = psurfBmp->SurfObj.sizlBitmap.cx;
719         gspv.cyWallpaper = psurfBmp->SurfObj.sizlBitmap.cy;
720         gspv.WallpaperMode = wmCenter;
721 
722         SURFACE_ShareUnlockSurface(psurfBmp);
723 
724         /* Change the bitmap's ownership */
725         GreSetObjectOwner(hbmp, GDI_OBJ_HMGR_PUBLIC);
726 
727         /* Yes, Windows really loads the current setting from the registry. */
728         ulTile = SpiLoadInt(KEY_DESKTOP, L"TileWallpaper", 0);
729         ulStyle = SpiLoadInt(KEY_DESKTOP, L"WallpaperStyle", 0);
730         TRACE("SpiSetWallpaper: ulTile=%lu, ulStyle=%lu\n", ulTile, ulStyle);
731 
732         /* Check the values we found in the registry */
733         if (ulTile && !ulStyle)
734         {
735             gspv.WallpaperMode = wmTile;
736         }
737         else if (!ulTile && ulStyle)
738         {
739             if (ulStyle == 2)
740             {
741                 gspv.WallpaperMode = wmStretch;
742             }
743             else if (ulStyle == 6)
744             {
745                 gspv.WallpaperMode = wmFit;
746             }
747             else if (ulStyle == 10)
748             {
749                 gspv.WallpaperMode = wmFill;
750             }
751         }
752     }
753     else
754     {
755         /* Remove wallpaper */
756         gspv.cxWallpaper = 0;
757         gspv.cyWallpaper = 0;
758         hbmp = 0;
759     }
760 
761     /* Take care of the old wallpaper, if any */
762     hOldBitmap = gspv.hbmWallpaper;
763     if(hOldBitmap != NULL)
764     {
765         /* Delete the old wallpaper */
766         GreSetObjectOwner(hOldBitmap, GDI_OBJ_HMGR_POWNED);
767         GreDeleteObject(hOldBitmap);
768     }
769 
770     /* Set the new wallpaper */
771     gspv.hbmWallpaper = hbmp;
772 
773     NtUserRedrawWindow(UserGetShellWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
774 
775 
776     return (UINT_PTR)KEY_DESKTOP;
777 }
778 
779 static BOOL
780 SpiNotifyNCMetricsChanged(VOID)
781 {
782     PWND pwndDesktop, pwndCurrent;
783     HWND *ahwnd;
784     USER_REFERENCE_ENTRY Ref;
785     int i;
786 
787     pwndDesktop = UserGetDesktopWindow();
788     ASSERT(pwndDesktop);
789 
790     ahwnd = IntWinListChildren(pwndDesktop);
791     if(!ahwnd)
792         return FALSE;
793 
794     for (i = 0; ahwnd[i]; i++)
795     {
796         pwndCurrent = UserGetWindowObject(ahwnd[i]);
797         if(!pwndCurrent)
798             continue;
799 
800         UserRefObjectCo(pwndCurrent, &Ref);
801         co_WinPosSetWindowPos(pwndCurrent, 0, pwndCurrent->rcWindow.left,pwndCurrent->rcWindow.top,
802                                               pwndCurrent->rcWindow.right-pwndCurrent->rcWindow.left
803                                               ,pwndCurrent->rcWindow.bottom - pwndCurrent->rcWindow.top,
804                               SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|
805                               SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW);
806         UserDerefObjectCo(pwndCurrent);
807     }
808 
809     ExFreePoolWithTag(ahwnd, USERTAG_WINDOWLIST);
810 
811     return TRUE;
812 }
813 
814 static
815 UINT_PTR
816 SpiGetSet(UINT uiAction, UINT uiParam, PVOID pvParam, FLONG fl)
817 {
818     switch (uiAction)
819     {
820         case SPI_GETBEEP:
821             return SpiGetInt(pvParam, &gspv.bBeep, fl);
822 
823         case SPI_SETBEEP:
824             return SpiSetYesNo(&gspv.bBeep, uiParam, KEY_SOUND, VAL_BEEP, fl);
825 
826         case SPI_GETMOUSE:
827             return SpiGet(pvParam, &gspv.caiMouse, 3 * sizeof(INT), fl);
828 
829         case SPI_SETMOUSE:
830             if (!SpiSet(&gspv.caiMouse, pvParam, 3 * sizeof(INT), fl))
831                 return 0;
832             if (fl & SPIF_UPDATEINIFILE)
833             {
834                 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE1, gspv.caiMouse.FirstThreshold);
835                 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE2, gspv.caiMouse.SecondThreshold);
836                 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE3, gspv.caiMouse.Acceleration);
837             }
838             return (UINT_PTR)KEY_MOUSE;
839 
840         case SPI_GETBORDER:
841             return SpiGetInt(pvParam, &gspv.ncm.iBorderWidth, fl);
842 
843         case SPI_SETBORDER:
844             uiParam = max(uiParam, 1);
845             return SpiSetInt(&gspv.ncm.iBorderWidth, uiParam, KEY_METRIC, VAL_BORDER, fl);
846 
847         case SPI_GETKEYBOARDSPEED:
848             return SpiGetInt(pvParam, &gspv.dwKbdSpeed, fl);
849 
850         case SPI_SETKEYBOARDSPEED:
851             return SpiSetInt(&gspv.dwKbdSpeed, uiParam, KEY_KBD, VAL_KBDSPD, fl);
852 
853         case SPI_LANGDRIVER:
854             ERR("SPI_LANGDRIVER is unimplemented\n");
855             break;
856 
857         case SPI_GETSCREENSAVETIMEOUT:
858             return SpiGetInt(pvParam, &gspv.iScrSaverTimeout, fl);
859 
860         case SPI_SETSCREENSAVETIMEOUT:
861             return SpiSetInt(&gspv.iScrSaverTimeout, uiParam, KEY_DESKTOP, VAL_SCRTO, fl);
862 
863         case SPI_GETSCREENSAVEACTIVE:
864             return SpiGetInt(pvParam, &gspv.bScrSaverActive, fl);
865 
866         case SPI_SETSCREENSAVEACTIVE:
867             return SpiSetInt(&gspv.bScrSaverActive, uiParam, KEY_DESKTOP, VAL_SCRACT, fl);
868 
869         case SPI_GETGRIDGRANULARITY:
870             return SpiGetInt(pvParam, &gspv.uiGridGranularity, fl);
871 
872         case SPI_SETGRIDGRANULARITY:
873             return SpiSetInt(&gspv.uiGridGranularity, uiParam, KEY_DESKTOP, VAL_GRID, fl);
874 
875         case SPI_GETDESKWALLPAPER:
876             uiParam = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
877             return SpiGet(pvParam, gspv.awcWallpaper, uiParam, fl);
878 
879         case SPI_SETDESKWALLPAPER:
880             return SpiSetWallpaper(pvParam, fl);
881 
882         case SPI_SETDESKPATTERN:
883             ERR("SPI_SETDESKPATTERN is unimplemented\n");
884             break;
885 
886         case SPI_GETKEYBOARDDELAY:
887             return SpiGetInt(pvParam, &gspv.iKbdDelay, fl);
888 
889         case SPI_SETKEYBOARDDELAY:
890             return SpiSetInt(&gspv.iKbdDelay, uiParam, KEY_KBD, VAL_KBDDELAY, fl);
891 
892         case SPI_ICONHORIZONTALSPACING:
893             if (pvParam)
894             {
895                 return SpiGetInt(pvParam, &gspv.im.iHorzSpacing, fl);
896             }
897             uiParam = max(uiParam, 32);
898             return SpiSetMetric(&gspv.im.iHorzSpacing, uiParam, VAL_ICONSPC, fl);
899 
900         case SPI_ICONVERTICALSPACING:
901             if (pvParam)
902             {
903                 return SpiGetInt(pvParam, &gspv.im.iVertSpacing, fl);
904             }
905             uiParam = max(uiParam, 32);
906             return SpiSetMetric(&gspv.im.iVertSpacing, uiParam, VAL_ICONVSPC, fl);
907 
908         case SPI_GETICONTITLEWRAP:
909             return SpiGetInt(pvParam, &gspv.im.iTitleWrap, fl);
910 
911         case SPI_SETICONTITLEWRAP:
912             return SpiSetInt(&gspv.im.iTitleWrap, uiParam, KEY_METRIC, VAL_ITWRAP, fl);
913 
914         case SPI_GETMENUDROPALIGNMENT:
915             return SpiGetInt(pvParam, &gspv.bMenuDropAlign, fl);
916 
917         case SPI_SETMENUDROPALIGNMENT:
918             return SpiSetBool(&gspv.bMenuDropAlign, uiParam, KEY_MDALIGN, VAL_MDALIGN, fl);
919 
920         case SPI_SETDOUBLECLKWIDTH:
921             return SpiSetInt(&gspv.iDblClickWidth, uiParam, KEY_MOUSE, VAL_DBLCLKWIDTH, fl);
922 
923         case SPI_SETDOUBLECLKHEIGHT:
924             return SpiSetInt(&gspv.iDblClickHeight, uiParam, KEY_MOUSE, VAL_DBLCLKHEIGHT, fl);
925 
926         case SPI_GETICONTITLELOGFONT:
927             return SpiGet(pvParam, &gspv.im.lfFont, sizeof(LOGFONTW), fl);
928 
929         case SPI_SETICONTITLELOGFONT:
930             if (!SpiSet(&gspv.im.lfFont, pvParam, sizeof(LOGFONTW), fl))
931                 return 0;
932             if (fl & SPIF_UPDATEINIFILE)
933             {
934                 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
935             }
936             return (UINT_PTR)KEY_METRIC;
937 
938         case SPI_SETDOUBLECLICKTIME:
939             return SpiSetInt(&gspv.iDblClickTime, uiParam, KEY_MOUSE, VAL_DBLCLKTIME, fl);
940 
941         case SPI_SETMOUSEBUTTONSWAP:
942             return SpiSetInt(&gspv.bMouseBtnSwap, uiParam, KEY_MOUSE, VAL_SWAP, fl);
943 
944         case SPI_GETFASTTASKSWITCH:
945             return SpiGetInt(pvParam, &gspv.bFastTaskSwitch, fl);
946 
947         case SPI_SETFASTTASKSWITCH:
948             /* According to Winetest this one is unimplemented */
949             return 1;
950 
951         case SPI_GETDRAGFULLWINDOWS:
952             return SpiGetInt(pvParam, &gspv.bDragFullWindows, fl);
953 
954         case SPI_SETDRAGFULLWINDOWS:
955             return SpiSetInt(&gspv.bDragFullWindows, uiParam, KEY_DESKTOP, VAL_DRAG, fl);
956 
957         case SPI_GETNONCLIENTMETRICS:
958         {
959             return SpiGet(pvParam, &gspv.ncm, sizeof(NONCLIENTMETRICSW), fl);
960         }
961 
962         case SPI_SETNONCLIENTMETRICS:
963         {
964             LPNONCLIENTMETRICSW metrics = (LPNONCLIENTMETRICSW)pvParam;
965 
966             /* Fixup user's structure size */
967             metrics->cbSize = sizeof(NONCLIENTMETRICSW);
968 
969             if (!SpiSet(&gspv.ncm, metrics, sizeof(NONCLIENTMETRICSW), fl))
970                 return 0;
971 
972             if (fl & SPIF_UPDATEINIFILE)
973             {
974                 SpiStoreMetric(VAL_BORDER, gspv.ncm.iBorderWidth);
975                 SpiStoreMetric(L"ScrollWidth", gspv.ncm.iScrollWidth);
976                 SpiStoreMetric(L"ScrollHeight", gspv.ncm.iScrollHeight);
977                 SpiStoreMetric(L"CaptionWidth", gspv.ncm.iCaptionWidth);
978                 SpiStoreMetric(L"CaptionHeight", gspv.ncm.iCaptionHeight);
979                 SpiStoreMetric(L"SmCaptionWidth", gspv.ncm.iSmCaptionWidth);
980                 SpiStoreMetric(L"SmCaptionHeight", gspv.ncm.iSmCaptionHeight);
981                 SpiStoreMetric(L"MenuWidth", gspv.ncm.iMenuWidth);
982                 SpiStoreMetric(L"MenuHeight", gspv.ncm.iMenuHeight);
983 #if (WINVER >= 0x0600)
984                 SpiStoreMetric(L"PaddedBorderWidth", gspv.ncm.iPaddedBorderWidth);
985 #endif
986                 SpiStoreFont(L"CaptionFont", &gspv.ncm.lfCaptionFont);
987                 SpiStoreFont(L"SmCaptionFont", &gspv.ncm.lfSmCaptionFont);
988                 SpiStoreFont(L"MenuFont", &gspv.ncm.lfMenuFont);
989                 SpiStoreFont(L"StatusFont", &gspv.ncm.lfStatusFont);
990                 SpiStoreFont(L"MessageFont", &gspv.ncm.lfMessageFont);
991             }
992 
993             if(!SpiNotifyNCMetricsChanged())
994                 return 0;
995 
996             return (UINT_PTR)KEY_METRIC;
997         }
998 
999         case SPI_GETMINIMIZEDMETRICS:
1000         {
1001             return SpiGet(pvParam, &gspv.mm, sizeof(MINIMIZEDMETRICS), fl);
1002         }
1003 
1004         case SPI_SETMINIMIZEDMETRICS:
1005         {
1006             LPMINIMIZEDMETRICS metrics = (LPMINIMIZEDMETRICS)pvParam;
1007 
1008             /* Fixup user's structure size */
1009             metrics->cbSize = sizeof(MINIMIZEDMETRICS);
1010 
1011             if (!SpiSet(&gspv.mm, metrics, sizeof(MINIMIZEDMETRICS), fl))
1012                 return 0;
1013 
1014             gspv.mm.iWidth = max(0, gspv.mm.iWidth);
1015             gspv.mm.iHorzGap = max(0, gspv.mm.iHorzGap);
1016             gspv.mm.iVertGap = max(0, gspv.mm.iVertGap);
1017             gspv.mm.iArrange = gspv.mm.iArrange & 0xf;
1018 
1019             if (fl & SPIF_UPDATEINIFILE)
1020             {
1021                 SpiStoreMetric(L"MinWidth", gspv.mm.iWidth);
1022                 SpiStoreMetric(L"MinHorzGap", gspv.mm.iHorzGap);
1023                 SpiStoreMetric(L"MinVertGap", gspv.mm.iVertGap);
1024                 SpiStoreMetric(L"MinArrange", gspv.mm.iArrange);
1025             }
1026 
1027             return (UINT_PTR)KEY_METRIC;
1028         }
1029 
1030         case SPI_GETICONMETRICS:
1031         {
1032             return SpiGet(pvParam, &gspv.im, sizeof(ICONMETRICSW), fl);
1033         }
1034 
1035         case SPI_SETICONMETRICS:
1036         {
1037             LPICONMETRICSW metrics = (LPICONMETRICSW)pvParam;
1038 
1039             /* Fixup user's structure size */
1040             metrics->cbSize = sizeof(ICONMETRICSW);
1041 
1042             if (!SpiSet(&gspv.im, metrics, sizeof(ICONMETRICSW), fl))
1043                 return 0;
1044 
1045             if (fl & SPIF_UPDATEINIFILE)
1046             {
1047                 SpiStoreMetric(VAL_ICONSPC, gspv.im.iHorzSpacing);
1048                 SpiStoreMetric(VAL_ICONVSPC, gspv.im.iVertSpacing);
1049                 SpiStoreMetric(VAL_ITWRAP, gspv.im.iTitleWrap);
1050                 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
1051             }
1052             return (UINT_PTR)KEY_METRIC;
1053         }
1054 
1055         case SPI_GETWORKAREA:
1056         {
1057             PMONITOR pmonitor = UserGetPrimaryMonitor();
1058 
1059             if(!pmonitor)
1060                 return 0;
1061 
1062             return SpiGet(pvParam, &pmonitor->rcWork, sizeof(RECTL), fl);
1063         }
1064 
1065         case SPI_SETWORKAREA:
1066         {
1067             PMONITOR pmonitor;
1068             RECTL rcWorkArea, rcIntersect;
1069 
1070             if (!pvParam)
1071                 return 0;
1072 
1073             RtlCopyMemory(&rcWorkArea, pvParam, sizeof(rcWorkArea));
1074 
1075             /* fail if empty */
1076             if (RECTL_bIsEmptyRect(&rcWorkArea))
1077                 return 0;
1078 
1079             /* get the nearest monitor */
1080             pmonitor = UserMonitorFromRect(&rcWorkArea, MONITOR_DEFAULTTONEAREST);
1081             if (!pmonitor)
1082                 return 0;
1083 
1084             /* fail unless work area is completely in monitor */
1085             if (!RECTL_bIntersectRect(&rcIntersect, &pmonitor->rcMonitor, &rcWorkArea) ||
1086                 !RtlEqualMemory(&rcIntersect, &rcWorkArea, sizeof(rcIntersect)))
1087             {
1088                 return 0;
1089             }
1090 
1091             if (!SpiSet(&pmonitor->rcWork, pvParam, sizeof(RECTL), fl))
1092                 return 0;
1093 
1094             if (fl & SPIF_UPDATEINIFILE)
1095             {
1096                 // FIXME: What to do?
1097             }
1098             return (UINT_PTR)KEY_DESKTOP;
1099         }
1100 
1101         case SPI_SETPENWINDOWS:
1102             ERR("SPI_SETPENWINDOWS is unimplemented\n");
1103             break;
1104 
1105         case SPI_GETFILTERKEYS:
1106         {
1107             LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1108 
1109             if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1110                 return 0;
1111 
1112             if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1113                 return 0;
1114 
1115             return SpiGet(pvParam, &gspv.filterkeys, sizeof(FILTERKEYS), fl);
1116         }
1117 
1118         case SPI_SETFILTERKEYS:
1119         {
1120             LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1121 
1122             if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1123                 return 0;
1124 
1125             if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1126                 return 0;
1127 
1128             if (!SpiSet(&gspv.filterkeys, pvParam, sizeof(FILTERKEYS), fl))
1129                 return 0;
1130 
1131             if (fl & SPIF_UPDATEINIFILE)
1132             {
1133                 // FIXME: What to do?
1134             }
1135             return (UINT_PTR)KEY_DESKTOP;
1136         }
1137 
1138         case SPI_GETTOGGLEKEYS:
1139         {
1140             LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1141 
1142             if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1143                 return 0;
1144 
1145             if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1146                 return 0;
1147 
1148             return SpiGet(pvParam, &gspv.togglekeys, sizeof(TOGGLEKEYS), fl);
1149         }
1150 
1151         case SPI_SETTOGGLEKEYS:
1152         {
1153             LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1154 
1155             if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1156                 return 0;
1157 
1158             if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1159                 return 0;
1160 
1161             if (!SpiSet(&gspv.togglekeys, pvParam, sizeof(TOGGLEKEYS), fl))
1162                 return 0;
1163 
1164             if (fl & SPIF_UPDATEINIFILE)
1165             {
1166                 // FIXME: What to do?
1167             }
1168             return (UINT_PTR)KEY_DESKTOP;
1169         }
1170 
1171         case SPI_GETMOUSEKEYS:
1172         {
1173             LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1174 
1175             if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1176                 return 0;
1177 
1178             if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1179                 return 0;
1180 
1181             return SpiGet(pvParam, &gspv.mousekeys, sizeof(MOUSEKEYS), fl);
1182         }
1183 
1184         case SPI_SETMOUSEKEYS:
1185         {
1186             LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1187 
1188             if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1189                 return 0;
1190 
1191             if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1192                 return 0;
1193 
1194             if (!SpiSet(&gspv.mousekeys, pvParam, sizeof(MOUSEKEYS), fl))
1195                 return 0;
1196 
1197             if (fl & SPIF_UPDATEINIFILE)
1198             {
1199                 // FIXME: What to do?
1200             }
1201             return (UINT_PTR)KEY_DESKTOP;
1202         }
1203 
1204         case SPI_GETSHOWSOUNDS:
1205             return SpiGetInt(pvParam, &gspv.bShowSounds, fl);
1206 
1207         case SPI_SETSHOWSOUNDS:
1208             return SpiSetBool(&gspv.bShowSounds, uiParam, KEY_SHOWSNDS, VAL_ON, fl);
1209 
1210         case SPI_GETSTICKYKEYS:
1211         {
1212             LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1213 
1214             if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1215                 return 0;
1216 
1217             if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1218                 return 0;
1219 
1220             return SpiGetEx(pvParam, &gspv.stickykeys, sizeof(STICKYKEYS), fl);
1221         }
1222 
1223         case SPI_SETSTICKYKEYS:
1224         {
1225             LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1226 
1227             if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1228                 return 0;
1229 
1230             if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1231                 return 0;
1232 
1233             if (!SpiSet(&gspv.stickykeys, pvParam, sizeof(STICKYKEYS), fl))
1234                 return 0;
1235 
1236             if (fl & SPIF_UPDATEINIFILE)
1237             {
1238                 // FIXME: What to do?
1239             }
1240             return (UINT_PTR)KEY_DESKTOP;
1241         }
1242 
1243         case SPI_GETACCESSTIMEOUT:
1244         {
1245             LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1246 
1247             if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1248                 return 0;
1249 
1250             if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1251                 return 0;
1252 
1253             return SpiGetEx(pvParam, &gspv.accesstimeout, sizeof(ACCESSTIMEOUT), fl);
1254         }
1255 
1256         case SPI_SETACCESSTIMEOUT:
1257         {
1258             LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1259 
1260             if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1261             {
1262                 return 0;
1263             }
1264 
1265             if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1266             {
1267                 return 0;
1268             }
1269 
1270             if (!SpiSet(&gspv.accesstimeout, pvParam, sizeof(ACCESSTIMEOUT), fl))
1271                 return 0;
1272 
1273             if (fl & SPIF_UPDATEINIFILE)
1274             {
1275                 // FIXME: What to do?
1276             }
1277             return (UINT_PTR)KEY_DESKTOP;
1278         }
1279 
1280         case SPI_GETSERIALKEYS:
1281         {
1282             LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1283 
1284             if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1285                 return 0;
1286 
1287             if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1288                 return 0;
1289 
1290             return SpiGet(pvParam, &gspv.serialkeys, sizeof(SERIALKEYS), fl);
1291         }
1292 
1293         case SPI_SETSERIALKEYS:
1294         {
1295             LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1296 
1297             if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1298                 return 0;
1299 
1300             if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1301                 return 0;
1302 
1303             if (!SpiSet(&gspv.serialkeys, pvParam, sizeof(SERIALKEYS), fl))
1304                 return 0;
1305 
1306             if (fl & SPIF_UPDATEINIFILE)
1307             {
1308                 // FIXME: What to do?
1309             }
1310             return (UINT_PTR)KEY_DESKTOP;
1311         }
1312 
1313         case SPI_GETSOUNDSENTRY:
1314         {
1315             LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1316 
1317             if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1318                 return 0;
1319 
1320             if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1321                 return 0;
1322 
1323             return SpiGet(pvParam, &gspv.soundsentry, sizeof(SOUNDSENTRYW), fl);
1324         }
1325 
1326         case SPI_SETSOUNDSENTRY:
1327         {
1328             LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1329 
1330             if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1331                 return 0;
1332 
1333             if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1334                 return 0;
1335 
1336             if (!SpiSet(&gspv.soundsentry, pvParam, sizeof(SOUNDSENTRYW), fl))
1337                 return 0;
1338 
1339             if (fl & SPIF_UPDATEINIFILE)
1340             {
1341                 // FIXME: What to do?
1342             }
1343             return (UINT_PTR)KEY_DESKTOP;
1344         }
1345 
1346         case SPI_GETHIGHCONTRAST:
1347         {
1348             LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1349 
1350             if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1351                 return 0;
1352 
1353             if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1354                 return 0;
1355 
1356             return SpiGet(pvParam, &gspv.highcontrast, sizeof(HIGHCONTRASTW), fl);
1357         }
1358 
1359         case SPI_SETHIGHCONTRAST:
1360         {
1361             LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1362 
1363             if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1364                 return 0;
1365 
1366             if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1367                 return 0;
1368 
1369             if (!SpiSet(&gspv.highcontrast, pvParam, sizeof(HIGHCONTRASTW), fl))
1370                 return 0;
1371 
1372             if (fl & SPIF_UPDATEINIFILE)
1373             {
1374                 // FIXME: What to do?
1375             }
1376             return (UINT_PTR)KEY_DESKTOP;
1377         }
1378 
1379         case SPI_GETKEYBOARDPREF:
1380             return SpiGetInt(pvParam, &gspv.bKbdPref, fl);
1381 
1382         case SPI_SETKEYBOARDPREF:
1383             return SpiSetBool(&gspv.bKbdPref, uiParam, KEY_KDBPREF, VAL_ON, fl);
1384 
1385         case SPI_GETSCREENREADER:
1386             return SpiGetInt(pvParam, &gspv.bScreenReader, fl);
1387 
1388         case SPI_SETSCREENREADER:
1389             return SpiSetBool(&gspv.bScreenReader, uiParam, KEY_SCRREAD, VAL_ON, fl);
1390 
1391         case SPI_GETANIMATION:
1392             return SpiGet(pvParam, &gspv.animationinfo, sizeof(ANIMATIONINFO), fl);
1393 
1394         case SPI_SETANIMATION:
1395             if (!SpiSet(&gspv.animationinfo, pvParam, sizeof(ANIMATIONINFO), fl))
1396                 return 0;
1397             if (fl & SPIF_UPDATEINIFILE)
1398             {
1399                 // FIXME: What to do?
1400             }
1401             return (UINT_PTR)KEY_DESKTOP;
1402 
1403         case SPI_GETFONTSMOOTHING:
1404             return SpiGetInt(pvParam, &gspv.bFontSmoothing, fl);
1405 
1406         case SPI_SETFONTSMOOTHING:
1407             gspv.bFontSmoothing = (uiParam == 2);
1408             if (fl & SPIF_UPDATEINIFILE)
1409             {
1410                 SpiStoreSz(KEY_DESKTOP, VAL_FONTSMOOTHING, (uiParam == 2) ? L"2" : L"0");
1411             }
1412             return (UINT_PTR)KEY_DESKTOP;
1413 
1414         case SPI_SETDRAGWIDTH:
1415             return SpiSetInt(&gspv.iDragWidth, uiParam, KEY_DESKTOP, VAL_DRAGWIDTH, fl);
1416 
1417         case SPI_SETDRAGHEIGHT:
1418             return SpiSetInt(&gspv.iDragHeight, uiParam, KEY_DESKTOP, VAL_DRAGHEIGHT, fl);
1419 
1420         case SPI_SETHANDHELD:
1421             return SpiSetBool(&gspv.bHandHeld, uiParam, KEY_DESKTOP, L"HandHeld", fl);
1422 
1423         case SPI_GETLOWPOWERTIMEOUT:
1424             return SpiGetInt(pvParam, &gspv.iLowPwrTimeout, fl);
1425 
1426         case SPI_GETPOWEROFFTIMEOUT:
1427             return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1428 
1429         case SPI_SETLOWPOWERTIMEOUT:
1430             return SpiSetInt(&gspv.iLowPwrTimeout, uiParam, KEY_DESKTOP, L"LowPowerTimeOut", fl);
1431 
1432         case SPI_SETPOWEROFFTIMEOUT:
1433             return SpiSetInt(&gspv.iPwrOffTimeout, uiParam, KEY_DESKTOP, L"PowerOffTimeOut", fl);
1434 
1435         case SPI_GETLOWPOWERACTIVE:
1436             return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1437 
1438         case SPI_GETPOWEROFFACTIVE:
1439             return SpiGetInt(pvParam, &gspv.bPwrOffActive, fl);
1440 
1441         case SPI_SETLOWPOWERACTIVE:
1442             return SpiSetBool(&gspv.bLowPwrActive, uiParam, KEY_DESKTOP, L"LowPowerActive", fl);
1443 
1444         case SPI_SETPOWEROFFACTIVE:
1445             return SpiSetBool(&gspv.bPwrOffActive, uiParam, KEY_DESKTOP, L"PowerOffActive", fl);
1446 
1447         case SPI_SETCURSORS:
1448             ERR("SPI_SETCURSORS is unimplemented\n");
1449             break;
1450 
1451         case SPI_SETICONS:
1452             ERR("SPI_SETICONS is unimplemented\n");
1453             break;
1454 
1455         case SPI_GETDEFAULTINPUTLANG:
1456             if (!gspklBaseLayout)
1457                 return FALSE;
1458 
1459             return SpiGet(pvParam, &gspklBaseLayout->hkl, sizeof(HKL), fl);
1460 
1461         case SPI_SETDEFAULTINPUTLANG:
1462         {
1463             HKL hkl;
1464 
1465             /* Note: SPIF_UPDATEINIFILE is not supported */
1466             if ((fl & SPIF_UPDATEINIFILE) || !SpiSet(&hkl, pvParam, sizeof(hkl), fl))
1467                 return FALSE;
1468 
1469             return UserSetDefaultInputLang(hkl);
1470         }
1471 
1472         case SPI_SETLANGTOGGLE:
1473             gdwLanguageToggleKey = UserGetLanguageToggle();
1474             return gdwLanguageToggleKey;
1475             break;
1476 
1477         case SPI_GETWINDOWSEXTENSION:
1478             ERR("SPI_GETWINDOWSEXTENSION is unimplemented\n");
1479             break;
1480 
1481         case SPI_GETMOUSETRAILS:
1482             return SpiGetInt(pvParam, &gspv.iMouseTrails, fl);
1483 
1484         case SPI_SETMOUSETRAILS:
1485             return SpiSetInt(&gspv.iMouseTrails, uiParam, KEY_MOUSE, VAL_MOUSETRAILS, fl);
1486 
1487         case SPI_GETSNAPTODEFBUTTON:
1488             return SpiGetInt(pvParam, &gspv.bSnapToDefBtn, fl);
1489 
1490         case SPI_SETSNAPTODEFBUTTON:
1491             return SpiSetBool(&gspv.bSnapToDefBtn, uiParam, KEY_MOUSE, VAL_SNAPDEFBTN, fl);
1492 
1493         case SPI_GETMOUSEHOVERWIDTH:
1494             return SpiGetInt(pvParam, &gspv.iMouseHoverWidth, fl);
1495 
1496         case SPI_SETMOUSEHOVERWIDTH:
1497             return SpiSetInt(&gspv.iMouseHoverWidth, uiParam, KEY_MOUSE, VAL_HOVERWIDTH, fl);
1498 
1499         case SPI_GETMOUSEHOVERHEIGHT:
1500             return SpiGetInt(pvParam, &gspv.iMouseHoverHeight, fl);
1501 
1502         case SPI_SETMOUSEHOVERHEIGHT:
1503             return SpiSetInt(&gspv.iMouseHoverHeight, uiParam, KEY_MOUSE, VAL_HOVERHEIGHT, fl);
1504 
1505         case SPI_GETMOUSEHOVERTIME:
1506             return SpiGetInt(pvParam, &gspv.iMouseHoverTime, fl);
1507 
1508         case SPI_SETMOUSEHOVERTIME:
1509            /* See http://msdn2.microsoft.com/en-us/library/ms724947.aspx
1510             * copy text from it, if some agument why xp and 2003 behovir diffent
1511             * only if they do not have SP install
1512             * " Windows Server 2003 and Windows XP: The operating system does not
1513             *   enforce the use of USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM until
1514             *   Windows Server 2003 SP1 and Windows XP SP2 "
1515             */
1516             return SpiSetInt(&gspv.iMouseHoverTime, uiParam, KEY_MOUSE, VAL_HOVERTIME, fl);
1517 
1518         case SPI_GETWHEELSCROLLLINES:
1519             return SpiGetInt(pvParam, &gspv.iWheelScrollLines, fl);
1520 
1521         case SPI_SETWHEELSCROLLLINES:
1522             return SpiSetInt(&gspv.iWheelScrollLines, uiParam, KEY_DESKTOP, VAL_SCRLLLINES, fl);
1523 
1524         case SPI_GETMENUSHOWDELAY:
1525             return SpiGetInt(pvParam, &gspv.dwMenuShowDelay, fl);
1526 
1527         case SPI_SETMENUSHOWDELAY:
1528             return SpiSetInt(&gspv.dwMenuShowDelay, uiParam, KEY_DESKTOP, L"MenuShowDelay", fl);
1529 
1530 #if (_WIN32_WINNT >= 0x0600)
1531         case SPI_GETWHEELSCROLLCHARS:
1532             return SpiGetInt(pvParam, &gspv.uiWheelScrollChars, fl);
1533 
1534         case SPI_SETWHEELSCROLLCHARS:
1535             return SpiSetInt(&gspv.uiWheelScrollChars, uiParam, KEY_DESKTOP, VAL_SCRLLCHARS, fl);
1536 #endif
1537         case SPI_GETSHOWIMEUI:
1538             return SpiGetInt(pvParam, &gspv.bShowImeUi, fl);
1539 
1540         case SPI_SETSHOWIMEUI:
1541             return SpiSetBool(&gspv.bShowImeUi, uiParam, KEY_DESKTOP, L"", fl);
1542 
1543         case SPI_GETMOUSESPEED:
1544             return SpiGetInt(pvParam, &gspv.iMouseSpeed, fl);
1545 
1546         case SPI_SETMOUSESPEED:
1547         {
1548             /* Allowed range is [1:20] */
1549             if ((INT_PTR)pvParam < 1 || (INT_PTR)pvParam > 20)
1550                 return 0;
1551             else
1552                 return SpiSetInt(&gspv.iMouseSpeed, (INT_PTR)pvParam, KEY_MOUSE, VAL_SENSITIVITY, fl);
1553         }
1554 
1555         case SPI_GETSCREENSAVERRUNNING:
1556             return SpiGetInt(pvParam, &gspv.bScrSaverRunning, fl);
1557 
1558         case SPI_SETSCREENSAVERRUNNING:
1559             // FIXME: also return value?
1560             return SpiSetBool(&gspv.bScrSaverRunning, uiParam, KEY_MOUSE, L"", fl);
1561 
1562 #if(WINVER >= 0x0600)
1563         case SPI_GETAUDIODESCRIPTION:
1564             return SpiGet(pvParam, &gspv.audiodescription, sizeof(AUDIODESCRIPTION), fl);
1565 
1566         case SPI_SETAUDIODESCRIPTION:
1567             ERR("SPI_SETAUDIODESCRIPTION is unimplemented\n");
1568             break;
1569 
1570         case SPI_GETSCREENSAVESECURE:
1571             return SpiGetInt(pvParam, &gspv.bScrSaverSecure, fl);
1572 
1573         case SPI_SETSCREENSAVESECURE:
1574             return SpiSetBool(&gspv.bScrSaverSecure, uiParam, KEY_DESKTOP, L"ScreenSaverIsSecure", fl);
1575 #endif
1576 
1577         case SPI_GETACTIVEWINDOWTRACKING:
1578             return SpiGetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1579 
1580         case SPI_SETACTIVEWINDOWTRACKING:
1581             return SpiSetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1582 
1583         case SPI_GETMENUANIMATION:
1584             return SpiGetUserPref(UPM_MENUANIMATION, pvParam, fl);
1585 
1586         case SPI_SETMENUANIMATION:
1587             return SpiSetUserPref(UPM_MENUANIMATION, pvParam, fl);
1588 
1589         case SPI_GETCOMBOBOXANIMATION:
1590             return SpiGetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1591 
1592         case SPI_SETCOMBOBOXANIMATION:
1593             return SpiSetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1594 
1595         case SPI_GETLISTBOXSMOOTHSCROLLING:
1596             return SpiGetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1597 
1598         case SPI_SETLISTBOXSMOOTHSCROLLING:
1599             return SpiSetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1600 
1601         case SPI_GETGRADIENTCAPTIONS:
1602         {
1603             if (NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL) <= 8)
1604             {
1605                 INT iValue = 0;
1606                 return SpiGetInt(pvParam, &iValue, fl);
1607             }
1608             else
1609             {
1610                 return SpiGetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1611             }
1612         }
1613 
1614         case SPI_SETGRADIENTCAPTIONS:
1615             return SpiSetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1616 
1617         case SPI_GETKEYBOARDCUES:
1618             return SpiGetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1619 
1620         case SPI_SETKEYBOARDCUES:
1621             return SpiSetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1622 
1623         case SPI_GETACTIVEWNDTRKZORDER:
1624             return SpiGetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1625 
1626         case SPI_SETACTIVEWNDTRKZORDER:
1627             return SpiSetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1628 
1629         case SPI_GETHOTTRACKING:
1630             return SpiGetUserPref(UPM_HOTTRACKING, pvParam, fl);
1631 
1632         case SPI_SETHOTTRACKING:
1633             return SpiSetUserPref(UPM_HOTTRACKING, pvParam, fl);
1634 
1635         case SPI_GETMENUFADE:
1636             return SpiGetUserPref(UPM_MENUFADE, pvParam, fl);
1637 
1638         case SPI_SETMENUFADE:
1639             return SpiSetUserPref(UPM_MENUFADE, pvParam, fl);
1640 
1641         case SPI_GETSELECTIONFADE:
1642             return SpiGetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1643 
1644         case SPI_SETSELECTIONFADE:
1645             return SpiSetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1646 
1647         case SPI_GETTOOLTIPANIMATION:
1648             return SpiGetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1649 
1650         case SPI_SETTOOLTIPANIMATION:
1651             return SpiSetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1652 
1653         case SPI_GETTOOLTIPFADE:
1654             return SpiGetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1655 
1656         case SPI_SETTOOLTIPFADE:
1657             return SpiSetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1658 
1659         case SPI_GETCURSORSHADOW:
1660             return SpiGetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1661 
1662         case SPI_SETCURSORSHADOW:
1663             gspv.bMouseCursorShadow = PtrToUlong(pvParam);
1664             return SpiSetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1665 
1666         case SPI_GETUIEFFECTS:
1667             return SpiGetUserPref(UPM_UIEFFECTS, pvParam, fl);
1668 
1669         case SPI_SETUIEFFECTS:
1670             return SpiSetUserPref(UPM_UIEFFECTS, pvParam, fl);
1671 
1672         case SPI_GETMOUSESONAR:
1673             return SpiGetInt(pvParam, &gspv.bMouseSonar, fl);
1674 
1675         case SPI_SETMOUSESONAR:
1676             return SpiSetBool(&gspv.bMouseSonar, uiParam, KEY_MOUSE, L"", fl);
1677 
1678         case SPI_GETMOUSECLICKLOCK:
1679             return SpiGetUserPref(UPM_CLICKLOCK, pvParam, fl);
1680 
1681         case SPI_SETMOUSECLICKLOCK:
1682             gspv.bMouseClickLock = PtrToUlong(pvParam);
1683             return SpiSetUserPref(UPM_CLICKLOCK, pvParam, fl);
1684 
1685         case SPI_GETMOUSEVANISH:
1686             return SpiGetInt(pvParam, &gspv.bMouseVanish, fl);
1687 
1688         case SPI_SETMOUSEVANISH:
1689             return SpiSetBool(&gspv.bMouseVanish, uiParam, KEY_MOUSE, L"", fl);
1690 
1691         case SPI_GETFLATMENU:
1692             return SpiGetUserPref(UPM_FLATMENU, pvParam, fl);
1693 
1694         case SPI_SETFLATMENU:
1695             return SpiSetUserPref(UPM_FLATMENU, pvParam, fl);
1696 
1697         case SPI_GETDROPSHADOW:
1698             return SpiGetUserPref(UPM_DROPSHADOW, pvParam, fl);
1699 
1700         case SPI_SETDROPSHADOW:
1701             return SpiSetUserPref(UPM_DROPSHADOW, pvParam, fl);
1702 
1703         case SPI_GETBLOCKSENDINPUTRESETS:
1704             return SpiGetInt(pvParam, &gspv.bBlockSendInputResets, fl);
1705 
1706         case SPI_SETBLOCKSENDINPUTRESETS:
1707             return SpiSetBool(&gspv.bBlockSendInputResets, uiParam, KEY_MOUSE, L"", fl);
1708 
1709 #if(_WIN32_WINNT >= 0x0600)
1710         case SPI_GETDISABLEOVERLAPPEDCONTENT:
1711             return SpiGetInt(pvParam, &gspv.bDisableOverlappedContent, fl);
1712 
1713         case SPI_SETDISABLEOVERLAPPEDCONTENT:
1714             return SpiSetBool(&gspv.bDisableOverlappedContent, uiParam, KEY_MOUSE, L"", fl);
1715 
1716         case SPI_GETCLIENTAREAANIMATION:
1717             return SpiGetInt(pvParam, &gspv.bClientAreaAnimation, fl);
1718 
1719         case SPI_SETCLIENTAREAANIMATION:
1720             return SpiSetBool(&gspv.bClientAreaAnimation, uiParam, KEY_MOUSE, L"", fl);
1721 
1722         case SPI_GETCLEARTYPE:
1723             return SpiGetInt(pvParam, &gspv.bClearType, fl);
1724 
1725         case SPI_SETCLEARTYPE:
1726             return SpiSetBool(&gspv.bClearType, uiParam, KEY_MOUSE, L"", fl);
1727 
1728         case SPI_GETSPEECHRECOGNITION:
1729             return SpiGetInt(pvParam, &gspv.bSpeechRecognition, fl);
1730 
1731         case SPI_SETSPEECHRECOGNITION:
1732             return SpiSetBool(&gspv.bSpeechRecognition, uiParam, KEY_MOUSE, L"", fl);
1733 #endif
1734 
1735         case SPI_GETFOREGROUNDLOCKTIMEOUT:
1736             return SpiGetInt(pvParam, &gspv.dwForegroundLockTimeout, fl);
1737 
1738         case SPI_SETFOREGROUNDLOCKTIMEOUT:
1739             return SpiSetInt(&gspv.dwForegroundLockTimeout, uiParam, KEY_MOUSE, L"", fl);
1740 
1741         case SPI_GETACTIVEWNDTRKTIMEOUT:
1742             return SpiGetInt(pvParam, &gspv.dwActiveTrackingTimeout, fl);
1743 
1744         case SPI_SETACTIVEWNDTRKTIMEOUT:
1745             return SpiSetInt(&gspv.dwActiveTrackingTimeout, uiParam, KEY_MOUSE, L"", fl);
1746 
1747         case SPI_GETFOREGROUNDFLASHCOUNT:
1748             return SpiGetInt(pvParam, &gspv.dwForegroundFlashCount, fl);
1749 
1750         case SPI_SETFOREGROUNDFLASHCOUNT:
1751             return SpiSetInt(&gspv.dwForegroundFlashCount, uiParam, KEY_MOUSE, L"", fl);
1752 
1753         case SPI_GETCARETWIDTH:
1754             return SpiGetInt(pvParam, &gspv.dwCaretWidth, fl);
1755 
1756         case SPI_SETCARETWIDTH:
1757             return SpiSetDWord(&gspv.dwCaretWidth, PtrToUlong(pvParam), KEY_DESKTOP, VAL_CARETWIDTH, fl);
1758 
1759         case SPI_GETMOUSECLICKLOCKTIME:
1760             return SpiGetInt(pvParam, &gspv.dwMouseClickLockTime, fl);
1761 
1762         case SPI_SETMOUSECLICKLOCKTIME:
1763             return SpiSetDWord(&gspv.dwMouseClickLockTime, uiParam, KEY_DESKTOP, VAL_CLICKLOCKTIME, fl);
1764 
1765         case SPI_GETFONTSMOOTHINGTYPE:
1766             return SpiGetInt(pvParam, &gspv.uiFontSmoothingType, fl);
1767 
1768         case SPI_SETFONTSMOOTHINGTYPE:
1769             return SpiSetDWord(&gspv.uiFontSmoothingType, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGTYPE, fl);
1770 
1771         case SPI_GETFONTSMOOTHINGCONTRAST:
1772             return SpiGetInt(pvParam, &gspv.uiFontSmoothingContrast, fl);
1773 
1774         case SPI_SETFONTSMOOTHINGCONTRAST:
1775             return SpiSetDWord(&gspv.uiFontSmoothingContrast, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGCONTRAST, fl);
1776 
1777         case SPI_GETFOCUSBORDERWIDTH:
1778             return SpiGetInt(pvParam, &gspv.uiFocusBorderWidth, fl);
1779 
1780         case SPI_SETFOCUSBORDERWIDTH:
1781             return SpiSetInt(&gspv.uiFocusBorderWidth, uiParam, KEY_MOUSE, L"", fl);
1782 
1783         case SPI_GETFOCUSBORDERHEIGHT:
1784             return SpiGetInt(pvParam, &gspv.uiFocusBorderHeight, fl);
1785 
1786         case SPI_SETFOCUSBORDERHEIGHT:
1787             return SpiSetInt(&gspv.uiFocusBorderHeight, uiParam, KEY_MOUSE, L"", fl);
1788 
1789         case SPI_GETFONTSMOOTHINGORIENTATION:
1790             return SpiGetInt(pvParam, &gspv.uiFontSmoothingOrientation, fl);
1791 
1792         case SPI_SETFONTSMOOTHINGORIENTATION:
1793             return SpiSetDWord(&gspv.uiFontSmoothingOrientation, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGORIENTATION, fl);
1794 
1795         /* The following are undocumented, but valid SPI values */
1796         case 0x1010:
1797         case 0x1011:
1798         case 0x1028:
1799         case 0x1029:
1800         case 0x102A:
1801         case 0x102B:
1802         case 0x102C:
1803         case 0x102D:
1804         case 0x102E:
1805         case 0x102F:
1806         case 0x1030:
1807         case 0x1031:
1808         case 0x1032:
1809         case 0x1033:
1810         case 0x1034:
1811         case 0x1035:
1812         case 0x1036:
1813         case 0x1037:
1814         case 0x1038:
1815         case 0x1039:
1816         case 0x103A:
1817         case 0x103B:
1818         case 0x103C:
1819         case 0x103D:
1820             ERR("Undocumented SPI value %x is unimplemented\n", uiAction);
1821             break;
1822 
1823         default:
1824             ERR("Invalid SPI value: %u\n", uiAction);
1825             EngSetLastError(ERROR_INVALID_PARAMETER);
1826             return 0;
1827     }
1828 
1829     return 0;
1830 }
1831 
1832 static BOOL
1833 SpiGetSetProbeBuffer(UINT uiAction, UINT uiParam, PVOID pvParam)
1834 {
1835     BOOL bToUser = TRUE;
1836     ULONG cbSize = 0;
1837 
1838     switch (uiAction)
1839     {
1840         case SPI_GETBEEP:
1841         case SPI_GETBORDER:
1842         case SPI_GETKEYBOARDSPEED:
1843         case SPI_GETSCREENSAVETIMEOUT:
1844         case SPI_GETSCREENSAVEACTIVE:
1845         case SPI_GETGRIDGRANULARITY:
1846         case SPI_GETKEYBOARDDELAY:
1847         case SPI_GETICONTITLEWRAP:
1848         case SPI_GETMENUDROPALIGNMENT:
1849         case SPI_GETFASTTASKSWITCH:
1850         case SPI_GETDRAGFULLWINDOWS:
1851         case SPI_GETSHOWSOUNDS:
1852         case SPI_GETKEYBOARDPREF:
1853         case SPI_GETSCREENREADER:
1854         case SPI_GETFONTSMOOTHING:
1855         case SPI_GETLOWPOWERTIMEOUT:
1856         case SPI_GETPOWEROFFTIMEOUT:
1857         case SPI_GETLOWPOWERACTIVE:
1858         case SPI_GETPOWEROFFACTIVE:
1859         case SPI_GETMOUSETRAILS:
1860         case SPI_GETSNAPTODEFBUTTON:
1861         case SPI_GETMOUSEHOVERWIDTH:
1862         case SPI_GETMOUSEHOVERHEIGHT:
1863         case SPI_GETMOUSEHOVERTIME:
1864         case SPI_GETWHEELSCROLLLINES:
1865         case SPI_GETMENUSHOWDELAY:
1866 #if (_WIN32_WINNT >= 0x0600)
1867         case SPI_GETWHEELSCROLLCHARS:
1868 #endif
1869         case SPI_GETSHOWIMEUI:
1870         case SPI_GETMOUSESPEED:
1871         case SPI_GETSCREENSAVERRUNNING:
1872 #if(WINVER >= 0x0600)
1873         case SPI_GETSCREENSAVESECURE:
1874 #endif
1875         case SPI_GETACTIVEWINDOWTRACKING:
1876         case SPI_GETMENUANIMATION:
1877         case SPI_GETCOMBOBOXANIMATION:
1878         case SPI_GETLISTBOXSMOOTHSCROLLING:
1879         case SPI_GETGRADIENTCAPTIONS:
1880         case SPI_GETKEYBOARDCUES:
1881         case SPI_GETACTIVEWNDTRKZORDER:
1882         case SPI_GETHOTTRACKING:
1883         case SPI_GETMENUFADE:
1884         case SPI_GETSELECTIONFADE:
1885         case SPI_GETTOOLTIPANIMATION:
1886         case SPI_GETTOOLTIPFADE:
1887         case SPI_GETCURSORSHADOW:
1888         case SPI_GETUIEFFECTS:
1889         case SPI_GETMOUSESONAR:
1890         case SPI_GETMOUSECLICKLOCK:
1891         case SPI_GETMOUSEVANISH:
1892         case SPI_GETFLATMENU:
1893         case SPI_GETDROPSHADOW:
1894         case SPI_GETBLOCKSENDINPUTRESETS:
1895 #if(_WIN32_WINNT >= 0x0600)
1896         case SPI_GETDISABLEOVERLAPPEDCONTENT:
1897         case SPI_GETCLIENTAREAANIMATION:
1898         case SPI_GETCLEARTYPE:
1899         case SPI_GETSPEECHRECOGNITION:
1900 #endif
1901         case SPI_GETFOREGROUNDLOCKTIMEOUT:
1902         case SPI_GETACTIVEWNDTRKTIMEOUT:
1903         case SPI_GETFOREGROUNDFLASHCOUNT:
1904         case SPI_GETCARETWIDTH:
1905         case SPI_GETMOUSECLICKLOCKTIME:
1906         case SPI_GETFONTSMOOTHINGTYPE:
1907         case SPI_GETFONTSMOOTHINGCONTRAST:
1908         case SPI_GETFOCUSBORDERWIDTH:
1909         case SPI_GETFOCUSBORDERHEIGHT:
1910         case SPI_GETFONTSMOOTHINGORIENTATION:
1911             cbSize = sizeof(INT);
1912             break;
1913 
1914         case SPI_ICONHORIZONTALSPACING:
1915         case SPI_ICONVERTICALSPACING:
1916             if (pvParam) cbSize = sizeof(INT);
1917             break;
1918 
1919         case SPI_GETMOUSE:
1920             cbSize = 3 * sizeof(INT);
1921             break;
1922 
1923         case SPI_GETDESKWALLPAPER:
1924             cbSize = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
1925             break;
1926 
1927         case SPI_GETICONTITLELOGFONT:
1928             cbSize = sizeof(LOGFONTW);
1929             break;
1930 
1931         case SPI_GETNONCLIENTMETRICS:
1932             cbSize = sizeof(NONCLIENTMETRICSW);
1933             break;
1934 
1935         case SPI_GETMINIMIZEDMETRICS:
1936             cbSize = sizeof(MINIMIZEDMETRICS);
1937             break;
1938 
1939         case SPI_GETICONMETRICS:
1940             cbSize = sizeof(ICONMETRICSW);
1941             break;
1942 
1943         case SPI_GETWORKAREA:
1944             cbSize = sizeof(RECTL);
1945             break;
1946 
1947         case SPI_GETFILTERKEYS:
1948             cbSize = sizeof(FILTERKEYS);
1949             break;
1950 
1951         case SPI_GETTOGGLEKEYS:
1952             cbSize = sizeof(TOGGLEKEYS);
1953             break;
1954 
1955         case SPI_GETMOUSEKEYS:
1956             cbSize = sizeof(MOUSEKEYS);
1957             break;
1958 
1959         case SPI_GETSTICKYKEYS:
1960             cbSize = sizeof(STICKYKEYS);
1961             break;
1962 
1963         case SPI_GETACCESSTIMEOUT:
1964             cbSize = sizeof(ACCESSTIMEOUT);
1965             break;
1966 
1967         case SPI_GETSERIALKEYS:
1968             cbSize = sizeof(SERIALKEYS);
1969             break;
1970 
1971         case SPI_GETSOUNDSENTRY:
1972             cbSize = sizeof(SOUNDSENTRYW);
1973             break;
1974 
1975         case SPI_GETHIGHCONTRAST:
1976             cbSize = sizeof(HIGHCONTRASTW);
1977             break;
1978 
1979         case SPI_GETANIMATION:
1980             cbSize = sizeof(ANIMATIONINFO);
1981             break;
1982 
1983         case SPI_GETDEFAULTINPUTLANG:
1984             cbSize = sizeof(HKL);
1985             break;
1986 
1987 #if(WINVER >= 0x0600)
1988         case SPI_GETAUDIODESCRIPTION:
1989             cbSize = sizeof(AUDIODESCRIPTION);
1990             break;
1991 #endif
1992 
1993         case SPI_SETMOUSE:
1994             cbSize = 3 * sizeof(INT);
1995             bToUser = FALSE;
1996             break;
1997 
1998         case SPI_SETICONTITLELOGFONT:
1999             cbSize = sizeof(LOGFONTW);
2000             bToUser = FALSE;
2001             break;
2002 
2003         case SPI_SETNONCLIENTMETRICS:
2004             cbSize = sizeof(NONCLIENTMETRICSW);
2005             bToUser = FALSE;
2006             break;
2007 
2008         case SPI_SETMINIMIZEDMETRICS:
2009             cbSize = sizeof(MINIMIZEDMETRICS);
2010             bToUser = FALSE;
2011             break;
2012 
2013         case SPI_SETICONMETRICS:
2014             cbSize = sizeof(ICONMETRICSW);
2015             bToUser = FALSE;
2016             break;
2017 
2018         case SPI_SETWORKAREA:
2019             cbSize = sizeof(RECTL);
2020             bToUser = FALSE;
2021             break;
2022 
2023         case SPI_SETFILTERKEYS:
2024             cbSize = sizeof(FILTERKEYS);
2025             bToUser = FALSE;
2026             break;
2027 
2028         case SPI_SETTOGGLEKEYS:
2029             cbSize = sizeof(TOGGLEKEYS);
2030             bToUser = FALSE;
2031             break;
2032 
2033         case SPI_SETMOUSEKEYS:
2034             cbSize = sizeof(MOUSEKEYS);
2035             bToUser = FALSE;
2036             break;
2037 
2038         case SPI_SETSTICKYKEYS:
2039             cbSize = sizeof(STICKYKEYS);
2040             bToUser = FALSE;
2041             break;
2042 
2043         case SPI_SETACCESSTIMEOUT:
2044             cbSize = sizeof(ACCESSTIMEOUT);
2045             bToUser = FALSE;
2046             break;
2047 
2048         case SPI_SETSERIALKEYS:
2049             cbSize = sizeof(SERIALKEYS);
2050             bToUser = FALSE;
2051             break;
2052 
2053         case SPI_SETSOUNDSENTRY:
2054             cbSize = sizeof(SOUNDSENTRYW);
2055             bToUser = FALSE;
2056             break;
2057 
2058         case SPI_SETHIGHCONTRAST:
2059             cbSize = sizeof(HIGHCONTRASTW);
2060             bToUser = FALSE;
2061             break;
2062 
2063         case SPI_SETANIMATION:
2064             cbSize = sizeof(ANIMATIONINFO);
2065             bToUser = FALSE;
2066             break;
2067 
2068         case SPI_SETDEFAULTINPUTLANG:
2069             cbSize = sizeof(HKL);
2070             bToUser = FALSE;
2071             break;
2072 
2073         case SPI_SETMOUSESPEED:
2074             cbSize = sizeof(INT);
2075             bToUser = FALSE;
2076             break;
2077     }
2078 
2079     if (cbSize)
2080     {
2081         _SEH2_TRY
2082         {
2083             if (bToUser)
2084             {
2085                 ProbeForWrite(pvParam, cbSize, sizeof(UCHAR));
2086             }
2087             else
2088             {
2089                 ProbeForRead(pvParam, cbSize, sizeof(UCHAR));
2090             }
2091         }
2092         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2093         {
2094             _SEH2_YIELD(return FALSE);
2095         }
2096         _SEH2_END;
2097     }
2098 
2099     return TRUE;
2100 }
2101 
2102 BOOL
2103 FASTCALL
2104 UserSystemParametersInfo(
2105     UINT uiAction,
2106     UINT uiParam,
2107     PVOID pvParam,
2108     UINT fWinIni)
2109 {
2110     ULONG_PTR ulResult;
2111     PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
2112 
2113     ASSERT(ppi);
2114 
2115     if (!gbSpiInitialized)
2116     {
2117         KeRosDumpStackFrames(NULL, 20);
2118         //ASSERT(FALSE);
2119         return FALSE;
2120     }
2121 
2122     /* Get a pointer to the current Windowstation */
2123     if (!ppi->prpwinsta)
2124     {
2125         ERR("UserSystemParametersInfo called without active window station.\n");
2126         //ASSERT(FALSE);
2127         //return FALSE;
2128     }
2129 
2130     if ((fWinIni & SPIF_PROTECT) && !SpiGetSetProbeBuffer(uiAction, uiParam, pvParam))
2131     {
2132         EngSetLastError(ERROR_NOACCESS);
2133         return FALSE;
2134     }
2135 
2136     /* Do the actual operation */
2137     ulResult = SpiGetSet(uiAction, uiParam, pvParam, fWinIni);
2138 
2139     /* Did we change something? */
2140     if (ulResult > 1)
2141     {
2142         SpiFixupValues();
2143 
2144         /* Update system metrics */
2145         InitMetrics();
2146 
2147         /* Send notification to toplevel windows, if requested */
2148         if (fWinIni & SPIF_SENDCHANGE)
2149         {
2150             /* Send WM_SETTINGCHANGE to all toplevel windows */
2151             co_IntSendMessageTimeout(HWND_BROADCAST,
2152                                      WM_SETTINGCHANGE,
2153                                      (WPARAM)uiAction,
2154                                      (LPARAM)ulResult,
2155                                      SMTO_NORMAL,
2156                                      100,
2157                                      &ulResult);
2158         }
2159         ulResult = 1;
2160     }
2161 
2162     return ulResult;
2163 }
2164 
2165 BOOL
2166 APIENTRY
2167 NtUserSystemParametersInfo(
2168     UINT uiAction,
2169     UINT uiParam,
2170     PVOID pvParam,
2171     UINT fWinIni)
2172 {
2173     BOOL bResult;
2174 
2175     TRACE("Enter NtUserSystemParametersInfo(%u)\n", uiAction);
2176     UserEnterExclusive();
2177 
2178     // FIXME: Get rid of the flags and only use this from um. kernel can access data directly.
2179     /* Set UM memory protection flag */
2180     fWinIni |= SPIF_PROTECT;
2181 
2182     /* Call internal function */
2183     bResult = UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
2184 
2185     TRACE("Leave NtUserSystemParametersInfo, returning %d\n", bResult);
2186     UserLeave();
2187 
2188     return bResult;
2189 }
2190 
2191 /* EOF */
2192