diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index d40fee8db241..650904d45e3d 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -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\`, - // 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];