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