[PATCH 2/3] ntdll: Implement thread description as information class.

Nikolay Sivov nsivov at codeweavers.com
Sun Nov 24 11:34:21 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/ntdll/thread.c            | 52 ++++++++++++++++++++++++++++++++++
 include/wine/server_protocol.h | 17 ++++++-----
 server/protocol.def            | 13 ++++++---
 server/request.h               |  2 ++
 server/thread.c                | 33 +++++++++++++++++++++
 server/thread.h                |  1 +
 server/trace.c                 |  4 +++
 7 files changed, 111 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 621aaddfe3..4655d25245 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -1115,6 +1115,38 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
         *(BOOL*)data = FALSE;
         if (ret_len) *ret_len = sizeof(BOOL);
         return STATUS_SUCCESS;
+    case ThreadDescription:
+        {
+            THREAD_DESCRIPTION_INFORMATION *info = data;
+            data_size_t len, desc_length = 0;
+            WCHAR *ptr;
+
+            len = length >= sizeof(*info) ? length - sizeof(*info) : 0;
+            ptr = info ? (WCHAR *)(info + 1) : NULL;
+
+            SERVER_START_REQ( get_thread_info )
+            {
+                req->handle = wine_server_obj_handle( handle );
+                req->mask = SET_THREAD_INFO_DESCRIPTION;
+                if (ptr && len) wine_server_set_reply( req, ptr, len );
+                if (!(status = wine_server_call( req )))
+                    desc_length = reply->desc_length;
+            }
+            SERVER_END_REQ;
+            if (status == STATUS_SUCCESS)
+            {
+                if (desc_length <= len && info)
+                {
+                    info->Length = desc_length << 16 | desc_length;
+                    info->Description = ptr;
+                }
+                else
+                    status = STATUS_BUFFER_TOO_SMALL;
+
+                if (ret_len) *ret_len = desc_length + sizeof(*info);
+            }
+        }
+        return status;
     case ThreadPriority:
     case ThreadBasePriority:
     case ThreadImpersonationToken:
@@ -1270,6 +1302,26 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
             SERVER_END_REQ;
         }
         return status;
+    case ThreadDescription:
+        {
+            const THREAD_DESCRIPTION_INFORMATION *info = data;
+
+            if (length != sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
+            if (!info) return STATUS_ACCESS_VIOLATION;
+            if (info->Length >> 16 != (info->Length & 0xffff)) return STATUS_INVALID_PARAMETER;
+            if (info->Length && !info->Description) return STATUS_ACCESS_VIOLATION;
+
+            SERVER_START_REQ( set_thread_info )
+            {
+                req->handle = wine_server_obj_handle( handle );
+                req->mask   = SET_THREAD_INFO_DESCRIPTION;
+                if (info->Length)
+                    wine_server_add_data( req, info->Description, info->Length & 0xffff );
+                status = wine_server_call( req );
+            }
+            SERVER_END_REQ;
+        }
+        return status;
     case ThreadBasicInformation:
     case ThreadTimes:
     case ThreadPriority:
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index d8f9816422..58e0dfc739 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -993,7 +993,7 @@ struct get_thread_info_request
     struct request_header __header;
     obj_handle_t handle;
     thread_id_t  tid_in;
-    char __pad_20[4];
+    int          mask;
 };
 struct get_thread_info_reply
 {
@@ -1006,7 +1006,8 @@ struct get_thread_info_reply
     int          exit_code;
     int          priority;
     int          last;
-    char __pad_52[4];
+    data_size_t  desc_length;
+    /* VARARG(desc,unicode_str); */
 };
 
 
@@ -1034,16 +1035,18 @@ struct set_thread_info_request
     affinity_t   affinity;
     client_ptr_t entry_point;
     obj_handle_t token;
+    /* VARARG(desc,unicode_str); */
     char __pad_44[4];
 };
 struct set_thread_info_reply
 {
     struct reply_header __header;
 };
-#define SET_THREAD_INFO_PRIORITY   0x01
-#define SET_THREAD_INFO_AFFINITY   0x02
-#define SET_THREAD_INFO_TOKEN      0x04
-#define SET_THREAD_INFO_ENTRYPOINT 0x08
+#define SET_THREAD_INFO_PRIORITY    0x01
+#define SET_THREAD_INFO_AFFINITY    0x02
+#define SET_THREAD_INFO_TOKEN       0x04
+#define SET_THREAD_INFO_ENTRYPOINT  0x08
+#define SET_THREAD_INFO_DESCRIPTION 0x10
 
 
 
@@ -6691,6 +6694,6 @@ union generic_reply
     struct resume_process_reply resume_process_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 589
+#define SERVER_PROTOCOL_VERSION 590
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 3a0df20bdb..f2ea58ec82 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -935,6 +935,7 @@ struct rawinput_device
 @REQ(get_thread_info)
     obj_handle_t handle;        /* thread handle */
     thread_id_t  tid_in;        /* thread id (optional) */
+    int          mask;          /* mask to request thread description */
 @REPLY
     process_id_t pid;           /* server process id */
     thread_id_t  tid;           /* server thread id */
@@ -944,6 +945,8 @@ struct rawinput_device
     int          exit_code;     /* thread exit code */
     int          priority;      /* thread priority level */
     int          last;          /* last thread in process */
+    data_size_t  desc_length;   /* description length in WCHARs */
+    VARARG(desc,unicode_str);   /* description string */
 @END
 
 
@@ -964,11 +967,13 @@ struct rawinput_device
     affinity_t   affinity;     /* affinity mask */
     client_ptr_t entry_point;  /* thread entry point */
     obj_handle_t token;        /* impersonation token */
+    VARARG(desc,unicode_str);  /* description string */
 @END
-#define SET_THREAD_INFO_PRIORITY   0x01
-#define SET_THREAD_INFO_AFFINITY   0x02
-#define SET_THREAD_INFO_TOKEN      0x04
-#define SET_THREAD_INFO_ENTRYPOINT 0x08
+#define SET_THREAD_INFO_PRIORITY    0x01
+#define SET_THREAD_INFO_AFFINITY    0x02
+#define SET_THREAD_INFO_TOKEN       0x04
+#define SET_THREAD_INFO_ENTRYPOINT  0x08
+#define SET_THREAD_INFO_DESCRIPTION 0x10
 
 
 /* Retrieve information about a module */
diff --git a/server/request.h b/server/request.h
index 1303b35ef7..a824b4a4d0 100644
--- a/server/request.h
+++ b/server/request.h
@@ -840,6 +840,7 @@ C_ASSERT( FIELD_OFFSET(struct set_process_info_request, affinity) == 24 );
 C_ASSERT( sizeof(struct set_process_info_request) == 32 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, handle) == 12 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, tid_in) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, mask) == 20 );
 C_ASSERT( sizeof(struct get_thread_info_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, pid) == 8 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, tid) == 12 );
@@ -849,6 +850,7 @@ C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, affinity) == 32 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, exit_code) == 40 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, priority) == 44 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, last) == 48 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_length) == 52 );
 C_ASSERT( sizeof(struct get_thread_info_reply) == 56 );
 C_ASSERT( FIELD_OFFSET(struct get_thread_times_request, handle) == 12 );
 C_ASSERT( sizeof(struct get_thread_times_request) == 16 );
diff --git a/server/thread.c b/server/thread.c
index e753c8d0dd..b0f3e9ed33 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -51,6 +51,7 @@
 #include "request.h"
 #include "user.h"
 #include "security.h"
+#include "unicode.h"
 
 
 #ifdef __i386__
@@ -201,6 +202,7 @@ static inline void init_thread_structure( struct thread *thread )
     thread->suspend         = 0;
     thread->desktop_users   = 0;
     thread->token           = NULL;
+    thread->desc            = NULL;
 
     thread->creation_time = current_time;
     thread->exit_time     = 0;
@@ -336,6 +338,7 @@ static void cleanup_thread( struct thread *thread )
             thread->inflight[i].client = thread->inflight[i].server = -1;
         }
     }
+    free( thread->desc );
     thread->req_data = NULL;
     thread->reply_data = NULL;
     thread->request_fd = NULL;
@@ -344,6 +347,7 @@ static void cleanup_thread( struct thread *thread )
     thread->context = NULL;
     thread->suspend_context = NULL;
     thread->desktop = 0;
+    thread->desc = NULL;
 }
 
 /* destroy a thread when its refcount is 0 */
@@ -551,6 +555,27 @@ static void set_thread_info( struct thread *thread,
         security_set_thread_token( thread, req->token );
     if (req->mask & SET_THREAD_INFO_ENTRYPOINT)
         thread->entry_point = req->entry_point;
+    if (req->mask & SET_THREAD_INFO_DESCRIPTION)
+    {
+        WCHAR *desc = NULL;
+        data_size_t len = get_req_data_size() / sizeof(WCHAR);
+
+        if (len)
+        {
+            if ((desc = mem_alloc( (len + 1) * sizeof(WCHAR) )))
+            {
+                memcpy( desc, get_req_data(), len * sizeof(WCHAR) );
+                desc[len] = 0;
+                free( thread->desc );
+                thread->desc = desc;
+            }
+        }
+        else
+        {
+            free( thread->desc );
+            thread->desc = NULL;
+        }
+    }
 }
 
 /* stop a thread (at the Unix level) */
@@ -1436,6 +1461,14 @@ DECL_HANDLER(get_thread_info)
         reply->priority       = thread->priority;
         reply->affinity       = thread->affinity;
         reply->last           = thread->process->running_threads == 1;
+        reply->desc_length    = 0;
+
+        if (thread->desc && req->mask & SET_THREAD_INFO_DESCRIPTION)
+        {
+            reply->desc_length = strlenW( thread->desc ) * sizeof(WCHAR);
+            if (get_reply_max_size() >= reply->desc_length)
+                set_reply_data( thread->desc, min( reply->desc_length, get_reply_max_size() ));
+        }
 
         release_object( thread );
     }
diff --git a/server/thread.h b/server/thread.h
index e10120dcf6..73b46d01be 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -88,6 +88,7 @@ struct thread
     timeout_t              exit_time;     /* Thread exit time */
     struct token          *token;         /* security token associated with this thread */
     struct list            kernel_object; /* list of kernel object pointers */
+    WCHAR                 *desc;          /* thread description string */
 };
 
 struct thread_snapshot
diff --git a/server/trace.c b/server/trace.c
index 55d5e68962..f216233ca3 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1411,6 +1411,7 @@ static void dump_get_thread_info_request( const struct get_thread_info_request *
 {
     fprintf( stderr, " handle=%04x", req->handle );
     fprintf( stderr, ", tid_in=%04x", req->tid_in );
+    fprintf( stderr, ", mask=%d", req->mask );
 }
 
 static void dump_get_thread_info_reply( const struct get_thread_info_reply *req )
@@ -1423,6 +1424,8 @@ static void dump_get_thread_info_reply( const struct get_thread_info_reply *req
     fprintf( stderr, ", exit_code=%d", req->exit_code );
     fprintf( stderr, ", priority=%d", req->priority );
     fprintf( stderr, ", last=%d", req->last );
+    fprintf( stderr, ", desc_length=%u", req->desc_length );
+    dump_varargs_unicode_str( ", desc=", cur_size );
 }
 
 static void dump_get_thread_times_request( const struct get_thread_times_request *req )
@@ -1444,6 +1447,7 @@ static void dump_set_thread_info_request( const struct set_thread_info_request *
     dump_uint64( ", affinity=", &req->affinity );
     dump_uint64( ", entry_point=", &req->entry_point );
     fprintf( stderr, ", token=%04x", req->token );
+    dump_varargs_unicode_str( ", desc=", cur_size );
 }
 
 static void dump_get_dll_info_request( const struct get_dll_info_request *req )
-- 
2.24.0




More information about the wine-devel mailing list