using System; using System.IO; using SabreTools.Data.Models.WiseInstaller.Actions; using SabreTools.IO; using SabreTools.IO.Compression.Deflate; using SabreTools.IO.Extensions; namespace SabreTools.Wrappers { public partial class WiseOverlayHeader { /// /// Extract the predefined, static files defined in the header /// /// Output directory to write to /// True to include debug data, false otherwise /// True if the files extracted successfully, false otherwise /// On success, this sets public bool ExtractHeaderDefinedFiles(string outputDirectory, bool includeDebug) { lock (_dataSourceLock) { // Seek to the compressed data offset _dataSource.SeekIfPossible(CompressedDataOffset, SeekOrigin.Begin); if (includeDebug) Console.WriteLine($"Beginning of header-defined files: {CompressedDataOffset}"); // Extract WiseColors.dib, if it exists var expected = new DeflateInfo { InputSize = DibDeflatedSize, OutputSize = DibInflatedSize, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, "WiseColors.dib", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract WiseScript.bin expected = new DeflateInfo { InputSize = WiseScriptDeflatedSize, OutputSize = WiseScriptInflatedSize, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, "WiseScript.bin", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract WISE0001.DLL, if it exists expected = new DeflateInfo { InputSize = WiseDllDeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "WISE0001.DLL", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract CTL3D32.DLL, if it exists expected = new DeflateInfo { InputSize = Ctl3d32DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "CTL3D32.DLL", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE0004, if it exists expected = new DeflateInfo { InputSize = SomeData4DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE0004", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract Ocxreg32.EXE, if it exists expected = new DeflateInfo { InputSize = RegToolDeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "Ocxreg32.EXE", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract PROGRESS.DLL, if it exists expected = new DeflateInfo { InputSize = ProgressDllDeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "PROGRESS.DLL", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE0007, if it exists expected = new DeflateInfo { InputSize = SomeData7DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE0007", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE0008, if it exists expected = new DeflateInfo { InputSize = SomeData8DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE0008", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE0009, if it exists expected = new DeflateInfo { InputSize = SomeData9DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE0009", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE000A, if it exists expected = new DeflateInfo { InputSize = SomeData10DeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE000A", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract install script, if it exists expected = new DeflateInfo { InputSize = InstallScriptDeflatedSize, OutputSize = -1, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "INSTALL_SCRIPT", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; // Extract FILE000{n}.DAT, if it exists expected = new DeflateInfo { InputSize = FinalFileDeflatedSize, OutputSize = FinalFileInflatedSize, Crc32 = 0 }; if (InflateWrapper.ExtractFile(_dataSource, IsPKZIP ? null : "FILE00XX.DAT", outputDirectory, expected, IsPKZIP, includeDebug) == ExtractionStatus.FAIL) return false; InstallerDataOffset = _dataSource.Position; } return true; } /// /// Attempt to extract a file defined by a file header /// /// Deflate information /// File index for automatic naming /// Output directory to write to /// True to include debug data, false otherwise /// True if the file extracted successfully, false otherwise /// Requires to be set public ExtractionStatus ExtractFile(InstallFile obj, int index, string outputDirectory, bool includeDebug) { // Get expected values var expected = new DeflateInfo { InputSize = obj.DeflateEnd - obj.DeflateStart, OutputSize = obj.InflatedSize, Crc32 = obj.Crc32, }; // Perform path replacements string filename = obj.DestinationPathname ?? $"WISE{index:X4}"; filename = filename.Replace("%", string.Empty); lock (_dataSourceLock) { _dataSource.SeekIfPossible(InstallerDataOffset + obj.DeflateStart, SeekOrigin.Begin); return InflateWrapper.ExtractFile(_dataSource, filename, outputDirectory, expected, IsPKZIP, includeDebug); } } /// /// Attempt to extract a file defined by a file header /// /// Deflate information /// Output directory to write to /// True to include debug data, false otherwise /// True if the file extracted successfully, false otherwise /// Requires to be set public ExtractionStatus ExtractFile(DisplayBillboard obj, string outputDirectory, bool includeDebug) { // Get the generated base name string baseName = $"CustomBillboardSet_{obj.Flags:X4}-{obj.Operand_2}-{obj.Operand_3}"; // If there are no deflate objects if (obj.DeflateInfo is null) { if (includeDebug) Console.WriteLine($"Skipping {baseName} because the deflate object array is null!"); return ExtractionStatus.FAIL; } // Loop through the values for (int i = 0; i < obj.DeflateInfo.Length; i++) { // Get the deflate info object var info = obj.DeflateInfo[i]; // Get expected values var expected = new DeflateInfo { InputSize = info.DeflateEnd - info.DeflateStart, OutputSize = info.InflatedSize, Crc32 = 0, }; // Perform path replacements string filename = $"{baseName}{i:X4}"; lock (_dataSourceLock) { _dataSource.SeekIfPossible(InstallerDataOffset + info.DeflateStart, SeekOrigin.Begin); _ = InflateWrapper.ExtractFile(_dataSource, filename, outputDirectory, expected, IsPKZIP, includeDebug); } } // Always return good -- TODO: Fix this return ExtractionStatus.GOOD; } /// /// Attempt to extract a file defined by a file header /// /// Deflate information /// Output directory to write to /// True to include debug data, false otherwise /// True if the file extracted successfully, false otherwise /// Requires to be set public ExtractionStatus ExtractFile(CustomDialogSet obj, string outputDirectory, bool includeDebug) { // Get expected values var expected = new DeflateInfo { InputSize = obj.DeflateEnd - obj.DeflateStart, OutputSize = obj.InflatedSize, Crc32 = 0, }; // Perform path replacements string filename = $"CustomDialogSet_{obj.DisplayVariable}-{obj.Name}"; filename = filename.Replace("%", string.Empty); lock (_dataSourceLock) { _dataSource.SeekIfPossible(InstallerDataOffset + obj.DeflateStart, SeekOrigin.Begin); return InflateWrapper.ExtractFile(_dataSource, filename, outputDirectory, expected, IsPKZIP, includeDebug); } } /// /// Open a potential WISE installer file and any additional files /// /// Input filename or base name to read from /// True to include debug data, false otherwise /// True if the file could be opened, false otherwise public static bool OpenFile(string filename, bool includeDebug, out ReadOnlyCompositeStream? stream) { // If the file exists as-is if (File.Exists(filename)) { var fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream = new ReadOnlyCompositeStream([fileStream]); // Debug statement if (includeDebug) Console.WriteLine($"File {filename} was found and opened"); // Strip the extension and rebuild string? directory = Path.GetDirectoryName(filename); filename = Path.GetFileNameWithoutExtension(filename); if (directory is not null) filename = Path.Combine(directory, filename); } // If the base name was provided, try to open the associated exe else if (File.Exists($"{filename}.EXE")) { var fileStream = File.Open($"{filename}.EXE", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream = new ReadOnlyCompositeStream([fileStream]); // Debug statement if (includeDebug) Console.WriteLine($"File {filename}.EXE was found and opened"); } else if (File.Exists($"{filename}.exe")) { var fileStream = File.Open($"{filename}.exe", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream = new ReadOnlyCompositeStream([fileStream]); // Debug statement if (includeDebug) Console.WriteLine($"File {filename}.exe was found and opened"); } // Otherwise, the file cannot be opened else { stream = null; return false; } // Get the pattern for file naming string filePattern = string.Empty; bool longDigits = false; byte fileno = 0; bool foundStart = false; for (; fileno < 3; fileno++) { if (File.Exists($"{filename}.W0{fileno}")) { foundStart = true; filePattern = $"{filename}.W"; longDigits = false; break; } else if (File.Exists($"{filename}.w0{fileno}")) { foundStart = true; filePattern = $"{filename}.w"; longDigits = false; break; } else if (File.Exists($"{filename}.00{fileno}")) { foundStart = true; filePattern = $"{filename}."; longDigits = true; break; } } // If no starting part has been found if (!foundStart) return true; // Loop through and try to read all additional files for (; ; fileno++) { string nextPart = longDigits ? $"{filePattern}{fileno:D3}" : $"{filePattern}{fileno:D2}"; if (!File.Exists(nextPart)) { if (includeDebug) Console.WriteLine($"Part {nextPart} was not found"); break; } // Debug statement if (includeDebug) Console.WriteLine($"Part {nextPart} was found and appended"); var fileStream = File.Open(nextPart, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream.AddStream(fileStream); } return true; } } }