ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation).

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Michael Müller 2021-02-17 22:59:15 -06:00 committed by Alexandre Julliard
parent 51f1ab47a7
commit 835f5fff71
3 changed files with 149 additions and 0 deletions

View File

@ -609,6 +609,84 @@ done:
HeapFree( GetProcessHeap(), 0, shi);
}
static void test_query_handle_ex(void)
{
SYSTEM_HANDLE_INFORMATION_EX *info = malloc(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
ULONG size, expect_size;
NTSTATUS status;
unsigned int i;
HANDLE event;
BOOL found, ret;
event = CreateEventA(NULL, FALSE, FALSE, NULL);
ok(event != NULL, "failed to create event, error %u\n", GetLastError());
ret = SetHandleInformation(event, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE);
ok(ret, "got error %u\n", GetLastError());
size = 0;
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#x\n", status);
ok(size > sizeof(SYSTEM_HANDLE_INFORMATION_EX), "got size %u\n", size);
while (status == STATUS_INFO_LENGTH_MISMATCH)
{
info = realloc(info, size);
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
}
ok(!status, "got %#x\n", status);
expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
ok(size == expect_size, "expected size %u, got %u\n", expect_size, size);
ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
found = FALSE;
for (i = 0; i < info->NumberOfHandles; ++i)
{
if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
&& (HANDLE)info->Handles[i].HandleValue == event)
{
todo_wine ok(info->Handles[i].HandleAttributes == (OBJ_INHERIT | OBJ_PROTECT_CLOSE),
"got flags %#x\n", info->Handles[i].HandleAttributes);
ok(info->Handles[i].GrantedAccess == EVENT_ALL_ACCESS, "got access %#x\n", info->Handles[i].GrantedAccess);
found = TRUE;
}
ok(!info->Handles[i].CreatorBackTraceIndex, "got backtrace index %u\n", info->Handles[i].CreatorBackTraceIndex);
}
ok(found, "event handle not found\n");
ret = SetHandleInformation(event, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
ok(ret, "got error %u\n", GetLastError());
CloseHandle(event);
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
while (status == STATUS_INFO_LENGTH_MISMATCH)
{
info = realloc(info, size);
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
}
ok(!status, "got %#x\n", status);
expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
ok(size == expect_size, "expected size %u, got %u\n", expect_size, size);
ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
found = FALSE;
for (i = 0; i < info->NumberOfHandles; ++i)
{
if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
&& (HANDLE)info->Handles[i].HandleValue == event)
{
found = TRUE;
break;
}
}
ok(!found, "event handle found\n");
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
free(info);
}
static void test_query_cache(void)
{
NTSTATUS status;
@ -2959,6 +3037,7 @@ START_TEST(info)
test_query_procperf();
test_query_module();
test_query_handle();
test_query_handle_ex();
test_query_cache();
test_query_interrupt();
test_time_adjustment();

View File

@ -2461,6 +2461,56 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
break;
}
case SystemExtendedHandleInformation:
{
struct handle_info *handle_info;
DWORD i, num_handles;
if (size < sizeof(SYSTEM_HANDLE_INFORMATION_EX))
{
ret = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!info)
{
ret = STATUS_ACCESS_VIOLATION;
break;
}
num_handles = (size - FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles ))
/ sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX);
if (!(handle_info = malloc( sizeof(*handle_info) * num_handles ))) return STATUS_NO_MEMORY;
SERVER_START_REQ( get_system_handles )
{
wine_server_set_reply( req, handle_info, sizeof(*handle_info) * num_handles );
if (!(ret = wine_server_call( req )))
{
SYSTEM_HANDLE_INFORMATION_EX *shi = info;
shi->NumberOfHandles = wine_server_reply_size( req ) / sizeof(*handle_info);
len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles[shi->NumberOfHandles] );
for (i = 0; i < shi->NumberOfHandles; i++)
{
memset( &shi->Handles[i], 0, sizeof(shi->Handles[i]) );
shi->Handles[i].UniqueProcessId = handle_info[i].owner;
shi->Handles[i].HandleValue = handle_info[i].handle;
shi->Handles[i].GrantedAccess = handle_info[i].access;
/* FIXME: Fill out Object, HandleAttributes, ObjectTypeIndex */
}
}
else if (ret == STATUS_BUFFER_TOO_SMALL)
{
len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles[reply->count] );
ret = STATUS_INFO_LENGTH_MISMATCH;
}
}
SERVER_END_REQ;
free( handle_info );
break;
}
case SystemCacheInformation:
{
SYSTEM_CACHE_INFORMATION sci = { 0 };

View File

@ -1898,6 +1898,25 @@ typedef struct _SYSTEM_HANDLE_INFORMATION {
SYSTEM_HANDLE_ENTRY Handle[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
void *Object;
ULONG_PTR UniqueProcessId;
ULONG_PTR HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX;
/* System Information Class 0x15 */
typedef struct _SYSTEM_CACHE_INFORMATION {
@ -2289,6 +2308,7 @@ typedef struct _RTL_ATOM_TABLE
#define LOGONID_CURRENT ((ULONG)-1)
#define OBJ_PROTECT_CLOSE 0x00000001
#define OBJ_INHERIT 0x00000002
#define OBJ_PERMANENT 0x00000010
#define OBJ_EXCLUSIVE 0x00000020