public bool Open(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); byte[] hdrB = new byte[Marshal.SizeOf <RsIdeHeader>()]; stream.Read(hdrB, 0, hdrB.Length); RsIdeHeader hdr = Marshal.ByteArrayToStructureLittleEndian <RsIdeHeader>(hdrB); if (!hdr.magic.SequenceEqual(signature)) { return(false); } dataOff = hdr.dataOff; imageInfo.MediaType = MediaType.GENERIC_HDD; imageInfo.SectorSize = (uint)(hdr.flags.HasFlag(RsIdeFlags.HalfSectors) ? 256 : 512); imageInfo.ImageSize = (ulong)(stream.Length - dataOff); imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize; imageInfo.CreationTime = imageFilter.GetCreationTime(); imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); imageInfo.XmlMediaType = XmlMediaType.BlockMedia; imageInfo.Version = $"{hdr.revision >> 8}.{hdr.revision & 0x0F}"; if (!ArrayHelpers.ArrayIsNullOrEmpty(hdr.identify)) { identify = new byte[512]; Array.Copy(hdr.identify, 0, identify, 0, hdr.identify.Length); Identify.IdentifyDevice?ataId = Decoders.ATA.Identify.Decode(identify); if (ataId.HasValue) { imageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY); imageInfo.Cylinders = ataId.Value.Cylinders; imageInfo.Heads = ataId.Value.Heads; imageInfo.SectorsPerTrack = ataId.Value.SectorsPerCard; imageInfo.DriveFirmwareRevision = ataId.Value.FirmwareRevision; imageInfo.DriveModel = ataId.Value.Model; imageInfo.DriveSerialNumber = ataId.Value.SerialNumber; imageInfo.MediaSerialNumber = ataId.Value.MediaSerial; imageInfo.MediaManufacturer = ataId.Value.MediaManufacturer; } } if (imageInfo.Cylinders == 0 || imageInfo.Heads == 0 || imageInfo.SectorsPerTrack == 0) { imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63); imageInfo.Heads = 16; imageInfo.SectorsPerTrack = 63; } rsIdeImageFilter = imageFilter; return(true); }
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } if (imageInfo.Cylinders == 0) { imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63); imageInfo.Heads = 16; imageInfo.SectorsPerTrack = 63; while (imageInfo.Cylinders == 0) { imageInfo.Heads--; if (imageInfo.Heads == 0) { imageInfo.SectorsPerTrack--; imageInfo.Heads = 16; } imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack); if (imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) { break; } } } RsIdeHeader header = new RsIdeHeader { magic = signature, identify = new byte[106], dataOff = (ushort)Marshal.SizeOf <RsIdeHeader>(), revision = 1, reserved = new byte[11] }; if (imageInfo.SectorSize == 256) { header.flags = RsIdeFlags.HalfSectors; } if (identify == null) { Identify.IdentifyDevice ataId = new Identify.IdentifyDevice { GeneralConfiguration = Decoders.ATA.Identify.GeneralConfigurationBit.UltraFastIDE | Decoders.ATA.Identify.GeneralConfigurationBit.Fixed | Decoders.ATA.Identify.GeneralConfigurationBit.NotMFM | Decoders.ATA.Identify.GeneralConfigurationBit.SoftSector, Cylinders = (ushort)imageInfo.Cylinders, Heads = (ushort)imageInfo.Heads, SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, VendorWord47 = 0x80, Capabilities = Decoders.ATA.Identify.CapabilitiesBit.DMASupport | Decoders.ATA.Identify.CapabilitiesBit.IORDY | Decoders.ATA.Identify.CapabilitiesBit.LBASupport, ExtendedIdentify = Decoders.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid, CurrentCylinders = (ushort)imageInfo.Cylinders, CurrentHeads = (ushort)imageInfo.Heads, CurrentSectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, CurrentSectors = (uint)imageInfo.Sectors, LBASectors = (uint)imageInfo.Sectors, DMASupported = Decoders.ATA.Identify.TransferMode.Mode0, DMAActive = Decoders.ATA.Identify.TransferMode.Mode0 }; if (string.IsNullOrEmpty(imageInfo.DriveManufacturer)) { imageInfo.DriveManufacturer = "DiscImageChef"; } if (string.IsNullOrEmpty(imageInfo.DriveModel)) { imageInfo.DriveModel = ""; } if (string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision)) { Version.GetVersion(); } if (string.IsNullOrEmpty(imageInfo.DriveSerialNumber)) { imageInfo.DriveSerialNumber = $"{new Random().NextDouble():16X}"; } byte[] ataIdBytes = new byte[Marshal.SizeOf <Identify.IdentifyDevice>()]; IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512); System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, true); System.Runtime.InteropServices.Marshal.Copy(ptr, ataIdBytes, 0, Marshal.SizeOf <Identify.IdentifyDevice>()); System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr); Array.Copy(ScrambleAtaString(imageInfo.DriveManufacturer + " " + imageInfo.DriveModel, 40), 0, ataIdBytes, 27 * 2, 40); Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8); Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20); Array.Copy(ataIdBytes, 0, header.identify, 0, 106); } else { Array.Copy(identify, 0, header.identify, 0, 106); } byte[] hdr = new byte[Marshal.SizeOf <RsIdeHeader>()]; IntPtr hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <RsIdeHeader>()); System.Runtime.InteropServices.Marshal.StructureToPtr(header, hdrPtr, true); System.Runtime.InteropServices.Marshal.Copy(hdrPtr, hdr, 0, hdr.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(hdrPtr); writingStream.Seek(0, SeekOrigin.Begin); writingStream.Write(hdr, 0, hdr.Length); writingStream.Flush(); writingStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }