private (RawDirectoryEntry, IEnumerable <StreamRange>) GetHashableRanges( PEHeaders headers ) { var snDir = headers.CorHeader.StrongNameSignatureDirectory; RawDirectoryEntry rawSNDir; return(snDir.Size > 0 && headers.TryGetDirectoryOffset(snDir, out var snOffset) ? (rawSNDir = new RawDirectoryEntry(snOffset, snDir.Size), this.CalculateRangesWithValidSNDir(headers, rawSNDir)) :
public static void Write(Stream output, RawDirectoryEntry instance, Endian endian) { output.WriteValueS32(instance.DirectoryCount, endian); output.WriteValueS32(instance.DirectoryIndex, endian); output.WriteValueS32(instance.FileCount, endian); output.WriteValueS32(instance.FileIndex, endian); output.WriteValueU32(instance.Unknown10, endian); output.WriteValueU32(instance.Unknown14, endian); output.WriteValueU32(instance.Unknown18, endian); output.WriteValueU32(instance.Unknown1C, endian); }
public void Deserialize(Stream input) { var basePosition = input.Position; var magic = input.ReadValueU32(Endian.Big); if (magic != Signature) { throw new FormatException("bad header magic"); } var version = input.ReadValueU8(); if (version != 2) { throw new FormatException("bad header version"); } var endianness = input.ReadValueU8(); if (endianness != 0 && endianness != 1) { throw new FormatException("bad header endianness"); } var endian = endianness == 0 ? Endian.Little : Endian.Big; var headerSizeHi = input.ReadValueU8(); var unknown07 = input.ReadValueU8(); if (unknown07 != 0) { throw new FormatException("bad header unknown07"); } var unknown08 = input.ReadValueU32(endian); if (unknown08 != 0x00020001u) { throw new FormatException("bad header unknown08"); } var headerSizeLo = input.ReadValueU32(endian); var directoryCount = input.ReadValueU32(endian); var directoryTableOffset = input.ReadValueU32(endian); var fileCount = input.ReadValueU32(endian); var fileTableOffset = input.ReadValueU32(endian); var actualHeaderSize = 32L; actualHeaderSize += 64 * (directoryCount + fileCount); actualHeaderSize += 32 * directoryCount; actualHeaderSize += 32 * fileCount; var headerSize = (headerSizeHi << 32) | headerSizeLo; if (headerSize != 0) { if (headerSize != actualHeaderSize.Align(Alignment)) { throw new FormatException("bad header size"); } } if (input.Length < basePosition + actualHeaderSize) { throw new EndOfStreamException("stream too small for all header data"); } var directoryNames = new string[directoryCount]; for (uint i = 0; i < directoryCount; i++) { directoryNames[i] = input.ReadString(64, true, _Encoding); } var fileNames = new string[fileCount]; for (uint i = 0; i < fileCount; i++) { fileNames[i] = input.ReadString(64, true, _Encoding); } var rawDirectoryEntries = new RawDirectoryEntry[directoryCount]; if (directoryCount > 0) { input.Position = basePosition + directoryTableOffset; for (uint i = 0; i < directoryCount; i++) { var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(input, endian); if (directoryEntry.Unknown14 != 0) { throw new FormatException("bad directory unknown14"); } if (directoryEntry.Unknown18 != 0) { throw new FormatException("bad directory unknown18"); } if (directoryEntry.Unknown1C != 0) { throw new FormatException("bad directory unknown1C"); } } } var rawFileEntries = new RawFileEntry[fileCount]; if (fileCount > 0) { input.Position = basePosition + fileTableOffset; for (uint i = 0; i < fileCount; i++) { var fileEntry = rawFileEntries[i] = RawFileEntry.Read(input, endian); if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0) { throw new FormatException("bad file compression flags"); } if (fileEntry.Unknown14 != 0) { throw new FormatException("bad file unknown14"); } if (fileEntry.Unknown18 != 0) { throw new FormatException("bad file unknown18"); } } } var fileEntries = new List <FileEntry>(); if (directoryCount > 0) { var queue = new Queue <KeyValuePair <int, string> >(); queue.Enqueue(new KeyValuePair <int, string>(0, null)); while (queue.Count > 0) { var directoryInfo = queue.Dequeue(); var directoryIndex = directoryInfo.Key; var rawDirectoryEntry = rawDirectoryEntries[directoryIndex]; var directoryName = directoryNames[directoryIndex]; var isRootDirectory = directoryIndex == 0 && directoryName == "."; var directoryBasePath = directoryInfo.Value; var directoryPath = directoryBasePath == null ? isRootDirectory == true ? null : directoryName : isRootDirectory == true ? directoryBasePath : Path.Combine(directoryBasePath, directoryName); for (int i = 0, o = rawDirectoryEntry.DirectoryIndex; i < rawDirectoryEntry.DirectoryCount; i++, o++) { queue.Enqueue(new KeyValuePair <int, string>(o, directoryPath)); } for (int i = 0, o = rawDirectoryEntry.FileIndex; i < rawDirectoryEntry.FileCount; i++, o++) { var rawFileEntry = rawFileEntries[o]; FileEntry fileEntry; fileEntry.Path = directoryPath == null ? fileNames[o] : Path.Combine(directoryPath, fileNames[o]); fileEntry.IsCompressed = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) != 0; fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize; fileEntry.DataCompressedSize = rawFileEntry.DataCompressedSize; fileEntry.DataOffset = (long)(rawFileEntry.DataOffsetLo) << 0 | (long)(rawFileEntry.DataOffsetHi) << 32; fileEntries.Add(fileEntry); } } } else { // no directories but there's a file? if (fileCount > 0) { throw new FormatException("bad directory count"); } } this._Endian = endian; this._Entries.Clear(); this._Entries.AddRange(fileEntries); }
private void ReadHeader() { _stream.Seek(0, SeekOrigin.Begin); var magic = _reader.ReadUInt32(); if (magic != Signature) { throw new FormatException("Bad header magic"); } var version = _reader.ReadByte(); if (version != 2) { throw new FormatException("Unsupported version"); } var endianness = _reader.ReadByte(); _reader.Endianness = endianness == 0 ? Endianness.Little : Endianness.Big; var headerSizeHi = _reader.ReadByte(); var unknown07 = _reader.ReadByte(); // 0 var unknown08 = _reader.ReadUInt32(); // 0x00020001u var headerSizeLo = _reader.ReadUInt32(); var directoryCount = _reader.ReadUInt32(); var directoryTableOffset = _reader.ReadUInt32(); var fileCount = _reader.ReadUInt32(); var fileTableOffset = _reader.ReadUInt32(); var actualHeaderSize = 32L; actualHeaderSize += 64 * (directoryCount + fileCount); actualHeaderSize += 32 * directoryCount; actualHeaderSize += 32 * fileCount; var headerSize = (headerSizeHi << 32) | headerSizeLo; var directoryNames = new string[directoryCount]; for (uint i = 0; i < directoryCount; i++) { directoryNames[i] = _reader.ReadString(64, _Encoding); } var fileNames = new string[fileCount]; for (uint i = 0; i < fileCount; i++) { fileNames[i] = _reader.ReadString(64, _Encoding); } var rawDirectoryEntries = new RawDirectoryEntry[directoryCount]; if (directoryCount > 0) { _stream.Position = directoryTableOffset; for (uint i = 0; i < directoryCount; i++) { var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(_reader); if (directoryEntry.Unknown14 != 0) { throw new FormatException("bad directory unknown14"); } if (directoryEntry.Unknown18 != 0) { throw new FormatException("bad directory unknown18"); } if (directoryEntry.Unknown1C != 0) { throw new FormatException("bad directory unknown1C"); } } } var rawFileEntries = new RawFileEntry[fileCount]; if (fileCount > 0) { _stream.Position = fileTableOffset; for (uint i = 0; i < fileCount; i++) { var fileEntry = rawFileEntries[i] = RawFileEntry.Read(_reader); if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0) { throw new FormatException("bad file compression flags"); } if (fileEntry.Unknown14 != 0) { throw new FormatException("bad file unknown14"); } if (fileEntry.Unknown18 != 0) { throw new FormatException("bad file unknown18"); } } } Queue <(int Index, string BasePath)> queue = new Queue <(int Index, string BasePath)>(); queue.Enqueue((0, null)); while (queue.Count > 0) { var(index, basePath) = queue.Dequeue(); var rawDirectory = rawDirectoryEntries[index]; var directoryName = directoryNames[index]; var isRootDirectory = index == 0 && directoryName == "."; var directoryPath = basePath == null ? isRootDirectory ? null : directoryName : isRootDirectory ? basePath : Path.Combine(basePath, directoryName); for (int i = 0; i < rawDirectory.DirectoryCount; i++) { queue.Enqueue((i + rawDirectory.DirectoryOffset, directoryPath)); } for (int i = 0; i < rawDirectory.FileCount; i++) { var fileIndex = i + rawDirectory.FileOffset; var rawFileEntry = rawFileEntries[fileIndex]; FileEntry fileEntry; fileEntry.Path = directoryPath == null ? fileNames[fileIndex] : Path.Combine(directoryPath, fileNames[fileIndex]); fileEntry.IsCompressed = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) != 0; fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize; fileEntry.DataCompressedSize = rawFileEntry.DataCompressedSize; fileEntry.DataOffset = (long)(rawFileEntry.DataOffsetLo) << 0 | (long)(rawFileEntry.DataOffsetHi) << 32; fileEntry.Unknown10 = rawFileEntry.HeaderSize; fileEntry.Unknown14 = rawFileEntry.Unknown14; fileEntry.Unknown18 = rawFileEntry.Unknown18; fileEntry.Unknown1C = rawFileEntry.Unknown1C; _entries.Add(fileEntry); } } // _entries = _entries.OrderBy(e => e.DataOffset).ToList(); // int counter = 0; // for (int i = 1; i < _entries.Count; i++) // { // var prev = _entries[i - 1]; // var file = _entries[i]; // // // Console.WriteLine($"[{file.DataOffset % Alignment}] {file.DataOffset - (prev.DataOffset + (prev.IsCompressed ? prev.DataCompressedSize : prev.DataUncompressedSize))}"); // if (file.DataOffset % Alignment != 0) // { // // var sameBlock = (file.DataOffset / Alignment) == ((prev.DataOffset + prev.Size) / Alignment); // // counter++; // // Console.WriteLine(sameBlock); // } // else // { // var sameBlock = (file.DataOffset / Alignment) == ((prev.DataOffset + prev.Size) / Alignment); // counter++; // Console.WriteLine(sameBlock); // } // } // Console.WriteLine("Total: " + counter); }
public void Deserialize(Stream input) { var basePosition = input.Position; var magic = input.ReadValueU32(Endian.Big); if (magic != Signature) { throw new FormatException(); } var version = input.ReadValueU8(); if (version != 2) { throw new FormatException(); } var endianness = input.ReadValueU8(); if (endianness != 0 && endianness != 1) { throw new FormatException(); } var endian = endianness == 0 ? Endian.Little : Endian.Big; var unknown06 = input.ReadValueU8(); var unknown07 = input.ReadValueU8(); if (unknown06 != 0 || unknown07 != 0) { throw new FormatException(); } var unknown08 = input.ReadValueU32(endian); if (unknown08 != 0x00020001u) { throw new FormatException(); } var unknown0C = input.ReadValueU32(endian); if (unknown0C != 0) { throw new FormatException(); } var directoryCount = input.ReadValueU32(endian); var directoryTableOffset = input.ReadValueU32(endian); var fileCount = input.ReadValueU32(endian); var fileTableOffset = input.ReadValueU32(endian); var directoryNames = new string[directoryCount]; for (uint i = 0; i < directoryCount; i++) { directoryNames[i] = input.ReadString(64, true, Encoding.ASCII); } var fileNames = new string[fileCount]; for (uint i = 0; i < fileCount; i++) { fileNames[i] = input.ReadString(64, true, Encoding.ASCII); } var rawDirectoryEntries = new RawDirectoryEntry[directoryCount]; if (directoryCount > 0) { input.Position = basePosition + directoryTableOffset; for (uint i = 0; i < directoryCount; i++) { var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(input, endian); if (directoryEntry.Unknown14 != 0 || directoryEntry.Unknown18 != 0 || directoryEntry.Unknown1C != 0) { throw new FormatException(); } } } var rawFileEntries = new RawFileEntry[fileCount]; if (fileCount > 0) { input.Position = basePosition + fileTableOffset; for (uint i = 0; i < fileCount; i++) { var fileEntry = rawFileEntries[i] = RawFileEntry.Read(input, endian); if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0) { throw new FormatException(); } if (fileEntry.Unknown14 != 0 || fileEntry.Unknown18 != 0) { throw new FormatException(); } } } var fileEntries = new List<FileEntry>(); if (directoryCount > 0) { var queue = new Queue<KeyValuePair<int, string>>(); queue.Enqueue(new KeyValuePair<int, string>(0, null)); while (queue.Count > 0) { var directoryInfo = queue.Dequeue(); var directoryIndex = directoryInfo.Key; var rawDirectoryEntry = rawDirectoryEntries[directoryIndex]; var directoryName = directoryNames[directoryIndex]; var isRootDirectory = directoryIndex == 0 && directoryName == "."; var directoryBasePath = directoryInfo.Value; var directoryPath = directoryBasePath == null ? isRootDirectory == true ? null : directoryName : isRootDirectory == true ? directoryBasePath : Path.Combine(directoryBasePath, directoryName); for (int i = 0, o = rawDirectoryEntry.DirectoryIndex; i < rawDirectoryEntry.DirectoryCount; i++, o++) { queue.Enqueue(new KeyValuePair<int, string>(o, directoryPath)); } for (int i = 0, o = rawDirectoryEntry.FileIndex; i < rawDirectoryEntry.FileCount; i++, o++) { var rawFileEntry = rawFileEntries[o]; FileEntry fileEntry; fileEntry.Path = directoryPath == null ? fileNames[o] : Path.Combine(directoryPath, fileNames[o]); fileEntry.IsCompressed = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) != 0; fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize; fileEntry.DataCompressedSize = rawFileEntry.DataCompressedSize; fileEntry.DataOffset = (long)(rawFileEntry.DataOffsetLo) << 0 | (long)(rawFileEntry.DataOffsetHi) << 32; fileEntries.Add(fileEntry); } } } else { // no directories but there's a file? if (fileCount > 0) { throw new FormatException(); } } this._Endian = endian; this._Entries.Clear(); this._Entries.AddRange(fileEntries); }