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