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