[PATCH 2/2] ntdll: Correctly implement ThreadHideFromDebugger.
Rémi Bernon
rbernon at codeweavers.com
Fri Jun 26 04:27:29 CDT 2020
At least, store the thread information, instead of pretending and
failing to correctly validate handles and access rights.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
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
More information about the wine-devel
mailing list