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