diff --git a/BurnOutSharp.Wrappers/CFB.cs b/BurnOutSharp.Wrappers/CFB.cs new file mode 100644 index 00000000..aa99f703 --- /dev/null +++ b/BurnOutSharp.Wrappers/CFB.cs @@ -0,0 +1,309 @@ +using System; +using System.IO; + +namespace BurnOutSharp.Wrappers +{ + public class CFB : WrapperBase + { + #region Pass-Through Properties + + #region Header + + /// + public ulong Signature => _binary.Header.Signature; + + /// + public Guid CLSID => _binary.Header.CLSID; + + /// + public ushort MinorVersion => _binary.Header.MinorVersion; + + /// + public ushort MajorVersion => _binary.Header.MajorVersion; + + /// + public ushort ByteOrder => _binary.Header.ByteOrder; + + /// + public ushort SectorShift => _binary.Header.SectorShift; + + /// + public ushort MiniSectorShift => _binary.Header.MiniSectorShift; + + /// + public byte[] Reserved => _binary.Header.Reserved; + + /// + public uint NumberOfDirectorySectors => _binary.Header.NumberOfDirectorySectors; + + /// + public uint NumberOfFATSectors => _binary.Header.NumberOfFATSectors; + + /// + public uint FirstDirectorySectorLocation => _binary.Header.FirstDirectorySectorLocation; + + /// + public uint TransactionSignatureNumber => _binary.Header.TransactionSignatureNumber; + + /// + public uint MiniStreamCutoffSize => _binary.Header.MiniStreamCutoffSize; + + /// + public uint FirstMiniFATSectorLocation => _binary.Header.FirstMiniFATSectorLocation; + + /// + public uint NumberOfMiniFATSectors => _binary.Header.NumberOfMiniFATSectors; + + /// + public uint FirstDIFATSectorLocation => _binary.Header.FirstDIFATSectorLocation; + + /// + public uint NumberOfDIFATSectors => _binary.Header.NumberOfDIFATSectors; + + /// + public Models.CFB.SectorNumber[] DIFAT => _binary.Header.DIFAT; + + #endregion + + #region FAT Sector Numbers + + /// + public Models.CFB.SectorNumber[] FATSectorNumbers => _binary.FATSectorNumbers; + + #endregion + + #region Mini FAT Sector Numbers + + /// + public Models.CFB.SectorNumber[] MiniFATSectorNumbers => _binary.MiniFATSectorNumbers; + + #endregion + + #region DIFAT Sector Numbers + + /// + public Models.CFB.SectorNumber[] DIFATSectorNumbers => _binary.DIFATSectorNumbers; + + #endregion + + #region Directory Entries + + /// + public Models.CFB.DirectoryEntry[] DirectoryEntries => _binary.DirectoryEntries; + + #endregion + + #endregion + + #region Instance Variables + + /// + /// Internal representation of the file + /// + private Models.CFB.Binary _binary; + + #endregion + + #region Constructors + + /// + /// Private constructor + /// + private CFB() { } + + /// + /// Create a Compound File Binary from a byte array and offset + /// + /// Byte array representing the archive + /// Offset within the array to parse + /// A Compound File Binary wrapper on success, null on failure + public static CFB Create(byte[] data, int offset) + { + // If the data is invalid + if (data == null) + return null; + + // If the offset is out of bounds + if (offset < 0 || offset >= data.Length) + return null; + + // Create a memory stream and use that + MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset); + return Create(dataStream); + } + + /// + /// Create a Compound File Binary from a Stream + /// + /// Stream representing the archive + /// A Compound File Binary wrapper on success, null on failure + public static CFB Create(Stream data) + { + // If the data is invalid + if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) + return null; + + var binary = Builders.CFB.ParseBinary(data); + if (binary == null) + return null; + + var wrapper = new CFB + { + _binary = binary, + _dataSource = DataSource.Stream, + _streamData = data, + }; + return wrapper; + } + + #endregion + + #region Printing + + /// + public override void Print() + { + Console.WriteLine("Compound File Binary Information:"); + Console.WriteLine("-------------------------"); + Console.WriteLine(); + + PrintFileHeader(); + PrintFATSectorNumbers(); + PrintMiniFATSectorNumbers(); + PrintDIFATSectorNumbers(); + PrintDirectoryEntries(); + } + + /// + /// Print header information + /// + private void PrintFileHeader() + { + Console.WriteLine(" File Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Signature: {Signature}"); + Console.WriteLine($" CLSID: {CLSID}"); + Console.WriteLine($" Minor version: {MinorVersion}"); + Console.WriteLine($" Major version: {MajorVersion}"); + Console.WriteLine($" Byte order: {ByteOrder}"); + Console.WriteLine($" Sector shift: {SectorShift} [{(long)Math.Pow(2, SectorShift)}]"); + Console.WriteLine($" Mini sector shift: {MiniSectorShift} [{(long)Math.Pow(2, MiniSectorShift)}]"); + Console.WriteLine($" Reserved: {BitConverter.ToString(Reserved).Replace('-', ' ')}]"); + Console.WriteLine($" Number of directory sectors: {NumberOfDirectorySectors}"); + Console.WriteLine($" Number of FAT sectors: {NumberOfFATSectors}"); + Console.WriteLine($" First directory sector location: {FirstDirectorySectorLocation}"); + Console.WriteLine($" Transaction signature number: {TransactionSignatureNumber}"); + Console.WriteLine($" Mini stream cutoff size: {MiniStreamCutoffSize}"); + Console.WriteLine($" First mini FAT sector location: {FirstMiniFATSectorLocation}"); + Console.WriteLine($" Number of mini FAT sectors: {NumberOfMiniFATSectors}"); + Console.WriteLine($" First DIFAT sector location: {FirstDIFATSectorLocation}"); + Console.WriteLine($" Number of DIFAT sectors: {NumberOfDIFATSectors}"); + Console.WriteLine($" DIFAT:"); + for (int i = 0; i < DIFAT.Length; i++) + { + Console.WriteLine($" DIFAT Entry {i}: {DIFAT[i]}"); + } + Console.WriteLine(); + } + + /// + /// Print FAT sector numbers + /// + private void PrintFATSectorNumbers() + { + Console.WriteLine(" FAT Sectors Information:"); + Console.WriteLine(" -------------------------"); + if (FATSectorNumbers == null || FATSectorNumbers.Length == 0) + { + Console.WriteLine(" No FAT sectors"); + } + else + { + for (int i = 0; i < FATSectorNumbers.Length; i++) + { + Console.WriteLine($" FAT Sector Entry {i}: {FATSectorNumbers[i]}"); + } + } + Console.WriteLine(); + } + + /// + /// Print mini FAT sector numbers + /// + private void PrintMiniFATSectorNumbers() + { + Console.WriteLine(" Mini FAT Sectors Information:"); + Console.WriteLine(" -------------------------"); + if (MiniFATSectorNumbers == null || MiniFATSectorNumbers.Length == 0) + { + Console.WriteLine(" No mini FAT sectors"); + } + else + { + for (int i = 0; i < MiniFATSectorNumbers.Length; i++) + { + Console.WriteLine($" Mini FAT Sector Entry {i}: {MiniFATSectorNumbers[i]}"); + } + } + Console.WriteLine(); + } + + /// + /// Print DIFAT sector numbers + /// + private void PrintDIFATSectorNumbers() + { + Console.WriteLine(" DIFAT Sectors Information:"); + Console.WriteLine(" -------------------------"); + if (DIFATSectorNumbers == null || DIFATSectorNumbers.Length == 0) + { + Console.WriteLine(" No DIFAT sectors"); + } + else + { + for (int i = 0; i < DIFATSectorNumbers.Length; i++) + { + Console.WriteLine($" DIFAT Sector Entry {i}: {DIFATSectorNumbers[i]}"); + } + } + Console.WriteLine(); + } + + // + /// Print directory entries + /// + private void PrintDirectoryEntries() + { + Console.WriteLine(" Directory Entries Information:"); + Console.WriteLine(" -------------------------"); + if (DirectoryEntries == null || DirectoryEntries.Length == 0) + { + Console.WriteLine(" No directory entries"); + } + else + { + for (int i = 0; i < DirectoryEntries.Length; i++) + { + var directoryEntry = DirectoryEntries[i]; + Console.WriteLine($" DIFAT Sector Entry {i}"); + Console.WriteLine($" Name: {directoryEntry.Name}"); + Console.WriteLine($" Name length: {directoryEntry.NameLength}"); + Console.WriteLine($" Object type: {directoryEntry.ObjectType}"); + Console.WriteLine($" Color flag: {directoryEntry.ColorFlag}"); + Console.WriteLine($" Left sibling ID: {directoryEntry.LeftSiblingID}"); + Console.WriteLine($" Right sibling ID: {directoryEntry.RightSiblingID}"); + Console.WriteLine($" Child ID: {directoryEntry.ChildID}"); + Console.WriteLine($" CLSID: {directoryEntry.CLSID}"); + Console.WriteLine($" State bits: {directoryEntry.StateBits}"); + Console.WriteLine($" Creation time: {directoryEntry.CreationTime}"); + Console.WriteLine($" Modification time: {directoryEntry.ModifiedTime}"); + Console.WriteLine($" Staring sector location: {directoryEntry.StartingSectorLocation}"); + Console.WriteLine($" Stream size: {directoryEntry.StreamSize}"); + } + } + Console.WriteLine(); + } + + #endregion + } +} \ No newline at end of file