Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index b5d89f6ee5..dad89016ab 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1712,6 +1712,45 @@ static NTSTATUS create_device_symlink( DEVICE_OBJECT *device, UNICODE_STRING *sy return ret; }
+/******************************************************************* + * list_device_notifications + * + * Build an array of windows which have been registered to receive device + * notifications. The array must be freed with HeapFree. Returns NULL when no + * registered windows are found. + */ +static HWND *list_device_notifications( void ) +{ + HWND *list; + int i, count, size = 128; + + for (;;) + { + count = 0; + + if (!(list = heap_alloc( size * sizeof(HWND) ))) break; + + SERVER_START_REQ( get_device_notifications ) + { + wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) ); + if (!wine_server_call( req )) count = reply->count; + } + SERVER_END_REQ; + if (count && count < size) + { + /* start from the end since HWND is potentially larger than user_handle_t */ + for (i = count - 1; i >= 0; i--) + list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] ); + list[count] = 0; + return list; + } + heap_free( list ); + if (!count) break; + size = count + 1; /* restart with a large enough buffer */ + } + return NULL; +} + /*********************************************************************** * IoSetDeviceInterfaceState (NTOSKRNL.EXE.@) */ @@ -1739,6 +1778,8 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable NTSTATUS ret; GUID class; ULONG len; + HWND *registrations; + unsigned int i;
TRACE("(%s, %d)\n", debugstr_us(name), enable);
@@ -1822,6 +1863,19 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE, enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, (LPARAM)broadcast );
+ if ((registrations = list_device_notifications( ))) + { + for (i = 0; registrations[i]; i++) + { + TRACE("Sending WM_DEVICECHANGE to registered window %p\n", registrations[i]); + SendMessageTimeoutW( registrations[i], WM_DEVICECHANGE, + enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, + (LPARAM)broadcast, SMTO_ABORTIFHUNG, 2000, NULL ); + } + + heap_free( registrations ); + } + heap_free( broadcast ); } return ret;