diff options
| -rw-r--r-- | lib/std/os/windows.zig | 45 | ||||
| -rw-r--r-- | lib/std/os/windows/bits.zig | 16 | ||||
| -rw-r--r-- | lib/std/os/windows/ntdll.zig | 8 |
3 files changed, 69 insertions, 0 deletions
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index b489dbaf5d..725880a4b9 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -956,6 +956,51 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 { return @bitCast(u64, result); } +pub fn QueryObjectName( + handle: HANDLE, + out_buffer: []u16, +) ![]u16 { + var full_buffer: [@sizeOf(OBJECT_NAME_INFORMATION) + PATH_MAX_WIDE * 2]u8 align(@alignOf(OBJECT_NAME_INFORMATION)) = undefined; + var info = @ptrCast(*OBJECT_NAME_INFORMATION, &full_buffer); + //buffer size is specified in bytes + const full_buffer_length = @intCast(ULONG, @sizeOf(OBJECT_NAME_INFORMATION) + std.math.min(PATH_MAX_WIDE, (out_buffer.len + 1) * 2)); + //last argument would return the length required for full_buffer, not exposed here + const rc = ntdll.NtQueryObject(handle, .ObjectNameInformation, full_buffer[0..], full_buffer_length, null); + return switch (rc) { + .SUCCESS => if (@ptrCast(?[*]WCHAR, info.Name.Buffer)) |buffer| blk: { + //resulting string length is specified in bytes + const path_length_unterminated = @divExact(info.Name.Length, 2); + if (out_buffer.len < path_length_unterminated) { + return error.NameTooLong; + } + std.mem.copy(WCHAR, out_buffer[0..path_length_unterminated], buffer[0..path_length_unterminated :0]); + break :blk out_buffer[0..path_length_unterminated]; + } else error.Unexpected, + .ACCESS_DENIED => error.AccessDenied, + .INVALID_HANDLE => error.InvalidHandle, + .BUFFER_OVERFLOW, .BUFFER_TOO_SMALL => error.NameTooLong, + //name_buffer.len >= @sizeOf(OBJECT_NAME_INFORMATION) holds statically + .INFO_LENGTH_MISMATCH => unreachable, + else => |e| unexpectedStatus(e), + }; +} +test "QueryObjectName" { + if (comptime builtin.os.tag != .windows) + return; + + //any file will do; canonicalization works on NTFS junctions and symlinks, hardlinks remain separate paths. + const file = try std.fs.openSelfExe(.{}); + defer file.close(); + //make this large enough for the test runner exe path + var out_buffer align(16) = std.mem.zeroes([1 << 10]u16); + + var result_path = try QueryObjectName(file.handle, out_buffer[0..]); + //insufficient size + std.testing.expectError(error.NameTooLong, QueryObjectName(file.handle, out_buffer[0 .. result_path.len - 1])); + //exactly-sufficient size + _ = try QueryObjectName(file.handle, out_buffer[0..result_path.len]); +} + pub const GetFinalPathNameByHandleError = error { BadPathName, FileNotFound, diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 33005ef366..f6417f20cf 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -66,6 +66,7 @@ pub const SIZE_T = usize; pub const TCHAR = if (UNICODE) WCHAR else u8; pub const UINT = c_uint; pub const ULONG_PTR = usize; +pub const PULONG = *ULONG; pub const LONG_PTR = isize; pub const DWORD_PTR = ULONG_PTR; pub const UNICODE = false; @@ -1620,3 +1621,18 @@ pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008; pub const SD_RECEIVE = 0; pub const SD_SEND = 1; pub const SD_BOTH = 2; + +pub const OBJECT_INFORMATION_CLASS = extern enum { + ObjectBasicInformation = 0, + ObjectNameInformation = 1, + ObjectTypeInformation = 2, + ObjectTypesInformation = 3, + ObjectHandleFlagInformation = 4, + ObjectSessionInformation = 5, + MaxObjectInfoClass, +}; + +pub const OBJECT_NAME_INFORMATION = extern struct { + Name: UNICODE_STRING, +}; +pub const POBJECT_NAME_INFORMATION = *OBJECT_NAME_INFORMATION; diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 1587b4d5dd..1d91066a55 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -113,3 +113,11 @@ pub extern "NtDll" fn NtWaitForKeyedEvent( ) callconv(WINAPI) NTSTATUS; pub extern "NtDll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(WINAPI) NTSTATUS; + +pub extern "NtDll" fn NtQueryObject( + Handle: HANDLE, + ObjectInformationClass: OBJECT_INFORMATION_CLASS, + ObjectInformation: PVOID, + ObjectInformationLength: ULONG, + ReturnLength: ?PULONG, +) callconv(WINAPI) NTSTATUS; |
