Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }