ntdll: Pass a debug object in the new_process request.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-02-01 11:08:44 +01:00
parent da0b451f5f
commit 11e6f1007c
10 changed files with 70 additions and 33 deletions

View File

@ -1746,14 +1746,12 @@ static void test_kill_on_exit(const char *argv0)
ok( !status, "NtCreateDebugObject failed %x\n", status ); ok( !status, "NtCreateDebugObject failed %x\n", status );
pDbgUiSetThreadDebugObject( debug ); pDbgUiSetThreadDebugObject( debug );
exit_code = run_child_wait( cmd, event ); exit_code = run_child_wait( cmd, event );
todo_wine
ok( exit_code == 0, "exit code = %08x\n", exit_code); ok( exit_code == 0, "exit code = %08x\n", exit_code);
status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE ); status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
ok( !status, "NtCreateDebugObject failed %x\n", status ); ok( !status, "NtCreateDebugObject failed %x\n", status );
pDbgUiSetThreadDebugObject( debug ); pDbgUiSetThreadDebugObject( debug );
exit_code = run_child_wait( cmd, event ); exit_code = run_child_wait( cmd, event );
todo_wine
ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code); ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code);
status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0xfffe ); status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0xfffe );
@ -1762,7 +1760,6 @@ static void test_kill_on_exit(const char *argv0)
status = pDbgUiConnectToDbg(); status = pDbgUiConnectToDbg();
ok( !status, "DbgUiConnectToDbg failed %x\n", status ); ok( !status, "DbgUiConnectToDbg failed %x\n", status );
exit_code = run_child_wait( cmd, event ); exit_code = run_child_wait( cmd, event );
todo_wine
ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code); ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code);
heap_free(cmd); heap_free(cmd);

View File

@ -249,14 +249,15 @@ struct _PROC_THREAD_ATTRIBUTE_LIST
/*********************************************************************** /***********************************************************************
* create_nt_process * create_nt_process
*/ */
static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, static NTSTATUS create_nt_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags,
RTL_USER_PROCESS_PARAMETERS *params,
RTL_USER_PROCESS_INFORMATION *info, HANDLE parent, RTL_USER_PROCESS_INFORMATION *info, HANDLE parent,
const struct proc_thread_attr *handle_list ) const struct proc_thread_attr *handle_list )
{ {
OBJECT_ATTRIBUTES process_attr, thread_attr; OBJECT_ATTRIBUTES process_attr, thread_attr;
PS_CREATE_INFO create_info; 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; PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer;
UNICODE_STRING nameW; UNICODE_STRING nameW;
NTSTATUS status; NTSTATUS status;
@ -309,6 +310,14 @@ static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECUR
attr->Attributes[pos].ReturnLength = NULL; attr->Attributes[pos].ReturnLength = NULL;
pos++; 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] ); attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL ); 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 * create_vdm_process
*/ */
static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, static NTSTATUS create_vdm_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags,
RTL_USER_PROCESS_PARAMETERS *params,
RTL_USER_PROCESS_INFORMATION *info ) RTL_USER_PROCESS_INFORMATION *info )
{ {
const WCHAR *winevdm = (is_win64 || is_wow64 ? 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 ); winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer );
RtlInitUnicodeString( &params->ImagePathName, winevdm ); RtlInitUnicodeString( &params->ImagePathName, winevdm );
RtlInitUnicodeString( &params->CommandLine, newcmdline ); RtlInitUnicodeString( &params->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 ); HeapFree( GetProcessHeap(), 0, newcmdline );
return status; return status;
} }
@ -359,8 +369,9 @@ static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECU
/*********************************************************************** /***********************************************************************
* create_cmd_process * create_cmd_process
*/ */
static NTSTATUS create_cmd_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, static NTSTATUS create_cmd_process( HANDLE token, HANDLE debug, SECURITY_ATTRIBUTES *psa,
BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags,
RTL_USER_PROCESS_PARAMETERS *params,
RTL_USER_PROCESS_INFORMATION *info ) RTL_USER_PROCESS_INFORMATION *info )
{ {
WCHAR comspec[MAX_PATH]; 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 ); swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer );
RtlInitUnicodeString( &params->ImagePathName, comspec ); RtlInitUnicodeString( &params->ImagePathName, comspec );
RtlInitUnicodeString( &params->CommandLine, newcmdline ); RtlInitUnicodeString( &params->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 ); RtlFreeHeap( GetProcessHeap(), 0, newcmdline );
return status; return status;
} }
@ -486,7 +497,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR
WCHAR *p, *tidy_cmdline = cmd_line; WCHAR *p, *tidy_cmdline = cmd_line;
RTL_USER_PROCESS_PARAMETERS *params = NULL; RTL_USER_PROCESS_PARAMETERS *params = NULL;
RTL_USER_PROCESS_INFORMATION rtl_info; RTL_USER_PROCESS_INFORMATION rtl_info;
HANDLE parent = NULL; HANDLE parent = 0, debug = 0;
NTSTATUS status; NTSTATUS status;
/* Process the AppName and/or CmdLine to get module name and path */ /* 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; goto done;
} }
if (flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
{
if ((status = DbgUiConnectToDbg())) goto done;
debug = DbgUiGetThreadDebugObject();
}
if (flags & EXTENDED_STARTUPINFO_PRESENT) if (flags & EXTENDED_STARTUPINFO_PRESENT)
{ {
struct _PROC_THREAD_ATTRIBUTE_LIST *attrs = 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 ); flags, params, &rtl_info, parent, handle_list );
switch (status) 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_NE_FORMAT:
case STATUS_INVALID_IMAGE_PROTECT: case STATUS_INVALID_IMAGE_PROTECT:
TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) ); 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; break;
case STATUS_INVALID_IMAGE_NOT_MZ: case STATUS_INVALID_IMAGE_NOT_MZ:
/* check for .com or .bat extension */ /* 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" )) if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" ))
{ {
TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) ); 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" )) else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" ))
{ {
TRACE( "starting %s as batch binary\n", debugstr_w(app_name) ); 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; break;
} }

View File

@ -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 ), TRACE( "%s image %s cmdline %s parent %p\n", debugstr_us( &path ),
debugstr_us( &params->ImagePathName ), debugstr_us( &params->CommandLine ), parent ); debugstr_us( &params->ImagePathName ), debugstr_us( &params->CommandLine ), parent );
if (debug) FIXME( "debug port %p not supported yet\n", debug );
unixdir = get_unix_curdir( params ); unixdir = get_unix_curdir( params );
@ -942,6 +941,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
SERVER_START_REQ( new_process ) SERVER_START_REQ( new_process )
{ {
req->token = wine_server_obj_handle( token ); req->token = wine_server_obj_handle( token );
req->debug = wine_server_obj_handle( debug );
req->parent_process = wine_server_obj_handle( parent ); req->parent_process = wine_server_obj_handle( parent );
req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES); req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES);
req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */ req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */

View File

@ -790,6 +790,7 @@ struct new_process_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t token; obj_handle_t token;
obj_handle_t debug;
obj_handle_t parent_process; obj_handle_t parent_process;
int inherit_all; int inherit_all;
unsigned int create_flags; unsigned int create_flags;
@ -802,6 +803,7 @@ struct new_process_request
/* VARARG(handles,uints,handles_size); */ /* VARARG(handles,uints,handles_size); */
/* VARARG(info,startup_info,info_size); */ /* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */ /* VARARG(env,unicode_str); */
char __pad_52[4];
}; };
struct new_process_reply struct new_process_reply
{ {
@ -6209,7 +6211,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 657 #define SERVER_PROTOCOL_VERSION 658
/* ### protocol_version end ### */ /* ### protocol_version end ### */

View File

@ -355,6 +355,11 @@ static void debug_obj_destroy( struct object *obj )
unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); 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, static struct debug_obj *create_debug_obj( struct object *root, const struct unicode_str *name,
unsigned int attr, unsigned int flags, unsigned int attr, unsigned int flags,
const struct security_descriptor *sd ) const struct security_descriptor *sd )

View File

@ -1092,6 +1092,7 @@ DECL_HANDLER(new_process)
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
struct process *process = NULL; struct process *process = NULL;
struct token *token = NULL; struct token *token = NULL;
struct debug_obj *debug_obj = NULL;
struct process *parent; struct process *parent;
struct thread *parent_thread = current; struct thread *parent_thread = current;
int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
@ -1215,6 +1216,11 @@ DECL_HANDLER(new_process)
close( socket_fd ); close( socket_fd );
goto done; 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, if (!(process = create_process( socket_fd, parent, req->inherit_all, info->data, sd,
handles, req->handles_size / sizeof(*handles), token ))) handles, req->handles_size / sizeof(*handles), token )))
@ -1249,15 +1255,17 @@ DECL_HANDLER(new_process)
if (get_error() == STATUS_INVALID_HANDLE || if (get_error() == STATUS_INVALID_HANDLE ||
get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error(); 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); 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 */ /* debug_children is set to 1 by default */
} }
@ -1271,6 +1279,7 @@ DECL_HANDLER(new_process)
done: done:
if (process) release_object( process ); if (process) release_object( process );
if (debug_obj) release_object( debug_obj );
if (token) release_object( token ); if (token) release_object( token );
release_object( parent ); release_object( parent );
release_object( info ); release_object( info );

View File

@ -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 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_id( process_id_t id );
extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access ); 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 int process_set_debugger( struct process *process, struct thread *thread );
extern void debugger_detach( struct process *process, struct debug_obj *debug_obj ); extern void debugger_detach( struct process *process, struct debug_obj *debug_obj );
extern int set_process_debug_flag( struct process *process, int flag ); extern int set_process_debug_flag( struct process *process, int flag );

View File

@ -804,6 +804,7 @@ typedef struct
/* Create a new process from the context of the parent */ /* Create a new process from the context of the parent */
@REQ(new_process) @REQ(new_process)
obj_handle_t token; /* process token */ obj_handle_t token; /* process token */
obj_handle_t debug; /* process debug object */
obj_handle_t parent_process; /* parent process */ obj_handle_t parent_process; /* parent process */
int inherit_all; /* inherit all handles from parent */ int inherit_all; /* inherit all handles from parent */
unsigned int create_flags; /* creation flags */ unsigned int create_flags; /* creation flags */

View File

@ -708,15 +708,16 @@ C_ASSERT( sizeof(unsigned int) == 4 );
C_ASSERT( sizeof(unsigned short) == 2 ); C_ASSERT( sizeof(unsigned short) == 2 );
C_ASSERT( sizeof(user_handle_t) == 4 ); 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, token) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 16 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, debug) == 16 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 20 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 20 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 24 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 24 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 28 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 44 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 44 );
C_ASSERT( sizeof(struct new_process_request) == 48 ); 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, info) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 );

View File

@ -1310,6 +1310,7 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req ) static void dump_new_process_request( const struct new_process_request *req )
{ {
fprintf( stderr, " token=%04x", req->token ); fprintf( stderr, " token=%04x", req->token );
fprintf( stderr, ", debug=%04x", req->debug );
fprintf( stderr, ", parent_process=%04x", req->parent_process ); fprintf( stderr, ", parent_process=%04x", req->parent_process );
fprintf( stderr, ", inherit_all=%d", req->inherit_all ); fprintf( stderr, ", inherit_all=%d", req->inherit_all );
fprintf( stderr, ", create_flags=%08x", req->create_flags ); fprintf( stderr, ", create_flags=%08x", req->create_flags );