server: Implement AssignProcessToJobObject.

This commit is contained in:
Andrew Cook 2015-04-01 09:10:16 +11:00 committed by Alexandre Julliard
parent 0e78b0248d
commit 98132f0364
8 changed files with 121 additions and 6 deletions

View File

@ -2279,9 +2279,7 @@ static void test_TerminateJobObject(void)
SetLastError(0xdeadbeef);
ret = pAssignProcessToJobObject(job, pi.hProcess);
todo_wine
ok(!ret, "AssignProcessToJobObject unexpectedly succeeded\n");
todo_wine
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
CloseHandle(pi.hProcess);

View File

@ -654,8 +654,19 @@ NTSTATUS WINAPI NtIsProcessInJob( HANDLE process, HANDLE job )
*/
NTSTATUS WINAPI NtAssignProcessToJobObject( HANDLE job, HANDLE process )
{
FIXME( "stub: %p %p\n", job, process );
return STATUS_SUCCESS;
NTSTATUS status;
TRACE( "(%p %p)\n", job, process );
SERVER_START_REQ( assign_job )
{
req->job = wine_server_obj_handle( job );
req->process = wine_server_obj_handle( process );
status = wine_server_call( req );
}
SERVER_END_REQ;
return status;
}
/*

View File

@ -5099,6 +5099,20 @@ struct create_job_reply
};
struct assign_job_request
{
struct request_header __header;
obj_handle_t job;
obj_handle_t process;
char __pad_20[4];
};
struct assign_job_reply
{
struct reply_header __header;
};
enum request
{
REQ_new_process,
@ -5358,6 +5372,7 @@ enum request
REQ_get_suspend_context,
REQ_set_suspend_context,
REQ_create_job,
REQ_assign_job,
REQ_NB_REQUESTS
};
@ -5622,6 +5637,7 @@ union generic_request
struct get_suspend_context_request get_suspend_context_request;
struct set_suspend_context_request set_suspend_context_request;
struct create_job_request create_job_request;
struct assign_job_request assign_job_request;
};
union generic_reply
{
@ -5884,8 +5900,9 @@ union generic_reply
struct get_suspend_context_reply get_suspend_context_reply;
struct set_suspend_context_reply set_suspend_context_reply;
struct create_job_reply create_job_reply;
struct assign_job_reply assign_job_reply;
};
#define SERVER_PROTOCOL_VERSION 461
#define SERVER_PROTOCOL_VERSION 462
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -144,6 +144,8 @@ static void job_destroy( struct object *obj );
struct job
{
struct object obj; /* object header */
struct list process_list; /* list of all processes */
int num_processes; /* count of running processes */
};
static const struct object_ops job_ops =
@ -180,11 +182,18 @@ static struct job *create_job_object( struct directory *root, const struct unico
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION |
SACL_SECURITY_INFORMATION );
list_init( &job->process_list );
job->num_processes = 0;
}
}
return job;
}
static struct job *get_job_obj( struct process *process, obj_handle_t handle, unsigned int access )
{
return (struct job *)get_handle_obj( process, handle, access, &job_ops );
}
static struct object_type *job_get_type( struct object *obj )
{
static const WCHAR name[] = {'J','o','b'};
@ -201,15 +210,48 @@ static unsigned int job_map_access( struct object *obj, unsigned int access )
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}
static void add_job_process( struct job *job, struct process *process )
{
if (!process->running_threads)
{
set_error( STATUS_PROCESS_IS_TERMINATING );
return;
}
if (process->job)
{
set_error( STATUS_ACCESS_DENIED );
return;
}
process->job = (struct job *)grab_object( job );
list_add_tail( &job->process_list, &process->job_entry );
job->num_processes++;
}
/* called when a process has terminated, allow one additional process */
static void release_job_process( struct process *process )
{
struct job *job = process->job;
if (!job) return;
assert( job->num_processes );
job->num_processes--;
}
static void job_destroy( struct object *obj )
{
struct job *job = (struct job *)obj;
assert( obj->ops == &job_ops );
assert( !job->num_processes );
assert( list_empty(&job->process_list) );
}
static void job_dump( struct object *obj, int verbose )
{
struct job *job = (struct job *)obj;
assert( obj->ops == &job_ops );
fprintf( stderr, "Job\n");
fprintf( stderr, "Job processes=%d\n", list_count(&job->process_list) );
}
static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
@ -407,6 +449,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->is_system = 0;
process->debug_children = 0;
process->is_terminating = 0;
process->job = NULL;
process->console = NULL;
process->startup_state = STARTUP_IN_PROGRESS;
process->startup_info = NULL;
@ -505,6 +548,12 @@ static void process_destroy( struct object *obj )
close_process_handles( process );
set_process_startup_state( process, STARTUP_ABORTED );
if (process->job)
{
list_remove( &process->job_entry );
release_object( process->job );
}
if (process->console) release_object( process->console );
if (process->parent) release_object( process->parent );
if (process->msg_fd) release_object( process->msg_fd );
@ -742,6 +791,7 @@ static void process_killed( struct process *process )
remove_process_locks( process );
set_process_startup_state( process, STARTUP_ABORTED );
finish_process_tracing( process );
release_job_process( process );
start_sigkill_timer( process );
wake_up( &process->obj, 0 );
}
@ -1418,3 +1468,19 @@ DECL_HANDLER(create_job)
}
if (root) release_object( root );
}
/* assign a job object to a process */
DECL_HANDLER(assign_job)
{
struct process *process;
struct job *job = get_job_obj( current->process, req->job, JOB_OBJECT_ASSIGN_PROCESS );
if (!job) return;
if ((process = get_process_from_handle( req->process, PROCESS_SET_QUOTA | PROCESS_TERMINATE )))
{
add_job_process( job, process );
release_object( process );
}
release_object( job );
}

View File

@ -75,6 +75,8 @@ struct process
unsigned int is_system:1; /* is it a system process? */
unsigned int debug_children:1;/* also debug all child processes */
unsigned int is_terminating:1;/* is process terminating? */
struct job *job; /* job object ascoicated with this process */
struct list job_entry; /* list entry for job object */
struct list locks; /* list of file locks owned by the process */
struct list classes; /* window classes owned by the process */
struct console_input*console; /* console input */

View File

@ -3514,3 +3514,10 @@ enum coords_relative
@REPLY
obj_handle_t handle; /* handle to the job */
@END
/* Assign a job object to a process */
@REQ(assign_job)
obj_handle_t job; /* handle to the job */
obj_handle_t process; /* handle to the process */
@END

View File

@ -363,6 +363,7 @@ DECL_HANDLER(update_rawinput_devices);
DECL_HANDLER(get_suspend_context);
DECL_HANDLER(set_suspend_context);
DECL_HANDLER(create_job);
DECL_HANDLER(assign_job);
#ifdef WANT_REQUEST_HANDLERS
@ -626,6 +627,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_suspend_context,
(req_handler)req_set_suspend_context,
(req_handler)req_create_job,
(req_handler)req_assign_job,
};
C_ASSERT( sizeof(affinity_t) == 8 );
@ -2211,6 +2213,9 @@ C_ASSERT( FIELD_OFFSET(struct create_job_request, attributes) == 16 );
C_ASSERT( sizeof(struct create_job_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct create_job_reply, handle) == 8 );
C_ASSERT( sizeof(struct create_job_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct assign_job_request, job) == 12 );
C_ASSERT( FIELD_OFFSET(struct assign_job_request, process) == 16 );
C_ASSERT( sizeof(struct assign_job_request) == 24 );
#endif /* WANT_REQUEST_HANDLERS */

View File

@ -4107,6 +4107,12 @@ static void dump_create_job_reply( const struct create_job_reply *req )
fprintf( stderr, " handle=%04x", req->handle );
}
static void dump_assign_job_request( const struct assign_job_request *req )
{
fprintf( stderr, " job=%04x", req->job );
fprintf( stderr, ", process=%04x", req->process );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@ -4365,6 +4371,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_suspend_context_request,
(dump_func)dump_set_suspend_context_request,
(dump_func)dump_create_job_request,
(dump_func)dump_assign_job_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@ -4625,6 +4632,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_suspend_context_reply,
NULL,
(dump_func)dump_create_job_reply,
NULL,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@ -4885,6 +4893,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_suspend_context",
"set_suspend_context",
"create_job",
"assign_job",
};
static const struct