From 0eefa767919e81f3467141377b5ebb88eb794517 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 19 Sep 2017 12:26:06 +0200 Subject: [PATCH] ntdll: Suspend the process before attaching dlls, using the process initial context. Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/process.c | 19 ++++++++++--------- dlls/ntdll/server.c | 3 +++ include/wine/server_protocol.h | 4 +++- server/process.c | 2 +- server/protocol.def | 2 ++ server/request.h | 2 ++ server/trace.c | 7 ++++++- 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index e7fe35c8c9a..07daea82aec 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -3079,7 +3079,6 @@ static void test_SuspendProcessState(void) ok(orig_iat_entry_value, "IAT entry in OriginalFirstThunk is NULL\n"); /* The IAT should be UNRESOLVED */ - todo_wine ok(iat_entry_value == orig_iat_entry_value, "IAT entry resolved prematurely\n"); server_pipe_handle = CreateNamedPipeA(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH, @@ -3107,14 +3106,19 @@ static void test_SuspendProcessState(void) #ifdef __x86_64__ ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags ); ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax ); - todo_wine - { ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx ); ok( !ctx.Rsi, "rsi is not zero %lx\n", ctx.Rsi ); ok( !ctx.Rdi, "rdi is not zero %lx\n", ctx.Rdi ); ok( !ctx.Rbp, "rbp is not zero %lx\n", ctx.Rbp ); + ok( !ctx.R8, "r8 is not zero %lx\n", ctx.R8 ); + ok( !ctx.R9, "r9 is not zero %lx\n", ctx.R9 ); + ok( !ctx.R10, "r10 is not zero %lx\n", ctx.R10 ); + ok( !ctx.R11, "r11 is not zero %lx\n", ctx.R11 ); + ok( !ctx.R12, "r12 is not zero %lx\n", ctx.R12 ); + ok( !ctx.R13, "r13 is not zero %lx\n", ctx.R13 ); + ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 ); + ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 ); ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp ); - } entry_ptr = (void *)ctx.Rcx; peb_ptr = (void *)ctx.Rdx; @@ -3133,7 +3137,6 @@ static void test_SuspendProcessState(void) ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError()); #else ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags ); - todo_wine ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp ); if (!ctx.Ebp) /* winxp is completely different */ { @@ -3141,8 +3144,9 @@ static void test_SuspendProcessState(void) ok( !ctx.Edx, "edx is not zero %08x\n", ctx.Edx ); ok( !ctx.Esi, "esi is not zero %08x\n", ctx.Esi ); ok( !ctx.Edi, "edi is not zero %08x\n", ctx.Edi ); - ok( !((ctx.Esp + 0x10) & 0xfff), "esp is not at top of stack page %08x\n", ctx.Esp ); } + ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */ + "esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp ); entry_ptr = (void *)ctx.Eax; peb_ptr = (void *)ctx.Ebx; @@ -3163,12 +3167,9 @@ static void test_SuspendProcessState(void) #endif ret = ReadProcessMemory( pi.hProcess, peb_ptr, &child_peb, sizeof(child_peb), NULL ); - todo_wine ok( ret, "Failed to read PEB (%u)\n", GetLastError() ); - if (ret) ok( child_peb.ImageBaseAddress == exe_base, "wrong base %p/%p\n", child_peb.ImageBaseAddress, exe_base ); - todo_wine ok( entry_ptr == (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint, "wrong entry point %p/%p\n", entry_ptr, (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint ); diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index b20f1a5975e..c3b878e35ad 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -1427,6 +1427,7 @@ NTSTATUS server_init_process_done( CONTEXT *context ) IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); void *entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; NTSTATUS status; + int suspend; /* Install signal handlers; this cannot be done earlier, since we cannot * send exceptions to the debugger before the create process event that @@ -1446,9 +1447,11 @@ NTSTATUS server_init_process_done( CONTEXT *context ) req->entry = wine_server_client_ptr( entry ); req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); status = wine_server_call( req ); + suspend = reply->suspend; } SERVER_END_REQ; + if (suspend) wait_suspend( context ); return status; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index f903df49e7f..592dbf00fdb 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -799,6 +799,8 @@ struct init_process_done_request struct init_process_done_reply { struct reply_header __header; + int suspend; + char __pad_12[4]; }; @@ -6406,6 +6408,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 536 +#define SERVER_PROTOCOL_VERSION 537 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 2327a2664b3..d8c7ff7cec5 100644 --- a/server/process.c +++ b/server/process.c @@ -1322,8 +1322,8 @@ DECL_HANDLER(init_process_done) set_process_startup_state( process, STARTUP_DONE ); if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL ); - stop_thread_if_suspended( current ); if (process->debugger) set_process_debug_flag( process, 1 ); + reply->suspend = (current->suspend || process->suspend); } /* open a handle to a process */ diff --git a/server/protocol.def b/server/protocol.def index 35e1c7b1b32..4b21390fa14 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -785,6 +785,8 @@ struct rawinput_device mod_handle_t module; /* main module base address */ client_ptr_t ldt_copy; /* address of LDT copy (in thread address space) */ client_ptr_t entry; /* process entry point */ +@REPLY + int suspend; /* is process suspended? */ @END diff --git a/server/request.h b/server/request.h index f7c6dbad25a..de2f493fe76 100644 --- a/server/request.h +++ b/server/request.h @@ -757,6 +757,8 @@ C_ASSERT( FIELD_OFFSET(struct init_process_done_request, module) == 16 ); C_ASSERT( FIELD_OFFSET(struct init_process_done_request, ldt_copy) == 24 ); C_ASSERT( FIELD_OFFSET(struct init_process_done_request, entry) == 32 ); C_ASSERT( sizeof(struct init_process_done_request) == 40 ); +C_ASSERT( FIELD_OFFSET(struct init_process_done_reply, suspend) == 8 ); +C_ASSERT( sizeof(struct init_process_done_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_pid) == 12 ); C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_tid) == 16 ); C_ASSERT( FIELD_OFFSET(struct init_thread_request, debug_level) == 20 ); diff --git a/server/trace.c b/server/trace.c index 62b0cfe151c..3256c173cad 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1281,6 +1281,11 @@ static void dump_init_process_done_request( const struct init_process_done_reque dump_uint64( ", entry=", &req->entry ); } +static void dump_init_process_done_reply( const struct init_process_done_reply *req ) +{ + fprintf( stderr, " suspend=%d", req->suspend ); +} + static void dump_init_thread_request( const struct init_thread_request *req ) { fprintf( stderr, " unix_pid=%d", req->unix_pid ); @@ -4755,7 +4760,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_new_process_info_reply, (dump_func)dump_new_thread_reply, (dump_func)dump_get_startup_info_reply, - NULL, + (dump_func)dump_init_process_done_reply, (dump_func)dump_init_thread_reply, (dump_func)dump_terminate_process_reply, (dump_func)dump_terminate_thread_reply, -- 2.11.4.GIT