From f51cfeb451b35a1c8dc2226090ed1681573dfae8 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Wed, 3 Dec 2025 17:26:08 -0500 Subject: [PATCH 01/11] Better fix --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 9b754325..6b3039f5 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -174,12 +174,17 @@ public bool Extract(string outputDirectory, bool includeDebug) // Loop through the current folders for (int f = 0; f < cabinet.Folders.Length; f++) { + if (f == 0 && (cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT || + cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_FROM_PREV)) + continue; + var folder = cabinet.Folders[f]; allExtracted &= cabinet.ExtractFolder(Filename, outputDirectory, folder, f, ignorePrev, includeDebug); } // Move to the next cabinet, if possible cabinet = cabinet.Next; + cabinet?.Prev = null; if (cabinet?.Folders == null || cabinet.Folders.Length == 0) break; } From 4d2700a137ac37ceba2f99c2fbc2d95a3334367d Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Wed, 3 Dec 2025 18:43:03 -0500 Subject: [PATCH 02/11] initial --- .../Readers/MicrosoftCabinet.cs | 6 ----- .../Wrappers/MicrosoftCabinet.Extraction.cs | 26 +++++++++++++++++++ .../Wrappers/MicrosoftCabinet.cs | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs index 875f35a7..1d68dd29 100644 --- a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs @@ -204,12 +204,6 @@ private static CFDATA ParseDataBlock(Stream data, byte dataReservedSize) dataBlock.CompressedSize = data.ReadUInt16LittleEndian(); dataBlock.UncompressedSize = data.ReadUInt16LittleEndian(); - if (dataReservedSize > 0) - dataBlock.ReservedData = data.ReadBytes(dataReservedSize); - - if (dataBlock.CompressedSize > 0) - dataBlock.CompressedData = data.ReadBytes(dataBlock.CompressedSize); - return dataBlock; } diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 6b3039f5..d77b21dc 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -198,6 +198,32 @@ public bool Extract(string outputDirectory, bool includeDebug) } } + public void GetData(CFFOLDER folder) + { + if (folder.CabStartOffset > 0) + { + uint offset = folder.CabStartOffset; + + for (int i = 0; i < folder.DataCount; i++) + { + offset += 8; + + if (Header.DataReservedSize > 0) + { + folder.DataBlocks[i].ReservedData = ReadRangeFromSource(offset, Header.DataReservedSize); + offset += Header.DataReservedSize; + } + + if (folder.DataBlocks[i].CompressedSize > 0) + { + folder.DataBlocks[i].CompressedData = ReadRangeFromSource(offset, folder.DataBlocks[i].CompressedSize); + offset += folder.DataBlocks[i].CompressedSize; + } + } + } + } + + /// /// Extract the contents of a single folder /// diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 49ab1983..37e2c034 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -315,6 +315,8 @@ private static CompressionType GetCompressionType(CFFOLDER folder) if (folder?.DataBlocks == null || folder.DataBlocks.Length == 0) return null; + GetData(folder); + // Get all files for the folder var files = GetFiles(folderIndex); if (files.Length == 0) From 809aacacc71c996f91489d93f2067a0afb4deeca Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Wed, 3 Dec 2025 18:59:43 -0500 Subject: [PATCH 03/11] Fixed --- SabreTools.Serialization/Readers/MicrosoftCabinet.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs index 1d68dd29..c71f0962 100644 --- a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs @@ -203,7 +203,13 @@ private static CFDATA ParseDataBlock(Stream data, byte dataReservedSize) dataBlock.Checksum = data.ReadUInt32LittleEndian(); dataBlock.CompressedSize = data.ReadUInt16LittleEndian(); dataBlock.UncompressedSize = data.ReadUInt16LittleEndian(); + + if (dataReservedSize > 0) + data.SeekIfPossible(data.Position + dataReservedSize, SeekOrigin.Begin); + if (dataBlock.CompressedSize > 0) + data.SeekIfPossible(data.Position + dataBlock.CompressedSize, SeekOrigin.Begin); + return dataBlock; } From a4a5aa34a16546614fdc46d566bc3773cf49ddbc Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Wed, 3 Dec 2025 19:33:30 -0500 Subject: [PATCH 04/11] Move function to proper location, clear memory better --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 30 +++---------------- .../Wrappers/MicrosoftCabinet.cs | 25 ++++++++++++++++ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index d77b21dc..5e9a5d4d 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -183,6 +183,10 @@ public bool Extract(string outputDirectory, bool includeDebug) } // Move to the next cabinet, if possible + foreach (var folder in cabinet.Folders) + { + folder.DataBlocks = []; + } cabinet = cabinet.Next; cabinet?.Prev = null; if (cabinet?.Folders == null || cabinet.Folders.Length == 0) @@ -197,32 +201,6 @@ public bool Extract(string outputDirectory, bool includeDebug) return false; } } - - public void GetData(CFFOLDER folder) - { - if (folder.CabStartOffset > 0) - { - uint offset = folder.CabStartOffset; - - for (int i = 0; i < folder.DataCount; i++) - { - offset += 8; - - if (Header.DataReservedSize > 0) - { - folder.DataBlocks[i].ReservedData = ReadRangeFromSource(offset, Header.DataReservedSize); - offset += Header.DataReservedSize; - } - - if (folder.DataBlocks[i].CompressedSize > 0) - { - folder.DataBlocks[i].CompressedData = ReadRangeFromSource(offset, folder.DataBlocks[i].CompressedSize); - offset += folder.DataBlocks[i].CompressedSize; - } - } - } - } - /// /// Extract the contents of a single folder diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 37e2c034..4e39685f 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -362,6 +362,31 @@ private static CompressionType GetCompressionType(CFFOLDER folder) // Return all found blocks in order return [.. prevBlocks, .. folder.DataBlocks, .. nextBlocks]; } + + public void GetData(CFFOLDER folder) + { + if (folder.CabStartOffset > 0) + { + uint offset = folder.CabStartOffset; + + for (int i = 0; i < folder.DataCount; i++) + { + offset += 8; + + if (Header.DataReservedSize > 0) + { + folder.DataBlocks[i].ReservedData = ReadRangeFromSource(offset, Header.DataReservedSize); + offset += Header.DataReservedSize; + } + + if (folder.DataBlocks[i].CompressedSize > 0) + { + folder.DataBlocks[i].CompressedData = ReadRangeFromSource(offset, folder.DataBlocks[i].CompressedSize); + offset += folder.DataBlocks[i].CompressedSize; + } + } + } + } /// /// Get all files for the current folder index From d559f735e7bb8b77cadd10ac5278a113655a5041 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Thu, 4 Dec 2025 10:45:41 -0500 Subject: [PATCH 05/11] work so far --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 2 +- .../Wrappers/MicrosoftCabinet.cs | 77 ++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 5e9a5d4d..c7b74e95 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -226,7 +226,7 @@ private bool ExtractFolder(string? filename, // Loop through the files bool allExtracted = true; - var files = GetFiles(folderIndex, ignorePrev); + var files = GetFiles(filename, folderIndex, ignorePrev); for (int i = 0; i < files.Length; i++) { var file = files[i]; diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 4e39685f..f129d44b 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -318,7 +318,7 @@ private static CompressionType GetCompressionType(CFFOLDER folder) GetData(folder); // Get all files for the folder - var files = GetFiles(folderIndex); + var files = GetFiles(filename, folderIndex); if (files.Length == 0) return folder.DataBlocks; @@ -337,7 +337,7 @@ private static CompressionType GetCompressionType(CFFOLDER folder) // Get all blocks from Prev if (Prev?.Header != null && Prev.Folders != null) { - int prevFolderIndex = Prev.FolderCount; + int prevFolderIndex = Prev.FolderCount - 1; var prevFolder = Prev.Folders[prevFolderIndex - 1]; prevBlocks = Prev.GetDataBlocks(filename, prevFolder, prevFolderIndex, skipNext: true) ?? []; } @@ -387,6 +387,77 @@ public void GetData(CFFOLDER folder) } } } + + /// + /// Get all files for the current folder index + /// + /// Index of the folder in the cabinet + /// True to ignore previous links, false otherwise + /// Array of all files for the folder + private CFFILE[] GetFiles(string? filename, int folderIndex, bool ignorePrev = false, bool skipPrev = false, bool skipNext = false) + { + // Ignore invalid archives + if (Files == null) + return []; + + // Get all files with a name and matching index + var files = Array.FindAll(Files, f => + { + if (string.IsNullOrEmpty(f.Name)) + return false; + + // Ignore links to previous cabinets, if required + if (ignorePrev) + { + if (f.FolderIndex == FolderIndex.CONTINUED_FROM_PREV) + return false; + else if (f.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT) + return false; + } + + int fileFolder = GetFolderIndex(f); + return fileFolder == folderIndex; + }); + + // Check if the folder spans in either direction + bool spanPrev = Array.Exists(files, f => f.FolderIndex == FolderIndex.CONTINUED_FROM_PREV || f.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT); + bool spanNext = Array.Exists(files, f => f.FolderIndex == FolderIndex.CONTINUED_TO_NEXT || f.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT); + + // If the folder spans backward and Prev is not being skipped + CFFILE[] prevFiles = []; + if (!skipPrev && spanPrev) + { + // Try to get Prev if it doesn't exist + if (Prev?.Header == null) + Prev = OpenPrevious(filename); + + // Get all files from Prev + if (Prev?.Header != null && Prev.Folders != null) + { + int prevFolderIndex = Prev.FolderCount - 1; + prevFiles = Prev.GetFiles(filename, prevFolderIndex, skipNext: true) ?? []; + } + } + + // If the folder spans forward and Next is not being skipped + CFFILE[] nextFiles = []; + if (!skipNext && spanNext) + { + // Try to get Next if it doesn't exist + if (Next?.Header == null) + Next = OpenNext(filename); + + // Get all files from Prev + if (Next?.Header != null && Next.Folders != null) + { + var nextFolder = Next.Folders[0]; + nextFiles = Next.GetFiles(filename, 0, skipPrev: true) ?? []; + } + } + + // Return all found files in order + return [.. prevFiles, .. files, .. nextFiles]; + } /// /// Get all files for the current folder index @@ -394,7 +465,7 @@ public void GetData(CFFOLDER folder) /// Index of the folder in the cabinet /// True to ignore previous links, false otherwise /// Array of all files for the folder - private CFFILE[] GetFiles(int folderIndex, bool ignorePrev = false) + private CFFILE[] GetFilesOld(int folderIndex, bool ignorePrev = false) { // Ignore invalid archives if (Files == null) From 86fbfaa164b83bfce4163027053fa9cf7f041171 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Thu, 4 Dec 2025 10:57:36 -0500 Subject: [PATCH 06/11] more --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 2 +- .../Wrappers/MicrosoftCabinet.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index c7b74e95..3d22f28f 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -226,7 +226,7 @@ private bool ExtractFolder(string? filename, // Loop through the files bool allExtracted = true; - var files = GetFiles(filename, folderIndex, ignorePrev); + var files = GetSpannedFiles(filename, folderIndex, ignorePrev); for (int i = 0; i < files.Length; i++) { var file = files[i]; diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index f129d44b..fb18a4ec 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -318,7 +318,7 @@ private static CompressionType GetCompressionType(CFFOLDER folder) GetData(folder); // Get all files for the folder - var files = GetFiles(filename, folderIndex); + var files = GetFiles(folderIndex, skipPrev); if (files.Length == 0) return folder.DataBlocks; @@ -389,12 +389,12 @@ public void GetData(CFFOLDER folder) } /// - /// Get all files for the current folder index + /// Get all files for the current folder, plus connected spanned folders. /// /// Index of the folder in the cabinet /// True to ignore previous links, false otherwise /// Array of all files for the folder - private CFFILE[] GetFiles(string? filename, int folderIndex, bool ignorePrev = false, bool skipPrev = false, bool skipNext = false) + private CFFILE[] GetSpannedFiles(string? filename, int folderIndex, bool ignorePrev = false, bool skipPrev = false, bool skipNext = false) { // Ignore invalid archives if (Files == null) @@ -435,7 +435,7 @@ private CFFILE[] GetFiles(string? filename, int folderIndex, bool ignorePrev = f if (Prev?.Header != null && Prev.Folders != null) { int prevFolderIndex = Prev.FolderCount - 1; - prevFiles = Prev.GetFiles(filename, prevFolderIndex, skipNext: true) ?? []; + prevFiles = Prev.GetSpannedFiles(filename, prevFolderIndex, skipNext: true) ?? []; } } @@ -451,7 +451,7 @@ private CFFILE[] GetFiles(string? filename, int folderIndex, bool ignorePrev = f if (Next?.Header != null && Next.Folders != null) { var nextFolder = Next.Folders[0]; - nextFiles = Next.GetFiles(filename, 0, skipPrev: true) ?? []; + nextFiles = Next.GetSpannedFiles(filename, 0, skipPrev: true) ?? []; } } @@ -465,7 +465,7 @@ private CFFILE[] GetFiles(string? filename, int folderIndex, bool ignorePrev = f /// Index of the folder in the cabinet /// True to ignore previous links, false otherwise /// Array of all files for the folder - private CFFILE[] GetFilesOld(int folderIndex, bool ignorePrev = false) + private CFFILE[] GetFiles(int folderIndex, bool ignorePrev = false) { // Ignore invalid archives if (Files == null) From 37c7cf04772935cc654fe870b72476f7c6ec328b Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Thu, 4 Dec 2025 11:02:51 -0500 Subject: [PATCH 07/11] more work --- SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index fb18a4ec..14e85538 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -318,7 +318,7 @@ private static CompressionType GetCompressionType(CFFOLDER folder) GetData(folder); // Get all files for the folder - var files = GetFiles(folderIndex, skipPrev); + var files = GetFiles(folderIndex); if (files.Length == 0) return folder.DataBlocks; From 109c74677a36a7b3f346bf7e5a9027296446fab2 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Thu, 4 Dec 2025 11:25:52 -0500 Subject: [PATCH 08/11] No more per file seeking --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 3d22f28f..f561f696 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -227,14 +227,60 @@ private bool ExtractFolder(string? filename, // Loop through the files bool allExtracted = true; var files = GetSpannedFiles(filename, folderIndex, ignorePrev); + blockStream.SeekIfPossible(0, SeekOrigin.Begin); for (int i = 0; i < files.Length; i++) { var file = files[i]; - allExtracted &= ExtractFile(outputDirectory, blockStream, file, includeDebug); + if (file.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT || file.FolderIndex == FolderIndex.CONTINUED_FROM_PREV) + continue; + + allExtracted &= ExtractFiles(outputDirectory, blockStream, file, includeDebug); } return allExtracted; } + + // TODO: this will apparently improve memory usage/performance, but it's not clear if this implementation is enough for that to happen + /// + /// Extract the contents of a single file, intended to be used with all files in a straight shot + /// + /// Path to the output directory + /// Stream representing the uncompressed block data + /// File information + /// True to include debug data, false otherwise + /// True if the file extracted, false otherwise + private static bool ExtractFiles(string outputDirectory, Stream blockStream, CFFILE file, bool includeDebug) + { + try + { + byte[] fileData = blockStream.ReadBytes((int)file.FileSize); + + // Ensure directory separators are consistent + string filename = file.Name; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); + + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); + var directoryName = Path.GetDirectoryName(filename); + if (directoryName != null && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + + // Open the output file for writing + using var fs = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.None); + fs.Write(fileData, 0, fileData.Length); + fs.Flush(); + } + catch (Exception ex) + { + if (includeDebug) Console.Error.WriteLine(ex); + return false; + } + + return true; + } /// /// Extract the contents of a single file From 6613f82c69ef9002030dd0f7719c5445ab030fa1 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Thu, 4 Dec 2025 11:54:54 -0500 Subject: [PATCH 09/11] Finished work for now. --- .../Wrappers/MicrosoftCabinet.Extraction.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index f561f696..682ca3f1 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using SabreTools.Data.Models.MicrosoftCabinet; using SabreTools.IO.Extensions; @@ -189,6 +190,9 @@ public bool Extract(string outputDirectory, bool includeDebug) } cabinet = cabinet.Next; cabinet?.Prev = null; + + // TODO: already-extracted data isn't being cleared from memory, at least not nearly enough. + if (cabinet?.Folders == null || cabinet.Folders.Length == 0) break; } @@ -226,13 +230,29 @@ private bool ExtractFolder(string? filename, // Loop through the files bool allExtracted = true; - var files = GetSpannedFiles(filename, folderIndex, ignorePrev); + var filterFiles = GetSpannedFiles(filename, folderIndex, ignorePrev); + List fileList = []; + + // Filtering, add debug output eventually + for (int i = 0; i < filterFiles.Length; i++) + { + var file = filterFiles[i]; + + if (file.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT || + file.FolderIndex == FolderIndex.CONTINUED_FROM_PREV) + { + // debug output for inconsistencies would go here + continue; + } + + fileList.Add(file); + } + + CFFILE[] files = fileList.ToArray(); blockStream.SeekIfPossible(0, SeekOrigin.Begin); for (int i = 0; i < files.Length; i++) { var file = files[i]; - if (file.FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT || file.FolderIndex == FolderIndex.CONTINUED_FROM_PREV) - continue; allExtracted &= ExtractFiles(outputDirectory, blockStream, file, includeDebug); } From 4df3c8ecc69f6797849aeab1bcd0c2003b8cc468 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Mon, 5 Jan 2026 10:04:32 -0700 Subject: [PATCH 10/11] First round of fixes. --- .../Readers/MicrosoftCabinet.cs | 4 +-- .../Wrappers/MicrosoftCabinet.Extraction.cs | 10 +++--- .../Wrappers/MicrosoftCabinet.cs | 36 ++++++++++--------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs index c71f0962..25d2fdc2 100644 --- a/SabreTools.Serialization/Readers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Readers/MicrosoftCabinet.cs @@ -205,10 +205,10 @@ private static CFDATA ParseDataBlock(Stream data, byte dataReservedSize) dataBlock.UncompressedSize = data.ReadUInt16LittleEndian(); if (dataReservedSize > 0) - data.SeekIfPossible(data.Position + dataReservedSize, SeekOrigin.Begin); + data.SeekIfPossible(dataReservedSize, SeekOrigin.Current); if (dataBlock.CompressedSize > 0) - data.SeekIfPossible(data.Position + dataBlock.CompressedSize, SeekOrigin.Begin); + data.SeekIfPossible(dataBlock.CompressedSize, SeekOrigin.Current); return dataBlock; } diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 682ca3f1..8831b0d8 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -175,8 +175,8 @@ public bool Extract(string outputDirectory, bool includeDebug) // Loop through the current folders for (int f = 0; f < cabinet.Folders.Length; f++) { - if (f == 0 && (cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT || - cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_FROM_PREV)) + if (f == 0 && (cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_PREV_AND_NEXT + || cabinet.Files[0].FolderIndex == FolderIndex.CONTINUED_FROM_PREV)) continue; var folder = cabinet.Folders[f]; @@ -184,10 +184,8 @@ public bool Extract(string outputDirectory, bool includeDebug) } // Move to the next cabinet, if possible - foreach (var folder in cabinet.Folders) - { - folder.DataBlocks = []; - } + Array.ForEach(cabinet.Folders, folder => folder.DataBlocks = []); + cabinet = cabinet.Next; cabinet?.Prev = null; diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 14e85538..400aa510 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -363,29 +363,33 @@ private static CompressionType GetCompressionType(CFFOLDER folder) return [.. prevBlocks, .. folder.DataBlocks, .. nextBlocks]; } + /// + /// Loads in all the datablocks for the current folder. + /// + /// The folder to have the datablocks loaded for public void GetData(CFFOLDER folder) { - if (folder.CabStartOffset > 0) + if (folder.CabStartOffset <= 0) + return; + + uint offset = folder.CabStartOffset; + for (int i = 0; i < folder.DataCount; i++) { - uint offset = folder.CabStartOffset; + offset += 8; - for (int i = 0; i < folder.DataCount; i++) + if (Header.DataReservedSize > 0) { - offset += 8; - - if (Header.DataReservedSize > 0) - { - folder.DataBlocks[i].ReservedData = ReadRangeFromSource(offset, Header.DataReservedSize); - offset += Header.DataReservedSize; - } - - if (folder.DataBlocks[i].CompressedSize > 0) - { - folder.DataBlocks[i].CompressedData = ReadRangeFromSource(offset, folder.DataBlocks[i].CompressedSize); - offset += folder.DataBlocks[i].CompressedSize; - } + folder.DataBlocks[i].ReservedData = ReadRangeFromSource(offset, Header.DataReservedSize); + offset += Header.DataReservedSize; + } + + if (folder.DataBlocks[i].CompressedSize > 0) + { + folder.DataBlocks[i].CompressedData = ReadRangeFromSource(offset, folder.DataBlocks[i].CompressedSize); + offset += folder.DataBlocks[i].CompressedSize; } } + } /// From 46afbe0e6f1d3a1fb396c538d67041eac3296ecb Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Mon, 5 Jan 2026 10:39:43 -0700 Subject: [PATCH 11/11] Return if array is empty too --- SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 400aa510..78743500 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -2,6 +2,7 @@ using System.IO; using SabreTools.Data.Models.MicrosoftCabinet; using SabreTools.IO.Compression.MSZIP; +using SabreTools.IO.Extensions; namespace SabreTools.Serialization.Wrappers { @@ -401,7 +402,7 @@ public void GetData(CFFOLDER folder) private CFFILE[] GetSpannedFiles(string? filename, int folderIndex, bool ignorePrev = false, bool skipPrev = false, bool skipNext = false) { // Ignore invalid archives - if (Files == null) + if (Files.IsNullOrEmpty()) return []; // Get all files with a name and matching index