diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index e5667463ce1..de7440d5ed8 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -1746,14 +1746,12 @@ static void test_kill_on_exit(const char *argv0) ok( !status, "NtCreateDebugObject failed %x\n", status ); pDbgUiSetThreadDebugObject( debug ); exit_code = run_child_wait( cmd, event ); - todo_wine ok( exit_code == 0, "exit code = %08x\n", exit_code); status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE ); ok( !status, "NtCreateDebugObject failed %x\n", status ); pDbgUiSetThreadDebugObject( debug ); exit_code = run_child_wait( cmd, event ); - todo_wine ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code); status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0xfffe ); @@ -1762,7 +1760,6 @@ static void test_kill_on_exit(const char *argv0) status = pDbgUiConnectToDbg(); ok( !status, "DbgUiConnectToDbg failed %x\n", status ); exit_code = run_child_wait( cmd, event ); - todo_wine ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code); heap_free(cmd); diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 4a254a011f8..98cefc717da 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -249,14 +249,15 @@ struct _PROC_THREAD_ATTRIBUTE_LIST /*********************************************************************** * create_nt_process */ -static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, - BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, +static NTSTATUS create_nt_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, + SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags, + RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info, HANDLE parent, const struct proc_thread_attr *handle_list ) { OBJECT_ATTRIBUTES process_attr, thread_attr; PS_CREATE_INFO create_info; - ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[6] ) / sizeof(ULONG_PTR)]; + ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[7] ) / sizeof(ULONG_PTR)]; PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer; UNICODE_STRING nameW; NTSTATUS status; @@ -309,6 +310,14 @@ static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECUR attr->Attributes[pos].ReturnLength = NULL; pos++; } + if (debug) + { + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT; + attr->Attributes[pos].Size = sizeof(debug); + attr->Attributes[pos].ValuePtr = debug; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + } attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] ); InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL ); @@ -329,8 +338,9 @@ static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECUR /*********************************************************************** * create_vdm_process */ -static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, - BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, +static NTSTATUS create_vdm_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, + SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags, + RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info ) { const WCHAR *winevdm = (is_win64 || is_wow64 ? @@ -350,7 +360,7 @@ static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECU winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, winevdm ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); - status = create_nt_process( token, psa, tsa, inherit, flags, params, info, NULL, NULL ); + status = create_nt_process( token, debug, psa, tsa, inherit, flags, params, info, NULL, NULL ); HeapFree( GetProcessHeap(), 0, newcmdline ); return status; } @@ -359,8 +369,9 @@ static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECU /*********************************************************************** * create_cmd_process */ -static NTSTATUS create_cmd_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, - BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, +static NTSTATUS create_cmd_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa, + SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags, + RTL_USER_PROCESS_PARAMETERS *params, RTL_USER_PROCESS_INFORMATION *info ) { WCHAR comspec[MAX_PATH]; @@ -378,7 +389,7 @@ static NTSTATUS create_cmd_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECU swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, comspec ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); - status = create_nt_process( token, psa, tsa, inherit, flags, params, info, NULL, NULL ); + status = create_nt_process( token, debug, psa, tsa, inherit, flags, params, info, NULL, NULL ); RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); return status; } @@ -486,7 +497,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR WCHAR *p, *tidy_cmdline = cmd_line; RTL_USER_PROCESS_PARAMETERS *params = NULL; RTL_USER_PROCESS_INFORMATION rtl_info; - HANDLE parent = NULL; + HANDLE parent = 0, debug = 0; NTSTATUS status; /* Process the AppName and/or CmdLine to get module name and path */ @@ -536,6 +547,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR goto done; } + if (flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) + { + if ((status = DbgUiConnectToDbg())) goto done; + debug = DbgUiGetThreadDebugObject(); + } + if (flags & EXTENDED_STARTUPINFO_PRESENT) { struct _PROC_THREAD_ATTRIBUTE_LIST *attrs = @@ -577,7 +594,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR } } - status = create_nt_process( token, process_attr, thread_attr, inherit, + status = create_nt_process( token, debug, process_attr, thread_attr, inherit, flags, params, &rtl_info, parent, handle_list ); switch (status) { @@ -587,7 +604,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR case STATUS_INVALID_IMAGE_NE_FORMAT: case STATUS_INVALID_IMAGE_PROTECT: TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) ); - status = create_vdm_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + status = create_vdm_process( token, debug, process_attr, thread_attr, + inherit, flags, params, &rtl_info ); break; case STATUS_INVALID_IMAGE_NOT_MZ: /* check for .com or .bat extension */ @@ -595,12 +613,14 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" )) { TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) ); - status = create_vdm_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + status = create_vdm_process( token, debug, process_attr, thread_attr, + inherit, flags, params, &rtl_info ); } else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" )) { TRACE( "starting %s as batch binary\n", debugstr_w(app_name) ); - status = create_cmd_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + status = create_cmd_process( token, debug, process_attr, thread_attr, + inherit, flags, params, &rtl_info ); } break; } diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index b8bbdaadbce..e971006e030 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -893,7 +893,6 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ TRACE( "%s image %s cmdline %s parent %p\n", debugstr_us( &path ), debugstr_us( ¶ms->ImagePathName ), debugstr_us( ¶ms->CommandLine ), parent ); - if (debug) FIXME( "debug port %p not supported yet\n", debug ); unixdir = get_unix_curdir( params ); @@ -942,6 +941,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ SERVER_START_REQ( new_process ) { req->token = wine_server_obj_handle( token ); + req->debug = wine_server_obj_handle( debug ); req->parent_process = wine_server_obj_handle( parent ); req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES); req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 326fe012b74..7979dae3a44 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -790,6 +790,7 @@ struct new_process_request { struct request_header __header; obj_handle_t token; + obj_handle_t debug; obj_handle_t parent_process; int inherit_all; unsigned int create_flags; @@ -802,6 +803,7 @@ struct new_process_request /* VARARG(handles,uints,handles_size); */ /* VARARG(info,startup_info,info_size); */ /* VARARG(env,unicode_str); */ + char __pad_52[4]; }; struct new_process_reply { @@ -6209,7 +6211,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 657 +#define SERVER_PROTOCOL_VERSION 658 /* ### protocol_version end ### */ diff --git a/server/debugger.c b/server/debugger.c index 3fa7a63f33b..b6959269920 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -355,6 +355,11 @@ static void debug_obj_destroy( struct object *obj ) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); } +struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) +{ + return (struct debug_obj *)get_handle_obj( process, handle, access, &debug_obj_ops ); +} + static struct debug_obj *create_debug_obj( struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int flags, const struct security_descriptor *sd ) diff --git a/server/process.c b/server/process.c index a8f62862df3..bd04c5609c7 100644 --- a/server/process.c +++ b/server/process.c @@ -1092,6 +1092,7 @@ DECL_HANDLER(new_process) const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); struct process *process = NULL; struct token *token = NULL; + struct debug_obj *debug_obj = NULL; struct process *parent; struct thread *parent_thread = current; int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); @@ -1215,6 +1216,11 @@ DECL_HANDLER(new_process) close( socket_fd ); goto done; } + if (req->debug && !(debug_obj = get_debug_obj( current->process, req->debug, DEBUG_PROCESS_ASSIGN ))) + { + close( socket_fd ); + goto done; + } if (!(process = create_process( socket_fd, parent, req->inherit_all, info->data, sd, handles, req->handles_size / sizeof(*handles), token ))) @@ -1249,15 +1255,17 @@ DECL_HANDLER(new_process) if (get_error() == STATUS_INVALID_HANDLE || get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error(); } - /* attach to the debugger if requested */ - if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) + + /* attach to the debugger */ + if (debug_obj) { - set_process_debugger( process, current ); + process->debug_obj = debug_obj; process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS); + if (!current->debug_obj) current->debug_obj = (struct debug_obj *)grab_object( debug_obj ); } - else if (current->process->debug_children) + else if (parent->debug_children) { - process->debug_obj = current->process->debug_obj; + process->debug_obj = parent->debug_obj; /* debug_children is set to 1 by default */ } @@ -1271,6 +1279,7 @@ DECL_HANDLER(new_process) done: if (process) release_object( process ); + if (debug_obj) release_object( debug_obj ); if (token) release_object( token ); release_object( parent ); release_object( info ); diff --git a/server/process.h b/server/process.h index 5901e8fa3de..90c6e67aacd 100644 --- a/server/process.h +++ b/server/process.h @@ -114,6 +114,7 @@ extern data_size_t init_process( struct thread *thread ); extern struct thread *get_process_first_thread( struct process *process ); extern struct process *get_process_from_id( process_id_t id ); extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access ); +extern struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ); extern int process_set_debugger( struct process *process, struct thread *thread ); extern void debugger_detach( struct process *process, struct debug_obj *debug_obj ); extern int set_process_debug_flag( struct process *process, int flag ); diff --git a/server/protocol.def b/server/protocol.def index 853f9dbae01..b47c2575acf 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -804,6 +804,7 @@ typedef struct /* Create a new process from the context of the parent */ @REQ(new_process) obj_handle_t token; /* process token */ + obj_handle_t debug; /* process debug object */ obj_handle_t parent_process; /* parent process */ int inherit_all; /* inherit all handles from parent */ unsigned int create_flags; /* creation flags */ diff --git a/server/request.h b/server/request.h index f0b364223c6..ec57c3cc4b7 100644 --- a/server/request.h +++ b/server/request.h @@ -708,15 +708,16 @@ C_ASSERT( sizeof(unsigned int) == 4 ); C_ASSERT( sizeof(unsigned short) == 2 ); C_ASSERT( sizeof(user_handle_t) == 4 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, token) == 12 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 16 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 20 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 24 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 28 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 44 ); -C_ASSERT( sizeof(struct new_process_request) == 48 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, debug) == 16 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 20 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 24 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 28 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 32 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 36 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 40 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 44 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 48 ); +C_ASSERT( sizeof(struct new_process_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, info) == 8 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 ); diff --git a/server/trace.c b/server/trace.c index 4d59b06d040..33f439516ee 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1310,6 +1310,7 @@ typedef void (*dump_func)( const void *req ); static void dump_new_process_request( const struct new_process_request *req ) { fprintf( stderr, " token=%04x", req->token ); + fprintf( stderr, ", debug=%04x", req->debug ); fprintf( stderr, ", parent_process=%04x", req->parent_process ); fprintf( stderr, ", inherit_all=%d", req->inherit_all ); fprintf( stderr, ", create_flags=%08x", req->create_flags );