@@ -265,50 +265,65 @@ private static void ExtractFile(string outDir, Stream blockStream, CFFILE file,
265265 if ( db ? . CompressedData == null )
266266 continue ;
267267
268- switch ( compressionType )
268+ // Get the uncompressed data block
269+ byte [ ] data = compressionType switch
269270 {
270- // Uncompressed data
271- case CompressionType . TYPE_NONE :
272- ms . Write ( db . CompressedData , 0 , db . CompressedData . Length ) ;
273- ms . Flush ( ) ;
274- break ;
275-
276- // MS-ZIP
277- case CompressionType . TYPE_MSZIP :
278- long preMsZipPosition = ms . Position ;
279- mszip . CopyTo ( db . CompressedData , ms ) ;
280- long msZipDecompressedSize = ms . Position - preMsZipPosition ;
281-
282- // Pad to the correct size but throw a warning about this
283- if ( msZipDecompressedSize < db . UncompressedSize )
284- {
285- Console . Error . WriteLine ( $ "Data block { i } in folder { folderIndex } had mismatching sizes. Expected: { db . UncompressedSize } , Got: { msZipDecompressedSize } ") ;
286- byte [ ] padding = new byte [ db . UncompressedSize - msZipDecompressedSize ] ;
287- ms . Write ( padding , 0 , padding . Length ) ;
288- }
289-
290- break ;
291-
292- // Quantum
293- case CompressionType . TYPE_QUANTUM :
294- // TODO: Unsupported
295- break ;
296-
297- // LZX
298- case CompressionType . TYPE_LZX :
299- // TODO: Unsupported
300- break ;
301- }
271+ CompressionType . TYPE_NONE => db . CompressedData ,
272+ CompressionType . TYPE_MSZIP => DecompressMSZIPBlock ( folderIndex , mszip , i , db ) ,
273+
274+ // TODO: Unsupported
275+ CompressionType . TYPE_QUANTUM => [ ] ,
276+ CompressionType . TYPE_LZX => [ ] ,
277+
278+ // Should be impossible
279+ _ => [ ] ,
280+ } ;
281+
282+ // Write the uncompressed data block
283+ ms . Write ( data , 0 , data . Length ) ;
284+ ms . Flush ( ) ;
302285 }
303286
304287 return ms ;
305288 }
306289
290+ /// <summary>
291+ /// Decompress an MS-ZIP block using an existing decompressor
292+ /// </summary>
293+ /// <param name="folderIndex">Index of the folder in the cabinet</param>
294+ /// <param name="mszip">MS-ZIP decompressor with persistent state</param>
295+ /// <param name="blockIndex">Index of the block within the folder</param>
296+ /// <param name="block">Block data to be used for decompression</param>
297+ /// <returns>Byte array representing the decompressed data, empty on error</returns>
298+ /// TODO: Remove once Serialization is updated
299+ private static byte [ ] DecompressMSZIPBlock ( int folderIndex , SabreTools . Compression . MSZIP . Decompressor mszip , int blockIndex , CFDATA block )
300+ {
301+ // Ignore invalid blocks
302+ if ( block . CompressedData == null )
303+ return [ ] ;
304+
305+ // Decompress to a temporary stream
306+ using var stream = new MemoryStream ( ) ;
307+ mszip . CopyTo ( block . CompressedData , stream ) ;
308+
309+ // Pad to the correct size but throw a warning about this
310+ if ( stream . Length < block . UncompressedSize )
311+ {
312+ Console . Error . WriteLine ( $ "Data block { blockIndex } in folder { folderIndex } had mismatching sizes. Expected: { block . UncompressedSize } , Got: { stream . Length } ") ;
313+ byte [ ] padding = new byte [ block . UncompressedSize - stream . Length ] ;
314+ stream . Write ( padding , 0 , padding . Length ) ;
315+ }
316+
317+ // Return the byte array data
318+ return stream . ToArray ( ) ;
319+ }
320+
307321 /// <summary>
308322 /// Get the unmasked compression type for a folder
309323 /// </summary>
310324 /// <param name="folder">Folder to get the compression type for</param>
311325 /// <returns>Compression type on success, <see cref="ushort.MaxValue"/> on error</returns>
326+ /// TODO: Remove once Serialization is updated
312327 private static CompressionType GetCompressionType ( CFFOLDER folder )
313328 {
314329 if ( ( folder ! . CompressionType & CompressionType . MASK_TYPE ) == CompressionType . TYPE_NONE )
0 commit comments