ntdll: Return sufficient info size at once from NtQuerySystemInformation(SystemProcessInformation).
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ce6eeda018
commit
b5f3ddd185
|
@ -470,25 +470,30 @@ static void test_query_process(void)
|
|||
SYSTEM_THREAD_INFORMATION ti[1];
|
||||
} SYSTEM_PROCESS_INFORMATION_PRIVATE;
|
||||
|
||||
ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
|
||||
SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
|
||||
SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf;
|
||||
BOOL current_process_found = FALSE;
|
||||
|
||||
/* test ReturnLength */
|
||||
ReturnLength = 0;
|
||||
status = pNtQuerySystemInformation(SystemProcessInformation, 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");
|
||||
ok( ReturnLength > 0, "got 0 length\n" );
|
||||
|
||||
/* W2K3 and later returns the needed length, the rest returns 0, so we have to loop */
|
||||
for (;;)
|
||||
/* W2K3 and later returns the needed length, the rest returns 0. */
|
||||
if (!ReturnLength)
|
||||
{
|
||||
status = pNtQuerySystemInformation(SystemProcessInformation, spi_buf, SystemInformationLength, &ReturnLength);
|
||||
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH) break;
|
||||
|
||||
spi_buf = HeapReAlloc(GetProcessHeap(), 0, spi_buf , SystemInformationLength *= 2);
|
||||
win_skip( "Zero return length, skipping tests." );
|
||||
return;
|
||||
}
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
spi_buf = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
|
||||
status = pNtQuerySystemInformation(SystemProcessInformation, 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. */
|
||||
ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH,
|
||||
"Expected STATUS_SUCCESS, got %08x\n", status );
|
||||
|
||||
spi = spi_buf;
|
||||
|
||||
for (;;)
|
||||
|
@ -496,9 +501,16 @@ static void test_query_process(void)
|
|||
DWORD_PTR tid;
|
||||
DWORD j;
|
||||
|
||||
winetest_push_context( "i %u (%s)", i, debugstr_w(spi->ProcessName.Buffer) );
|
||||
|
||||
i++;
|
||||
|
||||
last_pid = (DWORD_PTR)spi->UniqueProcessId;
|
||||
ok( !(last_pid & 3), "Unexpected PID low bits: %p\n", spi->UniqueProcessId );
|
||||
|
||||
if (last_pid == GetCurrentProcessId())
|
||||
current_process_found = TRUE;
|
||||
|
||||
ok(!(last_pid & 3), "Unexpected PID low bits: %p\n", spi->UniqueProcessId);
|
||||
for (j = 0; j < spi->dwThreadCount; j++)
|
||||
{
|
||||
|
@ -511,12 +523,17 @@ static void test_query_process(void)
|
|||
ok(!(tid & 3), "Unexpected TID low bits: %p\n", spi->ti[j].ClientId.UniqueThread);
|
||||
}
|
||||
|
||||
if (!spi->NextEntryOffset) break;
|
||||
|
||||
if (!spi->NextEntryOffset)
|
||||
{
|
||||
winetest_pop_context();
|
||||
break;
|
||||
}
|
||||
one_before_last_pid = last_pid;
|
||||
|
||||
spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->NextEntryOffset);
|
||||
winetest_pop_context();
|
||||
}
|
||||
ok( current_process_found, "Test process not found.\n" );
|
||||
if (winetest_debug > 1) trace("%u processes, %u threads\n", i, k);
|
||||
|
||||
if (one_before_last_pid == 0) one_before_last_pid = last_pid;
|
||||
|
|
|
@ -2446,10 +2446,13 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
|
|||
|
||||
case SystemProcessInformation: /* 5 */
|
||||
{
|
||||
unsigned int process_count, i, j;
|
||||
unsigned int process_count, total_thread_count, total_name_len, i, j;
|
||||
char *buffer = NULL;
|
||||
unsigned int pos = 0;
|
||||
|
||||
C_ASSERT( sizeof(struct thread_info) <= sizeof(SYSTEM_THREAD_INFORMATION) );
|
||||
C_ASSERT( sizeof(struct process_info) <= sizeof(SYSTEM_PROCESS_INFORMATION) );
|
||||
|
||||
if (size && !(buffer = malloc( size )))
|
||||
{
|
||||
ret = STATUS_NO_MEMORY;
|
||||
|
@ -2460,19 +2463,25 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
|
|||
{
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
ret = wine_server_call( req );
|
||||
len = reply->info_size;
|
||||
total_thread_count = reply->total_thread_count;
|
||||
total_name_len = reply->total_name_len;
|
||||
process_count = reply->process_count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
len = 0;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
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);
|
||||
|
||||
free( buffer );
|
||||
break;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
|
||||
for (i = 0; i < process_count; i++)
|
||||
{
|
||||
SYSTEM_PROCESS_INFORMATION *nt_process = (SYSTEM_PROCESS_INFORMATION *)((char *)info + len);
|
||||
|
|
|
@ -2029,6 +2029,8 @@ struct list_processes_reply
|
|||
struct reply_header __header;
|
||||
data_size_t info_size;
|
||||
int process_count;
|
||||
int total_thread_count;
|
||||
data_size_t total_name_len;
|
||||
/* VARARG(data,process_info,info_size); */
|
||||
};
|
||||
|
||||
|
@ -6259,7 +6261,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 733
|
||||
#define SERVER_PROTOCOL_VERSION 734
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -1868,6 +1868,8 @@ DECL_HANDLER(list_processes)
|
|||
char *buffer;
|
||||
|
||||
reply->process_count = 0;
|
||||
reply->total_thread_count = 0;
|
||||
reply->total_name_len = 0;
|
||||
reply->info_size = 0;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
|
||||
|
@ -1877,6 +1879,8 @@ DECL_HANDLER(list_processes)
|
|||
reply->info_size = (reply->info_size + 7) & ~7;
|
||||
reply->info_size += process->running_threads * sizeof(struct thread_info);
|
||||
reply->process_count++;
|
||||
reply->total_thread_count += process->running_threads;
|
||||
reply->total_name_len += process->imagelen;
|
||||
}
|
||||
|
||||
if (reply->info_size > get_reply_max_size())
|
||||
|
|
|
@ -1624,6 +1624,8 @@ struct process_info
|
|||
@REPLY
|
||||
data_size_t info_size;
|
||||
int process_count;
|
||||
int total_thread_count;
|
||||
data_size_t total_name_len;
|
||||
VARARG(data,process_info,info_size);
|
||||
@END
|
||||
|
||||
|
|
|
@ -1127,7 +1127,9 @@ C_ASSERT( sizeof(struct get_mapping_filename_reply) == 16 );
|
|||
C_ASSERT( sizeof(struct list_processes_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, info_size) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, process_count) == 12 );
|
||||
C_ASSERT( sizeof(struct list_processes_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, total_thread_count) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, total_name_len) == 20 );
|
||||
C_ASSERT( sizeof(struct list_processes_reply) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_debug_obj_request, access) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_debug_obj_request, flags) == 16 );
|
||||
C_ASSERT( sizeof(struct create_debug_obj_request) == 24 );
|
||||
|
|
|
@ -2287,6 +2287,8 @@ static void dump_list_processes_reply( const struct list_processes_reply *req )
|
|||
{
|
||||
fprintf( stderr, " info_size=%u", req->info_size );
|
||||
fprintf( stderr, ", process_count=%d", req->process_count );
|
||||
fprintf( stderr, ", total_thread_count=%d", req->total_thread_count );
|
||||
fprintf( stderr, ", total_name_len=%u", req->total_name_len );
|
||||
dump_varargs_process_info( ", data=", min(cur_size,req->info_size) );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue