Skip to content

Commit a142049

Browse files
nolandercVexu
authored andcommitted
windows: support UNC paths
Fixes #8205 and #12729. The old method of prepending `\??\` at the start of the DOS path produced invalid strings for UNC paths (such as those found in WSL). Instead, we rely on the conversion routine in ntdll, which should handle all current and future edge cases properly.
1 parent ce3fe72 commit a142049

File tree

1 file changed

+13
-30
lines changed

1 file changed

+13
-30
lines changed

lib/std/os/windows.zig

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,37 +2002,20 @@ pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {
20022002
pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
20032003
// TODO https://github.com/ziglang/zig/issues/2765
20042004
var path_space: PathSpace = undefined;
2005-
const prefix = "\\??\\";
2006-
const prefix_index: usize = if (mem.startsWith(u8, s, prefix)) prefix.len else 0;
2007-
for (s[prefix_index..]) |byte| {
2008-
switch (byte) {
2009-
'*', '?', '"', '<', '>', '|' => return error.BadPathName,
2010-
else => {},
2011-
}
2012-
}
2013-
const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' };
2014-
const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {
2015-
mem.copy(u16, path_space.data[0..], prefix_u16[0..]);
2016-
break :blk prefix_u16.len;
2017-
};
2018-
path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
2019-
if (path_space.len > path_space.data.len) return error.NameTooLong;
2020-
path_space.len = start_index + (normalizePath(u16, path_space.data[start_index..path_space.len]) catch |err| switch (err) {
2021-
error.TooManyParentDirs => {
2022-
if (!std.fs.path.isAbsolute(s)) {
2023-
var temp_path: PathSpace = undefined;
2024-
temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, s);
2025-
std.debug.assert(temp_path.len == path_space.len);
2026-
temp_path.data[path_space.len] = 0;
2027-
path_space.len = prefix_u16.len + try getFullPathNameW(&temp_path.data, path_space.data[prefix_u16.len..]);
2028-
mem.copy(u16, &path_space.data, &prefix_u16);
2029-
std.debug.assert(path_space.data[path_space.len] == 0);
2030-
return path_space;
2031-
}
2032-
return error.BadPathName;
2033-
},
2034-
});
2005+
2006+
path_space.len = try std.unicode.utf8ToUtf16Le(&path_space.data, s);
20352007
path_space.data[path_space.len] = 0;
2008+
2009+
var out: UNICODE_STRING = undefined;
2010+
if (ntdll.RtlDosPathNameToNtPathName_U(path_space.span(), &out, null, null) == FALSE)
2011+
return error.BadPathName;
2012+
defer ntdll.RtlFreeUnicodeString(&out);
2013+
2014+
const out_path = out.Buffer[0 .. out.Length / 2];
2015+
mem.copy(u16, path_space.data[0..], out_path);
2016+
path_space.len = out.Length / 2;
2017+
path_space.data[path_space.len] = 0;
2018+
20362019
return path_space;
20372020
}
20382021

0 commit comments

Comments
 (0)