diff --git a/BurnOutSharp.Builders/InstallShieldCabinet.cs b/BurnOutSharp.Builders/InstallShieldCabinet.cs
index a18a4673..a7c84fff 100644
--- a/BurnOutSharp.Builders/InstallShieldCabinet.cs
+++ b/BurnOutSharp.Builders/InstallShieldCabinet.cs
@@ -18,7 +18,7 @@ namespace BurnOutSharp.Builders
/// Byte array to parse
/// Offset into the byte array
/// Filled cabinet on success, null on error
- public static Header ParseCabinet(byte[] data, int offset)
+ public static Cabinet ParseCabinet(byte[] data, int offset)
{
// If the data is invalid
if (data == null)
@@ -42,7 +42,7 @@ namespace BurnOutSharp.Builders
///
/// Stream to parse
/// Filled cabinet on success, null on error
- public static Header ParseCabinet(Stream data)
+ public static Cabinet ParseCabinet(Stream data)
{
// If the data is invalid
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
@@ -56,7 +56,7 @@ namespace BurnOutSharp.Builders
int initialOffset = (int)data.Position;
// Create a new cabinet to fill
- var header = new Header();
+ var cabinet = new Cabinet();
#region Common Header
@@ -66,7 +66,19 @@ namespace BurnOutSharp.Builders
return null;
// Set the cabinet header
- header.CommonHeader = commonHeader;
+ cabinet.CommonHeader = commonHeader;
+
+ #endregion
+
+ #region Volume Header
+
+ // Try to parse the volume header
+ var volumeHeader = ParseVolumeHeader(data, GetMajorVersion(commonHeader));
+ if (volumeHeader == null)
+ return null;
+
+ // Set the volume header
+ cabinet.VolumeHeader = volumeHeader;
#endregion
@@ -86,7 +98,7 @@ namespace BurnOutSharp.Builders
return null;
// Set the cabinet descriptor
- header.CabinetDescriptor = cabinetDescriptor;
+ cabinet.CabinetDescriptor = cabinetDescriptor;
#endregion
@@ -102,16 +114,16 @@ namespace BurnOutSharp.Builders
// Get the number of file table items
uint fileTableItems;
- if (header.MajorVersion <= 5)
+ if (GetMajorVersion(commonHeader) <= 5)
fileTableItems = cabinetDescriptor.DirectoryCount + cabinetDescriptor.FileCount;
else
fileTableItems = cabinetDescriptor.DirectoryCount;
// Create and fill the file table
- header.FileDescriptorOffsets = new uint[fileTableItems];
- for (int i = 0; i < header.FileDescriptorOffsets.Length; i++)
+ cabinet.FileDescriptorOffsets = new uint[fileTableItems];
+ for (int i = 0; i < cabinet.FileDescriptorOffsets.Length; i++)
{
- header.FileDescriptorOffsets[i] = data.ReadUInt32();
+ cabinet.FileDescriptorOffsets[i] = data.ReadUInt32();
}
#endregion
@@ -119,13 +131,13 @@ namespace BurnOutSharp.Builders
#region Directory Descriptors
// Create and fill the directory descriptors
- header.DirectoryDescriptors = new FileDescriptor[cabinetDescriptor.DirectoryCount];
+ cabinet.DirectoryDescriptors = new FileDescriptor[cabinetDescriptor.DirectoryCount];
for (int i = 0; i < cabinetDescriptor.DirectoryCount; i++)
{
// Get the directory descriptor offset
uint offset = cabinetDescriptorOffset
+ cabinetDescriptor.FileTableOffset
- + header.FileDescriptorOffsets[i];
+ + cabinet.FileDescriptorOffsets[i];
// If we have an invalid offset
if (offset < 0 || offset >= data.Length)
@@ -135,8 +147,8 @@ namespace BurnOutSharp.Builders
data.Seek(offset, SeekOrigin.Begin);
// Create and add the file descriptor
- FileDescriptor directoryDescriptor = ParseDirectoryDescriptor(data, header.MajorVersion);
- header.DirectoryDescriptors[i] = directoryDescriptor;
+ FileDescriptor directoryDescriptor = ParseDirectoryDescriptor(data, GetMajorVersion(commonHeader));
+ cabinet.DirectoryDescriptors[i] = directoryDescriptor;
}
#endregion
@@ -144,16 +156,16 @@ namespace BurnOutSharp.Builders
#region File Descriptors
// Create and fill the file descriptors
- header.FileDescriptors = new FileDescriptor[cabinetDescriptor.FileCount];
+ cabinet.FileDescriptors = new FileDescriptor[cabinetDescriptor.FileCount];
for (int i = 0; i < cabinetDescriptor.FileCount; i++)
{
// Get the file descriptor offset
uint offset;
- if (header.MajorVersion <= 5)
+ if (GetMajorVersion(commonHeader) <= 5)
{
offset = cabinetDescriptorOffset
+ cabinetDescriptor.FileTableOffset
- + header.FileDescriptorOffsets[cabinetDescriptor.DirectoryCount + i];
+ + cabinet.FileDescriptorOffsets[cabinetDescriptor.DirectoryCount + i];
}
else
{
@@ -171,8 +183,8 @@ namespace BurnOutSharp.Builders
data.Seek(offset, SeekOrigin.Begin);
// Create and add the file descriptor
- FileDescriptor fileDescriptor = ParseFileDescriptor(data, header.MajorVersion, cabinetDescriptorOffset + cabinetDescriptor.FileTableOffset);
- header.FileDescriptors[i] = fileDescriptor;
+ FileDescriptor fileDescriptor = ParseFileDescriptor(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset + cabinetDescriptor.FileTableOffset);
+ cabinet.FileDescriptors[i] = fileDescriptor;
}
#endregion
@@ -180,7 +192,7 @@ namespace BurnOutSharp.Builders
#region File Group Offsets
// Create and fill the file group offsets
- header.FileGroupOffsets = new Dictionary();
+ cabinet.FileGroupOffsets = new Dictionary();
for (int i = 0; i < cabinetDescriptor.FileGroupOffsets.Length; i++)
{
// Get the file group offset
@@ -197,8 +209,8 @@ namespace BurnOutSharp.Builders
data.Seek(offset, SeekOrigin.Begin);
// Create and add the offset
- OffsetList offsetList = ParseOffsetList(data, header.MajorVersion, cabinetDescriptorOffset);
- header.FileGroupOffsets[cabinetDescriptor.FileGroupOffsets[i]] = offsetList;
+ OffsetList offsetList = ParseOffsetList(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
+ cabinet.FileGroupOffsets[cabinetDescriptor.FileGroupOffsets[i]] = offsetList;
// If we have a nonzero next offset
uint nextOffset = offsetList.NextOffset;
@@ -211,8 +223,8 @@ namespace BurnOutSharp.Builders
data.Seek(internalOffset, SeekOrigin.Begin);
// Create and add the offset
- offsetList = ParseOffsetList(data, header.MajorVersion, cabinetDescriptorOffset);
- header.FileGroupOffsets[nextOffset] = offsetList;
+ offsetList = ParseOffsetList(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
+ cabinet.FileGroupOffsets[nextOffset] = offsetList;
// Set the next offset
nextOffset = offsetList.NextOffset;
@@ -225,7 +237,7 @@ namespace BurnOutSharp.Builders
// Create and fill the file groups
List fileGroups = new List();
- foreach (var kvp in header.FileGroupOffsets)
+ foreach (var kvp in cabinet.FileGroupOffsets)
{
// Get the offset
OffsetList list = kvp.Value;
@@ -236,21 +248,21 @@ namespace BurnOutSharp.Builders
data.Seek(list.DescriptorOffset + cabinetDescriptorOffset, SeekOrigin.Begin);
// Try to parse the file group
- FileGroup fileGroup = ParseFileGroup(data, header.MajorVersion, cabinetDescriptorOffset);
+ FileGroup fileGroup = ParseFileGroup(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
// Add the file group
fileGroups.Add(fileGroup);
}
// Set the file groups
- header.FileGroups = fileGroups.ToArray();
+ cabinet.FileGroups = fileGroups.ToArray();
#endregion
#region Component Offsets
// Create and fill the component offsets
- header.ComponentOffsets = new Dictionary();
+ cabinet.ComponentOffsets = new Dictionary();
for (int i = 0; i < cabinetDescriptor.ComponentOffsets.Length; i++)
{
// Get the component offset
@@ -267,8 +279,8 @@ namespace BurnOutSharp.Builders
data.Seek(offset, SeekOrigin.Begin);
// Create and add the offset
- OffsetList offsetList = ParseOffsetList(data, header.MajorVersion, cabinetDescriptorOffset);
- header.ComponentOffsets[cabinetDescriptor.ComponentOffsets[i]] = offsetList;
+ OffsetList offsetList = ParseOffsetList(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
+ cabinet.ComponentOffsets[cabinetDescriptor.ComponentOffsets[i]] = offsetList;
// If we have a nonzero next offset
uint nextOffset = offsetList.NextOffset;
@@ -281,8 +293,8 @@ namespace BurnOutSharp.Builders
data.Seek(internalOffset, SeekOrigin.Begin);
// Create and add the offset
- offsetList = ParseOffsetList(data, header.MajorVersion, cabinetDescriptorOffset);
- header.ComponentOffsets[nextOffset] = offsetList;
+ offsetList = ParseOffsetList(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
+ cabinet.ComponentOffsets[nextOffset] = offsetList;
// Set the next offset
nextOffset = offsetList.NextOffset;
@@ -295,7 +307,7 @@ namespace BurnOutSharp.Builders
// Create and fill the components
List components = new List();
- foreach (KeyValuePair kvp in header.ComponentOffsets)
+ foreach (KeyValuePair kvp in cabinet.ComponentOffsets)
{
// Get the offset
OffsetList list = kvp.Value;
@@ -306,18 +318,18 @@ namespace BurnOutSharp.Builders
data.Seek(list.DescriptorOffset + cabinetDescriptorOffset, SeekOrigin.Begin);
// Try to parse the component
- Component component = ParseComponent(data, header.MajorVersion, cabinetDescriptorOffset);
+ Component component = ParseComponent(data, GetMajorVersion(commonHeader), cabinetDescriptorOffset);
// Add the component
components.Add(component);
}
// Set the components
- header.Components = components.ToArray();
+ cabinet.Components = components.ToArray();
#endregion
- return header;
+ return cabinet;
}
///
@@ -342,6 +354,53 @@ namespace BurnOutSharp.Builders
return commonHeader;
}
+ ///
+ /// Parse a Stream into a volume header
+ ///
+ /// Stream to parse
+ /// Major version of the cabinet
+ /// Filled volume header on success, null on error
+ private static VolumeHeader ParseVolumeHeader(Stream data, int majorVersion)
+ {
+ VolumeHeader volumeHeader = new VolumeHeader();
+
+ // Read the descriptor based on version
+ if (majorVersion <= 5)
+ {
+ volumeHeader.DataOffset = data.ReadUInt32();
+ _ = data.ReadBytes(0x04); // Skip 0x04 bytes, unknown data?
+ volumeHeader.FirstFileIndex = data.ReadUInt32();
+ volumeHeader.LastFileIndex = data.ReadUInt32();
+ volumeHeader.FirstFileOffset = data.ReadUInt32();
+ volumeHeader.FirstFileSizeExpanded = data.ReadUInt32();
+ volumeHeader.FirstFileSizeCompressed = data.ReadUInt32();
+ volumeHeader.LastFileOffset = data.ReadUInt32();
+ volumeHeader.LastFileSizeExpanded = data.ReadUInt32();
+ volumeHeader.LastFileSizeCompressed = data.ReadUInt32();
+ }
+ else
+ {
+ volumeHeader.DataOffset = data.ReadUInt32();
+ volumeHeader.DataOffsetHigh = data.ReadUInt32();
+ volumeHeader.FirstFileIndex = data.ReadUInt32();
+ volumeHeader.LastFileIndex = data.ReadUInt32();
+ volumeHeader.FirstFileOffset = data.ReadUInt32();
+ volumeHeader.FirstFileOffsetHigh = data.ReadUInt32();
+ volumeHeader.FirstFileSizeExpanded = data.ReadUInt32();
+ volumeHeader.FirstFileSizeExpandedHigh = data.ReadUInt32();
+ volumeHeader.FirstFileSizeCompressed = data.ReadUInt32();
+ volumeHeader.FirstFileSizeCompressedHigh = data.ReadUInt32();
+ volumeHeader.LastFileOffset = data.ReadUInt32();
+ volumeHeader.LastFileOffsetHigh = data.ReadUInt32();
+ volumeHeader.LastFileSizeExpanded = data.ReadUInt32();
+ volumeHeader.LastFileSizeExpandedHigh = data.ReadUInt32();
+ volumeHeader.LastFileSizeCompressed = data.ReadUInt32();
+ volumeHeader.LastFileSizeCompressedHigh = data.ReadUInt32();
+ }
+
+ return volumeHeader;
+ }
+
///
/// Parse a Stream into a cabinet descriptor
///
@@ -599,51 +658,29 @@ namespace BurnOutSharp.Builders
return fileDescriptor;
}
+ #endregion
+
+ #region Helpers
+
///
- /// Parse a Stream into a volume header
+ /// Get the major version of the cabinet
///
- /// Stream to parse
- /// Major version of the cabinet
- /// Filled volume header on success, null on error
- private static VolumeHeader ParseVolumeHeader(Stream data, int majorVersion)
+ /// This should live in the wrapper but is needed during parsing
+ private static int GetMajorVersion(CommonHeader commonHeader)
{
- VolumeHeader volumeHeader = new VolumeHeader();
-
- // Read the descriptor based on version
- if (majorVersion <= 5)
+ uint majorVersion = commonHeader.Version;
+ if (majorVersion >> 24 == 1)
{
- volumeHeader.DataOffset = data.ReadUInt32();
- _ = data.ReadBytes(0x04); // Skip 0x04 bytes, unknown data?
- volumeHeader.FirstFileIndex = data.ReadUInt32();
- volumeHeader.LastFileIndex = data.ReadUInt32();
- volumeHeader.FirstFileOffset = data.ReadUInt32();
- volumeHeader.FirstFileSizeExpanded = data.ReadUInt32();
- volumeHeader.FirstFileSizeCompressed = data.ReadUInt32();
- volumeHeader.LastFileOffset = data.ReadUInt32();
- volumeHeader.LastFileSizeExpanded = data.ReadUInt32();
- volumeHeader.LastFileSizeCompressed = data.ReadUInt32();
+ majorVersion = (majorVersion >> 12) & 0x0F;
}
- else
+ else if (majorVersion >> 24 == 2 || majorVersion >> 24 == 4)
{
- volumeHeader.DataOffset = data.ReadUInt32();
- volumeHeader.DataOffsetHigh = data.ReadUInt32();
- volumeHeader.FirstFileIndex = data.ReadUInt32();
- volumeHeader.LastFileIndex = data.ReadUInt32();
- volumeHeader.FirstFileOffset = data.ReadUInt32();
- volumeHeader.FirstFileOffsetHigh = data.ReadUInt32();
- volumeHeader.FirstFileSizeExpanded = data.ReadUInt32();
- volumeHeader.FirstFileSizeExpandedHigh = data.ReadUInt32();
- volumeHeader.FirstFileSizeCompressed = data.ReadUInt32();
- volumeHeader.FirstFileSizeCompressedHigh = data.ReadUInt32();
- volumeHeader.LastFileOffset = data.ReadUInt32();
- volumeHeader.LastFileOffsetHigh = data.ReadUInt32();
- volumeHeader.LastFileSizeExpanded = data.ReadUInt32();
- volumeHeader.LastFileSizeExpandedHigh = data.ReadUInt32();
- volumeHeader.LastFileSizeCompressed = data.ReadUInt32();
- volumeHeader.LastFileSizeCompressedHigh = data.ReadUInt32();
+ majorVersion = majorVersion & 0xFFFF;
+ if (majorVersion != 0)
+ majorVersion /= 100;
}
- return volumeHeader;
+ return (int)majorVersion;
}
#endregion
diff --git a/BurnOutSharp.Models/InstallShieldCabinet/Cabinet.cs b/BurnOutSharp.Models/InstallShieldCabinet/Cabinet.cs
new file mode 100644
index 00000000..266b29b1
--- /dev/null
+++ b/BurnOutSharp.Models/InstallShieldCabinet/Cabinet.cs
@@ -0,0 +1,75 @@
+using System.Collections.Generic;
+
+namespace BurnOutSharp.Models.InstallShieldCabinet
+{
+ ///
+ ///
+ public sealed class Cabinet
+ {
+ #region Headers
+
+ ///
+ /// Common header
+ ///
+ public CommonHeader CommonHeader { get; set; }
+
+ ///
+ /// Volume header
+ ///
+ public VolumeHeader VolumeHeader { get; set; }
+
+ ///
+ /// Cabinet descriptor
+ ///
+ public CabDescriptor CabinetDescriptor { get; set; }
+
+ #endregion
+
+ #region File Descriptors
+
+ ///
+ /// Offsets to all file descriptors
+ ///
+ public uint[] FileDescriptorOffsets { get; set; }
+
+ ///
+ /// Directory file descriptors
+ ///
+ public FileDescriptor[] DirectoryDescriptors { get; set; }
+
+ ///
+ /// Standard file descriptors
+ ///
+ public FileDescriptor[] FileDescriptors { get; set; }
+
+ #endregion
+
+ #region File Groups
+
+ ///
+ /// File group offset to offset list mapping
+ ///
+ public Dictionary FileGroupOffsets { get; set; }
+
+ ///
+ /// File groups
+ ///
+ public FileGroup[] FileGroups { get; set; }
+
+ #endregion
+
+ #region Components
+
+ ///
+ /// Component offset to offset list mapping
+ ///
+ public Dictionary ComponentOffsets { get; set; }
+
+ ///
+ /// Components
+ ///
+ public Component[] Components { get; set; }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/BurnOutSharp.Models/InstallShieldCabinet/Header.cs b/BurnOutSharp.Models/InstallShieldCabinet/Header.cs
deleted file mode 100644
index 8c0d690a..00000000
--- a/BurnOutSharp.Models/InstallShieldCabinet/Header.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.Collections.Generic;
-
-namespace BurnOutSharp.Models.InstallShieldCabinet
-{
- ///
- public sealed class Header
- {
- // TODO: Move to wrapper, when exists
- public int MajorVersion
- {
- get
- {
- uint majorVersion = CommonHeader.Version;
- 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;
- }
- }
-
- #region Headers
-
- public CommonHeader CommonHeader { get; set; }
-
- public CabDescriptor CabinetDescriptor { get; set; }
-
- #endregion
-
- #region File Descriptors
-
- public uint[] FileDescriptorOffsets { get; set; }
-
- public FileDescriptor[] DirectoryDescriptors { get; set; }
-
- public FileDescriptor[] FileDescriptors { get; set; }
-
- #endregion
-
- #region File Groups
-
- public Dictionary FileGroupOffsets { get; set; }
-
- public FileGroup[] FileGroups { get; set; }
-
- #endregion
-
- #region Components
-
- public Dictionary ComponentOffsets { get; set; }
-
- public Component[] Components { get; set; }
-
- #endregion
- }
-}
\ No newline at end of file