mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-02 15:43:38 +00:00
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:
parent
0d3ebfc459
commit
6c61ea6a13
|
@ -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_free_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||||
extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||||
extern void signal_init_process(void) 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 NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) DECLSPEC_HIDDEN;
|
||||||
extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN;
|
extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN;
|
||||||
extern void debug_init(void) 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 BOOL is_wow64 DECLSPEC_HIDDEN;
|
||||||
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS server_init_process_done(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 abort_thread( int status ) DECLSPEC_HIDDEN;
|
||||||
extern void DECLSPEC_NORETURN terminate_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;
|
extern void DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1470,7 +1470,7 @@ NTSTATUS server_init_process_done(void)
|
||||||
*
|
*
|
||||||
* Send an init thread request. Return 0 if OK.
|
* 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 char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
|
||||||
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
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;
|
info_size = reply->info_size;
|
||||||
server_start_time = reply->server_start;
|
server_start_time = reply->server_start;
|
||||||
server_cpus = reply->all_cpus;
|
server_cpus = reply->all_cpus;
|
||||||
|
*suspend = reply->suspend;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
|
|
@ -1029,11 +1029,21 @@ static void thread_startup( void *param )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* 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;
|
NTSTATUS status;
|
||||||
|
CONTEXT context = { 0 };
|
||||||
struct startup_info info = { entry, arg };
|
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 )))
|
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
|
||||||
{
|
{
|
||||||
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
||||||
|
|
|
@ -900,11 +900,21 @@ static void thread_startup( void *param )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* 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;
|
NTSTATUS status;
|
||||||
|
CONTEXT context = { 0 };
|
||||||
struct startup_info info = { entry, arg };
|
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 )))
|
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
|
||||||
{
|
{
|
||||||
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
||||||
|
|
|
@ -2618,11 +2618,29 @@ static void thread_startup( void *param )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* 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;
|
NTSTATUS status;
|
||||||
|
CONTEXT context = { 0 };
|
||||||
struct startup_info info = { entry, arg };
|
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 )))
|
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
|
||||||
{
|
{
|
||||||
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
||||||
|
|
|
@ -1102,11 +1102,21 @@ static void thread_startup( void *param )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* 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;
|
NTSTATUS status;
|
||||||
|
CONTEXT context = { 0 };
|
||||||
struct startup_info info = { entry, arg };
|
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 )))
|
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
|
||||||
{
|
{
|
||||||
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
||||||
|
|
|
@ -3160,11 +3160,24 @@ static void thread_startup( void *param )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* 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;
|
NTSTATUS status;
|
||||||
|
CONTEXT context = { 0 };
|
||||||
struct startup_info info = { entry, arg };
|
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 )))
|
if (!(status = wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase )))
|
||||||
{
|
{
|
||||||
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
|
||||||
|
|
|
@ -272,6 +272,7 @@ HANDLE thread_init(void)
|
||||||
{
|
{
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
BOOL suspend;
|
||||||
SIZE_T size, info_size;
|
SIZE_T size, info_size;
|
||||||
HANDLE exe_file = 0;
|
HANDLE exe_file = 0;
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
|
@ -359,7 +360,7 @@ HANDLE thread_init(void)
|
||||||
|
|
||||||
/* setup the server connection */
|
/* setup the server connection */
|
||||||
server_init_process();
|
server_init_process();
|
||||||
info_size = server_init_thread( peb );
|
info_size = server_init_thread( peb, &suspend );
|
||||||
|
|
||||||
/* create the process heap */
|
/* create the process heap */
|
||||||
if (!(peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
|
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 )
|
static void start_thread( struct startup_info *info )
|
||||||
{
|
{
|
||||||
|
BOOL suspend;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
TEB *teb = info->teb;
|
TEB *teb = info->teb;
|
||||||
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
|
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();
|
thread_data->pthread_id = pthread_self();
|
||||||
|
|
||||||
signal_init_thread( teb );
|
signal_init_thread( teb );
|
||||||
server_init_thread( info->entry_point );
|
server_init_thread( info->entry_point, &suspend );
|
||||||
status = signal_start_thread( (LPTHREAD_START_ROUTINE)info->entry_point, info->entry_arg );
|
status = signal_start_thread( (LPTHREAD_START_ROUTINE)info->entry_point, info->entry_arg, suspend );
|
||||||
NtTerminateThread( GetCurrentThread(), status );
|
NtTerminateThread( GetCurrentThread(), status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -827,7 +827,7 @@ struct init_thread_reply
|
||||||
data_size_t info_size;
|
data_size_t info_size;
|
||||||
int version;
|
int version;
|
||||||
unsigned int all_cpus;
|
unsigned int all_cpus;
|
||||||
char __pad_36[4];
|
int suspend;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -6475,6 +6475,6 @@ union generic_reply
|
||||||
struct terminate_job_reply terminate_job_reply;
|
struct terminate_job_reply terminate_job_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 543
|
#define SERVER_PROTOCOL_VERSION 544
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -807,6 +807,7 @@ struct rawinput_device
|
||||||
data_size_t info_size; /* total size of startup info */
|
data_size_t info_size; /* total size of startup info */
|
||||||
int version; /* protocol version */
|
int version; /* protocol version */
|
||||||
unsigned int all_cpus; /* bitset of supported CPUs */
|
unsigned int all_cpus; /* bitset of supported CPUs */
|
||||||
|
int suspend; /* is thread suspended? */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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, info_size) == 24 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, version) == 28 );
|
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, all_cpus) == 32 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 36 );
|
||||||
C_ASSERT( sizeof(struct init_thread_reply) == 40 );
|
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, handle) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, exit_code) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, exit_code) == 16 );
|
||||||
|
|
|
@ -1323,7 +1323,6 @@ DECL_HANDLER(init_thread)
|
||||||
if (process->unix_pid != current->unix_pid)
|
if (process->unix_pid != current->unix_pid)
|
||||||
process->unix_pid = -1; /* can happen with linuxthreads */
|
process->unix_pid = -1; /* can happen with linuxthreads */
|
||||||
init_thread_context( current );
|
init_thread_context( current );
|
||||||
stop_thread_if_suspended( current );
|
|
||||||
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, &req->entry );
|
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, &req->entry );
|
||||||
set_thread_affinity( current, current->affinity );
|
set_thread_affinity( current, current->affinity );
|
||||||
}
|
}
|
||||||
|
@ -1334,6 +1333,7 @@ DECL_HANDLER(init_thread)
|
||||||
reply->version = SERVER_PROTOCOL_VERSION;
|
reply->version = SERVER_PROTOCOL_VERSION;
|
||||||
reply->server_start = server_start_time;
|
reply->server_start = server_start_time;
|
||||||
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
|
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
|
||||||
|
reply->suspend = (current->suspend || process->suspend);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -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, ", info_size=%u", req->info_size );
|
||||||
fprintf( stderr, ", version=%d", req->version );
|
fprintf( stderr, ", version=%d", req->version );
|
||||||
fprintf( stderr, ", all_cpus=%08x", req->all_cpus );
|
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 )
|
static void dump_terminate_process_request( const struct terminate_process_request *req )
|
||||||
|
|
Loading…
Reference in a new issue