Skip to content

Commit aaccbf5

Browse files
moosichusqueek502
andcommitted
Deal with NT paths in GetFinalPathNameByHandle
When calling QueryObjectName, NT namespaced paths can be returned. This change appropriately strips the prefix to turn it into an absolute path. (The above behaviour was observed at least in Wine so far) Co-authored-by: Ryan Liptak <[email protected]>
1 parent 7abf9b3 commit aaccbf5

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

lib/std/os/windows.zig

+21-4
Original file line numberDiff line numberDiff line change
@@ -1221,10 +1221,27 @@ pub fn GetFinalPathNameByHandle(
12211221
// parse the string to separate volume path from file path
12221222
const expected_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");
12231223

1224-
// TODO find out if a path can start with something besides `\Device\<volume name>`,
1225-
// and if we need to handle it differently
1226-
// (i.e. how to determine the start and end of the volume name in that case)
1227-
if (!mem.eql(u16, expected_prefix, final_path[0..expected_prefix.len])) return error.Unexpected;
1224+
// We aren't entirely sure of the structure of the path returned by
1225+
// QueryObjectName in all contexts/environments.
1226+
// This code is written to cover the various cases that have
1227+
// been encountered and solved appropriately. But note that there's
1228+
// no easy way to verify that they have all been tackled!
1229+
// (Unless you, the reader knows of one then please do action that!)
1230+
if (!mem.eql(u16, expected_prefix, final_path[0..expected_prefix.len])) {
1231+
// Wine seems to return NT namespaced paths from QueryObjectName
1232+
// (e.g. `\??\Z:\some\path\to\a\file.txt`), in which case we can just strip the
1233+
// prefix to turn it into an absolute path
1234+
if (getNamespacePrefix(u16, final_path) == .nt) {
1235+
const unprefixed_path = final_path[4..];
1236+
// TODO: Handle other possible path types, only drive absolute has been observed so far
1237+
if (getUnprefixedPathType(u16, unprefixed_path) != .drive_absolute) {
1238+
return error.Unexpected;
1239+
}
1240+
mem.copyForwards(u16, out_buffer[0..unprefixed_path.len], unprefixed_path);
1241+
return out_buffer[0..unprefixed_path.len];
1242+
}
1243+
return error.Unexpected;
1244+
}
12281245

12291246
const file_path_begin_index = mem.indexOfPos(u16, final_path, expected_prefix.len, &[_]u16{'\\'}) orelse unreachable;
12301247
const volume_name_u16 = final_path[0..file_path_begin_index];

0 commit comments

Comments
 (0)