[WIN32KNT_APITEST]
[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 RtlZeroMemory(&gspv, 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)
428 {
429 NTSTATUS Status = STATUS_SUCCESS;
430
431 if (bProtect)
432 {
433 _SEH2_TRY
434 {
435 RtlCopyMemory(pvDst, pvSrc, cbSize);
436 }
437 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
438 {
439 Status = _SEH2_GetExceptionCode();
440 }
441 _SEH2_END;
442 }
443 else
444 {
445 RtlCopyMemory(pvDst, pvSrc, cbSize);
446 }
447
448 if (!NT_SUCCESS(Status))
449 {
450 SetLastNtError(Status);
451 ERR("SpiMemCopy failed, pvDst=%p, pvSrc=%p, bProtect=%d\n", pvDst, pvSrc, bProtect);
452 }
453
454 return NT_SUCCESS(Status);
455 }
456
457 static inline
458 UINT_PTR
459 SpiGet(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
460 {
461 REQ_INTERACTIVE_WINSTA(ERROR_ACCESS_DENIED);
462 return SpiMemCopy(pvParam, pvData, cbSize, fl & SPIF_PROTECT);
463 }
464
465 static inline
466 UINT_PTR
467 SpiSet(PVOID pvData, PVOID pvParam, ULONG cbSize, FLONG fl)
468 {
469 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
470 return SpiMemCopy(pvData, pvParam, cbSize, fl & SPIF_PROTECT);
471 }
472
473 static inline
474 UINT_PTR
475 SpiGetEx(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
476 {
477 ULONG cbBufSize;
478 /* Get the cbSite member from UM memory */
479 if (!SpiSet(&cbBufSize, pvParam, sizeof(ULONG), fl))
480 return 0;
481 /* Verify the correct size */
482 if (cbBufSize != cbSize)
483 return 0;
484 return SpiGet(pvParam, pvData, cbSize, fl);
485 }
486
487 static inline
488 UINT_PTR
489 SpiGetInt(PVOID pvParam, PVOID piValue, FLONG fl)
490 {
491 return SpiGet(pvParam, piValue, sizeof(INT), fl);
492 }
493
494 static inline
495 UINT_PTR
496 SpiSetYesNo(BOOL *pbData, BOOL bValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
497 {
498 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
499 *pbData = bValue ? TRUE : FALSE;
500 if (fl & SPIF_UPDATEINIFILE)
501 {
502 SpiStoreSz(pwszKey, pwszValue, bValue ? L"Yes" : L"No");
503 }
504 return (UINT_PTR)pwszKey;
505 }
506
507 static inline
508 UINT_PTR
509 SpiSetBool(BOOL *pbData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
510 {
511 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
512 *pbData = iValue ? TRUE : FALSE;
513 if (fl & SPIF_UPDATEINIFILE)
514 {
515 SpiStoreSzInt(pwszKey, pwszValue, iValue);
516 }
517 return (UINT_PTR)pwszKey;
518 }
519
520 static inline
521 UINT_PTR
522 SpiSetDWord(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
523 {
524 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
525 *(INT*)pvData = iValue;
526 if (fl & SPIF_UPDATEINIFILE)
527 {
528 SpiStoreDWord(pwszKey, pwszValue, iValue);
529 }
530 return (UINT_PTR)pwszKey;
531 }
532
533 static inline
534 UINT_PTR
535 SpiSetInt(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
536 {
537 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
538 *(INT*)pvData = iValue;
539 if (fl & SPIF_UPDATEINIFILE)
540 {
541 SpiStoreSzInt(pwszKey, pwszValue, iValue);
542 }
543 return (UINT_PTR)pwszKey;
544 }
545
546 static inline
547 UINT_PTR
548 SpiSetMetric(PVOID pvData, INT iValue, PCWSTR pwszValue, FLONG fl)
549 {
550 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
551 *(INT*)pvData = iValue;
552 if (fl & SPIF_UPDATEINIFILE)
553 {
554 SpiStoreMetric(pwszValue, iValue);
555 }
556 return (UINT_PTR)KEY_METRIC;
557 }
558
559 static inline
560 UINT_PTR
561 SpiSetUserPref(DWORD dwMask, PVOID pvValue, FLONG fl)
562 {
563 DWORD dwRegMask;
564 BOOL bValue = (BOOL)pvValue;
565
566 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
567
568 /* Set or clear bit according to bValue */
569 gspv.dwUserPrefMask = bValue ? gspv.dwUserPrefMask | dwMask :
570 gspv.dwUserPrefMask & ~dwMask;
571
572 if (fl & SPIF_UPDATEINIFILE)
573 {
574 /* Read current value */
575 if (!RegReadUserSetting(KEY_DESKTOP,
576 VAL_USERPREFMASK,
577 REG_BINARY,
578 &dwRegMask,
579 sizeof(DWORD)))
580 {
581 WARN("Failed to read UserPreferencesMask setting\n");
582 dwRegMask = 0;
583 }
584
585 /* Set or clear bit according to bValue */
586 dwRegMask = bValue ? (dwRegMask | dwMask) : (dwRegMask & ~dwMask);
587
588 /* write back value */
589 RegWriteUserSetting(KEY_DESKTOP,
590 VAL_USERPREFMASK,
591 REG_BINARY,
592 &dwRegMask,
593 sizeof(DWORD));
594 }
595
596 return (UINT_PTR)KEY_DESKTOP;
597 }
598
599 static inline
600 UINT_PTR
601 SpiGetUserPref(DWORD dwMask, PVOID pvParam, FLONG fl)
602 {
603 INT iValue = gspv.dwUserPrefMask & dwMask ? 1 : 0;
604 return SpiGetInt(pvParam, &iValue, fl);
605 }
606
607 static
608 UINT_PTR
609 SpiSetWallpaper(PVOID pvParam, FLONG fl)
610 {
611 UNICODE_STRING ustr;
612 WCHAR awc[MAX_PATH];
613 BOOL bResult;
614 HBITMAP hbmp, hOldBitmap;
615 SURFACE *psurfBmp;
616 ULONG ulTile, ulStyle;
617
618 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
619
620 if (!pvParam)
621 {
622 /* FIXME: Reset Wallpaper to registry value */
623 return (UINT_PTR)KEY_DESKTOP;
624 }
625
626 /* Capture UNICODE_STRING */
627 bResult = SpiMemCopy(&ustr, pvParam, sizeof(ustr), fl & SPIF_PROTECT);
628 if (!bResult) return 0;
629 if (ustr.Length > MAX_PATH * sizeof(WCHAR))
630 return 0;
631
632 /* Copy the string buffer name */
633 bResult = SpiMemCopy(gspv.awcWallpaper, ustr.Buffer, ustr.Length, fl & SPIF_PROTECT);
634 if (!bResult) return 0;
635
636 /* Update the UNICODE_STRING */
637 gspv.ustrWallpaper.Buffer = gspv.awcWallpaper;
638 gspv.ustrWallpaper.MaximumLength = MAX_PATH * sizeof(WCHAR);
639 gspv.ustrWallpaper.Length = ustr.Length;
640 gspv.awcWallpaper[ustr.Length / sizeof(WCHAR)] = 0;
641
642 TRACE("SpiSetWallpaper, name=%S\n", gspv.awcWallpaper);
643
644 /* Update registry */
645 if (fl & SPIF_UPDATEINIFILE)
646 {
647 SpiStoreSz(KEY_DESKTOP, L"Wallpaper", gspv.awcWallpaper);
648 }
649
650 /* Got a filename? */
651 if (gspv.awcWallpaper[0] != 0)
652 {
653 /* Convert file name to nt file name */
654 ustr.Buffer = awc;
655 ustr.MaximumLength = MAX_PATH * sizeof(WCHAR);
656 ustr.Length = 0;
657 if (!W32kDosPathNameToNtPathName(gspv.awcWallpaper, &ustr))
658 {
659 ERR("RtlDosPathNameToNtPathName_U failed\n");
660 return 0;
661 }
662
663 /* Load the Bitmap */
664 hbmp = UserLoadImage(ustr.Buffer);
665 if (!hbmp)
666 {
667 ERR("UserLoadImage failed\n");
668 return 0;
669 }
670
671 /* Try to get the size of the wallpaper */
672 if(!(psurfBmp = SURFACE_ShareLockSurface(hbmp)))
673 {
674 GreDeleteObject(hbmp);
675 return 0;
676 }
677
678 gspv.cxWallpaper = psurfBmp->SurfObj.sizlBitmap.cx;
679 gspv.cyWallpaper = psurfBmp->SurfObj.sizlBitmap.cy;
680 gspv.WallpaperMode = wmCenter;
681
682 SURFACE_ShareUnlockSurface(psurfBmp);
683
684 /* Change the bitmap's ownership */
685 GreSetObjectOwner(hbmp, GDI_OBJ_HMGR_PUBLIC);
686
687 /* Yes, Windows really loads the current setting from the registry. */
688 ulTile = SpiLoadInt(KEY_DESKTOP, L"TileWallpaper", 0);
689 ulStyle = SpiLoadInt(KEY_DESKTOP, L"WallpaperStyle", 0);
690 TRACE("SpiSetWallpaper: ulTile=%lu, ulStyle=%lu\n", ulTile, ulStyle);
691
692 /* Check the values we found in the registry */
693 if(ulTile && !ulStyle)
694 {
695 gspv.WallpaperMode = wmTile;
696 }
697 else if(!ulTile && ulStyle == 2)
698 {
699 gspv.WallpaperMode = wmStretch;
700 }
701 }
702 else
703 {
704 /* Remove wallpaper */
705 gspv.cxWallpaper = 0;
706 gspv.cyWallpaper = 0;
707 hbmp = 0;
708 }
709
710 /* Take care of the old wallpaper, if any */
711 hOldBitmap = gspv.hbmWallpaper;
712 if(hOldBitmap != NULL)
713 {
714 /* Delete the old wallpaper */
715 GreSetObjectOwner(hOldBitmap, GDI_OBJ_HMGR_POWNED);
716 GreDeleteObject(hOldBitmap);
717 }
718
719 /* Set the new wallpaper */
720 gspv.hbmWallpaper = hbmp;
721
722 NtUserRedrawWindow(UserGetShellWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
723
724
725 return (UINT_PTR)KEY_DESKTOP;
726 }
727
728 static BOOL
729 SpiNotifyNCMetricsChanged(VOID)
730 {
731 PWND pwndDesktop, pwndCurrent;
732 HWND *ahwnd;
733 USER_REFERENCE_ENTRY Ref;
734 int i;
735
736 pwndDesktop = UserGetDesktopWindow();
737 ASSERT(pwndDesktop);
738
739 ahwnd = IntWinListChildren(pwndDesktop);
740 if(!ahwnd)
741 return FALSE;
742
743 for (i = 0; ahwnd[i]; i++)
744 {
745 pwndCurrent = UserGetWindowObject(ahwnd[i]);
746 if(!pwndCurrent)
747 continue;
748
749 UserRefObjectCo(pwndCurrent, &Ref);
750 co_WinPosSetWindowPos(pwndCurrent, 0, pwndCurrent->rcWindow.left,pwndCurrent->rcWindow.top,
751 pwndCurrent->rcWindow.right-pwndCurrent->rcWindow.left
752 ,pwndCurrent->rcWindow.bottom - pwndCurrent->rcWindow.top,
753 SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|
754 SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW);
755 UserDerefObjectCo(pwndCurrent);
756 }
757
758 ExFreePoolWithTag(ahwnd, USERTAG_WINDOWLIST);
759
760 return TRUE;
761 }
762
763 static
764 UINT_PTR
765 SpiGetSet(UINT uiAction, UINT uiParam, PVOID pvParam, FLONG fl)
766 {
767 switch (uiAction)
768 {
769 case SPI_GETBEEP:
770 return SpiGetInt(pvParam, &gspv.bBeep, fl);
771
772 case SPI_SETBEEP:
773 return SpiSetYesNo(&gspv.bBeep, uiParam, KEY_SOUND, VAL_BEEP, fl);
774
775 case SPI_GETMOUSE:
776 return SpiGet(pvParam, &gspv.caiMouse, 3 * sizeof(INT), fl);
777
778 case SPI_SETMOUSE:
779 if (!SpiSet(&gspv.caiMouse, pvParam, 3 * sizeof(INT), fl))
780 return 0;
781 if (fl & SPIF_UPDATEINIFILE)
782 {
783 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE1, gspv.caiMouse.FirstThreshold);
784 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE2, gspv.caiMouse.SecondThreshold);
785 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE3, gspv.caiMouse.Acceleration);
786 }
787 return (UINT_PTR)KEY_MOUSE;
788
789 case SPI_GETBORDER:
790 return SpiGetInt(pvParam, &gspv.ncm.iBorderWidth, fl);
791
792 case SPI_SETBORDER:
793 uiParam = max(uiParam, 1);
794 return SpiSetInt(&gspv.ncm.iBorderWidth, uiParam, KEY_METRIC, VAL_BORDER, fl);
795
796 case SPI_GETKEYBOARDSPEED:
797 return SpiGetInt(pvParam, &gspv.dwKbdSpeed, fl);
798
799 case SPI_SETKEYBOARDSPEED:
800 return SpiSetInt(&gspv.dwKbdSpeed, uiParam, KEY_KBD, VAL_KBDSPD, fl);
801
802 case SPI_LANGDRIVER:
803 ERR("SPI_LANGDRIVER is unimplemented\n");
804 break;
805
806 case SPI_GETSCREENSAVETIMEOUT:
807 return SpiGetInt(pvParam, &gspv.iScrSaverTimeout, fl);
808
809 case SPI_SETSCREENSAVETIMEOUT:
810 return SpiSetInt(&gspv.iScrSaverTimeout, uiParam, KEY_DESKTOP, VAL_SCRTO, fl);
811
812 case SPI_GETSCREENSAVEACTIVE:
813 return SpiGetInt(pvParam, &gspv.bScrSaverActive, fl);
814
815 case SPI_SETSCREENSAVEACTIVE:
816 return SpiSetInt(&gspv.bScrSaverActive, uiParam, KEY_DESKTOP, VAL_SCRACT, fl);
817
818 case SPI_GETGRIDGRANULARITY:
819 return SpiGetInt(pvParam, &gspv.uiGridGranularity, fl);
820
821 case SPI_SETGRIDGRANULARITY:
822 return SpiSetInt(&gspv.uiGridGranularity, uiParam, KEY_DESKTOP, VAL_GRID, fl);
823
824 case SPI_GETDESKWALLPAPER:
825 uiParam = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
826 return SpiGet(pvParam, gspv.awcWallpaper, uiParam, fl);
827
828 case SPI_SETDESKWALLPAPER:
829 return SpiSetWallpaper(pvParam, fl);
830
831 case SPI_SETDESKPATTERN:
832 ERR("SPI_SETDESKPATTERN is unimplemented\n");
833 break;
834
835 case SPI_GETKEYBOARDDELAY:
836 return SpiGetInt(pvParam, &gspv.iKbdDelay, fl);
837
838 case SPI_SETKEYBOARDDELAY:
839 return SpiSetInt(&gspv.iKbdDelay, uiParam, KEY_KBD, VAL_KBDDELAY, fl);
840
841 case SPI_ICONHORIZONTALSPACING:
842 if (pvParam)
843 {
844 return SpiGetInt(pvParam, &gspv.im.iHorzSpacing, fl);
845 }
846 uiParam = max(uiParam, 32);
847 return SpiSetMetric(&gspv.im.iHorzSpacing, uiParam, VAL_ICONSPC, fl);
848
849 case SPI_ICONVERTICALSPACING:
850 if (pvParam)
851 {
852 return SpiGetInt(pvParam, &gspv.im.iVertSpacing, fl);
853 }
854 uiParam = max(uiParam, 32);
855 return SpiSetMetric(&gspv.im.iVertSpacing, uiParam, VAL_ICONVSPC, fl);
856
857 case SPI_GETICONTITLEWRAP:
858 return SpiGetInt(pvParam, &gspv.im.iTitleWrap, fl);
859
860 case SPI_SETICONTITLEWRAP:
861 return SpiSetInt(&gspv.im.iTitleWrap, uiParam, KEY_METRIC, VAL_ITWRAP, fl);
862
863 case SPI_GETMENUDROPALIGNMENT:
864 return SpiGetInt(pvParam, &gspv.bMenuDropAlign, fl);
865
866 case SPI_SETMENUDROPALIGNMENT:
867 return SpiSetBool(&gspv.bMenuDropAlign, uiParam, KEY_MDALIGN, VAL_MDALIGN, fl);
868
869 case SPI_SETDOUBLECLKWIDTH:
870 return SpiSetInt(&gspv.iDblClickWidth, uiParam, KEY_MOUSE, VAL_DBLCLKWIDTH, fl);
871
872 case SPI_SETDOUBLECLKHEIGHT:
873 return SpiSetInt(&gspv.iDblClickHeight, uiParam, KEY_MOUSE, VAL_DBLCLKHEIGHT, fl);
874
875 case SPI_GETICONTITLELOGFONT:
876 return SpiGet(pvParam, &gspv.im.lfFont, sizeof(LOGFONTW), fl);
877
878 case SPI_SETICONTITLELOGFONT:
879 if (!SpiSet(&gspv.im.lfFont, pvParam, sizeof(LOGFONTW), fl))
880 return 0;
881 if (fl & SPIF_UPDATEINIFILE)
882 {
883 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
884 }
885 return (UINT_PTR)KEY_METRIC;
886
887 case SPI_SETDOUBLECLICKTIME:
888 return SpiSetInt(&gspv.iDblClickTime, uiParam, KEY_MOUSE, VAL_DBLCLKTIME, fl);
889
890 case SPI_SETMOUSEBUTTONSWAP:
891 return SpiSetInt(&gspv.bMouseBtnSwap, uiParam, KEY_MOUSE, VAL_SWAP, fl);
892
893 case SPI_GETFASTTASKSWITCH:
894 return SpiGetInt(pvParam, &gspv.bFastTaskSwitch, fl);
895
896 case SPI_SETFASTTASKSWITCH:
897 /* According to Winetest this one is unimplemented */
898 return 1;
899
900 case SPI_GETDRAGFULLWINDOWS:
901 return SpiGetInt(pvParam, &gspv.bDragFullWindows, fl);
902
903 case SPI_SETDRAGFULLWINDOWS:
904 return SpiSetInt(&gspv.bDragFullWindows, uiParam, KEY_DESKTOP, VAL_DRAG, fl);
905
906 case SPI_GETNONCLIENTMETRICS:
907 {
908 LPNONCLIENTMETRICSW metrics = (LPNONCLIENTMETRICSW)pvParam;
909
910 if (uiParam != 0 && uiParam != sizeof(NONCLIENTMETRICSW))
911 return 0;
912
913 if (!metrics || metrics->cbSize != sizeof(NONCLIENTMETRICSW))
914 return 0;
915
916 return SpiGet(pvParam, &gspv.ncm, sizeof(NONCLIENTMETRICSW), fl);
917 }
918
919 case SPI_SETNONCLIENTMETRICS:
920 {
921 LPNONCLIENTMETRICSW metrics = (LPNONCLIENTMETRICSW)pvParam;
922
923 if (uiParam != 0 && uiParam != sizeof(NONCLIENTMETRICSW))
924 return 0;
925
926 if (!metrics || metrics->cbSize != sizeof(NONCLIENTMETRICSW))
927 return 0;
928
929 if (!SpiSet(&gspv.ncm, pvParam, sizeof(NONCLIENTMETRICSW), fl))
930 return 0;
931
932 if (fl & SPIF_UPDATEINIFILE)
933 {
934 SpiStoreMetric(VAL_BORDER, gspv.ncm.iBorderWidth);
935 SpiStoreMetric(L"ScrollWidth", gspv.ncm.iScrollWidth);
936 SpiStoreMetric(L"ScrollHeight", gspv.ncm.iScrollHeight);
937 SpiStoreMetric(L"CaptionWidth", gspv.ncm.iCaptionWidth);
938 SpiStoreMetric(L"CaptionHeight", gspv.ncm.iCaptionHeight);
939 SpiStoreMetric(L"SmCaptionWidth", gspv.ncm.iSmCaptionWidth);
940 SpiStoreMetric(L"SmCaptionHeight", gspv.ncm.iSmCaptionHeight);
941 SpiStoreMetric(L"MenuWidth", gspv.ncm.iMenuWidth);
942 SpiStoreMetric(L"MenuHeight", gspv.ncm.iMenuHeight);
943 #if (WINVER >= 0x0600)
944 SpiStoreMetric(L"PaddedBorderWidth", gspv.ncm.iPaddedBorderWidth);
945 #endif
946 SpiStoreFont(L"CaptionFont", &gspv.ncm.lfCaptionFont);
947 SpiStoreFont(L"SmCaptionFont", &gspv.ncm.lfSmCaptionFont);
948 SpiStoreFont(L"MenuFont", &gspv.ncm.lfMenuFont);
949 SpiStoreFont(L"StatusFont", &gspv.ncm.lfStatusFont);
950 SpiStoreFont(L"MessageFont", &gspv.ncm.lfMessageFont);
951 }
952
953 if(!SpiNotifyNCMetricsChanged())
954 return 0;
955
956 return (UINT_PTR)KEY_METRIC;
957 }
958
959 case SPI_GETMINIMIZEDMETRICS:
960 {
961 LPMINIMIZEDMETRICS metrics = (LPMINIMIZEDMETRICS)pvParam;
962
963 if (uiParam != 0 && uiParam != sizeof(MINIMIZEDMETRICS))
964 return 0;
965
966 if (!metrics || metrics->cbSize != sizeof(MINIMIZEDMETRICS))
967 return 0;
968
969 return SpiGet(pvParam, &gspv.mm, sizeof(MINIMIZEDMETRICS), fl);
970 }
971
972 case SPI_SETMINIMIZEDMETRICS:
973 {
974 LPMINIMIZEDMETRICS metrics = (LPMINIMIZEDMETRICS)pvParam;
975
976 if (uiParam != 0 && uiParam != sizeof(MINIMIZEDMETRICS))
977 return 0;
978
979 if (!metrics || metrics->cbSize != sizeof(MINIMIZEDMETRICS))
980 return 0;
981
982 if (!SpiSet(&gspv.mm, pvParam, sizeof(MINIMIZEDMETRICS), fl))
983 return 0;
984
985 gspv.mm.iWidth = max(0, gspv.mm.iWidth);
986 gspv.mm.iHorzGap = max(0, gspv.mm.iHorzGap);
987 gspv.mm.iVertGap = max(0, gspv.mm.iVertGap);
988 gspv.mm.iArrange = gspv.mm.iArrange & 0xf;
989
990 if (fl & SPIF_UPDATEINIFILE)
991 {
992 SpiStoreMetric(L"MinWidth", gspv.mm.iWidth);
993 SpiStoreMetric(L"MinHorzGap", gspv.mm.iHorzGap);
994 SpiStoreMetric(L"MinVertGap", gspv.mm.iVertGap);
995 SpiStoreMetric(L"MinArrange", gspv.mm.iArrange);
996 }
997
998 return (UINT_PTR)KEY_METRIC;
999 }
1000
1001 case SPI_GETICONMETRICS:
1002 {
1003 LPICONMETRICSW IconMetrics = (LPICONMETRICSW)pvParam;
1004
1005 if (uiParam != 0 && uiParam != sizeof(ICONMETRICSW))
1006 return 0;
1007
1008 if (!IconMetrics || IconMetrics->cbSize != sizeof(ICONMETRICSW))
1009 return 0;
1010
1011 return SpiGet(pvParam, &gspv.im, sizeof(ICONMETRICSW), fl);
1012 }
1013
1014 case SPI_SETICONMETRICS:
1015 {
1016 LPICONMETRICS IconMetrics = (LPICONMETRICS)pvParam;
1017
1018 if (uiParam != 0 && uiParam != sizeof(ICONMETRICS))
1019 return 0;
1020
1021 if (!IconMetrics || IconMetrics->cbSize != sizeof(ICONMETRICS))
1022 return 0;
1023
1024 if (!SpiSet(&gspv.im, pvParam, sizeof(ICONMETRICS), fl))
1025 return 0;
1026
1027 if (fl & SPIF_UPDATEINIFILE)
1028 {
1029 SpiStoreMetric(VAL_ICONSPC, gspv.im.iHorzSpacing);
1030 SpiStoreMetric(VAL_ICONVSPC, gspv.im.iVertSpacing);
1031 SpiStoreMetric(VAL_ITWRAP, gspv.im.iTitleWrap);
1032 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
1033 }
1034 return (UINT_PTR)KEY_METRIC;
1035 }
1036
1037 case SPI_GETWORKAREA:
1038 {
1039 PMONITOR pmonitor = UserGetPrimaryMonitor();
1040
1041 if(!pmonitor)
1042 return 0;
1043
1044 return SpiGet(pvParam, &pmonitor->rcWork, sizeof(RECTL), fl);
1045 }
1046
1047 case SPI_SETWORKAREA:
1048 {
1049 /* FIXME: We should set the work area of the monitor
1050 that contains the specified rectangle */
1051 PMONITOR pmonitor = UserGetPrimaryMonitor();
1052 RECT rcWorkArea;
1053
1054 if(!pmonitor)
1055 return 0;
1056
1057 if (!SpiSet(&rcWorkArea, pvParam, sizeof(RECTL), fl))
1058 return 0;
1059
1060 /* Verify the new values */
1061 if (rcWorkArea.left < 0 ||
1062 rcWorkArea.top < 0 ||
1063 rcWorkArea.right > gpsi->aiSysMet[SM_CXSCREEN] ||
1064 rcWorkArea.bottom > gpsi->aiSysMet[SM_CYSCREEN] ||
1065 rcWorkArea.right <= rcWorkArea.left ||
1066 rcWorkArea.bottom <= rcWorkArea.top)
1067 return 0;
1068
1069 pmonitor->rcWork = rcWorkArea;
1070 if (fl & SPIF_UPDATEINIFILE)
1071 {
1072 // FIXME: What to do?
1073 }
1074 return (UINT_PTR)KEY_DESKTOP;
1075 }
1076
1077 case SPI_SETPENWINDOWS:
1078 ERR("SPI_SETPENWINDOWS is unimplemented\n");
1079 break;
1080
1081 case SPI_GETFILTERKEYS:
1082 {
1083 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1084
1085 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1086 return 0;
1087
1088 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1089 return 0;
1090
1091 return SpiGet(pvParam, &gspv.filterkeys, sizeof(FILTERKEYS), fl);
1092 }
1093
1094 case SPI_SETFILTERKEYS:
1095 {
1096 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1097
1098 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1099 return 0;
1100
1101 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1102 return 0;
1103
1104 if (!SpiSet(&gspv.filterkeys, pvParam, sizeof(FILTERKEYS), fl))
1105 return 0;
1106 if (fl & SPIF_UPDATEINIFILE)
1107 {
1108 // FIXME: What to do?
1109 }
1110 return (UINT_PTR)KEY_DESKTOP;
1111 }
1112
1113 case SPI_GETTOGGLEKEYS:
1114 {
1115 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1116
1117 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1118 return 0;
1119
1120 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1121 return 0;
1122
1123 return SpiGet(pvParam, &gspv.togglekeys, sizeof(TOGGLEKEYS), fl);
1124 }
1125
1126 case SPI_SETTOGGLEKEYS:
1127 {
1128 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1129
1130 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1131 return 0;
1132
1133 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1134 return 0;
1135
1136 if (!SpiSet(&gspv.togglekeys, pvParam, sizeof(TOGGLEKEYS), fl))
1137 return 0;
1138
1139 if (fl & SPIF_UPDATEINIFILE)
1140 {
1141 // FIXME: What to do?
1142 }
1143 return (UINT_PTR)KEY_DESKTOP;
1144 }
1145
1146 case SPI_GETMOUSEKEYS:
1147 {
1148 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1149
1150 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1151 return 0;
1152
1153 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1154 return 0;
1155
1156 return SpiGet(pvParam, &gspv.mousekeys, sizeof(MOUSEKEYS), fl);
1157 }
1158
1159 case SPI_SETMOUSEKEYS:
1160 {
1161 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1162
1163 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1164 return 0;
1165
1166 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1167 return 0;
1168
1169 if (!SpiSet(&gspv.mousekeys, pvParam, sizeof(MOUSEKEYS), fl))
1170 return 0;
1171
1172 if (fl & SPIF_UPDATEINIFILE)
1173 {
1174 // FIXME: What to do?
1175 }
1176 return (UINT_PTR)KEY_DESKTOP;
1177 }
1178
1179 case SPI_GETSHOWSOUNDS:
1180 return SpiGetInt(pvParam, &gspv.bShowSounds, fl);
1181
1182 case SPI_SETSHOWSOUNDS:
1183 return SpiSetBool(&gspv.bShowSounds, uiParam, KEY_SHOWSNDS, VAL_ON, fl);
1184
1185 case SPI_GETSTICKYKEYS:
1186 {
1187 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1188
1189 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1190 return 0;
1191
1192 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1193 return 0;
1194
1195 return SpiGetEx(pvParam, &gspv.stickykeys, sizeof(STICKYKEYS), fl);
1196 }
1197
1198 case SPI_SETSTICKYKEYS:
1199 {
1200 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1201
1202 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1203 return 0;
1204
1205 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1206 return 0;
1207
1208 if (!SpiSet(&gspv.stickykeys, pvParam, sizeof(STICKYKEYS), fl))
1209 return 0;
1210
1211 if (fl & SPIF_UPDATEINIFILE)
1212 {
1213 // FIXME: What to do?
1214 }
1215 return (UINT_PTR)KEY_DESKTOP;
1216 }
1217
1218 case SPI_GETACCESSTIMEOUT:
1219 {
1220 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1221
1222 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1223 return 0;
1224
1225 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1226 return 0;
1227
1228 return SpiGetEx(pvParam, &gspv.accesstimeout, sizeof(ACCESSTIMEOUT), fl);
1229 }
1230
1231 case SPI_SETACCESSTIMEOUT:
1232 {
1233 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1234
1235 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1236 {
1237 return 0;
1238 }
1239
1240 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1241 {
1242 return 0;
1243 }
1244
1245 if (!SpiSet(&gspv.accesstimeout, pvParam, sizeof(ACCESSTIMEOUT), fl))
1246 return 0;
1247
1248 if (fl & SPIF_UPDATEINIFILE)
1249 {
1250 // FIXME: What to do?
1251 }
1252 return (UINT_PTR)KEY_DESKTOP;
1253 }
1254
1255 case SPI_GETSERIALKEYS:
1256 {
1257 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1258
1259 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1260 return 0;
1261
1262 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1263 return 0;
1264
1265 return SpiGet(pvParam, &gspv.serialkeys, sizeof(SERIALKEYS), fl);
1266 }
1267
1268 case SPI_SETSERIALKEYS:
1269 {
1270 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1271
1272 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1273 return 0;
1274
1275 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1276 return 0;
1277
1278 if (!SpiSet(&gspv.serialkeys, pvParam, sizeof(SERIALKEYS), fl))
1279 return 0;
1280
1281 if (fl & SPIF_UPDATEINIFILE)
1282 {
1283 // FIXME: What to do?
1284 }
1285 return (UINT_PTR)KEY_DESKTOP;
1286 }
1287
1288 case SPI_GETSOUNDSENTRY:
1289 {
1290 LPSOUNDSENTRY SoundsEntry = (LPSOUNDSENTRY)pvParam;
1291
1292 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRY))
1293 return 0;
1294
1295 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRY))
1296 return 0;
1297
1298 return SpiGet(pvParam, &gspv.soundsentry, sizeof(SOUNDSENTRY), fl);
1299 }
1300
1301 case SPI_SETSOUNDSENTRY:
1302 {
1303 LPSOUNDSENTRY SoundsEntry = (LPSOUNDSENTRY)pvParam;
1304
1305 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRY))
1306 return 0;
1307
1308 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRY))
1309 return 0;
1310
1311 if (!SpiSet(&gspv.soundsentry, pvParam, sizeof(SOUNDSENTRY), fl))
1312 return 0;
1313
1314 if (fl & SPIF_UPDATEINIFILE)
1315 {
1316 // FIXME: What to do?
1317 }
1318 return (UINT_PTR)KEY_DESKTOP;
1319 }
1320
1321 case SPI_GETHIGHCONTRAST:
1322 return SpiGet(pvParam, &gspv.highcontrast, sizeof(HIGHCONTRAST), fl);
1323
1324 case SPI_SETHIGHCONTRAST:
1325 if (!SpiSet(&gspv.highcontrast, pvParam, sizeof(HIGHCONTRAST), fl))
1326 return 0;
1327 if (fl & SPIF_UPDATEINIFILE)
1328 {
1329 // FIXME: What to do?
1330 }
1331 return (UINT_PTR)KEY_DESKTOP;
1332
1333 case SPI_GETKEYBOARDPREF:
1334 return SpiGetInt(pvParam, &gspv.bKbdPref, fl);
1335
1336 case SPI_SETKEYBOARDPREF:
1337 return SpiSetBool(&gspv.bKbdPref, uiParam, KEY_KDBPREF, VAL_ON, fl);
1338
1339 case SPI_GETSCREENREADER:
1340 return SpiGetInt(pvParam, &gspv.bScreenReader, fl);
1341
1342 case SPI_SETSCREENREADER:
1343 return SpiSetBool(&gspv.bScreenReader, uiParam, KEY_SCRREAD, VAL_ON, fl);
1344
1345 case SPI_GETANIMATION:
1346 return SpiGet(pvParam, &gspv.animationinfo, sizeof(ANIMATIONINFO), fl);
1347
1348 case SPI_SETANIMATION:
1349 if (!SpiSet(&gspv.animationinfo, pvParam, sizeof(ANIMATIONINFO), fl))
1350 return 0;
1351 if (fl & SPIF_UPDATEINIFILE)
1352 {
1353 // FIXME: What to do?
1354 }
1355 return (UINT_PTR)KEY_DESKTOP;
1356
1357 case SPI_GETFONTSMOOTHING:
1358 return SpiGetInt(pvParam, &gspv.bFontSmoothing, fl);
1359
1360 case SPI_SETFONTSMOOTHING:
1361 gspv.bFontSmoothing = uiParam ? TRUE : FALSE;
1362 if (fl & SPIF_UPDATEINIFILE)
1363 {
1364 SpiStoreSzInt(KEY_DESKTOP, VAL_FNTSMOOTH, uiParam ? 2 : 0);
1365 }
1366 return (UINT_PTR)KEY_DESKTOP;
1367
1368 case SPI_SETDRAGWIDTH:
1369 return SpiSetInt(&gspv.iDragWidth, uiParam, KEY_DESKTOP, VAL_DRAGWIDTH, fl);
1370
1371 case SPI_SETDRAGHEIGHT:
1372 return SpiSetInt(&gspv.iDragHeight, uiParam, KEY_DESKTOP, VAL_DRAGHEIGHT, fl);
1373
1374 case SPI_SETHANDHELD:
1375 return SpiSetBool(&gspv.bHandHeld, uiParam, KEY_DESKTOP, L"HandHeld", fl);
1376
1377 case SPI_GETLOWPOWERTIMEOUT:
1378 return SpiGetInt(pvParam, &gspv.iLowPwrTimeout, fl);
1379
1380 case SPI_GETPOWEROFFTIMEOUT:
1381 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1382
1383 case SPI_SETLOWPOWERTIMEOUT:
1384 return SpiSetInt(&gspv.iLowPwrTimeout, uiParam, KEY_DESKTOP, L"LowPowerTimeOut", fl);
1385
1386 case SPI_SETPOWEROFFTIMEOUT:
1387 return SpiSetInt(&gspv.iPwrOffTimeout, uiParam, KEY_DESKTOP, L"PowerOffTimeOut", fl);
1388
1389 case SPI_GETLOWPOWERACTIVE:
1390 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1391
1392 case SPI_GETPOWEROFFACTIVE:
1393 return SpiGetInt(pvParam, &gspv.bPwrOffActive, fl);
1394
1395 case SPI_SETLOWPOWERACTIVE:
1396 return SpiSetBool(&gspv.bLowPwrActive, uiParam, KEY_DESKTOP, L"LowPowerActive", fl);
1397
1398 case SPI_SETPOWEROFFACTIVE:
1399 return SpiSetBool(&gspv.bPwrOffActive, uiParam, KEY_DESKTOP, L"PowerOffActive", fl);
1400
1401 case SPI_SETCURSORS:
1402 ERR("SPI_SETCURSORS is unimplemented\n");
1403 break;
1404
1405 case SPI_SETICONS:
1406 ERR("SPI_SETICONS is unimplemented\n");
1407 break;
1408
1409 case SPI_GETDEFAULTINPUTLANG:
1410 if (!gspklBaseLayout)
1411 return FALSE;
1412
1413 return SpiGet(pvParam, &gspklBaseLayout->hkl, sizeof(HKL), fl);
1414
1415 case SPI_SETDEFAULTINPUTLANG:
1416 {
1417 HKL hkl;
1418
1419 /* Note: SPIF_UPDATEINIFILE is not supported */
1420 if ((fl & SPIF_UPDATEINIFILE) || !SpiSet(&hkl, pvParam, sizeof(hkl), fl))
1421 return FALSE;
1422
1423 return UserSetDefaultInputLang(hkl);
1424 }
1425
1426 case SPI_SETLANGTOGGLE:
1427 gdwLanguageToggleKey = UserGetLanguageToggle();
1428 return gdwLanguageToggleKey;
1429 break;
1430
1431 case SPI_GETWINDOWSEXTENSION:
1432 ERR("SPI_GETWINDOWSEXTENSION is unimplemented\n");
1433 break;
1434
1435 case SPI_GETMOUSETRAILS:
1436 return SpiGetInt(pvParam, &gspv.iMouseTrails, fl);
1437
1438 case SPI_SETMOUSETRAILS:
1439 return SpiSetInt(&gspv.iMouseTrails, uiParam, KEY_MOUSE, VAL_MOUSETRAILS, fl);
1440
1441 case SPI_GETSNAPTODEFBUTTON:
1442 return SpiGetInt(pvParam, &gspv.bSnapToDefBtn, fl);
1443
1444 case SPI_SETSNAPTODEFBUTTON:
1445 return SpiSetBool(&gspv.bSnapToDefBtn, uiParam, KEY_MOUSE, VAL_SNAPDEFBTN, fl);
1446
1447 case SPI_GETMOUSEHOVERWIDTH:
1448 return SpiGetInt(pvParam, &gspv.iMouseHoverWidth, fl);
1449
1450 case SPI_SETMOUSEHOVERWIDTH:
1451 return SpiSetInt(&gspv.iMouseHoverWidth, uiParam, KEY_MOUSE, VAL_HOVERWIDTH, fl);
1452
1453 case SPI_GETMOUSEHOVERHEIGHT:
1454 return SpiGetInt(pvParam, &gspv.iMouseHoverHeight, fl);
1455
1456 case SPI_SETMOUSEHOVERHEIGHT:
1457 return SpiSetInt(&gspv.iMouseHoverHeight, uiParam, KEY_MOUSE, VAL_HOVERHEIGHT, fl);
1458
1459 case SPI_GETMOUSEHOVERTIME:
1460 return SpiGetInt(pvParam, &gspv.iMouseHoverTime, fl);
1461
1462 case SPI_SETMOUSEHOVERTIME:
1463 /* See http://msdn2.microsoft.com/en-us/library/ms724947.aspx
1464 * copy text from it, if some agument why xp and 2003 behovir diffent
1465 * only if they do not have SP install
1466 * " Windows Server 2003 and Windows XP: The operating system does not
1467 * enforce the use of USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM until
1468 * Windows Server 2003 SP1 and Windows XP SP2 "
1469 */
1470 return SpiSetInt(&gspv.iMouseHoverTime, uiParam, KEY_MOUSE, VAL_HOVERTIME, fl);
1471
1472 case SPI_GETWHEELSCROLLLINES:
1473 return SpiGetInt(pvParam, &gspv.iWheelScrollLines, fl);
1474
1475 case SPI_SETWHEELSCROLLLINES:
1476 return SpiSetInt(&gspv.iWheelScrollLines, uiParam, KEY_DESKTOP, VAL_SCRLLLINES, fl);
1477
1478 case SPI_GETMENUSHOWDELAY:
1479 return SpiGetInt(pvParam, &gspv.dwMenuShowDelay, fl);
1480
1481 case SPI_SETMENUSHOWDELAY:
1482 return SpiSetInt(&gspv.dwMenuShowDelay, uiParam, KEY_DESKTOP, L"MenuShowDelay", fl);
1483
1484 #if (_WIN32_WINNT >= 0x0600)
1485 case SPI_GETWHEELSCROLLCHARS:
1486 return SpiGetInt(pvParam, &gspv.uiWheelScrollChars, fl);
1487
1488 case SPI_SETWHEELSCROLLCHARS:
1489 return SpiSetInt(&gspv.uiWheelScrollChars, uiParam, KEY_DESKTOP, VAL_SCRLLCHARS, fl);
1490 #endif
1491 case SPI_GETSHOWIMEUI:
1492 return SpiGetInt(pvParam, &gspv.bShowImeUi, fl);
1493
1494 case SPI_SETSHOWIMEUI:
1495 return SpiSetBool(&gspv.bShowImeUi, uiParam, KEY_DESKTOP, L"", fl);
1496
1497 case SPI_GETMOUSESPEED:
1498 return SpiGetInt(pvParam, &gspv.iMouseSpeed, fl);
1499
1500 case SPI_SETMOUSESPEED:
1501 {
1502 /* Allowed range is [1:20] */
1503 if ((INT_PTR)pvParam < 1 || (INT_PTR)pvParam > 20)
1504 return 0;
1505 else
1506 return SpiSetInt(&gspv.iMouseSpeed, (INT_PTR)pvParam, KEY_MOUSE, VAL_SENSITIVITY, fl);
1507 }
1508
1509 case SPI_GETSCREENSAVERRUNNING:
1510 return SpiGetInt(pvParam, &gspv.bScrSaverRunning, fl);
1511
1512 case SPI_SETSCREENSAVERRUNNING:
1513 // FIXME: also return value?
1514 return SpiSetBool(&gspv.bScrSaverRunning, uiParam, KEY_MOUSE, L"", fl);
1515
1516 #if(WINVER >= 0x0600)
1517 case SPI_GETAUDIODESCRIPTION:
1518 return SpiGet(pvParam, &gspv.audiodesription, sizeof(AUDIODESCRIPTION), fl);
1519
1520 case SPI_SETAUDIODESCRIPTION:
1521 ERR("SPI_SETAUDIODESCRIPTION is unimplemented\n");
1522 break;
1523
1524 case SPI_GETSCREENSAVESECURE:
1525 return SpiGetInt(pvParam, &gspv.bScrSaverSecure, fl);
1526
1527 case SPI_SETSCREENSAVESECURE:
1528 return SpiSetBool(&gspv.bScrSaverSecure, uiParam, KEY_DESKTOP, L"ScreenSaverIsSecure", fl);
1529 #endif
1530
1531 case SPI_GETACTIVEWINDOWTRACKING:
1532 return SpiGetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1533
1534 case SPI_SETACTIVEWINDOWTRACKING:
1535 return SpiSetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1536
1537 case SPI_GETMENUANIMATION:
1538 return SpiGetUserPref(UPM_MENUANIMATION, pvParam, fl);
1539
1540 case SPI_SETMENUANIMATION:
1541 return SpiSetUserPref(UPM_MENUANIMATION, pvParam, fl);
1542
1543 case SPI_GETCOMBOBOXANIMATION:
1544 return SpiGetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1545
1546 case SPI_SETCOMBOBOXANIMATION:
1547 return SpiSetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1548
1549 case SPI_GETLISTBOXSMOOTHSCROLLING:
1550 return SpiGetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1551
1552 case SPI_SETLISTBOXSMOOTHSCROLLING:
1553 return SpiSetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1554
1555 case SPI_GETGRADIENTCAPTIONS:
1556 return SpiGetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1557
1558 case SPI_SETGRADIENTCAPTIONS:
1559 return SpiSetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1560
1561 case SPI_GETKEYBOARDCUES:
1562 return SpiGetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1563
1564 case SPI_SETKEYBOARDCUES:
1565 return SpiSetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1566
1567 case SPI_GETACTIVEWNDTRKZORDER:
1568 return SpiGetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1569
1570 case SPI_SETACTIVEWNDTRKZORDER:
1571 return SpiSetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1572
1573 case SPI_GETHOTTRACKING:
1574 return SpiGetUserPref(UPM_HOTTRACKING, pvParam, fl);
1575
1576 case SPI_SETHOTTRACKING:
1577 return SpiSetUserPref(UPM_HOTTRACKING, pvParam, fl);
1578
1579 case SPI_GETMENUFADE:
1580 return SpiGetUserPref(UPM_MENUFADE, pvParam, fl);
1581
1582 case SPI_SETMENUFADE:
1583 return SpiSetUserPref(UPM_MENUFADE, pvParam, fl);
1584
1585 case SPI_GETSELECTIONFADE:
1586 return SpiGetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1587
1588 case SPI_SETSELECTIONFADE:
1589 return SpiSetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1590
1591 case SPI_GETTOOLTIPANIMATION:
1592 return SpiGetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1593
1594 case SPI_SETTOOLTIPANIMATION:
1595 return SpiSetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1596
1597 case SPI_GETTOOLTIPFADE:
1598 return SpiGetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1599
1600 case SPI_SETTOOLTIPFADE:
1601 return SpiSetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1602
1603 case SPI_GETCURSORSHADOW:
1604 return SpiGetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1605
1606 case SPI_SETCURSORSHADOW:
1607 gspv.bMouseCursorShadow = (BOOL)pvParam;
1608 return SpiSetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1609
1610 case SPI_GETUIEFFECTS:
1611 return SpiGetUserPref(UPM_UIEFFECTS, pvParam, fl);
1612
1613 case SPI_SETUIEFFECTS:
1614 return SpiSetUserPref(UPM_UIEFFECTS, pvParam, fl);
1615
1616 case SPI_GETMOUSESONAR:
1617 return SpiGetInt(pvParam, &gspv.bMouseSonar, fl);
1618
1619 case SPI_SETMOUSESONAR:
1620 return SpiSetBool(&gspv.bMouseSonar, uiParam, KEY_MOUSE, L"", fl);
1621
1622 case SPI_GETMOUSECLICKLOCK:
1623 return SpiGetUserPref(UPM_CLICKLOCK, pvParam, fl);
1624
1625 case SPI_SETMOUSECLICKLOCK:
1626 gspv.bMouseClickLock = (BOOL)pvParam;
1627 return SpiSetUserPref(UPM_CLICKLOCK, pvParam, fl);
1628
1629 case SPI_GETMOUSEVANISH:
1630 return SpiGetInt(pvParam, &gspv.bMouseVanish, fl);
1631
1632 case SPI_SETMOUSEVANISH:
1633 return SpiSetBool(&gspv.bMouseVanish, uiParam, KEY_MOUSE, L"", fl);
1634
1635 case SPI_GETFLATMENU:
1636 return SpiGetInt(pvParam, &gspv.bFlatMenu, fl);
1637
1638 case SPI_SETFLATMENU:
1639 return SpiSetBool(&gspv.bFlatMenu, uiParam, KEY_MOUSE, L"", fl);
1640
1641 case SPI_GETDROPSHADOW:
1642 return SpiGetInt(pvParam, &gspv.bDropShadow, fl);
1643
1644 case SPI_SETDROPSHADOW:
1645 return SpiSetBool(&gspv.bDropShadow, uiParam, KEY_MOUSE, L"", fl);
1646
1647 case SPI_GETBLOCKSENDINPUTRESETS:
1648 return SpiGetInt(pvParam, &gspv.bBlockSendInputResets, fl);
1649
1650 case SPI_SETBLOCKSENDINPUTRESETS:
1651 return SpiSetBool(&gspv.bBlockSendInputResets, uiParam, KEY_MOUSE, L"", fl);
1652
1653 #if(_WIN32_WINNT >= 0x0600)
1654 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1655 return SpiGetInt(pvParam, &gspv.bDisableOverlappedContent, fl);
1656
1657 case SPI_SETDISABLEOVERLAPPEDCONTENT:
1658 return SpiSetBool(&gspv.bDisableOverlappedContent, uiParam, KEY_MOUSE, L"", fl);
1659
1660 case SPI_GETCLIENTAREAANIMATION:
1661 return SpiGetInt(pvParam, &gspv.bClientAnimation, fl);
1662
1663 case SPI_SETCLIENTAREAANIMATION:
1664 return SpiSetBool(&gspv.bClientAnimation, uiParam, KEY_MOUSE, L"", fl);
1665
1666 case SPI_GETCLEARTYPE:
1667 return SpiGetInt(pvParam, &gspv.bClearType, fl);
1668
1669 case SPI_SETCLEARTYPE:
1670 return SpiSetBool(&gspv.bClearType, uiParam, KEY_MOUSE, L"", fl);
1671
1672 case SPI_GETSPEECHRECOGNITION:
1673 return SpiGetInt(pvParam, &gspv.bSpeechRecognition, fl);
1674
1675 case SPI_SETSPEECHRECOGNITION:
1676 return SpiSetBool(&gspv.bSpeechRecognition, uiParam, KEY_MOUSE, L"", fl);
1677 #endif
1678
1679 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1680 return SpiGetInt(pvParam, &gspv.dwForegroundLockTimeout, fl);
1681
1682 case SPI_SETFOREGROUNDLOCKTIMEOUT:
1683 return SpiSetInt(&gspv.dwForegroundLockTimeout, uiParam, KEY_MOUSE, L"", fl);
1684
1685 case SPI_GETACTIVEWNDTRKTIMEOUT:
1686 return SpiGetInt(pvParam, &gspv.dwActiveTrackingTimeout, fl);
1687
1688 case SPI_SETACTIVEWNDTRKTIMEOUT:
1689 return SpiSetInt(&gspv.dwActiveTrackingTimeout, uiParam, KEY_MOUSE, L"", fl);
1690
1691 case SPI_GETFOREGROUNDFLASHCOUNT:
1692 return SpiGetInt(pvParam, &gspv.dwForegroundFlashCount, fl);
1693
1694 case SPI_SETFOREGROUNDFLASHCOUNT:
1695 return SpiSetInt(&gspv.dwForegroundFlashCount, uiParam, KEY_MOUSE, L"", fl);
1696
1697 case SPI_GETCARETWIDTH:
1698 return SpiGetInt(pvParam, &gspv.dwCaretWidth, fl);
1699
1700 case SPI_SETCARETWIDTH:
1701 return SpiSetInt(&gspv.dwCaretWidth, uiParam, KEY_MOUSE, L"", fl);
1702
1703 case SPI_GETMOUSECLICKLOCKTIME:
1704 return SpiGetInt(pvParam, &gspv.dwMouseClickLockTime, fl);
1705
1706 case SPI_SETMOUSECLICKLOCKTIME:
1707 return SpiSetDWord(&gspv.dwMouseClickLockTime, uiParam, KEY_DESKTOP, VAL_CLICKLOCKTIME, fl);
1708
1709 case SPI_GETFONTSMOOTHINGTYPE:
1710 return SpiGetInt(pvParam, &gspv.uiFontSmoothingType, fl);
1711
1712 case SPI_SETFONTSMOOTHINGTYPE:
1713 return SpiSetInt(&gspv.uiFontSmoothingType, uiParam, KEY_MOUSE, L"", fl);
1714
1715 case SPI_GETFONTSMOOTHINGCONTRAST:
1716 return SpiGetInt(pvParam, &gspv.uiFontSmoothingContrast, fl);
1717
1718 case SPI_SETFONTSMOOTHINGCONTRAST:
1719 return SpiSetInt(&gspv.uiFontSmoothingContrast, uiParam, KEY_MOUSE, L"", fl);
1720
1721 case SPI_GETFOCUSBORDERWIDTH:
1722 return SpiGetInt(pvParam, &gspv.uiFocusBorderWidth, fl);
1723
1724 case SPI_SETFOCUSBORDERWIDTH:
1725 return SpiSetInt(&gspv.uiFocusBorderWidth, uiParam, KEY_MOUSE, L"", fl);
1726
1727 case SPI_GETFOCUSBORDERHEIGHT:
1728 return SpiGetInt(pvParam, &gspv.uiFocusBorderHeight, fl);
1729
1730 case SPI_SETFOCUSBORDERHEIGHT:
1731 return SpiSetInt(&gspv.uiFocusBorderHeight, uiParam, KEY_MOUSE, L"", fl);
1732
1733 case SPI_GETFONTSMOOTHINGORIENTATION:
1734 return SpiGetInt(pvParam, &gspv.uiFontSmoothingOrientation, fl);
1735
1736 case SPI_SETFONTSMOOTHINGORIENTATION:
1737 return SpiSetInt(&gspv.uiFontSmoothingOrientation, uiParam, KEY_MOUSE, L"", fl);
1738
1739 /* The following are undocumented, but valid SPI values */
1740 case 0x1010:
1741 case 0x1011:
1742 case 0x1028:
1743 case 0x1029:
1744 case 0x102A:
1745 case 0x102B:
1746 case 0x102C:
1747 case 0x102D:
1748 case 0x102E:
1749 case 0x102F:
1750 case 0x1030:
1751 case 0x1031:
1752 case 0x1032:
1753 case 0x1033:
1754 case 0x1034:
1755 case 0x1035:
1756 case 0x1036:
1757 case 0x1037:
1758 case 0x1038:
1759 case 0x1039:
1760 case 0x103A:
1761 case 0x103B:
1762 case 0x103C:
1763 case 0x103D:
1764 ERR("Undocumented SPI value %x is unimplemented\n", uiAction);
1765 break;
1766
1767 default:
1768 ERR("Invalid SPI value: %u\n", uiAction);
1769 EngSetLastError(ERROR_INVALID_PARAMETER);
1770 return 0;
1771 }
1772
1773 return 0;
1774 }
1775
1776 static BOOL
1777 SpiGetSetProbeBuffer(UINT uiAction, UINT uiParam, PVOID pvParam)
1778 {
1779 BOOL bToUser = TRUE;
1780 ULONG cbSize = 0;
1781
1782 switch (uiAction)
1783 {
1784 case SPI_GETBEEP:
1785 case SPI_GETBORDER:
1786 case SPI_GETKEYBOARDSPEED:
1787 case SPI_GETSCREENSAVETIMEOUT:
1788 case SPI_GETSCREENSAVEACTIVE:
1789 case SPI_GETGRIDGRANULARITY:
1790 case SPI_GETKEYBOARDDELAY:
1791 case SPI_GETICONTITLEWRAP:
1792 case SPI_GETMENUDROPALIGNMENT:
1793 case SPI_GETFASTTASKSWITCH:
1794 case SPI_GETDRAGFULLWINDOWS:
1795 case SPI_GETSHOWSOUNDS:
1796 case SPI_GETKEYBOARDPREF:
1797 case SPI_GETSCREENREADER:
1798 case SPI_GETFONTSMOOTHING:
1799 case SPI_GETLOWPOWERTIMEOUT:
1800 case SPI_GETPOWEROFFTIMEOUT:
1801 case SPI_GETLOWPOWERACTIVE:
1802 case SPI_GETPOWEROFFACTIVE:
1803 case SPI_GETMOUSETRAILS:
1804 case SPI_GETSNAPTODEFBUTTON:
1805 case SPI_GETMOUSEHOVERWIDTH:
1806 case SPI_GETMOUSEHOVERHEIGHT:
1807 case SPI_GETMOUSEHOVERTIME:
1808 case SPI_GETWHEELSCROLLLINES:
1809 case SPI_GETMENUSHOWDELAY:
1810 #if (_WIN32_WINNT >= 0x0600)
1811 case SPI_GETWHEELSCROLLCHARS:
1812 #endif
1813 case SPI_GETSHOWIMEUI:
1814 case SPI_GETMOUSESPEED:
1815 case SPI_GETSCREENSAVERRUNNING:
1816 #if(WINVER >= 0x0600)
1817 case SPI_GETSCREENSAVESECURE:
1818 #endif
1819 case SPI_GETACTIVEWINDOWTRACKING:
1820 case SPI_GETMENUANIMATION:
1821 case SPI_GETCOMBOBOXANIMATION:
1822 case SPI_GETLISTBOXSMOOTHSCROLLING:
1823 case SPI_GETGRADIENTCAPTIONS:
1824 case SPI_GETKEYBOARDCUES:
1825 case SPI_GETACTIVEWNDTRKZORDER:
1826 case SPI_GETHOTTRACKING:
1827 case SPI_GETMENUFADE:
1828 case SPI_GETSELECTIONFADE:
1829 case SPI_GETTOOLTIPANIMATION:
1830 case SPI_GETTOOLTIPFADE:
1831 case SPI_GETCURSORSHADOW:
1832 case SPI_GETUIEFFECTS:
1833 case SPI_GETMOUSESONAR:
1834 case SPI_GETMOUSECLICKLOCK:
1835 case SPI_GETMOUSEVANISH:
1836 case SPI_GETFLATMENU:
1837 case SPI_GETDROPSHADOW:
1838 case SPI_GETBLOCKSENDINPUTRESETS:
1839 #if(_WIN32_WINNT >= 0x0600)
1840 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1841 case SPI_GETCLIENTAREAANIMATION:
1842 case SPI_GETCLEARTYPE:
1843 case SPI_GETSPEECHRECOGNITION:
1844 #endif
1845 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1846 case SPI_GETACTIVEWNDTRKTIMEOUT:
1847 case SPI_GETFOREGROUNDFLASHCOUNT:
1848 case SPI_GETCARETWIDTH:
1849 case SPI_GETMOUSECLICKLOCKTIME:
1850 case SPI_GETFONTSMOOTHINGTYPE:
1851 case SPI_GETFONTSMOOTHINGCONTRAST:
1852 case SPI_GETFOCUSBORDERWIDTH:
1853 case SPI_GETFOCUSBORDERHEIGHT:
1854 case SPI_GETFONTSMOOTHINGORIENTATION:
1855 cbSize = sizeof(INT);
1856 break;
1857
1858 case SPI_ICONHORIZONTALSPACING:
1859 case SPI_ICONVERTICALSPACING:
1860 if (pvParam) cbSize = sizeof(INT);
1861 break;
1862
1863 case SPI_GETMOUSE:
1864 cbSize = 3 * sizeof(INT);
1865 break;
1866
1867 case SPI_GETDESKWALLPAPER:
1868 cbSize = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
1869 break;
1870
1871 case SPI_GETICONTITLELOGFONT:
1872 cbSize = sizeof(LOGFONTW);
1873 break;
1874
1875 case SPI_GETNONCLIENTMETRICS:
1876 cbSize = sizeof(NONCLIENTMETRICSW);
1877 break;
1878
1879 case SPI_GETMINIMIZEDMETRICS:
1880 cbSize = sizeof(MINIMIZEDMETRICS);
1881 break;
1882
1883 case SPI_GETICONMETRICS:
1884 cbSize = sizeof(ICONMETRICS);
1885 break;
1886
1887 case SPI_GETWORKAREA:
1888 cbSize = sizeof(RECTL);
1889 break;
1890
1891 case SPI_GETFILTERKEYS:
1892 cbSize = sizeof(FILTERKEYS);
1893 break;
1894
1895 case SPI_GETTOGGLEKEYS:
1896 cbSize = sizeof(TOGGLEKEYS);
1897 break;
1898
1899 case SPI_GETMOUSEKEYS:
1900 cbSize = sizeof(MOUSEKEYS);
1901 break;
1902
1903 case SPI_GETSTICKYKEYS:
1904 cbSize = sizeof(STICKYKEYS);
1905 break;
1906
1907 case SPI_GETACCESSTIMEOUT:
1908 cbSize = sizeof(ACCESSTIMEOUT);
1909 break;
1910
1911 case SPI_GETSERIALKEYS:
1912 cbSize = sizeof(SERIALKEYS);
1913 break;
1914
1915 case SPI_GETSOUNDSENTRY:
1916 cbSize = sizeof(SOUNDSENTRY);
1917 break;
1918
1919 case SPI_GETHIGHCONTRAST:
1920 cbSize = sizeof(HIGHCONTRAST);
1921 break;
1922
1923 case SPI_GETANIMATION:
1924 cbSize = sizeof(ANIMATIONINFO);
1925 break;
1926
1927 case SPI_GETDEFAULTINPUTLANG:
1928 cbSize = sizeof(HKL);
1929 break;
1930
1931 #if(WINVER >= 0x0600)
1932 case SPI_GETAUDIODESCRIPTION:
1933 cbSize = sizeof(AUDIODESCRIPTION);
1934 break;
1935 #endif
1936
1937 case SPI_SETMOUSE:
1938 cbSize = 3 * sizeof(INT);
1939 bToUser = FALSE;
1940 break;
1941
1942 case SPI_SETICONTITLELOGFONT:
1943 cbSize = sizeof(LOGFONTW);
1944 bToUser = FALSE;
1945 break;
1946
1947 case SPI_SETNONCLIENTMETRICS:
1948 cbSize = sizeof(NONCLIENTMETRICSW);
1949 bToUser = FALSE;
1950 break;
1951
1952 case SPI_SETMINIMIZEDMETRICS:
1953 cbSize = sizeof(MINIMIZEDMETRICS);
1954 bToUser = FALSE;
1955 break;
1956
1957 case SPI_SETICONMETRICS:
1958 cbSize = sizeof(ICONMETRICS);
1959 bToUser = FALSE;
1960 break;
1961
1962 case SPI_SETWORKAREA:
1963 cbSize = sizeof(RECTL);
1964 bToUser = FALSE;
1965 break;
1966
1967 case SPI_SETFILTERKEYS:
1968 cbSize = sizeof(FILTERKEYS);
1969 bToUser = FALSE;
1970 break;
1971
1972 case SPI_SETTOGGLEKEYS:
1973 cbSize = sizeof(TOGGLEKEYS);
1974 bToUser = FALSE;
1975 break;
1976
1977 case SPI_SETMOUSEKEYS:
1978 cbSize = sizeof(MOUSEKEYS);
1979 bToUser = FALSE;
1980 break;
1981
1982 case SPI_SETSTICKYKEYS:
1983 cbSize = sizeof(STICKYKEYS);
1984 bToUser = FALSE;
1985 break;
1986
1987 case SPI_SETACCESSTIMEOUT:
1988 cbSize = sizeof(ACCESSTIMEOUT);
1989 bToUser = FALSE;
1990 break;
1991
1992 case SPI_SETSERIALKEYS:
1993 cbSize = sizeof(SERIALKEYS);
1994 bToUser = FALSE;
1995 break;
1996
1997 case SPI_SETSOUNDSENTRY:
1998 cbSize = sizeof(SOUNDSENTRY);
1999 bToUser = FALSE;
2000 break;
2001
2002 case SPI_SETHIGHCONTRAST:
2003 cbSize = sizeof(HIGHCONTRAST);
2004 bToUser = FALSE;
2005 break;
2006
2007 case SPI_SETANIMATION:
2008 cbSize = sizeof(ANIMATIONINFO);
2009 bToUser = FALSE;
2010 break;
2011
2012 case SPI_SETDEFAULTINPUTLANG:
2013 cbSize = sizeof(HKL);
2014 bToUser = FALSE;
2015 break;
2016
2017 case SPI_SETMOUSESPEED:
2018 cbSize = sizeof(INT);
2019 bToUser = FALSE;
2020 break;
2021 }
2022
2023 if (cbSize)
2024 {
2025 _SEH2_TRY
2026 {
2027 if (bToUser)
2028 {
2029 ProbeForWrite(pvParam, cbSize, sizeof(UCHAR));
2030 }
2031 else
2032 {
2033 ProbeForRead(pvParam, cbSize, sizeof(UCHAR));
2034 }
2035 }
2036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2037 {
2038 _SEH2_YIELD(return FALSE);
2039 }
2040 _SEH2_END;
2041 }
2042
2043 return TRUE;
2044 }
2045
2046 BOOL
2047 FASTCALL
2048 UserSystemParametersInfo(
2049 UINT uiAction,
2050 UINT uiParam,
2051 PVOID pvParam,
2052 UINT fWinIni)
2053 {
2054 ULONG_PTR ulResult;
2055 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
2056
2057 ASSERT(ppi);
2058
2059 if (!gbSpiInitialized)
2060 {
2061 KeRosDumpStackFrames(NULL, 20);
2062 //ASSERT(FALSE);
2063 return FALSE;
2064 }
2065
2066 /* Get a pointer to the current Windowstation */
2067 if (!ppi->prpwinsta)
2068 {
2069 ERR("UserSystemParametersInfo called without active window station.\n");
2070 //ASSERT(FALSE);
2071 //return FALSE;
2072 }
2073
2074 if ((fWinIni & SPIF_PROTECT) && !SpiGetSetProbeBuffer(uiAction, uiParam, pvParam))
2075 {
2076 EngSetLastError(ERROR_NOACCESS);
2077 return FALSE;
2078 }
2079
2080 /* Do the actual operation */
2081 ulResult = SpiGetSet(uiAction, uiParam, pvParam, fWinIni);
2082
2083 /* Did we change something? */
2084 if (ulResult > 1)
2085 {
2086 SpiFixupValues();
2087
2088 /* Update system metrics */
2089 InitMetrics();
2090
2091 /* Send notification to toplevel windows, if requested */
2092 if (fWinIni & (SPIF_SENDCHANGE | SPIF_SENDWININICHANGE))
2093 {
2094 /* Send WM_SETTINGCHANGE to all toplevel windows */
2095 co_IntSendMessageTimeout(HWND_BROADCAST,
2096 WM_SETTINGCHANGE,
2097 (WPARAM)uiAction,
2098 (LPARAM)ulResult,
2099 SMTO_NORMAL,
2100 100,
2101 &ulResult);
2102 }
2103 ulResult = 1;
2104 }
2105
2106 return ulResult;
2107 }
2108
2109 BOOL
2110 APIENTRY
2111 NtUserSystemParametersInfo(
2112 UINT uiAction,
2113 UINT uiParam,
2114 PVOID pvParam,
2115 UINT fWinIni)
2116 {
2117 BOOL bResult;
2118
2119 TRACE("Enter NtUserSystemParametersInfo(%u)\n", uiAction);
2120 UserEnterExclusive();
2121
2122 // FIXME: Get rid of the flags and only use this from um. kernel can access data directly.
2123 /* Set UM memory protection flag */
2124 fWinIni |= SPIF_PROTECT;
2125
2126 /* Call internal function */
2127 bResult = UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
2128
2129 TRACE("Leave NtUserSystemParametersInfo, returning %d\n", bResult);
2130 UserLeave();
2131
2132 return bResult;
2133 }
2134
2135 /* EOF */