[PATCH resend] ntdll: Implement JobObjectBasicProcessIdList for NtQueryInformationJobObject.

Gabriel Ivăncescu gabrielopcode at gmail.com
Mon Sep 13 10:27:25 CDT 2021


On 13/09/2021 11:37, Huw Davies wrote:
> On Thu, Aug 12, 2021 at 07:02:37PM +0300, Gabriel Ivăncescu wrote:
>> diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
>> index a13e53a..0594a5e 100644
>> --- a/dlls/ntdll/unix/sync.c
>> +++ b/dlls/ntdll/unix/sync.c
>> @@ -791,11 +791,36 @@ 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 - FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList);
>> +        count /= sizeof(process->ProcessIdList[0]);
>> +
>> +        SERVER_START_REQ( query_job_pids )
>> +        {
>> +            req->job = wine_server_user_handle(handle);
>> +            wine_server_set_reply(req, process->ProcessIdList, count * sizeof(process_id_t));
>> +            if ((ret = wine_server_call(req)) != STATUS_SUCCESS)
>> +                return ret;
> 
> Returning out of a SERVER_*_REQ block looks odd.
> 
>> +            process->NumberOfAssignedProcesses = reply->count;
>> +            process->NumberOfProcessIdsInList = min(count, reply->count);
>> +        }
>> +        SERVER_END_REQ;
>> +
>> +        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[0]))[i];
> 
>                     ULONG_PTR id = ((process_id_t *)(process->ProcessIdList))[i];
> looks simpler to understand to me.
> 
>> +                memcpy(&process->ProcessIdList[i], &id, sizeof(id));
> 
>                     process->ProcessIdList[i] = id;
> should work just fine.
> 
>> +            }
>> +        }
>> +
>> +        if (ret_len) *ret_len = (char*)(&process->ProcessIdList[process->NumberOfProcessIdsInList]) - (char*)process;
>> +        return count < process->NumberOfAssignedProcesses ? STATUS_MORE_ENTRIES : STATUS_SUCCESS;
>>       }
>>       case JobObjectExtendedLimitInformation:
>>       {
>> diff --git a/server/process.c b/server/process.c
>> index 0870de5..48e632a 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 data_size_t query_job_pids( struct job *job, data_size_t count, data_size_t maxcount, process_id_t *pids )
>> +{
>> +    struct process *process;
>> +    struct job *j;
>> +
>> +    LIST_FOR_EACH_ENTRY( j, &job->child_job_list, struct job, parent_job_entry )
>> +        count = query_job_pids( j, count, maxcount, pids );
>> +
>> +    LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
>> +    {
>> +        if (process->end_time) continue;
>> +        if (count < maxcount) pids[count] = process->id;
>> +        count++;
>> +    }
>> +
>> +    return count;
>> +}
>> +
>>   static void add_job_process( struct job *job, struct process *process )
>>   {
>>       struct job *j, *common_parent;
>> @@ -1741,6 +1759,22 @@ DECL_HANDLER(process_in_job)
>>       release_object( process );
>>   }
>>   
>> +/* get a list of the pids associated with the job */
>> +DECL_HANDLER(query_job_pids)
>> +{
>> +    struct job *job = get_job_obj( current->process, req->job, JOB_OBJECT_QUERY );
>> +    process_id_t *pids;
>> +    data_size_t len;
>> +
>> +    if (!job) return;
>> +
>> +    reply->count = query_job_pids( job, 0, 0, NULL );
> 
> Doesn't this just give you job->num_processes?
> 
>> +
>> +    len = min( get_reply_max_size(), reply->count * sizeof(*pids) );
>> +    if (len && ((pids = set_reply_data_size( len ))))
>> +        query_job_pids( job, 0, len / sizeof(*pids), pids );
>> +}
>> +
>>   /* retrieve information about a job */
>>   DECL_HANDLER(get_job_info)
>>   {
>> diff --git a/server/protocol.def b/server/protocol.def
>> index 133d6ad..5d97cb5 100644
>> --- a/server/protocol.def
>> +++ b/server/protocol.def
>> @@ -3671,6 +3671,15 @@ struct handle_info
>>   @END
>>   
>>   
>> +/* Query a list of pids associated with the job */
>> + at REQ(query_job_pids)
>> +    obj_handle_t job;             /* handle to the job */
>> + at REPLY
>> +    data_size_t count;            /* number of processes associated with the job */
>> +    VARARG(pids,uints);           /* list of pids */
>> + at END
>> +
> 
> Rather than introduce a new request, couldn't you extend the
> get_job_info request?
> 
> Huw.
> 

Hi Huw,

Thanks for the review. Indeed, I'm not very familiar with server code, I 
was worried for nothing that num_processes didn't include only the 
active processes, but you are absolutely right, I see it now in 
get_job_info—and extending it makes the code even simpler.

I'll send a new simpler version addressing all points.

Thanks,
Gabriel



More information about the wine-devel mailing list