Michael Müller : ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation).
Alexandre Julliard
julliard at winehq.org
Thu Feb 18 16:06:05 CST 2021
Module: wine
Branch: master
Commit: 835f5fff7150034139919801444b52a4c0186f44
URL: https://source.winehq.org/git/wine.git/?a=commit;h=835f5fff7150034139919801444b52a4c0186f44
Author: Michael Müller <michael at fds-team.de>
Date: Wed Feb 17 22:59:15 2021 -0600
ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation).
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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
More information about the wine-cvs
mailing list