xref: /reactos/dll/win32/syssetup/proppage.c (revision a6726659)
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