server: Implement AssignProcessToJobObject.
This commit is contained in:
parent
0e78b0248d
commit
98132f0364
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue