-- v2: user32: Merge rawinput.c into input.c. win32u: Move raw input device list management from user32. win32u: Move NtUserGetRegisteredRawInputDevices from user32. win32u: Move NtUserRegisterRawInputDevices from user32.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/rawinput.c | 63 ----------------------------------------- dlls/user32/user32.spec | 2 +- dlls/win32u/rawinput.c | 61 +++++++++++++++++++++++++++++++++++++++ dlls/win32u/syscall.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/wow64win/syscall.h | 1 + dlls/wow64win/user.c | 40 ++++++++++++++++++++++++++ include/ntuser.h | 1 + 8 files changed, 106 insertions(+), 65 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index d6290f08d12..1b02be1398d 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -401,69 +401,6 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun return rawinput_devices_count; }
-/*********************************************************************** - * RegisterRawInputDevices (USER32.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(const RAWINPUTDEVICE *devices, UINT device_count, UINT size) -{ - struct rawinput_device *d; - BOOL ret; - UINT i; - - TRACE("devices %p, device_count %u, size %u.\n", devices, device_count, size); - - if (size != sizeof(*devices)) - { - WARN("Invalid structure size %u.\n", size); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - for (i = 0; i < device_count; ++i) - { - if ((devices[i].dwFlags & RIDEV_INPUTSINK) && - (devices[i].hwndTarget == NULL)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ((devices[i].dwFlags & RIDEV_REMOVE) && - (devices[i].hwndTarget != NULL)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - } - - if (!(d = HeapAlloc( GetProcessHeap(), 0, device_count * sizeof(*d) ))) return FALSE; - - for (i = 0; i < device_count; ++i) - { - TRACE("device %u: page %#x, usage %#x, flags %#lx, target %p.\n", - i, devices[i].usUsagePage, devices[i].usUsage, - devices[i].dwFlags, devices[i].hwndTarget); - if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY)) - FIXME("Unhandled flags %#lx for device %u.\n", devices[i].dwFlags, i); - - d[i].usage_page = devices[i].usUsagePage; - d[i].usage = devices[i].usUsage; - d[i].flags = devices[i].dwFlags; - d[i].target = wine_server_user_handle( devices[i].hwndTarget ); - } - - SERVER_START_REQ( update_rawinput_devices ) - { - wine_server_add_data( req, d, device_count * sizeof(*d) ); - ret = !wine_server_call( req ); - } - SERVER_END_REQ; - - HeapFree( GetProcessHeap(), 0, d ); - - return ret; -} - /*********************************************************************** * GetRawInputDeviceInfoA (USER32.@) */ diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 887394227a3..dbe2a4c1430 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -605,7 +605,7 @@ @ stub RegisterNetworkCapabilities @ stdcall RegisterPointerDeviceNotifications(long long) @ stdcall RegisterPowerSettingNotification(long ptr long) -@ stdcall RegisterRawInputDevices(ptr long long) +@ stdcall RegisterRawInputDevices(ptr long long) NtUserRegisterRawInputDevices @ stdcall RegisterServicesProcess(long) @ stdcall RegisterShellHookWindow (long) @ stdcall RegisterSuspendResumeNotification(long long) diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index d6d4e0c13f7..359faa39083 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -366,3 +366,64 @@ BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_d msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); return TRUE; } + +/********************************************************************** + * NtUserRegisterRawInputDevices (win32u.@) + */ +BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT device_count, UINT size ) +{ + struct rawinput_device *server_devices; + BOOL ret; + UINT i; + + TRACE( "devices %p, device_count %u, size %u.\n", devices, device_count, size ); + + if (size != sizeof(*devices)) + { + WARN( "Invalid structure size %u.\n", size ); + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + for (i = 0; i < device_count; ++i) + { + if ((devices[i].dwFlags & RIDEV_INPUTSINK) && !devices[i].hwndTarget) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if ((devices[i].dwFlags & RIDEV_REMOVE) && devices[i].hwndTarget) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + } + + if (!(server_devices = malloc( device_count * sizeof(*server_devices) ))) return FALSE; + + for (i = 0; i < device_count; ++i) + { + TRACE( "device %u: page %#x, usage %#x, flags %#x, target %p.\n", + i, devices[i].usUsagePage, devices[i].usUsage, + devices[i].dwFlags, devices[i].hwndTarget ); + if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY)) + FIXME( "Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i ); + + server_devices[i].usage_page = devices[i].usUsagePage; + server_devices[i].usage = devices[i].usUsage; + server_devices[i].flags = devices[i].dwFlags; + server_devices[i].target = wine_server_user_handle( devices[i].hwndTarget ); + } + + SERVER_START_REQ( update_rawinput_devices ) + { + wine_server_add_data( req, server_devices, device_count * sizeof(*server_devices) ); + ret = !wine_server_call( req ); + } + SERVER_END_REQ; + + free( server_devices ); + + return ret; +} diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 12af30f6c98..3f2c596f727 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -160,6 +160,7 @@ static void * const syscalls[] = NtUserOpenDesktop, NtUserOpenInputDesktop, NtUserOpenWindowStation, + NtUserRegisterRawInputDevices, NtUserRemoveClipboardFormatListener, NtUserRemoveMenu, NtUserRemoveProp, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index c71f0d20429..687ef3af8dc 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1130,7 +1130,7 @@ @ stub NtUserRegisterManipulationThread @ stub NtUserRegisterPointerDeviceNotifications @ stub NtUserRegisterPointerInputTarget -@ stub NtUserRegisterRawInputDevices +@ stdcall -syscall NtUserRegisterRawInputDevices(ptr long long) @ stub NtUserRegisterServicesProcess @ stub NtUserRegisterSessionPort @ stub NtUserRegisterShellPTPListener diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 618a7990554..531f9f7f9cd 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -147,6 +147,7 @@ SYSCALL_ENTRY( NtUserOpenDesktop ) \ SYSCALL_ENTRY( NtUserOpenInputDesktop ) \ SYSCALL_ENTRY( NtUserOpenWindowStation ) \ + SYSCALL_ENTRY( NtUserRegisterRawInputDevices ) \ SYSCALL_ENTRY( NtUserRemoveClipboardFormatListener ) \ SYSCALL_ENTRY( NtUserRemoveMenu ) \ SYSCALL_ENTRY( NtUserRemoveProp ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 9c6730b24ae..231f6a04a1e 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -64,6 +64,14 @@ typedef struct UINT32 wParam; } RAWINPUTHEADER32;
+typedef struct +{ + USHORT usUsagePage; + USHORT usUsage; + DWORD dwFlags; + UINT32 hwndTarget; +} RAWINPUTDEVICE32; + static MSG *msg_32to64( MSG *msg, MSG32 *msg32 ) { if (!msg32) return NULL; @@ -975,3 +983,35 @@ NTSTATUS WINAPI wow64_NtUserGetRawInputBuffer( UINT *args ) * whether it's operating under WoW64 or not. */ return NtUserGetRawInputBuffer( data, data_size, sizeof(RAWINPUTHEADER) ); } + +NTSTATUS WINAPI wow64_NtUserRegisterRawInputDevices( UINT *args ) +{ + const RAWINPUTDEVICE32 *devices32 = get_ptr( &args ); + UINT count = get_ulong( &args ); + UINT size = get_ulong( &args ); + + RAWINPUTDEVICE *devices64; + unsigned int i; + + if (size != sizeof(RAWINPUTDEVICE32)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (!(devices64 = Wow64AllocateTemp( count * sizeof(*devices64) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + for (i = 0; i < count; ++i) + { + devices64[i].usUsagePage = devices32[i].usUsagePage; + devices64[i].usUsage = devices32[i].usUsage; + devices64[i].dwFlags = devices32[i].dwFlags; + devices64[i].hwndTarget = UlongToPtr( devices32[i].hwndTarget ); + } + + return NtUserRegisterRawInputDevices( devices64, count, sizeof(*devices64) ); +} diff --git a/include/ntuser.h b/include/ntuser.h index 18ddbcaa4a4..cb5696ec827 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -663,6 +663,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING * struct client_menu_name *client_menu_name, DWORD fnid, DWORD flags, DWORD *wow ); BOOL WINAPI NtUserRegisterHotKey( HWND hwnd, INT id, UINT modifiers, UINT vk ); +BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT device_count, UINT size ); INT WINAPI NtUserReleaseDC( HWND hwnd, HDC hdc ); BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd ); BOOL WINAPI NtUserRemoveMenu( HMENU menu, UINT id, UINT flags );
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/rawinput.c | 57 --------------------------------------- dlls/user32/user32.spec | 2 +- dlls/win32u/rawinput.c | 59 +++++++++++++++++++++++++++++++++++++++++ dlls/win32u/syscall.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/wow64win/syscall.h | 1 + dlls/wow64win/user.c | 41 ++++++++++++++++++++++++++++ include/ntuser.h | 1 + 8 files changed, 105 insertions(+), 59 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 1b02be1398d..588d1685cc0 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -506,63 +506,6 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT return *data_size; }
-static int __cdecl compare_raw_input_devices(const void *ap, const void *bp) -{ - const RAWINPUTDEVICE a = *(const RAWINPUTDEVICE *)ap; - const RAWINPUTDEVICE b = *(const RAWINPUTDEVICE *)bp; - - if (a.usUsagePage != b.usUsagePage) return a.usUsagePage - b.usUsagePage; - if (a.usUsage != b.usUsage) return a.usUsage - b.usUsage; - return 0; -} - -/*********************************************************************** - * GetRegisteredRawInputDevices (USER32.@) - */ -UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(RAWINPUTDEVICE *devices, UINT *device_count, UINT size) -{ - struct rawinput_device *buffer = NULL; - unsigned int i, status, count = ~0U, buffer_size; - - TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size); - - if (size != sizeof(RAWINPUTDEVICE) || !device_count || (devices && !*device_count)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - buffer_size = *device_count * sizeof(*buffer); - if (devices && !(buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size))) - return ~0U; - - SERVER_START_REQ(get_rawinput_devices) - { - if (buffer) wine_server_set_reply(req, buffer, buffer_size); - status = wine_server_call_err(req); - *device_count = reply->device_count; - } - SERVER_END_REQ; - - if (buffer && !status) - { - for (i = 0, count = *device_count; i < count; ++i) - { - devices[i].usUsagePage = buffer[i].usage_page; - devices[i].usUsage = buffer[i].usage; - devices[i].dwFlags = buffer[i].flags; - devices[i].hwndTarget = wine_server_ptr_handle(buffer[i].target); - } - - qsort(devices, count, sizeof(*devices), compare_raw_input_devices); - } - - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - else count = 0; - return count; -} - - /*********************************************************************** * DefRawInputProc (USER32.@) */ diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index dbe2a4c1430..3e20277251a 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -372,7 +372,7 @@ @ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) @ stdcall GetRawInputDeviceList(ptr ptr long) # @ stub GetReasonTitleFromReasonCode -@ stdcall GetRegisteredRawInputDevices(ptr ptr long) +@ stdcall GetRegisteredRawInputDevices(ptr ptr long) NtUserGetRegisteredRawInputDevices @ stdcall GetScrollBarInfo(long long ptr) @ stdcall GetScrollInfo(long long ptr) @ stdcall GetScrollPos(long long) diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 359faa39083..1caf11f2e76 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -427,3 +427,62 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d
return ret; } + +static int compare_raw_input_devices( const void *ap, const void *bp ) +{ + const RAWINPUTDEVICE a = *(const RAWINPUTDEVICE *)ap; + const RAWINPUTDEVICE b = *(const RAWINPUTDEVICE *)bp; + + if (a.usUsagePage != b.usUsagePage) return a.usUsagePage - b.usUsagePage; + if (a.usUsage != b.usUsage) return a.usUsage - b.usUsage; + return 0; +} + +/********************************************************************** + * NtUserGetRegisteredRawInputDevices (win32u.@) + */ +UINT WINAPI NtUserGetRegisteredRawInputDevices( RAWINPUTDEVICE *devices, UINT *device_count, UINT size ) +{ + struct rawinput_device *buffer = NULL; + unsigned int i, status, buffer_size; + + TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size); + + if (size != sizeof(RAWINPUTDEVICE) || !device_count || (devices && !*device_count)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + buffer_size = *device_count * sizeof(*buffer); + if (devices && !(buffer = malloc( buffer_size ))) + return ~0u; + + SERVER_START_REQ(get_rawinput_devices) + { + if (buffer) wine_server_set_reply( req, buffer, buffer_size ); + status = wine_server_call_err(req); + *device_count = reply->device_count; + } + SERVER_END_REQ; + if (status) + { + free( buffer ); + return ~0u; + } + + if (!devices) return 0; + + for (i = 0; i < *device_count; ++i) + { + devices[i].usUsagePage = buffer[i].usage_page; + devices[i].usUsage = buffer[i].usage; + devices[i].dwFlags = buffer[i].flags; + devices[i].hwndTarget = wine_server_ptr_handle(buffer[i].target); + } + + qsort( devices, *device_count, sizeof(*devices), compare_raw_input_devices ); + + free( buffer ); + return *device_count; +} diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 3f2c596f727..49746725816 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -147,6 +147,7 @@ static void * const syscalls[] = NtUserGetProp, NtUserGetRawInputBuffer, NtUserGetRawInputData, + NtUserGetRegisteredRawInputDevices, NtUserGetSystemDpiForProcess, NtUserGetThreadDesktop, NtUserGetTitleBarInfo, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 687ef3af8dc..dab6e2a5ed8 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -988,7 +988,7 @@ @ stub NtUserGetRawInputDeviceInfo @ stub NtUserGetRawInputDeviceList @ stub NtUserGetRawPointerDeviceData -@ stub NtUserGetRegisteredRawInputDevices +@ stdcall -syscall NtUserGetRegisteredRawInputDevices(ptr ptr long) @ stub NtUserGetRequiredCursorSizes @ stub NtUserGetResizeDCompositionSynchronizationObject @ stub NtUserGetScrollBarInfo diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 531f9f7f9cd..903f146025d 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -134,6 +134,7 @@ SYSCALL_ENTRY( NtUserGetProp ) \ SYSCALL_ENTRY( NtUserGetRawInputBuffer ) \ SYSCALL_ENTRY( NtUserGetRawInputData ) \ + SYSCALL_ENTRY( NtUserGetRegisteredRawInputDevices ) \ SYSCALL_ENTRY( NtUserGetSystemDpiForProcess ) \ SYSCALL_ENTRY( NtUserGetThreadDesktop ) \ SYSCALL_ENTRY( NtUserGetTitleBarInfo ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 231f6a04a1e..46a399752a4 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -1015,3 +1015,44 @@ NTSTATUS WINAPI wow64_NtUserRegisterRawInputDevices( UINT *args )
return NtUserRegisterRawInputDevices( devices64, count, sizeof(*devices64) ); } + +NTSTATUS WINAPI wow64_NtUserGetRegisteredRawInputDevices( UINT *args ) +{ + RAWINPUTDEVICE32 *devices32 = get_ptr( &args ); + UINT *count = get_ptr( &args ); + UINT size = get_ulong( &args ); + + if (size != sizeof(RAWINPUTDEVICE32)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (devices32) + { + RAWINPUTDEVICE *devices64; + unsigned int ret, i; + + if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + ret = NtUserGetRegisteredRawInputDevices( devices64, count, sizeof(RAWINPUTDEVICE) ); + if (ret == ~0u) return ret; + + for (i = 0; i < *count; ++i) + { + devices32[i].usUsagePage = devices64[i].usUsagePage; + devices32[i].usUsage = devices64[i].usUsage; + devices32[i].dwFlags = devices64[i].dwFlags; + devices32[i].hwndTarget = (ULONG_PTR)devices64[i].hwndTarget; + } + return ret; + } + else + { + return NtUserGetRegisteredRawInputDevices( NULL, count, sizeof(RAWINPUTDEVICE) ); + } +} diff --git a/include/ntuser.h b/include/ntuser.h index cb5696ec827..9c4aaf041a4 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -621,6 +621,7 @@ ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); DWORD WINAPI NtUserGetQueueStatus( UINT flags ); UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ); UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ); +UINT WINAPI NtUserGetRegisteredRawInputDevices( RAWINPUTDEVICE *devices, UINT *device_count, UINT size ); ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process ); HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert ); HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/rawinput.c | 433 +--------------------------------- dlls/user32/user32.spec | 4 +- dlls/user32/user_main.c | 2 - dlls/user32/user_private.h | 6 - dlls/win32u/message.c | 5 +- dlls/win32u/ntuser_private.h | 2 - dlls/win32u/rawinput.c | 434 ++++++++++++++++++++++++++++++++++- dlls/win32u/syscall.c | 2 + dlls/win32u/win32u.spec | 4 +- dlls/win32u/win32u_private.h | 1 + dlls/wow64win/syscall.h | 2 + dlls/wow64win/user.c | 55 +++++ include/ntuser.h | 2 + 13 files changed, 503 insertions(+), 449 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 588d1685cc0..98854d75690 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -39,368 +39,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
-struct device -{ - WCHAR *path; - HANDLE file; - HANDLE handle; - RID_DEVICE_INFO info; - struct hid_preparsed_data *data; -}; - -static struct device *rawinput_devices; -static unsigned int rawinput_devices_count, rawinput_devices_max; - -static CRITICAL_SECTION rawinput_devices_cs; -static CRITICAL_SECTION_DEBUG rawinput_devices_cs_debug = -{ - 0, 0, &rawinput_devices_cs, - { &rawinput_devices_cs_debug.ProcessLocksList, &rawinput_devices_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": rawinput_devices_cs") } -}; -static CRITICAL_SECTION rawinput_devices_cs = { &rawinput_devices_cs_debug, -1, 0, 0, 0, 0 }; - -static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) -{ - unsigned int new_capacity, max_capacity; - void *new_elements; - - if (count <= *capacity) - return TRUE; - - max_capacity = ~(SIZE_T)0 / size; - if (count > max_capacity) - return FALSE; - - new_capacity = max(4, *capacity); - while (new_capacity < count && new_capacity <= max_capacity / 2) - new_capacity *= 2; - if (new_capacity < count) - new_capacity = max_capacity; - - if (!(new_elements = realloc(*elements, new_capacity * size))) - return FALSE; - - *elements = new_elements; - *capacity = new_capacity; - - return TRUE; -} - -static ULONG query_reg_value( HKEY hkey, const WCHAR *name, - KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size ) -{ - unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0; - UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name }; - - if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, - info, size, &size )) - return 0; - - return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); -} - -static struct device *add_device( HKEY key, DWORD type ) -{ - static const WCHAR symbolic_linkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; - char value_buffer[4096]; - KEY_VALUE_PARTIAL_INFORMATION *value = (KEY_VALUE_PARTIAL_INFORMATION *)value_buffer; - static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101}; - static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE}; - struct hid_preparsed_data *preparsed = NULL; - HID_COLLECTION_INFORMATION hid_info; - struct device *device = NULL; - RID_DEVICE_INFO info; - IO_STATUS_BLOCK io; - WCHAR *path, *pos; - NTSTATUS status; - unsigned int i; - UINT32 handle; - HANDLE file; - - if (!query_reg_value( key, symbolic_linkW, value, sizeof(value_buffer) )) - { - ERR( "failed to get symbolic link value\n" ); - return NULL; - } - - if (!(path = malloc( value->DataLength + sizeof(WCHAR) ))) - return NULL; - memcpy( path, value->Data, value->DataLength ); - path[value->DataLength / sizeof(WCHAR)] = 0; - - /* upper case everything but the GUID */ - for (pos = path; *pos && *pos != '{'; pos++) *pos = towupper(*pos); - - file = CreateFileW( path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); - if (file == INVALID_HANDLE_VALUE) - { - ERR( "Failed to open device file %s, error %lu.\n", debugstr_w(path), GetLastError() ); - free( path ); - return NULL; - } - - status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, - IOCTL_HID_GET_WINE_RAWINPUT_HANDLE, - NULL, 0, &handle, sizeof(handle) ); - if (status) - { - ERR( "Failed to get raw input handle, status %#lx.\n", status ); - goto fail; - } - - memset( &info, 0, sizeof(info) ); - info.cbSize = sizeof(info); - info.dwType = type; - - switch (type) - { - case RIM_TYPEHID: - status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, - IOCTL_HID_GET_COLLECTION_INFORMATION, - NULL, 0, &hid_info, sizeof(hid_info) ); - if (status) - { - ERR( "Failed to get collection information, status %#lx.\n", status ); - goto fail; - } - - info.hid.dwVendorId = hid_info.VendorID; - info.hid.dwProductId = hid_info.ProductID; - info.hid.dwVersionNumber = hid_info.VersionNumber; - - if (!(preparsed = malloc( hid_info.DescriptorSize ))) - { - ERR( "Failed to allocate memory.\n" ); - goto fail; - } - - status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, - IOCTL_HID_GET_COLLECTION_DESCRIPTOR, - NULL, 0, preparsed, hid_info.DescriptorSize ); - if (status) - { - ERR( "Failed to get collection descriptor, status %#lx.\n", status ); - goto fail; - } - - info.hid.usUsagePage = preparsed->usage_page; - info.hid.usUsage = preparsed->usage; - break; - - case RIM_TYPEMOUSE: - info.mouse = mouse_info; - break; - - case RIM_TYPEKEYBOARD: - info.keyboard = keyboard_info; - break; - } - - for (i = 0; i < rawinput_devices_count && !device; ++i) - if (rawinput_devices[i].handle == UlongToHandle(handle)) - device = rawinput_devices + i; - - if (device) - { - TRACE( "Updating device %#x / %s.\n", handle, debugstr_w(path) ); - free(device->data); - CloseHandle(device->file); - free( device->path ); - } - else if (array_reserve((void **)&rawinput_devices, &rawinput_devices_max, - rawinput_devices_count + 1, sizeof(*rawinput_devices))) - { - device = &rawinput_devices[rawinput_devices_count++]; - TRACE( "Adding device %#x / %s.\n", handle, debugstr_w(path) ); - } - else - { - ERR("Failed to allocate memory.\n"); - goto fail; - } - - device->path = path; - device->file = file; - device->handle = ULongToHandle(handle); - device->info = info; - device->data = preparsed; - - return device; - -fail: - free( preparsed ); - CloseHandle( file ); - free( path ); - return NULL; -} - -static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len ) -{ - UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name }; - OBJECT_ATTRIBUTES attr; - HANDLE ret; - - attr.Length = sizeof(attr); - attr.RootDirectory = root; - attr.ObjectName = &nameW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - - if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 )) return 0; - return ret; -} - -static const WCHAR device_classesW[] = L"\Registry\Machine\System\CurrentControlSet\Control\DeviceClasses\"; -static const WCHAR guid_devinterface_hidW[] = L"{4d1e55b2-f16f-11cf-88cb-001111000030}"; -static const WCHAR guid_devinterface_keyboardW[] = L"{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"; -static const WCHAR guid_devinterface_mouseW[] = L"{378de44c-56ef-11d1-bc8c-00a0c91405dd}"; - -static void enumerate_devices( DWORD type, const WCHAR *class ) -{ - WCHAR buffer[1024]; - KEY_NODE_INFORMATION *subkey_info = (void *)buffer; - HKEY class_key, device_key, iface_key; - unsigned int i, j; - DWORD size; - - wcscpy( buffer, device_classesW ); - wcscat( buffer, class ); - if (!(class_key = reg_open_key( NULL, buffer, wcslen( buffer ) * sizeof(WCHAR) ))) - return; - - for (i = 0; !NtEnumerateKey( class_key, i, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++i) - { - if (!(device_key = reg_open_key( class_key, subkey_info->Name, subkey_info->NameLength ))) - { - ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) ); - continue; - } - - for (j = 0; !NtEnumerateKey( device_key, j, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++j) - { - if (!(iface_key = reg_open_key( device_key, subkey_info->Name, subkey_info->NameLength ))) - { - ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) ); - continue; - } - - add_device( iface_key, type ); - NtClose( iface_key ); - } - - NtClose( device_key ); - } - - NtClose( class_key ); -} - -void CDECL rawinput_update_device_list(void) -{ - DWORD idx; - - TRACE("\n"); - - EnterCriticalSection(&rawinput_devices_cs); - - /* destroy previous list */ - for (idx = 0; idx < rawinput_devices_count; ++idx) - { - free(rawinput_devices[idx].data); - CloseHandle(rawinput_devices[idx].file); - free( rawinput_devices[idx].path ); - } - rawinput_devices_count = 0; - - enumerate_devices( RIM_TYPEHID, guid_devinterface_hidW ); - enumerate_devices( RIM_TYPEMOUSE, guid_devinterface_mouseW ); - enumerate_devices( RIM_TYPEKEYBOARD, guid_devinterface_keyboardW ); - - LeaveCriticalSection(&rawinput_devices_cs); -} - - -static struct device *find_device_from_handle(HANDLE handle) -{ - UINT i; - for (i = 0; i < rawinput_devices_count; ++i) - if (rawinput_devices[i].handle == handle) - return rawinput_devices + i; - rawinput_update_device_list(); - for (i = 0; i < rawinput_devices_count; ++i) - if (rawinput_devices[i].handle == handle) - return rawinput_devices + i; - return NULL; -} - - -BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage) -{ - struct device *device; - - *usage_page = *usage = 0; - - if (!(device = find_device_from_handle(handle))) return FALSE; - if (device->info.dwType != RIM_TYPEHID) return FALSE; - - *usage_page = device->info.hid.usUsagePage; - *usage = device->info.hid.usUsage; - return TRUE; -} - - -/*********************************************************************** - * GetRawInputDeviceList (USER32.@) - */ -UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size) -{ - static UINT last_check; - UINT i, ticks = GetTickCount(); - - TRACE("devices %p, device_count %p, size %u.\n", devices, device_count, size); - - if (size != sizeof(*devices)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - if (!device_count) - { - SetLastError(ERROR_NOACCESS); - return ~0U; - } - - if (ticks - last_check > 2000) - { - last_check = ticks; - rawinput_update_device_list(); - } - - if (!devices) - { - *device_count = rawinput_devices_count; - return 0; - } - - if (*device_count < rawinput_devices_count) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - *device_count = rawinput_devices_count; - return ~0U; - } - - for (i = 0; i < rawinput_devices_count; ++i) - { - devices[i].hDevice = rawinput_devices[i].handle; - devices[i].dwType = rawinput_devices[i].info.dwType; - } - - return rawinput_devices_count; -} - /*********************************************************************** * GetRawInputDeviceInfoA (USER32.@) */ @@ -424,7 +62,7 @@ UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT else nameW = NULL;
- ret = GetRawInputDeviceInfoW(device, command, nameW, &nameW_sz); + ret = NtUserGetRawInputDeviceInfo( device, command, nameW, &nameW_sz );
if (ret && ret != ~0U) WideCharToMultiByte(CP_ACP, 0, nameW, -1, data, *data_size, NULL, NULL); @@ -436,74 +74,7 @@ UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT return ret; }
- return GetRawInputDeviceInfoW(device, command, data, data_size); -} - -/*********************************************************************** - * GetRawInputDeviceInfoW (USER32.@) - */ -UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT *data_size) -{ - struct hid_preparsed_data *preparsed; - RID_DEVICE_INFO info; - struct device *device; - DWORD len, data_len; - - TRACE("handle %p, command %#x, data %p, data_size %p.\n", - handle, command, data, data_size); - - if (!data_size) - { - SetLastError(ERROR_NOACCESS); - return ~0U; - } - if (!(device = find_device_from_handle(handle))) - { - SetLastError(ERROR_INVALID_HANDLE); - return ~0U; - } - - data_len = *data_size; - switch (command) - { - case RIDI_DEVICENAME: - if ((len = wcslen( device->path ) + 1) <= data_len && data) - memcpy( data, device->path, len * sizeof(WCHAR) ); - *data_size = len; - break; - - case RIDI_DEVICEINFO: - if ((len = sizeof(info)) <= data_len && data) - memcpy(data, &device->info, len); - *data_size = len; - break; - - case RIDI_PREPARSEDDATA: - if (!(preparsed = device->data)) len = 0; - else len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + - preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); - - if (preparsed && len <= data_len && data) - memcpy(data, preparsed, len); - *data_size = len; - break; - - default: - FIXME("command %#x not supported\n", command); - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - if (!data) - return 0; - - if (data_len < len) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return ~0U; - } - - return *data_size; + return NtUserGetRawInputDeviceInfo( device, command, data, data_size ); }
/*********************************************************************** diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 3e20277251a..e1cc18f7287 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -369,8 +369,8 @@ @ stdcall GetRawInputBuffer(ptr ptr long) NtUserGetRawInputBuffer @ stdcall GetRawInputData(ptr long ptr ptr long) NtUserGetRawInputData @ stdcall GetRawInputDeviceInfoA(ptr long ptr ptr) -@ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) -@ stdcall GetRawInputDeviceList(ptr ptr long) +@ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) NtUserGetRawInputDeviceInfo +@ stdcall GetRawInputDeviceList(ptr ptr long) NtUserGetRawInputDeviceList # @ stub GetReasonTitleFromReasonCode @ stdcall GetRegisteredRawInputDevices(ptr ptr long) NtUserGetRegisteredRawInputDevices @ stdcall GetScrollBarInfo(long long ptr) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 038f1f0796f..2391131e4a5 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -161,8 +161,6 @@ static const struct user_callbacks user_funcs = free_win_ptr, notify_ime, post_dde_message, - rawinput_update_device_list, - rawinput_device_get_usages, SCROLL_SetStandardScrollPainted, unpack_dde_message, register_imm, diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 71248e03bb8..a646f9a234d 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -60,14 +60,8 @@ extern HMODULE user32_module DECLSPEC_HIDDEN; struct dce; struct tagWND;
-struct hardware_msg_data; -extern BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage); -extern void CDECL rawinput_update_device_list(void); - extern BOOL post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid, DWORD type ) DECLSPEC_HIDDEN; -extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, - const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN; extern BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, void **buffer, size_t size ) DECLSPEC_HIDDEN; extern void free_cached_data( UINT format, HANDLE handle ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 94a1bc71520..0603a248f60 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2381,9 +2381,8 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r hid_usage_page = ((USAGE *)rawinput->data.hid.bRawData)[0]; hid_usage = ((USAGE *)rawinput->data.hid.bRawData)[1]; } - if (input->hi.uMsg == WM_INPUT && user_callbacks && - !user_callbacks->rawinput_device_get_usages( rawinput->header.hDevice, - &hid_usage_page, &hid_usage )) + if (input->hi.uMsg == WM_INPUT && + !rawinput_device_get_usages( rawinput->header.hDevice, &hid_usage_page, &hid_usage )) { WARN( "unable to get HID usages for device %p\n", rawinput->header.hDevice ); return STATUS_INVALID_HANDLE; diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index fd70c022c6f..82d70ec93bb 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -40,8 +40,6 @@ struct user_callbacks void (CDECL *notify_ime)( HWND hwnd, UINT param ); BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid, DWORD type ); - void (CDECL *rawinput_update_device_list)(void); - BOOL (CDECL *rawinput_device_get_usages)(HANDLE handle, USHORT *usage_page, USHORT *usage); void (WINAPI *set_standard_scroll_painted)( HWND hwnd, INT bar, BOOL visible ); BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, void **buffer, size_t size ); diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 1caf11f2e76..81403771c4a 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -24,8 +24,14 @@ #endif
#include <stdbool.h> +#include <pthread.h> + #include "win32u_private.h" #include "ntuser_private.h" +#define WIN32_NO_STATUS +#include "winioctl.h" +#include "ddk/hidclass.h" +#include "wine/hid.h" #include "wine/server.h" #include "wine/debug.h"
@@ -188,6 +194,432 @@ static bool rawinput_from_hardware_message( RAWINPUT *rawinput, const struct har return true; }
+struct device +{ + WCHAR *path; + HANDLE file; + HANDLE handle; + RID_DEVICE_INFO info; + struct hid_preparsed_data *data; +}; + +static struct device *rawinput_devices; +static unsigned int rawinput_devices_count, rawinput_devices_max; + +static pthread_mutex_t rawinput_devices_mutex = PTHREAD_MUTEX_INITIALIZER; + +static bool array_reserve( void **elements, unsigned int *capacity, unsigned int count, unsigned int size ) +{ + unsigned int new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return true; + + max_capacity = ~(unsigned int)0 / size; + if (count > max_capacity) + return false; + + new_capacity = max( 4, *capacity ); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = realloc( *elements, new_capacity * size ))) + return false; + + *elements = new_elements; + *capacity = new_capacity; + + return true; +} + +static struct device *add_device( HKEY key, DWORD type ) +{ + static const WCHAR symbolic_linkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; + char value_buffer[4096]; + KEY_VALUE_PARTIAL_INFORMATION *value = (KEY_VALUE_PARTIAL_INFORMATION *)value_buffer; + static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101}; + static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE}; + struct hid_preparsed_data *preparsed = NULL; + HID_COLLECTION_INFORMATION hid_info; + struct device *device = NULL; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + RID_DEVICE_INFO info; + IO_STATUS_BLOCK io; + WCHAR *path, *pos; + NTSTATUS status; + unsigned int i; + UINT32 handle; + HANDLE file; + + if (!query_reg_value( key, symbolic_linkW, value, sizeof(value_buffer) )) + { + ERR( "failed to get symbolic link value\n" ); + return NULL; + } + + if (!(path = malloc( value->DataLength + sizeof(WCHAR) ))) + return NULL; + memcpy( path, value->Data, value->DataLength ); + path[value->DataLength / sizeof(WCHAR)] = 0; + + /* upper case everything but the GUID */ + for (pos = path; *pos && *pos != '{'; pos++) *pos = towupper( *pos ); + + /* path is in DOS format and begins with \?\ prefix */ + path[1] = '?'; + + RtlInitUnicodeString( &string, path ); + InitializeObjectAttributes( &attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL ); + if ((status = NtOpenFile( &file, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ))) + { + ERR( "Failed to open device file %s, status %#x.\n", debugstr_w(path), status ); + free( path ); + return NULL; + } + + path[1] = '\'; + + status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, IOCTL_HID_GET_WINE_RAWINPUT_HANDLE, + NULL, 0, &handle, sizeof(handle) ); + if (status) + { + ERR( "Failed to get raw input handle, status %#x.\n", status ); + goto fail; + } + + memset( &info, 0, sizeof(info) ); + info.cbSize = sizeof(info); + info.dwType = type; + + switch (type) + { + case RIM_TYPEHID: + status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, + IOCTL_HID_GET_COLLECTION_INFORMATION, + NULL, 0, &hid_info, sizeof(hid_info) ); + if (status) + { + ERR( "Failed to get collection information, status %#x.\n", status ); + goto fail; + } + + info.hid.dwVendorId = hid_info.VendorID; + info.hid.dwProductId = hid_info.ProductID; + info.hid.dwVersionNumber = hid_info.VersionNumber; + + if (!(preparsed = malloc( hid_info.DescriptorSize ))) + { + ERR( "Failed to allocate memory.\n" ); + goto fail; + } + + status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, + IOCTL_HID_GET_COLLECTION_DESCRIPTOR, + NULL, 0, preparsed, hid_info.DescriptorSize ); + if (status) + { + ERR( "Failed to get collection descriptor, status %#x.\n", status ); + goto fail; + } + + info.hid.usUsagePage = preparsed->usage_page; + info.hid.usUsage = preparsed->usage; + break; + + case RIM_TYPEMOUSE: + info.mouse = mouse_info; + break; + + case RIM_TYPEKEYBOARD: + info.keyboard = keyboard_info; + break; + } + + for (i = 0; i < rawinput_devices_count && !device; ++i) + { + if (rawinput_devices[i].handle == UlongToHandle(handle)) + device = rawinput_devices + i; + } + + if (device) + { + TRACE( "Updating device %#x / %s.\n", handle, debugstr_w(path) ); + free( device->data ); + NtClose( device->file ); + free( device->path ); + } + else if (array_reserve( (void **)&rawinput_devices, &rawinput_devices_max, + rawinput_devices_count + 1, sizeof(*rawinput_devices) )) + { + device = &rawinput_devices[rawinput_devices_count++]; + TRACE( "Adding device %#x / %s.\n", handle, debugstr_w(path) ); + } + else + { + ERR( "Failed to allocate memory.\n" ); + goto fail; + } + + device->path = path; + device->file = file; + device->handle = ULongToHandle(handle); + device->info = info; + device->data = preparsed; + + return device; + +fail: + free( preparsed ); + NtClose( file ); + free( path ); + return NULL; +} + +static const WCHAR device_classesW[] = +{ + '\','R','e','g','i','s','t','r','y', + '\','M','a','c','h','i','n','e', + '\','S','y','s','t','e','m', + '\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', + '\','C','o','n','t','r','o','l', + '\','D','e','v','i','c','e','C','l','a','s','s','e','s','\',0 +}; +static const WCHAR guid_devinterface_hidW[] = +{ + '{','4','d','1','e','5','5','b','2','-','f','1','6','f','-','1','1','c','f', + '-','8','8','c','b','-','0','0','1','1','1','1','0','0','0','0','3','0','}',0 +}; +static const WCHAR guid_devinterface_keyboardW[] = +{ + '{','8','8','4','b','9','6','c','3','-','5','6','e','f','-','1','1','d','1', + '-','b','c','8','c','-','0','0','a','0','c','9','1','4','0','5','d','d','}',0 +}; +static const WCHAR guid_devinterface_mouseW[] = +{ + '{','3','7','8','d','e','4','4','c','-','5','6','e','f','-','1','1','d','1', + '-','b','c','8','c','-','0','0','a','0','c','9','1','4','0','5','d','d','}',0 +}; + +static void enumerate_devices( DWORD type, const WCHAR *class ) +{ + WCHAR buffer[1024]; + KEY_NODE_INFORMATION *subkey_info = (void *)buffer; + HKEY class_key, device_key, iface_key; + unsigned int i, j; + DWORD size; + + wcscpy( buffer, device_classesW ); + wcscat( buffer, class ); + if (!(class_key = reg_open_key( NULL, buffer, wcslen( buffer ) * sizeof(WCHAR) ))) + return; + + for (i = 0; !NtEnumerateKey( class_key, i, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++i) + { + if (!(device_key = reg_open_key( class_key, subkey_info->Name, subkey_info->NameLength ))) + { + ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) ); + continue; + } + + for (j = 0; !NtEnumerateKey( device_key, j, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++j) + { + if (!(iface_key = reg_open_key( device_key, subkey_info->Name, subkey_info->NameLength ))) + { + ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) ); + continue; + } + + add_device( iface_key, type ); + NtClose( iface_key ); + } + + NtClose( device_key ); + } + + NtClose( class_key ); +} + +static void rawinput_update_device_list(void) +{ + unsigned int i; + + TRACE( "\n" ); + + pthread_mutex_lock( &rawinput_devices_mutex ); + + /* destroy previous list */ + for (i = 0; i < rawinput_devices_count; ++i) + { + free( rawinput_devices[i].data ); + NtClose( rawinput_devices[i].file ); + free( rawinput_devices[i].path ); + } + rawinput_devices_count = 0; + + enumerate_devices( RIM_TYPEHID, guid_devinterface_hidW ); + enumerate_devices( RIM_TYPEMOUSE, guid_devinterface_mouseW ); + enumerate_devices( RIM_TYPEKEYBOARD, guid_devinterface_keyboardW ); + + pthread_mutex_unlock( &rawinput_devices_mutex ); +} + +static struct device *find_device_from_handle( HANDLE handle ) +{ + unsigned int i; + + for (i = 0; i < rawinput_devices_count; ++i) + { + if (rawinput_devices[i].handle == handle) + return rawinput_devices + i; + } + + rawinput_update_device_list(); + + for (i = 0; i < rawinput_devices_count; ++i) + { + if (rawinput_devices[i].handle == handle) + return rawinput_devices + i; + } + return NULL; +} + +BOOL rawinput_device_get_usages( HANDLE handle, USAGE *usage_page, USAGE *usage ) +{ + struct device *device; + + *usage_page = *usage = 0; + + if (!(device = find_device_from_handle( handle ))) return FALSE; + if (device->info.dwType != RIM_TYPEHID) return FALSE; + + *usage_page = device->info.hid.usUsagePage; + *usage = device->info.hid.usUsage; + return TRUE; +} + +/********************************************************************** + * NtUserGetRawInputDeviceList (win32u.@) + */ +UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size ) +{ + static unsigned int last_check; + unsigned int i, ticks = NtGetTickCount(); + + TRACE("devices %p, device_count %p, size %u.\n", devices, device_count, size); + + if (size != sizeof(*devices)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + if (!device_count) + { + SetLastError( ERROR_NOACCESS ); + return ~0u; + } + + if (ticks - last_check > 2000) + { + last_check = ticks; + rawinput_update_device_list(); + } + + if (!devices) + { + *device_count = rawinput_devices_count; + return 0; + } + + if (*device_count < rawinput_devices_count) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + *device_count = rawinput_devices_count; + return ~0u; + } + + for (i = 0; i < rawinput_devices_count; ++i) + { + devices[i].hDevice = rawinput_devices[i].handle; + devices[i].dwType = rawinput_devices[i].info.dwType; + } + + return rawinput_devices_count; +} + +/********************************************************************** + * NtUserGetRawInputDeviceInfo (win32u.@) + */ +UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data, UINT *data_size ) +{ + const struct hid_preparsed_data *preparsed; + struct device *device; + RID_DEVICE_INFO info; + DWORD len, data_len; + + TRACE( "handle %p, command %#x, data %p, data_size %p.\n", handle, command, data, data_size ); + + if (!data_size) + { + SetLastError( ERROR_NOACCESS ); + return ~0u; + } + if (!(device = find_device_from_handle( handle ))) + { + SetLastError( ERROR_INVALID_HANDLE ); + return ~0u; + } + + data_len = *data_size; + switch (command) + { + case RIDI_DEVICENAME: + if ((len = wcslen( device->path ) + 1) <= data_len && data) + memcpy( data, device->path, len * sizeof(WCHAR) ); + *data_size = len; + break; + + case RIDI_DEVICEINFO: + if ((len = sizeof(info)) <= data_len && data) + memcpy( data, &device->info, len ); + *data_size = len; + break; + + case RIDI_PREPARSEDDATA: + if (!(preparsed = device->data)) + len = 0; + else + len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); + + if (preparsed && len <= data_len && data) + memcpy( data, preparsed, len ); + *data_size = len; + break; + + default: + FIXME( "command %#x not supported\n", command ); + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + if (!data) + return 0; + + if (data_len < len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return ~0u; + } + + return *data_size; +} + /********************************************************************** * NtUserGetRawInputBuffer (win32u.@) */ @@ -353,7 +785,7 @@ BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_d
if (msg->message == WM_INPUT_DEVICE_CHANGE) { - if (user_callbacks) user_callbacks->rawinput_update_device_list(); + rawinput_update_device_list(); } else { diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 49746725816..e68519f15e5 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -147,6 +147,8 @@ static void * const syscalls[] = NtUserGetProp, NtUserGetRawInputBuffer, NtUserGetRawInputData, + NtUserGetRawInputDeviceInfo, + NtUserGetRawInputDeviceList, NtUserGetRegisteredRawInputDevices, NtUserGetSystemDpiForProcess, NtUserGetThreadDesktop, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index dab6e2a5ed8..68201f763ab 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -985,8 +985,8 @@ @ stub NtUserGetQueueStatusReadonly @ stdcall -syscall NtUserGetRawInputBuffer(ptr ptr long) @ stdcall -syscall NtUserGetRawInputData(ptr long ptr ptr long) -@ stub NtUserGetRawInputDeviceInfo -@ stub NtUserGetRawInputDeviceList +@ stdcall -syscall NtUserGetRawInputDeviceInfo(ptr long ptr ptr) +@ stdcall -syscall NtUserGetRawInputDeviceList(ptr ptr long) @ stub NtUserGetRawPointerDeviceData @ stdcall -syscall NtUserGetRegisteredRawInputDevices(ptr ptr long) @ stub NtUserGetRequiredCursorSizes diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a3f3855de7a..d3f359fd4ee 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -437,6 +437,7 @@ extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM
/* rawinput.c */ extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN; +extern BOOL rawinput_device_get_usages( HANDLE handle, USHORT *usage_page, USHORT *usage ) DECLSPEC_HIDDEN;
/* sysparams.c */ extern BOOL enable_thunk_lock DECLSPEC_HIDDEN; diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 903f146025d..30b6795f8e8 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -134,6 +134,8 @@ SYSCALL_ENTRY( NtUserGetProp ) \ SYSCALL_ENTRY( NtUserGetRawInputBuffer ) \ SYSCALL_ENTRY( NtUserGetRawInputData ) \ + SYSCALL_ENTRY( NtUserGetRawInputDeviceInfo ) \ + SYSCALL_ENTRY( NtUserGetRawInputDeviceList ) \ SYSCALL_ENTRY( NtUserGetRegisteredRawInputDevices ) \ SYSCALL_ENTRY( NtUserGetSystemDpiForProcess ) \ SYSCALL_ENTRY( NtUserGetThreadDesktop ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 46a399752a4..82f3881a8c6 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -72,6 +72,12 @@ typedef struct UINT32 hwndTarget; } RAWINPUTDEVICE32;
+typedef struct +{ + UINT32 hDevice; + DWORD dwType; +} RAWINPUTDEVICELIST32; + static MSG *msg_32to64( MSG *msg, MSG32 *msg32 ) { if (!msg32) return NULL; @@ -1056,3 +1062,52 @@ NTSTATUS WINAPI wow64_NtUserGetRegisteredRawInputDevices( UINT *args ) return NtUserGetRegisteredRawInputDevices( NULL, count, sizeof(RAWINPUTDEVICE) ); } } + +NTSTATUS WINAPI wow64_NtUserGetRawInputDeviceInfo( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + UINT command = get_ulong( &args ); + void *data = get_ptr( &args ); + UINT *data_size = get_ptr( &args ); + + return NtUserGetRawInputDeviceInfo( handle, command, data, data_size ); +} + +NTSTATUS WINAPI wow64_NtUserGetRawInputDeviceList( UINT *args ) +{ + RAWINPUTDEVICELIST32 *devices32 = get_ptr( &args ); + UINT *count = get_ptr( &args ); + UINT size = get_ulong( &args ); + + if (size != sizeof(RAWINPUTDEVICELIST32)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + if (devices32) + { + RAWINPUTDEVICELIST *devices64; + unsigned int ret, i; + + if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + ret = NtUserGetRawInputDeviceList( devices64, count, sizeof(RAWINPUTDEVICELIST) ); + if (ret == ~0u) return ret; + + for (i = 0; i < *count; ++i) + { + devices32[i].hDevice = (UINT_PTR)devices64[i].hDevice; + devices32[i].dwType = devices64[i].dwType; + } + return ret; + } + else + { + return NtUserGetRawInputDeviceList( NULL, count, sizeof(RAWINPUTDEVICELIST) ); + } +} diff --git a/include/ntuser.h b/include/ntuser.h index 9c4aaf041a4..3862eb55054 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -621,6 +621,8 @@ ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); DWORD WINAPI NtUserGetQueueStatus( UINT flags ); UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ); UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ); +UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data, UINT *data_size ); +UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size ); UINT WINAPI NtUserGetRegisteredRawInputDevices( RAWINPUTDEVICE *devices, UINT *device_count, UINT size ); ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process ); HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert );
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/Makefile.in | 1 - dlls/user32/input.c | 49 +++++++++++++++++++++++ dlls/user32/rawinput.c | 88 ----------------------------------------- 3 files changed, 49 insertions(+), 89 deletions(-) delete mode 100644 dlls/user32/rawinput.c
diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in index 79821929390..3a01810991d 100644 --- a/dlls/user32/Makefile.in +++ b/dlls/user32/Makefile.in @@ -34,7 +34,6 @@ C_SRCS = \ nonclient.c \ painting.c \ property.c \ - rawinput.c \ resource.c \ scroll.c \ static.c \ diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 52d4414b673..106f890da7a 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -6,6 +6,8 @@ * Copyright 1997 David Faure * Copyright 1998 Morten Welinder * Copyright 1998 Ulrich Weigand + * Copyright 2012 Henri Verbeet + * Copyright 2018 Zebediah Figura for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -623,3 +625,50 @@ BOOL WINAPI UnregisterDeviceNotification( HDEVNOTIFY handle )
return I_ScUnregisterDeviceNotification( handle ); } + +/*********************************************************************** + * GetRawInputDeviceInfoA (USER32.@) + */ +UINT WINAPI GetRawInputDeviceInfoA( HANDLE device, UINT command, void *data, UINT *size ) +{ + TRACE( "device %p, command %#x, data %p, size %p.\n", device, command, data, size ); + + /* RIDI_DEVICENAME size is in chars, not bytes */ + if (command == RIDI_DEVICENAME) + { + WCHAR *nameW; + UINT ret, sizeW; + + if (!size) return ~0U; + + sizeW = *size; + + if (data && sizeW > 0) + nameW = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * sizeW ); + else + nameW = NULL; + + ret = NtUserGetRawInputDeviceInfo( device, command, nameW, &sizeW ); + + if (ret && ret != ~0U) + WideCharToMultiByte( CP_ACP, 0, nameW, -1, data, *size, NULL, NULL ); + + *size = sizeW; + + HeapFree( GetProcessHeap(), 0, nameW ); + + return ret; + } + + return NtUserGetRawInputDeviceInfo( device, command, data, size ); +} + +/*********************************************************************** + * DefRawInputProc (USER32.@) + */ +LRESULT WINAPI DefRawInputProc( RAWINPUT **data, INT data_count, UINT header_size ) +{ + FIXME( "data %p, data_count %d, header_size %u stub!\n", data, data_count, header_size ); + + return 0; +} diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c deleted file mode 100644 index 98854d75690..00000000000 --- a/dlls/user32/rawinput.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Raw Input - * - * Copyright 2012 Henri Verbeet - * Copyright 2018 Zebediah Figura for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <stdarg.h> - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winioctl.h" -#include "winnls.h" -#include "winreg.h" -#include "winuser.h" -#include "ddk/hidclass.h" -#include "wine/debug.h" -#include "wine/server.h" -#include "wine/hid.h" - -#include "user_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rawinput); - -/*********************************************************************** - * GetRawInputDeviceInfoA (USER32.@) - */ -UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT *data_size) -{ - TRACE("device %p, command %#x, data %p, data_size %p.\n", - device, command, data, data_size); - - /* RIDI_DEVICENAME data_size is in chars, not bytes */ - if (command == RIDI_DEVICENAME) - { - WCHAR *nameW; - UINT ret, nameW_sz; - - if (!data_size) return ~0U; - - nameW_sz = *data_size; - - if (data && nameW_sz > 0) - nameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * nameW_sz); - else - nameW = NULL; - - ret = NtUserGetRawInputDeviceInfo( device, command, nameW, &nameW_sz ); - - if (ret && ret != ~0U) - WideCharToMultiByte(CP_ACP, 0, nameW, -1, data, *data_size, NULL, NULL); - - *data_size = nameW_sz; - - HeapFree(GetProcessHeap(), 0, nameW); - - return ret; - } - - return NtUserGetRawInputDeviceInfo( device, command, data, data_size ); -} - -/*********************************************************************** - * DefRawInputProc (USER32.@) - */ -LRESULT WINAPI DefRawInputProc(RAWINPUT **data, INT data_count, UINT header_size) -{ - FIXME("data %p, data_count %d, header_size %u stub!\n", data, data_count, header_size); - - return 0; -}
Rémi Bernon (@rbernon) commented about dlls/wow64win/user.c:
return NtUserRegisterRawInputDevices( devices64, count, sizeof(*devices64) );
}
+NTSTATUS WINAPI wow64_NtUserGetRegisteredRawInputDevices( UINT *args ) +{
- RAWINPUTDEVICE32 *devices32 = get_ptr( &args );
- UINT *count = get_ptr( &args );
- UINT size = get_ulong( &args );
- if (size != sizeof(RAWINPUTDEVICE32))
- {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
This should be ~0u.
Rémi Bernon (@rbernon) commented about dlls/wow64win/user.c:
- if (size != sizeof(RAWINPUTDEVICE32))
- {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
- }
- if (devices32)
- {
RAWINPUTDEVICE *devices64;
unsigned int ret, i;
if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
This should be ~0u.
Rémi Bernon (@rbernon) commented about dlls/wow64win/user.c:
- if (size != sizeof(RAWINPUTDEVICELIST32))
- {
SetLastError( ERROR_INVALID_PARAMETER );
return ~0u;
- }
- if (devices32)
- {
RAWINPUTDEVICELIST *devices64;
unsigned int ret, i;
if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
This should be ~0u.
On 6/28/22 02:10, Rémi Bernon (@rbernon) wrote:
Rémi Bernon (@rbernon) commented about dlls/wow64win/user.c:
- if (size != sizeof(RAWINPUTDEVICELIST32))
- {
SetLastError( ERROR_INVALID_PARAMETER );
return ~0u;
- }
- if (devices32)
- {
RAWINPUTDEVICELIST *devices64;
unsigned int ret, i;
if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
This should be ~0u.
The bridge doesn't give me any context on which commit is being responded to (is it not possible to reconstruct that information?) but RegisterRawInputDevices() returns BOOL, so one of those three is correct.
The other two are errors; thanks for finding them. I've resent a new version with them fixed.