ntdll: Correctly implement ThreadHideFromDebugger.
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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eef527723f
commit
e1e34cdc37
|
@ -2498,18 +2498,15 @@ static void test_HideFromDebugger(void)
|
||||||
|
|
||||||
dummy = 0;
|
dummy = 0;
|
||||||
status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
|
status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
|
||||||
todo_wine
|
|
||||||
ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
|
ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
|
||||||
"Expected STATUS_SUCCESS, got %08x\n", status );
|
"Expected STATUS_SUCCESS, got %08x\n", status );
|
||||||
if (status == STATUS_SUCCESS) ok( dummy == 0, "Expected dummy == 0, got %08x\n", dummy );
|
if (status == STATUS_SUCCESS) ok( dummy == 0, "Expected dummy == 0, got %08x\n", dummy );
|
||||||
|
|
||||||
status = pNtSetInformationThread( thread, ThreadHideFromDebugger, NULL, 0 );
|
status = pNtSetInformationThread( thread, ThreadHideFromDebugger, NULL, 0 );
|
||||||
todo_wine
|
|
||||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
|
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
|
||||||
|
|
||||||
dummy = 0;
|
dummy = 0;
|
||||||
status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
|
status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
|
||||||
todo_wine
|
|
||||||
ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
|
ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
|
||||||
"Expected STATUS_SUCCESS, got %08x\n", status );
|
"Expected STATUS_SUCCESS, got %08x\n", status );
|
||||||
if (status == STATUS_SUCCESS) ok( dummy == 1, "Expected dummy == 1, got %08x\n", dummy );
|
if (status == STATUS_SUCCESS) ok( dummy == 1, "Expected dummy == 1, got %08x\n", dummy );
|
||||||
|
|
|
@ -867,7 +867,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
if (!(status = wine_server_call( req )))
|
if (!(status = wine_server_call( req )))
|
||||||
{
|
{
|
||||||
info.ExitStatus = reply->exit_code;
|
info.ExitStatus = reply->exit_code;
|
||||||
|
@ -896,7 +895,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
if (!(status = wine_server_call( req ))) affinity = reply->affinity & affinity_mask;
|
if (!(status = wine_server_call( req ))) affinity = reply->affinity & affinity_mask;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -958,7 +956,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -976,7 +973,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -1000,7 +996,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
if (!(status = wine_server_call( req ))) affinity.Mask = reply->affinity & affinity_mask;
|
if (!(status = wine_server_call( req ))) affinity.Mask = reply->affinity & affinity_mask;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -1027,7 +1022,6 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
SERVER_START_REQ( get_thread_info )
|
SERVER_START_REQ( get_thread_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->tid_in = 0;
|
|
||||||
if (!(status = wine_server_call( req ))) *(ULONG *)data = reply->suspend_count;
|
if (!(status = wine_server_call( req ))) *(ULONG *)data = reply->suspend_count;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -1086,8 +1080,14 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
case ThreadHideFromDebugger:
|
case ThreadHideFromDebugger:
|
||||||
if (length != sizeof(BOOLEAN)) return STATUS_INFO_LENGTH_MISMATCH;
|
if (length != sizeof(BOOLEAN)) return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
if (!data) return STATUS_ACCESS_VIOLATION;
|
if (!data) return STATUS_ACCESS_VIOLATION;
|
||||||
if (handle != GetCurrentThread()) return STATUS_ACCESS_DENIED;
|
SERVER_START_REQ( get_thread_info )
|
||||||
*(BOOLEAN*)data = TRUE;
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
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);
|
if (ret_len) *ret_len = sizeof(BOOLEAN);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -1183,9 +1183,14 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
|
|
||||||
case ThreadHideFromDebugger:
|
case ThreadHideFromDebugger:
|
||||||
if (length) return STATUS_INFO_LENGTH_MISMATCH;
|
if (length) return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
if (handle != GetCurrentThread()) return STATUS_INVALID_HANDLE;
|
SERVER_START_REQ( set_thread_info )
|
||||||
/* pretend the call succeeded to satisfy some code protectors */
|
{
|
||||||
return STATUS_SUCCESS;
|
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:
|
case ThreadQuerySetWin32StartAddress:
|
||||||
{
|
{
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ struct get_thread_info_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
obj_handle_t handle;
|
obj_handle_t handle;
|
||||||
thread_id_t tid_in;
|
unsigned int access;
|
||||||
char __pad_20[4];
|
char __pad_20[4];
|
||||||
};
|
};
|
||||||
struct get_thread_info_reply
|
struct get_thread_info_reply
|
||||||
|
@ -1020,9 +1020,9 @@ struct get_thread_info_reply
|
||||||
int priority;
|
int priority;
|
||||||
int last;
|
int last;
|
||||||
int suspend_count;
|
int suspend_count;
|
||||||
|
int dbg_hidden;
|
||||||
data_size_t desc_len;
|
data_size_t desc_len;
|
||||||
/* VARARG(desc,unicode_str); */
|
/* VARARG(desc,unicode_str); */
|
||||||
char __pad_60[4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1064,6 +1064,7 @@ struct set_thread_info_reply
|
||||||
#define SET_THREAD_INFO_TOKEN 0x04
|
#define SET_THREAD_INFO_TOKEN 0x04
|
||||||
#define SET_THREAD_INFO_ENTRYPOINT 0x08
|
#define SET_THREAD_INFO_ENTRYPOINT 0x08
|
||||||
#define SET_THREAD_INFO_DESCRIPTION 0x10
|
#define SET_THREAD_INFO_DESCRIPTION 0x10
|
||||||
|
#define SET_THREAD_INFO_DBG_HIDDEN 0x20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6702,7 +6703,7 @@ union generic_reply
|
||||||
|
|
||||||
/* ### protocol_version begin ### */
|
/* ### protocol_version begin ### */
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 611
|
#define SERVER_PROTOCOL_VERSION 612
|
||||||
|
|
||||||
/* ### protocol_version end ### */
|
/* ### protocol_version end ### */
|
||||||
|
|
||||||
|
|
|
@ -945,7 +945,7 @@ struct rawinput_device
|
||||||
/* Retrieve information about a thread */
|
/* Retrieve information about a thread */
|
||||||
@REQ(get_thread_info)
|
@REQ(get_thread_info)
|
||||||
obj_handle_t handle; /* thread handle */
|
obj_handle_t handle; /* thread handle */
|
||||||
thread_id_t tid_in; /* thread id (optional) */
|
unsigned int access; /* required access rights */
|
||||||
@REPLY
|
@REPLY
|
||||||
process_id_t pid; /* server process id */
|
process_id_t pid; /* server process id */
|
||||||
thread_id_t tid; /* server thread id */
|
thread_id_t tid; /* server thread id */
|
||||||
|
@ -956,6 +956,7 @@ struct rawinput_device
|
||||||
int priority; /* thread priority level */
|
int priority; /* thread priority level */
|
||||||
int last; /* last thread in process */
|
int last; /* last thread in process */
|
||||||
int suspend_count; /* thread suspend count */
|
int suspend_count; /* thread suspend count */
|
||||||
|
int dbg_hidden; /* thread hidden from debugger */
|
||||||
data_size_t desc_len; /* description length in bytes */
|
data_size_t desc_len; /* description length in bytes */
|
||||||
VARARG(desc,unicode_str); /* description string */
|
VARARG(desc,unicode_str); /* description string */
|
||||||
@END
|
@END
|
||||||
|
@ -987,6 +988,7 @@ struct rawinput_device
|
||||||
#define SET_THREAD_INFO_TOKEN 0x04
|
#define SET_THREAD_INFO_TOKEN 0x04
|
||||||
#define SET_THREAD_INFO_ENTRYPOINT 0x08
|
#define SET_THREAD_INFO_ENTRYPOINT 0x08
|
||||||
#define SET_THREAD_INFO_DESCRIPTION 0x10
|
#define SET_THREAD_INFO_DESCRIPTION 0x10
|
||||||
|
#define SET_THREAD_INFO_DBG_HIDDEN 0x20
|
||||||
|
|
||||||
|
|
||||||
/* Retrieve information about a module */
|
/* Retrieve information about a module */
|
||||||
|
|
|
@ -845,7 +845,7 @@ C_ASSERT( FIELD_OFFSET(struct set_process_info_request, priority) == 20 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, affinity) == 24 );
|
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, affinity) == 24 );
|
||||||
C_ASSERT( sizeof(struct set_process_info_request) == 32 );
|
C_ASSERT( sizeof(struct set_process_info_request) == 32 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, handle) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, tid_in) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, access) == 16 );
|
||||||
C_ASSERT( sizeof(struct get_thread_info_request) == 24 );
|
C_ASSERT( sizeof(struct get_thread_info_request) == 24 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, pid) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, pid) == 8 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, tid) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, tid) == 12 );
|
||||||
|
@ -856,7 +856,8 @@ C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, exit_code) == 40 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, priority) == 44 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, priority) == 44 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, last) == 48 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, last) == 48 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, suspend_count) == 52 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, suspend_count) == 52 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_len) == 56 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, dbg_hidden) == 56 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_len) == 60 );
|
||||||
C_ASSERT( sizeof(struct get_thread_info_reply) == 64 );
|
C_ASSERT( sizeof(struct get_thread_info_reply) == 64 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_times_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_times_request, handle) == 12 );
|
||||||
C_ASSERT( sizeof(struct get_thread_times_request) == 16 );
|
C_ASSERT( sizeof(struct get_thread_times_request) == 16 );
|
||||||
|
|
|
@ -234,6 +234,7 @@ static inline void init_thread_structure( struct thread *thread )
|
||||||
thread->exit_code = 0;
|
thread->exit_code = 0;
|
||||||
thread->priority = 0;
|
thread->priority = 0;
|
||||||
thread->suspend = 0;
|
thread->suspend = 0;
|
||||||
|
thread->dbg_hidden = 0;
|
||||||
thread->desktop_users = 0;
|
thread->desktop_users = 0;
|
||||||
thread->token = NULL;
|
thread->token = NULL;
|
||||||
thread->desc = NULL;
|
thread->desc = NULL;
|
||||||
|
@ -624,6 +625,8 @@ static void set_thread_info( struct thread *thread,
|
||||||
security_set_thread_token( thread, req->token );
|
security_set_thread_token( thread, req->token );
|
||||||
if (req->mask & SET_THREAD_INFO_ENTRYPOINT)
|
if (req->mask & SET_THREAD_INFO_ENTRYPOINT)
|
||||||
thread->entry_point = req->entry_point;
|
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)
|
if (req->mask & SET_THREAD_INFO_DESCRIPTION)
|
||||||
{
|
{
|
||||||
WCHAR *desc;
|
WCHAR *desc;
|
||||||
|
@ -1515,11 +1518,10 @@ DECL_HANDLER(open_thread)
|
||||||
DECL_HANDLER(get_thread_info)
|
DECL_HANDLER(get_thread_info)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
obj_handle_t handle = req->handle;
|
unsigned int access = req->access & (THREAD_QUERY_INFORMATION | 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 );
|
|
||||||
|
|
||||||
|
if (!access) access = THREAD_QUERY_LIMITED_INFORMATION;
|
||||||
|
thread = get_thread_from_handle( req->handle, access );
|
||||||
if (thread)
|
if (thread)
|
||||||
{
|
{
|
||||||
reply->pid = get_process_id( thread->process );
|
reply->pid = get_process_id( thread->process );
|
||||||
|
@ -1531,6 +1533,7 @@ DECL_HANDLER(get_thread_info)
|
||||||
reply->affinity = thread->affinity;
|
reply->affinity = thread->affinity;
|
||||||
reply->last = thread->process->running_threads == 1;
|
reply->last = thread->process->running_threads == 1;
|
||||||
reply->suspend_count = thread->suspend;
|
reply->suspend_count = thread->suspend;
|
||||||
|
reply->dbg_hidden = thread->dbg_hidden;
|
||||||
reply->desc_len = thread->desc_len;
|
reply->desc_len = thread->desc_len;
|
||||||
|
|
||||||
if (thread->desc && get_reply_max_size())
|
if (thread->desc && get_reply_max_size())
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct thread
|
||||||
affinity_t affinity; /* affinity mask */
|
affinity_t affinity; /* affinity mask */
|
||||||
int priority; /* priority level */
|
int priority; /* priority level */
|
||||||
int suspend; /* suspend count */
|
int suspend; /* suspend count */
|
||||||
|
int dbg_hidden; /* hidden from debugger */
|
||||||
obj_handle_t desktop; /* desktop handle */
|
obj_handle_t desktop; /* desktop handle */
|
||||||
int desktop_users; /* number of objects using the thread desktop */
|
int desktop_users; /* number of objects using the thread desktop */
|
||||||
timeout_t creation_time; /* Thread creation time */
|
timeout_t creation_time; /* Thread creation time */
|
||||||
|
|
|
@ -1415,7 +1415,7 @@ static void dump_set_process_info_request( const struct set_process_info_request
|
||||||
static void dump_get_thread_info_request( const struct get_thread_info_request *req )
|
static void dump_get_thread_info_request( const struct get_thread_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%04x", req->handle );
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
fprintf( stderr, ", tid_in=%04x", req->tid_in );
|
fprintf( stderr, ", access=%08x", req->access );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_thread_info_reply( const struct get_thread_info_reply *req )
|
static void dump_get_thread_info_reply( const struct get_thread_info_reply *req )
|
||||||
|
@ -1429,6 +1429,7 @@ static void dump_get_thread_info_reply( const struct get_thread_info_reply *req
|
||||||
fprintf( stderr, ", priority=%d", req->priority );
|
fprintf( stderr, ", priority=%d", req->priority );
|
||||||
fprintf( stderr, ", last=%d", req->last );
|
fprintf( stderr, ", last=%d", req->last );
|
||||||
fprintf( stderr, ", suspend_count=%d", req->suspend_count );
|
fprintf( stderr, ", suspend_count=%d", req->suspend_count );
|
||||||
|
fprintf( stderr, ", dbg_hidden=%d", req->dbg_hidden );
|
||||||
fprintf( stderr, ", desc_len=%u", req->desc_len );
|
fprintf( stderr, ", desc_len=%u", req->desc_len );
|
||||||
dump_varargs_unicode_str( ", desc=", cur_size );
|
dump_varargs_unicode_str( ", desc=", cur_size );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue