Example #1
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // UDF is always UTF-8
            Encoding = Encoding.UTF8;
            byte[] sector;

            StringBuilder sbInformation = new StringBuilder();

            sbInformation.AppendLine("Universal Disk Format");

            AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer();

            // All positions where anchor may reside
            ulong[] positions = { 256, 512, partition.End - 256, partition.End };

            foreach (ulong position in positions)
            {
                sector = imagePlugin.ReadSector(position);
                anchor = new AnchorVolumeDescriptorPointer();
                IntPtr anchorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(anchor));
                Marshal.Copy(sector, 0, anchorPtr, Marshal.SizeOf(anchor));
                anchor =
                    (AnchorVolumeDescriptorPointer)Marshal.PtrToStructure(anchorPtr,
                                                                          typeof(AnchorVolumeDescriptorPointer));
                Marshal.FreeHGlobal(anchorPtr);

                if (anchor.tag.tagIdentifier == TagIdentifier.AnchorVolumeDescriptorPointer &&
                    anchor.tag.tagLocation == position &&
                    anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start < partition.End)
                {
                    break;
                }
            }

            ulong count = 0;

            PrimaryVolumeDescriptor          pvd  = new PrimaryVolumeDescriptor();
            LogicalVolumeDescriptor          lvd  = new LogicalVolumeDescriptor();
            LogicalVolumeIntegrityDescriptor lvid = new LogicalVolumeIntegrityDescriptor();
            LogicalVolumeIntegrityDescriptorImplementationUse lvidiu =
                new LogicalVolumeIntegrityDescriptorImplementationUse();

            while (count < 256)
            {
                sector = imagePlugin.ReadSector(partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location +
                                                count);
                TagIdentifier tagId    = (TagIdentifier)BitConverter.ToUInt16(sector, 0);
                uint          location = BitConverter.ToUInt32(sector, 0x0C);

                if (location == partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + count)
                {
                    if (tagId == TagIdentifier.TerminatingDescriptor)
                    {
                        break;
                    }

                    switch (tagId)
                    {
                    case TagIdentifier.LogicalVolumeDescriptor:
                        IntPtr lvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvd));
                        Marshal.Copy(sector, 0, lvdPtr, Marshal.SizeOf(lvd));
                        lvd = (LogicalVolumeDescriptor)
                              Marshal.PtrToStructure(lvdPtr, typeof(LogicalVolumeDescriptor));
                        Marshal.FreeHGlobal(lvdPtr);
                        break;

                    case TagIdentifier.PrimaryVolumeDescriptor:
                        IntPtr pvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pvd));
                        Marshal.Copy(sector, 0, pvdPtr, Marshal.SizeOf(pvd));
                        pvd = (PrimaryVolumeDescriptor)
                              Marshal.PtrToStructure(pvdPtr, typeof(PrimaryVolumeDescriptor));
                        Marshal.FreeHGlobal(pvdPtr);
                        break;
                    }
                }
                else
                {
                    break;
                }

                count++;
            }

            sector = imagePlugin.ReadSector(lvd.integritySequenceExtent.location);
            IntPtr lvidPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvid));

            Marshal.Copy(sector, 0, lvidPtr, Marshal.SizeOf(lvid));
            lvid =
                (LogicalVolumeIntegrityDescriptor)
                Marshal.PtrToStructure(lvidPtr, typeof(LogicalVolumeIntegrityDescriptor));
            Marshal.FreeHGlobal(lvidPtr);

            if (lvid.tag.tagIdentifier == TagIdentifier.LogicalVolumeIntegrityDescriptor &&
                lvid.tag.tagLocation == lvd.integritySequenceExtent.location)
            {
                IntPtr lvidiuPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvidiu));
                Marshal.Copy(sector, (int)(lvid.numberOfPartitions * 8 + 80), lvidiuPtr, Marshal.SizeOf(lvidiu));
                lvidiu =
                    (LogicalVolumeIntegrityDescriptorImplementationUse)Marshal.PtrToStructure(lvidiuPtr,
                                                                                              typeof(
                                                                                                  LogicalVolumeIntegrityDescriptorImplementationUse
                                                                                                  ));
                Marshal.FreeHGlobal(lvidiuPtr);
            }
            else
            {
                lvid = new LogicalVolumeIntegrityDescriptor();
            }

            sbInformation.AppendFormat("Volume is number {0} of {1}", pvd.volumeSequenceNumber,
                                       pvd.maximumVolumeSequenceNumber).AppendLine();
            sbInformation.AppendFormat("Volume set identifier: {0}",
                                       StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier)).AppendLine();
            sbInformation
            .AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier))
            .AppendLine();
            sbInformation.AppendFormat("Volume uses {0} bytes per block", lvd.logicalBlockSize).AppendLine();
            sbInformation.AppendFormat("Volume was las written in {0}", EcmaToDateTime(lvid.recordingDateTime))
            .AppendLine();
            sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine();
            sbInformation
            .AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories)
            .AppendLine();
            sbInformation.AppendFormat("Volume conforms to {0}",
                                       Encoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000'))
            .AppendLine();
            sbInformation.AppendFormat("Volume was last written by: {0}",
                                       Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'))
            .AppendLine();
            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read",
                                       Convert.ToInt32($"{(lvidiu.minimumReadUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumReadUDF & 0xFF}", 10)).AppendLine();
            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be written to",
                                       Convert.ToInt32($"{(lvidiu.minimumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumWriteUDF & 0xFF}", 10)).AppendLine();
            sbInformation.AppendFormat("Volume cannot be written by any UDF version higher than {0}.{1:X2}",
                                       Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)).AppendLine();

            XmlFsType = new FileSystemType
            {
                Type =
                    $"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}",
                ApplicationIdentifier     = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'),
                ClusterSize               = (int)lvd.logicalBlockSize,
                ModificationDate          = EcmaToDateTime(lvid.recordingDateTime),
                ModificationDateSpecified = true,
                Files               = lvidiu.files,
                FilesSpecified      = true,
                VolumeName          = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier),
                VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
                SystemIdentifier    = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')
            };
            XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize /
                                        (ulong)XmlFsType.ClusterSize);

            information = sbInformation.ToString();
        }
Example #2
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // UDF is always UTF-8
            Encoding = Encoding.UTF8;
            byte[] sector;

            var sbInformation = new StringBuilder();

            sbInformation.AppendLine("Universal Disk Format");

            var anchor = new AnchorVolumeDescriptorPointer();

            // All positions where anchor may reside, with the ratio between 512 and 2048bps
            ulong[][] positions =
            {
                new ulong[]
                {
                    256, 1
                },
                new ulong[]
                {
                    512, 1
                },
                new ulong[]
                {
                    partition.End - 256, 1
                },
                new ulong[]
                {
                    partition.End, 1
                },
                new ulong[]
                {
                    1024, 4
                },
                new ulong[]
                {
                    2048, 4
                },
                new ulong[]
                {
                    partition.End - 1024, 4
                },
                new ulong[]
                {
                    partition.End - 4, 4
                }
            };

            uint ratio = 1;

            foreach(ulong[] position in positions)
            {
                sector = imagePlugin.ReadSectors(position[0], (uint)position[1]);
                anchor = Marshal.ByteArrayToStructureLittleEndian<AnchorVolumeDescriptorPointer>(sector);

                if(anchor.tag.tagIdentifier != TagIdentifier.AnchorVolumeDescriptorPointer ||
                   anchor.tag.tagLocation != position[0] / position[1] ||
                   anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start >= partition.End)
                    continue;

                ratio = (uint)position[1];

                break;
            }

            ulong count = 0;

            var pvd    = new PrimaryVolumeDescriptor();
            var lvd    = new LogicalVolumeDescriptor();
            var lvid   = new LogicalVolumeIntegrityDescriptor();
            var lvidiu = new LogicalVolumeIntegrityDescriptorImplementationUse();

            while(count < 256)
            {
                sector =
                    imagePlugin.
                        ReadSectors(partition.Start + (anchor.mainVolumeDescriptorSequenceExtent.location * ratio) + (count * ratio),
                                    ratio);

                var  tagId    = (TagIdentifier)BitConverter.ToUInt16(sector, 0);
                uint location = BitConverter.ToUInt32(sector, 0x0C);

                if(location == (partition.Start / ratio) + anchor.mainVolumeDescriptorSequenceExtent.location + count)
                {
                    if(tagId == TagIdentifier.TerminatingDescriptor)
                        break;

                    switch(tagId)
                    {
                        case TagIdentifier.LogicalVolumeDescriptor:
                            lvd = Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeDescriptor>(sector);

                            break;
                        case TagIdentifier.PrimaryVolumeDescriptor:
                            pvd = Marshal.ByteArrayToStructureLittleEndian<PrimaryVolumeDescriptor>(sector);

                            break;
                    }
                }
                else
                    break;

                count++;
            }

            sector = imagePlugin.ReadSectors(lvd.integritySequenceExtent.location * ratio, ratio);
            lvid   = Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeIntegrityDescriptor>(sector);

            if(lvid.tag.tagIdentifier == TagIdentifier.LogicalVolumeIntegrityDescriptor &&
               lvid.tag.tagLocation   == lvd.integritySequenceExtent.location)
                lvidiu =
                    Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeIntegrityDescriptorImplementationUse>(sector,
                        (int)((lvid.numberOfPartitions * 8) + 80),
                        System.Runtime.InteropServices.Marshal.SizeOf(lvidiu));
            else
                lvid = new LogicalVolumeIntegrityDescriptor();

            sbInformation.AppendFormat("Volume is number {0} of {1}", pvd.volumeSequenceNumber,
                                       pvd.maximumVolumeSequenceNumber).AppendLine();

            sbInformation.AppendFormat("Volume set identifier: {0}",
                                       StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier)).AppendLine();

            sbInformation.
                AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier)).
                AppendLine();

            sbInformation.AppendFormat("Volume uses {0} bytes per block", lvd.logicalBlockSize).AppendLine();

            sbInformation.AppendFormat("Volume was last written in {0}", EcmaToDateTime(lvid.recordingDateTime)).
                          AppendLine();

            sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine();

            sbInformation.
                AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories).
                AppendLine();

            sbInformation.AppendFormat("Volume conforms to {0}",
                                       Encoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')).
                          AppendLine();

            sbInformation.AppendFormat("Volume was last written by: {0}",
                                       Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')).
                          AppendLine();

            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read",
                                       Convert.ToInt32($"{(lvidiu.minimumReadUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumReadUDF & 0xFF}", 10)).AppendLine();

            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be written to",
                                       Convert.ToInt32($"{(lvidiu.minimumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumWriteUDF & 0xFF}", 10)).AppendLine();

            sbInformation.AppendFormat("Volume cannot be written by any UDF version higher than {0}.{1:X2}",
                                       Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)).AppendLine();

            XmlFsType = new FileSystemType
            {
                Type =
                    $"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}",
                ApplicationIdentifier = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'),
                ClusterSize = lvd.logicalBlockSize,
                ModificationDate = EcmaToDateTime(lvid.recordingDateTime),
                ModificationDateSpecified = true,
                Files = lvidiu.files,
                FilesSpecified = true,
                VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier),
                VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
                VolumeSerial = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
                SystemIdentifier = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')
            };

            XmlFsType.Clusters = (partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize /
                                 XmlFsType.ClusterSize;

            information = sbInformation.ToString();
        }