/// <summary> /// Creates a new EWFInfo helper class from filePath. /// </summary> /// <param name="filePath">The path of the EWF file.</param> public EWFInfo(string filePath) { FilePath = filePath; using (FileStream fs = File.OpenRead(filePath)) { fs.Seek(0, SeekOrigin.Begin); byte[] buff = new byte[13]; fs.Read(buff, 0, 13); EWFHeader ewfHeader = new EWFHeader(buff); while (fs.Position < fs.Length) { buff = new byte[76]; fs.Read(buff, 0, 76); SectionDescriptor sd = new SectionDescriptor(buff, fs.Position - 76); switch (sd.SectionType) { case SECTION_TYPE.header: case SECTION_TYPE.header2: // Save the header buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); HeaderSection = new Section.Header2(buff); break; case SECTION_TYPE.volume: case SECTION_TYPE.disk: case SECTION_TYPE.data: // Save the volume buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); VolumeSection = new Section.Volume(buff); break; case SECTION_TYPE.next: case SECTION_TYPE.done: fs.Seek(76, SeekOrigin.Current); break; default: fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); break; } if (HeaderSection != null && VolumeSection != null) { break; } } } if (HeaderSection == null || VolumeSection == null) { throw new Exception("file missing header or volume section"); } }
/// <summary> /// Creates a new EWFInfo helper class from filePath. /// </summary> /// <param name="filePath">The path of the EWF file.</param> public EWFInfo(string filePath) { FilePath = filePath; using (FileStream fs = File.OpenRead(filePath)) { fs.Seek(0, SeekOrigin.Begin); byte[] buff = new byte[13]; fs.Read(buff, 0, 13); EWFHeader ewfHeader = new EWFHeader(buff); while (fs.Position < fs.Length) { buff = new byte[76]; fs.Read(buff, 0, 76); SectionDescriptor sd = new SectionDescriptor(buff, fs.Position - 76); switch (sd.SectionType) { case SECTION_TYPE.header: case SECTION_TYPE.header2: // Save the header buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); HeaderSection = new Section.Header2(buff); break; case SECTION_TYPE.volume: case SECTION_TYPE.disk: case SECTION_TYPE.data: // Save the volume buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); VolumeSection = new Section.Volume(buff); break; case SECTION_TYPE.next: case SECTION_TYPE.done: fs.Seek(76, SeekOrigin.Current); break; default: fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); break; } if (HeaderSection != null && VolumeSection != null) break; } } if (HeaderSection == null || VolumeSection == null) throw new Exception("file missing header or volume section"); }
private void PopulateChunkInfo() { long thisChunk = 0; for (int fileCount = 0; fileCount < Files.Count; fileCount++) { using (FileStream fs = File.OpenRead(Files[fileCount])) { bool gotTable, gotHeader, gotHeader2; gotTable = gotHeader = gotHeader2 = false; int endOfSectors = -1; fs.Seek(13, SeekOrigin.Begin); // Skip file header while (fs.Position < fs.Length) { byte[] buff = new byte[76]; fs.Read(buff, 0, 76); SectionDescriptor sd; try { sd = new SectionDescriptor(buff, fs.Position - 76); } catch (Exception ex) { throw new Exception(Files[fileCount], ex); } switch (sd.SectionType) { case SECTION_TYPE.header: break; case SECTION_TYPE.header2: break; case SECTION_TYPE.ltypes: break; case SECTION_TYPE.ltree: break; case SECTION_TYPE.session: break; case SECTION_TYPE.error2: break; case SECTION_TYPE.incomplete: break; case SECTION_TYPE.disk: break; case SECTION_TYPE.volume: break; case SECTION_TYPE.sectors: break; case SECTION_TYPE.table: break; case SECTION_TYPE.table2: break; case SECTION_TYPE.next: break; case SECTION_TYPE.data: break; case SECTION_TYPE.digest: break; case SECTION_TYPE.hash: break; case SECTION_TYPE.done: break; default: break; } switch (sd.SectionType) { case SECTION_TYPE.header: Sections.Add("header", new Section.Header2(readSection(sd, fs))); break; case SECTION_TYPE.header2: Sections.Add("header2", new Section.Header2(readSection(sd, fs))); break; case SECTION_TYPE.disk: case SECTION_TYPE.data: case SECTION_TYPE.volume: // Calculate bytes per chunk buff = new byte[sd.NextSectionOffset - (int)fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); Section.Volume VolumeSection = new Section.Volume(buff); Sections.Add("volume", VolumeSection); _bytesPerChunk = VolumeSection.SectorsPerChunk * VolumeSection.BytesPerSector; switch (VolumeSection.MediaType) { case MEDIA_TYPE.Disc: DiskType = VirtualDiskClass.OpticalDisk; break; case MEDIA_TYPE.Fixed: DiskType = VirtualDiskClass.HardDisk; break; default: DiskType = VirtualDiskClass.None; break; } if (_length < 0) { _length = (long)VolumeSection.BytesPerSector * (long)VolumeSection.SectorCount; } break; case SECTION_TYPE.table: case SECTION_TYPE.table2: // Calculate the chunks if (gotTable) // Don't read both versions of the table... { // ...so skip the bytes fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); } else { if (_bytesPerChunk < 0) { throw new Exception(string.Format("table/table2 section before disk/data/volume, in {0}", Files[fileCount])); } bool volumeCompression = ((Section.Volume)GetSection("volume")).Compression != COMPRESSION.None; buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); Section.Table table = new Section.Table(buff); Sections.Add("table", table); for (int i = 0; i < table.Entries.Count; i++) { Section.Table.TableEntry entry = table.Entries[i]; if (_chunkInfos.Count == 261) { Console.WriteLine("!!!"); } int bytesInChunk = i == table.Entries.Count - 1 ? endOfSectors - entry.Offset : table.Entries[i + 1].Offset - entry.Offset; _chunkInfos.Add(new ChunkInfo( fileCount, entry.Offset, _bytesPerChunk * thisChunk++, _bytesPerChunk, volumeCompression | entry.Compressed, bytesInChunk)); } } gotTable = !gotTable; break; case SECTION_TYPE.next: case SECTION_TYPE.done: fs.Seek(76, SeekOrigin.Current); break; case SECTION_TYPE.sectors: endOfSectors = sd.NextSectionOffset; fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); break; case SECTION_TYPE.digest: if (MD5 == null) { buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); Section.Digest digest = new Section.Digest(buff); MD5 = digest.MD5; } else { fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); } break; case SECTION_TYPE.hash: if (MD5 == null) { buff = new byte[sd.NextSectionOffset - fs.Position]; fs.Read(buff, 0, sd.NextSectionOffset - (int)fs.Position); Section.Hash hash = new Section.Hash(buff); MD5 = hash.MD5; } else { fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); } break; default: // Don't care about any other sections fs.Seek(sd.NextSectionOffset - (int)fs.Position, SeekOrigin.Current); break; } } } } if (_chunkInfos.Count > 0) { _chunkStarts = new long[_chunkInfos.Count]; int i = 0; foreach (ChunkInfo ci in _chunkInfos) { _chunkStarts[i++] = ci.Start; } } }