server: Partially implement JobObjectBasicAccountingInformation.

Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Derek Lesho 2020-05-18 08:20:37 -05:00 committed by Alexandre Julliard
parent a302ab44ac
commit d8d6a6b2e6
7 changed files with 89 additions and 4 deletions

View File

@ -2513,6 +2513,7 @@ static void test_QueryInformationJobObject(void)
PJOBOBJECT_BASIC_PROCESS_ID_LIST pid_list = (JOBOBJECT_BASIC_PROCESS_ID_LIST *)buf;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION ext_limit_info;
JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit_info = &ext_limit_info.BasicLimitInformation;
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION basic_accounting_info;
DWORD ret_len;
PROCESS_INFORMATION pi[2];
char buffer[50];
@ -2620,6 +2621,14 @@ static void test_QueryInformationJobObject(void)
ok(ret_len == sizeof(ext_limit_info), "QueryInformationJobObject returned ret_len=%u\n", ret_len);
expect_eq_d(0, basic_limit_info->LimitFlags);
/* test JobObjectBasicAccountingInformation */
ret = pQueryInformationJobObject(job, JobObjectBasicAccountingInformation, &basic_accounting_info,
sizeof(basic_accounting_info), &ret_len);
ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
ok(ret_len == sizeof(basic_accounting_info), "QueryInformationJobObject returned ret_len=%u\n", ret_len);
expect_eq_d(3, basic_accounting_info.TotalProcesses);
expect_eq_d(2, basic_accounting_info.ActiveProcesses);
TerminateProcess(pi[0].hProcess, 0);
CloseHandle(pi[0].hProcess);
CloseHandle(pi[0].hThread);

View File

@ -392,7 +392,9 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
NTSTATUS ret;
TRACE( "semi-stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
if (class >= MaxJobObjectInfoClass)
return STATUS_INVALID_PARAMETER;
@ -406,9 +408,21 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
return STATUS_INFO_LENGTH_MISMATCH;
accounting = (JOBOBJECT_BASIC_ACCOUNTING_INFORMATION *)info;
memset(accounting, 0, sizeof(*accounting));
SERVER_START_REQ(get_job_info)
{
req->handle = wine_server_obj_handle( handle );
if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
{
memset(accounting, 0, sizeof(*accounting));
accounting->TotalProcesses = reply->total_processes;
accounting->ActiveProcesses = reply->active_processes;
}
}
SERVER_END_REQ;
if (ret_len) *ret_len = sizeof(*accounting);
return STATUS_SUCCESS;
return ret;
}
case JobObjectBasicProcessIdList:

View File

@ -5744,6 +5744,20 @@ struct set_job_completion_port_reply
struct get_job_info_request
{
struct request_header __header;
obj_handle_t handle;
};
struct get_job_info_reply
{
struct reply_header __header;
int total_processes;
int active_processes;
};
struct terminate_job_request
{
struct request_header __header;
@ -6075,6 +6089,7 @@ enum request
REQ_process_in_job,
REQ_set_job_limits,
REQ_set_job_completion_port,
REQ_get_job_info,
REQ_terminate_job,
REQ_suspend_process,
REQ_resume_process,
@ -6377,6 +6392,7 @@ union generic_request
struct process_in_job_request process_in_job_request;
struct set_job_limits_request set_job_limits_request;
struct set_job_completion_port_request set_job_completion_port_request;
struct get_job_info_request get_job_info_request;
struct terminate_job_request terminate_job_request;
struct suspend_process_request suspend_process_request;
struct resume_process_request resume_process_request;
@ -6677,6 +6693,7 @@ union generic_reply
struct process_in_job_reply process_in_job_reply;
struct set_job_limits_reply set_job_limits_reply;
struct set_job_completion_port_reply set_job_completion_port_reply;
struct get_job_info_reply get_job_info_reply;
struct terminate_job_reply terminate_job_reply;
struct suspend_process_reply suspend_process_reply;
struct resume_process_reply resume_process_reply;
@ -6684,7 +6701,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 608
#define SERVER_PROTOCOL_VERSION 609
/* ### protocol_version end ### */

View File

@ -156,6 +156,7 @@ struct job
struct object obj; /* object header */
struct list process_list; /* list of all processes */
int num_processes; /* count of running processes */
int total_processes; /* count of processes which have been assigned */
unsigned int limit_flags; /* limit flags */
int terminating; /* job is terminating */
int signaled; /* job is signaled */
@ -198,6 +199,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_
/* initialize it if it didn't already exist */
list_init( &job->process_list );
job->num_processes = 0;
job->total_processes = 0;
job->limit_flags = 0;
job->terminating = 0;
job->signaled = 0;
@ -240,6 +242,7 @@ static void add_job_process( struct job *job, struct process *process )
process->job = (struct job *)grab_object( job );
list_add_tail( &job->process_list, &process->job_entry );
job->num_processes++;
job->total_processes++;
add_job_completion( job, JOB_OBJECT_MSG_NEW_PROCESS, get_process_id(process) );
}
@ -1727,6 +1730,18 @@ DECL_HANDLER(process_in_job)
release_object( process );
}
/* retrieve information about a job */
DECL_HANDLER(get_job_info)
{
struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_QUERY );
if (!job) return;
reply->total_processes = job->total_processes;
reply->active_processes = job->num_processes;
release_object( job );
}
/* terminate all processes associated with the job */
DECL_HANDLER(terminate_job)
{

View File

@ -3935,6 +3935,15 @@ struct handle_info
@END
/* Retrieve information about a job */
@REQ(get_job_info)
obj_handle_t handle; /* handle to the job */
@REPLY
int total_processes; /* total count of processes */
int active_processes; /* count of running processes */
@END
/* Terminate all processes associated with the job */
@REQ(terminate_job)
obj_handle_t handle; /* handle to the job */

View File

@ -411,6 +411,7 @@ DECL_HANDLER(assign_job);
DECL_HANDLER(process_in_job);
DECL_HANDLER(set_job_limits);
DECL_HANDLER(set_job_completion_port);
DECL_HANDLER(get_job_info);
DECL_HANDLER(terminate_job);
DECL_HANDLER(suspend_process);
DECL_HANDLER(resume_process);
@ -712,6 +713,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_process_in_job,
(req_handler)req_set_job_limits,
(req_handler)req_set_job_completion_port,
(req_handler)req_get_job_info,
(req_handler)req_terminate_job,
(req_handler)req_suspend_process,
(req_handler)req_resume_process,
@ -2436,6 +2438,11 @@ C_ASSERT( FIELD_OFFSET(struct set_job_completion_port_request, job) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_job_completion_port_request, port) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_job_completion_port_request, key) == 24 );
C_ASSERT( sizeof(struct set_job_completion_port_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct get_job_info_request, handle) == 12 );
C_ASSERT( sizeof(struct get_job_info_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_job_info_reply, total_processes) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_job_info_reply, active_processes) == 12 );
C_ASSERT( sizeof(struct get_job_info_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct terminate_job_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct terminate_job_request, status) == 16 );
C_ASSERT( sizeof(struct terminate_job_request) == 24 );

View File

@ -4578,6 +4578,17 @@ static void dump_set_job_completion_port_request( const struct set_job_completio
dump_uint64( ", key=", &req->key );
}
static void dump_get_job_info_request( const struct get_job_info_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
}
static void dump_get_job_info_reply( const struct get_job_info_reply *req )
{
fprintf( stderr, " total_processes=%d", req->total_processes );
fprintf( stderr, ", active_processes=%d", req->active_processes );
}
static void dump_terminate_job_request( const struct terminate_job_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
@ -4887,6 +4898,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_process_in_job_request,
(dump_func)dump_set_job_limits_request,
(dump_func)dump_set_job_completion_port_request,
(dump_func)dump_get_job_info_request,
(dump_func)dump_terminate_job_request,
(dump_func)dump_suspend_process_request,
(dump_func)dump_resume_process_request,
@ -5185,6 +5197,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
NULL,
NULL,
(dump_func)dump_get_job_info_reply,
NULL,
NULL,
NULL,
@ -5483,6 +5496,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"process_in_job",
"set_job_limits",
"set_job_completion_port",
"get_job_info",
"terminate_job",
"suspend_process",
"resume_process",