diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index b1b76a88878..87873d4a90d 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -2700,15 +2700,11 @@ static void test_QueryInformationJobObject(void) pid_list->NumberOfProcessIdsInList = 42; ret = QueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[1]), &ret_len); - todo_wine ok(!ret, "QueryInformationJobObject expected failure\n"); - todo_wine expect_eq_d(ERROR_MORE_DATA, GetLastError()); if (ret) { - todo_wine expect_eq_d(42, pid_list->NumberOfAssignedProcesses); - todo_wine expect_eq_d(42, pid_list->NumberOfProcessIdsInList); } @@ -2723,17 +2719,12 @@ static void test_QueryInformationJobObject(void) { ULONG_PTR *list = pid_list->ProcessIdList; - todo_wine ok(ret_len == FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[2]), "QueryInformationJobObject returned ret_len=%u\n", ret_len); - todo_wine expect_eq_d(2, pid_list->NumberOfAssignedProcesses); - todo_wine expect_eq_d(2, pid_list->NumberOfProcessIdsInList); - todo_wine expect_eq_d(pi[0].dwProcessId, list[0]); - todo_wine expect_eq_d(pi[1].dwProcessId, list[1]); } } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index a13e53a437b..5a5d49bf4bd 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -791,11 +791,40 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c case JobObjectBasicProcessIdList: { JOBOBJECT_BASIC_PROCESS_ID_LIST *process = info; + DWORD count, i; if (len < sizeof(*process)) return STATUS_INFO_LENGTH_MISMATCH; - memset( process, 0, sizeof(*process) ); - if (ret_len) *ret_len = sizeof(*process); - return STATUS_SUCCESS; + + count = len - offsetof( JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList ); + count /= sizeof(process->ProcessIdList[0]); + + SERVER_START_REQ( get_job_info ) + { + req->handle = wine_server_user_handle(handle); + wine_server_set_reply(req, process->ProcessIdList, count * sizeof(process_id_t)); + if (!(ret = wine_server_call(req))) + { + process->NumberOfAssignedProcesses = reply->active_processes; + process->NumberOfProcessIdsInList = min(count, reply->active_processes); + } + } + SERVER_END_REQ; + + if (ret != STATUS_SUCCESS) return ret; + + if (sizeof(process_id_t) < sizeof(process->ProcessIdList[0])) + { + /* start from the end to not overwrite */ + for (i = process->NumberOfProcessIdsInList; i--;) + { + ULONG_PTR id = ((process_id_t *)process->ProcessIdList)[i]; + process->ProcessIdList[i] = id; + } + } + + if (ret_len) + *ret_len = offsetof( JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[process->NumberOfProcessIdsInList] ); + return count < process->NumberOfAssignedProcesses ? STATUS_MORE_ENTRIES : STATUS_SUCCESS; } case JobObjectExtendedLimitInformation: { diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e5437576193..e9c12cac070 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5357,6 +5357,7 @@ struct get_job_info_reply struct reply_header __header; int total_processes; int active_processes; + /* VARARG(pids,uints); */ }; @@ -6256,7 +6257,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 730 +#define SERVER_PROTOCOL_VERSION 731 /* ### protocol_version end ### */ diff --git a/server/process.c b/server/process.c index 0870de5bb26..8109fbe8de4 100644 --- a/server/process.c +++ b/server/process.c @@ -286,6 +286,24 @@ static int process_in_job( struct job *job, struct process *process ) return process->job == job; } +static process_id_t *get_job_pids( struct job *job, process_id_t *pids, process_id_t *end ) +{ + struct process *process; + struct job *j; + + LIST_FOR_EACH_ENTRY( j, &job->child_job_list, struct job, parent_job_entry ) + pids = get_job_pids( j, pids, end ); + + LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry ) + { + if (pids == end) break; + if (process->end_time) continue; /* skip processes that ended */ + *pids++ = process->id; + } + + return pids; +} + static void add_job_process( struct job *job, struct process *process ) { struct job *j, *common_parent; @@ -1745,11 +1763,18 @@ DECL_HANDLER(process_in_job) DECL_HANDLER(get_job_info) { struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_QUERY ); + process_id_t *pids; + data_size_t len; if (!job) return; reply->total_processes = job->total_processes; reply->active_processes = job->num_processes; + + len = min( get_reply_max_size(), reply->active_processes * sizeof(*pids) ); + if (len && ((pids = set_reply_data_size( len )))) + get_job_pids( job, pids, pids + len / sizeof(*pids) ); + release_object( job ); } diff --git a/server/protocol.def b/server/protocol.def index cc1887dae2d..a5030fcf813 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3696,6 +3696,7 @@ struct handle_info @REPLY int total_processes; /* total count of processes */ int active_processes; /* count of running processes */ + VARARG(pids,uints); /* list of active pids */ @END diff --git a/server/trace.c b/server/trace.c index cfa6eefc36c..6e380fc4be5 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4525,6 +4525,7 @@ 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 ); + dump_varargs_uints( ", pids=", cur_size ); } static void dump_terminate_job_request( const struct terminate_job_request *req )