Skip to content

Commit

Permalink
Deal with NT paths in GetFinalPathNameByHandle
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
moosichu and squeek502 committed Oct 15, 2023
1 parent 7abf9b3 commit a52a3ca
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions lib/std/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1221,10 +1221,27 @@ pub fn GetFinalPathNameByHandle(
// parse the string to separate volume path from file path
const expected_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\");

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

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

0 comments on commit a52a3ca

Please sign in to comment.