1 /* 2 * PROJECT: ReactOS system libraries 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/syssetup/proppage.c 5 * PURPOSE: Property page providers 6 * PROGRAMMERS: Copyright 2018 Eric Kohl <eric.kohl@reactos.org> 7 */ 8 9 #include "precomp.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 typedef struct _MOUSE_INFO 15 { 16 HKEY hDeviceKey; 17 DWORD dwSampleRateIndex; 18 DWORD dwWheelDetection; 19 DWORD dwInputBufferLength; 20 DWORD dwInitPolled; 21 } MOUSE_INFO, *PMOUSE_INFO; 22 23 DWORD MouseSampleRates[] = {20, 40, 60, 80, 100, 200}; 24 25 #define DEFAULT_SAMPLERATEINDEX 4 26 #define DEFAULT_WHEELDETECTION 2 27 #define DEFAULT_INPUTBUFFERSIZE 100 28 #define DEFAULT_MINBUFFERSIZE 100 29 #define DEFAULT_MAXBUFFERSIZE 300 30 31 /* 32 * @implemented 33 */ 34 BOOL 35 WINAPI 36 CdromPropPageProvider( 37 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 38 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 39 _In_ LPARAM lParam) 40 { 41 DPRINT("CdromPropPageProvider(%p %p %lx)\n", 42 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 43 return FALSE; 44 } 45 46 47 /* 48 * @implemented 49 */ 50 BOOL 51 WINAPI 52 DiskPropPageProvider( 53 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 54 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 55 _In_ LPARAM lParam) 56 { 57 DPRINT("DiskPropPageProvider(%p %p %lx)\n", 58 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 59 return FALSE; 60 } 61 62 63 /* 64 * @implemented 65 */ 66 BOOL 67 WINAPI 68 EisaUpHalPropPageProvider( 69 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 70 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 71 _In_ LPARAM lParam) 72 { 73 DPRINT("EisaUpHalPropPageProvider(%p %p %lx)\n", 74 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 75 return FALSE; 76 } 77 78 79 /* 80 * @unimplemented 81 */ 82 BOOL 83 WINAPI 84 LegacyDriverPropPageProvider( 85 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 86 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 87 _In_ LPARAM lParam) 88 { 89 DPRINT1("LegacyDriverPropPageProvider(%p %p %lx)\n", 90 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 91 UNIMPLEMENTED; 92 return FALSE; 93 } 94 95 96 static 97 DWORD 98 MouseGetSampleRateIndex( 99 DWORD dwSampleRate) 100 { 101 DWORD i; 102 103 for (i = 0; i < ARRAYSIZE(MouseSampleRates); i++) 104 { 105 if (MouseSampleRates[i] == dwSampleRate) 106 return i; 107 } 108 109 return DEFAULT_SAMPLERATEINDEX; 110 } 111 112 113 static 114 BOOL 115 MouseOnDialogInit( 116 HWND hwndDlg, 117 LPARAM lParam) 118 { 119 PMOUSE_INFO pMouseInfo; 120 WCHAR szBuffer[64]; 121 UINT i; 122 DWORD dwType, dwSize; 123 DWORD dwSampleRate; 124 LONG lError; 125 126 /* Get the pointer to the mouse info struct */ 127 pMouseInfo = (PMOUSE_INFO)((LPPROPSHEETPAGE)lParam)->lParam; 128 if (pMouseInfo == NULL) 129 return FALSE; 130 131 /* Keep the pointer to the mouse info struct */ 132 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pMouseInfo); 133 134 /* Add the sample rates */ 135 for (i = 0; i < ARRAYSIZE(MouseSampleRates); i++) 136 { 137 wsprintf(szBuffer, L"%lu", MouseSampleRates[i]); 138 SendDlgItemMessageW(hwndDlg, 139 IDC_PS2MOUSESAMPLERATE, 140 CB_ADDSTRING, 141 0, 142 (LPARAM)szBuffer); 143 } 144 145 /* Read the SampleRate parameter */ 146 dwSize = sizeof(DWORD); 147 lError = RegQueryValueExW(pMouseInfo->hDeviceKey, 148 L"SampleRate", 149 NULL, 150 &dwType, 151 (LPBYTE)&dwSampleRate, 152 &dwSize); 153 if (lError == ERROR_SUCCESS && dwType == REG_DWORD && dwSize == sizeof(DWORD)) 154 { 155 pMouseInfo->dwSampleRateIndex = MouseGetSampleRateIndex(dwSampleRate); 156 } 157 else 158 { 159 /* Set the default sample rate (100 samples per second) */ 160 pMouseInfo->dwSampleRateIndex = DEFAULT_SAMPLERATEINDEX; 161 } 162 163 /* Set the sample rate */ 164 SendDlgItemMessageW(hwndDlg, 165 IDC_PS2MOUSESAMPLERATE, 166 CB_SETCURSEL, 167 pMouseInfo->dwSampleRateIndex, 168 0); 169 170 /* Add the detection options */ 171 for (i = IDS_DETECTIONDISABLED; i <= IDS_ASSUMEPRESENT; i++) 172 { 173 LoadStringW(hDllInstance, i, szBuffer, ARRAYSIZE(szBuffer)); 174 SendDlgItemMessageW(hwndDlg, 175 IDC_PS2MOUSEWHEEL, 176 CB_ADDSTRING, 177 0, 178 (LPARAM)szBuffer); 179 } 180 181 /* Read the EnableWheelDetection parameter */ 182 dwSize = sizeof(DWORD); 183 lError = RegQueryValueExW(pMouseInfo->hDeviceKey, 184 L"EnableWheelDetection", 185 NULL, 186 &dwType, 187 (LPBYTE)&pMouseInfo->dwWheelDetection, 188 &dwSize); 189 if (lError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD)) 190 { 191 /* Set the default wheel detection parameter */ 192 pMouseInfo->dwWheelDetection = DEFAULT_WHEELDETECTION; 193 } 194 195 /* Set the wheel detection parameter */ 196 SendDlgItemMessageW(hwndDlg, 197 IDC_PS2MOUSEWHEEL, 198 CB_SETCURSEL, 199 pMouseInfo->dwWheelDetection, 200 0); 201 202 /* Set the input buffer length range: 100-300 */ 203 SendDlgItemMessageW(hwndDlg, 204 IDC_PS2MOUSEINPUTUPDN, 205 UDM_SETRANGE32, 206 DEFAULT_MINBUFFERSIZE, 207 DEFAULT_MAXBUFFERSIZE); 208 209 /* Read the MouseDataQueueSize parameter */ 210 dwSize = sizeof(DWORD); 211 lError = RegQueryValueExW(pMouseInfo->hDeviceKey, 212 L"MouseDataQueueSize", 213 NULL, 214 &dwType, 215 (LPBYTE)&pMouseInfo->dwInputBufferLength, 216 &dwSize); 217 if (lError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD)) 218 { 219 /* Set the default input buffer length (100 packets) */ 220 pMouseInfo->dwInputBufferLength = DEFAULT_INPUTBUFFERSIZE; 221 } 222 223 /* Set the input buffer length */ 224 SendDlgItemMessageW(hwndDlg, 225 IDC_PS2MOUSEINPUTUPDN, 226 UDM_SETPOS32, 227 0, 228 pMouseInfo->dwInputBufferLength); 229 230 /* Read the MouseInitializePolled parameter */ 231 dwSize = sizeof(DWORD); 232 lError = RegQueryValueExW(pMouseInfo->hDeviceKey, 233 L"MouseInitializePolled", 234 NULL, 235 &dwType, 236 (LPBYTE)&pMouseInfo->dwInitPolled, 237 &dwSize); 238 if (lError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD)) 239 { 240 /* Set the default init polled value (FALSE) */ 241 pMouseInfo->dwInitPolled = 0; 242 } 243 244 /* Set the fast initialization option */ 245 SendDlgItemMessage(hwndDlg, 246 IDC_PS2MOUSEFASTINIT, 247 BM_SETCHECK, 248 (pMouseInfo->dwInitPolled == 0) ? BST_CHECKED : 0, 249 0); 250 251 return TRUE; 252 } 253 254 255 static 256 VOID 257 MouseOnCommand( 258 HWND hwndDlg, 259 WPARAM wParam, 260 LPARAM lParam) 261 { 262 switch (LOWORD(wParam)) 263 { 264 case IDC_PS2MOUSESAMPLERATE: 265 case IDC_PS2MOUSEWHEEL: 266 case IDC_PS2MOUSEINPUTLEN: 267 case IDC_PS2MOUSEFASTINIT: 268 if (HIWORD(wParam) == CBN_SELCHANGE || 269 HIWORD(wParam) == CBN_EDITCHANGE) 270 { 271 /* Enable the Apply button */ 272 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 273 } 274 break; 275 276 case IDC_PS2MOUSEDEFAULTS: 277 if (HIWORD(wParam) == BN_CLICKED) 278 { 279 /* Sample rate: 100 */ 280 SendDlgItemMessageW(hwndDlg, 281 IDC_PS2MOUSESAMPLERATE, 282 CB_SETCURSEL, 283 DEFAULT_SAMPLERATEINDEX, 284 0); 285 286 /* Wheel detection: Assume wheel present */ 287 SendDlgItemMessageW(hwndDlg, 288 IDC_PS2MOUSEWHEEL, 289 CB_SETCURSEL, 290 DEFAULT_WHEELDETECTION, 291 0); 292 293 /* Input buffer length: 100 packets */ 294 SendDlgItemMessageW(hwndDlg, 295 IDC_PS2MOUSEINPUTUPDN, 296 UDM_SETPOS32, 297 0, 298 DEFAULT_INPUTBUFFERSIZE); 299 300 /* Fast Initialization: Checked */ 301 SendDlgItemMessage(hwndDlg, 302 IDC_PS2MOUSEFASTINIT, 303 BM_SETCHECK, 304 (WPARAM)BST_CHECKED, 305 (LPARAM)0); 306 307 /* Enable the Apply button */ 308 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 309 } 310 break; 311 312 default: 313 break; 314 } 315 } 316 317 318 static 319 VOID 320 MouseOnApply( 321 HWND hwndDlg) 322 { 323 PMOUSE_INFO pMouseInfo; 324 DWORD dwSampleRateIndex = 0; 325 DWORD dwSampleRate, dwWheelDetection; 326 DWORD dwInputBufferLength; 327 DWORD dwInitPolled; 328 UINT uValue; 329 BOOL bFailed; 330 INT nIndex; 331 332 pMouseInfo = (PMOUSE_INFO)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 333 334 /* Get the sample rate setting and store it if it was changed */ 335 nIndex = SendDlgItemMessageW(hwndDlg, IDC_PS2MOUSESAMPLERATE, 336 CB_GETCURSEL, 0, 0); 337 if (nIndex == CB_ERR) 338 dwSampleRateIndex = DEFAULT_SAMPLERATEINDEX; 339 else 340 dwSampleRateIndex = (DWORD)nIndex; 341 342 if (dwSampleRateIndex != pMouseInfo->dwSampleRateIndex) 343 { 344 dwSampleRate = MouseSampleRates[dwSampleRateIndex]; 345 RegSetValueExW(pMouseInfo->hDeviceKey, 346 L"SampleRate", 347 0, 348 REG_DWORD, 349 (LPBYTE)&dwSampleRate, 350 sizeof(dwSampleRate)); 351 } 352 353 /* Get the wheel detection setting and store it if it was changed */ 354 nIndex = SendDlgItemMessageW(hwndDlg, IDC_PS2MOUSEWHEEL, 355 CB_GETCURSEL, 0, 0); 356 if (nIndex == CB_ERR) 357 dwWheelDetection = DEFAULT_WHEELDETECTION; 358 else 359 dwWheelDetection = (DWORD)nIndex; 360 361 if (dwWheelDetection != pMouseInfo->dwWheelDetection) 362 { 363 RegSetValueExW(pMouseInfo->hDeviceKey, 364 L"EnableWheelDetection", 365 0, 366 REG_DWORD, 367 (LPBYTE)&dwWheelDetection, 368 sizeof(dwWheelDetection)); 369 } 370 371 /* Get the input buffer length setting and store it if it was changed */ 372 uValue = SendDlgItemMessageW(hwndDlg, 373 IDC_PS2MOUSEINPUTUPDN, 374 UDM_GETPOS32, 375 0, 376 (LPARAM)&bFailed); 377 if (bFailed) 378 dwInputBufferLength = DEFAULT_INPUTBUFFERSIZE; 379 else 380 dwInputBufferLength = (DWORD)uValue; 381 382 if (dwInputBufferLength != pMouseInfo->dwInputBufferLength) 383 { 384 RegSetValueExW(pMouseInfo->hDeviceKey, 385 L"MouseDataQueueSize", 386 0, 387 REG_DWORD, 388 (LPBYTE)&dwInputBufferLength, 389 sizeof(dwInputBufferLength)); 390 } 391 392 /* Get the fast initialization setting and store it if it was changed */ 393 uValue = SendDlgItemMessage(hwndDlg, 394 IDC_PS2MOUSEFASTINIT, 395 BM_GETCHECK, 396 0, 397 0); 398 dwInitPolled = (uValue == BST_CHECKED) ? 0 : 1; 399 400 if (dwInitPolled != pMouseInfo->dwInitPolled) 401 { 402 RegSetValueExW(pMouseInfo->hDeviceKey, 403 L"MouseInitializePolled", 404 0, 405 REG_DWORD, 406 (LPBYTE)&dwInitPolled, 407 sizeof(dwInitPolled)); 408 } 409 } 410 411 412 static 413 BOOL 414 MouseOnNotify( 415 HWND hwndDlg, 416 WPARAM wParam, 417 LPARAM lParam) 418 { 419 switch (((LPNMHDR)lParam)->code) 420 { 421 case UDN_DELTAPOS: 422 if (((LPNMHDR)lParam)->idFrom == IDC_PS2MOUSEINPUTUPDN) 423 { 424 ((LPNMUPDOWN)lParam)->iDelta *= 10; 425 return FALSE; 426 } 427 break; 428 429 case PSN_APPLY: 430 MouseOnApply(hwndDlg); 431 return TRUE; 432 } 433 434 return FALSE; 435 } 436 437 438 static 439 INT_PTR 440 MouseOnCtrlColorStatic( 441 HWND hwndDlg, 442 WPARAM wParam, 443 LPARAM lParam) 444 { 445 if ((HWND)lParam != GetDlgItem(hwndDlg, IDC_PS2MOUSEINPUTLEN)) 446 return 0; 447 448 SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); 449 SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); 450 return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); 451 } 452 453 454 static 455 INT_PTR 456 CALLBACK 457 MouseDlgProc( 458 HWND hwndDlg, 459 UINT uMsg, 460 WPARAM wParam, 461 LPARAM lParam) 462 { 463 DPRINT("MouseDlgProc\n"); 464 465 switch (uMsg) 466 { 467 case WM_INITDIALOG: 468 return MouseOnDialogInit(hwndDlg, lParam); 469 470 case WM_COMMAND: 471 MouseOnCommand(hwndDlg, wParam, lParam); 472 break; 473 474 case WM_NOTIFY: 475 return MouseOnNotify(hwndDlg, wParam, lParam); 476 477 case WM_CTLCOLORSTATIC: 478 return MouseOnCtrlColorStatic(hwndDlg, wParam, lParam); 479 } 480 481 return FALSE; 482 } 483 484 485 static 486 UINT 487 CALLBACK 488 MouseCallback( 489 HWND hWnd, 490 UINT uMsg, 491 LPPROPSHEETPAGE ppsp) 492 { 493 PMOUSE_INFO pMouseInfo; 494 495 pMouseInfo = (PMOUSE_INFO)ppsp->lParam; 496 497 if (uMsg == PSPCB_RELEASE) 498 { 499 if (pMouseInfo->hDeviceKey != NULL) 500 RegCloseKey(pMouseInfo->hDeviceKey); 501 HeapFree(GetProcessHeap(), 0, pMouseInfo); 502 } 503 504 return 1; 505 } 506 507 508 /* 509 * @implemented 510 */ 511 BOOL 512 WINAPI 513 PS2MousePropPageProvider( 514 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 515 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 516 _In_ LPARAM lParam) 517 { 518 PROPSHEETPAGEW PropSheetPage; 519 HPROPSHEETPAGE hPropSheetPage; 520 PMOUSE_INFO pMouseInfo; 521 522 DPRINT("PS2MousePropPageProvider(%p %p %lx)\n", 523 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 524 525 if (lpPropSheetPageRequest->PageRequested != SPPSR_ENUM_ADV_DEVICE_PROPERTIES) 526 return FALSE; 527 528 pMouseInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MOUSE_INFO)); 529 if (pMouseInfo == NULL) 530 return FALSE; 531 532 pMouseInfo->hDeviceKey = SetupDiOpenDevRegKey(lpPropSheetPageRequest->DeviceInfoSet, 533 lpPropSheetPageRequest->DeviceInfoData, 534 DICS_FLAG_GLOBAL, 535 0, 536 DIREG_DEV, 537 KEY_ALL_ACCESS); 538 if (pMouseInfo->hDeviceKey == INVALID_HANDLE_VALUE) 539 { 540 DPRINT1("SetupDiOpenDevRegKey() failed (Error %lu)\n", GetLastError()); 541 HeapFree(GetProcessHeap(), 0, pMouseInfo); 542 return FALSE; 543 } 544 545 PropSheetPage.dwSize = sizeof(PROPSHEETPAGEW); 546 PropSheetPage.dwFlags = 0; 547 PropSheetPage.hInstance = hDllInstance; 548 PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PS2MOUSEPROPERTIES); 549 PropSheetPage.pfnDlgProc = MouseDlgProc; 550 PropSheetPage.lParam = (LPARAM)pMouseInfo; 551 PropSheetPage.pfnCallback = MouseCallback; 552 553 hPropSheetPage = CreatePropertySheetPageW(&PropSheetPage); 554 if (hPropSheetPage == NULL) 555 { 556 DPRINT1("CreatePropertySheetPageW() failed!\n"); 557 HeapFree(GetProcessHeap(), 0, pMouseInfo); 558 return FALSE; 559 } 560 561 if (!(*lpfnAddPropSheetPageProc)(hPropSheetPage, lParam)) 562 { 563 DPRINT1("lpfnAddPropSheetPageProc() failed!\n"); 564 DestroyPropertySheetPage(hPropSheetPage); 565 HeapFree(GetProcessHeap(), 0, pMouseInfo); 566 return FALSE; 567 } 568 569 return TRUE; 570 } 571 572 573 /* 574 * @implemented 575 */ 576 BOOL 577 WINAPI 578 TapePropPageProvider( 579 _In_ PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 580 _In_ LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc, 581 _In_ LPARAM lParam) 582 { 583 DPRINT("TapePropPageProvider(%p %p %lx)\n", 584 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam); 585 return FALSE; 586 } 587 588 /* EOF */ 589