/// <summary> /// Open the specified file. /// </summary> /// <param name="file"></param> /// <returns>True if the opened file was a Reko project.</returns> public bool OpenBinary(string file, string outputDir) { var ldr = Services.RequireService <ILoader>(); this.Decompiler = CreateDecompiler(ldr); var svc = Services.RequireService <IWorkerDialogService>(); bool isOldProject = false; svc.StartBackgroundWork("Loading program", delegate() { isOldProject = Decompiler.Load(file, outputDir); }); if (Decompiler.Project == null) { return(false); } ProgramResourceGroup prg = Decompiler.Project.Programs[0].Resources; // Process the resources adn save as files ProcessResources(prg, outputDir); var browserSvc = Services.RequireService <IProjectBrowserService>(); browserSvc.Load(Decompiler.Project); ShowLowLevelWindow(); return(isOldProject); }
public bool OpenBinaryAs(string file, string outputDir, LoadDetails details) { var ldr = Services.RequireService <ILoader>(); this.Decompiler = CreateDecompiler(ldr); IWorkerDialogService svc = Services.RequireService <IWorkerDialogService>(); svc.StartBackgroundWork("Loading program", delegate() { Program program = Decompiler.LoadRawImage(file, outputDir, details); ProgramResourceGroup prg = program.Resources; // Process the resources adn save as files ProcessResources(prg, outputDir); }); var browserSvc = Services.RequireService <IProjectBrowserService>(); if (Decompiler.Project != null) { browserSvc.Load(Decompiler.Project); ShowLowLevelWindow(); } else { browserSvc.Clear(); } return(false); // We never open projects this way. }
/// <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); }
private void ProcessResources(ProgramResourceGroup prg, string outputDir) { try { if (prg.Name == "PE resources") { // Create the dir Directory.CreateDirectory(outputDir + "\\resources"); foreach (ProgramResourceGroup pr in prg.Resources) { switch (pr.Name) { case "CURSOR": { WriteResourceFile(outputDir + "\\resources", "Cursor", ".cur", pr); } break; case "BITMAP": { WriteResourceFile(outputDir + "\\resources", "Bitmap", ".bmp", pr); } break; case "ICON": { WriteResourceFile(outputDir + "\\resources", "Icon", ".ico", pr); } break; case "FONT": { WriteResourceFile(outputDir + "\\resources", "Font", ".bin", pr); } break; case "NEWBITMAP": { WriteResourceFile(outputDir + "\\resources", "NewBitmap", ".bmp", pr); } break; default: break; } } } } catch (Exception) { } }
/// <summary> /// Reads a resource directory, starting at the position of the given image /// reader. /// </summary> /// <param name="rdr">A little endian <see cref="EndianImageReader"/>.</param> /// <returns>A list of the resources found in the directory.</returns> public List <ProgramResource> ReadResourceDirectory(EndianImageReader 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>(); // Read the named entries. 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, PeResourceType.FromInt(0))); entries.Add(e); } } // Read the entries accessed by numeric ID. for (int i = 0; i < cIdEntries; ++i) { var id = rdr.ReadInt32(); var rvaEntry = rdr.ReadUInt32(); var subRdr = new LeImageReader(imgLoaded, rvaResources + (rvaEntry & ~DIR_MASK)); if ((rvaEntry & DIR_MASK) == 0) { throw new BadImageFormatException(); } var rt = PeResourceType.FromInt(id); var e = new ProgramResourceGroup { Name = rt.Name }; e.Resources.AddRange(ReadNameDirectory(subRdr, rt)); entries.Add(e); } return(entries); }
public List <ProgramResource> ReadResourceDirectory(EndianImageReader 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); }
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 = ReadResourceUtf16leString(rvaResources + (rvaName & ~DIR_MASK)), }; 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); }
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); }
private bool WriteResourceFile(IFileSystemService fsSvc, string outputDir, string ResourceType, string ext, ProgramResourceGroup pr) { var dirPath = Path.Combine(outputDir, ResourceType); try { fsSvc.CreateDirectory(dirPath); } catch (Exception ex) { var diagSvc = services.RequireService <IDiagnosticsService>(); diagSvc.Error(ex, $"Unable to create directory '{dirPath}'."); return(false); } string path = ""; try { foreach (ProgramResourceGroup pr1 in pr.Resources) { foreach (ProgramResourceInstance pr2 in pr1.Resources) { path = Path.Combine(dirPath, pr1.Name + ext); fsSvc.WriteAllBytes(path, pr2.Bytes); } } } catch (Exception ex) { var diagSvc = services.RequireService <IDiagnosticsService>(); diagSvc.Error(ex, $"Unable to write file '{path}'"); return(false); } return(true); }
private void WriteResourceFile(string outputDir, string ResourceType, string ext, ProgramResourceGroup pr) { Directory.CreateDirectory(outputDir + "\\" + ResourceType); foreach (ProgramResourceGroup pr1 in pr.Resources) { foreach (ProgramResourceInstance pr2 in pr1.Resources) { // write the bytes to file try { using (var fs = new FileStream(outputDir + "\\" + ResourceType + "\\" + pr1.Name + ext, FileMode.Create, FileAccess.Write)) { fs.Write(pr2.Bytes, 0, pr2.Bytes.Length); } } catch (Exception ex) { } } } }
private bool WriteResource(ProgramResource?resource, IFileSystemService fsSvc, string outputDir, string ResourceType, ProgramResourceGroup pr) { if (resource is ProgramResourceGroup grp) { outputDir = Path.Combine(outputDir, grp.Name); try { fsSvc.CreateDirectory(outputDir); } catch (Exception ex) { eventListener.Error(ex, $"Unable to create directory '{outputDir}'."); return(false); } foreach (var res in grp.Resources) { if (!WriteResource(res, fsSvc, outputDir, "", null !)) { return(false); } } return(true); } else if (resource is ProgramResourceInstance pr2) { string path = ""; try { if (pr2.Bytes != null) { var filename = $"{pr2.Type}_{pr2.Name}{pr2.FileExtension}"; path = Path.Combine(outputDir, filename); fsSvc.WriteAllBytes(path, pr2.Bytes); } } catch (Exception ex) { eventListener.Error(ex, $"Unable to write file '{path}'."); return(false); } return(true); } return(true); }
/// <summary> /// Reads in the NE image resources. /// </summary> public List <ProgramResource> LoadResources() { List <ProgramResource> resources = new List <ProgramResource>(); var rsrcTable = new LeImageReader(RawImage, OffRsrcTable); var rdr = rsrcTable.Clone(); ushort size_shift = rdr.ReadLeUInt16(); var resourceGroups = new Dictionary <ResourceType, ProgramResourceGroup>(); var iconIds = new Dictionary <ushort, ProgramResourceInstance>(); ushort rsrcType = rdr.ReadLeUInt16(); while (rsrcType != 0) { var rt = Win16ResourceType.FromInt(rsrcType); if (!resourceGroups.TryGetValue(rt, out var resGrp)) { resGrp = new ProgramResourceGroup { Name = rt.Name }; resourceGroups.Add(rt, 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(RawImage, offset); var rsrc = rdrRsrc.ReadBytes((uint)nameLength << size_shift); var rsrcInstance = new ProgramResourceInstance { Name = resname, Type = resGrp.Name, Bytes = rsrc, FileExtension = rt.FileExtension, }; resGrp.Resources.Add(rsrcInstance); if (rt == Win16ResourceType.Icon) { iconIds[(ushort)(nameId & ~0x8000)] = rsrcInstance; } } resources.Add(resGrp); rsrcType = rdr.ReadLeUInt16(); } PostProcessIcons(resourceGroups, iconIds, resources); PostProcessBitmaps(resourceGroups); return(resources); }
/// <summary> /// Reads in the NE resources from OS/2. /// </summary> public List <ProgramResource> LoadOs2Resources(NeImageLoader.NeSegment[] segments, ushort segmentCount, ushort alignmentShift) { List <ProgramResource> resources = new List <ProgramResource>(); var rsrcTable = new LeImageReader(RawImage, OffRsrcTable); var rdr = rsrcTable.Clone(); ResourceTableEntry[] entries = new ResourceTableEntry[ResourceTableEntries]; for (int i = 0; i < entries.Length; i++) { entries[i].etype = rdr.ReadUInt16(); entries[i].ename = rdr.ReadUInt16(); } NeImageLoader.NeSegment[] resourceSegments = new NeImageLoader.NeSegment[ResourceTableEntries]; Array.Copy(segments, segmentCount - ResourceTableEntries, resourceSegments, 0, ResourceTableEntries); NeImageLoader.NeSegment[] realSegments = new NeImageLoader.NeSegment[segmentCount - ResourceTableEntries]; Array.Copy(segments, 0, realSegments, 0, realSegments.Length); segments = realSegments; var os2Resources = new SortedDictionary <ushort, ProgramResourceGroup>(); for (int i = 0; i < entries.Length; i++) { os2Resources.TryGetValue(entries[i].etype, out ProgramResourceGroup resGrp); var rt = Os2ResourceType.FromInt(entries[i].etype); if (resGrp == null) { resGrp = new ProgramResourceGroup { Name = rt.Name } } ; uint length = resourceSegments[i].DataLength; var dataOffset = (uint)(resourceSegments[i].DataOffset << alignmentShift); if (length == 0) { length = 65536; } if (dataOffset == 0) { dataOffset = 65536; } if ((resourceSegments[i].Flags & (ushort)0x4000) != 0) { length <<= alignmentShift; } var rdrRsrc = new LeImageReader(RawImage, dataOffset); var rsrc = rdrRsrc.ReadBytes(length); var rsrcInstance = new ProgramResourceInstance { Name = $"{entries[i].ename}", Type = "Os2_" + resGrp.Name, Bytes = rsrc, FileExtension = rt.FileExtension }; resGrp.Resources.Add(rsrcInstance); os2Resources.Remove(entries[i].etype); os2Resources[entries[i].etype] = resGrp; } foreach (var kvp in os2Resources) { resources.Add(kvp.Value); } return(resources); } string ReadByteLengthString(EndianImageReader rdr, int offset) { var clone = rdr.Clone(); clone.Offset = clone.Offset + offset; var len = clone.ReadByte(); var abStr = clone.ReadBytes(len); return(Encoding.ASCII.GetString(abStr)); }