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