[PATCH] ntdll: Implement JobObjectBasicProcessIdList for NtQueryInformationJobObject.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Mar 5 07:52:25 CST 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/kernel32/tests/process.c |  9 ---------
 dlls/ntdll/sync.c             | 34 +++++++++++++++++++++++++++++++---
 server/process.c              | 23 +++++++++++++++++++++++
 server/protocol.def           |  9 +++++++++
 4 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index b5ed990..6c29db3 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2606,15 +2606,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);
     }
 
@@ -2629,17 +2625,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/sync.c b/dlls/ntdll/sync.c
index 2b5b6ce..4a889eb 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -694,7 +694,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( "%p %u %p %u %p\n", handle, class, info, len, ret_len );
 
     if (class >= MaxJobObjectInfoClass)
         return STATUS_INVALID_PARAMETER;
@@ -707,6 +709,7 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
             if (len < sizeof(*accounting))
                 return STATUS_INFO_LENGTH_MISMATCH;
 
+            FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
             accounting = (JOBOBJECT_BASIC_ACCOUNTING_INFORMATION *)info;
             memset(accounting, 0, sizeof(*accounting));
             if (ret_len) *ret_len = sizeof(*accounting);
@@ -716,12 +719,34 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
     case JobObjectBasicProcessIdList:
         {
             JOBOBJECT_BASIC_PROCESS_ID_LIST *process;
+            DWORD count, i;
+
             if (len < sizeof(*process))
                 return STATUS_INFO_LENGTH_MISMATCH;
 
             process = (JOBOBJECT_BASIC_PROCESS_ID_LIST *)info;
-            memset(process, 0, sizeof(*process));
-            if (ret_len) *ret_len = sizeof(*process);
+            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, count * sizeof(process_id_t));
+                if ((ret = wine_server_call(req)) != STATUS_SUCCESS)
+                    return ret;
+                if (count < reply->count)
+                    return STATUS_MORE_ENTRIES;
+                count = reply->count;
+            }
+            SERVER_END_REQ;
+
+            /* start from the end to not overwrite */
+            for (i = count; i--;)
+                process->ProcessIdList[i] = ((process_id_t*)process)[i];
+            process->NumberOfAssignedProcesses = count;
+            process->NumberOfProcessIdsInList = count;
+
+            if (ret_len) *ret_len = (char*)(&process->ProcessIdList[count]) - (char*)process;
             return STATUS_SUCCESS;
         }
 
@@ -731,6 +756,7 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
             if (len < sizeof(*extended_limit))
                 return STATUS_INFO_LENGTH_MISMATCH;
 
+            FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
             extended_limit = (JOBOBJECT_EXTENDED_LIMIT_INFORMATION *)info;
             memset(extended_limit, 0, sizeof(*extended_limit));
             if (ret_len) *ret_len = sizeof(*extended_limit);
@@ -743,6 +769,7 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
             if (len < sizeof(*basic_limit))
                 return STATUS_INFO_LENGTH_MISMATCH;
 
+            FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
             basic_limit = (JOBOBJECT_BASIC_LIMIT_INFORMATION *)info;
             memset(basic_limit, 0, sizeof(*basic_limit));
             if (ret_len) *ret_len = sizeof(*basic_limit);
@@ -750,6 +777,7 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
         }
 
     default:
+        FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
         return STATUS_NOT_IMPLEMENTED;
     }
 }
diff --git a/server/process.c b/server/process.c
index 73984f3..46a61d0 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1715,6 +1715,29 @@ 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 );
+    struct process *process;
+    process_id_t *data;
+    data_size_t len;
+
+    if (!job) return;
+
+    reply->count = job->num_processes;
+    len = min( get_reply_max_size(), job->num_processes * sizeof(*data) );
+    if (len && ((data = set_reply_data_size( len ))))
+    {
+        process_id_t *end = data + len;
+        LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
+        {
+            if (data >= end) break;
+            *data++ = process->id;
+        }
+    }
+}
+
 /* terminate all processes associated with the job */
 DECL_HANDLER(terminate_job)
 {
diff --git a/server/protocol.def b/server/protocol.def
index 6c44b2b..8beda28 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3924,6 +3924,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
+
+
 /* Set limit flags on a job */
 @REQ(set_job_limits)
     obj_handle_t handle;          /* handle to the job */
-- 
2.21.0




More information about the wine-devel mailing list