authorgravatar for rohlemF@gmail.comRohlem <rohlemF@gmail.com> 2020-12-10 12:52:00+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 17:48:18-07:00
log964bbcd0b1976ca55d3f845d4d1dcf496bc36a1b
tree8da00fca87c6979b36e8f01b09d49ffe275e6e10
parent09dc651476408deb791e81408d617aac97458ebf

introduce std.os.windows.QueryObjectName


3 files changed, 69 insertions(+), 0 deletions(-)

lib/std/os/windows.zig+45
...@@ -956,6 +956,51 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 {...@@ -956,6 +956,51 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 {
956 return @bitCast(u64, result);956 return @bitCast(u64, result);
957}957}
958958
959pub fn QueryObjectName(
960 handle: HANDLE,
961 out_buffer: []u16,
962) ![]u16 {
963 var full_buffer: [@sizeOf(OBJECT_NAME_INFORMATION) + PATH_MAX_WIDE * 2]u8 align(@alignOf(OBJECT_NAME_INFORMATION)) = undefined;
964 var info = @ptrCast(*OBJECT_NAME_INFORMATION, &full_buffer);
965 //buffer size is specified in bytes
966 const full_buffer_length = @intCast(ULONG, @sizeOf(OBJECT_NAME_INFORMATION) + std.math.min(PATH_MAX_WIDE, (out_buffer.len + 1) * 2));
967 //last argument would return the length required for full_buffer, not exposed here
968 const rc = ntdll.NtQueryObject(handle, .ObjectNameInformation, full_buffer[0..], full_buffer_length, null);
969 return switch (rc) {
970 .SUCCESS => if (@ptrCast(?[*]WCHAR, info.Name.Buffer)) |buffer| blk: {
971 //resulting string length is specified in bytes
972 const path_length_unterminated = @divExact(info.Name.Length, 2);
973 if (out_buffer.len < path_length_unterminated) {
974 return error.NameTooLong;
975 }
976 std.mem.copy(WCHAR, out_buffer[0..path_length_unterminated], buffer[0..path_length_unterminated :0]);
977 break :blk out_buffer[0..path_length_unterminated];
978 } else error.Unexpected,
979 .ACCESS_DENIED => error.AccessDenied,
980 .INVALID_HANDLE => error.InvalidHandle,
981 .BUFFER_OVERFLOW, .BUFFER_TOO_SMALL => error.NameTooLong,
982 //name_buffer.len >= @sizeOf(OBJECT_NAME_INFORMATION) holds statically
983 .INFO_LENGTH_MISMATCH => unreachable,
984 else => |e| unexpectedStatus(e),
985 };
986}
987test "QueryObjectName" {
988 if (comptime builtin.os.tag != .windows)
989 return;
990
991 //any file will do; canonicalization works on NTFS junctions and symlinks, hardlinks remain separate paths.
992 const file = try std.fs.openSelfExe(.{});
993 defer file.close();
994 //make this large enough for the test runner exe path
995 var out_buffer align(16) = std.mem.zeroes([1 << 10]u16);
996
997 var result_path = try QueryObjectName(file.handle, out_buffer[0..]);
998 //insufficient size
999 std.testing.expectError(error.NameTooLong, QueryObjectName(file.handle, out_buffer[0 .. result_path.len - 1]));
1000 //exactly-sufficient size
1001 _ = try QueryObjectName(file.handle, out_buffer[0..result_path.len]);
1002}
1003
959pub const GetFinalPathNameByHandleError = error {1004pub const GetFinalPathNameByHandleError = error {
960 BadPathName,1005 BadPathName,
961 FileNotFound,1006 FileNotFound,
lib/std/os/windows/bits.zig+16
...@@ -66,6 +66,7 @@ pub const SIZE_T = usize;...@@ -66,6 +66,7 @@ pub const SIZE_T = usize;
66pub const TCHAR = if (UNICODE) WCHAR else u8;66pub const TCHAR = if (UNICODE) WCHAR else u8;
67pub const UINT = c_uint;67pub const UINT = c_uint;
68pub const ULONG_PTR = usize;68pub const ULONG_PTR = usize;
69pub const PULONG = *ULONG;
69pub const LONG_PTR = isize;70pub const LONG_PTR = isize;
70pub const DWORD_PTR = ULONG_PTR;71pub const DWORD_PTR = ULONG_PTR;
71pub const UNICODE = false;72pub const UNICODE = false;
...@@ -1620,3 +1621,18 @@ pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;...@@ -1620,3 +1621,18 @@ pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;
1620pub const SD_RECEIVE = 0;1621pub const SD_RECEIVE = 0;
1621pub const SD_SEND = 1;1622pub const SD_SEND = 1;
1622pub const SD_BOTH = 2;1623pub const SD_BOTH = 2;
1624
1625pub const OBJECT_INFORMATION_CLASS = extern enum {
1626 ObjectBasicInformation = 0,
1627 ObjectNameInformation = 1,
1628 ObjectTypeInformation = 2,
1629 ObjectTypesInformation = 3,
1630 ObjectHandleFlagInformation = 4,
1631 ObjectSessionInformation = 5,
1632 MaxObjectInfoClass,
1633};
1634
1635pub const OBJECT_NAME_INFORMATION = extern struct {
1636 Name: UNICODE_STRING,
1637};
1638pub const POBJECT_NAME_INFORMATION = *OBJECT_NAME_INFORMATION;
lib/std/os/windows/ntdll.zig+8
...@@ -113,3 +113,11 @@ pub extern "NtDll" fn NtWaitForKeyedEvent(...@@ -113,3 +113,11 @@ pub extern "NtDll" fn NtWaitForKeyedEvent(
113) callconv(WINAPI) NTSTATUS;113) callconv(WINAPI) NTSTATUS;
114114
115pub extern "NtDll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(WINAPI) NTSTATUS;115pub extern "NtDll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(WINAPI) NTSTATUS;
116
117pub extern "NtDll" fn NtQueryObject(
118 Handle: HANDLE,
119 ObjectInformationClass: OBJECT_INFORMATION_CLASS,
120 ObjectInformation: PVOID,
121 ObjectInformationLength: ULONG,
122 ReturnLength: ?PULONG,
123) callconv(WINAPI) NTSTATUS;