Exemplo n.º 1
0
        /// <summary>
        /// Get the current media type from drive letter
        /// </summary>
        /// <param name="drive"></param>
        /// <returns></returns>
        /// <remarks>
        /// This may eventually be replaced by Aaru.Devices being able to be about 10x more accurate.
        /// This will also end up making it so that IMAPI2 is no longer necessary. Unfortunately, that
        /// will only work for .NET Core 3.1 and beyond.
        /// </remarks>
        public static (MediaType?, string) GetMediaType(Drive drive)
        {
            // Take care of the non-optical stuff first
            // TODO: See if any of these can be more granular, like Optical is
            if (drive.InternalDriveType == InternalDriveType.Floppy)
            {
                return(MediaType.FloppyDisk, null);
            }
            else if (drive.InternalDriveType == InternalDriveType.HardDisk)
            {
                return(MediaType.HardDisk, null);
            }
            else if (drive.InternalDriveType == InternalDriveType.Removable)
            {
                return(MediaType.FlashDrive, null);
            }

            // Get the current drive information
            string deviceId = null;
            bool   loaded   = false;

            try
            {
                // Get the device ID first
                var searcher = new ManagementObjectSearcher(
                    "root\\CIMV2",
                    $"SELECT * FROM Win32_CDROMDrive WHERE Id = '{drive.Letter}:\'");

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    deviceId = (string)queryObj["DeviceID"];
                    loaded   = (bool)queryObj["MediaLoaded"];
                }

                // 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 NET_FRAMEWORK
                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
                // TODO: This entire .NET Core path still doesn't work
                // This may honestly require an entire import of IMAPI2 stuff and then try
                // as best as possible to get it working.

                return(null, "Media detection only supported on .NET Framework");
#endif
            }
            catch (Exception ex)
            {
                return(null, ex.Message);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get the current system from drive
        /// </summary>
        /// <param name="drive"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static KnownSystem?GetKnownSystem(Drive drive, KnownSystem?defaultValue)
        {
            // If drive or drive letter are provided, we can't do anything
            if (drive?.Letter == null)
            {
                return(defaultValue);
            }

            string drivePath = $"{drive.Letter}:\\";

            // If we can't read the media in that drive, we can't do anything
            if (!Directory.Exists(drivePath))
            {
                return(defaultValue);
            }

            // We're going to assume for floppies, HDDs, and removable drives
            // TODO: Try to be smarter about this
            if (drive.InternalDriveType != InternalDriveType.Optical)
            {
                return(KnownSystem.IBMPCCompatible);
            }

            // Audio CD
            if (drive.VolumeLabel.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
            {
                return(KnownSystem.AudioCD);
            }

            // DVD-Audio
            if (Directory.Exists(Path.Combine(drivePath, "AUDIO_TS")) &&
                Directory.EnumerateFiles(Path.Combine(drivePath, "AUDIO_TS")).Count() > 0)
            {
                return(KnownSystem.DVDAudio);
            }

            // DVD-Video and Xbox
            if (Directory.Exists(Path.Combine(drivePath, "VIDEO_TS")) &&
                Directory.EnumerateFiles(Path.Combine(drivePath, "VIDEO_TS")).Count() > 0)
            {
                // TODO: Maybe add video track hashes to compare for Xbox and X360?
                if (string.Equals(drive.VolumeLabel, "SEP13011042072", StringComparison.OrdinalIgnoreCase))
                {
                    return(KnownSystem.MicrosoftXBOX);
                }

                return(KnownSystem.DVDVideo);
            }

            // HD-DVD-Video
            if (Directory.Exists(Path.Combine(drivePath, "HVDVD_TS")) &&
                Directory.EnumerateFiles(Path.Combine(drivePath, "HVDVD_TS")).Count() > 0)
            {
                return(KnownSystem.HDDVDVideo);
            }

            // Sega Dreamcast
            if (File.Exists(Path.Combine(drivePath, "IP.BIN")))
            {
                return(KnownSystem.SegaDreamcast);
            }

            // Sega Mega-CD / Sega-CD
            if (File.Exists(Path.Combine(drivePath, "_BOOT", "IP.BIN")) ||
                File.Exists(Path.Combine(drivePath, "_BOOT", "SP.BIN")) ||
                File.Exists(Path.Combine(drivePath, "_BOOT", "SP_AS.BIN")) ||
                File.Exists(Path.Combine(drivePath, "FILESYSTEM.BIN")))
            {
                return(KnownSystem.SegaCDMegaCD);
            }

            // Sega Saturn
            try
            {
                byte[] sector = drive?.ReadSector(0);
                if (sector != null)
                {
                    if (sector.StartsWith(Interface.SaturnSectorZeroStart))
                    {
                        return(KnownSystem.SegaSaturn);
                    }
                }
            }
            catch { }

            // Sony PlayStation and Sony PlayStation 2
            string psxExePath    = Path.Combine(drivePath, "PSX.EXE");
            string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");

            if (File.Exists(systemCnfPath))
            {
                // Check for either BOOT or BOOT2
                var systemCnf = new IniFile(systemCnfPath);
                if (systemCnf.ContainsKey("BOOT"))
                {
                    return(KnownSystem.SonyPlayStation);
                }
                else if (systemCnf.ContainsKey("BOOT2"))
                {
                    return(KnownSystem.SonyPlayStation2);
                }
            }
            else if (File.Exists(psxExePath))
            {
                return(KnownSystem.SonyPlayStation);
            }

            // Sony PlayStation 4
            if (drive.VolumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
            {
                return(KnownSystem.SonyPlayStation4);
            }

            // Sony PlayStation 5
            if (drive.VolumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
            {
                return(KnownSystem.SonyPlayStation5);
            }

            // V.Tech V.Flash / V.Smile Pro
            if (File.Exists(Path.Combine(drivePath, "0SYSTEM")))
            {
                return(KnownSystem.VTechVFlashVSmilePro);
            }

            // VCD
            if (Directory.Exists(Path.Combine(drivePath, "VCD")) &&
                Directory.EnumerateFiles(Path.Combine(drivePath, "VCD")).Count() > 0)
            {
                return(KnownSystem.VideoCD);
            }

            // Default return
            return(defaultValue);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Get the current media type from drive letter
        /// </summary>
        /// <param name="drive"></param>
        /// <returns></returns>
        /// <remarks>
        /// https://stackoverflow.com/questions/11420365/detecting-if-disc-is-in-dvd-drive
        /// </remarks>
        public static MediaType?GetMediaType(Drive drive)
        {
            // Take care of the non-optical stuff first
            // TODO: See if any of these can be more granular, like Optical is
            if (drive.InternalDriveType == InternalDriveType.Floppy)
            {
                return(MediaType.FloppyDisk);
            }
            else if (drive.InternalDriveType == InternalDriveType.HardDisk)
            {
                return(MediaType.HardDisk);
            }
            else if (drive.InternalDriveType == InternalDriveType.Removable)
            {
                return(MediaType.FlashDrive);
            }

            // Get the DeviceID and MediaType from the current drive letter
            string deviceId  = null;
            int    mediaType = 0;

            try
            {
                // Get the device ID first
                var searcher = new ManagementObjectSearcher(
                    "root\\CIMV2",
                    $"SELECT * FROM Win32_CDROMDrive WHERE Id = '{drive.Letter}:\'");

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    deviceId = (string)queryObj["DeviceID"];

                    #region Possibly useful fields

                    //foreach (var property in queryObj.Properties)
                    //{
                    //    Console.WriteLine(property);
                    //}

                    //// Capabilities list
                    //ushort?[] capabilities = (ushort?[])queryObj["Capabilities"];

                    //// Internal name of the device
                    //string caption = (string)queryObj["Caption"];

                    //// Flags for the file system, see FileSystemFlags
                    //uint? fileSystemFlagsEx = (uint?)queryObj["FileSystemFlagsEx"];

                    //// "CD Writer" doesn't fit https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-cdromdrive
                    //string mediaTypeString = (string)queryObj["MediaType"];

                    //// Internal name of the device (Seems like a duplicate of Caption)
                    //string name = (string)queryObj["Name"];

                    //// Full device ID for the drive (Seems like duplicate of DeviceID)
                    //string pnpDeviceId = (string)queryObj["PNPDeviceId"];

                    //// Size of the loaded media (extrapolate disc type from this?)
                    //ulong? size = (ulong?)queryObj["Size"];

                    #endregion
                }

                // If we got no valid device, we don't care and just return
                if (deviceId == null)
                {
                    return(null);
                }

#if NET_FRAMEWORK
                MsftDiscMaster2 discMaster = new MsftDiscMaster2();
                deviceId = deviceId.ToLower().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);
                }

                // Otherwise, we get the media type, if any
                MsftDiscRecorder2 recorder = new MsftDiscRecorder2();
                recorder.InitializeDiscRecorder(id);
                MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data();
                dataWriter.Recorder = recorder;
                var media = dataWriter.CurrentPhysicalMediaType;
                if (media != IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN)
                {
                    return(media.IMAPIToMediaType());
                }

                return(null);
#else
                // TODO: This entire .NET Core path still doesn't work
                // This may honestly require an entire import of IMAPI2 stuff and then try
                // as best as possible to get it working.

                // Now try to get the physical media associated
                searcher = new ManagementObjectSearcher(
                    "root\\CIMV2",
                    $"SELECT * FROM Win32_PhysicalMedia");

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    foreach (var property in queryObj.Properties)
                    {
                        Console.WriteLine(property);
                    }

                    mediaType = (int)(queryObj["MediaType"] ?? 0);
                }

                return(((PhysicalMediaType)mediaType).ToMediaType());
#endif
            }
            catch
            {
                // We don't care what the error was
                return(null);
            }
        }