using System.Collections.Generic; using System.IO; using System.Text; namespace BinaryObjectScanner.Wrappers { public partial class InstallShieldCabinet : WrapperBase { #region Descriptive Properties /// public override string DescriptionString => "InstallShield Cabinet"; #endregion #region Pass-Through Properties #region Common Header /// #if NET48 public string Signature => _model.CommonHeader.Signature; #else public string? Signature => _model.CommonHeader?.Signature; #endif /// #if NET48 public uint Version => _model.CommonHeader.Version; #else public uint? Version => _model.CommonHeader?.Version; #endif /// #if NET48 public uint VolumeInfo => _model.CommonHeader.VolumeInfo; #else public uint? VolumeInfo => _model.CommonHeader?.VolumeInfo; #endif /// #if NET48 public uint DescriptorOffset => _model.CommonHeader.DescriptorOffset; #else public uint? DescriptorOffset => _model.CommonHeader?.DescriptorOffset; #endif /// #if NET48 public uint DescriptorSize => _model.CommonHeader.DescriptorSize; #else public uint? DescriptorSize => _model.CommonHeader?.DescriptorSize; #endif #endregion #region Volume Header /// #if NET48 public uint DataOffset => _model.VolumeHeader.DataOffset; #else public uint? DataOffset => _model.VolumeHeader?.DataOffset; #endif /// #if NET48 public uint DataOffsetHigh => _model.VolumeHeader.DataOffsetHigh; #else public uint? DataOffsetHigh => _model.VolumeHeader?.DataOffsetHigh; #endif /// #if NET48 public uint FirstFileIndex => _model.VolumeHeader.FirstFileIndex; #else public uint? FirstFileIndex => _model.VolumeHeader?.FirstFileIndex; #endif /// #if NET48 public uint LastFileIndex => _model.VolumeHeader.LastFileIndex; #else public uint? LastFileIndex => _model.VolumeHeader?.LastFileIndex; #endif /// #if NET48 public uint FirstFileOffset => _model.VolumeHeader.FirstFileOffset; #else public uint? FirstFileOffset => _model.VolumeHeader?.FirstFileOffset; #endif /// #if NET48 public uint FirstFileOffsetHigh => _model.VolumeHeader.FirstFileOffsetHigh; #else public uint? FirstFileOffsetHigh => _model.VolumeHeader?.FirstFileOffsetHigh; #endif /// #if NET48 public uint FirstFileSizeExpanded => _model.VolumeHeader.FirstFileSizeExpanded; #else public uint? FirstFileSizeExpanded => _model.VolumeHeader?.FirstFileSizeExpanded; #endif /// #if NET48 public uint FirstFileSizeExpandedHigh => _model.VolumeHeader.FirstFileSizeExpandedHigh; #else public uint? FirstFileSizeExpandedHigh => _model.VolumeHeader?.FirstFileSizeExpandedHigh; #endif /// #if NET48 public uint FirstFileSizeCompressed => _model.VolumeHeader.FirstFileSizeCompressed; #else public uint? FirstFileSizeCompressed => _model.VolumeHeader?.FirstFileSizeCompressed; #endif /// #if NET48 public uint FirstFileSizeCompressedHigh => _model.VolumeHeader.FirstFileSizeCompressedHigh; #else public uint? FirstFileSizeCompressedHigh => _model.VolumeHeader?.FirstFileSizeCompressedHigh; #endif /// #if NET48 public uint LastFileOffset => _model.VolumeHeader.LastFileOffset; #else public uint? LastFileOffset => _model.VolumeHeader?.LastFileOffset; #endif /// #if NET48 public uint LastFileOffsetHigh => _model.VolumeHeader.LastFileOffsetHigh; #else public uint? LastFileOffsetHigh => _model.VolumeHeader?.LastFileOffsetHigh; #endif /// #if NET48 public uint LastFileSizeExpanded => _model.VolumeHeader.LastFileSizeExpanded; #else public uint? LastFileSizeExpanded => _model.VolumeHeader?.LastFileSizeExpanded; #endif /// #if NET48 public uint LastFileSizeExpandedHigh => _model.VolumeHeader.LastFileSizeExpandedHigh; #else public uint? LastFileSizeExpandedHigh => _model.VolumeHeader?.LastFileSizeExpandedHigh; #endif /// #if NET48 public uint LastFileSizeCompressed => _model.VolumeHeader.LastFileSizeCompressed; #else public uint? LastFileSizeCompressed => _model.VolumeHeader?.LastFileSizeCompressed; #endif /// #if NET48 public uint LastFileSizeCompressedHigh => _model.VolumeHeader.LastFileSizeCompressedHigh; #else public uint? LastFileSizeCompressedHigh => _model.VolumeHeader?.LastFileSizeCompressedHigh; #endif #endregion #region Descriptor /// #if NET48 public uint StringsOffset => _model.Descriptor.StringsOffset; #else public uint? StringsOffset => _model.Descriptor?.StringsOffset; #endif /// #if NET48 public byte[] Reserved0 => _model.Descriptor.Reserved0; #else public byte[]? Reserved0 => _model.Descriptor?.Reserved0; #endif /// #if NET48 public uint ComponentListOffset => _model.Descriptor.ComponentListOffset; #else public uint? ComponentListOffset => _model.Descriptor?.ComponentListOffset; #endif /// #if NET48 public uint FileTableOffset => _model.Descriptor.FileTableOffset; #else public uint? FileTableOffset => _model.Descriptor?.FileTableOffset; #endif /// #if NET48 public byte[] Reserved1 => _model.Descriptor.Reserved1; #else public byte[]? Reserved1 => _model.Descriptor?.Reserved1; #endif /// #if NET48 public uint FileTableSize => _model.Descriptor.FileTableSize; #else public uint? FileTableSize => _model.Descriptor?.FileTableSize; #endif /// #if NET48 public uint FileTableSize2 => _model.Descriptor.FileTableSize2; #else public uint? FileTableSize2 => _model.Descriptor?.FileTableSize2; #endif /// #if NET48 public ushort DirectoryCount => _model.Descriptor.DirectoryCount; #else public ushort? DirectoryCount => _model.Descriptor?.DirectoryCount; #endif /// #if NET48 public byte[] Reserved2 => _model.Descriptor.Reserved2; #else public byte[]? Reserved2 => _model.Descriptor?.Reserved2; #endif /// #if NET48 public byte[] Reserved3 => _model.Descriptor.Reserved3; #else public byte[]? Reserved3 => _model.Descriptor?.Reserved3; #endif /// #if NET48 public byte[] Reserved4 => _model.Descriptor.Reserved4; #else public byte[]? Reserved4 => _model.Descriptor?.Reserved4; #endif /// #if NET48 public uint FileCount => _model.Descriptor.FileCount; #else public uint? FileCount => _model.Descriptor?.FileCount; #endif /// #if NET48 public uint FileTableOffset2 => _model.Descriptor.FileTableOffset2; #else public uint? FileTableOffset2 => _model.Descriptor?.FileTableOffset2; #endif /// #if NET48 public ushort ComponentTableInfoCount => _model.Descriptor.ComponentTableInfoCount; #else public ushort? ComponentTableInfoCount => _model.Descriptor?.ComponentTableInfoCount; #endif /// #if NET48 public uint ComponentTableOffset => _model.Descriptor.ComponentTableOffset; #else public uint? ComponentTableOffset => _model.Descriptor?.ComponentTableOffset; #endif /// #if NET48 public byte[] Reserved5 => _model.Descriptor.Reserved5; #else public byte[]? Reserved5 => _model.Descriptor?.Reserved5; #endif /// #if NET48 public byte[] Reserved6 => _model.Descriptor.Reserved6; #else public byte[]? Reserved6 => _model.Descriptor?.Reserved6; #endif /// #if NET48 public uint[] D_FileGroupOffsets => _model.Descriptor.FileGroupOffsets; #else public uint[]? D_FileGroupOffsets => _model.Descriptor?.FileGroupOffsets; #endif /// #if NET48 public uint[] D_ComponentOffsets => _model.Descriptor.ComponentOffsets; #else public uint[]? D_ComponentOffsets => _model.Descriptor?.ComponentOffsets; #endif /// #if NET48 public uint SetupTypesOffset => _model.Descriptor.SetupTypesOffset; #else public uint? SetupTypesOffset => _model.Descriptor?.SetupTypesOffset; #endif /// #if NET48 public uint SetupTableOffset => _model.Descriptor.SetupTableOffset; #else public uint? SetupTableOffset => _model.Descriptor?.SetupTableOffset; #endif /// #if NET48 public byte[] Reserved7 => _model.Descriptor.Reserved7; #else public byte[]? Reserved7 => _model.Descriptor?.Reserved7; #endif /// #if NET48 public byte[] Reserved8 => _model.Descriptor.Reserved8; #else public byte[]? Reserved8 => _model.Descriptor?.Reserved8; #endif #endregion #region File Descriptor Offsets /// #if NET48 public uint[] FileDescriptorOffsets => _model.FileDescriptorOffsets; #else public uint[]? FileDescriptorOffsets => _model.FileDescriptorOffsets; #endif #endregion #region Directory Descriptors /// #if NET48 public string[] DirectoryNames => _model.DirectoryNames; #else public string[]? DirectoryNames => _model.DirectoryNames; #endif #endregion #region File Descriptors /// #if NET48 public SabreTools.Models.InstallShieldCabinet.FileDescriptor[] FileDescriptors => _model.FileDescriptors; #else public SabreTools.Models.InstallShieldCabinet.FileDescriptor?[]? FileDescriptors => _model.FileDescriptors; #endif #endregion #region File Group Offsets /// #if NET48 public Dictionary FileGroupOffsets => _model.FileGroupOffsets; #else public Dictionary? FileGroupOffsets => _model.FileGroupOffsets; #endif #endregion #region File Groups /// #if NET48 public SabreTools.Models.InstallShieldCabinet.FileGroup[] FileGroups => _model.FileGroups; #else public SabreTools.Models.InstallShieldCabinet.FileGroup?[]? FileGroups => _model.FileGroups; #endif #endregion #region Component Offsets /// #if NET48 public Dictionary ComponentOffsets => _model.ComponentOffsets; #else public Dictionary? ComponentOffsets => _model.ComponentOffsets; #endif #endregion #region Components /// #if NET48 public SabreTools.Models.InstallShieldCabinet.Component[] Components => _model.Components; #else public SabreTools.Models.InstallShieldCabinet.Component?[]? Components => _model.Components; #endif #endregion #endregion #region Extension Properties /// /// The major version of the cabinet /// public int MajorVersion { get { #if NET48 uint majorVersion = Version; #else uint majorVersion = Version ?? 0; #endif if (majorVersion >> 24 == 1) { majorVersion = (majorVersion >> 12) & 0x0F; } else if (majorVersion >> 24 == 2 || majorVersion >> 24 == 4) { majorVersion = majorVersion & 0xFFFF; if (majorVersion != 0) majorVersion /= 100; } return (int)majorVersion; } } #endregion #region Constructors /// #if NET48 public InstallShieldCabinet(SabreTools.Models.InstallShieldCabinet.Cabinet model, byte[] data, int offset) #else public InstallShieldCabinet(SabreTools.Models.InstallShieldCabinet.Cabinet? model, byte[]? data, int offset) #endif : base(model, data, offset) { // All logic is handled by the base class } /// #if NET48 public InstallShieldCabinet(SabreTools.Models.InstallShieldCabinet.Cabinet model, Stream data) #else public InstallShieldCabinet(SabreTools.Models.InstallShieldCabinet.Cabinet? model, Stream? data) #endif : base(model, data) { // All logic is handled by the base class } /// /// Create an InstallShield Cabinet from a byte array and offset /// /// Byte array representing the cabinet /// Offset within the array to parse /// A cabinet wrapper on success, null on failure #if NET48 public static InstallShieldCabinet Create(byte[] data, int offset) #else public static InstallShieldCabinet? Create(byte[]? data, int offset) #endif { // 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 InstallShield Cabinet from a Stream /// /// Stream representing the cabinet /// A cabinet wrapper on success, null on failure #if NET48 public static InstallShieldCabinet Create(Stream data) #else public static InstallShieldCabinet? Create(Stream? data) #endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) return null; var cabinet = new SabreTools.Serialization.Streams.InstallShieldCabinet().Deserialize(data); if (cabinet == null) return null; try { return new InstallShieldCabinet(cabinet, data); } catch { return null; } } #endregion #region Printing /// public override StringBuilder PrettyPrint() { StringBuilder builder = new StringBuilder(); Printing.InstallShieldCabinet.Print(builder, _model); return builder; } #if NET6_0_OR_GREATER /// public override string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(_model, _jsonSerializerOptions); #endif #endregion } }