diff --git a/CHANGELIST.md b/CHANGELIST.md index 7c3b7938..ccc1ca9e 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -65,6 +65,7 @@ - Add Redumper Universal Hash support - Fix Redumper write offset support - Add Redumper non-zero data start +- Use media size for type detection on .NET 6 ### 2.4 (2022-10-26) diff --git a/MPF.Core/Data/Drive.cs b/MPF.Core/Data/Drive.cs index a82b8cfd..c3d494fe 100644 --- a/MPF.Core/Data/Drive.cs +++ b/MPF.Core/Data/Drive.cs @@ -166,7 +166,83 @@ namespace MPF.Core.Data /// /// public (MediaType?, string) GetMediaType() - => GetMediaType(this.Name, this.InternalDriveType); + { + // Take care of the non-optical stuff first + // TODO: See if any of these can be more granular, like Optical is + if (this.InternalDriveType == Data.InternalDriveType.Floppy) + return (MediaType.FloppyDisk, null); + else if (this.InternalDriveType == Data.InternalDriveType.HardDisk) + return (MediaType.HardDisk, null); + else if (this.InternalDriveType == Data.InternalDriveType.Removable) + return (MediaType.FlashDrive, null); +#if NET6_0_OR_GREATER + else + return GetMediaTypeFromSize(); +#endif + + // Get the current drive information + string deviceId = null; + bool loaded = false; + try + { + // Get the device ID first + CimSession session = CimSession.Create(null); + var collection = session.QueryInstances("root\\CIMV2", "WQL", $"SELECT * FROM Win32_CDROMDrive WHERE Id = '{this.Letter}:\'"); + + foreach (CimInstance instance in collection) + { + CimKeyedCollection properties = instance.CimInstanceProperties; + deviceId = (string)properties["DeviceID"]?.Value; + loaded = (bool)properties["MediaLoaded"]?.Value; + } + + // If we got no valid device, we don't care and just return + if (deviceId == null) + return (null, "Device could not be found"); + else if (!loaded) + return (null, "Device is not reporting media loaded"); + +#if NETFRAMEWORK + + MsftDiscMaster2 discMaster = new MsftDiscMaster2(); + deviceId = deviceId.ToLower().Replace('\\', '#').Replace('/', '#'); + string id = null; + foreach (var disc in discMaster) + { + if (disc.ToString().Contains(deviceId)) + id = disc.ToString(); + } + + // If we couldn't find the drive, we don't care and return + if (id == null) + return (null, "Device ID could not be found"); + + // Create the required objects for reading from the drive + MsftDiscRecorder2 recorder = new MsftDiscRecorder2(); + recorder.InitializeDiscRecorder(id); + MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data(); + + // If the recorder is not supported, just return + if (!dataWriter.IsRecorderSupported(recorder)) + return (null, "IMAPI2 recorder not supported"); + + // Otherwise, set the recorder to get information from + dataWriter.Recorder = recorder; + + var media = dataWriter.CurrentPhysicalMediaType; + return (media.IMAPIToMediaType(), null); + +#else + + return (null, "IMAPI2 recorder not supported"); + +#endif + } + catch (Exception ex) + { + return (null, ex.Message); + } + } /// /// Get the current system from drive @@ -488,17 +564,17 @@ namespace MPF.Core.Data #region Helpers /// - /// Get the media type for a device path + /// Get the media type for a device path based on size /// /// MediaType, null on error - private (MediaType?, string) GetMediaTypeFromFilesystemName() + private (MediaType?, string) GetMediaTypeFromSize() { - switch (this.DriveFormat) - { - case "CDFS": return (MediaType.CDROM, null); - case "UDF": return (MediaType.DVD, null); // TODO: UDF is not specific enough - default: return (null, $"Unrecognized format: {this.DriveFormat}"); - } + if (this.TotalSize >= 0 && this.TotalSize < 800_000_000 && this.DriveFormat == "CDFS") + return (MediaType.CDROM, null); + else if (this.TotalSize >= 400_000_000 && this.TotalSize <= 8_540_000_000 && this.DriveFormat == "UDF") + return (MediaType.DVD, null); + else + return (MediaType.BluRay, null); } /// @@ -552,93 +628,6 @@ namespace MPF.Core.Data return drives; } - /// - /// Get the media type for a device path using the Aaru libraries - /// - /// Path to the device - /// Current internal drive type - /// MediaType, null on error - private static (MediaType?, string) GetMediaType(string devicePath, InternalDriveType? internalDriveType) - { - char driveLetter = devicePath == null || !devicePath.Any() ? '\0' : devicePath[0]; - - // Take care of the non-optical stuff first - // TODO: See if any of these can be more granular, like Optical is - if (internalDriveType == Data.InternalDriveType.Floppy) - return (MediaType.FloppyDisk, null); - else if (internalDriveType == Data.InternalDriveType.HardDisk) - return (MediaType.HardDisk, null); - else if (internalDriveType == Data.InternalDriveType.Removable) - return (MediaType.FlashDrive, null); -#if NET6_0_OR_GREATER - else - return Create(internalDriveType, devicePath).GetMediaTypeFromFilesystemName(); -#endif - - // Get the current drive information - string deviceId = null; - bool loaded = false; - try - { - // Get the device ID first - CimSession session = CimSession.Create(null); - var collection = session.QueryInstances("root\\CIMV2", "WQL", $"SELECT * FROM Win32_CDROMDrive WHERE Id = '{driveLetter}:\'"); - - foreach (CimInstance instance in collection) - { - CimKeyedCollection properties = instance.CimInstanceProperties; - deviceId = (string)properties["DeviceID"]?.Value; - loaded = (bool)properties["MediaLoaded"]?.Value; - } - - // If we got no valid device, we don't care and just return - if (deviceId == null) - return (null, "Device could not be found"); - else if (!loaded) - return (null, "Device is not reporting media loaded"); - -#if NETFRAMEWORK - - MsftDiscMaster2 discMaster = new MsftDiscMaster2(); - deviceId = deviceId.ToLower().Replace('\\', '#').Replace('/', '#'); - string id = null; - foreach (var disc in discMaster) - { - if (disc.ToString().Contains(deviceId)) - id = disc.ToString(); - } - - // If we couldn't find the drive, we don't care and return - if (id == null) - return (null, "Device ID could not be found"); - - // Create the required objects for reading from the drive - MsftDiscRecorder2 recorder = new MsftDiscRecorder2(); - recorder.InitializeDiscRecorder(id); - MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data(); - - // If the recorder is not supported, just return - if (!dataWriter.IsRecorderSupported(recorder)) - return (null, "IMAPI2 recorder not supported"); - - // Otherwise, set the recorder to get information from - dataWriter.Recorder = recorder; - - var media = dataWriter.CurrentPhysicalMediaType; - return (media.IMAPIToMediaType(), null); - -#else - - return (null, "IMAPI2 recorder not supported"); - -#endif - } - catch (Exception ex) - { - return (null, ex.Message); - } - } - #endregion } }