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