public List<ProgramResource> ReadResourceDirectory(ImageReader rdr) { const uint DIR_MASK = 0x80000000; var flags = rdr.ReadUInt32(); var date = rdr.ReadUInt32(); var version = rdr.ReadUInt32(); var cNameEntries = rdr.ReadUInt16(); var cIdEntries = rdr.ReadUInt16(); var entries = new List<ProgramResource>(); for (int i = 0; i < cNameEntries; ++i) { var rvaName = rdr.ReadUInt32(); var rvaEntry = rdr.ReadUInt32(); var subRdr = new LeImageReader(imgLoaded, rvaResources + (rvaEntry & ~DIR_MASK)); if ((rvaEntry & DIR_MASK) == 0) throw new BadImageFormatException(); if ((rvaName & DIR_MASK) != 0) { var e = new ProgramResourceGroup { //Name = ReadResourceString(rvaName), Name = ReadResourceUtf16leString(rvaResources + (rvaName & ~DIR_MASK)), }; e.Resources.AddRange(ReadNameDirectory(subRdr, 0)); entries.Add(e); } } for (int i = 0; i < cIdEntries; ++i) { var id = rdr.ReadUInt32(); var rvaEntry = rdr.ReadUInt32(); var subRdr = new LeImageReader(imgLoaded, rvaResources + (rvaEntry & ~DIR_MASK)); if ((rvaEntry & DIR_MASK) == 0) throw new BadImageFormatException(); var e = new ProgramResourceGroup { Name = GenerateResourceName(id), }; e.Resources.AddRange(ReadNameDirectory(subRdr, id)); entries.Add(e); } return entries; }
/// <summary> /// Build icons out of the icon groups + icons. /// </summary> /// <param name="iconGroups"></param> /// <param name="icons"></param> private void PostProcessIcons( ProgramResourceGroup iconGroups, ProgramResourceGroup icons, Dictionary<ushort, ProgramResourceInstance> iconIds, List<ProgramResource> resources) { if (icons == null) { if (iconGroups != null) resources.Remove(iconGroups); return; } if (iconGroups == null) { if (icons == null) resources.Remove(icons); return; } foreach (ProgramResourceInstance iconGroup in iconGroups.Resources) { var r = new BinaryReader(new MemoryStream(iconGroup.Bytes)); var stm = new MemoryStream(); var w = new BinaryWriter(stm); // Copy the group header w.Write(r.ReadInt16()); w.Write(r.ReadInt16()); short dirEntries = r.ReadInt16(); w.Write(dirEntries); var icIds = new List<Tuple<ushort, int>>(); for (int i = 0; i < dirEntries; ++i) { w.Write(r.ReadInt32()); w.Write(r.ReadInt32()); w.Write(r.ReadInt32()); var iconId = r.ReadUInt16(); w.Flush(); icIds.Add(Tuple.Create(iconId, (int)stm.Position)); w.Write(0); } foreach (var id in icIds) { var icon = iconIds[id.Item1]; var icOffset = (int) w.Seek(0, SeekOrigin.Current); w.Seek(id.Item2, SeekOrigin.Begin); w.Write(icOffset); w.Seek(icOffset, SeekOrigin.Begin); w.Write(icon.Bytes); } iconGroup.Bytes = stm.ToArray(); iconGroup.Type = "Win16_ICON"; } iconGroups.Name = "ICON"; resources.Remove(icons); }
void PostProcessBitmaps(ProgramResourceGroup bitmaps) { if (bitmaps == null) return; foreach (ProgramResourceInstance bitmap in bitmaps.Resources) { var stm = new MemoryStream(); var bw = new BinaryWriter(stm); bw.Write('B'); bw.Write('M'); bw.Write(14 + bitmap.Bytes.Length); bw.Write(0); bw.Write(14); bw.Write(bitmap.Bytes, 0, bitmap.Bytes.Length); bw.Flush(); bitmap.Bytes = stm.ToArray(); } }
/// <summary> /// Reads in the NE image resources. /// </summary> //$REFACTOR: resource loading seems to want to belong in a separate file. private void LoadResources(List<ProgramResource> resources) { var rsrcTable = new LeImageReader(RawImage, this.lfaNew + offRsrcTable); var rdr = rsrcTable.Clone(); ushort size_shift = rdr.ReadLeUInt16(); ProgramResourceGroup bitmaps = null; ProgramResourceGroup iconGroups = null; ProgramResourceGroup icons = null; var iconIds = new Dictionary<ushort, ProgramResourceInstance>(); ushort rsrcType = rdr.ReadLeUInt16(); while (rsrcType != 0) { var resGrp = new ProgramResourceGroup { Name = GetResourceType(rsrcType) }; if (rsrcType == NE_RSCTYPE_GROUP_ICON) iconGroups = resGrp; else if (rsrcType == NE_RSCTYPE_ICON) icons = resGrp; else if (rsrcType == NE_RSCTYPE_BITMAP) bitmaps = resGrp; ushort typeCount = rdr.ReadLeUInt16(); uint resLoader = rdr.ReadLeUInt32(); for (int count = typeCount; count > 0; --count) { ushort nameOffset = rdr.ReadLeUInt16(); ushort nameLength = rdr.ReadLeUInt16(); ushort nameFlags = rdr.ReadLeUInt16(); ushort nameId = rdr.ReadLeUInt16(); ushort nameHandle = rdr.ReadLeUInt16(); ushort nameUsage = rdr.ReadLeUInt16(); string resname; if ((nameId & 0x8000) != 0) { resname = (nameId & ~0x8000).ToString(); } else { resname = ReadByteLengthString(rsrcTable, nameId); } var offset = (uint)nameOffset << size_shift; var rdrRsrc = new LeImageReader(base.RawImage, offset); var rsrc = rdrRsrc.ReadBytes((uint)nameLength << size_shift); var rsrcInstance = new ProgramResourceInstance { Name = resname, Type = "Win16_" + resGrp.Name, Bytes = rsrc, }; resGrp.Resources.Add(rsrcInstance); if (rsrcType == NE_RSCTYPE_ICON) iconIds[(ushort)(nameId & ~0x8000)] = rsrcInstance; } resources.Add(resGrp); rsrcType = rdr.ReadLeUInt16(); } PostProcessIcons(iconGroups, icons, iconIds, resources); PostProcessBitmaps(bitmaps); }
public List<ProgramResource> ReadNameDirectory(ImageReader rdr, uint resourceType) { const uint DIR_MASK = 0x80000000; var flags = rdr.ReadUInt32(); var date = rdr.ReadUInt32(); var version = rdr.ReadUInt32(); var cNameEntries = rdr.ReadUInt16(); var cIdEntries = rdr.ReadUInt16(); var entries = new List<ProgramResource>(); for (int i = 0; i < cNameEntries; ++i) { var rvaName = rdr.ReadUInt32(); var rvaEntry = rdr.ReadUInt32(); var subRdr = new LeImageReader(imgLoaded, rvaResources + (rvaEntry & ~DIR_MASK)); if ((rvaEntry & DIR_MASK) == 0) throw new BadImageFormatException(); var e = new ProgramResourceGroup { Name = ReadResourceString(rvaName), }; e.Resources.AddRange(ReadLanguageDirectory(subRdr, resourceType, e.Name)); entries.Add(e); } for (int i = 0; i < cIdEntries; ++i) { var id = rdr.ReadUInt32(); var rvaEntry = rdr.ReadUInt32(); var subRdr = new LeImageReader(imgLoaded, rvaResources + (rvaEntry & ~DIR_MASK)); if ((rvaEntry & DIR_MASK) == 0) throw new BadImageFormatException(); var e = new ProgramResourceGroup { Name = id.ToString(), }; e.Resources.AddRange(ReadLanguageDirectory(subRdr, resourceType, e.Name)); entries.Add(e); } return entries; }