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 );
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);

View File

@ -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( &params->ImagePathName, winevdm );
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 );
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( &params->ImagePathName, comspec );
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 );
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;
}

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 ),
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 );
@ -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 */

View File

@ -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 ### */

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 ));
}
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 )

View File

@ -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 );

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 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 );

View File

@ -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 */

View File

@ -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 );

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 )
{
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 );