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