| 219 | } |
| 220 | |
| 221 | inline WasiExpect<std::filesystem::path> |
| 222 | getHandlePath(HANDLE_ Handle) noexcept { |
| 223 | // First get the path of the handle |
| 224 | #if NTDDI_VERSION >= NTDDI_VISTA |
| 225 | std::array<wchar_t, UNICODE_STRING_MAX_CHARS_ + 1> Buffer; |
| 226 | const auto Size = GetFinalPathNameByHandleW( |
| 227 | Handle, Buffer.data(), static_cast<DWORD_>(Buffer.size()), |
| 228 | FILE_NAME_NORMALIZED_ | VOLUME_NAME_DOS_); |
| 229 | if (unlikely(Size == 0)) { |
| 230 | return WasiUnexpect(detail::fromLastError(GetLastError())); |
| 231 | } |
| 232 | std::wstring_view Path(Buffer.data(), Size); |
| 233 | if (Path.size() >= 4 && Path[0] == L'\\' && Path[1] == L'\\' && |
| 234 | Path[2] == L'?' && Path[3] == L'\\') { |
| 235 | Path = Path.substr(4); |
| 236 | } |
| 237 | return std::filesystem::path(Path); |
| 238 | #else |
| 239 | union { |
| 240 | OBJECT_NAME_INFORMATION_ Info; |
| 241 | std::array<char, sizeof(OBJECT_NAME_INFORMATION_) + |
| 242 | (MAX_PATH_ + 1) * sizeof(wchar_t)> |
| 243 | RawData; |
| 244 | } Buffer; |
| 245 | ULONG_ ReturnLength; |
| 246 | if (const auto Status = |
| 247 | NtQueryObject(Handle, ObjectNameInformation_, &Buffer, |
| 248 | sizeof(Buffer) - sizeof(wchar_t), &ReturnLength); |
| 249 | unlikely(!NT_SUCCESS_(Status))) { |
| 250 | return WasiUnexpect(detail::fromLastError(RtlNtStatusToDosError(Status))); |
| 251 | } |
| 252 | std::wstring_view LogicVolumePath(Buffer.Info.Name.Buffer, |
| 253 | Buffer.Info.Name.Length / sizeof(wchar_t)); |
| 254 | |
| 255 | // return format is like "A:\\\0B:\\\0C:\\\0\0" |
| 256 | std::array<wchar_t, 4 * 26 + 1> Drives; |
| 257 | const auto Size = GetLogicalDriveStringsW(Drives.size(), Drives.data()); |
| 258 | assuming(Size < Drives.size()); |
| 259 | // logic format is like "\Device\HarddiskVolume1\" |
| 260 | std::array<wchar_t, MAX_PATH_ + 1> FullName; |
| 261 | wchar_t Name[] = L" :"; |
| 262 | for (wchar_t *Iter = Drives.data(); *Iter != L'\0'; |
| 263 | Iter += std::wcslen(Iter) + 1) { |
| 264 | Name[0] = Iter[0]; |
| 265 | if (const auto FullNameSize = |
| 266 | QueryDosDeviceW(Name, FullName.data(), FullName.size()); |
| 267 | unlikely(!FullNameSize)) { |
| 268 | return WasiUnexpect(detail::fromLastError(GetLastError())); |
| 269 | } else { |
| 270 | // FullNameSize include L'\0', append backslash to FullName |
| 271 | FullName[FullNameSize - 2] = '\\'; |
| 272 | if (std::wcsncmp(FullName.data(), LogicVolumePath.data(), |
| 273 | FullNameSize - 1) == 0) { |
| 274 | std::filesystem::path Result(Iter); |
| 275 | Result /= LogicVolumePath.substr(FullNameSize - 1); |
| 276 | return Result; |
| 277 | } |
| 278 | } |
no test coverage detected