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