diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 42532bd9f1c..c4d78128758 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1028,6 +1028,7 @@ @ stdcall RtlUpperChar(long) @ stdcall RtlUpperString(ptr ptr) @ stub RtlUsageHeap +@ stdcall -norelay RtlUserThreadStart(ptr ptr) @ cdecl -i386 -norelay RtlUshortByteSwap() NTDLL_RtlUshortByteSwap @ stdcall RtlValidAcl(ptr) @ stdcall RtlValidRelativeSecurityDescriptor(ptr long long) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index f2fa9a8b752..18664030df5 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -256,12 +256,10 @@ void WINAPI RtlExitUserThread( ULONG status ) /*********************************************************************** - * call_thread_entry_point + * RtlUserThreadStart (NTDLL.@) */ #ifdef __i386__ - -extern void call_thread_entry_point(void) DECLSPEC_HIDDEN; -__ASM_GLOBAL_FUNC( call_thread_entry_point, +__ASM_STDCALL_FUNC( RtlUserThreadStart, 8, "pushl %ebp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") @@ -272,7 +270,7 @@ __ASM_GLOBAL_FUNC( call_thread_entry_point, "call " __ASM_NAME("call_thread_func") ) /* wrapper for apps that don't declare the thread function correctly */ -extern DWORD call_thread_func_wrapper( LPTHREAD_START_ROUTINE entry, void *arg ); +extern DWORD call_thread_func_wrapper( PRTL_THREAD_START_ROUTINE entry, void *arg ); __ASM_GLOBAL_FUNC(call_thread_func_wrapper, "pushl %ebp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") @@ -287,7 +285,7 @@ __ASM_GLOBAL_FUNC(call_thread_func_wrapper, __ASM_CFI(".cfi_same_value %ebp\n\t") "ret" ) -void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ) +void DECLSPEC_HIDDEN call_thread_func( PRTL_THREAD_START_ROUTINE entry, void *arg ) { __TRY { @@ -304,12 +302,12 @@ void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ) #else /* __i386__ */ -static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ) { __TRY { TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( entry( arg )); + RtlExitUserThread( ((LPTHREAD_START_ROUTINE)entry)( arg )); } __EXCEPT(call_unhandled_exception_filter) { @@ -330,29 +328,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle_ptr, ACCESS_MASK access, OBJECT ULONG flags, SIZE_T zero_bits, SIZE_T stack_commit, SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) { - NTSTATUS status; - CLIENT_ID client_id; - - if (!access) access = THREAD_ALL_ACCESS; - - status = unix_funcs->create_thread( handle_ptr, access, attr, process, - start, param, call_thread_entry_point, flags, - stack_commit, stack_reserve, &client_id ); - if (!status && attr_list) - { - SIZE_T i, count = (attr_list->TotalLength - sizeof(attr_list->TotalLength)) / sizeof(PS_ATTRIBUTE); - for (i = 0; i < count; i++) - { - if (attr_list->Attributes[i].Attribute == PS_ATTRIBUTE_CLIENT_ID) - { - SIZE_T size = min( attr_list->Attributes[i].Size, sizeof(client_id) ); - memcpy( attr_list->Attributes[i].ValuePtr, &client_id, size ); - if (attr_list->Attributes[i].ReturnLength) *attr_list->Attributes[i].ReturnLength = size; - } - else FIXME( "Unsupported attribute %08lx\n", attr_list->Attributes[i].Attribute ); - } - } - return status; + return unix_funcs->NtCreateThreadEx( handle_ptr, access, attr, process, start, param, + flags, zero_bits, stack_commit, stack_reserve, attr_list ); } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 6ca8be9e6cf..4502be5f876 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -993,6 +993,7 @@ static struct unix_funcs unix_funcs = NtCreateMutant, NtCreateSection, NtCreateSemaphore, + NtCreateThreadEx, NtCreateTimer, NtCurrentTeb, NtDelayExecution, @@ -1063,7 +1064,6 @@ static struct unix_funcs unix_funcs = virtual_release_address_space, virtual_set_large_address_space, init_threading, - create_thread, start_process, abort_thread, exit_thread, diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index ec8f1cf8c49..b6458da61ad 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -123,7 +123,6 @@ struct startup_info { PRTL_THREAD_START_ROUTINE entry; void *arg; - void *relay; HANDLE actctx; }; @@ -150,17 +149,38 @@ static void start_thread( TEB *teb ) RtlActivateActivationContext( 0, info->actctx, &cookie ); RtlReleaseActivationContext( info->actctx ); } - signal_start_thread( info->entry, info->arg, suspend, info->relay, teb ); + signal_start_thread( info->entry, info->arg, suspend, RtlUserThreadStart, teb ); } /*********************************************************************** - * create_thread + * update_attr_list + * + * Update the output attributes. */ -NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, - ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, - CLIENT_ID *id ) +static void update_attr_list( PS_ATTRIBUTE_LIST *attr, const CLIENT_ID *id ) +{ + SIZE_T i, count = (attr->TotalLength - sizeof(attr->TotalLength)) / sizeof(PS_ATTRIBUTE); + + for (i = 0; i < count; i++) + { + if (attr->Attributes[i].Attribute == PS_ATTRIBUTE_CLIENT_ID) + { + SIZE_T size = min( attr->Attributes[i].Size, sizeof(*id) ); + memcpy( attr->Attributes[i].ValuePtr, id, size ); + if (attr->Attributes[i].ReturnLength) *attr->Attributes[i].ReturnLength = size; + } + } +} + + +/*********************************************************************** + * NtCreateThreadEx (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, + ULONG flags, SIZE_T zero_bits, SIZE_T stack_commit, + SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) { sigset_t sigset; pthread_t pthread_id; @@ -172,6 +192,7 @@ NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU DWORD tid = 0; int request_pipe[2]; SIZE_T extra_stack = PTHREAD_STACK_MIN; + CLIENT_ID client_id; HANDLE actctx; TEB *teb; INITIAL_TEB stack; @@ -196,11 +217,9 @@ NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU if (result.create_thread.status == STATUS_SUCCESS) { *handle = wine_server_ptr_handle( result.create_thread.handle ); - if (id) - { - id->UniqueProcess = ULongToHandle( result.create_thread.pid ); - id->UniqueThread = ULongToHandle( result.create_thread.tid ); - } + client_id.UniqueProcess = ULongToHandle( result.create_thread.pid ); + client_id.UniqueThread = ULongToHandle( result.create_thread.tid ); + if (attr_list) update_attr_list( attr_list, &client_id ); } return result.create_thread.status; } @@ -214,6 +233,8 @@ NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU } server_send_fd( request_pipe[0] ); + if (!access) access = THREAD_ALL_ACCESS; + SERVER_START_REQ( new_thread ) { req->process = wine_server_obj_handle( process ); @@ -249,14 +270,13 @@ NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU goto done; } - teb->ClientId.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); - teb->ClientId.UniqueThread = ULongToHandle( tid ); - if (id) *id = teb->ClientId; + client_id.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); + client_id.UniqueThread = ULongToHandle( tid ); + teb->ClientId = client_id; info = (struct startup_info *)(teb + 1); info->entry = start; info->arg = param; - info->relay = relay; info->actctx = actctx; teb->Tib.StackBase = stack.StackBase; @@ -286,11 +306,15 @@ NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU done: pthread_sigmask( SIG_SETMASK, &sigset, NULL ); - if (!status) return STATUS_SUCCESS; - NtClose( *handle ); - RtlReleaseActivationContext( actctx ); - close( request_pipe[1] ); - return status; + if (status) + { + NtClose( *handle ); + RtlReleaseActivationContext( actctx ); + close( request_pipe[1] ); + return status; + } + if (attr_list) update_attr_list( attr_list, &client_id ); + return STATUS_SUCCESS; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 3e848f87661..debc14f68c2 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -97,10 +97,6 @@ extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN; extern TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, - ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, - CLIENT_ID *id ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN start_process( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 5ce1ff9b717..5eea152a0e1 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 28 +#define NTDLL_UNIXLIB_VERSION 29 struct unix_funcs { @@ -50,6 +50,10 @@ struct unix_funcs ULONG protect, ULONG sec_flags, HANDLE file ); NTSTATUS (WINAPI *NtCreateSemaphore)( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max ); + NTSTATUS (WINAPI *NtCreateThreadEx)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, + ULONG flags, SIZE_T zero_bits, SIZE_T stack_commit, + SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ); NTSTATUS (WINAPI *NtCreateTimer)( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, TIMER_TYPE type ); TEB * (WINAPI *NtCurrentTeb)(void); @@ -166,10 +170,6 @@ struct unix_funcs /* thread/process functions */ TEB * (CDECL *init_threading)( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ); - NTSTATUS (CDECL *create_thread)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, - ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, - CLIENT_ID *id ); void (CDECL *start_process)( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ); void (CDECL *abort_thread)( int status ); void (CDECL *exit_thread)( int status ); diff --git a/include/winternl.h b/include/winternl.h index ad64df9d2e0..edc21b5c089 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3122,6 +3122,7 @@ NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeToOemN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWO NTSYSAPI NTSTATUS WINAPI RtlUpdateTimer(HANDLE, HANDLE, DWORD, DWORD); NTSYSAPI CHAR WINAPI RtlUpperChar(CHAR); NTSYSAPI void WINAPI RtlUpperString(STRING *,const STRING *); +NTSYSAPI void WINAPI RtlUserThreadStart(PRTL_THREAD_START_ROUTINE,void*); NTSYSAPI NTSTATUS WINAPI RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR); NTSYSAPI BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR,ULONG,SECURITY_INFORMATION); NTSYSAPI BOOLEAN WINAPI RtlValidAcl(PACL);