using System.IO; using SabreTools.Data.Models.WiseInstaller; namespace SabreTools.Wrappers { public partial class WiseSectionHeader : WrapperBase { #region Descriptive Properties /// public override string DescriptionString => "Self-Extracting Wise Installer Header"; #endregion #region Extension Properties /// /// Returns the offset relative to the start of the header /// where the compressed data lives /// /// TODO: Find a way for this to be automatically found based on the model /// Likely would be able to replace most of the unknown values with /// an array of values followed by padding bytes. This should be sufficient /// to ensure that all possible values before the temp string are found /// and read properly public long CompressedDataOffset { get; private set; } /// public uint UnknownDataSize => Model.UnknownDataSize; /// // TODO: VERIFY ON CHANGE public uint SecondExecutableFileEntryLength => Model.SecondExecutableFileEntryLength; /// public uint UnknownValue2 => Model.UnknownValue2; /// public uint UnknownValue3 => Model.UnknownValue3; /// public uint UnknownValue4 => Model.UnknownValue4; /// public uint FirstExecutableFileEntryLength => Model.FirstExecutableFileEntryLength; // TODO: VERIFY ON CHANGE /// public uint MsiFileEntryLength => Model.MsiFileEntryLength; /// public uint UnknownValue7 => Model.UnknownValue7; /// public uint UnknownValue8 => Model.UnknownValue8; /// public uint ThirdExecutableFileEntryLength => Model.ThirdExecutableFileEntryLength; /// public uint UnknownValue10 => Model.UnknownValue10; /// public uint UnknownValue11 => Model.UnknownValue11; /// public uint UnknownValue12 => Model.UnknownValue12; /// public uint UnknownValue13 => Model.UnknownValue13; /// public uint UnknownValue14 => Model.UnknownValue14; /// public uint UnknownValue15 => Model.UnknownValue15; /// public uint UnknownValue16 => Model.UnknownValue16; /// public uint UnknownValue17 => Model.UnknownValue17; /// public uint UnknownValue18 => Model.UnknownValue18; /// public byte[] Version => Model.Version; /// public byte[] PreStringValues => Model.PreStringValues; /// public byte[][] Strings => Model.Strings; #endregion #region Constructors /// public WiseSectionHeader(SectionHeader model, byte[] data) : base(model, data) { } /// public WiseSectionHeader(SectionHeader model, byte[] data, int offset) : base(model, data, offset) { } /// public WiseSectionHeader(SectionHeader model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// public WiseSectionHeader(SectionHeader model, Stream data) : base(model, data) { } /// public WiseSectionHeader(SectionHeader model, Stream data, long offset) : base(model, data, offset) { } /// public WiseSectionHeader(SectionHeader model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion #region Static Constructors /// /// Create a Wise Self-Extracting installer .WISE section from a byte array and offset /// /// Byte array representing the section /// Offset within the array to parse /// A Wise Self-Extracting installer .WISE section wrapper on success, null on failure public static WiseSectionHeader? Create(byte[]? data, int offset) { // If the data is invalid if (data is null || data.Length == 0) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Create a memory stream and use that var dataStream = new MemoryStream(data, offset, data.Length - offset); return Create(dataStream); } /// /// Create a Wise Self-Extracting installer .WISE section from a Stream /// /// Stream representing the section /// A Wise Self-Extracting installer .WISE section wrapper on success, null on failure public static WiseSectionHeader? Create(Stream? data) { // If the data is invalid if (data is null || !data.CanRead) return null; try { // Cache the current offset long currentOffset = data.Position; var model = new Serialization.Readers.WiseSectionHeader().Deserialize(data); if (model is null) return null; // HACK: Cache the end-of-header offset long endOffset = data.Position - currentOffset; return new WiseSectionHeader(model, data, currentOffset) { CompressedDataOffset = endOffset }; } catch { return null; } } #endregion } }