Gabriel Ivăncescu : ntdll: Implement JobObjectBasicProcessIdList for NtQueryInformationJobObject.

Alexandre Julliard julliard at winehq.org
Tue Sep 14 16:00:13 CDT 2021


Module: wine
Branch: master
Commit: 2fe70331d9df49708ec78f12ebff8406f0536881
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2fe70331d9df49708ec78f12ebff8406f0536881

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Tue Sep 14 16:07:38 2021 +0300

ntdll: Implement JobObjectBasicProcessIdList for NtQueryInformationJobObject.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/process.c  |  9 ---------
 dlls/ntdll/unix/sync.c         | 35 ++++++++++++++++++++++++++++++++---
 include/wine/server_protocol.h |  3 ++-
 server/process.c               | 25 +++++++++++++++++++++++++
 server/protocol.def            |  1 +
 server/trace.c                 |  1 +
 6 files changed, 61 insertions(+), 13 deletions(-)

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 )




More information about the wine-cvs mailing list