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;
There's no conversion to do, the device name in the filter is ignored.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/input.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 67ca7e178f2..fde4b9965ed 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1186,13 +1186,9 @@ extern BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ); * * See RegisterDeviceNotificationW. */ -HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hRecipient, LPVOID pNotificationFilter, DWORD dwFlags) +HDEVNOTIFY WINAPI RegisterDeviceNotificationA( HANDLE handle, void *filter, DWORD flags ) { - TRACE("(hwnd=%p, filter=%p,flags=0x%08x)\n", - hRecipient,pNotificationFilter,dwFlags); - if (pNotificationFilter) - FIXME("The notification filter will requires an A->W when filter support is implemented\n"); - return RegisterDeviceNotificationW(hRecipient, pNotificationFilter, dwFlags); + return RegisterDeviceNotificationW( handle, filter, flags ); }
/***********************************************************************
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/hotplug.c | 7 ++----- dlls/sechost/service.c | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 5cb8358e3a9..9993ce23c99 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -197,7 +197,6 @@ static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, L
winetest_push_context( "%u", device_change_count );
- todo_wine_if( IsEqualGUID( &iface->dbcc_classguid, &control_class ) && !device_change_all ) ok( IsEqualGUID( &iface->dbcc_classguid, &expect_guid ), "got dbch_classguid %s\n", debugstr_guid( &iface->dbcc_classguid ) ); ok( iface->dbcc_size >= offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name[wcslen( iface->dbcc_name ) + 1] ), @@ -315,8 +314,7 @@ static void test_RegisterDeviceNotification(void) while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
device_change_count = 0; - if (!strcmp( winetest_platform, "wine" )) device_change_expect = 4; - else device_change_expect = 2; + device_change_expect = 2; device_change_hwnd = hwnd; device_change_all = FALSE; stop_event = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -349,8 +347,7 @@ static void test_RegisterDeviceNotification(void) while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
device_change_count = 0; - if (!strcmp( winetest_platform, "wine" )) device_change_expect = 4; - else device_change_expect = 2; + device_change_expect = 2; device_change_hwnd = hwnd; device_change_all = FALSE; stop_event = CreateEventW( NULL, FALSE, FALSE, NULL ); diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 00485869e9c..fee3b52b6ac 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1990,6 +1990,23 @@ struct device_notify_registration struct device_notification_details details; };
+static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, DEV_BROADCAST_HDR *event ) +{ + if (!filter->dbch_devicetype) return TRUE; + if (filter->dbch_devicetype != event->dbch_devicetype) return FALSE; + + if (filter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + { + DEV_BROADCAST_DEVICEINTERFACE_W *filter_iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)filter; + DEV_BROADCAST_DEVICEINTERFACE_W *event_iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)event; + if (filter_iface->dbcc_size == offsetof(DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid)) return TRUE; + return IsEqualGUID( &filter_iface->dbcc_classguid, &event_iface->dbcc_classguid ); + } + + FIXME( "Filter dbch_devicetype %u not implemented\n", filter->dbch_devicetype ); + return TRUE; +} + static DWORD WINAPI device_notify_proc( void *arg ) { WCHAR endpoint[] = L"\pipe\wine_plugplay"; @@ -2074,6 +2091,7 @@ static DWORD WINAPI device_notify_proc( void *arg )
for (i = 0; i < details_copy_nelems; i++) { + if (!notification_filter_matches( &details_copy[i].filter.header, (DEV_BROADCAST_HDR *)buf )) continue; details_copy[i].cb( details_copy[i].handle, code, (DEV_BROADCAST_HDR *)buf ); } MIDL_user_free(buf); @@ -2104,8 +2122,6 @@ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_det
TRACE("callback %p, handle %p, filter %p, flags %#x\n", details->cb, details->handle, filter, flags);
- if (filter) FIXME("Notification filters are not yet implemented.\n"); - if (!(registration = heap_alloc(sizeof(struct device_notify_registration)))) { SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/hotplug.c | 2 -- dlls/ntoskrnl.exe/pnp.c | 8 +++++++- 2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 9993ce23c99..10aaeebcfd3 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -201,14 +201,12 @@ static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, L debugstr_guid( &iface->dbcc_classguid ) ); ok( iface->dbcc_size >= offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name[wcslen( iface->dbcc_name ) + 1] ), "got dbcc_size %u\n", iface->dbcc_size ); - todo_wine ok( !wcsncmp( iface->dbcc_name, expect_prefix, wcslen( expect_prefix ) ), "got dbcc_name %s\n", debugstr_w(iface->dbcc_name) );
upper_end = wcschr( iface->dbcc_name + wcslen( expect_prefix ), '#' ); name_end = iface->dbcc_name + wcslen( iface->dbcc_name ) + 1; ok( !!upper_end, "got dbcc_name %s\n", debugstr_w(iface->dbcc_name) ); - todo_wine ok( all_upper( iface->dbcc_name, upper_end ), "got dbcc_name %s\n", debugstr_w(iface->dbcc_name) ); ok( all_lower( upper_end, name_end ), "got dbcc_name %s\n", debugstr_w(iface->dbcc_name) );
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 8d3481b2a72..ee1402e0e49 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -698,11 +698,11 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
size_t namelen = name->Length / sizeof(WCHAR); DEV_BROADCAST_DEVICEINTERFACE_W *broadcast; + WCHAR *path, *refstr, *p, *upper_end; struct device_interface *iface; HANDLE iface_key, control_key; OBJECT_ATTRIBUTES attr = {0}; struct wine_rb_entry *entry; - WCHAR *path, *refstr, *p; UNICODE_STRING string; DWORD data = enable; NTSTATUS ret; @@ -788,6 +788,12 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable broadcast->dbcc_classguid = iface->interface_class; lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 ); if (namelen > 1) broadcast->dbcc_name[1] = '\'; + + upper_end = wcschr( broadcast->dbcc_name, '#' ); + if (upper_end) upper_end = wcschr( upper_end + 1, '#' ); + while (upper_end && upper_end-- != broadcast->dbcc_name) + *upper_end = towupper( *upper_end ); + send_devicechange( enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, broadcast, len ); heap_free( broadcast ); }