From f35438fc41fcbdb27e96e8bfcf2aff40df2fa1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 16 Sep 2026 18:34:30 +0200 Subject: [PATCH] [NTUSER] Read input device attributes in OpenInputDevice() (#9562) We now detect number of mouse buttons at runtime, and NtUserGetRawInputDeviceInfo() returns correct device information. CORE-9818 --- win32ss/user/ntuser/input.c | 65 ++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/win32ss/user/ntuser/input.c b/win32ss/user/ntuser/input.c index a0b511e408f..70a64782e78 100644 --- a/win32ss/user/ntuser/input.c +++ b/win32ss/user/ntuser/input.c @@ -103,34 +103,65 @@ DoTheScreenSaver(VOID) */ static NTSTATUS NTAPI -OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName) +OpenInputDevice( + _In_ PINPUT_DEVICE_INFO DeviceInfo) { - UNICODE_STRING DeviceName; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; IO_STATUS_BLOCK Iosb; - RtlInitUnicodeString(&DeviceName, pszDeviceName); - InitializeObjectAttributes(&ObjectAttributes, - &DeviceName, + &DeviceInfo->DeviceName, OBJ_KERNEL_HANDLE, NULL, NULL); - Status = ZwOpenFile(pHandle, + Status = ZwOpenFile(&DeviceInfo->Handle, FILE_ALL_ACCESS, &ObjectAttributes, &Iosb, 0, 0); - if (NT_SUCCESS(Status) && ppObject) + if (!NT_SUCCESS(Status)) { - Status = ObReferenceObjectByHandle(*pHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)ppObject, NULL); - ASSERT(NT_SUCCESS(Status)); + ERR("ZwOpenFile('%wZ') failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status); + return Status; } - return Status; + if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD) + { + Status = ZwDeviceIoControlFile(DeviceInfo->Handle, + NULL, + NULL, + NULL, + &DeviceInfo->Iosb, + IOCTL_KEYBOARD_QUERY_ATTRIBUTES, + NULL, 0, + &DeviceInfo->Keyboard.Attributes, + sizeof(DeviceInfo->Keyboard.Attributes)); + if (!NT_SUCCESS(Status)) + { + ERR("ZwDeviceIoControlFile('%wZ', IOCTL_KEYBOARD_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status); + } + } + else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE) + { + Status = ZwDeviceIoControlFile(DeviceInfo->Handle, + NULL, + NULL, + NULL, + &DeviceInfo->Iosb, + IOCTL_MOUSE_QUERY_ATTRIBUTES, + NULL, 0, + &DeviceInfo->Mouse.Attributes, + sizeof(DeviceInfo->Mouse.Attributes)); + if (!NT_SUCCESS(Status)) + { + ERR("ZwDeviceIoControlFile('%wZ', IOCTL_MOUSE_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status); + } + } + + return STATUS_SUCCESS; } /* @@ -159,7 +190,6 @@ RawInputThreadMain(VOID) RtlZeroMemory(&Mouse, sizeof(Mouse)); Mouse.DeviceType = RIM_TYPEMOUSE; RtlInitUnicodeString(&Mouse.DeviceName, L"\\Device\\PointerClass0"); - Mouse.Mouse.Attributes.NumberOfButtons = 2; RtlZeroMemory(&Keyboard, sizeof(Keyboard)); Keyboard.DeviceType = RIM_TYPEKEYBOARD; @@ -212,30 +242,33 @@ RawInputThreadMain(VOID) if (!ghMouseDevice) { /* Check if mouse device already exists */ - Status = OpenInputDevice(&ghMouseDevice, &pMouDevice, Mouse.DeviceName.Buffer); + Status = OpenInputDevice(&Mouse); if (NT_SUCCESS(Status)) { ++cMaxWaitObjects; TRACE("Mouse connected!\n"); - Mouse.Handle = ghMouseDevice; Mouse.pNextDeviceInfo = gpInputDeviceInfo; gpInputDeviceInfo = &Mouse; + ghMouseDevice = Mouse.Handle; + Status = ObReferenceObjectByHandle(Mouse.Handle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)&pMouDevice, NULL); + ASSERT(NT_SUCCESS(Status)); } } if (!ghKeyboardDevice) { /* Check if keyboard device already exists */ - Status = OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, Keyboard.DeviceName.Buffer); + Status = OpenInputDevice(&Keyboard); if (NT_SUCCESS(Status)) { ++cMaxWaitObjects; TRACE("Keyboard connected!\n"); - Keyboard.Handle = ghKeyboardDevice; Keyboard.pNextDeviceInfo = gpInputDeviceInfo; gpInputDeviceInfo = &Keyboard; + ghKeyboardDevice = Keyboard.Handle; + Status = ObReferenceObjectByHandle(Keyboard.Handle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)&pKbdDevice, NULL); + ASSERT(NT_SUCCESS(Status)); // Get and load keyboard attributes. UserInitKeyboard(ghKeyboardDevice); - Keyboard.Keyboard.Attributes = gKeyboardInfo; UserEnterExclusive(); // Register the Window hotkey. UserRegisterHotKey(PWND_BOTTOM, IDHK_WINKEY, MOD_WIN, 0);