authorgravatar for rohlemF@gmail.comRohlem <rohlemF@gmail.com> 2020-12-23 21:50:08+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 17:48:18-07:00
logf301a8467c0171ab603036b5b31be48fbb40e8ad
treed3c921663d014ab45769081c361496c5ae084ed1
parentcb205039903868a6273b9f9d65916e943675d540

std.os.windows.GetFinalPathNameByHandle: remove QueryInformationFile code path


1 files changed, 20 insertions(+), 54 deletions(-)

lib/std/os/windows.zig+20-54
......@@ -28,10 +28,6 @@ pub const gdi32 = @import("windows/gdi32.zig");
2828
2929pub usingnamespace @import("windows/bits.zig");
3030
31//version detection
32const version = std.zig.system.windows;
33const WindowsVersion = version.WindowsVersion;
34
3531pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize));
3632
3733pub const OpenError = error{
......@@ -1034,65 +1030,35 @@ pub fn GetFinalPathNameByHandle(
10341030 out_buffer: []u16,
10351031) GetFinalPathNameByHandleError![]u16 {
10361032 var path_buffer: [math.max(@sizeOf(FILE_NAME_INFORMATION), @sizeOf(OBJECT_NAME_INFORMATION)) + PATH_MAX_WIDE * 2]u8 align(@alignOf(FILE_NAME_INFORMATION)) = undefined;
1037 var volume_buffer: [@sizeOf(FILE_NAME_INFORMATION) + MAX_PATH]u8 align(@alignOf(FILE_NAME_INFORMATION)) = undefined; // MAX_PATH bytes should be enough since it's Windows-defined name
1038
1039 var file_name_u16: []const u16 = undefined;
1040 var volume_name_u16: []const u16 = undefined;
1041 if ((comptime (std.builtin.os.version_range.windows.isAtLeast(WindowsVersion.win10_rs4) != true)) and !version.detectRuntimeVersion().isAtLeast(WindowsVersion.win10_rs4)) {
1042 const final_path = QueryObjectName(hFile, mem.bytesAsSlice(u16, &path_buffer)) catch |err| return switch (err) {
1043 // we assume InvalidHandle is close enough to FileNotFound in semantics
1044 // to not further complicate the error set
1045 error.InvalidHandle => error.FileNotFound,
1046 else => |e| e,
1047 };
1033 const final_path = QueryObjectName(hFile, mem.bytesAsSlice(u16, &path_buffer)) catch |err| switch (err) {
1034 // we assume InvalidHandle is close enough to FileNotFound in semantics
1035 // to not further complicate the error set
1036 error.InvalidHandle => return error.FileNotFound,
1037 else => |e| return e,
1038 };
10481039
1049 if (fmt.volume_name == .Nt) {
1040 switch (fmt.volume_name) {
1041 .Nt => {
1042 // the returned path is already in .Nt format
10501043 if (out_buffer.len < final_path.len) {
10511044 return error.NameTooLong;
10521045 }
10531046 mem.copy(u16, out_buffer, final_path);
10541047 return out_buffer[0..final_path.len];
1055 }
1056
1057 //otherwise we need to parse the string for volume path for the .Dos logic below to work
1058 const expected_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");
1059
1060 // TODO find out if a path can start with something besides `\Device\<volume name>`,
1061 // and if we need to handle it differently
1062 // (i.e. how to determine the start and end of the volume name in that case)
1063 if (!mem.eql(u16, expected_prefix, final_path[0..expected_prefix.len])) return error.Unexpected;
1064
1065 const index = mem.indexOfPos(u16, final_path, expected_prefix.len, &[_]u16{'\\'}) orelse unreachable;
1066 volume_name_u16 = final_path[0..index];
1067 file_name_u16 = final_path[index..];
1068
1069 //fallthrough for fmt.volume_name != .Nt
1070 } else {
1071 // Get normalized path; doesn't include volume name though.
1072 try QueryInformationFile(hFile, .FileNormalizedNameInformation, &path_buffer);
1073 const file_name = @ptrCast(*const FILE_NAME_INFORMATION, &path_buffer);
1074 file_name_u16 = @ptrCast([*]const u16, &file_name.FileName)[0..@divExact(file_name.FileNameLength, 2)];
1075
1076 // Get NT volume name.
1077 try QueryInformationFile(hFile, .FileVolumeNameInformation, &volume_buffer);
1078 const volume_name_info = @ptrCast(*const FILE_NAME_INFORMATION, &volume_buffer);
1079 volume_name_u16 = @ptrCast([*]const u16, &volume_name_info.FileName)[0..@divExact(volume_name_info.FileNameLength, 2)];
1048 },
1049 .Dos => {
1050 // parse the string to separate volume path from file path
1051 const expected_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");
10801052
1081 if (fmt.volume_name == .Nt) {
1082 // Nothing to do, we simply copy the bytes to the user-provided buffer.
1083 if (out_buffer.len < volume_name_u16.len + file_name_u16.len) return error.NameTooLong;
1053 // TODO find out if a path can start with something besides `\Device\<volume name>`,
1054 // and if we need to handle it differently
1055 // (i.e. how to determine the start and end of the volume name in that case)
1056 if (!mem.eql(u16, expected_prefix, final_path[0..expected_prefix.len])) return error.Unexpected;
10841057
1085 mem.copy(u16, out_buffer, volume_name_u16);
1086 mem.copy(u16, out_buffer[volume_name_u16.len..], file_name_u16);
1058 const file_path_begin_index = mem.indexOfPos(u16, final_path, expected_prefix.len, &[_]u16{'\\'}) orelse unreachable;
1059 const volume_name_u16 = final_path[0..file_path_begin_index];
1060 const file_name_u16 = final_path[file_path_begin_index..];
10871061
1088 return out_buffer[0 .. volume_name_u16.len + file_name_u16.len];
1089 }
1090 //fallthrough for fmt.volume_name != .Nt
1091 }
1092
1093 switch (fmt.volume_name) {
1094 .Nt => unreachable, //handled above
1095 .Dos => {
10961062 // Get DOS volume name. DOS volume names are actually symbolic link objects to the
10971063 // actual NT volume. For example:
10981064 // (NT) \Device\HarddiskVolume4 => (DOS) \DosDevices\C: == (DOS) C: