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