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