@@ -1219,16 +1219,33 @@ pub fn GetFinalPathNameByHandle(
1219
1219
},
1220
1220
.Dos = > {
1221
1221
// parse the string to separate volume path from file path
1222
- const expected_prefix = std .unicode .utf8ToUtf16LeStringLiteral ("\\ Device\\ " );
1223
-
1224
- // TODO find out if a path can start with something besides `\Device\<volume name>`,
1225
- // and if we need to handle it differently
1226
- // (i.e. how to determine the start and end of the volume name in that case)
1227
- if (! mem .eql (u16 , expected_prefix , final_path [0.. expected_prefix .len ])) return error .Unexpected ;
1222
+ const device_prefix = std .unicode .utf8ToUtf16LeStringLiteral ("\\ Device\\ " );
1223
+
1224
+ // We aren't entirely sure of the structure of the path returned by
1225
+ // QueryObjectName in all contexts/environments.
1226
+ // This code is written to cover the various cases that have
1227
+ // been encountered and solved appropriately. But note that there's
1228
+ // no easy way to verify that they have all been tackled!
1229
+ // (Unless you, the reader knows of one then please do action that!)
1230
+ if (! mem .eql (u16 , device_prefix , final_path [0.. device_prefix .len ])) {
1231
+ // Wine seems to return NT namespaced paths from QueryObjectName
1232
+ // (e.g. `\??\Z:\some\path\to\a\file.txt`), in which case we can just strip the
1233
+ // prefix to turn it into an absolute paths
1234
+ const namespace_prefix = getNamespacePrefix (u16 , final_path );
1235
+ if (namespace_prefix == .nt ) {
1236
+ const unprefixed_path = final_path [NamespacePrefix .len .. ];
1237
+ // TODO: Handle other possible path types, only drive absolute has been observed so far
1238
+ if (getUnprefixedPathType (u16 , unprefixed_path ) != .drive_absolute ) {
1239
+ return error .Unexpected ;
1240
+ }
1241
+ return unprefixed_path ;
1242
+ }
1243
+ return error .Unexpected ;
1244
+ }
1228
1245
1229
- const file_path_begin_index = mem .indexOfPos (u16 , final_path , expected_prefix .len , &[_ ]u16 {'\\ ' }) orelse unreachable ;
1246
+ const file_path_begin_index = mem .indexOfPos (u16 , final_path , device_prefix .len , &[_ ]u16 {'\\ ' }) orelse unreachable ;
1230
1247
const volume_name_u16 = final_path [0.. file_path_begin_index ];
1231
- const device_name_u16 = volume_name_u16 [expected_prefix .len .. ];
1248
+ const device_name_u16 = volume_name_u16 [device_prefix .len .. ];
1232
1249
const file_name_u16 = final_path [file_path_begin_index .. ];
1233
1250
1234
1251
// MUP is Multiple UNC Provider, and indicates that the path is a UNC
@@ -2343,6 +2360,9 @@ pub const NamespacePrefix = enum {
2343
2360
fake_verbatim ,
2344
2361
/// `\??\`
2345
2362
nt ,
2363
+
2364
+ // The length of all the prefixes (except `none`)
2365
+ pub const len : usize = 4 ;
2346
2366
};
2347
2367
2348
2368
/// If `T` is `u16`, then `path` should be encoded as UTF-16LE.
0 commit comments