Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/hotplug.c | 24 ----------------------- dlls/sechost/service.c | 5 +++++ dlls/user32/input.c | 39 ++++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 25 deletions(-)
diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index d271d9bc1db..5cb8358e3a9 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -252,87 +252,63 @@ static void test_RegisterDeviceNotification(void)
SetLastError( 0xdeadbeef ); devnotify = RegisterDeviceNotificationA( NULL, NULL, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); devnotify = RegisterDeviceNotificationA( (HWND)0xdeadbeef, NULL, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); devnotify = RegisterDeviceNotificationA( hwnd, NULL, 2 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); memset( header, 0, sizeof(DEV_BROADCAST_OEM) ); header->dbch_size = sizeof(DEV_BROADCAST_OEM); header->dbch_devicetype = DBT_DEVTYP_OEM; devnotify = RegisterDeviceNotificationA( hwnd, header, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); memset( header, 0, sizeof(DEV_BROADCAST_DEVNODE) ); header->dbch_size = sizeof(DEV_BROADCAST_DEVNODE); header->dbch_devicetype = DBT_DEVTYP_DEVNODE; devnotify = RegisterDeviceNotificationA( hwnd, header, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); memset( header, 0, sizeof(DEV_BROADCAST_VOLUME) ); header->dbch_size = sizeof(DEV_BROADCAST_VOLUME); header->dbch_devicetype = DBT_DEVTYP_VOLUME; devnotify = RegisterDeviceNotificationA( hwnd, header, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); memset( header, 0, sizeof(DEV_BROADCAST_PORT_A) ); header->dbch_size = sizeof(DEV_BROADCAST_PORT_A); header->dbch_devicetype = DBT_DEVTYP_PORT; devnotify = RegisterDeviceNotificationA( hwnd, header, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
SetLastError( 0xdeadbeef ); memset( header, 0, sizeof(DEV_BROADCAST_NET) ); header->dbch_size = sizeof(DEV_BROADCAST_NET); header->dbch_devicetype = DBT_DEVTYP_NET; devnotify = RegisterDeviceNotificationA( hwnd, header, 0 ); - todo_wine ok( !devnotify, "RegisterDeviceNotificationA succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_SERVICE_SPECIFIC_ERROR, "got error %u\n", GetLastError() ); - if (devnotify) UnregisterDeviceNotification( devnotify );
devnotify = RegisterDeviceNotificationA( hwnd, &iface_filter_a, DEVICE_NOTIFY_WINDOW_HANDLE ); ok( !!devnotify, "RegisterDeviceNotificationA failed, error %u\n", GetLastError() ); diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 4dfb40b4bac..00485869e9c 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1974,6 +1974,11 @@ struct device_notification_details { DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); HANDLE handle; + union + { + DEV_BROADCAST_HDR header; + DEV_BROADCAST_DEVICEINTERFACE_W iface; + } filter; };
static HANDLE device_notify_thread; diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 08a00c0e647..67ca7e178f2 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1170,6 +1170,11 @@ struct device_notification_details { DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); HANDLE handle; + union + { + DEV_BROADCAST_HDR header; + DEV_BROADCAST_DEVICEINTERFACE_W iface; + } filter; };
extern HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_details *details, @@ -1196,11 +1201,43 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hRecipient, LPVOID pNotific HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWORD flags ) { struct device_notification_details details; + DEV_BROADCAST_HDR *header = filter;
TRACE("handle %p, filter %p, flags %#x\n", handle, filter, flags);
if (flags & ~(DEVICE_NOTIFY_SERVICE_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)) - FIXME("unhandled flags %#x\n", flags); + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + if (!(flags & DEVICE_NOTIFY_SERVICE_HANDLE) && !IsWindow( handle )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + if (!header) details.filter.header.dbch_devicetype = 0; + else if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + { + DEV_BROADCAST_DEVICEINTERFACE_W *iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)header; + details.filter.iface = *iface; + + if (flags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) + details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid ); + else + details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name ); + } + else if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) + { + FIXME( "DBT_DEVTYP_HANDLE filter type not implemented\n" ); + details.filter.header.dbch_devicetype = 0; + } + else + { + SetLastError( ERROR_INVALID_DATA ); + return NULL; + }
details.handle = handle;