Alexandre Julliard : ntdll: Abuse RtlCreateUserThread to call the thread function for CreateThread directly .

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jan 19 06:29:17 CST 2007


Module: wine
Branch: master
Commit: 7a383cf83f1f2896f67352a76c07b13510baff1d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7a383cf83f1f2896f67352a76c07b13510baff1d

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jan 18 15:02:11 2007 +0100

ntdll: Abuse RtlCreateUserThread to call the thread function for CreateThread directly.

---

 dlls/kernel32/thread.c |   49 +-----------------------------------------------
 dlls/ntdll/thread.c    |   48 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 45 insertions(+), 52 deletions(-)

diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
index 4f2594c..cdbe1e1 100644
--- a/dlls/kernel32/thread.c
+++ b/dlls/kernel32/thread.c
@@ -45,42 +45,6 @@
 #include "kernel_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(thread);
-WINE_DECLARE_DEBUG_CHANNEL(relay);
-
-
-struct new_thread_info
-{
-    LPTHREAD_START_ROUTINE func;
-    void                  *arg;
-};
-
-
-/***********************************************************************
- *           THREAD_Start
- *
- * Start execution of a newly created thread. Does not return.
- */
-static void CALLBACK THREAD_Start( void *ptr )
-{
-    struct new_thread_info *info = ptr;
-    LPTHREAD_START_ROUTINE func = info->func;
-    void *arg = info->arg;
-
-    RtlFreeHeap( GetProcessHeap(), 0, info );
-
-    if (TRACE_ON(relay))
-        DPRINTF("%04x:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
-
-    __TRY
-    {
-        ExitThread( func( arg ) );
-    }
-    __EXCEPT(UnhandledExceptionFilter)
-    {
-        TerminateThread( GetCurrentThread(), GetExceptionCode() );
-    }
-    __ENDTRY
-}
 
 
 /***********************************************************************
@@ -120,22 +84,13 @@ HANDLE WINAPI CreateRemoteThread( HANDLE
     CLIENT_ID client_id;
     NTSTATUS status;
     SIZE_T stack_reserve = 0, stack_commit = 0;
-    struct new_thread_info *info;
-
-    if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) )))
-    {
-        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
-        return 0;
-    }
-    info->func = start;
-    info->arg  = param;
 
     if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
     else stack_commit = stack;
 
     status = RtlCreateUserThread( hProcess, NULL, TRUE,
                                   NULL, stack_reserve, stack_commit,
-                                  THREAD_Start, info, &handle, &client_id );
+                                  (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
     if (status == STATUS_SUCCESS)
     {
         if (id) *id = (DWORD)client_id.UniqueThread;
@@ -147,7 +102,6 @@ HANDLE WINAPI CreateRemoteThread( HANDLE
             if (NtResumeThread( handle, &ret ))
             {
                 NtClose( handle );
-                RtlFreeHeap( GetProcessHeap(), 0, info );
                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
                 handle = 0;
             }
@@ -155,7 +109,6 @@ HANDLE WINAPI CreateRemoteThread( HANDLE
     }
     else
     {
-        RtlFreeHeap( GetProcessHeap(), 0, info );
         SetLastError( RtlNtStatusToDosError(status) );
         handle = 0;
     }
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 4d99195..b06d1a3 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -43,6 +43,7 @@
 #include "wine/exception.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(thread);
+WINE_DECLARE_DEBUG_CHANNEL(relay);
 
 /* info passed to a starting thread */
 struct startup_info
@@ -349,6 +350,47 @@ static PUNHANDLED_EXCEPTION_FILTER get_u
 }
 
 /***********************************************************************
+ *           call_thread_func
+ *
+ * Hack to make things compatible with the thread procedures used by kernel32.CreateThread.
+ */
+static void DECLSPEC_NORETURN call_thread_func( PRTL_THREAD_START_ROUTINE rtl_func, void *arg )
+{
+    LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)rtl_func;
+    DWORD exit_code;
+    BOOL last;
+
+    MODULE_DllThreadAttach( NULL );
+
+    if (TRACE_ON(relay))
+        DPRINTF( "%04x:Starting thread proc %p (arg=%p)\n", GetCurrentThreadId(), func, arg );
+
+    exit_code = func( arg );
+
+    /* send the exit code to the server */
+    SERVER_START_REQ( terminate_thread )
+    {
+        req->handle    = GetCurrentThread();
+        req->exit_code = exit_code;
+        wine_server_call( req );
+        last = reply->last;
+    }
+    SERVER_END_REQ;
+
+    if (last)
+    {
+        LdrShutdownProcess();
+        exit( exit_code );
+    }
+    else
+    {
+        LdrShutdownThread();
+        server_exit_thread( exit_code );
+    }
+}
+
+
+/***********************************************************************
  *           start_thread
  *
  * Startup routine for a newly created thread.
@@ -397,7 +439,7 @@ static void start_thread( struct wine_pt
     {
         __TRY
         {
-            MODULE_DllThreadAttach( NULL );
+            call_thread_func( func, arg );
         }
         __EXCEPT(get_unhandled_exception_filter())
         {
@@ -406,9 +448,7 @@ static void start_thread( struct wine_pt
         __ENDTRY
     }
     else
-        MODULE_DllThreadAttach( NULL );
-
-    func( arg );
+        call_thread_func( func, arg );
 }
 
 




More information about the wine-cvs mailing list