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_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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue