-- v4: 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..87c522071aa 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 ~0u; + } + + if (devices32) + { + RAWINPUTDEVICE *devices64; + unsigned int ret, i; + + if (!(devices64 = Wow64AllocateTemp( (*count) * sizeof(*devices64) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return ~0u; + } + + 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 87c522071aa..ca84c4a7bab 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 ~0u; + } + + 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; -}
This merge request was approved by Rémi Bernon.