From 835f5fff7150034139919801444b52a4c0186f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Wed, 17 Feb 2021 22:59:15 -0600 Subject: [PATCH] ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation). Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/info.c | 79 ++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/system.c | 50 +++++++++++++++++++++++++ include/winternl.h | 20 ++++++++++ 3 files changed, 149 insertions(+) diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index c848248fae3..419d8582dd3 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -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(); diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index a889b2e020c..e2482f91041 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -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 }; diff --git a/include/winternl.h b/include/winternl.h index 61bcd0f1d92..76feca83596 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -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