From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/rawinput.c | 131 +++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 56 deletions(-)
diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 013a55bcc2a..e495f3743ba 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -31,6 +31,8 @@ #define WIN32_NO_STATUS #include "winioctl.h" #include "ddk/hidclass.h" +#include "dbt.h" + #include "wine/hid.h" #include "wine/server.h" #include "wine/debug.h" @@ -209,11 +211,8 @@ static unsigned int registered_device_count; static struct list devices = LIST_INIT( devices ); static pthread_mutex_t rawinput_mutex = PTHREAD_MUTEX_INITIALIZER;
-static struct device *add_device( HKEY key, DWORD type ) +static struct device *device_create( WCHAR *path, UINT type ) { - static const WCHAR symbolic_linkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; - char value_buffer[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[MAX_PATH * sizeof(WCHAR)])]; - 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; @@ -228,18 +227,8 @@ static struct device *add_device( HKEY key, DWORD type ) void *buffer; SIZE_T size; HANDLE file; - WCHAR *path;
- if (!query_reg_value( key, symbolic_linkW, value, sizeof(value_buffer) - sizeof(WCHAR) )) - { - ERR( "failed to get symbolic link value\n" ); - return NULL; - } - memset( value->Data + value->DataLength, 0, sizeof(WCHAR) ); - - /* upper case everything but the GUID */ - for (path = (WCHAR *)value->Data; *path && *path != '{'; path++) *path = towupper( *path ); - path = (WCHAR *)value->Data; + TRACE( "path %s type %#x\n", debugstr_w(path), type );
/* path is in DOS format and begins with \?\ prefix */ path[1] = '?'; @@ -345,8 +334,6 @@ static struct device *add_device( HKEY key, DWORD type ) device->handle = ULongToHandle(handle); device->info = info; device->data = preparsed; - list_add_tail( &devices, &device->entry ); - return device;
fail: @@ -355,6 +342,48 @@ fail: return NULL; }
+static void device_remove( struct device *device ) +{ + list_remove( &device->entry ); + NtClose( device->file ); + free( device->data ); + free( device ); +} + +static struct device *find_device_from_path( WCHAR *path ) +{ + struct device *device; + + LIST_FOR_EACH_ENTRY( device, &devices, struct device, entry ) + if (!wcscmp( device->path, path )) return device; + + WARN( "Failed to find device with path %s.\n", debugstr_w(path) ); + return NULL; +} + +static void 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[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[MAX_PATH * sizeof(WCHAR)])]; + KEY_VALUE_PARTIAL_INFORMATION *value = (KEY_VALUE_PARTIAL_INFORMATION *)value_buffer; + struct device *device; + WCHAR *path; + + if (!query_reg_value( key, symbolic_linkW, value, sizeof(value_buffer) - sizeof(WCHAR) )) + { + ERR( "failed to get symbolic link value\n" ); + return; + } + memset( value->Data + value->DataLength, 0, sizeof(WCHAR) ); + + /* upper case everything but the GUID */ + for (path = (WCHAR *)value->Data; *path && *path != '{'; path++) *path = towupper( *path ); + path = (WCHAR *)value->Data; + + if ((device = device_create( path, type ))) + list_add_tail( &devices, &device->entry ); +} + static const WCHAR device_classesW[] = { '\','R','e','g','i','s','t','r','y', @@ -419,25 +448,6 @@ static void enumerate_devices( DWORD type, const WCHAR *class ) NtClose( class_key ); }
-static void rawinput_update_device_list(void) -{ - struct device *device, *next; - - TRACE( "\n" ); - - LIST_FOR_EACH_ENTRY_SAFE( device, next, &devices, struct device, entry ) - { - list_remove( &device->entry ); - NtClose( device->file ); - free( device->data ); - free( device ); - } - - enumerate_devices( RIM_TYPEMOUSE, guid_devinterface_mouseW ); - enumerate_devices( RIM_TYPEKEYBOARD, guid_devinterface_keyboardW ); - enumerate_devices( RIM_TYPEHID, guid_devinterface_hidW ); -} - static struct device *find_device_from_handle( HANDLE handle ) { struct device *device; @@ -445,11 +455,7 @@ static struct device *find_device_from_handle( HANDLE handle ) LIST_FOR_EACH_ENTRY( device, &devices, struct device, entry ) if (device->handle == handle) return device;
- rawinput_update_device_list(); - - LIST_FOR_EACH_ENTRY( device, &devices, struct device, entry ) - if (device->handle == handle) return device; - + WARN( "Failed to find device with handle %p.\n", handle ); return NULL; }
@@ -476,11 +482,37 @@ static LRESULT CALLBACK rawinput_window_proc( HWND hwnd, UINT msg, WPARAM wparam { TRACE( "hwnd %p, msg %#x, wparam %#zx, lparam %#zx\n", hwnd, msg, (size_t)wparam, (size_t)lparam );
+ if (msg == WM_DEVICECHANGE) + { + DEV_BROADCAST_DEVICEINTERFACE_W *iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)lparam; + struct device *device; + + switch (wparam) + { + case DBT_DEVICEARRIVAL: + pthread_mutex_lock( &rawinput_mutex ); + if ((device = device_create( iface->dbcc_name, RIM_TYPEHID ))) + list_add_tail( &devices, &device->entry ); + pthread_mutex_unlock( &rawinput_mutex ); + break; + case DBT_DEVICEREMOVECOMPLETE: + pthread_mutex_lock( &rawinput_mutex ); + if ((device = find_device_from_path( iface->dbcc_name ))) + device_remove( device ); + pthread_mutex_unlock( &rawinput_mutex ); + break; + } + } + return NtUserMessageCall( hwnd, msg, wparam, lparam, 0, NtUserDefWindowProc, FALSE ); }
DWORD rawinput_thread( HWND hwnd, DWORD_PTR param ) { + enumerate_devices( RIM_TYPEMOUSE, guid_devinterface_mouseW ); + enumerate_devices( RIM_TYPEKEYBOARD, guid_devinterface_keyboardW ); + enumerate_devices( RIM_TYPEHID, guid_devinterface_hidW ); + NtUserSetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR)rawinput_window_proc, FALSE );
for (;;) @@ -504,8 +536,7 @@ DWORD rawinput_thread( HWND hwnd, DWORD_PTR param ) */ UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *device_list, UINT *device_count, UINT size ) { - unsigned int count = 0, ticks = NtGetTickCount(); - static unsigned int last_check; + unsigned int count = 0; struct device *device;
TRACE( "device_list %p, device_count %p, size %u.\n", device_list, device_count, size ); @@ -524,12 +555,6 @@ UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *device_list, UINT *
pthread_mutex_lock( &rawinput_mutex );
- if (ticks - last_check > 2000) - { - last_check = ticks; - rawinput_update_device_list(); - } - LIST_FOR_EACH_ENTRY( device, &devices, struct device, entry ) { if (*device_count < ++count || !device_list) continue; @@ -804,13 +829,7 @@ BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_d if (!(thread_data = get_rawinput_thread_data())) return FALSE;
- if (msg->message == WM_INPUT_DEVICE_CHANGE) - { - pthread_mutex_lock( &rawinput_mutex ); - rawinput_update_device_list(); - pthread_mutex_unlock( &rawinput_mutex ); - } - else + if (msg->message == WM_INPUT) { thread_data->buffer->header.dwSize = RAWINPUT_BUFFER_SIZE; if (!rawinput_from_hardware_message( thread_data->buffer, msg_data )) return FALSE;