string GetResourceName(int index, out int dataOffset) { long pos = nameSectionPosition + namePositions[index]; byte[] bytes; lock (reader) { reader.Seek(pos, SeekOrigin.Begin); // Can't use reader.ReadString, since it's using UTF-8! int byteLen = reader.Read7BitEncodedInt(); if (byteLen < 0) { throw new BadImageFormatException("Resource name has negative length"); } bytes = new byte[byteLen]; // We must read byteLen bytes, or we have a corrupted file. // Use a blocking read in case the stream doesn't give us back // everything immediately. int count = byteLen; while (count > 0) { int n = reader.Read(bytes, byteLen - count, count); if (n == 0) { throw new BadImageFormatException("End of stream within a resource name"); } count -= n; } dataOffset = reader.ReadInt32(); if (dataOffset < 0) { throw new BadImageFormatException("Negative data offset"); } } return(Encoding.Unicode.GetString(bytes)); }
public ResourcesFile(Stream stream, bool leaveOpen = true) { fileStartPosition = stream.Position; reader = new MyBinaryReader(stream, leaveOpen); const string ResourcesHeaderCorrupted = "Resources header corrupted."; // Read ResourceManager header // Check for magic number int magicNum = reader.ReadInt32(); if (magicNum != MagicNumber) { throw new BadImageFormatException("Not a .resources file - invalid magic number"); } // Assuming this is ResourceManager header V1 or greater, hopefully // after the version number there is a number of bytes to skip // to bypass the rest of the ResMgr header. For V2 or greater, we // use this to skip to the end of the header int resMgrHeaderVersion = reader.ReadInt32(); int numBytesToSkip = reader.ReadInt32(); if (numBytesToSkip < 0 || resMgrHeaderVersion < 0) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } if (resMgrHeaderVersion > 1) { reader.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current); } else { // We don't care about numBytesToSkip; read the rest of the header // readerType: reader.ReadString(); // resourceSetType: reader.ReadString(); } // Read RuntimeResourceSet header // Do file version check version = reader.ReadInt32(); if (version != ResourceSetVersion && version != 1) { throw new BadImageFormatException($"Unsupported resource set version: {version}"); } numResources = reader.ReadInt32(); if (numResources < 0) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } // Read type positions into type positions array. // But delay initialize the type table. int numTypes = reader.ReadInt32(); if (numTypes < 0) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } typeTable = new string[numTypes]; for (int i = 0; i < numTypes; i++) { typeTable[i] = reader.ReadString(); } // Prepare to read in the array of name hashes // Note that the name hashes array is aligned to 8 bytes so // we can use pointers into it on 64 bit machines. (4 bytes // may be sufficient, but let's plan for the future) // Skip over alignment stuff. All public .resources files // should be aligned No need to verify the byte values. long pos = reader.BaseStream.Position - fileStartPosition; int alignBytes = unchecked ((int)pos) & 7; if (alignBytes != 0) { for (int i = 0; i < 8 - alignBytes; i++) { reader.ReadByte(); } } // Skip over the array of name hashes try { reader.Seek(checked (4 * numResources), SeekOrigin.Current); } catch (OverflowException) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } // Read in the array of relative positions for all the names. namePositions = new int[numResources]; for (int i = 0; i < numResources; i++) { int namePosition = reader.ReadInt32(); if (namePosition < 0) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } namePositions[i] = namePosition; } // Read location of data section. int dataSectionOffset = reader.ReadInt32(); if (dataSectionOffset < 0) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } // Store current location as start of name section nameSectionPosition = reader.BaseStream.Position; dataSectionPosition = fileStartPosition + dataSectionOffset; // _nameSectionOffset should be <= _dataSectionOffset; if not, it's corrupt if (dataSectionPosition < nameSectionPosition) { throw new BadImageFormatException(ResourcesHeaderCorrupted); } }