From: "Rémi Bernon" Subject: [PATCH 2/2] ntdll: Correctly implement ThreadHideFromDebugger. Message-Id: <20200626092729.720672-2-rbernon@codeweavers.com> Date: Fri, 26 Jun 2020 11:27:29 +0200 In-Reply-To: <20200626092729.720672-1-rbernon@codeweavers.com> References: <20200626092729.720672-1-rbernon@codeweavers.com> At least, store the thread information, instead of pretending and failing to correctly validate handles and access rights. Signed-off-by: Rémi Bernon --- dlls/ntdll/tests/info.c | 3 --- dlls/ntdll/unix/thread.c | 22 +++++++++++++++++----- server/protocol.def | 3 +++ server/thread.c | 8 +++++++- server/thread.h | 1 + 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index b91d54375ce..aae729dccff 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2498,18 +2498,15 @@ static void test_HideFromDebugger(void) dummy = 0; status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL ); - todo_wine ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_SUCCESS, got %08x\n", status ); if (status == STATUS_SUCCESS) ok( dummy == 0, "Expected dummy == 0, got %08x\n", dummy ); status = pNtSetInformationThread( thread, ThreadHideFromDebugger, NULL, 0 ); - todo_wine ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status ); dummy = 0; status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL ); - todo_wine ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_SUCCESS, got %08x\n", status ); if (status == STATUS_SUCCESS) ok( dummy == 1, "Expected dummy == 1, got %08x\n", dummy ); diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index f3dddd2b02a..8463119a5ed 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1067,8 +1067,15 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, case ThreadHideFromDebugger: if (length != sizeof(BOOLEAN)) return STATUS_INFO_LENGTH_MISMATCH; if (!data) return STATUS_ACCESS_VIOLATION; - if (handle != GetCurrentThread()) return STATUS_ACCESS_DENIED; - *(BOOLEAN*)data = TRUE; + SERVER_START_REQ( get_thread_info ) + { + req->handle = wine_server_obj_handle( handle ); + req->tid_in = 0; + req->access = THREAD_QUERY_INFORMATION; + if ((status = wine_server_call( req ))) return status; + *(BOOLEAN*)data = reply->dbg_hidden; + } + SERVER_END_REQ; if (ret_len) *ret_len = sizeof(BOOLEAN); return STATUS_SUCCESS; @@ -1164,9 +1171,14 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class, case ThreadHideFromDebugger: if (length) return STATUS_INFO_LENGTH_MISMATCH; - if (handle != GetCurrentThread()) return STATUS_INVALID_HANDLE; - /* pretend the call succeeded to satisfy some code protectors */ - return STATUS_SUCCESS; + SERVER_START_REQ( set_thread_info ) + { + req->handle = wine_server_obj_handle( handle ); + req->mask = SET_THREAD_INFO_DBG_HIDDEN; + status = wine_server_call( req ); + } + SERVER_END_REQ; + return status; case ThreadQuerySetWin32StartAddress: { diff --git a/server/protocol.def b/server/protocol.def index c3442c06e9b..ff2f3ed31ab 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -946,6 +946,7 @@ struct rawinput_device @REQ(get_thread_info) obj_handle_t handle; /* thread handle */ thread_id_t tid_in; /* thread id (optional) */ + unsigned int access; /* required access rights */ @REPLY process_id_t pid; /* server process id */ thread_id_t tid; /* server thread id */ @@ -956,6 +957,7 @@ struct rawinput_device int priority; /* thread priority level */ int last; /* last thread in process */ int suspend_count; /* thread suspend count */ + int dbg_hidden; /* thread hidden from debugger */ data_size_t desc_len; /* description length in bytes */ VARARG(desc,unicode_str); /* description string */ @END @@ -985,6 +987,7 @@ struct rawinput_device #define SET_THREAD_INFO_TOKEN 0x04 #define SET_THREAD_INFO_ENTRYPOINT 0x08 #define SET_THREAD_INFO_DESCRIPTION 0x10 +#define SET_THREAD_INFO_DBG_HIDDEN 0x20 /* Retrieve information about a module */ diff --git a/server/thread.c b/server/thread.c index e2bfa50c7ba..eb287d74184 100644 --- a/server/thread.c +++ b/server/thread.c @@ -234,6 +234,7 @@ static inline void init_thread_structure( struct thread *thread ) thread->exit_code = 0; thread->priority = 0; thread->suspend = 0; + thread->dbg_hidden = 0; thread->desktop_users = 0; thread->token = NULL; thread->desc = NULL; @@ -624,6 +625,8 @@ static void set_thread_info( struct thread *thread, security_set_thread_token( thread, req->token ); if (req->mask & SET_THREAD_INFO_ENTRYPOINT) thread->entry_point = req->entry_point; + if (req->mask & SET_THREAD_INFO_DBG_HIDDEN) + thread->dbg_hidden = 1; if (req->mask & SET_THREAD_INFO_DESCRIPTION) { WCHAR *desc; @@ -1516,9 +1519,11 @@ DECL_HANDLER(get_thread_info) { struct thread *thread; obj_handle_t handle = req->handle; + unsigned int access = req->access; + if (!access) access = THREAD_QUERY_LIMITED_INFORMATION; if (!handle) thread = get_thread_from_id( req->tid_in ); - else thread = get_thread_from_handle( req->handle, THREAD_QUERY_LIMITED_INFORMATION ); + else thread = get_thread_from_handle( req->handle, access ); if (thread) { @@ -1531,6 +1536,7 @@ DECL_HANDLER(get_thread_info) reply->affinity = thread->affinity; reply->last = thread->process->running_threads == 1; reply->suspend_count = thread->suspend; + reply->dbg_hidden = thread->dbg_hidden; reply->desc_len = thread->desc_len; if (thread->desc && get_reply_max_size()) diff --git a/server/thread.h b/server/thread.h index 5d12d24dd89..183f6baa0f2 100644 --- a/server/thread.h +++ b/server/thread.h @@ -82,6 +82,7 @@ struct thread affinity_t affinity; /* affinity mask */ int priority; /* priority level */ int suspend; /* suspend count */ + int dbg_hidden; /* hidden from debugger */ obj_handle_t desktop; /* desktop handle */ int desktop_users; /* number of objects using the thread desktop */ timeout_t creation_time; /* Thread creation time */ -- 2.27.0