zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 289f2f0d3455d2bdefb84af84075602c53a730bd (tree)
parent 66fe584eade01f5f71e565ba2fbf036436c4bf5a
Author: Ryan Liptak <squeek502@hotmail.com>
Date:   Mon, 24 Nov 2025 07:17:30 -0800

Merge pull request #17541 from moosichu/fix/wine-get-final-path-name-by-handle

Windows: Deal with NT namespaced paths in GetFinalPathNameByHandle
Diffstat:
Mlib/std/os/windows.zig | 29+++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig @@ -1392,16 +1392,29 @@ pub fn GetFinalPathNameByHandle( }, .Dos => { // 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; + const device_prefix = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\"); + + // 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.startsWith(u16, final_path, device_prefix)) { + // Wine seems to return NT namespaced paths starting with \??\ 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. + // https://github.com/ziglang/zig/issues/26029 + // https://bugs.winehq.org/show_bug.cgi?id=39569 + return ntToWin32Namespace(final_path, out_buffer) catch |err| switch (err) { + error.NotNtPath => return error.Unexpected, + error.NameTooLong => |e| return e, + }; + } - const file_path_begin_index = mem.indexOfPos(u16, final_path, expected_prefix.len, &[_]u16{'\\'}) orelse unreachable; + const file_path_begin_index = mem.indexOfPos(u16, final_path, device_prefix.len, &[_]u16{'\\'}) orelse unreachable; const volume_name_u16 = final_path[0..file_path_begin_index]; - const device_name_u16 = volume_name_u16[expected_prefix.len..]; + const device_name_u16 = volume_name_u16[device_prefix.len..]; const file_name_u16 = final_path[file_path_begin_index..]; // MUP is Multiple UNC Provider, and indicates that the path is a UNC