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