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