Skip to content

Commit 289f2f0

Browse files
authored
Merge pull request #17541 from moosichu/fix/wine-get-final-path-name-by-handle
Windows: Deal with NT namespaced paths in GetFinalPathNameByHandle
2 parents 66fe584 + d48faf1 commit 289f2f0

1 file changed

Lines changed: 21 additions & 8 deletions

File tree

lib/std/os/windows.zig

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,16 +1392,29 @@ pub fn GetFinalPathNameByHandle(
13921392
},
13931393
.Dos => {
13941394
// parse the string to separate volume path from file path
1395-
const expected_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");
1396-
1397-
// TODO find out if a path can start with something besides `\Device\<volume name>`,
1398-
// and if we need to handle it differently
1399-
// (i.e. how to determine the start and end of the volume name in that case)
1400-
if (!mem.eql(u16, expected_prefix, final_path[0..expected_prefix.len])) return error.Unexpected;
1395+
const device_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");
1396+
1397+
// We aren't entirely sure of the structure of the path returned by
1398+
// QueryObjectName in all contexts/environments.
1399+
// This code is written to cover the various cases that have
1400+
// been encountered and solved appropriately. But note that there's
1401+
// no easy way to verify that they have all been tackled!
1402+
// (Unless you, the reader knows of one then please do action that!)
1403+
if (!mem.startsWith(u16, final_path, device_prefix)) {
1404+
// Wine seems to return NT namespaced paths starting with \??\ from QueryObjectName
1405+
// (e.g. `\??\Z:\some\path\to\a\file.txt`), in which case we can just strip the
1406+
// prefix to turn it into an absolute path.
1407+
// https://github.com/ziglang/zig/issues/26029
1408+
// https://bugs.winehq.org/show_bug.cgi?id=39569
1409+
return ntToWin32Namespace(final_path, out_buffer) catch |err| switch (err) {
1410+
error.NotNtPath => return error.Unexpected,
1411+
error.NameTooLong => |e| return e,
1412+
};
1413+
}
14011414

1402-
const file_path_begin_index = mem.indexOfPos(u16, final_path, expected_prefix.len, &[_]u16{'\\'}) orelse unreachable;
1415+
const file_path_begin_index = mem.indexOfPos(u16, final_path, device_prefix.len, &[_]u16{'\\'}) orelse unreachable;
14031416
const volume_name_u16 = final_path[0..file_path_begin_index];
1404-
const device_name_u16 = volume_name_u16[expected_prefix.len..];
1417+
const device_name_u16 = volume_name_u16[device_prefix.len..];
14051418
const file_name_u16 = final_path[file_path_begin_index..];
14061419

14071420
// MUP is Multiple UNC Provider, and indicates that the path is a UNC

0 commit comments

Comments
 (0)