From: Michael Müller michael@fds-team.de
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- 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 a95d2ae6cd1..bb396e90064 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
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/info.c | 24 +++++++++++++++++++----- dlls/ntdll/unix/system.c | 12 +++++++----- server/handle.c | 5 +++++ server/protocol.def | 1 + server/trace.c | 4 ++-- 5 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 419d8582dd3..85c523881ef 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -542,11 +542,14 @@ static void test_query_handle(void) ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION); SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength); HANDLE EventHandle; - BOOL found; + BOOL found, ret; INT i;
EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL); ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() ); + ret = SetHandleInformation(EventHandle, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, + HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE); + ok(ret, "got error %u\n", GetLastError());
/* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */ ReturnLength = 0xdeadbeef; @@ -581,11 +584,22 @@ static void test_query_handle(void) goto done; }
- for (i = 0, found = FALSE; i < shi->Count && !found; i++) - found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) && - ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle); + found = FALSE; + for (i = 0; i < shi->Count; i++) + { + if (shi->Handle[i].OwnerPid == GetCurrentProcessId() && + (HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle) + { + ok(shi->Handle[i].HandleFlags == (OBJ_INHERIT | OBJ_PROTECT_CLOSE), + "got attributes %#x\n", shi->Handle[i].HandleFlags); + found = TRUE; + break; + } + } ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() );
+ ret = SetHandleInformation(EventHandle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); + ok(ret, "got error %u\n", GetLastError()); CloseHandle(EventHandle);
ReturnLength = 0xdeadbeef; @@ -645,7 +659,7 @@ static void test_query_handle_ex(void) if (info->Handles[i].UniqueProcessId == GetCurrentProcessId() && (HANDLE)info->Handles[i].HandleValue == event) { - todo_wine ok(info->Handles[i].HandleAttributes == (OBJ_INHERIT | OBJ_PROTECT_CLOSE), + 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; diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index e2482f91041..f4a879d8748 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2446,7 +2446,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, shi->Handle[i].OwnerPid = handle_info[i].owner; shi->Handle[i].HandleValue = handle_info[i].handle; shi->Handle[i].AccessMask = handle_info[i].access; - /* FIXME: Fill out ObjectType, HandleFlags, ObjectPointer */ + shi->Handle[i].HandleFlags = handle_info[i].attributes; + /* FIXME: Fill out ObjectType, ObjectPointer */ } } else if (ret == STATUS_BUFFER_TOO_SMALL) @@ -2493,10 +2494,11 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, 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 */ + shi->Handles[i].UniqueProcessId = handle_info[i].owner; + shi->Handles[i].HandleValue = handle_info[i].handle; + shi->Handles[i].GrantedAccess = handle_info[i].access; + shi->Handles[i].HandleAttributes = handle_info[i].attributes; + /* FIXME: Fill out Object, ObjectTypeIndex */ } } else if (ret == STATUS_BUFFER_TOO_SMALL) diff --git a/server/handle.c b/server/handle.c index ef0f595bf08..c32b001f2e2 100644 --- a/server/handle.c +++ b/server/handle.c @@ -833,6 +833,11 @@ static int enum_handles( struct process *process, void *user ) handle->owner = process->id; handle->handle = index_to_handle(i); handle->access = entry->access & ~RESERVED_ALL; + handle->attributes = 0; + if (entry->access & RESERVED_INHERIT) + handle->attributes |= OBJ_INHERIT; + if (entry->access & RESERVED_CLOSE_PROTECT) + handle->attributes |= OBJ_PROTECT_CLOSE; info->count--; }
diff --git a/server/protocol.def b/server/protocol.def index fa19bb41bb4..5126a9e37e5 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3197,6 +3197,7 @@ struct handle_info process_id_t owner; obj_handle_t handle; unsigned int access; + unsigned int attributes; };
/* Return a list of all opened handles */ diff --git a/server/trace.c b/server/trace.c index 2737cb16499..9faa3d5a443 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1342,8 +1342,8 @@ static void dump_varargs_handle_infos( const char *prefix, data_size_t size ) while (size >= sizeof(*handle)) { handle = cur_data; - fprintf( stderr, "{owner=%04x,handle=%04x,access=%08x}", - handle->owner, handle->handle, handle->access ); + fprintf( stderr, "{owner=%04x,handle=%04x,access=%08x,attributes=%08x}", + handle->owner, handle->handle, handle->access, handle->attributes ); size -= sizeof(*handle); remove_data( sizeof(*handle) ); if (size) fputc( ',', stderr );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/system.c | 6 ++++-- server/handle.c | 4 ++++ server/protocol.def | 1 + server/trace.c | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index f4a879d8748..6cf044d496f 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2447,7 +2447,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, shi->Handle[i].HandleValue = handle_info[i].handle; shi->Handle[i].AccessMask = handle_info[i].access; shi->Handle[i].HandleFlags = handle_info[i].attributes; - /* FIXME: Fill out ObjectType, ObjectPointer */ + shi->Handle[i].ObjectType = handle_info[i].type; + /* FIXME: Fill out ObjectPointer */ } } else if (ret == STATUS_BUFFER_TOO_SMALL) @@ -2498,7 +2499,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, shi->Handles[i].HandleValue = handle_info[i].handle; shi->Handles[i].GrantedAccess = handle_info[i].access; shi->Handles[i].HandleAttributes = handle_info[i].attributes; - /* FIXME: Fill out Object, ObjectTypeIndex */ + shi->Handles[i].ObjectTypeIndex = handle_info[i].type; + /* FIXME: Fill out Object */ } } else if (ret == STATUS_BUFFER_TOO_SMALL) diff --git a/server/handle.c b/server/handle.c index c32b001f2e2..399cd7fa62b 100644 --- a/server/handle.c +++ b/server/handle.c @@ -815,6 +815,7 @@ static int enum_handles( struct process *process, void *user ) struct handle_table *table = process->handles; struct handle_entry *entry; struct handle_info *handle; + struct object *obj; unsigned int i;
if (!table) @@ -838,6 +839,9 @@ static int enum_handles( struct process *process, void *user ) handle->attributes |= OBJ_INHERIT; if (entry->access & RESERVED_CLOSE_PROTECT) handle->attributes |= OBJ_PROTECT_CLOSE; + obj = get_handle_obj( process, index_to_handle(i), 0, NULL ); + handle->type = obj->ops->type->index; + release_object( obj ); info->count--; }
diff --git a/server/protocol.def b/server/protocol.def index 5126a9e37e5..7f3b785df51 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3198,6 +3198,7 @@ struct handle_info obj_handle_t handle; unsigned int access; unsigned int attributes; + unsigned int type; };
/* Return a list of all opened handles */ diff --git a/server/trace.c b/server/trace.c index 9faa3d5a443..b07935cc54b 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1342,8 +1342,8 @@ static void dump_varargs_handle_infos( const char *prefix, data_size_t size ) while (size >= sizeof(*handle)) { handle = cur_data; - fprintf( stderr, "{owner=%04x,handle=%04x,access=%08x,attributes=%08x}", - handle->owner, handle->handle, handle->access, handle->attributes ); + fprintf( stderr, "{owner=%04x,handle=%04x,access=%08x,attributes=%08x,type=%u}", + handle->owner, handle->handle, handle->access, handle->attributes, handle->type ); size -= sizeof(*handle); remove_data( sizeof(*handle) ); if (size) fputc( ',', stderr );