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