| ... | @@ -898,7 +898,6 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 { | ... | @@ -898,7 +898,6 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 { |
| 898 | | 898 | |
| 899 | pub const GetFinalPathNameByHandleError = error{ | 899 | pub const GetFinalPathNameByHandleError = error{ |
| 900 | FileNotFound, | 900 | FileNotFound, |
| 901 | SystemResources, | | |
| 902 | NameTooLong, | 901 | NameTooLong, |
| 903 | Unexpected, | 902 | Unexpected, |
| 904 | }; | 903 | }; |
| ... | @@ -963,9 +962,19 @@ pub fn GetFinalPathNameByHandle(hFile: HANDLE, out_buffer: []u16) GetFinalPathNa | ... | @@ -963,9 +962,19 @@ pub fn GetFinalPathNameByHandle(hFile: HANDLE, out_buffer: []u16) GetFinalPathNa |
| 963 | break :blk @as([*]const u16, object_name.Name.Buffer)[0..object_name.Name.Length / 2]; | 962 | break :blk @as([*]const u16, object_name.Name.Buffer)[0..object_name.Name.Length / 2]; |
| 964 | }; | 963 | }; |
| 965 | | 964 | |
| 966 | // Since `NtQueryObject` returns a fully-qualified NT path, we need to translate | 965 | // By now, we got a a fully-qualified NT path, which we need to translate |
| 967 | // the result into a Win32/DOS path (e.g., \Device\HarddiskVolume4\foo would become | 966 | // into a Win32/DOS path, for instance: |
| 968 | // C:\foo). | 967 | // \Device\HarddiskVolume4\foo => C:\foo |
| | 968 | // |
| | 969 | // NOTE: |
| | 970 | // I couldn't figure out a better way of doing this unfortunately... |
| | 971 | // This snippet below is in part based around `QueryDosDeviceW` implementation |
| | 972 | // found in Wine. The trick with `NtQueryDirectoryObject` for some reason |
| | 973 | // only lists `\DosDevices\Global` as the only SymblinkObject available, which |
| | 974 | // means it's not possible to query the kernel for all available DOS volume name |
| | 975 | // symlinks. |
| | 976 | // TODO investigate! |
| | 977 | // Wine source: https://source.winehq.com/git/wine.git/blob/HEAD:/dlls/kernelbase/volume.c#l1009 |
| 969 | const dos_drive_letters = &[_]u16{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; | 978 | const dos_drive_letters = &[_]u16{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; |
| 970 | var query_path = [_]u16{ '\\', 'D', 'o', 's', 'D', 'e', 'v', 'i', 'c', 'e', 's', '\\', 'C', ':' }; | 979 | var query_path = [_]u16{ '\\', 'D', 'o', 's', 'D', 'e', 'v', 'i', 'c', 'e', 's', '\\', 'C', ':' }; |
| 971 | for (dos_drive_letters) |drive_letter| { | 980 | for (dos_drive_letters) |drive_letter| { |
| ... | @@ -1010,14 +1019,17 @@ pub fn GetFinalPathNameByHandle(hFile: HANDLE, out_buffer: []u16) GetFinalPathNa | ... | @@ -1010,14 +1019,17 @@ pub fn GetFinalPathNameByHandle(hFile: HANDLE, out_buffer: []u16) GetFinalPathNa |
| 1010 | const link_path = @as([*]const u16, link.Buffer)[0..link.Length / 2]; | 1019 | const link_path = @as([*]const u16, link.Buffer)[0..link.Length / 2]; |
| 1011 | const idx = std.mem.indexOf(u16, object_path, link_path) orelse continue; | 1020 | const idx = std.mem.indexOf(u16, object_path, link_path) orelse continue; |
| 1012 | | 1021 | |
| 1013 | // TODO check the provided buffer is actually big enough. | 1022 | // TODO is this the most appropriate error here? |
| | 1023 | if (out_buffer.len < drive.len + object_path.len) return error.NameTooLong; |
| | 1024 | |
| 1014 | std.mem.copy(u16, out_buffer[0..], drive[0..]); | 1025 | std.mem.copy(u16, out_buffer[0..], drive[0..]); |
| 1015 | std.mem.copy(u16, out_buffer[2..], object_path[link_path.len..]); | 1026 | std.mem.copy(u16, out_buffer[2..], object_path[link_path.len..]); |
| 1016 | | 1027 | |
| 1017 | return out_buffer[0..object_path.len - link_path.len + 2]; | 1028 | return out_buffer[0..object_path.len - link_path.len + 2]; |
| 1018 | } | 1029 | } |
| 1019 | | 1030 | |
| 1020 | // If we're here, that means there was no match so error out! | 1031 | // If we're here, that means there was no match so we panic! |
| | 1032 | // TODO should we actually panic here or return an error instead? |
| 1021 | unreachable; | 1033 | unreachable; |
| 1022 | } | 1034 | } |
| 1023 | | 1035 | |