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