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