diff --git a/BinaryObjectScanner/FileType/MicrosoftCAB.cs b/BinaryObjectScanner/FileType/MicrosoftCAB.cs
index a5ba6c8d..c939257c 100644
--- a/BinaryObjectScanner/FileType/MicrosoftCAB.cs
+++ b/BinaryObjectScanner/FileType/MicrosoftCAB.cs
@@ -265,50 +265,65 @@ namespace BinaryObjectScanner.FileType
if (db?.CompressedData == null)
continue;
- switch (compressionType)
+ // Get the uncompressed data block
+ byte[] data = compressionType switch
{
- // Uncompressed data
- case CompressionType.TYPE_NONE:
- ms.Write(db.CompressedData, 0, db.CompressedData.Length);
- ms.Flush();
- break;
+ CompressionType.TYPE_NONE => db.CompressedData,
+ CompressionType.TYPE_MSZIP => DecompressMSZIPBlock(folderIndex, mszip, i, db),
- // MS-ZIP
- case CompressionType.TYPE_MSZIP:
- long preMsZipPosition = ms.Position;
- mszip.CopyTo(db.CompressedData, ms);
- long msZipDecompressedSize = ms.Position - preMsZipPosition;
+ // TODO: Unsupported
+ CompressionType.TYPE_QUANTUM => [],
+ CompressionType.TYPE_LZX => [],
- // Pad to the correct size but throw a warning about this
- if (msZipDecompressedSize < db.UncompressedSize)
- {
- Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {msZipDecompressedSize}");
- byte[] padding = new byte[db.UncompressedSize - msZipDecompressedSize];
- ms.Write(padding, 0, padding.Length);
- }
+ // Should be impossible
+ _ => [],
+ };
- break;
-
- // Quantum
- case CompressionType.TYPE_QUANTUM:
- // TODO: Unsupported
- break;
-
- // LZX
- case CompressionType.TYPE_LZX:
- // TODO: Unsupported
- break;
- }
+ // Write the uncompressed data block
+ ms.Write(data, 0, data.Length);
+ ms.Flush();
}
return ms;
}
+ ///
+ /// Decompress an MS-ZIP block using an existing decompressor
+ ///
+ /// Index of the folder in the cabinet
+ /// MS-ZIP decompressor with persistent state
+ /// Index of the block within the folder
+ /// Block data to be used for decompression
+ /// Byte array representing the decompressed data, empty on error
+ /// TODO: Remove once Serialization is updated
+ private static byte[] DecompressMSZIPBlock(int folderIndex, SabreTools.Compression.MSZIP.Decompressor mszip, int blockIndex, CFDATA block)
+ {
+ // Ignore invalid blocks
+ if (block.CompressedData == null)
+ return [];
+
+ // Decompress to a temporary stream
+ using var stream = new MemoryStream();
+ mszip.CopyTo(block.CompressedData, stream);
+
+ // Pad to the correct size but throw a warning about this
+ if (stream.Length < block.UncompressedSize)
+ {
+ Console.Error.WriteLine($"Data block {blockIndex} in folder {folderIndex} had mismatching sizes. Expected: {block.UncompressedSize}, Got: {stream.Length}");
+ byte[] padding = new byte[block.UncompressedSize - stream.Length];
+ stream.Write(padding, 0, padding.Length);
+ }
+
+ // Return the byte array data
+ return stream.ToArray();
+ }
+
///
/// Get the unmasked compression type for a folder
///
/// Folder to get the compression type for
/// Compression type on success, on error
+ /// TODO: Remove once Serialization is updated
private static CompressionType GetCompressionType(CFFOLDER folder)
{
if ((folder!.CompressionType & CompressionType.MASK_TYPE) == CompressionType.TYPE_NONE)