ReactOS 0.4.17-dev-1190-g4c812f4
rawinput.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Win32k subsystem
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Functions related to Raw Input handling
5 * COPYRIGHT: Copyright 2026 Hervé Poussineau
6 */
7
8#include <win32k.h>
9#define NDEBUG
10#include <debug.h>
11
12#ifndef HID_USAGE_PAGE_GENERIC
13#define HID_USAGE_PAGE_GENERIC 0x01
14#endif
15
16#ifndef HID_USAGE_GENERIC_MOUSE
17#define HID_USAGE_GENERIC_MOUSE 0x02
18#endif
19
20#ifndef HID_USAGE_GENERIC_KEYBOARD
21#define HID_USAGE_GENERIC_KEYBOARD 0x06
22#endif
23
24typedef struct _USER_RAWINPUT
25{
27 RAWINPUT RawInput;
29
30C_ASSERT(FIELD_OFFSET(RAWINPUT, data) == sizeof(RAWINPUTHEADER));
31C_ASSERT(sizeof(RAWINPUTHEADER) + sizeof(RAWMOUSE) <= sizeof(RAWINPUT));
32C_ASSERT(sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD) <= sizeof(RAWINPUT));
33
34#define MAX_RAWINPUT_PER_QUEUE 256
35
37PRAWINPUTDEVICE global_pRawInputDevices = NULL;
39
43 _In_opt_ HANDLE hDevice,
44 _In_ UINT uiCommand,
46 _Inout_ PUINT pcbSize)
47{
49 UINT cbSize, cbRequiredSize;
50 UINT Ret = (UINT)-1;
51
53 {
54 ProbeForRead(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
55 cbSize = *pcbSize;
56 }
58 {
60 _SEH2_YIELD(return Ret);
61 }
63
65 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo && DeviceInfo != hDevice; DeviceInfo = DeviceInfo->pNextDeviceInfo)
66 ;
67 if (!DeviceInfo)
68 {
71 return Ret;
72 }
73
75
76 switch (uiCommand)
77 {
78 case RIDI_PREPARSEDDATA:
79 if (DeviceInfo->DeviceType == RIM_TYPEHID)
80 cbRequiredSize = DeviceInfo->Hid.CollectionInformation.DescriptorSize;
81 else
82 cbRequiredSize = 0;
83 break;
84 case RIDI_DEVICENAME:
85 cbRequiredSize = DeviceInfo->DeviceName.Length / sizeof(WCHAR) + sizeof(ANSI_NULL);
86 break;
87 case RIDI_DEVICEINFO:
88 cbRequiredSize = sizeof(RID_DEVICE_INFO);
89 break;
90 default:
92 goto cleanup;
93 }
94
96 {
97 if (!pData)
98 {
99 ProbeForWrite(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
100 *pcbSize = cbRequiredSize;
101 Ret = 0;
103 }
104
105 if (cbSize < cbRequiredSize)
106 {
107 ProbeForWrite(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
108 *pcbSize = cbRequiredSize;
111 }
112
113 ProbeForWrite(pData, cbRequiredSize, sizeof(DWORD));
114 switch (uiCommand)
115 {
116 case RIDI_PREPARSEDDATA:
117 if (DeviceInfo->DeviceType == RIM_TYPEHID)
118 RtlCopyMemory(pData, DeviceInfo->Hid.PreparsedData, cbRequiredSize);
119 break;
120 case RIDI_DEVICENAME:
121 // As cbSize/cbRequiredSize are in chars, we didn't probe a big enough buffer
122 // Do it again
123 ProbeForWrite(pData, DeviceInfo->DeviceName.Length + sizeof(UNICODE_NULL), sizeof(DWORD));
124 RtlCopyMemory(pData, DeviceInfo->DeviceName.Buffer, DeviceInfo->DeviceName.Length);
125 ((WCHAR*)pData)[cbRequiredSize - 1] = UNICODE_NULL;
126 break;
127 case RIDI_DEVICEINFO:
128 {
129 PRID_DEVICE_INFO prdi = pData;
130 ProbeForRead(&prdi->cbSize, sizeof(prdi->cbSize), sizeof(DWORD));
131 if (prdi->cbSize != cbRequiredSize)
132 {
134 _SEH2_YIELD(break);
135 }
136
137 ProbeForWrite(prdi, sizeof(*prdi), sizeof(DWORD));
138 RtlZeroMemory(prdi, sizeof(*prdi));
139 prdi->cbSize = sizeof(*prdi);
140 prdi->dwType = DeviceInfo->DeviceType;
141
142 switch (DeviceInfo->DeviceType)
143 {
144 case RIM_TYPEMOUSE:
145 prdi->mouse.dwId = DeviceInfo->Mouse.Attributes.MouseIdentifier & ~HORIZONTAL_WHEEL_PRESENT;
146 prdi->mouse.dwNumberOfButtons = DeviceInfo->Mouse.Attributes.NumberOfButtons;
147 prdi->mouse.dwSampleRate = DeviceInfo->Mouse.Attributes.SampleRate;
148 prdi->mouse.fHasHorizontalWheel = !!(DeviceInfo->Mouse.Attributes.MouseIdentifier & HORIZONTAL_WHEEL_PRESENT);
149 break;
150
151 case RIM_TYPEKEYBOARD:
152 prdi->keyboard.dwType = DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type;
153 prdi->keyboard.dwSubType = DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Subtype;
154 prdi->keyboard.dwKeyboardMode = DeviceInfo->Keyboard.Attributes.KeyboardMode;
155 prdi->keyboard.dwNumberOfFunctionKeys = DeviceInfo->Keyboard.Attributes.NumberOfFunctionKeys;
156 prdi->keyboard.dwNumberOfIndicators = DeviceInfo->Keyboard.Attributes.NumberOfIndicators;
157 prdi->keyboard.dwNumberOfKeysTotal = DeviceInfo->Keyboard.Attributes.NumberOfKeysTotal;
158 break;
159
160 case RIM_TYPEHID:
161 prdi->hid.dwVendorId = DeviceInfo->Hid.CollectionInformation.VendorID;
162 prdi->hid.dwProductId = DeviceInfo->Hid.CollectionInformation.ProductID;
163 prdi->hid.dwVersionNumber = DeviceInfo->Hid.CollectionInformation.VersionNumber;
164 prdi->hid.usUsagePage = DeviceInfo->Hid.Caps.UsagePage;
165 prdi->hid.usUsage = DeviceInfo->Hid.Caps.Usage;
166 break;
167
168 default:
169 break;
170 }
171 break;
172 }
173 default:
174 ASSERT(FALSE);
175 break;
176 }
177 Ret = cbRequiredSize;
178 }
180 {
182 }
183 _SEH2_END;
184
185cleanup:
186 UserLeave();
188 return Ret;
189}
190
191
192static
193INT
195 DWORD dwType)
196{
197 switch (dwType)
198 {
199 case RIM_TYPEMOUSE:
200 return 0;
201
202 case RIM_TYPEKEYBOARD:
203 return 1;
204
205 default:
206 return -1;
207 }
208}
209
210static
211PRAWINPUTDEVICE
213 DWORD dwType)
214{
216
217 if (!global_pRawInputDevices || Index < 0)
218 return NULL;
219
221 return NULL;
222
223 if ((dwType == RIM_TYPEMOUSE && global_pRawInputDevices[Index].usUsage != HID_USAGE_GENERIC_MOUSE) ||
224 (dwType == RIM_TYPEKEYBOARD && global_pRawInputDevices[Index].usUsage != HID_USAGE_GENERIC_KEYBOARD))
225 return NULL;
226
228}
229
230static
231VOID
233 const RAWINPUTDEVICE *Device)
234{
235 BOOL IsMouse = (Device->usUsagePage == HID_USAGE_PAGE_GENERIC &&
236 Device->usUsage == HID_USAGE_GENERIC_MOUSE);
237 BOOL IsKeyboard = (Device->usUsagePage == HID_USAGE_PAGE_GENERIC &&
239 DWORD PageFlags = Device->dwFlags & (RIDEV_PAGEONLY | RIDEV_EXCLUDE);
240
241 if ((PageFlags == RIDEV_NOLEGACY) && (IsMouse || IsKeyboard))
242 {
243 DPRINT1("RIDEV_NOLEGACY for raw %s is accepted but not implemented yet.\n",
244 IsMouse ? "mouse" : "keyboard");
245 }
246 else
247 {
248 if (Device->dwFlags & RIDEV_PAGEONLY)
249 DPRINT1("RIDEV_PAGEONLY is accepted but not implemented yet.\n");
250
251 if (Device->dwFlags & RIDEV_EXCLUDE)
252 DPRINT1("RIDEV_EXCLUDE is accepted but not implemented yet.\n");
253 }
254
255 if (IsMouse && (Device->dwFlags & RIDEV_CAPTUREMOUSE))
256 DPRINT1("RIDEV_CAPTUREMOUSE for raw mouse is accepted but not implemented yet.\n");
257
258 if (IsKeyboard && (Device->dwFlags & RIDEV_NOHOTKEYS))
259 DPRINT1("RIDEV_NOHOTKEYS for raw keyboard is accepted but not implemented yet.\n");
260
261 if (IsKeyboard && (Device->dwFlags & RIDEV_APPKEYS))
262 DPRINT1("RIDEV_APPKEYS for raw keyboard is accepted but not implemented yet.\n");
263
264 if (Device->dwFlags & RIDEV_EXINPUTSINK)
265 DPRINT1("RIDEV_EXINPUTSINK is only partially implemented.\n");
266
267 if (Device->dwFlags & RIDEV_DEVNOTIFY)
268 DPRINT1("RIDEV_DEVNOTIFY is accepted but not implemented yet.\n");
269}
270
271static
274 PUSER_MESSAGE_QUEUE MessageQueue,
275 HRAWINPUT hRawInput)
276{
278
279 if (!MessageQueue || !hRawInput)
280 return NULL;
281
282 for (Entry = MessageQueue->RawInputListHead.Flink;
283 Entry != &MessageQueue->RawInputListHead;
284 Entry = Entry->Flink)
285 {
286 PUSER_RAWINPUT RawEntry = CONTAINING_RECORD(Entry, USER_RAWINPUT, ListEntry);
287 if ((HRAWINPUT)&RawEntry->RawInput == hRawInput)
288 return RawEntry;
289 }
290
291 return NULL;
292}
293
294static
295VOID
297 PUSER_MESSAGE_QUEUE MessageQueue,
298 PUSER_RAWINPUT RawEntry)
299{
300 ASSERT(MessageQueue->cRawInput > 0);
301 RemoveEntryList(&RawEntry->ListEntry);
302 MessageQueue->cRawInput--;
303 ExFreeToPagedLookasideList(&gRawInputLookasideList, RawEntry);
304}
305
306CODE_SEG("INIT")
308NTAPI
310{
312 NULL,
313 NULL,
314 0,
315 sizeof(USER_RAWINPUT),
316 'iwar',
317 256);
318 return STATUS_SUCCESS;
319}
320
321HRAWINPUT
324 PTHREADINFO pti,
325 DWORD dwType,
326 HANDLE hDevice,
329 UINT cbData)
330{
331 PUSER_RAWINPUT RawEntry;
332
333 if (!pti || !pti->MessageQueue || !pData)
334 return NULL;
335
336 ASSERT(cbData <= sizeof(RawEntry->RawInput.data));
337 if (cbData > sizeof(RawEntry->RawInput.data))
338 return NULL;
339
340 if (pti->MessageQueue->cRawInput >= MAX_RAWINPUT_PER_QUEUE)
341 {
342 DPRINT("Dropping raw input, queue %p is not being pumped\n", pti->MessageQueue);
343 return NULL;
344 }
345
346 RawEntry = ExAllocateFromPagedLookasideList(&gRawInputLookasideList);
347 if (!RawEntry)
348 return NULL;
349
350 RtlZeroMemory(RawEntry, sizeof(*RawEntry));
351 RawEntry->RawInput.header.dwType = dwType;
352 RawEntry->RawInput.header.dwSize = sizeof(RAWINPUTHEADER) + cbData;
353 RawEntry->RawInput.header.hDevice = hDevice;
354 RawEntry->RawInput.header.wParam = wParam;
355 RtlCopyMemory(&RawEntry->RawInput.data, pData, cbData);
356
357 InsertTailList(&pti->MessageQueue->RawInputListHead, &RawEntry->ListEntry);
358 pti->MessageQueue->cRawInput++;
359 return (HRAWINPUT)&RawEntry->RawInput;
360}
361
362BOOL
365 PUSER_MESSAGE_QUEUE MessageQueue,
366 HRAWINPUT hRawInput)
367{
368 PUSER_RAWINPUT RawEntry = RawInputEntryFromHandle(MessageQueue, hRawInput);
369
370 if (!RawEntry)
371 return FALSE;
372
373 RawInputFreeEntry(MessageQueue, RawEntry);
374 return TRUE;
375}
376
377VOID
380 PTHREADINFO pti,
381 CONST MSG *pMsg)
382{
383 if (pti->hPrevRawInput)
384 {
386 pti->hPrevRawInput = NULL;
387 }
388
389 if (pMsg->message == WM_INPUT &&
390 (pMsg->wParam == RIM_INPUT || pMsg->wParam == RIM_INPUTSINK))
391 {
392 pti->hPrevRawInput = (HRAWINPUT)pMsg->lParam;
393 }
394}
395
396VOID
399 PUSER_MESSAGE_QUEUE MessageQueue)
400{
401 while (!IsListEmpty(&MessageQueue->RawInputListHead))
402 {
403 PUSER_RAWINPUT RawEntry;
404 RawEntry = CONTAINING_RECORD(MessageQueue->RawInputListHead.Flink,
406 ListEntry);
407 RawInputFreeEntry(MessageQueue, RawEntry);
408 }
409}
410
411BOOL
414 DWORD dwType,
415 PTHREADINFO *ppti,
416 HWND *phwndTarget,
417 WPARAM *pwParam)
418{
419 PRAWINPUTDEVICE Registration;
420 PUSER_MESSAGE_QUEUE pFocusQueue;
421 PWND pWnd = NULL;
422 PTHREADINFO pti;
423
425 if (!Registration)
426 return FALSE;
427
428 pFocusQueue = IntGetFocusMessageQueue();
429 if (!pFocusQueue)
430 return FALSE;
431
432 if (Registration->hwndTarget)
433 {
434 pWnd = UserGetWindowObject(Registration->hwndTarget);
435 if (!pWnd)
436 return FALSE;
437 }
438 else
439 {
440 pWnd = pFocusQueue->spwndFocus;
441 if (!pWnd)
442 pWnd = pFocusQueue->spwndActive;
443 if (!pWnd)
444 return FALSE;
445 }
446
447 pti = pWnd->head.pti;
448 if (!pti)
449 return FALSE;
450
451 if (pFocusQueue->ptiKeyboard && pti->rpdesk != pFocusQueue->ptiKeyboard->rpdesk)
452 return FALSE;
453
454 if (Registration->dwFlags & RIDEV_INPUTSINK)
455 {
456 *pwParam = (pti->MessageQueue == pFocusQueue) ? RIM_INPUT : RIM_INPUTSINK;
457 *phwndTarget = UserHMGetHandle(pWnd);
458 *ppti = pti;
459 return TRUE;
460 }
461
462 if (Registration->dwFlags & RIDEV_EXINPUTSINK)
463 {
464 if (pti->MessageQueue != pFocusQueue)
465 return FALSE; /* FIXME: Needs per-process arbitration like Windows */
466
467 *pwParam = RIM_INPUT;
468 *phwndTarget = UserHMGetHandle(pWnd);
469 *ppti = pti;
470 return TRUE;
471 }
472
473 if (pti->MessageQueue != pFocusQueue)
474 return FALSE;
475
476 *pwParam = RIM_INPUT;
477 *phwndTarget = UserHMGetHandle(pWnd);
478 *ppti = pti;
479 return TRUE;
480}
481
482static
483DWORD
485 PRAWINPUT RawInput,
486 UINT uiCommand,
488 PUINT pcbSize,
489 UINT cbSizeHeader)
490{
491 UINT OutputDataSize;
492
493 if (cbSizeHeader != sizeof(RAWINPUTHEADER) || !pcbSize)
494 {
496 return ~0u;
497 }
498
499 switch (uiCommand)
500 {
501 case RID_INPUT:
502 OutputDataSize = RawInput->header.dwSize;
503 break;
504
505 case RID_HEADER:
506 OutputDataSize = sizeof(RAWINPUTHEADER);
507 break;
508
509 default:
511 return ~0u;
512 }
513
514 if (!pData)
515 {
516 *pcbSize = OutputDataSize;
518 return 0;
519 }
520
521 if (*pcbSize < OutputDataSize)
522 {
523 *pcbSize = OutputDataSize;
525 return ~0u;
526 }
527
528 if (uiCommand == RID_HEADER)
529 RtlCopyMemory(pData, &RawInput->header, OutputDataSize);
530 else
531 RtlCopyMemory(pData, RawInput, OutputDataSize);
532
533 return OutputDataSize;
534}
535
536/* This file is pretty deeply inspired by how wine seems to do it, but wine can't be DIRECTLY used. */
537DWORD
540 PRAWINPUT pData,
541 PUINT pcbSize,
542 UINT cbSizeHeader)
543{
544 PTHREADINFO pti;
545 PUSER_MESSAGE_QUEUE MessageQueue;
546 PUSER_RAWINPUT RawEntry;
547 PLIST_ENTRY Entry, NextEntry;
548 UINT BufferSize, UsedSize = 0, Count = 0;
549
550 if (cbSizeHeader != sizeof(RAWINPUTHEADER) || !pcbSize)
551 {
553 return ~0u;
554 }
555
557 MessageQueue = pti ? pti->MessageQueue : NULL;
558 if (!MessageQueue)
559 {
560 *pcbSize = 0;
561 return 0;
562 }
563
564 Entry = MessageQueue->HardwareMessagesListHead.Flink;
565 if (!pData)
566 {
567 while (Entry != &MessageQueue->HardwareMessagesListHead)
568 {
570 if (Message->Msg.message == WM_INPUT)
571 {
572 RawEntry = RawInputEntryFromHandle(MessageQueue, (HRAWINPUT)Message->Msg.lParam);
573 *pcbSize = RawEntry ? RawEntry->RawInput.header.dwSize : 0;
575 return 0;
576 }
577 Entry = Entry->Flink;
578 }
579
580 *pcbSize = 0;
581 return 0;
582 }
583
584 BufferSize = *pcbSize;
585 while (Entry != &MessageQueue->HardwareMessagesListHead)
586 {
588 UINT RawSize;
589
590 NextEntry = Entry->Flink;
592 Entry = NextEntry;
593
594 if (Message->Msg.message != WM_INPUT)
595 continue;
596
597 RawEntry = RawInputEntryFromHandle(MessageQueue, (HRAWINPUT)Message->Msg.lParam);
598 if (!RawEntry)
599 continue;
600
601 RawSize = RawEntry->RawInput.header.dwSize;
602 if (UsedSize + RawSize > BufferSize)
603 {
604 if (Count == 0)
605 {
606 *pcbSize = RawSize;
608 return ~0u;
609 }
610 break;
611 }
612
613 RtlCopyMemory((PBYTE)pData + UsedSize, &RawEntry->RawInput, RawSize);
614 UsedSize += RawSize;
615 Count++;
616
617 ClearMsgBitsMask(pti, Message->QS_Flags);
619 RawInputFreeEntry(MessageQueue, RawEntry);
620 }
621
622 return Count;
623}
624
625DWORD
628 _Out_opt_ PRAWINPUTDEVICELIST pRawInputDeviceList,
629 _Inout_ PUINT puiNumDevices,
631{
633 UINT cDevices = 0, i, Ret = (UINT)-1;
634
635 if (cbSize != sizeof(RAWINPUTDEVICELIST))
636 {
638 return Ret;
639 }
640
642 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo; DeviceInfo = DeviceInfo->pNextDeviceInfo)
643 cDevices++;
644
646
648 {
649 if (!pRawInputDeviceList)
650 {
651 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
652 *puiNumDevices = cDevices;
653 Ret = 0;
655 }
656
657 ProbeForRead(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
658 if (*puiNumDevices < cDevices)
659 {
660 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
661 *puiNumDevices = cDevices;
664 }
665
666 ProbeForWrite(pRawInputDeviceList, cDevices * sizeof(*pRawInputDeviceList), sizeof(PVOID));
667 for (DeviceInfo = gpInputDeviceInfo, i = 0; DeviceInfo && i < cDevices; DeviceInfo = DeviceInfo->pNextDeviceInfo, i++)
668 {
669 pRawInputDeviceList[i].hDevice = DeviceInfo;
670 pRawInputDeviceList[i].dwType = DeviceInfo->DeviceType;
671 }
672 Ret = cDevices;
673 }
675 {
677 }
678 _SEH2_END;
679
680 UserLeave();
682 return Ret;
683}
684
685DWORD
686NTAPI
688 HRAWINPUT hRawInput,
689 UINT uiCommand,
691 PUINT pcbSize,
692 UINT cbSizeHeader)
693{
694 PTHREADINFO pti;
695 PUSER_MESSAGE_QUEUE MessageQueue;
696 PUSER_RAWINPUT RawEntry;
697
698 if (cbSizeHeader != sizeof(RAWINPUTHEADER) || !pcbSize)
699 {
701 return ~0u;
702 }
703
704 if (!hRawInput)
705 {
707 return ~0u;
708 }
709
711 MessageQueue = pti ? pti->MessageQueue : NULL;
712 RawEntry = RawInputEntryFromHandle(MessageQueue, hRawInput);
713 if (!RawEntry)
714 {
716 return ~0u;
717 }
718
719 return RawInputCopyData(&RawEntry->RawInput, uiCommand, pData, pcbSize, cbSizeHeader);
720}
721
722
723DWORD
726 _Out_opt_ PRAWINPUTDEVICE pRawInputDevices,
727 _Inout_ PUINT puiNumDevices,
729{
730 RAWINPUTDEVICE Registrations[2];
731 PRAWINPUTDEVICE Registration;
732 UINT cDevices = 0, uiNumDevices, Ret = (UINT)-1;
733
734 if (cbSize != sizeof(*pRawInputDevices))
735 {
737 return Ret;
738 }
739
741
742 /* Snapshot the registrations, ordered by usage like Windows does */
744 if (Registration)
745 Registrations[cDevices++] = *Registration;
746
747 Registration = RawInputRegistrationFromType(RIM_TYPEKEYBOARD);
748 if (Registration)
749 Registrations[cDevices++] = *Registration;
750
752 {
753 if (!pRawInputDevices)
754 {
755 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
756 *puiNumDevices = cDevices;
757 Ret = 0;
759 }
760
761 ProbeForRead(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
762 uiNumDevices = *puiNumDevices;
763 if (uiNumDevices == 0)
764 {
767 }
768
769 /* Windows raises an access violation for counts it cannot probe */
770 if (uiNumDevices > MAXULONG / sizeof(*pRawInputDevices))
771 {
774 }
775
776 ProbeForWrite(pRawInputDevices, uiNumDevices * sizeof(*pRawInputDevices), sizeof(PVOID));
777 if (uiNumDevices < cDevices)
778 {
779 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
780 *puiNumDevices = cDevices;
783 }
784
785 RtlCopyMemory(pRawInputDevices, Registrations, cDevices * sizeof(*pRawInputDevices));
786 Ret = cDevices;
787 }
789 {
791 }
792 _SEH2_END;
793
794 UserLeave();
795 return Ret;
796}
797
798BOOL
801 IN PCRAWINPUTDEVICE pRawInputDevices,
802 IN UINT uiNumDevices,
803 IN UINT cbSize)
804{
805 UINT i;
806
807 if (!pRawInputDevices || !uiNumDevices || cbSize != sizeof(RAWINPUTDEVICE))
808 {
810 return FALSE;
811 }
812
814 {
816 2 * sizeof(RAWINPUTDEVICE),
817 'iwar');
819 {
821 return FALSE;
822 }
823
824 RtlZeroMemory(global_pRawInputDevices, 2 * sizeof(RAWINPUTDEVICE));
825 }
826
827 for (i = 0; i < uiNumDevices; ++i)
828 {
829 INT Index;
830 const RAWINPUTDEVICE *Device = &pRawInputDevices[i];
831
832 if ((Device->dwFlags & RIDEV_INPUTSINK) && !Device->hwndTarget)
833 {
835 return FALSE;
836 }
837
838 if ((Device->dwFlags & RIDEV_REMOVE) && Device->hwndTarget)
839 {
841 return FALSE;
842 }
843
845
846 if (Device->usUsagePage != HID_USAGE_PAGE_GENERIC)
847 continue;
848
849 if (Device->usUsage == HID_USAGE_GENERIC_MOUSE)
850 Index = 0;
851 else if (Device->usUsage == HID_USAGE_GENERIC_KEYBOARD)
852 Index = 1;
853 else
854 continue;
855
856 if (Device->dwFlags & RIDEV_REMOVE)
857 RtlZeroMemory(&global_pRawInputDevices[Index], sizeof(RAWINPUTDEVICE));
858 else
860 }
861
863 (global_pRawInputDevices[0].usUsage != 0) ||
864 (global_pRawInputDevices[1].usUsage != 0);
865
866 return TRUE;
867}
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
WPARAM wParam
Definition: combotst.c:138
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
_In_ ULONG BufferSize
Definition: dispmprt.h:490
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
static void cleanup(void)
Definition: main.c:1335
static const WCHAR Message[]
Definition: register.c:74
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define NonPagedPool
Definition: env_spec_w32.h:307
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ CONST FLT_REGISTRATION * Registration
Definition: fltkernel.h:991
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
unsigned int UINT
Definition: sysinfo.c:13
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
#define UserHMGetHandle(obj)
Definition: ntuser.h:233
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define C_ASSERT(e)
Definition: intsafe.h:73
VOID NTAPI ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:270
UINT_PTR WPARAM
Definition: minwindef.h:174
#define ASSERT(a)
Definition: mode.c:44
VOID FASTCALL ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits)
Definition: msgqueue.c:445
VOID FASTCALL MsqDestroyMessage(PUSER_MESSAGE Message)
Definition: msgqueue.c:748
unsigned int * PUINT
Definition: ndis.h:50
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Inout_opt_
Definition: no_sal2.h:216
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
int Count
Definition: noreturn.cpp:7
#define FASTCALL
Definition: nt_native.h:50
#define UNICODE_NULL
#define ANSI_NULL
#define HORIZONTAL_WHEEL_PRESENT
Definition: ntddmou.h:106
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:829
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:241
#define CONST
Definition: pedump.c:81
BYTE * PBYTE
Definition: pedump.c:66
short WCHAR
Definition: pedump.c:58
void * EngAllocMem(int zero, unsigned long size, int tag=0)
Definition: polytest.cpp:70
#define RIDEV_PAGEONLY
Definition: winuser.h:2962
#define RIDEV_APPKEYS
Definition: winuser.h:2967
#define RIDEV_CAPTUREMOUSE
Definition: winuser.h:2965
#define RIDEV_NOLEGACY
Definition: winuser.h:2963
#define WM_INPUT
Definition: winuser.h:1740
#define RIDEV_EXCLUDE
Definition: winuser.h:2961
#define RIDEV_INPUTSINK
Definition: winuser.h:2964
#define RIDEV_NOHOTKEYS
Definition: winuser.h:2966
#define RIDEV_REMOVE
Definition: winuser.h:2960
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define _SEH2_LEAVE
Definition: pseh2_64.h:206
DWORD APIENTRY NtUserGetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader)
Definition: rawinput.c:539
BOOL FASTCALL UserFreeRawInput(PUSER_MESSAGE_QUEUE MessageQueue, HRAWINPUT hRawInput)
Definition: rawinput.c:364
struct _USER_RAWINPUT * PUSER_RAWINPUT
BOOL FASTCALL UserGetRawInputTarget(DWORD dwType, PTHREADINFO *ppti, HWND *phwndTarget, WPARAM *pwParam)
Definition: rawinput.c:413
#define HID_USAGE_GENERIC_MOUSE
Definition: rawinput.c:17
PRAWINPUTDEVICE global_pRawInputDevices
Definition: rawinput.c:37
static PUSER_RAWINPUT RawInputEntryFromHandle(PUSER_MESSAGE_QUEUE MessageQueue, HRAWINPUT hRawInput)
Definition: rawinput.c:273
VOID FASTCALL UserCleanupRawInput(PUSER_MESSAGE_QUEUE MessageQueue)
Definition: rawinput.c:398
VOID FASTCALL UserUpdatePrevRawInput(PTHREADINFO pti, CONST MSG *pMsg)
Definition: rawinput.c:379
#define MAX_RAWINPUT_PER_QUEUE
Definition: rawinput.c:34
static INT RawInputDeviceIndexFromType(DWORD dwType)
Definition: rawinput.c:194
HRAWINPUT FASTCALL UserCreateRawInput(PTHREADINFO pti, DWORD dwType, HANDLE hDevice, WPARAM wParam, CONST VOID *pData, UINT cbData)
Definition: rawinput.c:323
DWORD NTAPI NtUserGetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader)
Definition: rawinput.c:687
struct _USER_RAWINPUT USER_RAWINPUT
DWORD APIENTRY NtUserGetRawInputDeviceList(_Out_opt_ PRAWINPUTDEVICELIST pRawInputDeviceList, _Inout_ PUINT puiNumDevices, _In_ UINT cbSize)
Definition: rawinput.c:627
static PAGED_LOOKASIDE_LIST gRawInputLookasideList
Definition: rawinput.c:36
static DWORD RawInputCopyData(PRAWINPUT RawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader)
Definition: rawinput.c:484
#define HID_USAGE_PAGE_GENERIC
Definition: rawinput.c:13
DWORD APIENTRY NtUserGetRawInputDeviceInfo(_In_opt_ HANDLE hDevice, _In_ UINT uiCommand, _Inout_opt_ LPVOID pData, _Inout_ PUINT pcbSize)
Definition: rawinput.c:42
static PRAWINPUTDEVICE RawInputRegistrationFromType(DWORD dwType)
Definition: rawinput.c:212
static VOID RawInputWarnUnimplementedFlags(const RAWINPUTDEVICE *Device)
Definition: rawinput.c:232
NTSTATUS NTAPI InitRawInputImpl(VOID)
Definition: rawinput.c:309
static VOID RawInputFreeEntry(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_RAWINPUT RawEntry)
Definition: rawinput.c:296
DWORD APIENTRY NtUserGetRegisteredRawInputDevices(_Out_opt_ PRAWINPUTDEVICE pRawInputDevices, _Inout_ PUINT puiNumDevices, _In_ UINT cbSize)
Definition: rawinput.c:725
#define HID_USAGE_GENERIC_KEYBOARD
Definition: rawinput.c:21
BOOLEAN RawInputEnabled
Definition: rawinput.c:38
BOOL APIENTRY NtUserRegisterRawInputDevices(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize)
Definition: rawinput.c:800
#define UINT
Definition: utils.c:29
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
HRAWINPUT hPrevRawInput
Definition: win32.h:156
struct _DESKTOP * rpdesk
Definition: win32.h:93
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
LIST_ENTRY HardwareMessagesListHead
Definition: msgqueue.h:59
PTHREADINFO ptiKeyboard
Definition: msgqueue.h:56
LIST_ENTRY RawInputListHead
Definition: msgqueue.h:61
RAWINPUT RawInput
Definition: rawinput.c:27
LIST_ENTRY ListEntry
Definition: rawinput.c:26
Definition: ntuser.h:698
THRDESKHEAD head
Definition: ntuser.h:699
PCBYTE PBYTE SIZE_T cbData
UINT32 cbSize
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define MAXULONG
Definition: typedefs.h:251
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:123
_In_ WDFCOLLECTION _In_ ULONG Index
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1335
PINPUT_DEVICE_INFO gpInputDeviceInfo
Definition: input.c:27
FORCEINLINE VOID ReleaseDeviceInfoListMutex(VOID)
Definition: input.h:165
FORCEINLINE VOID AcquireDeviceInfoListMutex(VOID)
Definition: input.h:157
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
#define ERROR_NOACCESS
Definition: winerror.h:902
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST