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