[PATCH] ntdll: Implement NtGetNextProcess().
Nikolay Sivov
nsivov at codeweavers.com
Fri Oct 2 08:05:49 CDT 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45119
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/tests/om.c | 28 +++++++++++++++++++++++
dlls/ntdll/unix/process.c | 20 +++++++++++++++++
include/wine/server_protocol.h | 23 ++++++++++++++++++-
server/process.c | 41 ++++++++++++++++++++++++++++++++++
server/protocol.def | 11 +++++++++
server/request.h | 9 ++++++++
server/trace.c | 16 +++++++++++++
8 files changed, 148 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index ce9f6281d5d..701fab0ade8 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -222,6 +222,7 @@
@ stdcall -norelay -syscall NtGetContextThread(long ptr)
@ stdcall -syscall NtGetCurrentProcessorNumber()
# @ stub NtGetDevicePowerState
+@ stdcall -syscall NtGetNextProcess(long long long long ptr)
@ stdcall NtGetNlsSectionPtr(long long long ptr ptr)
@ stub NtGetPlugPlayEvent
@ stdcall NtGetTickCount()
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index d3b932bec1d..6c43ee27823 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -73,6 +73,7 @@ static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
static void (WINAPI *pRtlWakeAddressAll)( const void * );
static void (WINAPI *pRtlWakeAddressSingle)( const void * );
+static NTSTATUS (WINAPI *pNtGetNextProcess)(HANDLE process, ACCESS_MASK access, ULONG attributes, ULONG flags, HANDLE *handle);
#define KEYEDEVENT_WAIT 0x0001
#define KEYEDEVENT_WAKE 0x0002
@@ -2034,6 +2035,31 @@ static void test_wait_on_address(void)
ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
}
+static void test_get_next_process(void)
+{
+ NTSTATUS status;
+ HANDLE handle;
+
+ if (!pNtGetNextProcess)
+ {
+ win_skip("NtGetNextProcess is not available.\n");
+ return;
+ }
+
+ status = pNtGetNextProcess(0, PROCESS_QUERY_LIMITED_INFORMATION, OBJ_INHERIT, 0, &handle);
+ ok(!status, "Unexpected status %#x.\n", status);
+ pNtClose(handle);
+
+ /* Reversed search only supported in recent enough Win10 */
+ status = pNtGetNextProcess(0, PROCESS_QUERY_LIMITED_INFORMATION, OBJ_INHERIT, 1, &handle);
+ ok(!status || broken(status == STATUS_INVALID_PARAMETER), "Unexpected status %#x.\n", status);
+ if (status)
+ pNtClose(handle);
+
+ status = pNtGetNextProcess(0, PROCESS_QUERY_LIMITED_INFORMATION, OBJ_INHERIT, 2, &handle);
+ ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#x.\n", status);
+}
+
START_TEST(om)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -2082,6 +2108,7 @@ START_TEST(om)
pRtlWaitOnAddress = (void *)GetProcAddress(hntdll, "RtlWaitOnAddress");
pRtlWakeAddressAll = (void *)GetProcAddress(hntdll, "RtlWakeAddressAll");
pRtlWakeAddressSingle = (void *)GetProcAddress(hntdll, "RtlWakeAddressSingle");
+ pNtGetNextProcess = (void *)GetProcAddress(hntdll, "NtGetNextProcess");
test_case_sensitive();
test_namespace_pipe();
@@ -2096,4 +2123,5 @@ START_TEST(om)
test_keyed_events();
test_null_device();
test_wait_on_address();
+ test_get_next_process();
}
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c
index 5ccf435e9ff..b0f7fa88d34 100644
--- a/dlls/ntdll/unix/process.c
+++ b/dlls/ntdll/unix/process.c
@@ -1743,6 +1743,26 @@ NTSTATUS WINAPI NtResumeProcess( HANDLE handle )
return ret;
}
+/**********************************************************************
+ * NtGetNextProcess (NTDLL.@)
+ */
+NTSTATUS WINAPI NtGetNextProcess( HANDLE process, ACCESS_MASK access, ULONG attributes,
+ ULONG flags, HANDLE *handle )
+{
+ NTSTATUS ret;
+
+ SERVER_START_REQ( get_next_process )
+ {
+ req->last = wine_server_obj_handle( process );
+ req->access = access;
+ req->attributes = attributes;
+ req->flags = flags;
+ ret = wine_server_call( req );
+ if (!ret) *handle = wine_server_ptr_handle( reply->handle );
+ }
+ SERVER_END_REQ;
+ return ret;
+}
/***********************************************************************
* __wine_make_process_system (NTDLL.@)
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index ea62e73f63c..70aa8839314 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -5441,6 +5441,24 @@ struct resume_process_reply
};
+
+struct get_next_process_request
+{
+ struct request_header __header;
+ obj_handle_t last;
+ unsigned int access;
+ unsigned int attributes;
+ unsigned int flags;
+ char __pad_28[4];
+};
+struct get_next_process_reply
+{
+ struct reply_header __header;
+ obj_handle_t handle;
+ char __pad_12[4];
+};
+
+
enum request
{
REQ_new_process,
@@ -5724,6 +5742,7 @@ enum request
REQ_terminate_job,
REQ_suspend_process,
REQ_resume_process,
+ REQ_get_next_process,
REQ_NB_REQUESTS
};
@@ -6012,6 +6031,7 @@ union generic_request
struct terminate_job_request terminate_job_request;
struct suspend_process_request suspend_process_request;
struct resume_process_request resume_process_request;
+ struct get_next_process_request get_next_process_request;
};
union generic_reply
{
@@ -6298,11 +6318,12 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
struct suspend_process_reply suspend_process_reply;
struct resume_process_reply resume_process_reply;
+ struct get_next_process_reply get_next_process_reply;
};
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 647
+#define SERVER_PROTOCOL_VERSION 648
/* ### protocol_version end ### */
diff --git a/server/process.c b/server/process.c
index 1786493a814..ced638ec966 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1829,6 +1829,47 @@ DECL_HANDLER(resume_process)
}
}
+/* Iterate process list */
+DECL_HANDLER(get_next_process)
+{
+ struct process *process = NULL, *next;
+ struct list *ptr;
+
+ reply->handle = 0;
+
+ if ( req->flags > 1 )
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (!req->last)
+ {
+ ptr = req->flags ? list_tail( &process_list ) : list_head( &process_list );
+ }
+ else if ((process = get_process_from_handle( req->last, 0 )))
+ {
+ ptr = req->flags ? list_prev( &process_list, &process->entry ) :
+ list_next( &process_list, &process->entry );
+ }
+ else
+ return;
+
+ while (ptr)
+ {
+ next = LIST_ENTRY( ptr, struct process, entry );
+ if ((reply->handle = alloc_handle( current->process, next, req->access, req->attributes )))
+ break;
+ ptr = req->flags ? list_prev( &process_list, &next->entry ) : list_next( &process_list, &next->entry );
+ }
+
+ if (!reply->handle)
+ set_error( STATUS_NO_MORE_ENTRIES );
+
+ if (process)
+ release_object( process );
+}
+
/* Get a list of processes and threads currently running */
DECL_HANDLER(list_processes)
{
diff --git a/server/protocol.def b/server/protocol.def
index f538c6dcf51..81ce88cca82 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3703,3 +3703,14 @@ struct handle_info
@REQ(resume_process)
obj_handle_t handle; /* process handle */
@END
+
+
+/* Iterate process list */
+ at REQ(get_next_process)
+ obj_handle_t last; /* process handle to start with */
+ unsigned int access; /* desired access for returned handle */
+ unsigned int attributes; /* returned handle attributes */
+ unsigned int flags; /* controls iteration direction */
+ at REPLY
+ obj_handle_t handle; /* next process handle */
+ at END
diff --git a/server/request.h b/server/request.h
index bc6f29f2110..26fc80dc5d6 100644
--- a/server/request.h
+++ b/server/request.h
@@ -400,6 +400,7 @@ DECL_HANDLER(get_job_info);
DECL_HANDLER(terminate_job);
DECL_HANDLER(suspend_process);
DECL_HANDLER(resume_process);
+DECL_HANDLER(get_next_process);
#ifdef WANT_REQUEST_HANDLERS
@@ -687,6 +688,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_terminate_job,
(req_handler)req_suspend_process,
(req_handler)req_resume_process,
+ (req_handler)req_get_next_process,
};
C_ASSERT( sizeof(abstime_t) == 8 );
@@ -2280,6 +2282,13 @@ C_ASSERT( FIELD_OFFSET(struct suspend_process_request, handle) == 12 );
C_ASSERT( sizeof(struct suspend_process_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct resume_process_request, handle) == 12 );
C_ASSERT( sizeof(struct resume_process_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_next_process_request, last) == 12 );
+C_ASSERT( FIELD_OFFSET(struct get_next_process_request, access) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_next_process_request, attributes) == 20 );
+C_ASSERT( FIELD_OFFSET(struct get_next_process_request, flags) == 24 );
+C_ASSERT( sizeof(struct get_next_process_request) == 32 );
+C_ASSERT( FIELD_OFFSET(struct get_next_process_reply, handle) == 8 );
+C_ASSERT( sizeof(struct get_next_process_reply) == 16 );
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/trace.c b/server/trace.c
index ffe9d6e19c6..092cc8e94f8 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -4424,6 +4424,19 @@ static void dump_resume_process_request( const struct resume_process_request *re
fprintf( stderr, " handle=%04x", req->handle );
}
+static void dump_get_next_process_request( const struct get_next_process_request *req )
+{
+ fprintf( stderr, " last=%04x", req->last );
+ fprintf( stderr, ", access=%08x", req->access );
+ fprintf( stderr, ", attributes=%08x", req->attributes );
+ fprintf( stderr, ", flags=%08x", req->flags );
+}
+
+static void dump_get_next_process_reply( const struct get_next_process_reply *req )
+{
+ fprintf( stderr, " handle=%04x", req->handle );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_exec_process_request,
@@ -4706,6 +4719,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_terminate_job_request,
(dump_func)dump_suspend_process_request,
(dump_func)dump_resume_process_request,
+ (dump_func)dump_get_next_process_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -4990,6 +5004,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
NULL,
NULL,
+ (dump_func)dump_get_next_process_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -5274,6 +5289,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"terminate_job",
"suspend_process",
"resume_process",
+ "get_next_process",
};
static const struct
--
2.28.0
More information about the wine-devel
mailing list