@@ -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