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:
parent
bb6aa6c773
commit
98a5466380
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ### */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue