ntdll: Implement SystemExtendedProcessInformation system info class.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2021-10-25 21:46:21 +03:00 committed by Alexandre Julliard
parent bb6aa6c773
commit 98a5466380
6 changed files with 128 additions and 28 deletions

View File

@ -438,7 +438,7 @@ static void test_query_timeofday(void)
if (winetest_debug > 1) trace("uCurrentTimeZoneId : (%d)\n", sti.uCurrentTimeZoneId);
}
static void test_query_process(void)
static void test_query_process( BOOL extended )
{
NTSTATUS status;
DWORD last_pid;
@ -470,12 +470,27 @@ static void test_query_process(void)
SYSTEM_THREAD_INFORMATION ti[1];
} SYSTEM_PROCESS_INFORMATION_PRIVATE;
BOOL is_process_wow64 = FALSE, current_process_found = FALSE;
SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf;
BOOL current_process_found = FALSE;
SYSTEM_EXTENDED_THREAD_INFORMATION *ti;
SYSTEM_INFORMATION_CLASS info_class;
void *expected_address;
ULONG thread_info_size;
if (extended)
{
info_class = SystemExtendedProcessInformation;
thread_info_size = sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION);
}
else
{
info_class = SystemProcessInformation;
thread_info_size = sizeof(SYSTEM_THREAD_INFORMATION);
}
/* test ReturnLength */
ReturnLength = 0;
status = pNtQuerySystemInformation(SystemProcessInformation, NULL, 0, &ReturnLength);
status = pNtQuerySystemInformation( info_class, NULL, 0, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH got %08x\n", status);
ok( ReturnLength > 0, "got 0 length\n" );
@ -486,8 +501,10 @@ static void test_query_process(void)
return;
}
winetest_push_context( "extended %d", extended );
spi_buf = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
status = pNtQuerySystemInformation(SystemProcessInformation, spi_buf, ReturnLength, &ReturnLength);
status = pNtQuerySystemInformation(info_class, spi_buf, ReturnLength, &ReturnLength);
/* Sometimes new process or threads appear between the call and increase the size,
* otherwise the previously returned buffer size should be sufficient. */
@ -511,16 +528,67 @@ static void test_query_process(void)
if (last_pid == GetCurrentProcessId())
current_process_found = TRUE;
ok(!(last_pid & 3), "Unexpected PID low bits: %p\n", spi->UniqueProcessId);
if (extended && is_wow64 && spi->UniqueProcessId)
{
InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
cid.UniqueProcess = spi->UniqueProcessId;
cid.UniqueThread = 0;
status = NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, &attr, &cid );
ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
"Got unexpected status %#x, pid %p.\n", status, spi->UniqueProcessId );
if (!status)
{
ULONG_PTR info;
status = NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL );
ok( status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status );
is_process_wow64 = !!info;
NtClose( handle );
}
}
for (j = 0; j < spi->dwThreadCount; j++)
{
k++;
ok ( spi->ti[j].ClientId.UniqueProcess == spi->UniqueProcessId,
"The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
spi->ti[j].ClientId.UniqueProcess, spi->UniqueProcessId);
ti = (SYSTEM_EXTENDED_THREAD_INFORMATION *)((BYTE *)spi->ti + j * thread_info_size);
tid = (DWORD_PTR)spi->ti[j].ClientId.UniqueThread;
ok(!(tid & 3), "Unexpected TID low bits: %p\n", spi->ti[j].ClientId.UniqueThread);
k++;
ok ( ti->ThreadInfo.ClientId.UniqueProcess == spi->UniqueProcessId,
"The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
ti->ThreadInfo.ClientId.UniqueProcess, spi->UniqueProcessId );
tid = (DWORD_PTR)ti->ThreadInfo.ClientId.UniqueThread;
ok( !(tid & 3), "Unexpected TID low bits: %p\n", ti->ThreadInfo.ClientId.UniqueThread );
if (extended)
{
todo_wine ok( !!ti->StackBase, "Got NULL StackBase.\n" );
todo_wine ok( !!ti->StackLimit, "Got NULL StackLimit.\n" );
ok( !!ti->Win32StartAddress, "Got NULL Win32StartAddress.\n" );
cid.UniqueProcess = 0;
cid.UniqueThread = ti->ThreadInfo.ClientId.UniqueThread;
InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
status = NtOpenThread( &handle, THREAD_QUERY_INFORMATION, &attr, &cid );
if (!status)
{
THREAD_BASIC_INFORMATION tbi;
status = pNtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
ok( status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status );
expected_address = tbi.TebBaseAddress;
if (is_wow64 && is_process_wow64)
expected_address = (BYTE *)expected_address - 0x2000;
if (!is_wow64 && !is_process_wow64 && !tbi.TebBaseAddress)
win_skip( "Could not get TebBaseAddress, thread %u.\n", j );
else
ok( ti->TebBase == expected_address || (is_wow64 && !expected_address && !!ti->TebBase),
"Got unexpected TebBase %p, expected %p.\n", ti->TebBase, expected_address );
NtClose( handle );
}
}
}
if (!spi->NextEntryOffset)
@ -577,6 +645,7 @@ static void test_query_process(void)
NtClose( handle );
}
winetest_pop_context();
}
static void test_query_procperf(void)
@ -3317,7 +3386,8 @@ START_TEST(info)
test_query_cpu();
test_query_performance();
test_query_timeofday();
test_query_process();
test_query_process( TRUE );
test_query_process( FALSE );
test_query_procperf();
test_query_module();
test_query_handle();

View File

@ -2359,9 +2359,10 @@ static void read_dev_urandom( void *buf, ULONG len )
else WARN( "can't open /dev/urandom\n" );
}
static NTSTATUS get_system_process_info( void *info, ULONG size, ULONG *len )
static NTSTATUS get_system_process_info( SYSTEM_INFORMATION_CLASS class, void *info, ULONG size, ULONG *len )
{
unsigned int process_count, total_thread_count, total_name_len, i, j;
unsigned int thread_info_size;
unsigned int pos = 0;
char *buffer = NULL;
NTSTATUS ret;
@ -2369,6 +2370,11 @@ static NTSTATUS get_system_process_info( void *info, ULONG size, ULONG *len )
C_ASSERT( sizeof(struct thread_info) <= sizeof(SYSTEM_THREAD_INFORMATION) );
C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
if (class == SystemExtendedProcessInformation)
thread_info_size = sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION);
else
thread_info_size = sizeof(SYSTEM_THREAD_INFORMATION);
*len = 0;
if (size && !(buffer = malloc( size ))) return STATUS_NO_MEMORY;
@ -2387,7 +2393,7 @@ C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
if (ret == STATUS_INFO_LENGTH_MISMATCH)
*len = sizeof(SYSTEM_PROCESS_INFORMATION) * process_count
+ (total_name_len + process_count) * sizeof(WCHAR)
+ total_thread_count * sizeof(SYSTEM_THREAD_INFORMATION);
+ total_thread_count * thread_info_size;
free( buffer );
return ret;
@ -2414,13 +2420,13 @@ C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
name_len++;
}
proc_len = sizeof(*nt_process) + server_process->thread_count * sizeof(SYSTEM_THREAD_INFORMATION)
proc_len = sizeof(*nt_process) + server_process->thread_count * thread_info_size
+ (name_len + 1) * sizeof(WCHAR);
*len += proc_len;
if (*len <= size)
{
memset(nt_process, 0, sizeof(*nt_process));
memset(nt_process, 0, proc_len);
if (i < process_count - 1)
nt_process->NextEntryOffset = proc_len;
nt_process->CreationTime.QuadPart = server_process->start_time;
@ -2438,16 +2444,23 @@ C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
for (j = 0; j < server_process->thread_count; j++)
{
const struct thread_info *server_thread = (const struct thread_info *)(buffer + pos);
SYSTEM_EXTENDED_THREAD_INFORMATION *ti;
if (*len <= size)
{
nt_process->ti[j].CreateTime.QuadPart = server_thread->start_time;
nt_process->ti[j].ClientId.UniqueProcess = UlongToHandle(server_process->pid);
nt_process->ti[j].ClientId.UniqueThread = UlongToHandle(server_thread->tid);
nt_process->ti[j].dwCurrentPriority = server_thread->current_priority;
nt_process->ti[j].dwBasePriority = server_thread->base_priority;
ti = (SYSTEM_EXTENDED_THREAD_INFORMATION *)((BYTE *)nt_process->ti + j * thread_info_size);
ti->ThreadInfo.CreateTime.QuadPart = server_thread->start_time;
ti->ThreadInfo.ClientId.UniqueProcess = UlongToHandle(server_process->pid);
ti->ThreadInfo.ClientId.UniqueThread = UlongToHandle(server_thread->tid);
ti->ThreadInfo.dwCurrentPriority = server_thread->current_priority;
ti->ThreadInfo.dwBasePriority = server_thread->base_priority;
get_thread_times( server_process->unix_pid, server_thread->unix_tid,
&nt_process->ti[j].KernelTime, &nt_process->ti[j].UserTime );
&ti->ThreadInfo.KernelTime, &ti->ThreadInfo.UserTime );
if (class == SystemExtendedProcessInformation)
{
ti->Win32StartAddress = wine_server_get_ptr( server_thread->entry_point );
ti->TebBase = wine_server_get_ptr( server_thread->teb );
}
}
pos += sizeof(*server_thread);
@ -2455,7 +2468,8 @@ C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
if (*len <= size)
{
nt_process->ProcessName.Buffer = (WCHAR *)&nt_process->ti[server_process->thread_count];
nt_process->ProcessName.Buffer = (WCHAR *)((BYTE *)nt_process->ti
+ server_process->thread_count * thread_info_size);
nt_process->ProcessName.Length = name_len * sizeof(WCHAR);
nt_process->ProcessName.MaximumLength = (name_len + 1) * sizeof(WCHAR);
memcpy(nt_process->ProcessName.Buffer, file_part, name_len * sizeof(WCHAR));
@ -2554,7 +2568,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
}
case SystemProcessInformation: /* 5 */
ret = get_system_process_info( info, size, &len );
ret = get_system_process_info( class, info, size, &len );
break;
case SystemProcessorPerformanceInformation: /* 8 */
@ -2858,9 +2872,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
}
case SystemExtendedProcessInformation: /* 57 */
FIXME("SystemExtendedProcessInformation, size %u, info %p, stub!\n", size, info);
memset( info, 0, size );
ret = STATUS_SUCCESS;
ret = get_system_process_info( class, info, size, &len );
break;
case SystemRecommendedSharedDataAlignment: /* 58 */

View File

@ -2001,6 +2001,8 @@ struct thread_info
int base_priority;
int current_priority;
int unix_tid;
client_ptr_t teb;
client_ptr_t entry_point;
};
struct process_info
@ -6261,7 +6263,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 734
#define SERVER_PROTOCOL_VERSION 735
/* ### protocol_version end ### */

View File

@ -2005,6 +2005,18 @@ typedef struct _SYSTEM_THREAD_INFORMATION
DWORD dwUnknown; /* 3c/4c */
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION
{
SYSTEM_THREAD_INFORMATION ThreadInfo; /* 00/00 */
void *StackBase; /* 40/50 */
void *StackLimit; /* 44/58 */
void *Win32StartAddress; /* 48/60 */
void *TebBase; /* 4c/68 */
ULONG_PTR Reserved2; /* 50/70 */
ULONG_PTR Reserved3; /* 54/78 */
ULONG_PTR Reserved4; /* 58/80 */
} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;

View File

@ -1920,6 +1920,8 @@ DECL_HANDLER(list_processes)
thread_info->base_priority = thread->priority;
thread_info->current_priority = thread->priority; /* FIXME */
thread_info->unix_tid = thread->unix_tid;
thread_info->entry_point = thread->entry_point;
thread_info->teb = thread->teb;
pos += sizeof(*thread_info);
}
}

View File

@ -1602,6 +1602,8 @@ struct thread_info
int base_priority;
int current_priority;
int unix_tid;
client_ptr_t teb;
client_ptr_t entry_point;
};
struct process_info