ntdll: Implement NtQueryInformationThread(ThreadIsTerminated).
This commit is contained in:
parent
72590048b2
commit
4c9b39964c
8 changed files with 74 additions and 7 deletions
|
@ -3697,6 +3697,44 @@ static void test_debuggee_dbgport(int argc, char **argv)
|
||||||
winetest_pop_context();
|
winetest_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI test_ThreadIsTerminated_thread( void *stop_event )
|
||||||
|
{
|
||||||
|
WaitForSingleObject( stop_event, INFINITE );
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ThreadIsTerminated(void)
|
||||||
|
{
|
||||||
|
HANDLE thread, stop_event;
|
||||||
|
ULONG terminated;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||||
|
thread = CreateThread( NULL, 0, test_ThreadIsTerminated_thread, stop_event, 0, NULL );
|
||||||
|
ok( thread != INVALID_HANDLE_VALUE, "failed, error %ld\n", GetLastError() );
|
||||||
|
|
||||||
|
status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated) * 2, NULL );
|
||||||
|
ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx.\n", status );
|
||||||
|
|
||||||
|
terminated = 0xdeadbeef;
|
||||||
|
status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
ok( !terminated, "got %lu.\n", terminated );
|
||||||
|
|
||||||
|
SetEvent( stop_event );
|
||||||
|
WaitForSingleObject( thread, INFINITE );
|
||||||
|
|
||||||
|
status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
|
||||||
|
ok( !status, "got %#lx.\n", status );
|
||||||
|
ok( terminated == 1, "got %lu.\n", terminated );
|
||||||
|
|
||||||
|
CloseHandle(stop_event);
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
|
||||||
|
ok( status == STATUS_INVALID_HANDLE, "got %#lx.\n", status );
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(info)
|
START_TEST(info)
|
||||||
{
|
{
|
||||||
char **argv;
|
char **argv;
|
||||||
|
@ -3760,6 +3798,7 @@ START_TEST(info)
|
||||||
test_thread_start_address();
|
test_thread_start_address();
|
||||||
test_thread_lookup();
|
test_thread_lookup();
|
||||||
test_thread_ideal_processor();
|
test_thread_ideal_processor();
|
||||||
|
test_ThreadIsTerminated();
|
||||||
|
|
||||||
test_affinity();
|
test_affinity();
|
||||||
test_debug_object();
|
test_debug_object();
|
||||||
|
|
|
@ -2143,6 +2143,25 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
if (ret_len) *ret_len = sizeof(BOOL);
|
if (ret_len) *ret_len = sizeof(BOOL);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
case ThreadIsTerminated:
|
||||||
|
{
|
||||||
|
ULONG terminated;
|
||||||
|
|
||||||
|
if (length != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
SERVER_START_REQ( get_thread_info )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
if (!(status = wine_server_call( req ))) terminated = !!(reply->flags & GET_THREAD_INFO_FLAG_TERMINATED);
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
*(ULONG *)data = terminated;
|
||||||
|
if (ret_len) *ret_len = sizeof(ULONG);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
case ThreadSuspendCount:
|
case ThreadSuspendCount:
|
||||||
if (length != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
|
if (length != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
if (!data) return STATUS_ACCESS_VIOLATION;
|
if (!data) return STATUS_ACCESS_VIOLATION;
|
||||||
|
@ -2196,7 +2215,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->access = THREAD_QUERY_INFORMATION;
|
req->access = THREAD_QUERY_INFORMATION;
|
||||||
if ((status = wine_server_call( req ))) return status;
|
if ((status = wine_server_call( req ))) return status;
|
||||||
*(BOOLEAN*)data = reply->dbg_hidden;
|
*(BOOLEAN*)data = !!(reply->flags & GET_THREAD_INFO_FLAG_DBG_HIDDEN);
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
if (ret_len) *ret_len = sizeof(BOOLEAN);
|
if (ret_len) *ret_len = sizeof(BOOLEAN);
|
||||||
|
|
|
@ -688,6 +688,7 @@ NTSTATUS WINAPI wow64_NtQueryInformationThread( UINT *args )
|
||||||
case ThreadEnableAlignmentFaultFixup: /* set only */
|
case ThreadEnableAlignmentFaultFixup: /* set only */
|
||||||
case ThreadAmILastThread: /* ULONG */
|
case ThreadAmILastThread: /* ULONG */
|
||||||
case ThreadIsIoPending: /* ULONG */
|
case ThreadIsIoPending: /* ULONG */
|
||||||
|
case ThreadIsTerminated: /* ULONG */
|
||||||
case ThreadHideFromDebugger: /* BOOLEAN */
|
case ThreadHideFromDebugger: /* BOOLEAN */
|
||||||
case ThreadSuspendCount: /* ULONG */
|
case ThreadSuspendCount: /* ULONG */
|
||||||
case ThreadPriorityBoost: /* ULONG */
|
case ThreadPriorityBoost: /* ULONG */
|
||||||
|
|
|
@ -1162,10 +1162,12 @@ struct get_thread_info_reply
|
||||||
int priority;
|
int priority;
|
||||||
int last;
|
int last;
|
||||||
int suspend_count;
|
int suspend_count;
|
||||||
int dbg_hidden;
|
unsigned int flags;
|
||||||
data_size_t desc_len;
|
data_size_t desc_len;
|
||||||
/* VARARG(desc,unicode_str); */
|
/* VARARG(desc,unicode_str); */
|
||||||
};
|
};
|
||||||
|
#define GET_THREAD_INFO_FLAG_DBG_HIDDEN 0x01
|
||||||
|
#define GET_THREAD_INFO_FLAG_TERMINATED 0x02
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6504,7 +6506,7 @@ union generic_reply
|
||||||
|
|
||||||
/* ### protocol_version begin ### */
|
/* ### protocol_version begin ### */
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 784
|
#define SERVER_PROTOCOL_VERSION 785
|
||||||
|
|
||||||
/* ### protocol_version end ### */
|
/* ### protocol_version end ### */
|
||||||
|
|
||||||
|
|
|
@ -1085,10 +1085,12 @@ typedef struct
|
||||||
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 */
|
unsigned int flags; /* GET_THREAD_INFO_FLAG_ flags */
|
||||||
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
|
||||||
|
#define GET_THREAD_INFO_FLAG_DBG_HIDDEN 0x01
|
||||||
|
#define GET_THREAD_INFO_FLAG_TERMINATED 0x02
|
||||||
|
|
||||||
|
|
||||||
/* Retrieve information about thread times */
|
/* Retrieve information about thread times */
|
||||||
|
|
|
@ -860,7 +860,7 @@ 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, dbg_hidden) == 56 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, flags) == 56 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_len) == 60 );
|
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 );
|
||||||
|
|
|
@ -1496,8 +1496,12 @@ 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;
|
||||||
|
reply->flags = 0;
|
||||||
|
if (thread->dbg_hidden)
|
||||||
|
reply->flags |= GET_THREAD_INFO_FLAG_DBG_HIDDEN;
|
||||||
|
if (thread->state == TERMINATED)
|
||||||
|
reply->flags |= GET_THREAD_INFO_FLAG_TERMINATED;
|
||||||
|
|
||||||
if (thread->desc && get_reply_max_size())
|
if (thread->desc && get_reply_max_size())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1604,7 +1604,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, ", flags=%08x", req->flags );
|
||||||
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…
Add table
Reference in a new issue