server: Support creating processes with specified parent.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47817 Signed-off-by: Paul Gofman <gofmanp@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b989a85484
commit
74a74556dd
|
@ -3861,14 +3861,14 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
|
|||
|
||||
memset(&parent_data, 0, sizeof(parent_data));
|
||||
ret = ReadFile(read_pipe, &parent_data, sizeof(parent_data), &size, NULL);
|
||||
todo_wine_if(level == 2) ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
|
||||
ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
|
||||
"Got unexpected ret %#x, level %u, GetLastError() %u.\n",
|
||||
ret, level, GetLastError());
|
||||
}
|
||||
|
||||
if (level == 2)
|
||||
{
|
||||
todo_wine ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
|
||||
ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
|
||||
parent_id, parent_data.parent_id);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1709,6 +1709,7 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
|
|||
|
||||
SERVER_START_REQ( new_process )
|
||||
{
|
||||
req->parent_process = wine_server_obj_handle(parent);
|
||||
req->inherit_all = inherit;
|
||||
req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */
|
||||
req->socket_fd = socketfd[1];
|
||||
|
|
|
@ -769,6 +769,7 @@ struct rawinput_device
|
|||
struct new_process_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t parent_process;
|
||||
int inherit_all;
|
||||
unsigned int create_flags;
|
||||
int socket_fd;
|
||||
|
@ -779,6 +780,7 @@ struct new_process_request
|
|||
/* VARARG(objattr,object_attributes); */
|
||||
/* VARARG(info,startup_info,info_size); */
|
||||
/* VARARG(env,unicode_str); */
|
||||
char __pad_44[4];
|
||||
};
|
||||
struct new_process_reply
|
||||
{
|
||||
|
@ -6702,6 +6704,6 @@ union generic_reply
|
|||
struct resume_process_reply resume_process_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 594
|
||||
#define SERVER_PROTOCOL_VERSION 595
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -504,25 +504,25 @@ int free_console( struct process *process )
|
|||
* 2/ parent is a renderer which launches process, and process should attach to the console
|
||||
* rendered by parent
|
||||
*/
|
||||
void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin)
|
||||
void inherit_console( struct thread *parent_thread, struct process *parent, struct process *process,
|
||||
obj_handle_t hconin )
|
||||
{
|
||||
int done = 0;
|
||||
struct process* parent = parent_thread->process;
|
||||
|
||||
/* if parent is a renderer, then attach current process to its console
|
||||
* a bit hacky....
|
||||
*/
|
||||
if (hconin)
|
||||
if (hconin && parent_thread)
|
||||
{
|
||||
struct console_input* console;
|
||||
struct console_input *console;
|
||||
|
||||
/* FIXME: should we check some access rights ? */
|
||||
if ((console = (struct console_input*)get_handle_obj( parent, hconin,
|
||||
if ((console = (struct console_input *)get_handle_obj( parent, hconin,
|
||||
0, &console_input_ops )))
|
||||
{
|
||||
if (console->renderer == parent_thread)
|
||||
{
|
||||
process->console = (struct console_input*)grab_object( console );
|
||||
process->console = (struct console_input *)grab_object( console );
|
||||
process->console->num_proc++;
|
||||
done = 1;
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ void inherit_console(struct thread *parent_thread, struct process *process, obj_
|
|||
/* otherwise, if parent has a console, attach child to this console */
|
||||
if (!done && parent->console)
|
||||
{
|
||||
process->console = (struct console_input*)grab_object( parent->console );
|
||||
process->console = (struct console_input *)grab_object( parent->console );
|
||||
process->console->num_proc++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1116,7 +1116,8 @@ DECL_HANDLER(new_process)
|
|||
const struct security_descriptor *sd;
|
||||
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
|
||||
struct process *process = NULL;
|
||||
struct process *parent = current->process;
|
||||
struct process *parent;
|
||||
struct thread *parent_thread = current;
|
||||
int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
|
||||
|
||||
if (socket_fd == -1)
|
||||
|
@ -1148,11 +1149,23 @@ DECL_HANDLER(new_process)
|
|||
return;
|
||||
}
|
||||
|
||||
if (req->parent_process)
|
||||
{
|
||||
if (!(parent = get_process_from_handle( req->parent_process, PROCESS_CREATE_PROCESS)))
|
||||
{
|
||||
close( socket_fd );
|
||||
return;
|
||||
}
|
||||
parent_thread = NULL;
|
||||
}
|
||||
else parent = (struct process *)grab_object( current->process );
|
||||
|
||||
if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) &&
|
||||
!(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
close( socket_fd );
|
||||
release_object( parent );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1160,6 +1173,7 @@ DECL_HANDLER(new_process)
|
|||
if (!(info = alloc_object( &startup_info_ops )))
|
||||
{
|
||||
close( socket_fd );
|
||||
release_object( parent );
|
||||
return;
|
||||
}
|
||||
info->process = NULL;
|
||||
|
@ -1222,7 +1236,7 @@ DECL_HANDLER(new_process)
|
|||
}
|
||||
|
||||
/* connect to the window station */
|
||||
connect_process_winstation( process, current );
|
||||
connect_process_winstation( process, parent_thread, parent );
|
||||
|
||||
/* set the process console */
|
||||
if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)))
|
||||
|
@ -1231,7 +1245,7 @@ DECL_HANDLER(new_process)
|
|||
* like if hConOut and hConIn are console handles, then they should be on the same
|
||||
* physical console
|
||||
*/
|
||||
inherit_console( current, process, req->inherit_all ? info->data->hstdin : 0 );
|
||||
inherit_console( parent_thread, parent, process, req->inherit_all ? info->data->hstdin : 0 );
|
||||
}
|
||||
|
||||
if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE))
|
||||
|
@ -1246,16 +1260,15 @@ 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))
|
||||
{
|
||||
set_process_debugger( process, current );
|
||||
process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
|
||||
}
|
||||
else if (parent->debugger && parent->debug_children)
|
||||
else if (current->process->debugger && current->process->debug_children)
|
||||
{
|
||||
set_process_debugger( process, parent->debugger );
|
||||
set_process_debugger( process, current->process->debugger );
|
||||
/* debug_children is set to 1 by default */
|
||||
}
|
||||
|
||||
|
@ -1265,10 +1278,11 @@ DECL_HANDLER(new_process)
|
|||
info->process = (struct process *)grab_object( process );
|
||||
reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 );
|
||||
reply->pid = get_process_id( process );
|
||||
reply->handle = alloc_handle_no_access_check( parent, process, req->access, objattr->attributes );
|
||||
reply->handle = alloc_handle_no_access_check( current->process, process, req->access, objattr->attributes );
|
||||
|
||||
done:
|
||||
if (process) release_object( process );
|
||||
release_object( parent );
|
||||
release_object( info );
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,8 @@ extern struct process_snapshot *process_snap( int *count );
|
|||
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
|
||||
|
||||
/* console functions */
|
||||
extern void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin);
|
||||
extern void inherit_console( struct thread *parent_thread, struct process *parent,
|
||||
struct process *process, obj_handle_t hconin );
|
||||
extern int free_console( struct process *process );
|
||||
extern struct thread *console_get_renderer( struct console_input *console );
|
||||
|
||||
|
|
|
@ -783,6 +783,7 @@ struct rawinput_device
|
|||
|
||||
/* Create a new process from the context of the parent */
|
||||
@REQ(new_process)
|
||||
obj_handle_t parent_process; /* parent process */
|
||||
int inherit_all; /* inherit all handles from parent */
|
||||
unsigned int create_flags; /* creation flags */
|
||||
int socket_fd; /* file descriptor for process socket */
|
||||
|
|
|
@ -745,14 +745,15 @@ C_ASSERT( sizeof(unsigned char) == 1 );
|
|||
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, inherit_all) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 28 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 36 );
|
||||
C_ASSERT( sizeof(struct new_process_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 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( sizeof(struct new_process_request) == 48 );
|
||||
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 );
|
||||
|
|
|
@ -1243,7 +1243,8 @@ typedef void (*dump_func)( const void *req );
|
|||
|
||||
static void dump_new_process_request( const struct new_process_request *req )
|
||||
{
|
||||
fprintf( stderr, " inherit_all=%d", req->inherit_all );
|
||||
fprintf( stderr, " parent_process=%04x", req->parent_process );
|
||||
fprintf( stderr, ", inherit_all=%d", req->inherit_all );
|
||||
fprintf( stderr, ", create_flags=%08x", req->create_flags );
|
||||
fprintf( stderr, ", socket_fd=%d", req->socket_fd );
|
||||
fprintf( stderr, ", exe_file=%04x", req->exe_file );
|
||||
|
|
|
@ -183,7 +183,8 @@ extern client_ptr_t get_class_client_ptr( struct window_class *class );
|
|||
extern struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access );
|
||||
extern struct winstation *get_process_winstation( struct process *process, unsigned int access );
|
||||
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
|
||||
extern void connect_process_winstation( struct process *process, struct thread *parent );
|
||||
extern void connect_process_winstation( struct process *process, struct thread *parent_thread,
|
||||
struct process *parent_process );
|
||||
extern void set_process_default_desktop( struct process *process, struct desktop *desktop,
|
||||
obj_handle_t handle );
|
||||
extern void close_process_desktop( struct process *process );
|
||||
|
|
|
@ -372,7 +372,8 @@ void set_process_default_desktop( struct process *process, struct desktop *deskt
|
|||
}
|
||||
|
||||
/* connect a process to its window station */
|
||||
void connect_process_winstation( struct process *process, struct thread *parent )
|
||||
void connect_process_winstation( struct process *process, struct thread *parent_thread,
|
||||
struct process *parent_process )
|
||||
{
|
||||
struct winstation *winstation = NULL;
|
||||
struct desktop *desktop = NULL;
|
||||
|
@ -383,9 +384,9 @@ void connect_process_winstation( struct process *process, struct thread *parent
|
|||
{
|
||||
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
|
||||
}
|
||||
else if (parent && parent->process->winstation)
|
||||
else if (parent_process->winstation)
|
||||
{
|
||||
handle = duplicate_handle( parent->process, parent->process->winstation,
|
||||
handle = duplicate_handle( parent_process, parent_process->winstation,
|
||||
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
|
||||
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
|
||||
}
|
||||
|
@ -397,14 +398,21 @@ void connect_process_winstation( struct process *process, struct thread *parent
|
|||
desktop = get_desktop_obj( process, handle, 0 );
|
||||
if (!desktop || desktop->winstation != winstation) goto done;
|
||||
}
|
||||
else if (parent && parent->desktop)
|
||||
else
|
||||
{
|
||||
desktop = get_desktop_obj( parent->process, parent->desktop, 0 );
|
||||
if (!desktop || desktop->winstation != winstation) goto done;
|
||||
handle = duplicate_handle( parent->process, parent->desktop,
|
||||
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
|
||||
}
|
||||
if (parent_thread && parent_thread->desktop)
|
||||
handle = parent_thread->desktop;
|
||||
else if (parent_process->desktop)
|
||||
handle = parent_process->desktop;
|
||||
else
|
||||
goto done;
|
||||
|
||||
desktop = get_desktop_obj( parent_process, handle, 0 );
|
||||
|
||||
if (!desktop || desktop->winstation != winstation) goto done;
|
||||
|
||||
handle = duplicate_handle( parent_process, handle, process, 0, 0, DUP_HANDLE_SAME_ACCESS );
|
||||
}
|
||||
if (handle) set_process_default_desktop( process, desktop, handle );
|
||||
|
||||
done:
|
||||
|
|
Loading…
Reference in New Issue