From: Etaash Mathamsetty etaash.mathamsetty@gmail.com
--- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/unix/process.c | 28 ++++++++++++++++++++++++++ dlls/wow64/process.c | 21 ++++++++++++++++++++ include/winternl.h | 1 + server/process.c | 41 +++++++++++++++++++++++++++++++++++++++ server/protocol.def | 9 +++++++++ 6 files changed, 101 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1908a089d44..3644c666fce 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -230,6 +230,7 @@ @ stdcall -norelay -syscall NtGetContextThread(long ptr) @ stdcall -syscall NtGetCurrentProcessorNumber() # @ stub NtGetDevicePowerState +@ stdcall -syscall NtGetNextProcess(ptr long long long ptr) @ stdcall -syscall NtGetNextThread(ptr ptr long long long ptr) @ stdcall -syscall NtGetNlsSectionPtr(long long long ptr ptr) # @ stub NtGetPlugPlayEvent diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 71eab55920d..fb82a0a622c 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -1768,6 +1768,34 @@ NTSTATUS WINAPI NtResumeProcess( HANDLE handle ) return ret; }
+/********************************************************************** + * NtGetNextProcess (NTDLL.@) + */ +NTSTATUS WINAPI NtGetNextProcess( HANDLE process, ACCESS_MASK access, ULONG attributes, + ULONG flags, HANDLE *handle ) +{ + unsigned int ret; + HANDLE ret_handle; + + TRACE( "process %p, access %#x, attributes %#x, flags %#x, handle %p.\n", + process, (int)access, (int)attributes, (int)flags, handle ); + + + SERVER_START_REQ( get_next_process ) + { + req->last = wine_server_obj_handle( process ); + req->access = access; + req->attributes = attributes; + req->flags = flags; + if (!(ret = wine_server_call( req ))) ret_handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + *handle = ret_handle; + return ret; +} + +
/********************************************************************** * NtDebugActiveProcess (NTDLL.@) diff --git a/dlls/wow64/process.c b/dlls/wow64/process.c index 817926d0f13..6fe997bb0b4 100644 --- a/dlls/wow64/process.c +++ b/dlls/wow64/process.c @@ -435,6 +435,27 @@ NTSTATUS WINAPI wow64_NtFlushProcessWriteBuffers( UINT *args ) }
+/********************************************************************** + * wow64_NtGetNextProcess + */ +NTSTATUS WINAPI wow64_NtGetNextProcess( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ACCESS_MASK access = get_ulong( &args ); + ULONG attributes = get_ulong( &args ); + ULONG flags = get_ulong( &args ); + ULONG *handle_ptr = get_ptr( &args ); + + HANDLE handle = 0; + NTSTATUS status; + + *handle_ptr = 0; + status = NtGetNextProcess( process, access, attributes, flags, &handle ); + put_handle( handle_ptr, handle ); + return status; +} + + /********************************************************************** * wow64_NtGetNextThread */ diff --git a/include/winternl.h b/include/winternl.h index ff8756211a1..ab79940e8e7 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4411,6 +4411,7 @@ NTSYSAPI NTSTATUS WINAPI NtFreeVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); NTSYSAPI NTSTATUS WINAPI NtFsControlFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,PVOID,ULONG,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtGetContextThread(HANDLE,CONTEXT*); NTSYSAPI ULONG WINAPI NtGetCurrentProcessorNumber(void); +NTSYSAPI NTSTATUS WINAPI NtGetNextProcess(HANDLE,ACCESS_MASK,ULONG,ULONG,HANDLE*); NTSYSAPI NTSTATUS WINAPI NtGetNextThread(HANDLE,HANDLE,ACCESS_MASK,ULONG,ULONG,HANDLE*); NTSYSAPI NTSTATUS WINAPI NtGetNlsSectionPtr(ULONG,ULONG,void*,void**,SIZE_T*); NTSYSAPI NTSTATUS WINAPI NtGetPlugPlayEvent(ULONG,ULONG,PVOID,ULONG); diff --git a/server/process.c b/server/process.c index a0d5ea64d97..f19e87a7a46 100644 --- a/server/process.c +++ b/server/process.c @@ -1390,6 +1390,47 @@ DECL_HANDLER(get_new_process_info) } }
+/* Itererate processes using global process list */ +DECL_HANDLER(get_next_process) +{ + struct process *process = NULL; + struct list *ptr; + + 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_id( req->last ))) + return; + ptr = req->flags ? list_prev( &process_list, &process->entry ) + : list_next( &process_list, &process->entry ); + release_object( process ); + } + + while (ptr) + { + process = LIST_ENTRY( ptr, struct process, entry ); + if ((reply->handle = alloc_handle( current->process, process, req->access, req->attributes ))) + break; + ptr = req->flags ? list_prev( &process_list, &process->entry ) + : list_next( &process_list, &process->entry ); + } + + if (!reply->handle) + set_error( STATUS_NO_MORE_ENTRIES ); + + if (process) + release_object( process ); +} + /* Retrieve the new process startup info */ DECL_HANDLER(get_startup_info) { diff --git a/server/protocol.def b/server/protocol.def index 5d60e7fcda3..267ca60182c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3873,6 +3873,15 @@ struct handle_info obj_handle_t handle; /* process handle */ @END
+/* Itererate processes using global process list */ +@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 */ +@REPLY + obj_handle_t handle; /* next process handle */ +@END
/* Iterate thread list for process */ @REQ(get_next_thread)