ReactOS 0.4.17-dev-804-g023d8af
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
13 _In_opt_ HANDLE hDevice,
14 _In_ UINT uiCommand,
16 _Inout_ PUINT pcbSize)
17{
19 UINT cbSize, cbRequiredSize;
20 UINT Ret = (UINT)-1;
21
23 {
24 ProbeForRead(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
25 cbSize = *pcbSize;
26 }
28 {
30 _SEH2_YIELD(return Ret);
31 }
33
35 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo && DeviceInfo != hDevice; DeviceInfo = DeviceInfo->pNextDeviceInfo)
36 ;
37 if (!DeviceInfo)
38 {
41 return Ret;
42 }
43
45
46 switch (uiCommand)
47 {
48 case RIDI_PREPARSEDDATA:
49 if (DeviceInfo->DeviceType == RIM_TYPEHID)
50 cbRequiredSize = DeviceInfo->Hid.CollectionInformation.DescriptorSize;
51 else
52 cbRequiredSize = 0;
53 break;
54 case RIDI_DEVICENAME:
55 cbRequiredSize = DeviceInfo->DeviceName.Length / sizeof(WCHAR) + sizeof(ANSI_NULL);
56 break;
57 case RIDI_DEVICEINFO:
58 cbRequiredSize = sizeof(RID_DEVICE_INFO);
59 break;
60 default:
62 goto cleanup;
63 }
64
66 {
67 if (!pData)
68 {
69 ProbeForWrite(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
70 *pcbSize = cbRequiredSize;
71 Ret = 0;
73 }
74
75 if (cbSize < cbRequiredSize)
76 {
77 ProbeForWrite(pcbSize, sizeof(*pcbSize), sizeof(DWORD));
78 *pcbSize = cbRequiredSize;
81 }
82
83 ProbeForWrite(pData, cbRequiredSize, sizeof(DWORD));
84 switch (uiCommand)
85 {
86 case RIDI_PREPARSEDDATA:
87 if (DeviceInfo->DeviceType == RIM_TYPEHID)
88 RtlCopyMemory(pData, DeviceInfo->Hid.PreparsedData, cbRequiredSize);
89 break;
90 case RIDI_DEVICENAME:
91 // As cbSize/cbRequiredSize are in chars, we didn't probe a big enough buffer
92 // Do it again
93 ProbeForWrite(pData, DeviceInfo->DeviceName.Length + sizeof(UNICODE_NULL), sizeof(DWORD));
94 RtlCopyMemory(pData, DeviceInfo->DeviceName.Buffer, DeviceInfo->DeviceName.Length);
95 ((WCHAR*)pData)[cbRequiredSize - 1] = UNICODE_NULL;
96 break;
97 case RIDI_DEVICEINFO:
98 {
99 PRID_DEVICE_INFO prdi = pData;
100 ProbeForRead(&prdi->cbSize, sizeof(prdi->cbSize), sizeof(DWORD));
101 if (prdi->cbSize != cbRequiredSize)
102 {
104 _SEH2_YIELD(break);
105 }
106
107 ProbeForWrite(prdi, sizeof(*prdi), sizeof(DWORD));
108 RtlZeroMemory(prdi, sizeof(*prdi));
109 prdi->cbSize = sizeof(*prdi);
110 prdi->dwType = DeviceInfo->DeviceType;
111
112 switch (DeviceInfo->DeviceType)
113 {
114 case RIM_TYPEMOUSE:
115 prdi->mouse.dwId = DeviceInfo->Mouse.Attributes.MouseIdentifier & ~HORIZONTAL_WHEEL_PRESENT;
116 prdi->mouse.dwNumberOfButtons = DeviceInfo->Mouse.Attributes.NumberOfButtons;
117 prdi->mouse.dwSampleRate = DeviceInfo->Mouse.Attributes.SampleRate;
118 prdi->mouse.fHasHorizontalWheel = !!(DeviceInfo->Mouse.Attributes.MouseIdentifier & HORIZONTAL_WHEEL_PRESENT);
119 break;
120
121 case RIM_TYPEKEYBOARD:
122 prdi->keyboard.dwType = DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type;
123 prdi->keyboard.dwSubType = DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Subtype;
124 prdi->keyboard.dwKeyboardMode = DeviceInfo->Keyboard.Attributes.KeyboardMode;
125 prdi->keyboard.dwNumberOfFunctionKeys = DeviceInfo->Keyboard.Attributes.NumberOfFunctionKeys;
126 prdi->keyboard.dwNumberOfIndicators = DeviceInfo->Keyboard.Attributes.NumberOfIndicators;
127 prdi->keyboard.dwNumberOfKeysTotal = DeviceInfo->Keyboard.Attributes.NumberOfKeysTotal;
128 break;
129
130 case RIM_TYPEHID:
131 prdi->hid.dwVendorId = DeviceInfo->Hid.CollectionInformation.VendorID;
132 prdi->hid.dwProductId = DeviceInfo->Hid.CollectionInformation.ProductID;
133 prdi->hid.dwVersionNumber = DeviceInfo->Hid.CollectionInformation.VersionNumber;
134 prdi->hid.usUsagePage = DeviceInfo->Hid.Caps.UsagePage;
135 prdi->hid.usUsage = DeviceInfo->Hid.Caps.Usage;
136 break;
137
138 default:
139 break;
140 }
141 break;
142 }
143 default:
144 ASSERT(FALSE);
145 break;
146 }
147 Ret = cbRequiredSize;
148 }
150 {
152 }
153 _SEH2_END;
154
155cleanup:
156 UserLeave();
158 return Ret;
159}
160
161DWORD
164 _Out_opt_ PRAWINPUTDEVICELIST pRawInputDeviceList,
165 _Inout_ PUINT puiNumDevices,
166 _In_ UINT cbSize)
167{
169 UINT cDevices = 0, i, Ret = (UINT)-1;
170
171 if (cbSize != sizeof(RAWINPUTDEVICELIST))
172 {
174 return Ret;
175 }
176
178 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo; DeviceInfo = DeviceInfo->pNextDeviceInfo)
179 cDevices++;
180
182
184 {
185 if (!pRawInputDeviceList)
186 {
187 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
188 *puiNumDevices = cDevices;
189 Ret = 0;
191 }
192
193 ProbeForRead(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
194 if (*puiNumDevices < cDevices)
195 {
196 ProbeForWrite(puiNumDevices, sizeof(*puiNumDevices), sizeof(DWORD));
197 *puiNumDevices = cDevices;
200 }
201
202 ProbeForWrite(pRawInputDeviceList, cDevices * sizeof(*pRawInputDeviceList), sizeof(PVOID));
203 for (DeviceInfo = gpInputDeviceInfo, i = 0; DeviceInfo && i < cDevices; DeviceInfo = DeviceInfo->pNextDeviceInfo, i++)
204 {
205 pRawInputDeviceList[i].hDevice = DeviceInfo;
206 pRawInputDeviceList[i].dwType = DeviceInfo->DeviceType;
207 }
208 Ret = cDevices;
209 }
211 {
213 }
214 _SEH2_END;
215
216 UserLeave();
218 return Ret;
219}
220
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#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
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 long DWORD
Definition: ntddk_ex.h:95
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
unsigned int UINT
Definition: sysinfo.c:13
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define ASSERT(a)
Definition: mode.c:44
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
#define UNICODE_NULL
#define ANSI_NULL
#define HORIZONTAL_WHEEL_PRESENT
Definition: ntddmou.h:106
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:241
short WCHAR
Definition: pedump.c:58
#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 NtUserGetRawInputDeviceList(_Out_opt_ PRAWINPUTDEVICELIST pRawInputDeviceList, _Inout_ PUINT puiNumDevices, _In_ UINT cbSize)
Definition: rawinput.c:163
DWORD APIENTRY NtUserGetRawInputDeviceInfo(_In_opt_ HANDLE hDevice, _In_ UINT uiCommand, _Inout_opt_ LPVOID pData, _Inout_ PUINT pcbSize)
Definition: rawinput.c:12
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
PINPUT_DEVICE_INFO gpInputDeviceInfo
Definition: input.c:27
FORCEINLINE VOID ReleaseDeviceInfoListMutex(VOID)
Definition: input.h:148
FORCEINLINE VOID AcquireDeviceInfoListMutex(VOID)
Definition: input.h:140
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21