diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/FileSystem/Associations/InstallShield/PKG.uexml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/FileSystem/Associations/InstallShield/PKG.uexml new file mode 100644 index 00000000..cadfd5f0 --- /dev/null +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/FileSystem/Associations/InstallShield/PKG.uexml @@ -0,0 +1,25 @@ + + + + + + + + *.pkg + + + + 4AA3 + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj index ac851523..1d5f2313 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj @@ -658,6 +658,7 @@ + diff --git a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/CABDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/CABDataFormat.cs index 2d791e87..e93df9cc 100644 --- a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/CABDataFormat.cs +++ b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/CABDataFormat.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using UniversalEditor.Accessors; using UniversalEditor.IO; using UniversalEditor.ObjectModels.FileSystem; @@ -37,13 +38,25 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.Cabinet FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); if (fsom == null) return; - Reader br = base.Accessor.Reader; + Reader br = Accessor.Reader; br.Accessor.Seek(0, SeekOrigin.Begin); br.Endianness = Endianness.LittleEndian; string ISc_ = br.ReadFixedLengthString(4); if (ISc_ != "ISc(") throw new InvalidDataFormatException(); + + string hdrfilename = System.IO.Path.ChangeExtension(Accessor.GetFileName(), ".hdr"); + if (System.IO.File.Exists(hdrfilename)) + { + FileAccessor fa = new FileAccessor(hdrfilename, false, false, true); + + HDRDataFormat hdr = new HDRDataFormat(); + hdr.IgnoreCabinet = true; // set this because WE are the cabinet + + Document.Load(fsom, hdr, fa); + } + uint version = br.ReadUInt32(); int majorVersion = 0; if (version >> 24 == 1) @@ -79,9 +92,10 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.Cabinet uint unknown6 = br.ReadUInt32(); uint fileCount = br.ReadUInt32(); uint fileTableOffset2 = br.ReadUInt32(); + return; - if (br.Accessor.Position != 0x30) throw new InvalidDataFormatException(); - if (fileTableSize != fileTableSize2) throw new InvalidDataFormatException("File table sizes do not match"); + // if (br.Accessor.Position != 0x30) throw new InvalidDataFormatException(); + // if (fileTableSize != fileTableSize2) throw new InvalidDataFormatException("File table sizes do not match"); uint unknown7 = br.ReadUInt32(); uint unknown8 = br.ReadUInt32(); @@ -98,9 +112,6 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.Cabinet { componentOffsets[i] = br.ReadUInt32(); } - - - } protected override void SaveInternal(ObjectModel objectModel) diff --git a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/HDRDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/HDRDataFormat.cs index f91045d9..129a4313 100644 --- a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/HDRDataFormat.cs +++ b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/Cabinet/HDRDataFormat.cs @@ -2,29 +2,236 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using UniversalEditor.Compression; +using UniversalEditor.IO; using UniversalEditor.ObjectModels.FileSystem; namespace UniversalEditor.DataFormats.FileSystem.InstallShield.Cabinet { - public class HDRDataFormat : DataFormat - { - private static DataFormatReference _dfr = null; - protected override DataFormatReference MakeReferenceInternal() - { - if (_dfr == null) - { - _dfr = base.MakeReferenceInternal(); - _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All); - } - return _dfr; - } + public class HDRDataFormat : DataFormat + { + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = base.MakeReferenceInternal(); + _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All); + } + return _dfr; + } - protected override void LoadInternal(ref ObjectModel objectModel) - { - } + private System.IO.FileStream cabfile = null; + /// + /// Gets or sets a value indicating whether this + /// should skip + /// attempting to load the respective cabinet. This should be set to FALSE when using this DataFormat interactively + /// so that the associated can retrieve data appropriately, but it should be + /// set to TRUE when using this DataFormat in conjunction with the , since that handles + /// data retrieval itself. + /// + /// true if the associated cabinet file should be ignored; otherwise, false. + public bool IgnoreCabinet { get; set; } = false; - protected override void SaveInternal(ObjectModel objectModel) - { - } - } + protected override void LoadInternal(ref ObjectModel objectModel) + { + FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); + if (fsom == null) + throw new ObjectModelNotSupportedException(); + + Reader reader = Accessor.Reader; + + // ZLibX compression (see aluigi's code from quickbms) + if (!IgnoreCabinet) + { + string cabfilename = System.IO.Path.ChangeExtension(Accessor.GetFileName(), ".cab"); + if (System.IO.File.Exists(cabfilename)) + { + cabfile = System.IO.File.Open(cabfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); + } + } + + string signature = reader.ReadFixedLengthString(4); + if (signature != "ISc(") + throw new InvalidDataFormatException("invalid CAB or HDR file - does not begin with 'ISc('"); + + uint unknown1 = reader.ReadUInt32(); + if (unknown1 != 16798209) + { + Console.WriteLine("ue: ISc: warning: magic value does not equal 16798209; this has not been tested"); + } + + uint unknown2 = reader.ReadUInt32(); + uint stringDirectoryOffset = reader.ReadUInt32(); + uint stringDirectoryLength = reader.ReadUInt32(); + if (stringDirectoryLength == 0) + { + // proooooobably not a HDR, maybe a CAB? + throw new InvalidDataFormatException(); + } + + uint totalFileLength = reader.ReadUInt32(); + + // rest is padding to offset 512 + // STRINGS DIRECTORY + reader.Seek(stringDirectoryOffset, SeekOrigin.Begin); + uint enStrTblOffset = reader.ReadUInt32(); + uint unknownB1 = reader.ReadUInt32(); + uint unknownB2 = reader.ReadUInt32(); + uint strTblLength = reader.ReadUInt32(); + uint unknownB3 = reader.ReadUInt32(); + uint unknownB4 = reader.ReadUInt32(); // 4 - Unknown(337) + uint unknownB4_2 = reader.ReadUInt32(); // 4 - Unknown(337) + uint folderCount = reader.ReadUInt32(); + uint unknownB6 = reader.ReadUInt32(); + uint unknownB7 = reader.ReadUInt32(); + uint fileCount = reader.ReadUInt32(); + uint unknownB9 = reader.ReadUInt32(); + uint unknownB10 = reader.ReadUInt32(); + uint unknownB11 = reader.ReadUInt32(); + + // X - Unknown Stuff + reader.Seek(stringDirectoryOffset + strTblLength, SeekOrigin.Begin); + + string[] folderNames = new string[folderCount]; + for (uint i = 0; i < folderCount; i++) + { + uint folderNameOffset = reader.ReadUInt32(); + reader.Accessor.SavePosition(); + reader.Seek(stringDirectoryOffset + strTblLength + folderNameOffset, SeekOrigin.Begin); + string folderName = ReadName(reader, unknown1); + reader.Accessor.LoadPosition(); + folderNames[i] = folderName; + } + + ushort uver = reader.ReadUInt16(); + reader.Seek(-2, SeekOrigin.Current); + + if (uver <= 0x10) + { + long CHUNK_SIZE = 0x8000; + for (uint i = 0; i < fileCount; i++) + { + short type = reader.ReadInt16(); + ulong decompressedLength = reader.ReadUInt64(); + ulong compressedLength = reader.ReadUInt64(); + ulong offset = reader.ReadUInt64(); + + string hash = reader.ReadFixedLengthString(16); + ushort dummy1 = reader.ReadUInt16(); // 0 or 1 + ushort dummy2 = reader.ReadUInt16(); // 0 or 0xa + ushort dummy3 = reader.ReadUInt16(); // 0 or 0xee + ushort dummy4 = reader.ReadUInt16(); // 0 + ulong zero = reader.ReadUInt64(); + uint nameOffset = reader.ReadUInt32(); + ushort folderIndex = reader.ReadUInt16(); + uint flags = reader.ReadUInt32(); + uint dummy5 = reader.ReadUInt32(); + uint dataID = reader.ReadUInt32(); // duplicate but sometimes it's zero when a cab is not available + + string dummy = reader.ReadFixedLengthString(9); + ushort dataID2 = reader.ReadUInt16();// yeah it's the same as before + + reader.Accessor.SavePosition(); + reader.Seek(stringDirectoryOffset + strTblLength + nameOffset, SeekOrigin.Begin); + string fileName = ReadName(reader, unknown1); + reader.Accessor.LoadPosition(); + + File file = fsom.AddFile(fileName); + file.Properties.Add("offset", offset); + file.Properties.Add("compressedLength", compressedLength); + file.Properties.Add("decompressedLength", decompressedLength); + } + } + else + { + ulong CHUNK_SIZE = 0x10000; + + for (uint i = 0; i < fileCount; i++) + { + uint offset = reader.ReadUInt32(); + reader.Accessor.SavePosition(); + reader.Accessor.Seek(stringDirectoryOffset + strTblLength + offset, SeekOrigin.Begin); + uint nameOffset = reader.ReadUInt32(); + uint folderIndex = reader.ReadUInt32(); + ushort type = reader.ReadUInt16(); + uint decompressedLength = reader.ReadUInt32(); + uint compressedLength = reader.ReadUInt32(); + uint dummy1 = reader.ReadUInt32(); + uint dummy2 = reader.ReadUInt32(); + uint dummy3 = reader.ReadUInt32(); + ushort dummy4 = reader.ReadUInt16(); + uint dummy5 = reader.ReadUInt32(); + ushort dummy6 = reader.ReadUInt16(); + uint offset2 = reader.ReadUInt32(); + ulong dummt7 = reader.ReadUInt64(); + ulong dummy8 = reader.ReadUInt64(); + uint data_id = 1; + + reader.Seek(stringDirectoryOffset + strTblLength + nameOffset, SeekOrigin.Begin); + string fileName = ReadName(reader, unknown1); + + reader.Accessor.LoadPosition(); + + if (folderIndex > 0) + { + fileName = folderNames[folderIndex] + '/' + fileName; + } + + File file = fsom.AddFile(fileName); + file.Properties.Add("offset", offset); + file.Properties.Add("compressedLength", compressedLength); + file.Properties.Add("decompressedLength", decompressedLength); + file.Size = decompressedLength; + file.DataRequest += File_DataRequest; ; + } + } + } + + private void File_DataRequest(object sender, DataRequestEventArgs e) + { + if (cabfile == null) + return; + + File file = (sender as File); + uint offset = (uint)file.Properties["offset"]; + uint compressedLength = (uint)file.Properties["compressedLength"]; + uint decompressedLength = (uint)file.Properties["decompressedLength"]; + + byte[] compressedData = new byte[compressedLength]; + cabfile.Seek(offset, System.IO.SeekOrigin.Begin); + cabfile.Read(compressedData, 0, compressedData.Length); + + CompressionModule deflatex = CompressionModule.FromKnownCompressionMethod(Compression.CompressionMethod.Deflate); + byte[] decompressedData = deflatex.Decompress(compressedData, (int)decompressedLength); + + e.Data = decompressedData; + } + + + private string ReadName(Reader reader, uint flags) + { + string folderName = null; + if ((flags & 0x04000000) == 0x04000000) + { + folderName = reader.ReadNullTerminatedString(IO.Encoding.UTF16LittleEndian); + } + else + { + folderName = reader.ReadNullTerminatedString(); + } + return folderName; + } + + protected override void SaveInternal(ObjectModel objectModel) + { + FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); + if (fsom == null) + throw new ObjectModelNotSupportedException(); + + Writer writer = Accessor.Writer; + writer.WriteFixedLengthString("ISc("); + writer.WriteUInt32(16798209); + } + } } diff --git a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/PKG/PKGDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/PKG/PKGDataFormat.cs index db874a6b..31a9af72 100644 --- a/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/PKG/PKGDataFormat.cs +++ b/CSharp/Plugins/UniversalEditor.Plugins.InstallShield/DataFormats/FileSystem/InstallShield/PKG/PKGDataFormat.cs @@ -33,7 +33,7 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.PKG FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); if (fsom == null) return; - Reader br = base.Accessor.Reader; + Reader br = Accessor.Reader; ushort signature = br.ReadUInt16(); if (signature != 0xA34A) throw new InvalidDataFormatException("File does not begin with 0xA34A"); @@ -41,28 +41,29 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.PKG ushort unknown1b = br.ReadUInt16(); uint unknown2 = br.ReadUInt32(); uint unknown3 = br.ReadUInt32(); + /* uint unknown4 = br.ReadUInt32(); ushort unknown5 = br.ReadUInt16(); ushort unknown6 = br.ReadUInt16(); ushort unknown7 = br.ReadUInt16(); + */ ushort fileCount = br.ReadUInt16(); for (ushort i = 0; i < fileCount; i++) { - string FileName = br.ReadLengthPrefixedString(); + ushort FileNameLength = br.ReadUInt16(); + string FileName = br.ReadFixedLengthString(FileNameLength); + /* byte unknown8 = br.ReadByte(); uint unknown9 = br.ReadUInt32(); ushort unknown10 = br.ReadUInt16(); - - File file = new File(); - file.Name = FileName; - file.Size = unknown10; + */ + ushort unknown8 = br.ReadUInt16(); + ushort maybeLength = br.ReadUInt16(); + ushort unknown9 = br.ReadUInt16(); + + File file = fsom.AddFile(FileName); + file.Size = maybeLength; file.DataRequest += new DataRequestEventHandler(file_DataRequest); - fsom.Files.Add(file); - - if (file.Name == "OP.Z") - { - - } } } @@ -72,7 +73,26 @@ namespace UniversalEditor.DataFormats.FileSystem.InstallShield.PKG protected override void SaveInternal(ObjectModel objectModel) { - throw new NotImplementedException(); + FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); + if (fsom == null) return; + + Writer bw = Accessor.Writer; + bw.WriteUInt16(0xA34A); + bw.WriteUInt32(10); + bw.WriteUInt32(2); + bw.WriteUInt32(65536); + + File[] files = fsom.GetAllFiles(); + bw.WriteUInt16((ushort)files.Length); + for (ushort i = 0; i < (ushort)files.Length; i++) + { + bw.WriteUInt16((ushort)files[i].Name.Length); + bw.WriteFixedLengthString(files[i].Name, (ushort)files[i].Name.Length); + + bw.WriteUInt16(2); + bw.WriteUInt16((ushort)files[i].Size); + bw.WriteUInt16(8); + } } } }