ntdll: Suspend a thread with its start context explicitly before attaching dlls.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-11-30 11:01:47 +01:00
parent 0d3ebfc459
commit 6c61ea6a13
13 changed files with 81 additions and 14 deletions

View File

@ -68,7 +68,7 @@ extern NTSTATUS signal_alloc_thread( TEB **teb ) DECLSPEC_HIDDEN;
extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN;
extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN;
extern void signal_init_process(void) DECLSPEC_HIDDEN;
extern NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
extern NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) DECLSPEC_HIDDEN;
extern NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) DECLSPEC_HIDDEN;
extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN;
extern void debug_init(void) DECLSPEC_HIDDEN;
@ -85,7 +85,7 @@ extern unsigned int server_cpus DECLSPEC_HIDDEN;
extern BOOL is_wow64 DECLSPEC_HIDDEN;
extern void server_init_process(void) DECLSPEC_HIDDEN;
extern NTSTATUS server_init_process_done(void) DECLSPEC_HIDDEN;
extern size_t server_init_thread( void *entry_point ) DECLSPEC_HIDDEN;
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN terminate_thread( int status ) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;

View File

@ -1470,7 +1470,7 @@ NTSTATUS server_init_process_done(void)
*
* Send an init thread request. Return 0 if OK.
*/
size_t server_init_thread( void *entry_point )
size_t server_init_thread( void *entry_point, BOOL *suspend )
{
static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
@ -1511,6 +1511,7 @@ size_t server_init_thread( void *entry_point )
info_size = reply->info_size;
server_start_time = reply->server_start;
server_cpus = reply->all_cpus;
*suspend = reply->suspend;
}
SERVER_END_REQ;

View File

@ -1029,11 +1029,21 @@ static void thread_startup( void *param )
/***********************************************************************
* signal_start_thread
*/
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg )
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
NTSTATUS status;
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.R0 = (DWORD)entry;
context.R1 = (DWORD)arg;
context.Sp = (DWORD)NtCurrentTeb()->Tib.StackBase;
context.Pc = (DWORD)call_thread_entry_point;
if (suspend) wait_suspend( &context );
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
{
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );

View File

@ -900,11 +900,21 @@ static void thread_startup( void *param )
/***********************************************************************
* signal_start_thread
*/
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg )
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
NTSTATUS status;
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.X0 = (DWORD_PTR)entry;
context.X1 = (DWORD_PTR)arg;
context.Sp = (DWORD_PTR)NtCurrentTeb()->Tib.StackBase;
context.Pc = (DWORD_PTR)call_thread_entry_point;
if (suspend) wait_suspend( &context );
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
{
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );

View File

@ -2618,11 +2618,29 @@ static void thread_startup( void *param )
/***********************************************************************
* signal_start_thread
*/
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg )
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
NTSTATUS status;
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.SegCs = wine_get_cs();
context.SegDs = wine_get_ds();
context.SegEs = wine_get_es();
context.SegFs = wine_get_fs();
context.SegGs = wine_get_gs();
context.SegSs = wine_get_ss();
context.Eax = (DWORD)entry;
context.Ebx = (DWORD)arg;
context.Esp = (DWORD)NtCurrentTeb()->Tib.StackBase - 16;
context.Eip = (DWORD)call_thread_entry_point;
((void **)context.Esp)[1] = entry;
((void **)context.Esp)[2] = arg;
if (suspend) wait_suspend( &context );
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
{
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );

View File

@ -1102,11 +1102,21 @@ static void thread_startup( void *param )
/***********************************************************************
* signal_start_thread
*/
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg )
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
NTSTATUS status;
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.Gpr1 = (DWORD)NtCurrentTeb()->Tib.StackBase;
context.Gpr3 = (DWORD)entry;
context.Gpr4 = (DWORD)arg;
context.Iar = (DWORD)call_thread_entry_point;
if (suspend) wait_suspend( &context );
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
{
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );

View File

@ -3160,11 +3160,24 @@ static void thread_startup( void *param )
/***********************************************************************
* signal_start_thread
*/
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg )
NTSTATUS signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
NTSTATUS status;
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
__asm__( "movw %%cs,%0" : "=m" (context.SegCs) );
__asm__( "movw %%ss,%0" : "=m" (context.SegSs) );
__asm__( "fxsave %0" : "=m" (context.u.FltSave) );
context.Rcx = (ULONG_PTR)entry;
context.Rdx = (ULONG_PTR)arg;
context.Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28;
context.Rip = (ULONG_PTR)call_thread_entry_point;
if (suspend) wait_suspend( &context );
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
{
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );

View File

@ -272,6 +272,7 @@ HANDLE thread_init(void)
{
TEB *teb;
void *addr;
BOOL suspend;
SIZE_T size, info_size;
HANDLE exe_file = 0;
LARGE_INTEGER now;
@ -359,7 +360,7 @@ HANDLE thread_init(void)
/* setup the server connection */
server_init_process();
info_size = server_init_thread( peb );
info_size = server_init_thread( peb, &suspend );
/* create the process heap */
if (!(peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
@ -496,6 +497,7 @@ void exit_thread( int status )
*/
static void start_thread( struct startup_info *info )
{
BOOL suspend;
NTSTATUS status;
TEB *teb = info->teb;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
@ -507,8 +509,8 @@ static void start_thread( struct startup_info *info )
thread_data->pthread_id = pthread_self();
signal_init_thread( teb );
server_init_thread( info->entry_point );
status = signal_start_thread( (LPTHREAD_START_ROUTINE)info->entry_point, info->entry_arg );
server_init_thread( info->entry_point, &suspend );
status = signal_start_thread( (LPTHREAD_START_ROUTINE)info->entry_point, info->entry_arg, suspend );
NtTerminateThread( GetCurrentThread(), status );
}

View File

@ -827,7 +827,7 @@ struct init_thread_reply
data_size_t info_size;
int version;
unsigned int all_cpus;
char __pad_36[4];
int suspend;
};
@ -6475,6 +6475,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 543
#define SERVER_PROTOCOL_VERSION 544
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -807,6 +807,7 @@ struct rawinput_device
data_size_t info_size; /* total size of startup info */
int version; /* protocol version */
unsigned int all_cpus; /* bitset of supported CPUs */
int suspend; /* is thread suspended? */
@END

View File

@ -782,6 +782,7 @@ C_ASSERT( FIELD_OFFSET(struct init_thread_reply, server_start) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, info_size) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, version) == 28 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, all_cpus) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 36 );
C_ASSERT( sizeof(struct init_thread_reply) == 40 );
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, exit_code) == 16 );

View File

@ -1323,7 +1323,6 @@ DECL_HANDLER(init_thread)
if (process->unix_pid != current->unix_pid)
process->unix_pid = -1; /* can happen with linuxthreads */
init_thread_context( current );
stop_thread_if_suspended( current );
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, &req->entry );
set_thread_affinity( current, current->affinity );
}
@ -1334,6 +1333,7 @@ DECL_HANDLER(init_thread)
reply->version = SERVER_PROTOCOL_VERSION;
reply->server_start = server_start_time;
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
reply->suspend = (current->suspend || process->suspend);
return;
error:

View File

@ -1306,6 +1306,7 @@ static void dump_init_thread_reply( const struct init_thread_reply *req )
fprintf( stderr, ", info_size=%u", req->info_size );
fprintf( stderr, ", version=%d", req->version );
fprintf( stderr, ", all_cpus=%08x", req->all_cpus );
fprintf( stderr, ", suspend=%d", req->suspend );
}
static void dump_terminate_process_request( const struct terminate_process_request *req )