[PATCH v4 1/5] server: Added support for tracking registered device notifications

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


Signed-off-by: Micah N Gorrell <mgorrell at codeweavers.com>
---
 server/protocol.def |  23 +++++++++
 server/user.h       |   3 +-
 server/window.c     | 112 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/server/protocol.def b/server/protocol.def
index e450388c17..1645d09d5f 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3692,6 +3692,29 @@ struct handle_info
 @END
 
 
+/* Register a handle for device notifications */
+ at REQ(register_device_notification)
+    user_handle_t  recipient;     /* handle to a window or service that will receive device events */
+ at REPLY
+    user_handle_t  handle;        /* handle associated with the registration */
+ at END
+
+
+/* Unregister device notifications for a handle */
+ at REQ(unregister_device_notification)
+    user_handle_t  notification;  /* handle that was previously returned by register_device_notification */
+ at END
+
+
+/* Return a list of handles that have registered for device notifications */
+ at REQ(get_device_notifications)
+ at REPLY
+    int            count;         /* total count of registered handles */
+    VARARG(handles,user_handles); /* registered handles */
+ at END
+
+
+
 /* Make the current process a system process */
 @REQ(make_process_system)
 @REPLY
diff --git a/server/user.h b/server/user.h
index eb1b7ce1e4..282cb63339 100644
--- a/server/user.h
+++ b/server/user.h
@@ -36,7 +36,8 @@ enum user_object
 {
     USER_WINDOW = 1,
     USER_HOOK,
-    USER_CLIENT  /* arbitrary client handle */
+    USER_CLIENT, /* arbitrary client handle */
+    USER_DEVNOTIFY
 };
 
 #define DESKTOP_ATOM  ((atom_t)32769)
diff --git a/server/window.c b/server/window.c
index c9b131cba5..80ac897ea6 100644
--- a/server/window.c
+++ b/server/window.c
@@ -129,6 +129,19 @@ static struct window *taskman_window;
 #define WINPTR_TOPMOST   ((struct window *)3L)
 #define WINPTR_NOTOPMOST ((struct window *)4L)
 
+struct device_notification
+{
+    user_handle_t   recipient;      /* the window handle to send notifications to */
+    user_handle_t   handle;         /* full handle for this window */
+    struct process  *process;       /* process that owns this notification handle */
+    struct list     entry;          /* entry in global notifications list */
+
+    /* FIXME: Add support for notification filters */
+};
+
+/* global list of handles that have registered for device notifications */
+static struct list device_notifications = LIST_INIT(device_notifications);
+
 /* retrieve a pointer to a window from its handle */
 static inline struct window *get_window( user_handle_t handle )
 {
@@ -2880,3 +2893,102 @@ DECL_HANDLER(set_window_layered_info)
     }
     else set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
 }
+
+/* retrieve a pointer to a device_notification from its handle */
+static inline struct device_notification *get_device_notification( user_handle_t handle )
+{
+    struct device_notification *ret = get_user_object( handle, USER_DEVNOTIFY );
+    if (!ret) set_win32_error( ERROR_INVALID_HANDLE );
+    return ret;
+}
+
+/* create a new device notification structure and link it into the global list */
+static struct device_notification *register_device_notification( struct window *recipient )
+{
+    struct device_notification *notification;
+
+    if (!recipient)
+    {
+        return NULL;
+    }
+
+    if (!(notification = mem_alloc( sizeof(*notification) ))) goto failed;
+    if (!(notification->handle = alloc_user_handle( notification, USER_DEVNOTIFY ))) goto failed;
+
+    notification->recipient = recipient->handle;
+    notification->process = current->process;
+    /* FIXME: Add support for notification filters */
+
+    list_add_tail( &device_notifications, &notification->entry );
+
+    return notification;
+failed:
+    if (notification)
+    {
+        if (notification->handle) free_user_handle( notification->handle );
+        free( notification );
+    }
+
+    return NULL;
+}
+
+static void unregister_device_notification( struct device_notification *notification)
+{
+    list_remove( &notification->entry );
+    free_user_handle( notification->handle );
+    memset( notification, 0x55, sizeof(*notification) );
+    free( notification );
+}
+
+static int get_device_notifications( struct user_handle_array *array )
+{
+    struct device_notification *notification;
+
+    LIST_FOR_EACH_ENTRY( notification, &device_notifications, struct device_notification, entry )
+    {
+        /* FIXME: Implement notification filtering */
+        if (!add_handle_to_array( array, notification->recipient )) return 0;
+    }
+
+    return 1;
+}
+
+/* register for device notifications */
+DECL_HANDLER(register_device_notification)
+{
+    struct device_notification *notification = NULL;
+    struct window *recipient = get_window( req->recipient );
+
+    reply->handle = 0;
+    if (!recipient) return;
+
+    if (!(notification = register_device_notification( recipient ))) return;
+
+    reply->handle = notification->handle;
+}
+
+DECL_HANDLER(unregister_device_notification)
+{
+    struct device_notification *notification = get_device_notification( req->notification );
+    if (notification) {
+        if (notification->process == current->process) unregister_device_notification(notification);
+        else set_error( STATUS_ACCESS_DENIED );
+    }
+}
+
+DECL_HANDLER(get_device_notifications)
+{
+    struct user_handle_array array;
+    data_size_t len;
+
+    array.handles = NULL;
+    array.count = 0;
+    array.total = 0;
+
+    if (!get_device_notifications( &array )) return;
+
+    reply->count = array.count;
+    len = min( get_reply_max_size(), array.count * sizeof(user_handle_t) );
+    if (len) set_reply_data_ptr( array.handles, len );
+    else free( array.handles );
+}
-- 
2.21.0




More information about the wine-devel mailing list