[FORMATTING] Remove trailing whitespace. Addendum to 34593d93.
[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 PMONITOR pmonitor;
1052 RECTL rcWorkArea, rcIntersect;
1053
1054 if (!pvParam)
1055 return 0;
1056
1057 RtlCopyMemory(&rcWorkArea, pvParam, sizeof(rcWorkArea));
1058
1059 /* fail if empty */
1060 if (RECTL_bIsEmptyRect(&rcWorkArea))
1061 return 0;
1062
1063 /* get the nearest monitor */
1064 pmonitor = UserMonitorFromRect(&rcWorkArea, MONITOR_DEFAULTTONEAREST);
1065 if (!pmonitor)
1066 return 0;
1067
1068 /* fail unless work area is completely in monitor */
1069 if (!RECTL_bIntersectRect(&rcIntersect, &pmonitor->rcMonitor, &rcWorkArea) ||
1070 !RtlEqualMemory(&rcIntersect, &rcWorkArea, sizeof(rcIntersect)))
1071 {
1072 return 0;
1073 }
1074
1075 if (!SpiSet(&pmonitor->rcWork, pvParam, sizeof(RECTL), fl))
1076 return 0;
1077
1078 if (fl & SPIF_UPDATEINIFILE)
1079 {
1080 // FIXME: What to do?
1081 }
1082 return (UINT_PTR)KEY_DESKTOP;
1083 }
1084
1085 case SPI_SETPENWINDOWS:
1086 ERR("SPI_SETPENWINDOWS is unimplemented\n");
1087 break;
1088
1089 case SPI_GETFILTERKEYS:
1090 {
1091 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1092
1093 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1094 return 0;
1095
1096 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1097 return 0;
1098
1099 return SpiGet(pvParam, &gspv.filterkeys, sizeof(FILTERKEYS), fl);
1100 }
1101
1102 case SPI_SETFILTERKEYS:
1103 {
1104 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1105
1106 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1107 return 0;
1108
1109 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1110 return 0;
1111
1112 if (!SpiSet(&gspv.filterkeys, pvParam, sizeof(FILTERKEYS), fl))
1113 return 0;
1114
1115 if (fl & SPIF_UPDATEINIFILE)
1116 {
1117 // FIXME: What to do?
1118 }
1119 return (UINT_PTR)KEY_DESKTOP;
1120 }
1121
1122 case SPI_GETTOGGLEKEYS:
1123 {
1124 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1125
1126 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1127 return 0;
1128
1129 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1130 return 0;
1131
1132 return SpiGet(pvParam, &gspv.togglekeys, sizeof(TOGGLEKEYS), fl);
1133 }
1134
1135 case SPI_SETTOGGLEKEYS:
1136 {
1137 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1138
1139 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1140 return 0;
1141
1142 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1143 return 0;
1144
1145 if (!SpiSet(&gspv.togglekeys, pvParam, sizeof(TOGGLEKEYS), fl))
1146 return 0;
1147
1148 if (fl & SPIF_UPDATEINIFILE)
1149 {
1150 // FIXME: What to do?
1151 }
1152 return (UINT_PTR)KEY_DESKTOP;
1153 }
1154
1155 case SPI_GETMOUSEKEYS:
1156 {
1157 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1158
1159 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1160 return 0;
1161
1162 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1163 return 0;
1164
1165 return SpiGet(pvParam, &gspv.mousekeys, sizeof(MOUSEKEYS), fl);
1166 }
1167
1168 case SPI_SETMOUSEKEYS:
1169 {
1170 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1171
1172 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1173 return 0;
1174
1175 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1176 return 0;
1177
1178 if (!SpiSet(&gspv.mousekeys, pvParam, sizeof(MOUSEKEYS), fl))
1179 return 0;
1180
1181 if (fl & SPIF_UPDATEINIFILE)
1182 {
1183 // FIXME: What to do?
1184 }
1185 return (UINT_PTR)KEY_DESKTOP;
1186 }
1187
1188 case SPI_GETSHOWSOUNDS:
1189 return SpiGetInt(pvParam, &gspv.bShowSounds, fl);
1190
1191 case SPI_SETSHOWSOUNDS:
1192 return SpiSetBool(&gspv.bShowSounds, uiParam, KEY_SHOWSNDS, VAL_ON, fl);
1193
1194 case SPI_GETSTICKYKEYS:
1195 {
1196 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1197
1198 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1199 return 0;
1200
1201 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1202 return 0;
1203
1204 return SpiGetEx(pvParam, &gspv.stickykeys, sizeof(STICKYKEYS), fl);
1205 }
1206
1207 case SPI_SETSTICKYKEYS:
1208 {
1209 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1210
1211 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1212 return 0;
1213
1214 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1215 return 0;
1216
1217 if (!SpiSet(&gspv.stickykeys, pvParam, sizeof(STICKYKEYS), fl))
1218 return 0;
1219
1220 if (fl & SPIF_UPDATEINIFILE)
1221 {
1222 // FIXME: What to do?
1223 }
1224 return (UINT_PTR)KEY_DESKTOP;
1225 }
1226
1227 case SPI_GETACCESSTIMEOUT:
1228 {
1229 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1230
1231 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1232 return 0;
1233
1234 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1235 return 0;
1236
1237 return SpiGetEx(pvParam, &gspv.accesstimeout, sizeof(ACCESSTIMEOUT), fl);
1238 }
1239
1240 case SPI_SETACCESSTIMEOUT:
1241 {
1242 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1243
1244 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1245 {
1246 return 0;
1247 }
1248
1249 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1250 {
1251 return 0;
1252 }
1253
1254 if (!SpiSet(&gspv.accesstimeout, pvParam, sizeof(ACCESSTIMEOUT), fl))
1255 return 0;
1256
1257 if (fl & SPIF_UPDATEINIFILE)
1258 {
1259 // FIXME: What to do?
1260 }
1261 return (UINT_PTR)KEY_DESKTOP;
1262 }
1263
1264 case SPI_GETSERIALKEYS:
1265 {
1266 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1267
1268 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1269 return 0;
1270
1271 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1272 return 0;
1273
1274 return SpiGet(pvParam, &gspv.serialkeys, sizeof(SERIALKEYS), fl);
1275 }
1276
1277 case SPI_SETSERIALKEYS:
1278 {
1279 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1280
1281 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1282 return 0;
1283
1284 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1285 return 0;
1286
1287 if (!SpiSet(&gspv.serialkeys, pvParam, sizeof(SERIALKEYS), fl))
1288 return 0;
1289
1290 if (fl & SPIF_UPDATEINIFILE)
1291 {
1292 // FIXME: What to do?
1293 }
1294 return (UINT_PTR)KEY_DESKTOP;
1295 }
1296
1297 case SPI_GETSOUNDSENTRY:
1298 {
1299 LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1300
1301 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1302 return 0;
1303
1304 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1305 return 0;
1306
1307 return SpiGet(pvParam, &gspv.soundsentry, sizeof(SOUNDSENTRYW), fl);
1308 }
1309
1310 case SPI_SETSOUNDSENTRY:
1311 {
1312 LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1313
1314 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1315 return 0;
1316
1317 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1318 return 0;
1319
1320 if (!SpiSet(&gspv.soundsentry, pvParam, sizeof(SOUNDSENTRYW), fl))
1321 return 0;
1322
1323 if (fl & SPIF_UPDATEINIFILE)
1324 {
1325 // FIXME: What to do?
1326 }
1327 return (UINT_PTR)KEY_DESKTOP;
1328 }
1329
1330 case SPI_GETHIGHCONTRAST:
1331 {
1332 LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1333
1334 if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1335 return 0;
1336
1337 if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1338 return 0;
1339
1340 return SpiGet(pvParam, &gspv.highcontrast, sizeof(HIGHCONTRASTW), fl);
1341 }
1342
1343 case SPI_SETHIGHCONTRAST:
1344 {
1345 LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1346
1347 if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1348 return 0;
1349
1350 if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1351 return 0;
1352
1353 if (!SpiSet(&gspv.highcontrast, pvParam, sizeof(HIGHCONTRASTW), fl))
1354 return 0;
1355
1356 if (fl & SPIF_UPDATEINIFILE)
1357 {
1358 // FIXME: What to do?
1359 }
1360 return (UINT_PTR)KEY_DESKTOP;
1361 }
1362
1363 case SPI_GETKEYBOARDPREF:
1364 return SpiGetInt(pvParam, &gspv.bKbdPref, fl);
1365
1366 case SPI_SETKEYBOARDPREF:
1367 return SpiSetBool(&gspv.bKbdPref, uiParam, KEY_KDBPREF, VAL_ON, fl);
1368
1369 case SPI_GETSCREENREADER:
1370 return SpiGetInt(pvParam, &gspv.bScreenReader, fl);
1371
1372 case SPI_SETSCREENREADER:
1373 return SpiSetBool(&gspv.bScreenReader, uiParam, KEY_SCRREAD, VAL_ON, fl);
1374
1375 case SPI_GETANIMATION:
1376 return SpiGet(pvParam, &gspv.animationinfo, sizeof(ANIMATIONINFO), fl);
1377
1378 case SPI_SETANIMATION:
1379 if (!SpiSet(&gspv.animationinfo, pvParam, sizeof(ANIMATIONINFO), fl))
1380 return 0;
1381 if (fl & SPIF_UPDATEINIFILE)
1382 {
1383 // FIXME: What to do?
1384 }
1385 return (UINT_PTR)KEY_DESKTOP;
1386
1387 case SPI_GETFONTSMOOTHING:
1388 return SpiGetInt(pvParam, &gspv.bFontSmoothing, fl);
1389
1390 case SPI_SETFONTSMOOTHING:
1391 gspv.bFontSmoothing = (uiParam == 2);
1392 if (fl & SPIF_UPDATEINIFILE)
1393 {
1394 SpiStoreSz(KEY_DESKTOP, VAL_FONTSMOOTHING, (uiParam == 2) ? L"2" : L"0");
1395 }
1396 return (UINT_PTR)KEY_DESKTOP;
1397
1398 case SPI_SETDRAGWIDTH:
1399 return SpiSetInt(&gspv.iDragWidth, uiParam, KEY_DESKTOP, VAL_DRAGWIDTH, fl);
1400
1401 case SPI_SETDRAGHEIGHT:
1402 return SpiSetInt(&gspv.iDragHeight, uiParam, KEY_DESKTOP, VAL_DRAGHEIGHT, fl);
1403
1404 case SPI_SETHANDHELD:
1405 return SpiSetBool(&gspv.bHandHeld, uiParam, KEY_DESKTOP, L"HandHeld", fl);
1406
1407 case SPI_GETLOWPOWERTIMEOUT:
1408 return SpiGetInt(pvParam, &gspv.iLowPwrTimeout, fl);
1409
1410 case SPI_GETPOWEROFFTIMEOUT:
1411 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1412
1413 case SPI_SETLOWPOWERTIMEOUT:
1414 return SpiSetInt(&gspv.iLowPwrTimeout, uiParam, KEY_DESKTOP, L"LowPowerTimeOut", fl);
1415
1416 case SPI_SETPOWEROFFTIMEOUT:
1417 return SpiSetInt(&gspv.iPwrOffTimeout, uiParam, KEY_DESKTOP, L"PowerOffTimeOut", fl);
1418
1419 case SPI_GETLOWPOWERACTIVE:
1420 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1421
1422 case SPI_GETPOWEROFFACTIVE:
1423 return SpiGetInt(pvParam, &gspv.bPwrOffActive, fl);
1424
1425 case SPI_SETLOWPOWERACTIVE:
1426 return SpiSetBool(&gspv.bLowPwrActive, uiParam, KEY_DESKTOP, L"LowPowerActive", fl);
1427
1428 case SPI_SETPOWEROFFACTIVE:
1429 return SpiSetBool(&gspv.bPwrOffActive, uiParam, KEY_DESKTOP, L"PowerOffActive", fl);
1430
1431 case SPI_SETCURSORS:
1432 ERR("SPI_SETCURSORS is unimplemented\n");
1433 break;
1434
1435 case SPI_SETICONS:
1436 ERR("SPI_SETICONS is unimplemented\n");
1437 break;
1438
1439 case SPI_GETDEFAULTINPUTLANG:
1440 if (!gspklBaseLayout)
1441 return FALSE;
1442
1443 return SpiGet(pvParam, &gspklBaseLayout->hkl, sizeof(HKL), fl);
1444
1445 case SPI_SETDEFAULTINPUTLANG:
1446 {
1447 HKL hkl;
1448
1449 /* Note: SPIF_UPDATEINIFILE is not supported */
1450 if ((fl & SPIF_UPDATEINIFILE) || !SpiSet(&hkl, pvParam, sizeof(hkl), fl))
1451 return FALSE;
1452
1453 return UserSetDefaultInputLang(hkl);
1454 }
1455
1456 case SPI_SETLANGTOGGLE:
1457 gdwLanguageToggleKey = UserGetLanguageToggle();
1458 return gdwLanguageToggleKey;
1459 break;
1460
1461 case SPI_GETWINDOWSEXTENSION:
1462 ERR("SPI_GETWINDOWSEXTENSION is unimplemented\n");
1463 break;
1464
1465 case SPI_GETMOUSETRAILS:
1466 return SpiGetInt(pvParam, &gspv.iMouseTrails, fl);
1467
1468 case SPI_SETMOUSETRAILS:
1469 return SpiSetInt(&gspv.iMouseTrails, uiParam, KEY_MOUSE, VAL_MOUSETRAILS, fl);
1470
1471 case SPI_GETSNAPTODEFBUTTON:
1472 return SpiGetInt(pvParam, &gspv.bSnapToDefBtn, fl);
1473
1474 case SPI_SETSNAPTODEFBUTTON:
1475 return SpiSetBool(&gspv.bSnapToDefBtn, uiParam, KEY_MOUSE, VAL_SNAPDEFBTN, fl);
1476
1477 case SPI_GETMOUSEHOVERWIDTH:
1478 return SpiGetInt(pvParam, &gspv.iMouseHoverWidth, fl);
1479
1480 case SPI_SETMOUSEHOVERWIDTH:
1481 return SpiSetInt(&gspv.iMouseHoverWidth, uiParam, KEY_MOUSE, VAL_HOVERWIDTH, fl);
1482
1483 case SPI_GETMOUSEHOVERHEIGHT:
1484 return SpiGetInt(pvParam, &gspv.iMouseHoverHeight, fl);
1485
1486 case SPI_SETMOUSEHOVERHEIGHT:
1487 return SpiSetInt(&gspv.iMouseHoverHeight, uiParam, KEY_MOUSE, VAL_HOVERHEIGHT, fl);
1488
1489 case SPI_GETMOUSEHOVERTIME:
1490 return SpiGetInt(pvParam, &gspv.iMouseHoverTime, fl);
1491
1492 case SPI_SETMOUSEHOVERTIME:
1493 /* See http://msdn2.microsoft.com/en-us/library/ms724947.aspx
1494 * copy text from it, if some agument why xp and 2003 behovir diffent
1495 * only if they do not have SP install
1496 * " Windows Server 2003 and Windows XP: The operating system does not
1497 * enforce the use of USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM until
1498 * Windows Server 2003 SP1 and Windows XP SP2 "
1499 */
1500 return SpiSetInt(&gspv.iMouseHoverTime, uiParam, KEY_MOUSE, VAL_HOVERTIME, fl);
1501
1502 case SPI_GETWHEELSCROLLLINES:
1503 return SpiGetInt(pvParam, &gspv.iWheelScrollLines, fl);
1504
1505 case SPI_SETWHEELSCROLLLINES:
1506 return SpiSetInt(&gspv.iWheelScrollLines, uiParam, KEY_DESKTOP, VAL_SCRLLLINES, fl);
1507
1508 case SPI_GETMENUSHOWDELAY:
1509 return SpiGetInt(pvParam, &gspv.dwMenuShowDelay, fl);
1510
1511 case SPI_SETMENUSHOWDELAY:
1512 return SpiSetInt(&gspv.dwMenuShowDelay, uiParam, KEY_DESKTOP, L"MenuShowDelay", fl);
1513
1514 #if (_WIN32_WINNT >= 0x0600)
1515 case SPI_GETWHEELSCROLLCHARS:
1516 return SpiGetInt(pvParam, &gspv.uiWheelScrollChars, fl);
1517
1518 case SPI_SETWHEELSCROLLCHARS:
1519 return SpiSetInt(&gspv.uiWheelScrollChars, uiParam, KEY_DESKTOP, VAL_SCRLLCHARS, fl);
1520 #endif
1521 case SPI_GETSHOWIMEUI:
1522 return SpiGetInt(pvParam, &gspv.bShowImeUi, fl);
1523
1524 case SPI_SETSHOWIMEUI:
1525 return SpiSetBool(&gspv.bShowImeUi, uiParam, KEY_DESKTOP, L"", fl);
1526
1527 case SPI_GETMOUSESPEED:
1528 return SpiGetInt(pvParam, &gspv.iMouseSpeed, fl);
1529
1530 case SPI_SETMOUSESPEED:
1531 {
1532 /* Allowed range is [1:20] */
1533 if ((INT_PTR)pvParam < 1 || (INT_PTR)pvParam > 20)
1534 return 0;
1535 else
1536 return SpiSetInt(&gspv.iMouseSpeed, (INT_PTR)pvParam, KEY_MOUSE, VAL_SENSITIVITY, fl);
1537 }
1538
1539 case SPI_GETSCREENSAVERRUNNING:
1540 return SpiGetInt(pvParam, &gspv.bScrSaverRunning, fl);
1541
1542 case SPI_SETSCREENSAVERRUNNING:
1543 // FIXME: also return value?
1544 return SpiSetBool(&gspv.bScrSaverRunning, uiParam, KEY_MOUSE, L"", fl);
1545
1546 #if(WINVER >= 0x0600)
1547 case SPI_GETAUDIODESCRIPTION:
1548 return SpiGet(pvParam, &gspv.audiodescription, sizeof(AUDIODESCRIPTION), fl);
1549
1550 case SPI_SETAUDIODESCRIPTION:
1551 ERR("SPI_SETAUDIODESCRIPTION is unimplemented\n");
1552 break;
1553
1554 case SPI_GETSCREENSAVESECURE:
1555 return SpiGetInt(pvParam, &gspv.bScrSaverSecure, fl);
1556
1557 case SPI_SETSCREENSAVESECURE:
1558 return SpiSetBool(&gspv.bScrSaverSecure, uiParam, KEY_DESKTOP, L"ScreenSaverIsSecure", fl);
1559 #endif
1560
1561 case SPI_GETACTIVEWINDOWTRACKING:
1562 return SpiGetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1563
1564 case SPI_SETACTIVEWINDOWTRACKING:
1565 return SpiSetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1566
1567 case SPI_GETMENUANIMATION:
1568 return SpiGetUserPref(UPM_MENUANIMATION, pvParam, fl);
1569
1570 case SPI_SETMENUANIMATION:
1571 return SpiSetUserPref(UPM_MENUANIMATION, pvParam, fl);
1572
1573 case SPI_GETCOMBOBOXANIMATION:
1574 return SpiGetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1575
1576 case SPI_SETCOMBOBOXANIMATION:
1577 return SpiSetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1578
1579 case SPI_GETLISTBOXSMOOTHSCROLLING:
1580 return SpiGetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1581
1582 case SPI_SETLISTBOXSMOOTHSCROLLING:
1583 return SpiSetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1584
1585 case SPI_GETGRADIENTCAPTIONS:
1586 {
1587 if (NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL) <= 8)
1588 {
1589 INT iValue = 0;
1590 return SpiGetInt(pvParam, &iValue, fl);
1591 }
1592 else
1593 {
1594 return SpiGetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1595 }
1596 }
1597
1598 case SPI_SETGRADIENTCAPTIONS:
1599 return SpiSetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1600
1601 case SPI_GETKEYBOARDCUES:
1602 return SpiGetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1603
1604 case SPI_SETKEYBOARDCUES:
1605 return SpiSetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1606
1607 case SPI_GETACTIVEWNDTRKZORDER:
1608 return SpiGetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1609
1610 case SPI_SETACTIVEWNDTRKZORDER:
1611 return SpiSetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1612
1613 case SPI_GETHOTTRACKING:
1614 return SpiGetUserPref(UPM_HOTTRACKING, pvParam, fl);
1615
1616 case SPI_SETHOTTRACKING:
1617 return SpiSetUserPref(UPM_HOTTRACKING, pvParam, fl);
1618
1619 case SPI_GETMENUFADE:
1620 return SpiGetUserPref(UPM_MENUFADE, pvParam, fl);
1621
1622 case SPI_SETMENUFADE:
1623 return SpiSetUserPref(UPM_MENUFADE, pvParam, fl);
1624
1625 case SPI_GETSELECTIONFADE:
1626 return SpiGetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1627
1628 case SPI_SETSELECTIONFADE:
1629 return SpiSetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1630
1631 case SPI_GETTOOLTIPANIMATION:
1632 return SpiGetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1633
1634 case SPI_SETTOOLTIPANIMATION:
1635 return SpiSetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1636
1637 case SPI_GETTOOLTIPFADE:
1638 return SpiGetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1639
1640 case SPI_SETTOOLTIPFADE:
1641 return SpiSetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1642
1643 case SPI_GETCURSORSHADOW:
1644 return SpiGetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1645
1646 case SPI_SETCURSORSHADOW:
1647 gspv.bMouseCursorShadow = PtrToUlong(pvParam);
1648 return SpiSetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1649
1650 case SPI_GETUIEFFECTS:
1651 return SpiGetUserPref(UPM_UIEFFECTS, pvParam, fl);
1652
1653 case SPI_SETUIEFFECTS:
1654 return SpiSetUserPref(UPM_UIEFFECTS, pvParam, fl);
1655
1656 case SPI_GETMOUSESONAR:
1657 return SpiGetInt(pvParam, &gspv.bMouseSonar, fl);
1658
1659 case SPI_SETMOUSESONAR:
1660 return SpiSetBool(&gspv.bMouseSonar, uiParam, KEY_MOUSE, L"", fl);
1661
1662 case SPI_GETMOUSECLICKLOCK:
1663 return SpiGetUserPref(UPM_CLICKLOCK, pvParam, fl);
1664
1665 case SPI_SETMOUSECLICKLOCK:
1666 gspv.bMouseClickLock = PtrToUlong(pvParam);
1667 return SpiSetUserPref(UPM_CLICKLOCK, pvParam, fl);
1668
1669 case SPI_GETMOUSEVANISH:
1670 return SpiGetInt(pvParam, &gspv.bMouseVanish, fl);
1671
1672 case SPI_SETMOUSEVANISH:
1673 return SpiSetBool(&gspv.bMouseVanish, uiParam, KEY_MOUSE, L"", fl);
1674
1675 case SPI_GETFLATMENU:
1676 return SpiGetUserPref(UPM_FLATMENU, pvParam, fl);
1677
1678 case SPI_SETFLATMENU:
1679 return SpiSetUserPref(UPM_FLATMENU, pvParam, fl);
1680
1681 case SPI_GETDROPSHADOW:
1682 return SpiGetUserPref(UPM_DROPSHADOW, pvParam, fl);
1683
1684 case SPI_SETDROPSHADOW:
1685 return SpiSetUserPref(UPM_DROPSHADOW, pvParam, fl);
1686
1687 case SPI_GETBLOCKSENDINPUTRESETS:
1688 return SpiGetInt(pvParam, &gspv.bBlockSendInputResets, fl);
1689
1690 case SPI_SETBLOCKSENDINPUTRESETS:
1691 return SpiSetBool(&gspv.bBlockSendInputResets, uiParam, KEY_MOUSE, L"", fl);
1692
1693 #if(_WIN32_WINNT >= 0x0600)
1694 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1695 return SpiGetInt(pvParam, &gspv.bDisableOverlappedContent, fl);
1696
1697 case SPI_SETDISABLEOVERLAPPEDCONTENT:
1698 return SpiSetBool(&gspv.bDisableOverlappedContent, uiParam, KEY_MOUSE, L"", fl);
1699
1700 case SPI_GETCLIENTAREAANIMATION:
1701 return SpiGetInt(pvParam, &gspv.bClientAreaAnimation, fl);
1702
1703 case SPI_SETCLIENTAREAANIMATION:
1704 return SpiSetBool(&gspv.bClientAreaAnimation, uiParam, KEY_MOUSE, L"", fl);
1705
1706 case SPI_GETCLEARTYPE:
1707 return SpiGetInt(pvParam, &gspv.bClearType, fl);
1708
1709 case SPI_SETCLEARTYPE:
1710 return SpiSetBool(&gspv.bClearType, uiParam, KEY_MOUSE, L"", fl);
1711
1712 case SPI_GETSPEECHRECOGNITION:
1713 return SpiGetInt(pvParam, &gspv.bSpeechRecognition, fl);
1714
1715 case SPI_SETSPEECHRECOGNITION:
1716 return SpiSetBool(&gspv.bSpeechRecognition, uiParam, KEY_MOUSE, L"", fl);
1717 #endif
1718
1719 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1720 return SpiGetInt(pvParam, &gspv.dwForegroundLockTimeout, fl);
1721
1722 case SPI_SETFOREGROUNDLOCKTIMEOUT:
1723 return SpiSetInt(&gspv.dwForegroundLockTimeout, uiParam, KEY_MOUSE, L"", fl);
1724
1725 case SPI_GETACTIVEWNDTRKTIMEOUT:
1726 return SpiGetInt(pvParam, &gspv.dwActiveTrackingTimeout, fl);
1727
1728 case SPI_SETACTIVEWNDTRKTIMEOUT:
1729 return SpiSetInt(&gspv.dwActiveTrackingTimeout, uiParam, KEY_MOUSE, L"", fl);
1730
1731 case SPI_GETFOREGROUNDFLASHCOUNT:
1732 return SpiGetInt(pvParam, &gspv.dwForegroundFlashCount, fl);
1733
1734 case SPI_SETFOREGROUNDFLASHCOUNT:
1735 return SpiSetInt(&gspv.dwForegroundFlashCount, uiParam, KEY_MOUSE, L"", fl);
1736
1737 case SPI_GETCARETWIDTH:
1738 return SpiGetInt(pvParam, &gspv.dwCaretWidth, fl);
1739
1740 case SPI_SETCARETWIDTH:
1741 return SpiSetInt(&gspv.dwCaretWidth, uiParam, KEY_MOUSE, L"", fl);
1742
1743 case SPI_GETMOUSECLICKLOCKTIME:
1744 return SpiGetInt(pvParam, &gspv.dwMouseClickLockTime, fl);
1745
1746 case SPI_SETMOUSECLICKLOCKTIME:
1747 return SpiSetDWord(&gspv.dwMouseClickLockTime, uiParam, KEY_DESKTOP, VAL_CLICKLOCKTIME, fl);
1748
1749 case SPI_GETFONTSMOOTHINGTYPE:
1750 return SpiGetInt(pvParam, &gspv.uiFontSmoothingType, fl);
1751
1752 case SPI_SETFONTSMOOTHINGTYPE:
1753 return SpiSetDWord(&gspv.uiFontSmoothingType, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGTYPE, fl);
1754
1755 case SPI_GETFONTSMOOTHINGCONTRAST:
1756 return SpiGetInt(pvParam, &gspv.uiFontSmoothingContrast, fl);
1757
1758 case SPI_SETFONTSMOOTHINGCONTRAST:
1759 return SpiSetDWord(&gspv.uiFontSmoothingContrast, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGCONTRAST, fl);
1760
1761 case SPI_GETFOCUSBORDERWIDTH:
1762 return SpiGetInt(pvParam, &gspv.uiFocusBorderWidth, fl);
1763
1764 case SPI_SETFOCUSBORDERWIDTH:
1765 return SpiSetInt(&gspv.uiFocusBorderWidth, uiParam, KEY_MOUSE, L"", fl);
1766
1767 case SPI_GETFOCUSBORDERHEIGHT:
1768 return SpiGetInt(pvParam, &gspv.uiFocusBorderHeight, fl);
1769
1770 case SPI_SETFOCUSBORDERHEIGHT:
1771 return SpiSetInt(&gspv.uiFocusBorderHeight, uiParam, KEY_MOUSE, L"", fl);
1772
1773 case SPI_GETFONTSMOOTHINGORIENTATION:
1774 return SpiGetInt(pvParam, &gspv.uiFontSmoothingOrientation, fl);
1775
1776 case SPI_SETFONTSMOOTHINGORIENTATION:
1777 return SpiSetDWord(&gspv.uiFontSmoothingOrientation, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGORIENTATION, fl);
1778
1779 /* The following are undocumented, but valid SPI values */
1780 case 0x1010:
1781 case 0x1011:
1782 case 0x1028:
1783 case 0x1029:
1784 case 0x102A:
1785 case 0x102B:
1786 case 0x102C:
1787 case 0x102D:
1788 case 0x102E:
1789 case 0x102F:
1790 case 0x1030:
1791 case 0x1031:
1792 case 0x1032:
1793 case 0x1033:
1794 case 0x1034:
1795 case 0x1035:
1796 case 0x1036:
1797 case 0x1037:
1798 case 0x1038:
1799 case 0x1039:
1800 case 0x103A:
1801 case 0x103B:
1802 case 0x103C:
1803 case 0x103D:
1804 ERR("Undocumented SPI value %x is unimplemented\n", uiAction);
1805 break;
1806
1807 default:
1808 ERR("Invalid SPI value: %u\n", uiAction);
1809 EngSetLastError(ERROR_INVALID_PARAMETER);
1810 return 0;
1811 }
1812
1813 return 0;
1814 }
1815
1816 static BOOL
1817 SpiGetSetProbeBuffer(UINT uiAction, UINT uiParam, PVOID pvParam)
1818 {
1819 BOOL bToUser = TRUE;
1820 ULONG cbSize = 0;
1821
1822 switch (uiAction)
1823 {
1824 case SPI_GETBEEP:
1825 case SPI_GETBORDER:
1826 case SPI_GETKEYBOARDSPEED:
1827 case SPI_GETSCREENSAVETIMEOUT:
1828 case SPI_GETSCREENSAVEACTIVE:
1829 case SPI_GETGRIDGRANULARITY:
1830 case SPI_GETKEYBOARDDELAY:
1831 case SPI_GETICONTITLEWRAP:
1832 case SPI_GETMENUDROPALIGNMENT:
1833 case SPI_GETFASTTASKSWITCH:
1834 case SPI_GETDRAGFULLWINDOWS:
1835 case SPI_GETSHOWSOUNDS:
1836 case SPI_GETKEYBOARDPREF:
1837 case SPI_GETSCREENREADER:
1838 case SPI_GETFONTSMOOTHING:
1839 case SPI_GETLOWPOWERTIMEOUT:
1840 case SPI_GETPOWEROFFTIMEOUT:
1841 case SPI_GETLOWPOWERACTIVE:
1842 case SPI_GETPOWEROFFACTIVE:
1843 case SPI_GETMOUSETRAILS:
1844 case SPI_GETSNAPTODEFBUTTON:
1845 case SPI_GETMOUSEHOVERWIDTH:
1846 case SPI_GETMOUSEHOVERHEIGHT:
1847 case SPI_GETMOUSEHOVERTIME:
1848 case SPI_GETWHEELSCROLLLINES:
1849 case SPI_GETMENUSHOWDELAY:
1850 #if (_WIN32_WINNT >= 0x0600)
1851 case SPI_GETWHEELSCROLLCHARS:
1852 #endif
1853 case SPI_GETSHOWIMEUI:
1854 case SPI_GETMOUSESPEED:
1855 case SPI_GETSCREENSAVERRUNNING:
1856 #if(WINVER >= 0x0600)
1857 case SPI_GETSCREENSAVESECURE:
1858 #endif
1859 case SPI_GETACTIVEWINDOWTRACKING:
1860 case SPI_GETMENUANIMATION:
1861 case SPI_GETCOMBOBOXANIMATION:
1862 case SPI_GETLISTBOXSMOOTHSCROLLING:
1863 case SPI_GETGRADIENTCAPTIONS:
1864 case SPI_GETKEYBOARDCUES:
1865 case SPI_GETACTIVEWNDTRKZORDER:
1866 case SPI_GETHOTTRACKING:
1867 case SPI_GETMENUFADE:
1868 case SPI_GETSELECTIONFADE:
1869 case SPI_GETTOOLTIPANIMATION:
1870 case SPI_GETTOOLTIPFADE:
1871 case SPI_GETCURSORSHADOW:
1872 case SPI_GETUIEFFECTS:
1873 case SPI_GETMOUSESONAR:
1874 case SPI_GETMOUSECLICKLOCK:
1875 case SPI_GETMOUSEVANISH:
1876 case SPI_GETFLATMENU:
1877 case SPI_GETDROPSHADOW:
1878 case SPI_GETBLOCKSENDINPUTRESETS:
1879 #if(_WIN32_WINNT >= 0x0600)
1880 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1881 case SPI_GETCLIENTAREAANIMATION:
1882 case SPI_GETCLEARTYPE:
1883 case SPI_GETSPEECHRECOGNITION:
1884 #endif
1885 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1886 case SPI_GETACTIVEWNDTRKTIMEOUT:
1887 case SPI_GETFOREGROUNDFLASHCOUNT:
1888 case SPI_GETCARETWIDTH:
1889 case SPI_GETMOUSECLICKLOCKTIME:
1890 case SPI_GETFONTSMOOTHINGTYPE:
1891 case SPI_GETFONTSMOOTHINGCONTRAST:
1892 case SPI_GETFOCUSBORDERWIDTH:
1893 case SPI_GETFOCUSBORDERHEIGHT:
1894 case SPI_GETFONTSMOOTHINGORIENTATION:
1895 cbSize = sizeof(INT);
1896 break;
1897
1898 case SPI_ICONHORIZONTALSPACING:
1899 case SPI_ICONVERTICALSPACING:
1900 if (pvParam) cbSize = sizeof(INT);
1901 break;
1902
1903 case SPI_GETMOUSE:
1904 cbSize = 3 * sizeof(INT);
1905 break;
1906
1907 case SPI_GETDESKWALLPAPER:
1908 cbSize = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
1909 break;
1910
1911 case SPI_GETICONTITLELOGFONT:
1912 cbSize = sizeof(LOGFONTW);
1913 break;
1914
1915 case SPI_GETNONCLIENTMETRICS:
1916 cbSize = sizeof(NONCLIENTMETRICSW);
1917 break;
1918
1919 case SPI_GETMINIMIZEDMETRICS:
1920 cbSize = sizeof(MINIMIZEDMETRICS);
1921 break;
1922
1923 case SPI_GETICONMETRICS:
1924 cbSize = sizeof(ICONMETRICSW);
1925 break;
1926
1927 case SPI_GETWORKAREA:
1928 cbSize = sizeof(RECTL);
1929 break;
1930
1931 case SPI_GETFILTERKEYS:
1932 cbSize = sizeof(FILTERKEYS);
1933 break;
1934
1935 case SPI_GETTOGGLEKEYS:
1936 cbSize = sizeof(TOGGLEKEYS);
1937 break;
1938
1939 case SPI_GETMOUSEKEYS:
1940 cbSize = sizeof(MOUSEKEYS);
1941 break;
1942
1943 case SPI_GETSTICKYKEYS:
1944 cbSize = sizeof(STICKYKEYS);
1945 break;
1946
1947 case SPI_GETACCESSTIMEOUT:
1948 cbSize = sizeof(ACCESSTIMEOUT);
1949 break;
1950
1951 case SPI_GETSERIALKEYS:
1952 cbSize = sizeof(SERIALKEYS);
1953 break;
1954
1955 case SPI_GETSOUNDSENTRY:
1956 cbSize = sizeof(SOUNDSENTRYW);
1957 break;
1958
1959 case SPI_GETHIGHCONTRAST:
1960 cbSize = sizeof(HIGHCONTRASTW);
1961 break;
1962
1963 case SPI_GETANIMATION:
1964 cbSize = sizeof(ANIMATIONINFO);
1965 break;
1966
1967 case SPI_GETDEFAULTINPUTLANG:
1968 cbSize = sizeof(HKL);
1969 break;
1970
1971 #if(WINVER >= 0x0600)
1972 case SPI_GETAUDIODESCRIPTION:
1973 cbSize = sizeof(AUDIODESCRIPTION);
1974 break;
1975 #endif
1976
1977 case SPI_SETMOUSE:
1978 cbSize = 3 * sizeof(INT);
1979 bToUser = FALSE;
1980 break;
1981
1982 case SPI_SETICONTITLELOGFONT:
1983 cbSize = sizeof(LOGFONTW);
1984 bToUser = FALSE;
1985 break;
1986
1987 case SPI_SETNONCLIENTMETRICS:
1988 cbSize = sizeof(NONCLIENTMETRICSW);
1989 bToUser = FALSE;
1990 break;
1991
1992 case SPI_SETMINIMIZEDMETRICS:
1993 cbSize = sizeof(MINIMIZEDMETRICS);
1994 bToUser = FALSE;
1995 break;
1996
1997 case SPI_SETICONMETRICS:
1998 cbSize = sizeof(ICONMETRICSW);
1999 bToUser = FALSE;
2000 break;
2001
2002 case SPI_SETWORKAREA:
2003 cbSize = sizeof(RECTL);
2004 bToUser = FALSE;
2005 break;
2006
2007 case SPI_SETFILTERKEYS:
2008 cbSize = sizeof(FILTERKEYS);
2009 bToUser = FALSE;
2010 break;
2011
2012 case SPI_SETTOGGLEKEYS:
2013 cbSize = sizeof(TOGGLEKEYS);
2014 bToUser = FALSE;
2015 break;
2016
2017 case SPI_SETMOUSEKEYS:
2018 cbSize = sizeof(MOUSEKEYS);
2019 bToUser = FALSE;
2020 break;
2021
2022 case SPI_SETSTICKYKEYS:
2023 cbSize = sizeof(STICKYKEYS);
2024 bToUser = FALSE;
2025 break;
2026
2027 case SPI_SETACCESSTIMEOUT:
2028 cbSize = sizeof(ACCESSTIMEOUT);
2029 bToUser = FALSE;
2030 break;
2031
2032 case SPI_SETSERIALKEYS:
2033 cbSize = sizeof(SERIALKEYS);
2034 bToUser = FALSE;
2035 break;
2036
2037 case SPI_SETSOUNDSENTRY:
2038 cbSize = sizeof(SOUNDSENTRYW);
2039 bToUser = FALSE;
2040 break;
2041
2042 case SPI_SETHIGHCONTRAST:
2043 cbSize = sizeof(HIGHCONTRASTW);
2044 bToUser = FALSE;
2045 break;
2046
2047 case SPI_SETANIMATION:
2048 cbSize = sizeof(ANIMATIONINFO);
2049 bToUser = FALSE;
2050 break;
2051
2052 case SPI_SETDEFAULTINPUTLANG:
2053 cbSize = sizeof(HKL);
2054 bToUser = FALSE;
2055 break;
2056
2057 case SPI_SETMOUSESPEED:
2058 cbSize = sizeof(INT);
2059 bToUser = FALSE;
2060 break;
2061 }
2062
2063 if (cbSize)
2064 {
2065 _SEH2_TRY
2066 {
2067 if (bToUser)
2068 {
2069 ProbeForWrite(pvParam, cbSize, sizeof(UCHAR));
2070 }
2071 else
2072 {
2073 ProbeForRead(pvParam, cbSize, sizeof(UCHAR));
2074 }
2075 }
2076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2077 {
2078 _SEH2_YIELD(return FALSE);
2079 }
2080 _SEH2_END;
2081 }
2082
2083 return TRUE;
2084 }
2085
2086 BOOL
2087 FASTCALL
2088 UserSystemParametersInfo(
2089 UINT uiAction,
2090 UINT uiParam,
2091 PVOID pvParam,
2092 UINT fWinIni)
2093 {
2094 ULONG_PTR ulResult;
2095 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
2096
2097 ASSERT(ppi);
2098
2099 if (!gbSpiInitialized)
2100 {
2101 KeRosDumpStackFrames(NULL, 20);
2102 //ASSERT(FALSE);
2103 return FALSE;
2104 }
2105
2106 /* Get a pointer to the current Windowstation */
2107 if (!ppi->prpwinsta)
2108 {
2109 ERR("UserSystemParametersInfo called without active window station.\n");
2110 //ASSERT(FALSE);
2111 //return FALSE;
2112 }
2113
2114 if ((fWinIni & SPIF_PROTECT) && !SpiGetSetProbeBuffer(uiAction, uiParam, pvParam))
2115 {
2116 EngSetLastError(ERROR_NOACCESS);
2117 return FALSE;
2118 }
2119
2120 /* Do the actual operation */
2121 ulResult = SpiGetSet(uiAction, uiParam, pvParam, fWinIni);
2122
2123 /* Did we change something? */
2124 if (ulResult > 1)
2125 {
2126 SpiFixupValues();
2127
2128 /* Update system metrics */
2129 InitMetrics();
2130
2131 /* Send notification to toplevel windows, if requested */
2132 if (fWinIni & SPIF_SENDCHANGE)
2133 {
2134 /* Send WM_SETTINGCHANGE to all toplevel windows */
2135 co_IntSendMessageTimeout(HWND_BROADCAST,
2136 WM_SETTINGCHANGE,
2137 (WPARAM)uiAction,
2138 (LPARAM)ulResult,
2139 SMTO_NORMAL,
2140 100,
2141 &ulResult);
2142 }
2143 ulResult = 1;
2144 }
2145
2146 return ulResult;
2147 }
2148
2149 BOOL
2150 APIENTRY
2151 NtUserSystemParametersInfo(
2152 UINT uiAction,
2153 UINT uiParam,
2154 PVOID pvParam,
2155 UINT fWinIni)
2156 {
2157 BOOL bResult;
2158
2159 TRACE("Enter NtUserSystemParametersInfo(%u)\n", uiAction);
2160 UserEnterExclusive();
2161
2162 // FIXME: Get rid of the flags and only use this from um. kernel can access data directly.
2163 /* Set UM memory protection flag */
2164 fWinIni |= SPIF_PROTECT;
2165
2166 /* Call internal function */
2167 bResult = UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
2168
2169 TRACE("Leave NtUserSystemParametersInfo, returning %d\n", bResult);
2170 UserLeave();
2171
2172 return bResult;
2173 }
2174
2175 /* EOF */