ILRepack/Steps/Win32Resources/RsrcReader.cs (88 lines of code) (raw):
//
// Copyright (c) 2012 Francois Valdy
// Copyright (c) 2018 Alexander Vostres
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System.IO;
using System.Text;
using ILRepacking.Steps.Win32Resources.PE;
namespace ILRepacking.Steps.Win32Resources
{
internal class RsrcReader
{
internal static ResourceDirectory ReadResourceDirectory(byte[] b, uint baseAddress)
{
var dr = new MemoryStream(b);
return ReadResourceDirectory(new BinaryReader(dr), baseAddress);
}
private static ResourceDirectory ReadResourceDirectory(BinaryReader dr, uint baseAddress)
{
var d = ReadResourceDirectoryTable(dr);
int ne = d.NumNameEntries + d.NumIdEntries;
for (int i = 0; i < ne; i++)
d.Entries.Add(ReadResourceEntry(dr, baseAddress));
return d;
}
private static ResourceEntry ReadResourceEntry(BinaryReader dr, uint baseAddress)
{
var re = new ResourceEntry();
uint id = dr.ReadUInt32();
uint offset = dr.ReadUInt32();
long pos = dr.BaseStream.Position;
if ((id & 0x80000000) != 0)
{
dr.BaseStream.Position = (id & 0x7fffffff);
var b = new StringBuilder();
int c;
while ((c = dr.Read()) > 0)
b.Append((char) c);
re.Name = b.ToString();
}
else
{
re.Id = id;
}
if ((offset & 0x80000000) != 0)
{
dr.BaseStream.Position = (offset & 0x7fffffff);
re.Directory = ReadResourceDirectory(dr, baseAddress);
}
else
{
dr.BaseStream.Position = offset;
uint rva = dr.ReadUInt32();
uint size = dr.ReadUInt32();
uint cp = dr.ReadUInt32();
uint res = dr.ReadUInt32();
re.CodePage = cp;
re.Reserved = res;
dr.BaseStream.Position = (rva - baseAddress);
re.Data = dr.ReadBytes((int)size);
}
dr.BaseStream.Position = pos;
return re;
}
private static ResourceDirectory ReadResourceDirectoryTable(BinaryReader dr)
{
var t = new ResourceDirectory
{
Characteristics = dr.ReadUInt32(),
TimeDateStamp = dr.ReadUInt32(),
MajorVersion = dr.ReadUInt16(),
MinVersion = dr.ReadUInt16(),
NumNameEntries = dr.ReadUInt16(),
NumIdEntries = dr.ReadUInt16()
};
return t;
}
public static ResourceDirectory ReadResourceDirectory(string fileName)
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var reader = new ImageReader(stream);
var data = reader.GetSectionData(".rsrc");
if (data == null)
{
return new ResourceDirectory();
}
return ReadResourceDirectory(data.Data, data.VirtualAddress);
}
}
}
}