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