/
githubmirror
/
Files
Обзор
Документация
Войти
/
githubmirror
/
Files
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Files.App/Utils/Storage/Helpers/DriveHelpers.cs
183 строки
6 KB
Saravanan G
Fix: Fixed issue where the Customize tab was shown for folders that don't support custom icons (#18762)
26 июл 2026, 17:11
Не верифицирован
26 июл 2026, 17:11
3dfd70a
Код
Авторство
О чём код?
// Copyright (c) Files Community // Licensed under the MIT License. using DiscUtils.Udf; using Windows.Devices.Enumeration; using Windows.Devices.Portable; using Windows.Storage; using Windows.Storage.FileProperties; using Windows.Win32; using Windows.Win32.Foundation; namespace Files.App.Utils.Storage { public static class DriveHelpers { public static async void EjectDeviceAsync(string path) { await ContextMenu.InvokeVerb("eject", path); } public static async Task<bool> CheckEmptyDrive(string? drivePath) { if (string.IsNullOrWhiteSpace(drivePath)) return false; var drivesViewModel = Ioc.Default.GetRequiredService<DrivesViewModel>(); var matchingDrive = drivesViewModel.Drives.Cast<DriveItem>().FirstOrDefault(x => drivePath.StartsWith(x.Path, StringComparison.Ordinal)); if (matchingDrive is null || matchingDrive.Type != Data.Items.DriveType.CDRom || matchingDrive.MaxSpace != ByteSizeLib.ByteSize.FromBytes(0)) return false; var ejectButton = await DialogDisplayHelper.ShowDialogAsync( Strings.InsertDiscDialogTitle.GetLocalizedResource(), string.Format(Strings.InsertDiscDialogText.GetLocalizedResource(), matchingDrive.Path), Strings.InsertDiscDialog_OpenDriveButton.GetLocalizedResource(), Strings.Close.GetLocalizedResource()); if (ejectButton) EjectDeviceAsync(matchingDrive.Path); return true; } public static async Task<StorageFolderWithPath> GetRootFromPathAsync(string devicePath) { if (!SystemIO.Path.IsPathRooted(devicePath)) return null; var drivesViewModel = Ioc.Default.GetRequiredService<DrivesViewModel>(); var rootPath = SystemIO.Path.GetPathRoot(devicePath); if (devicePath.StartsWith(@"\\?\", StringComparison.Ordinal)) // USB device { // Check among already discovered drives StorageFolder matchingDrive = drivesViewModel.Drives.Cast<DriveItem>().FirstOrDefault(x => Helpers.PathNormalization.NormalizePath(x.Path) == Helpers.PathNormalization.NormalizePath(rootPath))?.Root; if (matchingDrive is null) { // Check on all removable drives var remDevices = await DeviceInformation.FindAllAsync(StorageDevice.GetDeviceSelector()); string normalizedRootPath = Helpers.PathNormalization.NormalizePath(rootPath).Replace(@"\\?\", string.Empty, StringComparison.Ordinal); foreach (var item in remDevices) { try { var root = StorageDevice.FromId(item.Id); if (normalizedRootPath == root.Name.ToUpperInvariant()) { matchingDrive = root; break; } } catch (Exception) { // Ignore this.. } } } if (matchingDrive is not null) { return new StorageFolderWithPath(matchingDrive, rootPath); } } // Network share else if ( (devicePath.StartsWith(@"\\", StringComparison.Ordinal) || GetDriveType(new SystemIO.DriveInfo(devicePath)) is DriveType.Network) && !devicePath.StartsWith(@"\\SHELL\", StringComparison.Ordinal) ) { int lastSepIndex = rootPath.LastIndexOf('\\'); rootPath = lastSepIndex > 1 ? rootPath.Substring(0, lastSepIndex) : rootPath; // Remove share name return new StorageFolderWithPath(await StorageFolder.GetFolderFromPathAsync(rootPath), rootPath); } // It's ok to return null here, on normal drives StorageFolder.GetFolderFromPathAsync works return null; } public static bool IsMtpPath(string path) { return path.StartsWith(@"\\?\", StringComparison.Ordinal); } public static bool IsNetworkPath(string path) { if (IsMtpPath(path)) return false; try { return path.StartsWith(@"\\", StringComparison.Ordinal) || GetDriveType(new SystemIO.DriveInfo(path)) is Data.Items.DriveType.Network; } catch { return false; } } public static Data.Items.DriveType GetDriveType(System.IO.DriveInfo drive) { if (drive.DriveType is System.IO.DriveType.Unknown) { string path = PathNormalization.NormalizePath(drive.Name); if (path is "A:" or "B:") return Data.Items.DriveType.FloppyDisk; } return drive.DriveType switch { SystemIO.DriveType.CDRom => Data.Items.DriveType.CDRom, SystemIO.DriveType.Fixed => Data.Items.DriveType.Fixed, SystemIO.DriveType.Network => Data.Items.DriveType.Network, SystemIO.DriveType.NoRootDirectory => Data.Items.DriveType.NoRootDirectory, SystemIO.DriveType.Ram => Data.Items.DriveType.Ram, SystemIO.DriveType.Removable => Data.Items.DriveType.Removable, _ => Data.Items.DriveType.Unknown, }; } public static unsafe string GetExtendedDriveLabel(SystemIO.DriveInfo drive) { return SafetyExtensions.IgnoreExceptions(() => { if (drive.DriveType is not SystemIO.DriveType.CDRom || drive.DriveFormat is not "UDF") return drive.VolumeLabel; return SafetyExtensions.IgnoreExceptions(() => { string dosDevicePath = ""; fixed (char* cDeviceName = drive.Name) { var cch = PInvoke.QueryDosDevice(cDeviceName, null, 0u); fixed (char* cTargetPath = new char[cch]) { PWSTR pszTargetPath = new(cTargetPath); PInvoke.QueryDosDevice(cDeviceName, pszTargetPath, 0u); dosDevicePath = pszTargetPath.ToString(); } } if (string.IsNullOrEmpty(dosDevicePath)) return drive.VolumeLabel; using var driveStream = new SystemIO.FileStream( dosDevicePath.Replace(@"\Device\", @"\\.\"), SystemIO.FileMode.Open, SystemIO.FileAccess.Read); using var udf = new UdfReader(driveStream); return udf.VolumeLabel; }) ?? drive.VolumeLabel; }) ?? ""; } public static async Task<StorageItemThumbnail> GetThumbnailAsync(StorageFolder folder) => (StorageItemThumbnail)await FilesystemTasks.Wrap(() => folder.GetThumbnailAsync(ThumbnailMode.SingleItem, 40, ThumbnailOptions.UseCurrentScale).AsTask() ); } }