Alexandre Julliard : server: Specify the process in which to create a new thread.

Alexandre Julliard julliard at winehq.org
Thu Sep 20 13:45:33 CDT 2018


Module: wine
Branch: master
Commit: 0fd450af5bad816f7134b5ce6a5b81fb7b962b44
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=0fd450af5bad816f7134b5ce6a5b81fb7b962b44

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Sep 20 13:19:49 2018 +0200

server: Specify the process in which to create a new thread.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/thread.c            |  1 +
 include/wine/server_protocol.h |  4 +++-
 server/protocol.def            |  3 ++-
 server/request.h               |  9 +++++----
 server/thread.c                | 31 +++++++++++++++++++++++++++----
 server/trace.c                 |  3 ++-
 6 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 7fa087d..8171638 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -605,6 +605,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr,
 
     SERVER_START_REQ( new_thread )
     {
+        req->process    = wine_server_obj_handle( process );
         req->access     = THREAD_ALL_ACCESS;
         req->suspend    = suspended;
         req->request_fd = request_pipe[0];
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index d31a1d4..02734bc 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -766,10 +766,12 @@ struct get_new_process_info_reply
 struct new_thread_request
 {
     struct request_header __header;
+    obj_handle_t process;
     unsigned int access;
     int          suspend;
     int          request_fd;
     /* VARARG(objattr,object_attributes); */
+    char __pad_28[4];
 };
 struct new_thread_reply
 {
@@ -6534,6 +6536,6 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 561
+#define SERVER_PROTOCOL_VERSION 562
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 46669d6..1c2e130 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -766,8 +766,9 @@ struct rawinput_device
 @END
 
 
-/* Create a new thread from the context of the parent */
+/* Create a new thread */
 @REQ(new_thread)
+    obj_handle_t process;      /* process in which to create thread */
     unsigned int access;       /* wanted access rights */
     int          suspend;      /* new thread should be suspended on creation */
     int          request_fd;   /* fd for request pipe */
diff --git a/server/request.h b/server/request.h
index ff2da53..d7a4c8d 100644
--- a/server/request.h
+++ b/server/request.h
@@ -752,10 +752,11 @@ C_ASSERT( sizeof(struct get_new_process_info_request) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_new_process_info_reply, success) == 8 );
 C_ASSERT( FIELD_OFFSET(struct get_new_process_info_reply, exit_code) == 12 );
 C_ASSERT( sizeof(struct get_new_process_info_reply) == 16 );
-C_ASSERT( FIELD_OFFSET(struct new_thread_request, access) == 12 );
-C_ASSERT( FIELD_OFFSET(struct new_thread_request, suspend) == 16 );
-C_ASSERT( FIELD_OFFSET(struct new_thread_request, request_fd) == 20 );
-C_ASSERT( sizeof(struct new_thread_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct new_thread_request, process) == 12 );
+C_ASSERT( FIELD_OFFSET(struct new_thread_request, access) == 16 );
+C_ASSERT( FIELD_OFFSET(struct new_thread_request, suspend) == 20 );
+C_ASSERT( FIELD_OFFSET(struct new_thread_request, request_fd) == 24 );
+C_ASSERT( sizeof(struct new_thread_request) == 32 );
 C_ASSERT( FIELD_OFFSET(struct new_thread_reply, tid) == 8 );
 C_ASSERT( FIELD_OFFSET(struct new_thread_reply, handle) == 12 );
 C_ASSERT( sizeof(struct new_thread_reply) == 16 );
diff --git a/server/thread.c b/server/thread.c
index d671377..7162fc3 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1271,19 +1271,40 @@ unsigned int get_supported_cpu_mask(void)
 DECL_HANDLER(new_thread)
 {
     struct thread *thread;
+    struct process *process;
     struct unicode_str name;
     const struct security_descriptor *sd;
     const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
     int request_fd = thread_get_inflight_fd( current, req->request_fd );
 
-    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
+    if (!(process = get_process_from_handle( req->process, PROCESS_CREATE_THREAD )))
     {
         if (request_fd != -1) close( request_fd );
-        set_error( STATUS_INVALID_HANDLE );
         return;
     }
 
-    if ((thread = create_thread( request_fd, current->process, sd )))
+    if (process != current->process)
+    {
+        if (request_fd != -1)  /* can't create a request fd in a different process */
+        {
+            close( request_fd );
+            set_error( STATUS_INVALID_PARAMETER );
+            goto done;
+        }
+        if (process->running_threads)  /* only the initial thread can be created in another process */
+        {
+            set_error( STATUS_ACCESS_DENIED );
+            goto done;
+        }
+    }
+    else if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
+    {
+        if (request_fd != -1) close( request_fd );
+        set_error( STATUS_INVALID_HANDLE );
+        goto done;
+    }
+
+    if ((thread = create_thread( request_fd, process, sd )))
     {
         thread->system_regs = current->system_regs;
         if (req->suspend) thread->suspend++;
@@ -1292,10 +1313,12 @@ DECL_HANDLER(new_thread)
                                                            req->access, objattr->attributes )))
         {
             /* thread object will be released when the thread gets killed */
-            return;
+            goto done;
         }
         kill_thread( thread, 1 );
     }
+done:
+    release_object( process );
 }
 
 /* initialize a new thread */
diff --git a/server/trace.c b/server/trace.c
index 3054a18..a419ddf 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1261,7 +1261,8 @@ static void dump_get_new_process_info_reply( const struct get_new_process_info_r
 
 static void dump_new_thread_request( const struct new_thread_request *req )
 {
-    fprintf( stderr, " access=%08x", req->access );
+    fprintf( stderr, " process=%04x", req->process );
+    fprintf( stderr, ", access=%08x", req->access );
     fprintf( stderr, ", suspend=%d", req->suspend );
     fprintf( stderr, ", request_fd=%d", req->request_fd );
     dump_varargs_object_attributes( ", objattr=", cur_size );




More information about the wine-cvs mailing list