@@ -1291,16 +1291,33 @@ pub fn GetFinalPathNameByHandle(
1291
1291
},
1292
1292
.Dos = > {
1293
1293
// parse the string to separate volume path from file path
1294
- const expected_prefix = std .unicode .utf8ToUtf16LeStringLiteral ("\\ Device\\ " );
1295
-
1296
- // TODO find out if a path can start with something besides `\Device\<volume name>`,
1297
- // and if we need to handle it differently
1298
- // (i.e. how to determine the start and end of the volume name in that case)
1299
- if (! mem .eql (u16 , expected_prefix , final_path [0.. expected_prefix .len ])) return error .Unexpected ;
1294
+ const device_prefix = std .unicode .utf8ToUtf16LeStringLiteral ("\\ Device\\ " );
1295
+
1296
+ // We aren't entirely sure of the structure of the path returned by
1297
+ // QueryObjectName in all contexts/environments.
1298
+ // This code is written to cover the various cases that have
1299
+ // been encountered and solved appropriately. But note that there's
1300
+ // no easy way to verify that they have all been tackled!
1301
+ // (Unless you, the reader knows of one then please do action that!)
1302
+ if (! mem .eql (u16 , device_prefix , final_path [0.. device_prefix .len ])) {
1303
+ // Wine seems to return NT namespaced paths from QueryObjectName
1304
+ // (e.g. `\??\Z:\some\path\to\a\file.txt`), in which case we can just strip the
1305
+ // prefix to turn it into an absolute paths
1306
+ const namespace_prefix = getNamespacePrefix (u16 , final_path );
1307
+ if (namespace_prefix == .nt ) {
1308
+ const unprefixed_path = final_path [NamespacePrefix .len .. ];
1309
+ // TODO: Handle other possible path types, only drive absolute has been observed so far
1310
+ if (getUnprefixedPathType (u16 , unprefixed_path ) != .drive_absolute ) {
1311
+ return error .Unexpected ;
1312
+ }
1313
+ return unprefixed_path ;
1314
+ }
1315
+ return error .Unexpected ;
1316
+ }
1300
1317
1301
- const file_path_begin_index = mem .indexOfPos (u16 , final_path , expected_prefix .len , &[_ ]u16 {'\\ ' }) orelse unreachable ;
1318
+ const file_path_begin_index = mem .indexOfPos (u16 , final_path , device_prefix .len , &[_ ]u16 {'\\ ' }) orelse unreachable ;
1302
1319
const volume_name_u16 = final_path [0.. file_path_begin_index ];
1303
- const device_name_u16 = volume_name_u16 [expected_prefix .len .. ];
1320
+ const device_name_u16 = volume_name_u16 [device_prefix .len .. ];
1304
1321
const file_name_u16 = final_path [file_path_begin_index .. ];
1305
1322
1306
1323
// MUP is Multiple UNC Provider, and indicates that the path is a UNC
@@ -2558,6 +2575,9 @@ pub const NamespacePrefix = enum {
2558
2575
fake_verbatim ,
2559
2576
/// `\??\`
2560
2577
nt ,
2578
+
2579
+ // The length of all the prefixes (except `none`)
2580
+ pub const len : usize = 4 ;
2561
2581
};
2562
2582
2563
2583
/// If `T` is `u16`, then `path` should be encoded as WTF-16LE.
0 commit comments