1 /*
2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS win32 kernel mode subsystem server
4 * PURPOSE: System parameters functions
5 * FILE: win32ss/user/ntuser/sysparams.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 // TODO:
10 // - Check all values that are in Winsta in ROS.
11 // - Does setting invalid fonts work?
12 // - Save appropriate text metrics.
13
14 #include <win32k.h>
15 DBG_DEFAULT_CHANNEL(UserSysparams);
16
17 SPIVALUES gspv;
18 BOOL gbSpiInitialized = FALSE;
19 BOOL g_PaintDesktopVersion = FALSE;
20 BOOL g_bWindowSnapEnabled = TRUE;
21
22 // HACK! We initialize SPI before we have a proper surface to get this from.
23 #define dpi 96
24 //(pPrimarySurface->GDIInfo.ulLogPixelsY)
25 #define REG2METRIC(reg) (reg > 0 ? reg : ((-(reg) * dpi + 720) / 1440))
26 #define METRIC2REG(met) (-((((met) * 1440)- 0) / dpi))
27
28 #define REQ_INTERACTIVE_WINSTA(err) \
29 do { \
30 if (GetW32ProcessInfo()->prpwinsta != InputWindowStation) \
31 { \
32 if (GetW32ProcessInfo()->prpwinsta == NULL) \
33 { \
34 ERR("NtUserSystemParametersInfo called without active window station, and it requires an interactive one\n"); \
35 } \
36 else \
37 { \
38 ERR("NtUserSystemParametersInfo requires interactive window station (current is '%wZ')\n", \
39 &(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(GetW32ProcessInfo()->prpwinsta))->Name)); \
40 } \
41 EngSetLastError(err); \
42 return 0; \
43 } \
44 } while (0)
45
46 static const WCHAR* KEY_MOUSE = L"Control Panel\\Mouse";
47 static const WCHAR* VAL_MOUSE1 = L"MouseThreshold1";
48 static const WCHAR* VAL_MOUSE2 = L"MouseThreshold2";
49 static const WCHAR* VAL_MOUSE3 = L"MouseSpeed";
50 static const WCHAR* VAL_MOUSETRAILS = L"MouseTrails";
51 static const WCHAR* VAL_DBLCLKWIDTH = L"DoubleClickWidth";
52 static const WCHAR* VAL_DBLCLKHEIGHT = L"DoubleClickHeight";
53 static const WCHAR* VAL_DBLCLKTIME = L"DoubleClickSpeed";
54 static const WCHAR* VAL_SNAPDEFBTN = L"SnapToDefaultButton";
55 static const WCHAR* VAL_SWAP = L"SwapMouseButtons";
56 static const WCHAR* VAL_HOVERTIME = L"MouseHoverTime";
57 static const WCHAR* VAL_HOVERWIDTH = L"MouseHoverWidth";
58 static const WCHAR* VAL_HOVERHEIGHT = L"MouseHoverHeight";
59 static const WCHAR* VAL_SENSITIVITY = L"MouseSensitivity";
60
61 static const WCHAR* KEY_DESKTOP = L"Control Panel\\Desktop";
62 static const WCHAR* VAL_SCRTO = L"ScreenSaveTimeOut";
63 static const WCHAR* VAL_SCRNSV = L"SCRNSAVE.EXE";
64 static const WCHAR* VAL_SCRACT = L"ScreenSaveActive";
65 static const WCHAR* VAL_GRID = L"GridGranularity";
66 static const WCHAR* VAL_DRAG = L"DragFullWindows";
67 static const WCHAR* VAL_DRAGHEIGHT = L"DragHeight";
68 static const WCHAR* VAL_DRAGWIDTH = L"DragWidth";
69 static const WCHAR* VAL_FONTSMOOTHING = L"FontSmoothing";
70 static const WCHAR* VAL_FONTSMOOTHINGTYPE = L"FontSmoothingType";
71 static const WCHAR* VAL_FONTSMOOTHINGCONTRAST = L"FontSmoothingGamma";
72 static const WCHAR* VAL_FONTSMOOTHINGORIENTATION = L"FontSmoothingOrientation";
73 static const WCHAR* VAL_SCRLLLINES = L"WheelScrollLines";
74 static const WCHAR* VAL_CLICKLOCKTIME = L"ClickLockTime";
75 static const WCHAR* VAL_PAINTDESKVER = L"PaintDesktopVersion";
76 static const WCHAR* VAL_CARETRATE = L"CursorBlinkRate";
77 static const WCHAR* VAL_CARETWIDTH = L"CaretWidth";
78 #if (_WIN32_WINNT >= 0x0600)
79 static const WCHAR* VAL_SCRLLCHARS = L"WheelScrollChars";
80 #endif
81 static const WCHAR* VAL_USERPREFMASK = L"UserPreferencesMask";
82
83 static const WCHAR* KEY_MDALIGN = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
84 static const WCHAR* VAL_MDALIGN = L"MenuDropAlignment";
85
86 static const WCHAR* KEY_METRIC = L"Control Panel\\Desktop\\WindowMetrics";
87 static const WCHAR* VAL_BORDER = L"BorderWidth";
88 static const WCHAR* VAL_ICONSPC = L"IconSpacing";
89 static const WCHAR* VAL_ICONVSPC = L"IconVerticalspacing";
90 static const WCHAR* VAL_ITWRAP = L"IconTitleWrap";
91
92 static const WCHAR* KEY_SOUND = L"Control Panel\\Sound";
93 static const WCHAR* VAL_BEEP = L"Beep";
94
95 static const WCHAR* KEY_KBD = L"Control Panel\\Keyboard";
96 static const WCHAR* VAL_KBDSPD = L"KeyboardSpeed";
97 static const WCHAR* VAL_KBDDELAY = L"KeyboardDelay";
98
99 static const WCHAR* KEY_SHOWSNDS = L"Control Panel\\Accessibility\\ShowSounds";
100 static const WCHAR* KEY_KDBPREF = L"Control Panel\\Accessibility\\Keyboard Preference";
101 static const WCHAR* KEY_SCRREAD = L"Control Panel\\Accessibility\\Blind Access";
102 static const WCHAR* VAL_ON = L"On";
103
104 /** Loading the settings ******************************************************/
105
106 static
107 INT
SpiLoadDWord(PCWSTR pwszKey,PCWSTR pwszValue,INT iValue)108 SpiLoadDWord(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
109 {
110 DWORD Result;
111 if (!RegReadUserSetting(pwszKey, pwszValue, REG_DWORD, &Result, sizeof(Result)))
112 {
113 return iValue;
114 }
115 return Result;
116 }
117
118 static
119 INT
SpiLoadInt(PCWSTR pwszKey,PCWSTR pwszValue,INT iValue)120 SpiLoadInt(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
121 {
122 WCHAR awcBuffer[12];
123 ULONG cbSize;
124
125 cbSize = sizeof(awcBuffer);
126 if (!RegReadUserSetting(pwszKey, pwszValue, REG_SZ, awcBuffer, cbSize))
127 {
128 return iValue;
129 }
130 return _wtoi(awcBuffer);
131 }
132
133 static
134 DWORD
SpiLoadUserPrefMask(DWORD dValue)135 SpiLoadUserPrefMask(DWORD dValue)
136 {
137 DWORD Result;
138 if (!RegReadUserSetting(KEY_DESKTOP, VAL_USERPREFMASK, REG_BINARY, &Result, sizeof(Result)))
139 {
140 return dValue;
141 }
142 return Result;
143 }
144
145 static
146 DWORD
SpiLoadTimeOut(VOID)147 SpiLoadTimeOut(VOID)
148 { // Must have the string!
149 WCHAR szApplicationName[MAX_PATH];
150 RtlZeroMemory(&szApplicationName, sizeof(szApplicationName));
151 if (!RegReadUserSetting(KEY_DESKTOP, VAL_SCRNSV, REG_SZ, &szApplicationName, sizeof(szApplicationName)))
152 {
153 return 0;
154 }
155 if (szApplicationName[0] == 0) return 0;
156 return SpiLoadInt(KEY_DESKTOP, VAL_SCRTO, 600);
157 }
158
159 static
160 INT
SpiLoadMouse(PCWSTR pwszValue,INT iValue)161 SpiLoadMouse(PCWSTR pwszValue, INT iValue)
162 {
163 return SpiLoadInt(KEY_MOUSE, pwszValue, iValue);
164 }
165
166 static
167 INT
SpiLoadMetric(PCWSTR pwszValue,INT iValue)168 SpiLoadMetric(PCWSTR pwszValue, INT iValue)
169 {
170 INT iRegVal;
171
172 iRegVal = SpiLoadInt(KEY_METRIC, pwszValue, METRIC2REG(iValue));
173 TRACE("Loaded metric setting '%S', iValue=%d(reg:%d), ret=%d(reg:%d)\n",
174 pwszValue, iValue, METRIC2REG(iValue), REG2METRIC(iRegVal), iRegVal);
175 return REG2METRIC(iRegVal);
176 }
177
178 static
179 VOID
SpiLoadFont(PLOGFONTW plfOut,LPWSTR pwszValueName,PLOGFONTW plfDefault)180 SpiLoadFont(PLOGFONTW plfOut, LPWSTR pwszValueName, PLOGFONTW plfDefault)
181 {
182 BOOL bResult;
183
184 bResult = RegReadUserSetting(KEY_METRIC,
185 pwszValueName,
186 REG_BINARY,
187 plfOut,
188 sizeof(LOGFONTW));
189 if (!bResult)
190 *plfOut = *plfDefault;
191 }
192
193 static
194 VOID
SpiFixupValues(VOID)195 SpiFixupValues(VOID)
196 {
197 /* Fixup values */
198 gspv.ncm.iCaptionWidth = max(gspv.ncm.iCaptionWidth, 8);
199 gspv.ncm.iBorderWidth = max(gspv.ncm.iBorderWidth, 1);
200 gspv.ncm.iScrollWidth = max(gspv.ncm.iScrollWidth, 8);
201 gspv.ncm.iScrollHeight = max(gspv.ncm.iScrollHeight, 8);
202 // gspv.ncm.iMenuHeight = max(gspv.ncm.iMenuHeight, gspv.tmMenuFont.tmHeight);
203 // gspv.ncm.iMenuHeight = max(gspv.ncm.iMenuHeight,
204 // 2 + gspv.tmMenuFont.tmHeight +
205 // gspv.tmMenuFont.tmExternalLeading);
206 if (gspv.iDblClickTime == 0) gspv.iDblClickTime = 500;
207
208 // FIXME: Hack!!!
209 gspv.tmMenuFont.tmHeight = 11;
210 gspv.tmMenuFont.tmExternalLeading = 2;
211
212 gspv.tmCaptionFont.tmHeight = 11;
213 gspv.tmCaptionFont.tmExternalLeading = 2;
214
215 }
216
217 /* Is Window Snap enabled? */
IntIsWindowSnapEnabled(VOID)218 static BOOL IntIsWindowSnapEnabled(VOID)
219 {
220 WCHAR szValue[2];
221 if (RegReadUserSetting(L"Control Panel\\Desktop", L"WindowArrangementActive",
222 REG_SZ, szValue, sizeof(szValue)))
223 {
224 szValue[RTL_NUMBER_OF(szValue) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
225 return (_wtoi(szValue) != 0);
226 }
227 return TRUE;
228 }
229
230 static
231 VOID
SpiUpdatePerUserSystemParameters(VOID)232 SpiUpdatePerUserSystemParameters(VOID)
233 {
234 static LOGFONTW lf1 = {-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
235 FALSE, ANSI_CHARSET, 0, 0, DEFAULT_QUALITY,
236 VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif"};
237 static LOGFONTW lf2 = {-11, 0, 0, 0, FW_BOLD, FALSE, FALSE,
238 FALSE, ANSI_CHARSET, 0, 0, DEFAULT_QUALITY,
239 VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif"};
240
241 TRACE("Enter SpiUpdatePerUserSystemParameters\n");
242
243 /* Clear the structure */
244 RtlZeroMemory(&gspv, sizeof(gspv));
245
246 /* Load mouse settings */
247 gspv.caiMouse.FirstThreshold = SpiLoadMouse(VAL_MOUSE1, 6);
248 gspv.caiMouse.SecondThreshold = SpiLoadMouse(VAL_MOUSE2, 10);
249 gspv.caiMouse.Acceleration = SpiLoadMouse(VAL_MOUSE3, 1);
250 gspv.iMouseSpeed = SpiLoadMouse(VAL_SENSITIVITY, 10);
251 gspv.bMouseBtnSwap = SpiLoadMouse(VAL_SWAP, 0);
252 gspv.bSnapToDefBtn = SpiLoadMouse(VAL_SNAPDEFBTN, 0);
253 gspv.iMouseTrails = SpiLoadMouse(VAL_MOUSETRAILS, 0);
254 gspv.iDblClickTime = SpiLoadMouse(VAL_DBLCLKTIME, 500);
255 gspv.iDblClickWidth = SpiLoadMouse(VAL_DBLCLKWIDTH, 4);
256 gspv.iDblClickHeight = SpiLoadMouse(VAL_DBLCLKHEIGHT, 4);
257 gspv.iMouseHoverTime = SpiLoadMouse(VAL_HOVERTIME, 400);
258 gspv.iMouseHoverWidth = SpiLoadMouse(VAL_HOVERWIDTH, 4);
259 gspv.iMouseHoverHeight = SpiLoadMouse(VAL_HOVERHEIGHT, 4);
260
261 /* Load keyboard settings */
262 gspv.dwKbdSpeed = SpiLoadInt(KEY_KBD, VAL_KBDSPD, 31);
263 gspv.iKbdDelay = SpiLoadInt(KEY_KBD, VAL_KBDDELAY, 1);
264
265 /* Load NONCLIENTMETRICS */
266 gspv.ncm.cbSize = sizeof(NONCLIENTMETRICSW);
267 gspv.ncm.iBorderWidth = SpiLoadMetric(VAL_BORDER, 1);
268 gspv.ncm.iScrollWidth = SpiLoadMetric(L"ScrollWidth", 16);
269 gspv.ncm.iScrollHeight = SpiLoadMetric(L"ScrollHeight", 16);
270 gspv.ncm.iCaptionWidth = SpiLoadMetric(L"CaptionWidth", 19);
271 gspv.ncm.iCaptionHeight = SpiLoadMetric(L"CaptionHeight", 19);
272 gspv.ncm.iSmCaptionWidth = SpiLoadMetric(L"SmCaptionWidth", 12);
273 gspv.ncm.iSmCaptionHeight = SpiLoadMetric(L"SmCaptionHeight", 15);
274 gspv.ncm.iMenuWidth = SpiLoadMetric(L"MenuWidth", 18);
275 gspv.ncm.iMenuHeight = SpiLoadMetric(L"MenuHeight", 18);
276 #if (WINVER >= 0x0600)
277 gspv.ncm.iPaddedBorderWidth = SpiLoadMetric(L"PaddedBorderWidth", 18);
278 #endif
279 SpiLoadFont(&gspv.ncm.lfCaptionFont, L"CaptionFont", &lf2);
280 SpiLoadFont(&gspv.ncm.lfSmCaptionFont, L"SmCaptionFont", &lf1);
281 SpiLoadFont(&gspv.ncm.lfMenuFont, L"MenuFont", &lf1);
282 SpiLoadFont(&gspv.ncm.lfStatusFont, L"StatusFont", &lf1);
283 SpiLoadFont(&gspv.ncm.lfMessageFont, L"MessageFont", &lf1);
284
285 /* Load MINIMIZEDMETRICS */
286 gspv.mm.cbSize = sizeof(MINIMIZEDMETRICS);
287 gspv.mm.iWidth = SpiLoadMetric(L"MinWidth", 160);
288 gspv.mm.iHorzGap = SpiLoadMetric(L"MinHorzGap", 160);
289 gspv.mm.iVertGap = SpiLoadMetric(L"MinVertGap", 24);
290 gspv.mm.iArrange = SpiLoadInt(KEY_METRIC, L"MinArrange", ARW_HIDE);
291
292 /* Load ICONMETRICS */
293 gspv.im.cbSize = sizeof(ICONMETRICSW);
294 gspv.im.iHorzSpacing = SpiLoadMetric(VAL_ICONSPC, 64);
295 gspv.im.iVertSpacing = SpiLoadMetric(VAL_ICONVSPC, 64);
296 gspv.im.iTitleWrap = SpiLoadMetric(VAL_ITWRAP, 1);
297 SpiLoadFont(&gspv.im.lfFont, L"IconFont", &lf1);
298
299 /* Load desktop settings */
300 gspv.bDragFullWindows = SpiLoadInt(KEY_DESKTOP, VAL_DRAG, 0);
301 gspv.iWheelScrollLines = SpiLoadInt(KEY_DESKTOP, VAL_SCRLLLINES, 3);
302 gspv.dwMouseClickLockTime = SpiLoadDWord(KEY_DESKTOP, VAL_CLICKLOCKTIME, 1200);
303 gpsi->dtCaretBlink = SpiLoadInt(KEY_DESKTOP, VAL_CARETRATE, 530);
304 gspv.dwCaretWidth = SpiLoadDWord(KEY_DESKTOP, VAL_CARETWIDTH, 1);
305 gspv.dwUserPrefMask = SpiLoadUserPrefMask(UPM_DEFAULT);
306 gspv.bMouseClickLock = (gspv.dwUserPrefMask & UPM_CLICKLOCK) != 0;
307 gspv.bMouseCursorShadow = (gspv.dwUserPrefMask & UPM_CURSORSHADOW) != 0;
308 gspv.bFontSmoothing = SpiLoadInt(KEY_DESKTOP, VAL_FONTSMOOTHING, 0) == 2;
309 gspv.uiFontSmoothingType = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGTYPE, 1);
310 gspv.uiFontSmoothingContrast = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGCONTRAST, 1400);
311 gspv.uiFontSmoothingOrientation = SpiLoadDWord(KEY_DESKTOP, VAL_FONTSMOOTHINGORIENTATION, 1);
312 #if (_WIN32_WINNT >= 0x0600)
313 gspv.uiWheelScrollChars = SpiLoadInt(KEY_DESKTOP, VAL_SCRLLCHARS, 3);
314 #endif
315
316 /* Some hardcoded values for now */
317
318 gspv.tmCaptionFont.tmAveCharWidth = 6;
319 gspv.bBeep = TRUE;
320 gspv.uiFocusBorderWidth = 1;
321 gspv.uiFocusBorderHeight = 1;
322 gspv.bMenuDropAlign = 0;
323 gspv.dwMenuShowDelay = SpiLoadInt(KEY_DESKTOP, L"MenuShowDelay", 400);
324 gspv.dwForegroundFlashCount = 3;
325
326 gspv.iScrSaverTimeout = SpiLoadTimeOut();
327 gspv.bScrSaverActive = FALSE;
328 gspv.bScrSaverRunning = FALSE;
329 #if(WINVER >= 0x0600)
330 gspv.bScrSaverSecure = FALSE;
331 #endif
332
333 gspv.bFastTaskSwitch = TRUE;
334
335 gspv.accesstimeout.cbSize = sizeof(ACCESSTIMEOUT);
336 gspv.filterkeys.cbSize = sizeof(FILTERKEYS);
337 gspv.togglekeys.cbSize = sizeof(TOGGLEKEYS);
338 gspv.mousekeys.cbSize = sizeof(MOUSEKEYS);
339 gspv.stickykeys.cbSize = sizeof(STICKYKEYS);
340 gspv.serialkeys.cbSize = sizeof(SERIALKEYS);
341 gspv.soundsentry.cbSize = sizeof(SOUNDSENTRYW);
342 gspv.highcontrast.cbSize = sizeof(HIGHCONTRASTW);
343 gspv.animationinfo.cbSize = sizeof(ANIMATIONINFO);
344
345 /* Make sure we don't use broken values */
346 SpiFixupValues();
347
348 /* Update SystemMetrics */
349 InitMetrics();
350
351 if (gbSpiInitialized && gpsi)
352 {
353 if (gspv.bKbdPref) gpsi->dwSRVIFlags |= SRVINFO_KBDPREF;
354 if (SPITESTPREF(UPM_KEYBOARDCUES)) gpsi->PUSIFlags |= PUSIF_KEYBOARDCUES;
355 if (SPITESTPREF(UPM_COMBOBOXANIMATION)) gpsi->PUSIFlags |= PUSIF_COMBOBOXANIMATION;
356 if (SPITESTPREF(UPM_LISTBOXSMOOTHSCROLLING)) gpsi->PUSIFlags |= PUSIF_LISTBOXSMOOTHSCROLLING;
357 }
358 gdwLanguageToggleKey = UserGetLanguageToggle(L"Language Hotkey", 1);
359 gdwLayoutToggleKey = UserGetLanguageToggle(L"Layout Hotkey", 2);
360
361 g_bWindowSnapEnabled = IntIsWindowSnapEnabled();
362 }
363
364 BOOL
InitSysParams(VOID)365 InitSysParams(VOID)
366 {
367 SpiUpdatePerUserSystemParameters();
368 gbSpiInitialized = TRUE;
369 return TRUE;
370 }
371
372
373 BOOL
374 APIENTRY
NtUserUpdatePerUserSystemParameters(DWORD dwReserved,BOOL bEnable)375 NtUserUpdatePerUserSystemParameters(
376 DWORD dwReserved,
377 BOOL bEnable)
378 {
379 BOOL bResult;
380
381 TRACE("Enter NtUserUpdatePerUserSystemParameters\n");
382 UserEnterExclusive();
383
384 SpiUpdatePerUserSystemParameters();
385 if(bEnable)
386 g_PaintDesktopVersion = SpiLoadDWord(KEY_DESKTOP, VAL_PAINTDESKVER, 0);
387 else
388 g_PaintDesktopVersion = FALSE;
389 bResult = TRUE;
390
391 TRACE("Leave NtUserUpdatePerUserSystemParameters, returning %d\n", bResult);
392 UserLeave();
393
394 return bResult;
395 }
396
397
398 /** Storing the settings ******************************************************/
399
400 static
401 VOID
SpiStoreDWord(PCWSTR pwszKey,PCWSTR pwszValue,DWORD Value)402 SpiStoreDWord(PCWSTR pwszKey, PCWSTR pwszValue, DWORD Value)
403 {
404 RegWriteUserSetting(pwszKey,
405 pwszValue,
406 REG_DWORD,
407 &Value,
408 sizeof(Value));
409 }
410
411 static
412 VOID
SpiStoreSz(PCWSTR pwszKey,PCWSTR pwszValue,PCWSTR pwsz)413 SpiStoreSz(PCWSTR pwszKey, PCWSTR pwszValue, PCWSTR pwsz)
414 {
415 RegWriteUserSetting(pwszKey,
416 pwszValue,
417 REG_SZ,
418 pwsz,
419 (wcslen(pwsz) + 1) * sizeof(WCHAR));
420 }
421
422 static
423 VOID
SpiStoreSzInt(PCWSTR pwszKey,PCWSTR pwszValue,INT iValue)424 SpiStoreSzInt(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue)
425 {
426 WCHAR awcBuffer[15];
427
428 _itow(iValue, awcBuffer, 10);
429 RegWriteUserSetting(pwszKey,
430 pwszValue,
431 REG_SZ,
432 awcBuffer,
433 (wcslen(awcBuffer) + 1) * sizeof(WCHAR));
434 }
435
436 static
437 VOID
SpiStoreMetric(LPCWSTR pwszValue,INT iValue)438 SpiStoreMetric(LPCWSTR pwszValue, INT iValue)
439 {
440 SpiStoreSzInt(KEY_METRIC, pwszValue, METRIC2REG(iValue));
441 }
442
443 static
444 VOID
SpiStoreFont(PCWSTR pwszValue,LOGFONTW * plogfont)445 SpiStoreFont(PCWSTR pwszValue, LOGFONTW* plogfont)
446 {
447 RegWriteUserSetting(KEY_METRIC,
448 pwszValue,
449 REG_BINARY,
450 plogfont,
451 sizeof(LOGFONTW));
452 }
453
454
455 /** Get/Set value *************************************************************/
456
457 // FIXME: get rid of the flags and only use this from um. kernel can access data directly.
458 static
459 UINT_PTR
SpiMemCopy(PVOID pvDst,PVOID pvSrc,ULONG cbSize,BOOL bProtect)460 SpiMemCopy(PVOID pvDst, PVOID pvSrc, ULONG cbSize, BOOL bProtect)
461 {
462 NTSTATUS Status = STATUS_SUCCESS;
463
464 if (bProtect)
465 {
466 _SEH2_TRY
467 {
468 RtlCopyMemory(pvDst, pvSrc, cbSize);
469 }
470 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
471 {
472 Status = _SEH2_GetExceptionCode();
473 }
474 _SEH2_END;
475 }
476 else
477 {
478 RtlCopyMemory(pvDst, pvSrc, cbSize);
479 }
480
481 if (!NT_SUCCESS(Status))
482 {
483 SetLastNtError(Status);
484 ERR("SpiMemCopy failed, pvDst=%p, pvSrc=%p, bProtect=%d\n", pvDst, pvSrc, bProtect);
485 }
486
487 return NT_SUCCESS(Status);
488 }
489
490 static inline
491 UINT_PTR
SpiGet(PVOID pvParam,PVOID pvData,ULONG cbSize,FLONG fl)492 SpiGet(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
493 {
494 REQ_INTERACTIVE_WINSTA(ERROR_ACCESS_DENIED);
495 return SpiMemCopy(pvParam, pvData, cbSize, fl & SPIF_PROTECT);
496 }
497
498 static inline
499 UINT_PTR
SpiSet(PVOID pvData,PVOID pvParam,ULONG cbSize,FLONG fl)500 SpiSet(PVOID pvData, PVOID pvParam, ULONG cbSize, FLONG fl)
501 {
502 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
503 return SpiMemCopy(pvData, pvParam, cbSize, fl & SPIF_PROTECT);
504 }
505
506 static inline
507 UINT_PTR
SpiGetEx(PVOID pvParam,PVOID pvData,ULONG cbSize,FLONG fl)508 SpiGetEx(PVOID pvParam, PVOID pvData, ULONG cbSize, FLONG fl)
509 {
510 ULONG cbBufSize;
511 /* Get the cbSite member from UM memory */
512 if (!SpiSet(&cbBufSize, pvParam, sizeof(ULONG), fl))
513 return 0;
514 /* Verify the correct size */
515 if (cbBufSize != cbSize)
516 return 0;
517 return SpiGet(pvParam, pvData, cbSize, fl);
518 }
519
520 static inline
521 UINT_PTR
SpiGetInt(PVOID pvParam,PVOID piValue,FLONG fl)522 SpiGetInt(PVOID pvParam, PVOID piValue, FLONG fl)
523 {
524 return SpiGet(pvParam, piValue, sizeof(INT), fl);
525 }
526
527 static inline
528 UINT_PTR
SpiSetYesNo(BOOL * pbData,BOOL bValue,PCWSTR pwszKey,PCWSTR pwszValue,FLONG fl)529 SpiSetYesNo(BOOL *pbData, BOOL bValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
530 {
531 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
532 *pbData = bValue ? TRUE : FALSE;
533 if (fl & SPIF_UPDATEINIFILE)
534 {
535 SpiStoreSz(pwszKey, pwszValue, bValue ? L"Yes" : L"No");
536 }
537 return (UINT_PTR)pwszKey;
538 }
539
540 static inline
541 UINT_PTR
SpiSetBool(BOOL * pbData,INT iValue,PCWSTR pwszKey,PCWSTR pwszValue,FLONG fl)542 SpiSetBool(BOOL *pbData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
543 {
544 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
545 *pbData = iValue ? TRUE : FALSE;
546 if (fl & SPIF_UPDATEINIFILE)
547 {
548 SpiStoreSzInt(pwszKey, pwszValue, iValue);
549 }
550 return (UINT_PTR)pwszKey;
551 }
552
553 static inline
554 UINT_PTR
SpiSetDWord(PVOID pvData,INT iValue,PCWSTR pwszKey,PCWSTR pwszValue,FLONG fl)555 SpiSetDWord(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
556 {
557 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
558 *(INT*)pvData = iValue;
559 if (fl & SPIF_UPDATEINIFILE)
560 {
561 SpiStoreDWord(pwszKey, pwszValue, iValue);
562 }
563 return (UINT_PTR)pwszKey;
564 }
565
566 static inline
567 UINT_PTR
SpiSetInt(PVOID pvData,INT iValue,PCWSTR pwszKey,PCWSTR pwszValue,FLONG fl)568 SpiSetInt(PVOID pvData, INT iValue, PCWSTR pwszKey, PCWSTR pwszValue, FLONG fl)
569 {
570 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
571 *(INT*)pvData = iValue;
572 if (fl & SPIF_UPDATEINIFILE)
573 {
574 SpiStoreSzInt(pwszKey, pwszValue, iValue);
575 }
576 return (UINT_PTR)pwszKey;
577 }
578
579 static inline
580 UINT_PTR
SpiSetMetric(PVOID pvData,INT iValue,PCWSTR pwszValue,FLONG fl)581 SpiSetMetric(PVOID pvData, INT iValue, PCWSTR pwszValue, FLONG fl)
582 {
583 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
584 *(INT*)pvData = iValue;
585 if (fl & SPIF_UPDATEINIFILE)
586 {
587 SpiStoreMetric(pwszValue, iValue);
588 }
589 return (UINT_PTR)KEY_METRIC;
590 }
591
592 static inline
593 UINT_PTR
SpiSetUserPref(DWORD dwMask,PVOID pvValue,FLONG fl)594 SpiSetUserPref(DWORD dwMask, PVOID pvValue, FLONG fl)
595 {
596 DWORD dwRegMask;
597 BOOL bValue = PtrToUlong(pvValue);
598
599 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
600
601 /* Set or clear bit according to bValue */
602 gspv.dwUserPrefMask = bValue ? gspv.dwUserPrefMask | dwMask :
603 gspv.dwUserPrefMask & ~dwMask;
604
605 if (fl & SPIF_UPDATEINIFILE)
606 {
607 /* Read current value */
608 if (!RegReadUserSetting(KEY_DESKTOP,
609 VAL_USERPREFMASK,
610 REG_BINARY,
611 &dwRegMask,
612 sizeof(DWORD)))
613 {
614 WARN("Failed to read UserPreferencesMask setting\n");
615 dwRegMask = 0;
616 }
617
618 /* Set or clear bit according to bValue */
619 dwRegMask = bValue ? (dwRegMask | dwMask) : (dwRegMask & ~dwMask);
620
621 /* write back value */
622 RegWriteUserSetting(KEY_DESKTOP,
623 VAL_USERPREFMASK,
624 REG_BINARY,
625 &dwRegMask,
626 sizeof(DWORD));
627 }
628
629 return (UINT_PTR)KEY_DESKTOP;
630 }
631
632 static inline
633 UINT_PTR
SpiGetUserPref(DWORD dwMask,PVOID pvParam,FLONG fl)634 SpiGetUserPref(DWORD dwMask, PVOID pvParam, FLONG fl)
635 {
636 INT iValue = gspv.dwUserPrefMask & dwMask ? 1 : 0;
637 return SpiGetInt(pvParam, &iValue, fl);
638 }
639
640 static
641 UINT_PTR
SpiSetWallpaper(PVOID pvParam,FLONG fl)642 SpiSetWallpaper(PVOID pvParam, FLONG fl)
643 {
644 UNICODE_STRING ustr;
645 WCHAR awc[MAX_PATH];
646 BOOL bResult;
647 HBITMAP hbmp, hOldBitmap;
648 SURFACE *psurfBmp;
649 ULONG ulTile, ulStyle;
650
651 REQ_INTERACTIVE_WINSTA(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
652
653 if (!pvParam)
654 {
655 /* FIXME: Reset Wallpaper to registry value */
656 return (UINT_PTR)KEY_DESKTOP;
657 }
658
659 /* Capture UNICODE_STRING */
660 bResult = SpiMemCopy(&ustr, pvParam, sizeof(ustr), fl & SPIF_PROTECT);
661 if (!bResult)
662 {
663 return 0;
664 }
665 if (ustr.Length > MAX_PATH * sizeof(WCHAR))
666 {
667 return 0;
668 }
669
670 /* Copy the string buffer name */
671 bResult = SpiMemCopy(gspv.awcWallpaper, ustr.Buffer, ustr.Length, fl & SPIF_PROTECT);
672 if (!bResult)
673 {
674 return 0;
675 }
676
677 /* Update the UNICODE_STRING */
678 gspv.ustrWallpaper.Buffer = gspv.awcWallpaper;
679 gspv.ustrWallpaper.MaximumLength = MAX_PATH * sizeof(WCHAR);
680 gspv.ustrWallpaper.Length = ustr.Length;
681 gspv.awcWallpaper[ustr.Length / sizeof(WCHAR)] = 0;
682
683 TRACE("SpiSetWallpaper, name=%S\n", gspv.awcWallpaper);
684
685 /* Update registry */
686 if (fl & SPIF_UPDATEINIFILE)
687 {
688 SpiStoreSz(KEY_DESKTOP, L"Wallpaper", gspv.awcWallpaper);
689 }
690
691 /* Got a filename? */
692 if (gspv.awcWallpaper[0] != 0)
693 {
694 /* Convert file name to nt file name */
695 ustr.Buffer = awc;
696 ustr.MaximumLength = MAX_PATH * sizeof(WCHAR);
697 ustr.Length = 0;
698 if (!W32kDosPathNameToNtPathName(gspv.awcWallpaper, &ustr))
699 {
700 ERR("RtlDosPathNameToNtPathName_U failed\n");
701 return 0;
702 }
703
704 /* Load the Bitmap */
705 hbmp = UserLoadImage(ustr.Buffer);
706 if (!hbmp)
707 {
708 ERR("UserLoadImage failed\n");
709 return 0;
710 }
711
712 /* Try to get the size of the wallpaper */
713 if (!(psurfBmp = SURFACE_ShareLockSurface(hbmp)))
714 {
715 GreDeleteObject(hbmp);
716 return 0;
717 }
718
719 gspv.cxWallpaper = psurfBmp->SurfObj.sizlBitmap.cx;
720 gspv.cyWallpaper = psurfBmp->SurfObj.sizlBitmap.cy;
721 gspv.WallpaperMode = wmCenter;
722
723 SURFACE_ShareUnlockSurface(psurfBmp);
724
725 /* Change the bitmap's ownership */
726 GreSetObjectOwner(hbmp, GDI_OBJ_HMGR_PUBLIC);
727
728 /* Yes, Windows really loads the current setting from the registry. */
729 ulTile = SpiLoadInt(KEY_DESKTOP, L"TileWallpaper", 0);
730 ulStyle = SpiLoadInt(KEY_DESKTOP, L"WallpaperStyle", 0);
731 TRACE("SpiSetWallpaper: ulTile=%lu, ulStyle=%lu\n", ulTile, ulStyle);
732
733 /* Check the values we found in the registry */
734 if (ulTile && !ulStyle)
735 {
736 gspv.WallpaperMode = wmTile;
737 }
738 else if (!ulTile && ulStyle)
739 {
740 if (ulStyle == 2)
741 {
742 gspv.WallpaperMode = wmStretch;
743 }
744 else if (ulStyle == 6)
745 {
746 gspv.WallpaperMode = wmFit;
747 }
748 else if (ulStyle == 10)
749 {
750 gspv.WallpaperMode = wmFill;
751 }
752 }
753 }
754 else
755 {
756 /* Remove wallpaper */
757 gspv.cxWallpaper = 0;
758 gspv.cyWallpaper = 0;
759 hbmp = 0;
760 }
761
762 /* Take care of the old wallpaper, if any */
763 hOldBitmap = gspv.hbmWallpaper;
764 if(hOldBitmap != NULL)
765 {
766 /* Delete the old wallpaper */
767 GreSetObjectOwner(hOldBitmap, GDI_OBJ_HMGR_POWNED);
768 GreDeleteObject(hOldBitmap);
769 }
770
771 /* Set the new wallpaper */
772 gspv.hbmWallpaper = hbmp;
773
774 NtUserRedrawWindow(UserGetShellWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
775
776
777 return (UINT_PTR)KEY_DESKTOP;
778 }
779
780 static BOOL
SpiNotifyNCMetricsChanged(VOID)781 SpiNotifyNCMetricsChanged(VOID)
782 {
783 PWND pwndDesktop, pwndCurrent;
784 HWND *ahwnd;
785 USER_REFERENCE_ENTRY Ref;
786 int i;
787
788 pwndDesktop = UserGetDesktopWindow();
789 ASSERT(pwndDesktop);
790
791 ahwnd = IntWinListChildren(pwndDesktop);
792 if(!ahwnd)
793 return FALSE;
794
795 for (i = 0; ahwnd[i]; i++)
796 {
797 pwndCurrent = UserGetWindowObject(ahwnd[i]);
798 if(!pwndCurrent)
799 continue;
800
801 UserRefObjectCo(pwndCurrent, &Ref);
802 co_WinPosSetWindowPos(pwndCurrent, 0, pwndCurrent->rcWindow.left,pwndCurrent->rcWindow.top,
803 pwndCurrent->rcWindow.right-pwndCurrent->rcWindow.left
804 ,pwndCurrent->rcWindow.bottom - pwndCurrent->rcWindow.top,
805 SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|
806 SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW);
807 UserDerefObjectCo(pwndCurrent);
808 }
809
810 ExFreePoolWithTag(ahwnd, USERTAG_WINDOWLIST);
811
812 return TRUE;
813 }
814
815 static
816 UINT_PTR
SpiGetSet(UINT uiAction,UINT uiParam,PVOID pvParam,FLONG fl)817 SpiGetSet(UINT uiAction, UINT uiParam, PVOID pvParam, FLONG fl)
818 {
819 switch (uiAction)
820 {
821 case SPI_GETBEEP:
822 return SpiGetInt(pvParam, &gspv.bBeep, fl);
823
824 case SPI_SETBEEP:
825 return SpiSetYesNo(&gspv.bBeep, uiParam, KEY_SOUND, VAL_BEEP, fl);
826
827 case SPI_GETMOUSE:
828 return SpiGet(pvParam, &gspv.caiMouse, 3 * sizeof(INT), fl);
829
830 case SPI_SETMOUSE:
831 if (!SpiSet(&gspv.caiMouse, pvParam, 3 * sizeof(INT), fl))
832 return 0;
833 if (fl & SPIF_UPDATEINIFILE)
834 {
835 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE1, gspv.caiMouse.FirstThreshold);
836 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE2, gspv.caiMouse.SecondThreshold);
837 SpiStoreSzInt(KEY_MOUSE, VAL_MOUSE3, gspv.caiMouse.Acceleration);
838 }
839 return (UINT_PTR)KEY_MOUSE;
840
841 case SPI_GETBORDER:
842 return SpiGetInt(pvParam, &gspv.ncm.iBorderWidth, fl);
843
844 case SPI_SETBORDER:
845 uiParam = max(uiParam, 1);
846 return SpiSetInt(&gspv.ncm.iBorderWidth, uiParam, KEY_METRIC, VAL_BORDER, fl);
847
848 case SPI_GETKEYBOARDSPEED:
849 return SpiGetInt(pvParam, &gspv.dwKbdSpeed, fl);
850
851 case SPI_SETKEYBOARDSPEED:
852 return SpiSetInt(&gspv.dwKbdSpeed, uiParam, KEY_KBD, VAL_KBDSPD, fl);
853
854 case SPI_LANGDRIVER:
855 ERR("SPI_LANGDRIVER is unimplemented\n");
856 break;
857
858 case SPI_GETSCREENSAVETIMEOUT:
859 return SpiGetInt(pvParam, &gspv.iScrSaverTimeout, fl);
860
861 case SPI_SETSCREENSAVETIMEOUT:
862 return SpiSetInt(&gspv.iScrSaverTimeout, uiParam, KEY_DESKTOP, VAL_SCRTO, fl);
863
864 case SPI_GETSCREENSAVEACTIVE:
865 return SpiGetInt(pvParam, &gspv.bScrSaverActive, fl);
866
867 case SPI_SETSCREENSAVEACTIVE:
868 return SpiSetInt(&gspv.bScrSaverActive, uiParam, KEY_DESKTOP, VAL_SCRACT, fl);
869
870 case SPI_GETGRIDGRANULARITY:
871 return SpiGetInt(pvParam, &gspv.uiGridGranularity, fl);
872
873 case SPI_SETGRIDGRANULARITY:
874 return SpiSetInt(&gspv.uiGridGranularity, uiParam, KEY_DESKTOP, VAL_GRID, fl);
875
876 case SPI_GETDESKWALLPAPER:
877 uiParam = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
878 return SpiGet(pvParam, gspv.awcWallpaper, uiParam, fl);
879
880 case SPI_SETDESKWALLPAPER:
881 return SpiSetWallpaper(pvParam, fl);
882
883 case SPI_SETDESKPATTERN:
884 ERR("SPI_SETDESKPATTERN is unimplemented\n");
885 break;
886
887 case SPI_GETKEYBOARDDELAY:
888 return SpiGetInt(pvParam, &gspv.iKbdDelay, fl);
889
890 case SPI_SETKEYBOARDDELAY:
891 return SpiSetInt(&gspv.iKbdDelay, uiParam, KEY_KBD, VAL_KBDDELAY, fl);
892
893 case SPI_ICONHORIZONTALSPACING:
894 if (pvParam)
895 {
896 return SpiGetInt(pvParam, &gspv.im.iHorzSpacing, fl);
897 }
898 uiParam = max(uiParam, 32);
899 return SpiSetMetric(&gspv.im.iHorzSpacing, uiParam, VAL_ICONSPC, fl);
900
901 case SPI_ICONVERTICALSPACING:
902 if (pvParam)
903 {
904 return SpiGetInt(pvParam, &gspv.im.iVertSpacing, fl);
905 }
906 uiParam = max(uiParam, 32);
907 return SpiSetMetric(&gspv.im.iVertSpacing, uiParam, VAL_ICONVSPC, fl);
908
909 case SPI_GETICONTITLEWRAP:
910 return SpiGetInt(pvParam, &gspv.im.iTitleWrap, fl);
911
912 case SPI_SETICONTITLEWRAP:
913 return SpiSetInt(&gspv.im.iTitleWrap, uiParam, KEY_METRIC, VAL_ITWRAP, fl);
914
915 case SPI_GETMENUDROPALIGNMENT:
916 return SpiGetInt(pvParam, &gspv.bMenuDropAlign, fl);
917
918 case SPI_SETMENUDROPALIGNMENT:
919 return SpiSetBool(&gspv.bMenuDropAlign, uiParam, KEY_MDALIGN, VAL_MDALIGN, fl);
920
921 case SPI_SETDOUBLECLKWIDTH:
922 return SpiSetInt(&gspv.iDblClickWidth, uiParam, KEY_MOUSE, VAL_DBLCLKWIDTH, fl);
923
924 case SPI_SETDOUBLECLKHEIGHT:
925 return SpiSetInt(&gspv.iDblClickHeight, uiParam, KEY_MOUSE, VAL_DBLCLKHEIGHT, fl);
926
927 case SPI_GETICONTITLELOGFONT:
928 return SpiGet(pvParam, &gspv.im.lfFont, sizeof(LOGFONTW), fl);
929
930 case SPI_SETICONTITLELOGFONT:
931 if (!SpiSet(&gspv.im.lfFont, pvParam, sizeof(LOGFONTW), fl))
932 return 0;
933 if (fl & SPIF_UPDATEINIFILE)
934 {
935 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
936 }
937 return (UINT_PTR)KEY_METRIC;
938
939 case SPI_SETDOUBLECLICKTIME:
940 return SpiSetInt(&gspv.iDblClickTime, uiParam, KEY_MOUSE, VAL_DBLCLKTIME, fl);
941
942 case SPI_SETMOUSEBUTTONSWAP:
943 return SpiSetInt(&gspv.bMouseBtnSwap, uiParam, KEY_MOUSE, VAL_SWAP, fl);
944
945 case SPI_GETFASTTASKSWITCH:
946 return SpiGetInt(pvParam, &gspv.bFastTaskSwitch, fl);
947
948 case SPI_SETFASTTASKSWITCH:
949 /* According to Winetest this one is unimplemented */
950 return 1;
951
952 case SPI_GETDRAGFULLWINDOWS:
953 return SpiGetInt(pvParam, &gspv.bDragFullWindows, fl);
954
955 case SPI_SETDRAGFULLWINDOWS:
956 return SpiSetInt(&gspv.bDragFullWindows, uiParam, KEY_DESKTOP, VAL_DRAG, fl);
957
958 case SPI_GETNONCLIENTMETRICS:
959 {
960 return SpiGet(pvParam, &gspv.ncm, sizeof(NONCLIENTMETRICSW), fl);
961 }
962
963 case SPI_SETNONCLIENTMETRICS:
964 {
965 LPNONCLIENTMETRICSW metrics = (LPNONCLIENTMETRICSW)pvParam;
966
967 /* Fixup user's structure size */
968 metrics->cbSize = sizeof(NONCLIENTMETRICSW);
969
970 if (!SpiSet(&gspv.ncm, metrics, sizeof(NONCLIENTMETRICSW), fl))
971 return 0;
972
973 if (fl & SPIF_UPDATEINIFILE)
974 {
975 SpiStoreMetric(VAL_BORDER, gspv.ncm.iBorderWidth);
976 SpiStoreMetric(L"ScrollWidth", gspv.ncm.iScrollWidth);
977 SpiStoreMetric(L"ScrollHeight", gspv.ncm.iScrollHeight);
978 SpiStoreMetric(L"CaptionWidth", gspv.ncm.iCaptionWidth);
979 SpiStoreMetric(L"CaptionHeight", gspv.ncm.iCaptionHeight);
980 SpiStoreMetric(L"SmCaptionWidth", gspv.ncm.iSmCaptionWidth);
981 SpiStoreMetric(L"SmCaptionHeight", gspv.ncm.iSmCaptionHeight);
982 SpiStoreMetric(L"MenuWidth", gspv.ncm.iMenuWidth);
983 SpiStoreMetric(L"MenuHeight", gspv.ncm.iMenuHeight);
984 #if (WINVER >= 0x0600)
985 SpiStoreMetric(L"PaddedBorderWidth", gspv.ncm.iPaddedBorderWidth);
986 #endif
987 SpiStoreFont(L"CaptionFont", &gspv.ncm.lfCaptionFont);
988 SpiStoreFont(L"SmCaptionFont", &gspv.ncm.lfSmCaptionFont);
989 SpiStoreFont(L"MenuFont", &gspv.ncm.lfMenuFont);
990 SpiStoreFont(L"StatusFont", &gspv.ncm.lfStatusFont);
991 SpiStoreFont(L"MessageFont", &gspv.ncm.lfMessageFont);
992 }
993
994 if(!SpiNotifyNCMetricsChanged())
995 return 0;
996
997 return (UINT_PTR)KEY_METRIC;
998 }
999
1000 case SPI_GETMINIMIZEDMETRICS:
1001 {
1002 return SpiGet(pvParam, &gspv.mm, sizeof(MINIMIZEDMETRICS), fl);
1003 }
1004
1005 case SPI_SETMINIMIZEDMETRICS:
1006 {
1007 LPMINIMIZEDMETRICS metrics = (LPMINIMIZEDMETRICS)pvParam;
1008
1009 /* Fixup user's structure size */
1010 metrics->cbSize = sizeof(MINIMIZEDMETRICS);
1011
1012 if (!SpiSet(&gspv.mm, metrics, sizeof(MINIMIZEDMETRICS), fl))
1013 return 0;
1014
1015 gspv.mm.iWidth = max(0, gspv.mm.iWidth);
1016 gspv.mm.iHorzGap = max(0, gspv.mm.iHorzGap);
1017 gspv.mm.iVertGap = max(0, gspv.mm.iVertGap);
1018 gspv.mm.iArrange = gspv.mm.iArrange & 0xf;
1019
1020 if (fl & SPIF_UPDATEINIFILE)
1021 {
1022 SpiStoreMetric(L"MinWidth", gspv.mm.iWidth);
1023 SpiStoreMetric(L"MinHorzGap", gspv.mm.iHorzGap);
1024 SpiStoreMetric(L"MinVertGap", gspv.mm.iVertGap);
1025 SpiStoreMetric(L"MinArrange", gspv.mm.iArrange);
1026 }
1027
1028 return (UINT_PTR)KEY_METRIC;
1029 }
1030
1031 case SPI_GETICONMETRICS:
1032 {
1033 return SpiGet(pvParam, &gspv.im, sizeof(ICONMETRICSW), fl);
1034 }
1035
1036 case SPI_SETICONMETRICS:
1037 {
1038 LPICONMETRICSW metrics = (LPICONMETRICSW)pvParam;
1039
1040 /* Fixup user's structure size */
1041 metrics->cbSize = sizeof(ICONMETRICSW);
1042
1043 if (!SpiSet(&gspv.im, metrics, sizeof(ICONMETRICSW), fl))
1044 return 0;
1045
1046 if (fl & SPIF_UPDATEINIFILE)
1047 {
1048 SpiStoreMetric(VAL_ICONSPC, gspv.im.iHorzSpacing);
1049 SpiStoreMetric(VAL_ICONVSPC, gspv.im.iVertSpacing);
1050 SpiStoreMetric(VAL_ITWRAP, gspv.im.iTitleWrap);
1051 SpiStoreFont(L"IconFont", &gspv.im.lfFont);
1052 }
1053 return (UINT_PTR)KEY_METRIC;
1054 }
1055
1056 case SPI_GETWORKAREA:
1057 {
1058 PMONITOR pmonitor = UserGetPrimaryMonitor();
1059
1060 if(!pmonitor)
1061 return 0;
1062
1063 return SpiGet(pvParam, &pmonitor->rcWork, sizeof(RECTL), fl);
1064 }
1065
1066 case SPI_SETWORKAREA:
1067 {
1068 PMONITOR pmonitor;
1069 RECTL rcWorkArea, rcIntersect;
1070
1071 if (!pvParam)
1072 return 0;
1073
1074 RtlCopyMemory(&rcWorkArea, pvParam, sizeof(rcWorkArea));
1075
1076 /* fail if empty */
1077 if (RECTL_bIsEmptyRect(&rcWorkArea))
1078 return 0;
1079
1080 /* get the nearest monitor */
1081 pmonitor = UserMonitorFromRect(&rcWorkArea, MONITOR_DEFAULTTONEAREST);
1082 if (!pmonitor)
1083 return 0;
1084
1085 /* fail unless work area is completely in monitor */
1086 if (!RECTL_bIntersectRect(&rcIntersect, &pmonitor->rcMonitor, &rcWorkArea) ||
1087 !RtlEqualMemory(&rcIntersect, &rcWorkArea, sizeof(rcIntersect)))
1088 {
1089 return 0;
1090 }
1091
1092 if (!SpiSet(&pmonitor->rcWork, pvParam, sizeof(RECTL), fl))
1093 return 0;
1094
1095 if (fl & SPIF_UPDATEINIFILE)
1096 {
1097 // FIXME: What to do?
1098 }
1099 return (UINT_PTR)KEY_DESKTOP;
1100 }
1101
1102 case SPI_SETPENWINDOWS:
1103 ERR("SPI_SETPENWINDOWS is unimplemented\n");
1104 break;
1105
1106 case SPI_GETFILTERKEYS:
1107 {
1108 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1109
1110 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1111 return 0;
1112
1113 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1114 return 0;
1115
1116 return SpiGet(pvParam, &gspv.filterkeys, sizeof(FILTERKEYS), fl);
1117 }
1118
1119 case SPI_SETFILTERKEYS:
1120 {
1121 LPFILTERKEYS FilterKeys = (LPFILTERKEYS)pvParam;
1122
1123 if (uiParam != 0 && uiParam != sizeof(FILTERKEYS))
1124 return 0;
1125
1126 if (!FilterKeys || FilterKeys->cbSize != sizeof(FILTERKEYS))
1127 return 0;
1128
1129 if (!SpiSet(&gspv.filterkeys, pvParam, sizeof(FILTERKEYS), fl))
1130 return 0;
1131
1132 if (fl & SPIF_UPDATEINIFILE)
1133 {
1134 // FIXME: What to do?
1135 }
1136 return (UINT_PTR)KEY_DESKTOP;
1137 }
1138
1139 case SPI_GETTOGGLEKEYS:
1140 {
1141 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1142
1143 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1144 return 0;
1145
1146 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1147 return 0;
1148
1149 return SpiGet(pvParam, &gspv.togglekeys, sizeof(TOGGLEKEYS), fl);
1150 }
1151
1152 case SPI_SETTOGGLEKEYS:
1153 {
1154 LPTOGGLEKEYS ToggleKeys = (LPTOGGLEKEYS)pvParam;
1155
1156 if (uiParam != 0 && uiParam != sizeof(TOGGLEKEYS))
1157 return 0;
1158
1159 if (!ToggleKeys || ToggleKeys->cbSize != sizeof(TOGGLEKEYS))
1160 return 0;
1161
1162 if (!SpiSet(&gspv.togglekeys, pvParam, sizeof(TOGGLEKEYS), fl))
1163 return 0;
1164
1165 if (fl & SPIF_UPDATEINIFILE)
1166 {
1167 // FIXME: What to do?
1168 }
1169 return (UINT_PTR)KEY_DESKTOP;
1170 }
1171
1172 case SPI_GETMOUSEKEYS:
1173 {
1174 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1175
1176 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1177 return 0;
1178
1179 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1180 return 0;
1181
1182 return SpiGet(pvParam, &gspv.mousekeys, sizeof(MOUSEKEYS), fl);
1183 }
1184
1185 case SPI_SETMOUSEKEYS:
1186 {
1187 LPMOUSEKEYS MouseKeys = (LPMOUSEKEYS)pvParam;
1188
1189 if (uiParam != 0 && uiParam != sizeof(MOUSEKEYS))
1190 return 0;
1191
1192 if (!MouseKeys || MouseKeys->cbSize != sizeof(MOUSEKEYS))
1193 return 0;
1194
1195 if (!SpiSet(&gspv.mousekeys, pvParam, sizeof(MOUSEKEYS), fl))
1196 return 0;
1197
1198 if (fl & SPIF_UPDATEINIFILE)
1199 {
1200 // FIXME: What to do?
1201 }
1202 return (UINT_PTR)KEY_DESKTOP;
1203 }
1204
1205 case SPI_GETSHOWSOUNDS:
1206 return SpiGetInt(pvParam, &gspv.bShowSounds, fl);
1207
1208 case SPI_SETSHOWSOUNDS:
1209 return SpiSetBool(&gspv.bShowSounds, uiParam, KEY_SHOWSNDS, VAL_ON, fl);
1210
1211 case SPI_GETSTICKYKEYS:
1212 {
1213 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1214
1215 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1216 return 0;
1217
1218 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1219 return 0;
1220
1221 return SpiGetEx(pvParam, &gspv.stickykeys, sizeof(STICKYKEYS), fl);
1222 }
1223
1224 case SPI_SETSTICKYKEYS:
1225 {
1226 LPSTICKYKEYS StickyKeys = (LPSTICKYKEYS)pvParam;
1227
1228 if (uiParam != 0 && uiParam != sizeof(STICKYKEYS))
1229 return 0;
1230
1231 if (!StickyKeys || StickyKeys->cbSize != sizeof(STICKYKEYS))
1232 return 0;
1233
1234 if (!SpiSet(&gspv.stickykeys, pvParam, sizeof(STICKYKEYS), fl))
1235 return 0;
1236
1237 if (fl & SPIF_UPDATEINIFILE)
1238 {
1239 // FIXME: What to do?
1240 }
1241 return (UINT_PTR)KEY_DESKTOP;
1242 }
1243
1244 case SPI_GETACCESSTIMEOUT:
1245 {
1246 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1247
1248 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1249 return 0;
1250
1251 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1252 return 0;
1253
1254 return SpiGetEx(pvParam, &gspv.accesstimeout, sizeof(ACCESSTIMEOUT), fl);
1255 }
1256
1257 case SPI_SETACCESSTIMEOUT:
1258 {
1259 LPACCESSTIMEOUT AccessTimeout = (LPACCESSTIMEOUT)pvParam;
1260
1261 if (uiParam != 0 && uiParam != sizeof(ACCESSTIMEOUT))
1262 {
1263 return 0;
1264 }
1265
1266 if (!AccessTimeout || AccessTimeout->cbSize != sizeof(ACCESSTIMEOUT))
1267 {
1268 return 0;
1269 }
1270
1271 if (!SpiSet(&gspv.accesstimeout, pvParam, sizeof(ACCESSTIMEOUT), fl))
1272 return 0;
1273
1274 if (fl & SPIF_UPDATEINIFILE)
1275 {
1276 // FIXME: What to do?
1277 }
1278 return (UINT_PTR)KEY_DESKTOP;
1279 }
1280
1281 case SPI_GETSERIALKEYS:
1282 {
1283 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1284
1285 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1286 return 0;
1287
1288 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1289 return 0;
1290
1291 return SpiGet(pvParam, &gspv.serialkeys, sizeof(SERIALKEYS), fl);
1292 }
1293
1294 case SPI_SETSERIALKEYS:
1295 {
1296 LPSERIALKEYS SerialKeys = (LPSERIALKEYS)pvParam;
1297
1298 if (uiParam != 0 && uiParam != sizeof(SERIALKEYS))
1299 return 0;
1300
1301 if (!SerialKeys || SerialKeys->cbSize != sizeof(SERIALKEYS))
1302 return 0;
1303
1304 if (!SpiSet(&gspv.serialkeys, pvParam, sizeof(SERIALKEYS), fl))
1305 return 0;
1306
1307 if (fl & SPIF_UPDATEINIFILE)
1308 {
1309 // FIXME: What to do?
1310 }
1311 return (UINT_PTR)KEY_DESKTOP;
1312 }
1313
1314 case SPI_GETSOUNDSENTRY:
1315 {
1316 LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1317
1318 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1319 return 0;
1320
1321 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1322 return 0;
1323
1324 return SpiGet(pvParam, &gspv.soundsentry, sizeof(SOUNDSENTRYW), fl);
1325 }
1326
1327 case SPI_SETSOUNDSENTRY:
1328 {
1329 LPSOUNDSENTRYW SoundsEntry = (LPSOUNDSENTRYW)pvParam;
1330
1331 if (uiParam != 0 && uiParam != sizeof(SOUNDSENTRYW))
1332 return 0;
1333
1334 if (!SoundsEntry || SoundsEntry->cbSize != sizeof(SOUNDSENTRYW))
1335 return 0;
1336
1337 if (!SpiSet(&gspv.soundsentry, pvParam, sizeof(SOUNDSENTRYW), fl))
1338 return 0;
1339
1340 if (fl & SPIF_UPDATEINIFILE)
1341 {
1342 // FIXME: What to do?
1343 }
1344 return (UINT_PTR)KEY_DESKTOP;
1345 }
1346
1347 case SPI_GETHIGHCONTRAST:
1348 {
1349 LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1350
1351 if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1352 return 0;
1353
1354 if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1355 return 0;
1356
1357 return SpiGet(pvParam, &gspv.highcontrast, sizeof(HIGHCONTRASTW), fl);
1358 }
1359
1360 case SPI_SETHIGHCONTRAST:
1361 {
1362 LPHIGHCONTRASTW highcontrast = (LPHIGHCONTRASTW)pvParam;
1363
1364 if (uiParam != 0 && uiParam != sizeof(HIGHCONTRASTW))
1365 return 0;
1366
1367 if (!highcontrast || highcontrast->cbSize != sizeof(HIGHCONTRASTW))
1368 return 0;
1369
1370 if (!SpiSet(&gspv.highcontrast, pvParam, sizeof(HIGHCONTRASTW), fl))
1371 return 0;
1372
1373 if (fl & SPIF_UPDATEINIFILE)
1374 {
1375 // FIXME: What to do?
1376 }
1377 return (UINT_PTR)KEY_DESKTOP;
1378 }
1379
1380 case SPI_GETKEYBOARDPREF:
1381 return SpiGetInt(pvParam, &gspv.bKbdPref, fl);
1382
1383 case SPI_SETKEYBOARDPREF:
1384 return SpiSetBool(&gspv.bKbdPref, uiParam, KEY_KDBPREF, VAL_ON, fl);
1385
1386 case SPI_GETSCREENREADER:
1387 return SpiGetInt(pvParam, &gspv.bScreenReader, fl);
1388
1389 case SPI_SETSCREENREADER:
1390 return SpiSetBool(&gspv.bScreenReader, uiParam, KEY_SCRREAD, VAL_ON, fl);
1391
1392 case SPI_GETANIMATION:
1393 return SpiGet(pvParam, &gspv.animationinfo, sizeof(ANIMATIONINFO), fl);
1394
1395 case SPI_SETANIMATION:
1396 if (!SpiSet(&gspv.animationinfo, pvParam, sizeof(ANIMATIONINFO), fl))
1397 return 0;
1398 if (fl & SPIF_UPDATEINIFILE)
1399 {
1400 // FIXME: What to do?
1401 }
1402 return (UINT_PTR)KEY_DESKTOP;
1403
1404 case SPI_GETFONTSMOOTHING:
1405 return SpiGetInt(pvParam, &gspv.bFontSmoothing, fl);
1406
1407 case SPI_SETFONTSMOOTHING:
1408 gspv.bFontSmoothing = !!uiParam;
1409 if (fl & SPIF_UPDATEINIFILE)
1410 {
1411 SpiStoreSzInt(KEY_DESKTOP, VAL_FONTSMOOTHING, gspv.bFontSmoothing ? 2 : 0);
1412 }
1413 return (UINT_PTR)KEY_DESKTOP;
1414
1415 case SPI_SETDRAGWIDTH:
1416 return SpiSetInt(&gspv.iDragWidth, uiParam, KEY_DESKTOP, VAL_DRAGWIDTH, fl);
1417
1418 case SPI_SETDRAGHEIGHT:
1419 return SpiSetInt(&gspv.iDragHeight, uiParam, KEY_DESKTOP, VAL_DRAGHEIGHT, fl);
1420
1421 case SPI_SETHANDHELD:
1422 return SpiSetBool(&gspv.bHandHeld, uiParam, KEY_DESKTOP, L"HandHeld", fl);
1423
1424 case SPI_GETLOWPOWERTIMEOUT:
1425 return SpiGetInt(pvParam, &gspv.iLowPwrTimeout, fl);
1426
1427 case SPI_GETPOWEROFFTIMEOUT:
1428 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1429
1430 case SPI_SETLOWPOWERTIMEOUT:
1431 return SpiSetInt(&gspv.iLowPwrTimeout, uiParam, KEY_DESKTOP, L"LowPowerTimeOut", fl);
1432
1433 case SPI_SETPOWEROFFTIMEOUT:
1434 return SpiSetInt(&gspv.iPwrOffTimeout, uiParam, KEY_DESKTOP, L"PowerOffTimeOut", fl);
1435
1436 case SPI_GETLOWPOWERACTIVE:
1437 return SpiGetInt(pvParam, &gspv.iPwrOffTimeout, fl);
1438
1439 case SPI_GETPOWEROFFACTIVE:
1440 return SpiGetInt(pvParam, &gspv.bPwrOffActive, fl);
1441
1442 case SPI_SETLOWPOWERACTIVE:
1443 return SpiSetBool(&gspv.bLowPwrActive, uiParam, KEY_DESKTOP, L"LowPowerActive", fl);
1444
1445 case SPI_SETPOWEROFFACTIVE:
1446 return SpiSetBool(&gspv.bPwrOffActive, uiParam, KEY_DESKTOP, L"PowerOffActive", fl);
1447
1448 case SPI_SETCURSORS:
1449 ERR("SPI_SETCURSORS is unimplemented\n");
1450 break;
1451
1452 case SPI_SETICONS:
1453 ERR("SPI_SETICONS is unimplemented\n");
1454 break;
1455
1456 case SPI_GETDEFAULTINPUTLANG:
1457 if (!gspklBaseLayout)
1458 return FALSE;
1459
1460 return SpiGet(pvParam, &gspklBaseLayout->hkl, sizeof(HKL), fl);
1461
1462 case SPI_SETDEFAULTINPUTLANG:
1463 {
1464 HKL hkl;
1465
1466 /* Note: SPIF_UPDATEINIFILE is not supported */
1467 if ((fl & SPIF_UPDATEINIFILE) || !SpiSet(&hkl, pvParam, sizeof(hkl), fl))
1468 return FALSE;
1469
1470 return UserSetDefaultInputLang(hkl);
1471 }
1472
1473 case SPI_SETLANGTOGGLE:
1474 gdwLayoutToggleKey = UserGetLanguageToggle(L"Layout Hotkey", 2);
1475 gdwLanguageToggleKey = UserGetLanguageToggle(L"Language Hotkey", 1);
1476 return gdwLanguageToggleKey;
1477
1478 case SPI_GETWINDOWSEXTENSION:
1479 ERR("SPI_GETWINDOWSEXTENSION is unimplemented\n");
1480 break;
1481
1482 case SPI_GETMOUSETRAILS:
1483 return SpiGetInt(pvParam, &gspv.iMouseTrails, fl);
1484
1485 case SPI_SETMOUSETRAILS:
1486 return SpiSetInt(&gspv.iMouseTrails, uiParam, KEY_MOUSE, VAL_MOUSETRAILS, fl);
1487
1488 case SPI_GETSNAPTODEFBUTTON:
1489 return SpiGetInt(pvParam, &gspv.bSnapToDefBtn, fl);
1490
1491 case SPI_SETSNAPTODEFBUTTON:
1492 return SpiSetBool(&gspv.bSnapToDefBtn, uiParam, KEY_MOUSE, VAL_SNAPDEFBTN, fl);
1493
1494 case SPI_GETMOUSEHOVERWIDTH:
1495 return SpiGetInt(pvParam, &gspv.iMouseHoverWidth, fl);
1496
1497 case SPI_SETMOUSEHOVERWIDTH:
1498 return SpiSetInt(&gspv.iMouseHoverWidth, uiParam, KEY_MOUSE, VAL_HOVERWIDTH, fl);
1499
1500 case SPI_GETMOUSEHOVERHEIGHT:
1501 return SpiGetInt(pvParam, &gspv.iMouseHoverHeight, fl);
1502
1503 case SPI_SETMOUSEHOVERHEIGHT:
1504 return SpiSetInt(&gspv.iMouseHoverHeight, uiParam, KEY_MOUSE, VAL_HOVERHEIGHT, fl);
1505
1506 case SPI_GETMOUSEHOVERTIME:
1507 return SpiGetInt(pvParam, &gspv.iMouseHoverTime, fl);
1508
1509 case SPI_SETMOUSEHOVERTIME:
1510 /* See http://msdn2.microsoft.com/en-us/library/ms724947.aspx
1511 * copy text from it, if some agument why xp and 2003 behovir diffent
1512 * only if they do not have SP install
1513 * " Windows Server 2003 and Windows XP: The operating system does not
1514 * enforce the use of USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM until
1515 * Windows Server 2003 SP1 and Windows XP SP2 "
1516 */
1517 return SpiSetInt(&gspv.iMouseHoverTime, uiParam, KEY_MOUSE, VAL_HOVERTIME, fl);
1518
1519 case SPI_GETWHEELSCROLLLINES:
1520 return SpiGetInt(pvParam, &gspv.iWheelScrollLines, fl);
1521
1522 case SPI_SETWHEELSCROLLLINES:
1523 return SpiSetInt(&gspv.iWheelScrollLines, uiParam, KEY_DESKTOP, VAL_SCRLLLINES, fl);
1524
1525 case SPI_GETMENUSHOWDELAY:
1526 return SpiGetInt(pvParam, &gspv.dwMenuShowDelay, fl);
1527
1528 case SPI_SETMENUSHOWDELAY:
1529 return SpiSetInt(&gspv.dwMenuShowDelay, uiParam, KEY_DESKTOP, L"MenuShowDelay", fl);
1530
1531 #if (_WIN32_WINNT >= 0x0600)
1532 case SPI_GETWHEELSCROLLCHARS:
1533 return SpiGetInt(pvParam, &gspv.uiWheelScrollChars, fl);
1534
1535 case SPI_SETWHEELSCROLLCHARS:
1536 return SpiSetInt(&gspv.uiWheelScrollChars, uiParam, KEY_DESKTOP, VAL_SCRLLCHARS, fl);
1537 #endif
1538 case SPI_GETSHOWIMEUI:
1539 return SpiGetInt(pvParam, &gspv.bShowImeUi, fl);
1540
1541 case SPI_SETSHOWIMEUI:
1542 return SpiSetBool(&gspv.bShowImeUi, uiParam, KEY_DESKTOP, L"", fl);
1543
1544 case SPI_GETMOUSESPEED:
1545 return SpiGetInt(pvParam, &gspv.iMouseSpeed, fl);
1546
1547 case SPI_SETMOUSESPEED:
1548 {
1549 /* Allowed range is [1:20] */
1550 if ((INT_PTR)pvParam < 1 || (INT_PTR)pvParam > 20)
1551 return 0;
1552 else
1553 return SpiSetInt(&gspv.iMouseSpeed, (INT_PTR)pvParam, KEY_MOUSE, VAL_SENSITIVITY, fl);
1554 }
1555
1556 case SPI_GETSCREENSAVERRUNNING:
1557 return SpiGetInt(pvParam, &gspv.bScrSaverRunning, fl);
1558
1559 case SPI_SETSCREENSAVERRUNNING:
1560 // FIXME: also return value?
1561 return SpiSetBool(&gspv.bScrSaverRunning, uiParam, KEY_MOUSE, L"", fl);
1562
1563 #if(WINVER >= 0x0600)
1564 case SPI_GETAUDIODESCRIPTION:
1565 return SpiGet(pvParam, &gspv.audiodescription, sizeof(AUDIODESCRIPTION), fl);
1566
1567 case SPI_SETAUDIODESCRIPTION:
1568 ERR("SPI_SETAUDIODESCRIPTION is unimplemented\n");
1569 break;
1570
1571 case SPI_GETSCREENSAVESECURE:
1572 return SpiGetInt(pvParam, &gspv.bScrSaverSecure, fl);
1573
1574 case SPI_SETSCREENSAVESECURE:
1575 return SpiSetBool(&gspv.bScrSaverSecure, uiParam, KEY_DESKTOP, L"ScreenSaverIsSecure", fl);
1576 #endif
1577
1578 case SPI_GETACTIVEWINDOWTRACKING:
1579 return SpiGetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1580
1581 case SPI_SETACTIVEWINDOWTRACKING:
1582 return SpiSetUserPref(UPM_ACTIVEWINDOWTRACKING, pvParam, fl);
1583
1584 case SPI_GETMENUANIMATION:
1585 return SpiGetUserPref(UPM_MENUANIMATION, pvParam, fl);
1586
1587 case SPI_SETMENUANIMATION:
1588 return SpiSetUserPref(UPM_MENUANIMATION, pvParam, fl);
1589
1590 case SPI_GETCOMBOBOXANIMATION:
1591 return SpiGetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1592
1593 case SPI_SETCOMBOBOXANIMATION:
1594 return SpiSetUserPref(UPM_COMBOBOXANIMATION, pvParam, fl);
1595
1596 case SPI_GETLISTBOXSMOOTHSCROLLING:
1597 return SpiGetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1598
1599 case SPI_SETLISTBOXSMOOTHSCROLLING:
1600 return SpiSetUserPref(UPM_LISTBOXSMOOTHSCROLLING, pvParam, fl);
1601
1602 case SPI_GETGRADIENTCAPTIONS:
1603 {
1604 if (NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL) <= 8)
1605 {
1606 INT iValue = 0;
1607 return SpiGetInt(pvParam, &iValue, fl);
1608 }
1609 else
1610 {
1611 return SpiGetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1612 }
1613 }
1614
1615 case SPI_SETGRADIENTCAPTIONS:
1616 return SpiSetUserPref(UPM_GRADIENTCAPTIONS, pvParam, fl);
1617
1618 case SPI_GETKEYBOARDCUES:
1619 return SpiGetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1620
1621 case SPI_SETKEYBOARDCUES:
1622 return SpiSetUserPref(UPM_KEYBOARDCUES, pvParam, fl);
1623
1624 case SPI_GETACTIVEWNDTRKZORDER:
1625 return SpiGetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1626
1627 case SPI_SETACTIVEWNDTRKZORDER:
1628 return SpiSetUserPref(UPM_ACTIVEWNDTRKZORDER, pvParam, fl);
1629
1630 case SPI_GETHOTTRACKING:
1631 return SpiGetUserPref(UPM_HOTTRACKING, pvParam, fl);
1632
1633 case SPI_SETHOTTRACKING:
1634 return SpiSetUserPref(UPM_HOTTRACKING, pvParam, fl);
1635
1636 case SPI_GETMENUFADE:
1637 return SpiGetUserPref(UPM_MENUFADE, pvParam, fl);
1638
1639 case SPI_SETMENUFADE:
1640 return SpiSetUserPref(UPM_MENUFADE, pvParam, fl);
1641
1642 case SPI_GETSELECTIONFADE:
1643 return SpiGetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1644
1645 case SPI_SETSELECTIONFADE:
1646 return SpiSetUserPref(UPM_SELECTIONFADE, pvParam, fl);
1647
1648 case SPI_GETTOOLTIPANIMATION:
1649 return SpiGetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1650
1651 case SPI_SETTOOLTIPANIMATION:
1652 return SpiSetUserPref(UPM_TOOLTIPANIMATION, pvParam, fl);
1653
1654 case SPI_GETTOOLTIPFADE:
1655 return SpiGetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1656
1657 case SPI_SETTOOLTIPFADE:
1658 return SpiSetUserPref(UPM_TOOLTIPFADE, pvParam, fl);
1659
1660 case SPI_GETCURSORSHADOW:
1661 return SpiGetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1662
1663 case SPI_SETCURSORSHADOW:
1664 gspv.bMouseCursorShadow = PtrToUlong(pvParam);
1665 return SpiSetUserPref(UPM_CURSORSHADOW, pvParam, fl);
1666
1667 case SPI_GETUIEFFECTS:
1668 return SpiGetUserPref(UPM_UIEFFECTS, pvParam, fl);
1669
1670 case SPI_SETUIEFFECTS:
1671 return SpiSetUserPref(UPM_UIEFFECTS, pvParam, fl);
1672
1673 case SPI_GETMOUSESONAR:
1674 return SpiGetInt(pvParam, &gspv.bMouseSonar, fl);
1675
1676 case SPI_SETMOUSESONAR:
1677 return SpiSetBool(&gspv.bMouseSonar, uiParam, KEY_MOUSE, L"", fl);
1678
1679 case SPI_GETMOUSECLICKLOCK:
1680 return SpiGetUserPref(UPM_CLICKLOCK, pvParam, fl);
1681
1682 case SPI_SETMOUSECLICKLOCK:
1683 gspv.bMouseClickLock = PtrToUlong(pvParam);
1684 return SpiSetUserPref(UPM_CLICKLOCK, pvParam, fl);
1685
1686 case SPI_GETMOUSEVANISH:
1687 return SpiGetInt(pvParam, &gspv.bMouseVanish, fl);
1688
1689 case SPI_SETMOUSEVANISH:
1690 return SpiSetBool(&gspv.bMouseVanish, uiParam, KEY_MOUSE, L"", fl);
1691
1692 case SPI_GETFLATMENU:
1693 return SpiGetUserPref(UPM_FLATMENU, pvParam, fl);
1694
1695 case SPI_SETFLATMENU:
1696 return SpiSetUserPref(UPM_FLATMENU, pvParam, fl);
1697
1698 case SPI_GETDROPSHADOW:
1699 return SpiGetUserPref(UPM_DROPSHADOW, pvParam, fl);
1700
1701 case SPI_SETDROPSHADOW:
1702 return SpiSetUserPref(UPM_DROPSHADOW, pvParam, fl);
1703
1704 case SPI_GETBLOCKSENDINPUTRESETS:
1705 return SpiGetInt(pvParam, &gspv.bBlockSendInputResets, fl);
1706
1707 case SPI_SETBLOCKSENDINPUTRESETS:
1708 return SpiSetBool(&gspv.bBlockSendInputResets, uiParam, KEY_MOUSE, L"", fl);
1709
1710 #if(_WIN32_WINNT >= 0x0600)
1711 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1712 return SpiGetInt(pvParam, &gspv.bDisableOverlappedContent, fl);
1713
1714 case SPI_SETDISABLEOVERLAPPEDCONTENT:
1715 return SpiSetBool(&gspv.bDisableOverlappedContent, uiParam, KEY_MOUSE, L"", fl);
1716
1717 case SPI_GETCLIENTAREAANIMATION:
1718 return SpiGetInt(pvParam, &gspv.bClientAreaAnimation, fl);
1719
1720 case SPI_SETCLIENTAREAANIMATION:
1721 return SpiSetBool(&gspv.bClientAreaAnimation, uiParam, KEY_MOUSE, L"", fl);
1722
1723 case SPI_GETCLEARTYPE:
1724 return SpiGetInt(pvParam, &gspv.bClearType, fl);
1725
1726 case SPI_SETCLEARTYPE:
1727 return SpiSetBool(&gspv.bClearType, uiParam, KEY_MOUSE, L"", fl);
1728
1729 case SPI_GETSPEECHRECOGNITION:
1730 return SpiGetInt(pvParam, &gspv.bSpeechRecognition, fl);
1731
1732 case SPI_SETSPEECHRECOGNITION:
1733 return SpiSetBool(&gspv.bSpeechRecognition, uiParam, KEY_MOUSE, L"", fl);
1734 #endif
1735
1736 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1737 return SpiGetInt(pvParam, &gspv.dwForegroundLockTimeout, fl);
1738
1739 case SPI_SETFOREGROUNDLOCKTIMEOUT:
1740 return SpiSetInt(&gspv.dwForegroundLockTimeout, uiParam, KEY_MOUSE, L"", fl);
1741
1742 case SPI_GETACTIVEWNDTRKTIMEOUT:
1743 return SpiGetInt(pvParam, &gspv.dwActiveTrackingTimeout, fl);
1744
1745 case SPI_SETACTIVEWNDTRKTIMEOUT:
1746 return SpiSetInt(&gspv.dwActiveTrackingTimeout, uiParam, KEY_MOUSE, L"", fl);
1747
1748 case SPI_GETFOREGROUNDFLASHCOUNT:
1749 return SpiGetInt(pvParam, &gspv.dwForegroundFlashCount, fl);
1750
1751 case SPI_SETFOREGROUNDFLASHCOUNT:
1752 return SpiSetInt(&gspv.dwForegroundFlashCount, uiParam, KEY_MOUSE, L"", fl);
1753
1754 case SPI_GETCARETWIDTH:
1755 return SpiGetInt(pvParam, &gspv.dwCaretWidth, fl);
1756
1757 case SPI_SETCARETWIDTH:
1758 return SpiSetDWord(&gspv.dwCaretWidth, PtrToUlong(pvParam), KEY_DESKTOP, VAL_CARETWIDTH, fl);
1759
1760 case SPI_GETMOUSECLICKLOCKTIME:
1761 return SpiGetInt(pvParam, &gspv.dwMouseClickLockTime, fl);
1762
1763 case SPI_SETMOUSECLICKLOCKTIME:
1764 return SpiSetDWord(&gspv.dwMouseClickLockTime, uiParam, KEY_DESKTOP, VAL_CLICKLOCKTIME, fl);
1765
1766 case SPI_GETFONTSMOOTHINGTYPE:
1767 return SpiGetInt(pvParam, &gspv.uiFontSmoothingType, fl);
1768
1769 case SPI_SETFONTSMOOTHINGTYPE:
1770 return SpiSetDWord(&gspv.uiFontSmoothingType, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGTYPE, fl);
1771
1772 case SPI_GETFONTSMOOTHINGCONTRAST:
1773 return SpiGetInt(pvParam, &gspv.uiFontSmoothingContrast, fl);
1774
1775 case SPI_SETFONTSMOOTHINGCONTRAST:
1776 return SpiSetDWord(&gspv.uiFontSmoothingContrast, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGCONTRAST, fl);
1777
1778 case SPI_GETFOCUSBORDERWIDTH:
1779 return SpiGetInt(pvParam, &gspv.uiFocusBorderWidth, fl);
1780
1781 case SPI_SETFOCUSBORDERWIDTH:
1782 return SpiSetInt(&gspv.uiFocusBorderWidth, uiParam, KEY_MOUSE, L"", fl);
1783
1784 case SPI_GETFOCUSBORDERHEIGHT:
1785 return SpiGetInt(pvParam, &gspv.uiFocusBorderHeight, fl);
1786
1787 case SPI_SETFOCUSBORDERHEIGHT:
1788 return SpiSetInt(&gspv.uiFocusBorderHeight, uiParam, KEY_MOUSE, L"", fl);
1789
1790 case SPI_GETFONTSMOOTHINGORIENTATION:
1791 return SpiGetInt(pvParam, &gspv.uiFontSmoothingOrientation, fl);
1792
1793 case SPI_SETFONTSMOOTHINGORIENTATION:
1794 return SpiSetDWord(&gspv.uiFontSmoothingOrientation, PtrToUlong(pvParam), KEY_DESKTOP, VAL_FONTSMOOTHINGORIENTATION, fl);
1795
1796 /* The following are undocumented, but valid SPI values */
1797 case 0x1010:
1798 case 0x1011:
1799 case 0x1028:
1800 case 0x1029:
1801 case 0x102A:
1802 case 0x102B:
1803 case 0x102C:
1804 case 0x102D:
1805 case 0x102E:
1806 case 0x102F:
1807 case 0x1030:
1808 case 0x1031:
1809 case 0x1032:
1810 case 0x1033:
1811 case 0x1034:
1812 case 0x1035:
1813 case 0x1036:
1814 case 0x1037:
1815 case 0x1038:
1816 case 0x1039:
1817 case 0x103A:
1818 case 0x103B:
1819 case 0x103C:
1820 case 0x103D:
1821 ERR("Undocumented SPI value %x is unimplemented\n", uiAction);
1822 break;
1823
1824 default:
1825 ERR("Invalid SPI value: %u\n", uiAction);
1826 EngSetLastError(ERROR_INVALID_PARAMETER);
1827 return 0;
1828 }
1829
1830 return 0;
1831 }
1832
1833 static BOOL
SpiGetSetProbeBuffer(UINT uiAction,UINT uiParam,PVOID pvParam)1834 SpiGetSetProbeBuffer(UINT uiAction, UINT uiParam, PVOID pvParam)
1835 {
1836 BOOL bToUser = TRUE;
1837 ULONG cbSize = 0;
1838
1839 switch (uiAction)
1840 {
1841 case SPI_GETBEEP:
1842 case SPI_GETBORDER:
1843 case SPI_GETKEYBOARDSPEED:
1844 case SPI_GETSCREENSAVETIMEOUT:
1845 case SPI_GETSCREENSAVEACTIVE:
1846 case SPI_GETGRIDGRANULARITY:
1847 case SPI_GETKEYBOARDDELAY:
1848 case SPI_GETICONTITLEWRAP:
1849 case SPI_GETMENUDROPALIGNMENT:
1850 case SPI_GETFASTTASKSWITCH:
1851 case SPI_GETDRAGFULLWINDOWS:
1852 case SPI_GETSHOWSOUNDS:
1853 case SPI_GETKEYBOARDPREF:
1854 case SPI_GETSCREENREADER:
1855 case SPI_GETFONTSMOOTHING:
1856 case SPI_GETLOWPOWERTIMEOUT:
1857 case SPI_GETPOWEROFFTIMEOUT:
1858 case SPI_GETLOWPOWERACTIVE:
1859 case SPI_GETPOWEROFFACTIVE:
1860 case SPI_GETMOUSETRAILS:
1861 case SPI_GETSNAPTODEFBUTTON:
1862 case SPI_GETMOUSEHOVERWIDTH:
1863 case SPI_GETMOUSEHOVERHEIGHT:
1864 case SPI_GETMOUSEHOVERTIME:
1865 case SPI_GETWHEELSCROLLLINES:
1866 case SPI_GETMENUSHOWDELAY:
1867 #if (_WIN32_WINNT >= 0x0600)
1868 case SPI_GETWHEELSCROLLCHARS:
1869 #endif
1870 case SPI_GETSHOWIMEUI:
1871 case SPI_GETMOUSESPEED:
1872 case SPI_GETSCREENSAVERRUNNING:
1873 #if(WINVER >= 0x0600)
1874 case SPI_GETSCREENSAVESECURE:
1875 #endif
1876 case SPI_GETACTIVEWINDOWTRACKING:
1877 case SPI_GETMENUANIMATION:
1878 case SPI_GETCOMBOBOXANIMATION:
1879 case SPI_GETLISTBOXSMOOTHSCROLLING:
1880 case SPI_GETGRADIENTCAPTIONS:
1881 case SPI_GETKEYBOARDCUES:
1882 case SPI_GETACTIVEWNDTRKZORDER:
1883 case SPI_GETHOTTRACKING:
1884 case SPI_GETMENUFADE:
1885 case SPI_GETSELECTIONFADE:
1886 case SPI_GETTOOLTIPANIMATION:
1887 case SPI_GETTOOLTIPFADE:
1888 case SPI_GETCURSORSHADOW:
1889 case SPI_GETUIEFFECTS:
1890 case SPI_GETMOUSESONAR:
1891 case SPI_GETMOUSECLICKLOCK:
1892 case SPI_GETMOUSEVANISH:
1893 case SPI_GETFLATMENU:
1894 case SPI_GETDROPSHADOW:
1895 case SPI_GETBLOCKSENDINPUTRESETS:
1896 #if(_WIN32_WINNT >= 0x0600)
1897 case SPI_GETDISABLEOVERLAPPEDCONTENT:
1898 case SPI_GETCLIENTAREAANIMATION:
1899 case SPI_GETCLEARTYPE:
1900 case SPI_GETSPEECHRECOGNITION:
1901 #endif
1902 case SPI_GETFOREGROUNDLOCKTIMEOUT:
1903 case SPI_GETACTIVEWNDTRKTIMEOUT:
1904 case SPI_GETFOREGROUNDFLASHCOUNT:
1905 case SPI_GETCARETWIDTH:
1906 case SPI_GETMOUSECLICKLOCKTIME:
1907 case SPI_GETFONTSMOOTHINGTYPE:
1908 case SPI_GETFONTSMOOTHINGCONTRAST:
1909 case SPI_GETFOCUSBORDERWIDTH:
1910 case SPI_GETFOCUSBORDERHEIGHT:
1911 case SPI_GETFONTSMOOTHINGORIENTATION:
1912 cbSize = sizeof(INT);
1913 break;
1914
1915 case SPI_ICONHORIZONTALSPACING:
1916 case SPI_ICONVERTICALSPACING:
1917 if (pvParam) cbSize = sizeof(INT);
1918 break;
1919
1920 case SPI_GETMOUSE:
1921 cbSize = 3 * sizeof(INT);
1922 break;
1923
1924 case SPI_GETDESKWALLPAPER:
1925 cbSize = min(uiParam, gspv.ustrWallpaper.Length + 1UL);
1926 break;
1927
1928 case SPI_GETICONTITLELOGFONT:
1929 cbSize = sizeof(LOGFONTW);
1930 break;
1931
1932 case SPI_GETNONCLIENTMETRICS:
1933 cbSize = sizeof(NONCLIENTMETRICSW);
1934 break;
1935
1936 case SPI_GETMINIMIZEDMETRICS:
1937 cbSize = sizeof(MINIMIZEDMETRICS);
1938 break;
1939
1940 case SPI_GETICONMETRICS:
1941 cbSize = sizeof(ICONMETRICSW);
1942 break;
1943
1944 case SPI_GETWORKAREA:
1945 cbSize = sizeof(RECTL);
1946 break;
1947
1948 case SPI_GETFILTERKEYS:
1949 cbSize = sizeof(FILTERKEYS);
1950 break;
1951
1952 case SPI_GETTOGGLEKEYS:
1953 cbSize = sizeof(TOGGLEKEYS);
1954 break;
1955
1956 case SPI_GETMOUSEKEYS:
1957 cbSize = sizeof(MOUSEKEYS);
1958 break;
1959
1960 case SPI_GETSTICKYKEYS:
1961 cbSize = sizeof(STICKYKEYS);
1962 break;
1963
1964 case SPI_GETACCESSTIMEOUT:
1965 cbSize = sizeof(ACCESSTIMEOUT);
1966 break;
1967
1968 case SPI_GETSERIALKEYS:
1969 cbSize = sizeof(SERIALKEYS);
1970 break;
1971
1972 case SPI_GETSOUNDSENTRY:
1973 cbSize = sizeof(SOUNDSENTRYW);
1974 break;
1975
1976 case SPI_GETHIGHCONTRAST:
1977 cbSize = sizeof(HIGHCONTRASTW);
1978 break;
1979
1980 case SPI_GETANIMATION:
1981 cbSize = sizeof(ANIMATIONINFO);
1982 break;
1983
1984 case SPI_GETDEFAULTINPUTLANG:
1985 cbSize = sizeof(HKL);
1986 break;
1987
1988 #if(WINVER >= 0x0600)
1989 case SPI_GETAUDIODESCRIPTION:
1990 cbSize = sizeof(AUDIODESCRIPTION);
1991 break;
1992 #endif
1993
1994 case SPI_SETMOUSE:
1995 cbSize = 3 * sizeof(INT);
1996 bToUser = FALSE;
1997 break;
1998
1999 case SPI_SETICONTITLELOGFONT:
2000 cbSize = sizeof(LOGFONTW);
2001 bToUser = FALSE;
2002 break;
2003
2004 case SPI_SETNONCLIENTMETRICS:
2005 cbSize = sizeof(NONCLIENTMETRICSW);
2006 bToUser = FALSE;
2007 break;
2008
2009 case SPI_SETMINIMIZEDMETRICS:
2010 cbSize = sizeof(MINIMIZEDMETRICS);
2011 bToUser = FALSE;
2012 break;
2013
2014 case SPI_SETICONMETRICS:
2015 cbSize = sizeof(ICONMETRICSW);
2016 bToUser = FALSE;
2017 break;
2018
2019 case SPI_SETWORKAREA:
2020 cbSize = sizeof(RECTL);
2021 bToUser = FALSE;
2022 break;
2023
2024 case SPI_SETFILTERKEYS:
2025 cbSize = sizeof(FILTERKEYS);
2026 bToUser = FALSE;
2027 break;
2028
2029 case SPI_SETTOGGLEKEYS:
2030 cbSize = sizeof(TOGGLEKEYS);
2031 bToUser = FALSE;
2032 break;
2033
2034 case SPI_SETMOUSEKEYS:
2035 cbSize = sizeof(MOUSEKEYS);
2036 bToUser = FALSE;
2037 break;
2038
2039 case SPI_SETSTICKYKEYS:
2040 cbSize = sizeof(STICKYKEYS);
2041 bToUser = FALSE;
2042 break;
2043
2044 case SPI_SETACCESSTIMEOUT:
2045 cbSize = sizeof(ACCESSTIMEOUT);
2046 bToUser = FALSE;
2047 break;
2048
2049 case SPI_SETSERIALKEYS:
2050 cbSize = sizeof(SERIALKEYS);
2051 bToUser = FALSE;
2052 break;
2053
2054 case SPI_SETSOUNDSENTRY:
2055 cbSize = sizeof(SOUNDSENTRYW);
2056 bToUser = FALSE;
2057 break;
2058
2059 case SPI_SETHIGHCONTRAST:
2060 cbSize = sizeof(HIGHCONTRASTW);
2061 bToUser = FALSE;
2062 break;
2063
2064 case SPI_SETANIMATION:
2065 cbSize = sizeof(ANIMATIONINFO);
2066 bToUser = FALSE;
2067 break;
2068
2069 case SPI_SETDEFAULTINPUTLANG:
2070 cbSize = sizeof(HKL);
2071 bToUser = FALSE;
2072 break;
2073
2074 case SPI_SETMOUSESPEED:
2075 cbSize = sizeof(INT);
2076 bToUser = FALSE;
2077 break;
2078 }
2079
2080 if (cbSize)
2081 {
2082 _SEH2_TRY
2083 {
2084 if (bToUser)
2085 {
2086 ProbeForWrite(pvParam, cbSize, sizeof(UCHAR));
2087 }
2088 else
2089 {
2090 ProbeForRead(pvParam, cbSize, sizeof(UCHAR));
2091 }
2092 }
2093 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2094 {
2095 _SEH2_YIELD(return FALSE);
2096 }
2097 _SEH2_END;
2098 }
2099
2100 return TRUE;
2101 }
2102
2103 BOOL
2104 FASTCALL
UserSystemParametersInfo(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinIni)2105 UserSystemParametersInfo(
2106 UINT uiAction,
2107 UINT uiParam,
2108 PVOID pvParam,
2109 UINT fWinIni)
2110 {
2111 ULONG_PTR ulResult;
2112 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
2113
2114 ASSERT(ppi);
2115
2116 if (!gbSpiInitialized)
2117 {
2118 KeRosDumpStackFrames(NULL, 20);
2119 //ASSERT(FALSE);
2120 return FALSE;
2121 }
2122
2123 /* Get a pointer to the current Windowstation */
2124 if (!ppi->prpwinsta)
2125 {
2126 ERR("UserSystemParametersInfo called without active window station.\n");
2127 //ASSERT(FALSE);
2128 //return FALSE;
2129 }
2130
2131 if ((fWinIni & SPIF_PROTECT) && !SpiGetSetProbeBuffer(uiAction, uiParam, pvParam))
2132 {
2133 EngSetLastError(ERROR_NOACCESS);
2134 return FALSE;
2135 }
2136
2137 /* Do the actual operation */
2138 ulResult = SpiGetSet(uiAction, uiParam, pvParam, fWinIni);
2139
2140 /* Did we change something? */
2141 if (ulResult > 1)
2142 {
2143 SpiFixupValues();
2144
2145 /* Update system metrics */
2146 InitMetrics();
2147
2148 /* Send notification to toplevel windows, if requested */
2149 if (fWinIni & SPIF_SENDCHANGE)
2150 {
2151 /* Send WM_SETTINGCHANGE to all toplevel windows */
2152 co_IntSendMessageTimeout(HWND_BROADCAST,
2153 WM_SETTINGCHANGE,
2154 (WPARAM)uiAction,
2155 (LPARAM)ulResult,
2156 SMTO_NORMAL,
2157 100,
2158 &ulResult);
2159 }
2160 ulResult = 1;
2161 }
2162
2163 return ulResult;
2164 }
2165
2166 BOOL
2167 APIENTRY
NtUserSystemParametersInfo(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinIni)2168 NtUserSystemParametersInfo(
2169 UINT uiAction,
2170 UINT uiParam,
2171 PVOID pvParam,
2172 UINT fWinIni)
2173 {
2174 BOOL bResult;
2175
2176 TRACE("Enter NtUserSystemParametersInfo(%u)\n", uiAction);
2177 UserEnterExclusive();
2178
2179 // FIXME: Get rid of the flags and only use this from um. kernel can access data directly.
2180 /* Set UM memory protection flag */
2181 fWinIni |= SPIF_PROTECT;
2182
2183 /* Call internal function */
2184 bResult = UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
2185
2186 TRACE("Leave NtUserSystemParametersInfo, returning %d\n", bResult);
2187 UserLeave();
2188
2189 return bResult;
2190 }
2191
2192 /* EOF */
2193