[PATCH v4 4/5] ntoskrnl.exe: Send WM_DEVICECHANGE messages to handles that have registered

Micah N Gorrell mgorrell at codeweavers.com
Thu May 30 16:41:16 CDT 2019


Signed-off-by: Micah N Gorrell <mgorrell at 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;
-- 
2.21.0




More information about the wine-devel mailing list