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