Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45119 Signed-off-by: Nikolay Sivov nsivov@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 */ +@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 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
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79777
Your paranoid android.
=== debiant (build log) ===
error: patch failed: include/wine/server_protocol.h:6298 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: include/wine/server_protocol.h:6298 Task: Patch failed to apply