Ejemplo n.º 1
0
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            baseExecutable = new MZ(BaseStream);
            if (!baseExecutable.Recognized)
            {
                return;
            }

            if (baseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return;
            }

            BaseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
            Marshal.FreeHGlobal(hdrPtr);
            Recognized = header.signature == SIGNATURE;

            if (!Recognized)
            {
                return;
            }

            Type = "Portable Executable (PE)";

            if (header.coff.optionalHeader.magic == PE32Plus)
            {
                BaseStream.Position -= 4;
                buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader64))];
                BaseStream.Read(buffer, 0, buffer.Length);
                hdrPtr = Marshal.AllocHGlobal(buffer.Length);
                Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
                winHeader = (WindowsHeader64)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader64));
                Marshal.FreeHGlobal(hdrPtr);
            }
            else
            {
                buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader))];
                BaseStream.Read(buffer, 0, buffer.Length);
                hdrPtr = Marshal.AllocHGlobal(buffer.Length);
                Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
                WindowsHeader hdr32 = (WindowsHeader)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader));
                Marshal.FreeHGlobal(hdrPtr);
                winHeader = ToPlus(hdr32);
            }

            OperatingSystem reqOs = new OperatingSystem();

            switch (winHeader.subsystem)
            {
            case Subsystems.IMAGE_SUBSYSTEM_UNKNOWN:
                reqOs.Name = "Unknown";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_NATIVE:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "Native";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_GUI:
                reqOs.Name      = winHeader.majorSubsystemVersion <= 3 ? "Windows NT" : "Windows";
                reqOs.Subsystem = "GUI";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CUI:
                reqOs.Name      = winHeader.majorSubsystemVersion <= 3 ? "Windows NT" : "Windows";
                reqOs.Subsystem = "Console";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_OS2_CUI:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "OS/2";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_POSIX_CUI:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "POSIX";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
                reqOs.Name      = "Windows";
                reqOs.Subsystem = "Native";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
                reqOs.Name = "Windows CE";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_EFI_APPLICATION:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_ROM:
                reqOs.Name = "EFI";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_XBOX:
                reqOs.Name = "Xbox OS";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "Boot environment";
                break;

            default:
                reqOs.Name = $"Unknown code ${(ushort)winHeader.subsystem}";
                break;
            }

            reqOs.MajorVersion      = winHeader.majorSubsystemVersion;
            reqOs.MinorVersion      = winHeader.minorSubsystemVersion;
            RequiredOperatingSystem = reqOs;

            buffer           = new byte[Marshal.SizeOf(typeof(ImageDataDirectory))];
            directoryEntries = new ImageDataDirectory[winHeader.numberOfRvaAndSizes];
            for (int i = 0; i < directoryEntries.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                directoryEntries[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ImageDataDirectory>(buffer);
            }

            buffer         = new byte[Marshal.SizeOf(typeof(COFF.SectionHeader))];
            sectionHeaders = new COFF.SectionHeader[header.coff.numberOfSections];
            for (int i = 0; i < sectionHeaders.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                sectionHeaders[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <COFF.SectionHeader>(buffer);
            }

            Dictionary <string, COFF.SectionHeader> newSectionHeaders =
                sectionHeaders.ToDictionary(section => section.name);

            for (int i = 0; i < directoryEntries.Length; i++)
            {
                string tableName;
                switch (i)
                {
                case 0:
                    tableName = ".edata";
                    break;

                case 1:
                    tableName = ".idata";
                    break;

                case 2:
                    tableName = ".rsrc";
                    break;

                case 3:
                    tableName = ".pdata";
                    break;

                case 5:
                    tableName = ".reloc";
                    break;

                case 6:
                    tableName = ".debug";
                    break;

                case 9:
                    tableName = ".tls";
                    break;

                case 14:
                    tableName = ".cormeta";
                    break;

                default: continue;
                }

                if (newSectionHeaders.ContainsKey(tableName))
                {
                    continue;
                }
                if (directoryEntries[i].rva == 0)
                {
                    continue;
                }

                newSectionHeaders.Add(tableName,
                                      new COFF.SectionHeader
                {
                    characteristics =
                        COFF.SectionFlags.IMAGE_SCN_CNT_INITIALIZED_DATA |
                        COFF.SectionFlags.IMAGE_SCN_MEM_READ,
                    name             = tableName,
                    pointerToRawData = RvaToReal(directoryEntries[i].rva, sectionHeaders),
                    virtualAddress   = directoryEntries[i].rva,
                    sizeOfRawData    = directoryEntries[i].size,
                    virtualSize      = directoryEntries[i].size
                });
            }

            List <byte>   chars;
            List <string> strings = new List <string>();

            if (newSectionHeaders.TryGetValue(".edata", out COFF.SectionHeader edata))
            {
                buffer = new byte[Marshal.SizeOf(typeof(ExportDirectoryTable))];
                BaseStream.Position = edata.pointerToRawData;
                BaseStream.Read(buffer, 0, buffer.Length);
                ExportDirectoryTable edataTable =
                    BigEndianMarshal.ByteArrayToStructureLittleEndian <ExportDirectoryTable>(buffer);

                BaseStream.Position = RvaToReal(edataTable.nameRva, sectionHeaders);
                chars = new List <byte>();
                while (true)
                {
                    int ch = BaseStream.ReadByte();
                    if (ch <= 0)
                    {
                        break;
                    }

                    chars.Add((byte)ch);
                }

                moduleName = Encoding.ASCII.GetString(chars.ToArray());

                uint[] namePointers = new uint[edataTable.numberOfNamePointers];
                exportedNames       = new string[edataTable.numberOfNamePointers];
                buffer              = new byte[Marshal.SizeOf(typeof(uint)) * edataTable.numberOfNamePointers];
                BaseStream.Position = RvaToReal(edataTable.namePointerRva, sectionHeaders);
                BaseStream.Read(buffer, 0, buffer.Length);
                for (int i = 0; i < edataTable.numberOfNamePointers; i++)
                {
                    namePointers[i]     = BitConverter.ToUInt32(buffer, i * 4);
                    BaseStream.Position = RvaToReal(namePointers[i], sectionHeaders);

                    chars = new List <byte>();
                    while (true)
                    {
                        int ch = BaseStream.ReadByte();
                        if (ch <= 0)
                        {
                            break;
                        }

                        chars.Add((byte)ch);
                    }

                    exportedNames[i] = Encoding.ASCII.GetString(chars.ToArray());
                }
            }

            if (newSectionHeaders.TryGetValue(".idata", out COFF.SectionHeader idata))
            {
                buffer = new byte[Marshal.SizeOf(typeof(ImportDirectoryTable))];
                BaseStream.Position = idata.pointerToRawData;
                List <ImportDirectoryTable> importDirectoryEntries = new List <ImportDirectoryTable>();

                while (true)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    if (buffer.All(b => b == 0))
                    {
                        break;
                    }

                    importDirectoryEntries.Add(BigEndianMarshal
                                               .ByteArrayToStructureLittleEndian <ImportDirectoryTable>(buffer));
                }

                importedNames = new string[importDirectoryEntries.Count];
                for (int i = 0; i < importDirectoryEntries.Count; i++)
                {
                    BaseStream.Position = RvaToReal(importDirectoryEntries[i].nameRva, sectionHeaders);

                    chars = new List <byte>();
                    while (true)
                    {
                        int ch = BaseStream.ReadByte();
                        if (ch <= 0)
                        {
                            break;
                        }

                        chars.Add((byte)ch);
                    }

                    importedNames[i] = Encoding.ASCII.GetString(chars.ToArray());

                    // BeOS R3 uses PE with no subsystem
                    if (importedNames[i].ToLower() == "libbe.so")
                    {
                        reqOs.MajorVersion      = 3;
                        reqOs.MinorVersion      = 0;
                        reqOs.Subsystem         = null;
                        reqOs.Name              = "BeOS";
                        RequiredOperatingSystem = reqOs;
                    }
                    // Singularity appears as a native NT executable
                    else if (importedNames[i].ToLower() == "singularity.v1.dll")
                    {
                        reqOs.MajorVersion      = 1;
                        reqOs.MinorVersion      = 0;
                        reqOs.Subsystem         = null;
                        reqOs.Name              = "Singularity";
                        RequiredOperatingSystem = reqOs;
                    }
                }
            }

            if (newSectionHeaders.TryGetValue(".debug", out COFF.SectionHeader debug) && debug.virtualAddress > 0)
            {
                buffer = new byte[Marshal.SizeOf(typeof(DebugDirectory))];
                BaseStream.Position = debug.pointerToRawData;
                BaseStream.Read(buffer, 0, buffer.Length);
                debugDirectory = BigEndianMarshal.ByteArrayToStructureLittleEndian <DebugDirectory>(buffer);
            }

            if (newSectionHeaders.TryGetValue(".rsrc", out COFF.SectionHeader rsrc))
            {
                if (reqOs.Name == "BeOS")
                {
                    newSectionHeaders.Remove(".rsrc");
                    rsrc.pointerToRawData = rsrc.virtualAddress;

                    long maxPosition = BaseStream.Length;
                    foreach (KeyValuePair <string, COFF.SectionHeader> kvp in newSectionHeaders)
                    {
                        if (kvp.Value.pointerToRawData <= maxPosition &&
                            kvp.Value.pointerToRawData > rsrc.pointerToRawData)
                        {
                            maxPosition = kvp.Value.pointerToRawData;
                        }
                    }

                    rsrc.sizeOfRawData = (uint)(maxPosition - rsrc.pointerToRawData);
                    rsrc.virtualSize   = rsrc.sizeOfRawData;
                    newSectionHeaders.Add(".rsrc", rsrc);

                    buffer = new byte[rsrc.sizeOfRawData];
                    BaseStream.Position = rsrc.pointerToRawData;
                    BaseStream.Read(buffer, 0, buffer.Length);
                    BeosResources = Resources.Decode(buffer);

                    strings.AddRange(from type in BeosResources
                                     where type.type == Consts.B_VERSION_INFO_TYPE
                                     from resource in type.resources
                                     select BigEndianMarshal
                                     .ByteArrayToStructureLittleEndian <VersionInfo>(resource.data)
                                     into versionInfo
                                     select StringHandlers.CToString(versionInfo.long_info, Encoding.UTF8));
                }
                else
                {
                    WindowsResourcesRoot = GetResourceNode(BaseStream, rsrc.pointerToRawData,
                                                           rsrc.virtualAddress,
                                                           rsrc.pointerToRawData, 0, null, 0);
                    Versions = GetVersions().ToArray();

                    strings.AddRange(from v in Versions from s in v.StringsByLanguage from k in s.Value select k.Value);

                    foreach (ResourceNode rtype in WindowsResourcesRoot.children.Where(r => r.name == "RT_STRING"))
                    {
                        strings.AddRange(GetStrings(rtype));
                    }
                }
            }

            sectionHeaders = newSectionHeaders.Values.OrderBy(s => s.pointerToRawData).ToArray();
            Segment[] segments = new Segment[sectionHeaders.Length];
            for (int i = 0; i < segments.Length; i++)
            {
                segments[i] = new Segment
                {
                    Flags  = $"{sectionHeaders[i].characteristics}",
                    Name   = sectionHeaders[i].name,
                    Offset = sectionHeaders[i].pointerToRawData,
                    Size   = sectionHeaders[i].sizeOfRawData
                }
            }
            ;

            Segments = segments;
            strings.Sort();
            Strings = strings;
        }
Ejemplo n.º 2
0
        void Initialize()
        {
            Recognized = false;

            if (BaseStream == null)
            {
                return;
            }

            byte[] buffer = new byte[Marshal.SizeOf(typeof(AtariHeader))];
            BaseStream.Position = 0;
            BaseStream.Read(buffer, 0, buffer.Length);
            Header     = BigEndianMarshal.ByteArrayToStructureBigEndian <AtariHeader>(buffer);
            Recognized = Header.signature == SIGNATURE;
            List <string> strings = new List <string>();

            if (!Recognized)
            {
                return;
            }

            Type = "Atari ST executable";

            if (Header.symb_len != 0)
            {
                BaseStream.Position = 0x1C + Header.text_len + Header.data_len;
                buffer  = new byte[Marshal.SizeOf(typeof(SymbolEntry))];
                symbols = new SymbolEntry[Header.symb_len / Marshal.SizeOf(typeof(SymbolEntry))];
                for (int i = 0; i < symbols.Length; i++)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    symbols[i]      = new SymbolEntry();
                    symbols[i]      = BigEndianMarshal.ByteArrayToStructureBigEndian <SymbolEntry>(buffer);
                    symbols[i].type = (SymbolType)Swapping.Swap((ushort)symbols[i].type);
                    strings.Add(StringHandlers.CToString(symbols[i].name, Encoding.AtariSTEncoding));
                }
            }

            Segments = new []
            {
                new Segment
                {
                    Name   = ".text",
                    Flags  = $"{(PrgFlags)(Header.flags & 0xFFCF)} {(PrgSharing)(Header.flags & PF_SHARE_MASK)}",
                    Offset = 0x1C,
                    Size   = Header.text_len
                },
                new Segment
                {
                    Name   = ".data",
                    Flags  = "",
                    Offset = 0x1C + Header.text_len,
                    Size   = Header.data_len
                },
                new Segment
                {
                    Name   = ".bss",
                    Flags  = "",
                    Offset = 0,
                    Size   = Header.bss_len
                }
            };

            RequiredOperatingSystem = new OperatingSystem {
                Name = Header.mint == MINT_SIGNATURE ? "MiNT" : "Atari TOS"
            };

            if (ResourceStream == null)
            {
                return;
            }

            buffer = new byte[Marshal.SizeOf(typeof(GEM.GemResourceHeader))];
            ResourceStream.Position = 0;
            ResourceStream.Read(buffer, 0, buffer.Length);
            GEM.GemResourceHeader gemResourceHeader =
                BigEndianMarshal.ByteArrayToStructureBigEndian <GEM.GemResourceHeader>(buffer);

            if (gemResourceHeader.rsh_vrsn != 0 && gemResourceHeader.rsh_vrsn != 1 && gemResourceHeader.rsh_vrsn != 3 &&
                gemResourceHeader.rsh_vrsn != 4 && gemResourceHeader.rsh_vrsn != 5)
            {
                return;
            }

            if (gemResourceHeader.rsh_vrsn == 3)
            {
                buffer = new byte[Marshal.SizeOf(typeof(GEM.MagiCResourceHeader))];
                ResourceStream.Position = 0;
                ResourceStream.Read(buffer, 0, buffer.Length);
                ResourceHeader =
                    BigEndianMarshal.ByteArrayToStructureBigEndian <GEM.MagiCResourceHeader>(buffer);
                RequiredOperatingSystem = new OperatingSystem {
                    Name = "MagiC"
                };
            }
            else
            {
                ResourceHeader = GEM.GemToMagiC(gemResourceHeader);
            }

            if ((ResourceHeader.rsh_vrsn & 4) == 4)
            {
                buffer = new byte[Marshal.SizeOf(typeof(GEM.GemResourceExtension))];
                ResourceStream.Position = ResourceHeader.rsh_rssize;
                ResourceStream.Read(buffer, 0, buffer.Length);
                ResourceExtension = BigEndianMarshal.ByteArrayToStructureBigEndian <GEM.GemResourceExtension>(buffer);

                GemColorIcons = GEM.GetColorIcons(ResourceStream, ResourceExtension.color_ic, true,
                                                  Encoding.AtariSTEncoding);
            }

            if (ResourceHeader.rsh_ntree > 0)
            {
                ResourceStream.Position = ResourceHeader.rsh_trindex;
                int[]  treeOffsets = new int[ResourceHeader.rsh_ntree];
                byte[] tmp         = new byte[4];

                for (int i = 0; i < ResourceHeader.rsh_ntree; i++)
                {
                    ResourceStream.Read(tmp, 0, 4);
                    treeOffsets[i] = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
                }

                ResourceObjectRoots = new GEM.TreeObjectNode[ResourceHeader.rsh_ntree];

                for (int i = 0; i < ResourceHeader.rsh_ntree; i++)
                {
                    if (treeOffsets[i] <= 0 || treeOffsets[i] >= ResourceStream.Length)
                    {
                        continue;
                    }

                    ResourceStream.Position = treeOffsets[i];

                    List <GEM.ObjectNode> nodes = new List <GEM.ObjectNode>();
                    while (true)
                    {
                        buffer = new byte[Marshal.SizeOf(typeof(GEM.ObjectNode))];
                        ResourceStream.Read(buffer, 0, buffer.Length);
                        GEM.ObjectNode node = BigEndianMarshal.ByteArrayToStructureBigEndian <GEM.ObjectNode>(buffer);
                        nodes.Add(node);
                        if (((GEM.ObjectFlags)node.ob_flags).HasFlag(GEM.ObjectFlags.Lastob))
                        {
                            break;
                        }
                    }

                    List <short> knownNodes = new List <short>();
                    ResourceObjectRoots[i] =
                        GEM.ProcessResourceObject(nodes, ref knownNodes, 0, ResourceStream, strings, true,
                                                  Encoding.AtariSTEncoding);
                }
            }
            else if (ResourceHeader.rsh_nobs > 0)
            {
                GEM.ObjectNode[] nodes = new GEM.ObjectNode[ResourceHeader.rsh_nobs];

                ResourceStream.Position = ResourceHeader.rsh_object;
                for (short i = 0; i < ResourceHeader.rsh_nobs; i++)
                {
                    buffer = new byte[Marshal.SizeOf(typeof(GEM.ObjectNode))];
                    ResourceStream.Read(buffer, 0, buffer.Length);
                    nodes[i] = BigEndianMarshal.ByteArrayToStructureBigEndian <GEM.ObjectNode>(buffer);
                }

                List <short> knownNodes = new List <short>();
                ResourceObjectRoots    = new GEM.TreeObjectNode[1];
                ResourceObjectRoots[0] =
                    GEM.ProcessResourceObject(nodes, ref knownNodes, 0, ResourceStream, strings, true,
                                              Encoding.AtariSTEncoding);
            }

            if (strings.Count > 0)
            {
                strings.Sort();
                Strings = strings.Distinct();
            }
        }
Ejemplo n.º 3
0
        // TODO: How to know VxD structure offset
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            BaseExecutable = new MZ(BaseStream);
            if (!BaseExecutable.Recognized)
            {
                return;
            }

            if (BaseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return;
            }

            BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
            Marshal.FreeHGlobal(hdrPtr);
            Recognized = Header.signature == SIGNATURE || Header.signature == SIGNATURE16;

            if (!Recognized)
            {
                return;
            }

            Type        = Header.signature == SIGNATURE16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)";
            IsBigEndian = Header.byte_order == 1 || Header.word_order == 1;
            List <string> strings = new List <string>();

            OperatingSystem reqOs = new OperatingSystem();

            switch (Header.os_type)
            {
            case TargetOS.OS2:
                reqOs.Name = "OS/2";
                if (Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                    !Header.module_flags.HasFlag(ModuleFlags.PMCompatible) ||
                    !Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                    Header.module_flags.HasFlag(ModuleFlags.PMCompatible))
                {
                    reqOs.Subsystem = "Console";
                }
                else if (Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                         Header.module_flags.HasFlag(ModuleFlags.PMCompatible))
                {
                    reqOs.Subsystem = "Presentation Manager";
                }
                break;

            case TargetOS.Windows:
            case TargetOS.Win32:
            case TargetOS.Unknown:
                reqOs.Name = "Windows";
                break;

            case TargetOS.DOS:
                reqOs.Name = "Windows";
                break;

            default:
                reqOs.Name = $"Unknown code {(ushort)Header.os_type}";
                break;
            }

            RequiredOperatingSystem = reqOs;

            if (Header.resident_names_off != 0)
            {
                ResidentNames =
                    GetResidentStrings(BaseStream, BaseExecutable.Header.new_offset, Header.resident_names_off);

                if (ResidentNames.Length >= 1)
                {
                    ModuleName = ResidentNames[0].name;

                    if (ResidentNames.Length > 1)
                    {
                        NE.ResidentName[] newResidentNames = new NE.ResidentName[ResidentNames.Length - 1];
                        Array.Copy(ResidentNames, 1, newResidentNames, 0, ResidentNames.Length - 1);
                        ResidentNames = newResidentNames;
                    }
                    else
                    {
                        ResidentNames = null;
                    }
                }
            }

            if (Header.nonresident_name_table_len > 0)
            {
                NonResidentNames = GetResidentStrings(BaseStream, 0, Header.nonresident_name_table_off);

                if (NonResidentNames.Length >= 1)
                {
                    ModuleDescription = NonResidentNames[0].name;

                    if (NonResidentNames.Length > 1)
                    {
                        NE.ResidentName[] newNonResidentNames = new NE.ResidentName[NonResidentNames.Length - 1];
                        Array.Copy(NonResidentNames, 1, newNonResidentNames, 0, NonResidentNames.Length - 1);
                        NonResidentNames = newNonResidentNames;
                    }
                    else
                    {
                        NonResidentNames = null;
                    }
                }
            }

            if (Header.import_module_table_off != 0 && Header.import_module_entries > 0)
            {
                BaseStream.Position = Header.import_module_table_off + BaseExecutable.Header.new_offset;
                ImportedNames       = new string[Header.import_module_entries];
                for (int i = 0; i < Header.import_module_entries; i++)
                {
                    int len = BaseStream.ReadByte();
                    buffer = new byte[len];
                    BaseStream.Read(buffer, 0, len);
                    ImportedNames[i] = Encoding.ASCII.GetString(buffer);
                }
            }

            if (!string.IsNullOrEmpty(ModuleName))
            {
                strings.Add(ModuleName);
            }
            if (!string.IsNullOrEmpty(ModuleDescription))
            {
                strings.Add(ModuleDescription);
            }

            objectTableEntries     = new ObjectTableEntry[Header.obj_no];
            objectPageTableEntries = new ObjectPageTableEntry[Header.module_pages_no];

            BaseStream.Position = Header.obj_table_off + BaseExecutable.Header.new_offset;
            buffer = new byte[Marshal.SizeOf(typeof(ObjectTableEntry))];
            for (int i = 0; i < Header.obj_no; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                objectTableEntries[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectTableEntry>(buffer);
            }

            BaseStream.Position = Header.obj_page_table_off + BaseExecutable.Header.new_offset;

            if (Header.signature == SIGNATURE16)
            {
                buffer = new byte[Marshal.SizeOf(typeof(ObjectPageTableEntry16))];
                for (int i = 0; i < Header.module_pages_no; i++)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    ObjectPageTableEntry16 page16 =
                        BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectPageTableEntry16>(buffer);

                    int pageNo = (page16.High << 8) + page16.Low;

                    objectPageTableEntries[i] = new ObjectPageTableEntry
                    {
                        DataSize       = (ushort)Header.page_size,
                        Flags          = (PageTableAttributes)page16.Flags,
                        PageDataOffset = (uint)((pageNo - 1) * Header.page_size)
                    };
                }
            }
            else
            {
                buffer = new byte[Marshal.SizeOf(typeof(ObjectPageTableEntry))];
                for (int i = 0; i < Header.module_pages_no; i++)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    objectPageTableEntries[i] =
                        BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectPageTableEntry>(buffer);
                }
            }

            int debugSections   = 0;
            int winrsrcSections = 0;

            if (Header.debug_info_len > 0)
            {
                debugSections = 1;
            }
            if (Header.win_res_len > 0)
            {
                winrsrcSections = 1;
            }

            Segment[] sections = new Segment[objectTableEntries.Length + debugSections + winrsrcSections];
            for (int i = 0; i < objectTableEntries.Length; i++)
            {
                sections[i] = new Segment {
                    Flags = $"{objectTableEntries[i].ObjectFlags}"
                };
                if (objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Resource))
                {
                    sections[i].Name = ".rsrc";
                }
                else if (objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Executable))
                {
                    sections[i].Name = ".text";
                }
                else if (!objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Writable))
                {
                    sections[i].Name = ".rodata";
                }
                else if (StringHandlers.CToString(objectTableEntries[i].Name).ToLower() == "bss")
                {
                    sections[i].Name = ".bss";
                }
                else if (!string.IsNullOrWhiteSpace(StringHandlers.CToString(objectTableEntries[i].Name).Trim()))
                {
                    sections[i].Name = StringHandlers.CToString(objectTableEntries[i].Name).Trim();
                }
                else
                {
                    sections[i].Name = ".data";
                }

                if (objectTableEntries[i].PageTableEntries == 0 ||
                    objectTableEntries[i].PageTableIndex > objectPageTableEntries.Length)
                {
                    sections[i].Size = objectTableEntries[i].VirtualSize;
                    continue;
                }

                int shift = (int)(Header.signature == SIGNATURE16 ? 0 : Header.page_off_shift);

                if (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1]
                    .Flags.HasFlag(PageTableAttributes.IteratedDataPage))
                {
                    sections[i].Offset =
                        (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1].PageDataOffset << shift) +
                        Header.obj_iter_pages_off;
                }
                else if (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1]
                         .Flags.HasFlag(PageTableAttributes.LegalPhysicalPage))
                {
                    sections[i].Offset =
                        (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1].PageDataOffset << shift) +
                        Header.data_pages_off;
                }
                else
                {
                    sections[i].Offset = 0;
                }

                sections[i].Size = 0;
                for (int j = 0; j < objectTableEntries[i].PageTableEntries; j++)
                {
                    sections[i].Size += objectPageTableEntries[j + objectTableEntries[i].PageTableIndex - 1].DataSize;
                }

                if (sections[i].Offset + sections[i].Size > BaseStream.Length)
                {
                    sections[i].Size = BaseStream.Length - sections[i].Offset;
                }
            }

            if (winrsrcSections > 0)
            {
                sections[sections.Length - debugSections - winrsrcSections] = new Segment
                {
                    Name   = ".rsrc",
                    Size   = Header.win_res_len,
                    Offset = Header.win_res_off
                }
            }
            ;

            if (debugSections > 0)
            {
                sections[sections.Length - debugSections] = new Segment
                {
                    Name   = ".debug",
                    Size   = Header.debug_info_len,
                    Offset = Header.debug_info_off
                }
            }
            ;

            // It only contains a RT_VERSION resource prefixed by some 12-byte header I can't find information about, so let's just skip it.
            if (winrsrcSections > 0)
            {
                buffer = new byte[Header.win_res_len];
                BaseStream.Position = Header.win_res_off + 12;
                BaseStream.Read(buffer, 0, buffer.Length);
                WinVersion = new NE.Version(buffer);
                strings.AddRange(from s in WinVersion.StringsByLanguage from k in s.Value select k.Value);
            }

            resources           = new ResourceTableEntry[Header.resource_entries];
            BaseStream.Position = Header.resource_table_off + BaseExecutable.Header.new_offset;
            buffer = new byte[Marshal.SizeOf(typeof(ResourceTableEntry))];
            for (int i = 0; i < resources.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                resources[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourceTableEntry>(buffer);
            }

            SortedDictionary <ResourceTypes, List <NE.Resource> > os2Resources =
                new SortedDictionary <ResourceTypes, List <NE.Resource> >();

            for (int i = 0; i < resources.Length; i++)
            {
                os2Resources.TryGetValue(resources[i].type, out List <NE.Resource> thisResourceType);

                if (thisResourceType == null)
                {
                    thisResourceType = new List <NE.Resource>();
                }

                NE.Resource thisResource = new NE.Resource
                {
                    id         = resources[i].id,
                    name       = $"{resources[i].id}",
                    flags      = 0,
                    dataOffset = (uint)(sections[resources[i].obj_no - 1].Offset + resources[i].offset),
                    length     = resources[i].size
                };

                thisResource.data   = new byte[thisResource.length];
                BaseStream.Position = thisResource.dataOffset;
                BaseStream.Read(thisResource.data, 0, thisResource.data.Length);

                thisResourceType.Add(thisResource);
                os2Resources.Remove(resources[i].type);
                os2Resources.Add(resources[i].type, thisResourceType);
            }

            if (os2Resources.Count > 0)
            {
                neFormatResourceTable = new NE.ResourceTable();
                int counter = 0;
                neFormatResourceTable.types = new NE.ResourceType[os2Resources.Count];
                foreach (KeyValuePair <ResourceTypes, List <NE.Resource> > kvp in os2Resources)
                {
                    neFormatResourceTable.types[counter].count     = (ushort)kvp.Value.Count;
                    neFormatResourceTable.types[counter].id        = (ushort)kvp.Key;
                    neFormatResourceTable.types[counter].name      = Resources.IdToName((ushort)kvp.Key);
                    neFormatResourceTable.types[counter].resources = kvp.Value.OrderBy(r => r.id).ToArray();
                    counter++;
                }

                foreach (NE.ResourceType rtype in neFormatResourceTable.types)
                {
                    if (rtype.name != "RT_STRING")
                    {
                        continue;
                    }

                    strings.AddRange(NE.GetOs2Strings(rtype));
                }
            }

            Segments = sections;
            Strings  = strings;
        }
Ejemplo n.º 4
0
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            BaseStream.Seek(0, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(GeodeHeaderV2))];
            BaseStream.Read(buffer, 0, buffer.Length);
            header  = BigEndianMarshal.ByteArrayToStructureLittleEndian <GeodeHeader>(buffer);
            header2 = BigEndianMarshal.ByteArrayToStructureLittleEndian <GeodeHeaderV2>(buffer);

            Recognized = header.magic == GEOS_ID && header.type == FileType.GFT_EXECUTABLE ||
                         header2.magic == GEOS2_ID && header2.type == FileType2.GFT_EXECUTABLE;

            if (!Recognized)
            {
                return;
            }

            isNewHeader             = header2.magic == GEOS2_ID;
            RequiredOperatingSystem = new OperatingSystem {
                Name = "GEOS", MajorVersion = isNewHeader ? 2 : 1
            };

            List <string> strings = new List <string>
            {
                StringHandlers.CToString(isNewHeader ? header2.name : header.name, geosEncoding),
                StringHandlers.CToString(isNewHeader ? header2.copyright : header.copyright, geosEncoding),
                StringHandlers.CToString(isNewHeader ? header2.info : header.info, geosEncoding)
            };

            uint segmentBase = 0;

            if (isNewHeader)
            {
                BaseStream.Position = Marshal.SizeOf(typeof(GeodeHeaderV2));
                buffer      = new byte[Marshal.SizeOf(typeof(ApplicationHeaderV2))];
                segmentBase = (uint)Marshal.SizeOf(typeof(GeodeHeaderV2));
                BaseStream.Read(buffer, 0, buffer.Length);
                applicationHeader2 = BigEndianMarshal.ByteArrayToStructureLittleEndian <ApplicationHeaderV2>(buffer);
                imports            = new Import[applicationHeader2.imports];
                exports            = new Export[applicationHeader2.exports];
                segments           = new SegmentDescriptor[applicationHeader2.segments];
                strings.Add($"{StringHandlers.CToString(applicationHeader2.name, geosEncoding).Trim()}.{StringHandlers.CToString(applicationHeader2.extension, geosEncoding).Trim()}");
            }
            else
            {
                BaseStream.Position = Marshal.SizeOf(typeof(GeodeHeader));
                buffer = new byte[Marshal.SizeOf(typeof(ApplicationHeader))];
                BaseStream.Read(buffer, 0, buffer.Length);
                applicationHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <ApplicationHeader>(buffer);
                imports           = new Import[applicationHeader.imports];
                exports           = new Export[applicationHeader.exports];
                segments          = new SegmentDescriptor[applicationHeader.segments];
                strings.Add($"{StringHandlers.CToString(applicationHeader.name, geosEncoding).Trim()}.{StringHandlers.CToString(applicationHeader.extension, geosEncoding).Trim()}");
            }

            buffer = new byte[Marshal.SizeOf(typeof(Import))];
            for (int i = 0; i < imports.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                imports[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Import>(buffer);
                strings.Add(StringHandlers.CToString(imports[i].name, geosEncoding).Trim());
            }

            buffer = new byte[Marshal.SizeOf(typeof(Export))];
            for (int i = 0; i < exports.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                exports[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Export>(buffer);
            }

            if (segments.Length > 0)
            {
                buffer = new byte[Marshal.SizeOf(typeof(SegmentDescriptor)) * segments.Length];
                BaseStream.Read(buffer, 0, buffer.Length);
                Segment[] mySegments = new Segment[segments.Length];

                for (int i = 0; i < segments.Length; i++)
                {
                    segments[i].length = BitConverter.ToUInt16(buffer, 2 * i);
                    segments[i].offset =
                        BitConverter.ToUInt32(buffer, 2 * segments.Length + 4 * i) + segmentBase;
                    segments[i].relocs_length = BitConverter.ToUInt16(buffer, 6 * segments.Length + 2 * i);
                    segments[i].flags         =
                        (SegmentFlags)BitConverter.ToUInt16(buffer, 8 * segments.Length + 2 * i);

                    mySegments[i] = new Segment
                    {
                        Flags  = $"{segments[i].flags}",
                        Offset = segments[i].offset,
                        Size   = segments[i].length
                    };

                    if (i == 1)
                    {
                        mySegments[i].Name = ".idata";
                    }
                    else if (segments[i].flags.HasFlag(SegmentFlags.HAF_CODE))
                    {
                        mySegments[i].Name = ".text";
                    }
                    else if (segments[i].flags.HasFlag(SegmentFlags.HAF_OBJECT_RESOURCE))
                    {
                        mySegments[i].Name = ".rsrc";
                    }
                    else if (segments[i].flags.HasFlag(SegmentFlags.HAF_ZERO_INIT))
                    {
                        mySegments[i].Name = ".bss";
                    }
                    else if (segments[i].flags.HasFlag(SegmentFlags.HAF_READ_ONLY))
                    {
                        mySegments[i].Name = ".rodata";
                    }
                    else
                    {
                        mySegments[i].Name = ".data";
                    }
                }

                Segments = mySegments;
            }

            strings.Remove("");
            strings.Remove(null);
            Strings = strings;
        }
Ejemplo n.º 5
0
        internal static TreeObjectNode ProcessResourceObject(IList <ObjectNode> nodes, ref List <short> knownNodes,
                                                             short nodeNumber, Stream resourceStream,
                                                             List <string> strings, bool bigEndian,
                                                             Encoding encoding)
        {
            TreeObjectNode node = new TreeObjectNode
            {
                type   = (ObjectTypes)(nodes[nodeNumber].ob_type & 0xff),
                flags  = (ObjectFlags)nodes[nodeNumber].ob_flags,
                state  = (ObjectStates)nodes[nodeNumber].ob_state,
                data   = nodes[nodeNumber].ob_spec,
                x      = nodes[nodeNumber].ob_x,
                y      = nodes[nodeNumber].ob_y,
                width  = nodes[nodeNumber].ob_width,
                height = nodes[nodeNumber].ob_height
            };

            byte[] buffer;
            switch (node.type)
            {
            case ObjectTypes.G_TEXT:
            case ObjectTypes.G_BOXTEXT:
            case ObjectTypes.G_FTEXT:
            case ObjectTypes.G_FBOXTEXT:
                if (node.data <= 0 || node.data >= resourceStream.Length)
                {
                    break;
                }

                resourceStream.Position = node.data;
                buffer = new byte[Marshal.SizeOf(typeof(TedInfo))];
                resourceStream.Read(buffer, 0, buffer.Length);
                TedInfo ted = bigEndian
                                      ? BigEndianMarshal.ByteArrayToStructureBigEndian <TedInfo>(buffer)
                                      : BigEndianMarshal.ByteArrayToStructureLittleEndian <TedInfo>(buffer);

                node.TedInfo = new TextBlock
                {
                    Font          = (ObjectFont)ted.te_font,
                    Justification = (ObjectJustification)ted.te_just,
                    BorderColor   = (ObjectColors)((ted.te_color & BorderColorMask) >> 12),
                    TextColor     = (ObjectColors)((ted.te_color & TextColorMask) >> 8),
                    Transparency  = (ted.te_color & TransparentColor) != TransparentColor,
                    Fill          = (ObjectFillPattern)((ted.te_color & FillPatternMask) >> 4),
                    InsideColor   = (ObjectColors)(ted.te_color & InsideColorMask),
                    Thickness     = ted.te_thickness
                };

                byte[] tmpStr;

                if (ted.te_ptext > 0 && ted.te_ptext < resourceStream.Length && ted.te_txtlen > 0)
                {
                    tmpStr = new byte[ted.te_txtlen];
                    resourceStream.Position = ted.te_ptext;
                    resourceStream.Read(tmpStr, 0, ted.te_txtlen);
                    node.TedInfo.Text = StringHandlers.CToString(tmpStr, encoding);
                    if (!string.IsNullOrWhiteSpace(node.TedInfo.Text))
                    {
                        strings.Add(node.TedInfo.Text.Trim());
                    }
                }

                if (ted.te_pvalid > 0 && ted.te_pvalid < resourceStream.Length && ted.te_txtlen > 0)
                {
                    tmpStr = new byte[ted.te_txtlen];
                    resourceStream.Position = ted.te_pvalid;
                    resourceStream.Read(tmpStr, 0, ted.te_txtlen);
                    node.TedInfo.Validation = StringHandlers.CToString(tmpStr, encoding);
                    if (!string.IsNullOrWhiteSpace(node.TedInfo.Validation))
                    {
                        strings.Add(node.TedInfo.Validation.Trim());
                    }
                }

                if (ted.te_ptmplt > 0 && ted.te_ptmplt < resourceStream.Length && ted.te_tmplen > 0)
                {
                    tmpStr = new byte[ted.te_tmplen];
                    resourceStream.Position = ted.te_ptmplt;
                    resourceStream.Read(tmpStr, 0, ted.te_tmplen);
                    node.TedInfo.Template = StringHandlers.CToString(tmpStr, encoding);
                    if (!string.IsNullOrWhiteSpace(node.TedInfo.Template))
                    {
                        strings.Add(node.TedInfo.Template.Trim());
                    }
                }

                break;

            case ObjectTypes.G_IMAGE:
                if (node.data <= 0 || node.data >= resourceStream.Length)
                {
                    break;
                }

                resourceStream.Position = node.data;
                buffer = new byte[Marshal.SizeOf(typeof(BitBlock))];
                resourceStream.Read(buffer, 0, buffer.Length);
                BitBlock bitBlock = bigEndian
                                            ? BigEndianMarshal.ByteArrayToStructureBigEndian <BitBlock>(buffer)
                                            : BigEndianMarshal.ByteArrayToStructureLittleEndian <BitBlock>(buffer);

                node.BitBlock = new BitmapBlock
                {
                    Color  = (ObjectColors)bitBlock.bi_color,
                    Height = bitBlock.bi_hl,
                    Width  = (uint)(bitBlock.bi_wb * 8),
                    X      = bitBlock.bi_x,
                    Y      = bitBlock.bi_y
                };

                if (bitBlock.bi_pdata == 0 || bitBlock.bi_pdata >= resourceStream.Length)
                {
                    break;
                }

                node.BitBlock.Data      = new byte[bitBlock.bi_wb * bitBlock.bi_hl];
                resourceStream.Position = bitBlock.bi_pdata;
                resourceStream.Read(node.BitBlock.Data, 0, node.BitBlock.Data.Length);

                // Because the image is stored as words, they get reversed on PC GEM (Little-endian)
                if (!bigEndian)
                {
                    byte[] data = new byte[node.BitBlock.Data.Length];
                    for (int i = 0; i < data.Length; i += 2)
                    {
                        data[i]     = node.BitBlock.Data[i + 1];
                        data[i + 1] = node.BitBlock.Data[i];
                    }

                    node.BitBlock.Data = data;
                }

                break;

            case ObjectTypes.G_USERDEF:
                if (node.data <= 0 || node.data >= resourceStream.Length)
                {
                    break;
                }

                resourceStream.Position = node.data;
                buffer = new byte[Marshal.SizeOf(typeof(ApplicationBlock))];
                resourceStream.Read(buffer, 0, buffer.Length);
                node.ApplicationBlock = bigEndian
                                                ? BigEndianMarshal
                                        .ByteArrayToStructureBigEndian <ApplicationBlock>(buffer)
                                                : BigEndianMarshal
                                        .ByteArrayToStructureLittleEndian <ApplicationBlock>(buffer);
                break;

            case ObjectTypes.G_ICON:
                if (node.data <= 0 || node.data >= resourceStream.Length)
                {
                    break;
                }

                resourceStream.Position = node.data;
                buffer = new byte[Marshal.SizeOf(typeof(IconBlock))];
                resourceStream.Read(buffer, 0, buffer.Length);

                node.IconBlock = GetIconBlock(resourceStream, buffer, bigEndian, encoding);

                if (!string.IsNullOrWhiteSpace(node.IconBlock.Text))
                {
                    strings.Add(node.IconBlock.Text.Trim());
                }

                break;

            case ObjectTypes.G_CICON:
                // Do nothing, it is done separately...
                break;

            case ObjectTypes.G_BUTTON:
            case ObjectTypes.G_STRING:
            case ObjectTypes.G_TITLE:
            case ObjectTypes.G_SHORTCUT:
                if (node.data <= 0 || node.data >= resourceStream.Length)
                {
                    break;
                }

                resourceStream.Position = node.data;
                List <byte> chars = new List <byte>();
                while (true)
                {
                    int character = resourceStream.ReadByte();

                    if (character <= 0)
                    {
                        break;
                    }

                    chars.Add((byte)character);
                }

                node.String = StringHandlers.CToString(chars.ToArray(), encoding);
                if (!string.IsNullOrWhiteSpace(node.String))
                {
                    strings.Add(node.String.Trim());
                }
                break;
            }

            knownNodes.Add(nodeNumber);

            if (nodes[nodeNumber].ob_head > 0 && !knownNodes.Contains(nodes[nodeNumber].ob_head))
            {
                node.child = ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_head, resourceStream,
                                                   strings, bigEndian, encoding);
            }

            if (nodes[nodeNumber].ob_next > 0 && !knownNodes.Contains(nodes[nodeNumber].ob_next))
            {
                node.sibling = ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_next, resourceStream,
                                                     strings, bigEndian, encoding);
            }

            return(node);
        }
Ejemplo n.º 6
0
        public static ColorIcon[] GetColorIcons(Stream resourceStream, int colorIc, bool bigEndian, Encoding encoding)
        {
            byte[] buffer;

            if (colorIc == -1 || colorIc >= resourceStream.Length)
            {
                return(null);
            }

            resourceStream.Position = colorIc;

            int cicons = 0;

            while (true)
            {
                buffer = new byte[4];
                resourceStream.Read(buffer, 0, buffer.Length);

                if (BitConverter.ToInt32(buffer, 0) == -1)
                {
                    break;
                }

                cicons++;
            }

            ColorIcon[] colorIcons = new ColorIcon[cicons];

            for (int i = 0; i < cicons; i++)
            {
                buffer = new byte[Marshal.SizeOf(typeof(IconBlock))];
                resourceStream.Read(buffer, 0, buffer.Length);
                IconBlock iconBlock = BigEndianMarshal.ByteArrayToStructureBigEndian <IconBlock>(buffer);
                int       isize     = iconBlock.ib_wicon * iconBlock.ib_hicon / 8;

                buffer = new byte[4];
                resourceStream.Position -= 2;
                resourceStream.Read(buffer, 0, buffer.Length);
                int numRez = BitConverter.ToInt32(buffer.Reverse().ToArray(), 0);

                colorIcons[i] = new ColorIcon
                {
                    Color      = new ColorIconPlane[numRez],
                    Monochrome = new Icon
                    {
                        Width           = iconBlock.ib_wicon,
                        Height          = iconBlock.ib_hicon,
                        X               = iconBlock.ib_xicon,
                        Y               = iconBlock.ib_yicon,
                        ForegroundColor = (ObjectColors)((iconBlock.ib_char >> 12) & 0x000F),
                        BackgroundColor = (ObjectColors)((iconBlock.ib_char >> 8) & 0x000F),
                        Character       = encoding.GetString(new[] { (byte)(iconBlock.ib_char & 0xFF) })[0],
                        CharX           = iconBlock.ib_xchar,
                        CharY           = iconBlock.ib_ychar,
                        TextX           = iconBlock.ib_xtext,
                        TextY           = iconBlock.ib_ytext,
                        TextWidth       = iconBlock.ib_wtext,
                        TextHeight      = iconBlock.ib_htext,
                        Data            = new byte[isize],
                        Mask            = new byte[isize]
                    }
                };

                resourceStream.Read(colorIcons[i].Monochrome.Data, 0, isize);

                // Because the image is stored as words, they get reversed on PC GEM (Little-endian)
                if (!bigEndian)
                {
                    byte[] data = new byte[colorIcons[i].Monochrome.Data.Length];
                    for (int d = 0; d < data.Length; d += 2)
                    {
                        data[d]     = colorIcons[d].Monochrome.Data[d + 1];
                        data[d + 1] = colorIcons[d].Monochrome.Data[d];
                    }

                    colorIcons[i].Monochrome.Data = data;
                }

                resourceStream.Read(colorIcons[i].Monochrome.Mask, 0, isize);

                // Because the mask is stored as words, they get reversed on PC GEM (Little-endian)
                if (!bigEndian)
                {
                    byte[] mask = new byte[colorIcons[i].Monochrome.Mask.Length];
                    for (int m = 0; m < mask.Length; m += 2)
                    {
                        mask[m]     = colorIcons[m].Monochrome.Mask[m + 1];
                        mask[m + 1] = colorIcons[m].Monochrome.Mask[m];
                    }

                    colorIcons[i].Monochrome.Mask = mask;
                }

                if (iconBlock.ib_ptext > 0 && iconBlock.ib_ptext < resourceStream.Length)
                {
                    long oldPosition = resourceStream.Position;
                    resourceStream.Position = iconBlock.ib_ptext;
                    List <byte> chars = new List <byte>();
                    while (true)
                    {
                        int character = resourceStream.ReadByte();

                        if (character <= 0)
                        {
                            break;
                        }

                        chars.Add((byte)character);
                    }

                    colorIcons[i].Monochrome.Text = StringHandlers.CToString(chars.ToArray(), encoding);
                    resourceStream.Position       = oldPosition + 12;
                }
                else
                {
                    byte[] ptext = new byte[12];
                    resourceStream.Read(ptext, 0, 12);
                    colorIcons[i].Monochrome.Text = StringHandlers.CToString(ptext, encoding);
                }

                colorIcons[i].Color = new ColorIconPlane[numRez];

                for (int r = 0; r < numRez; r++)
                {
                    byte[] data;
                    byte[] mask;

                    buffer = new byte[Marshal.SizeOf(typeof(ColorIconBlock))];
                    resourceStream.Read(buffer, 0, buffer.Length);
                    ColorIconBlock cib = BigEndianMarshal.ByteArrayToStructureBigEndian <ColorIconBlock>(buffer);

                    colorIcons[i].Color[r] = new ColorIconPlane
                    {
                        Planes = cib.num_planes,
                        Data   = new byte[isize * cib.num_planes],
                        Mask   = new byte[isize]
                    };

                    resourceStream.Read(colorIcons[i].Color[r].Data, 0, isize * cib.num_planes);

                    // Because the image is stored as words, they get reversed on PC GEM (Little-endian)
                    if (!bigEndian)
                    {
                        data = new byte[colorIcons[i].Color[r].Data.Length];
                        for (int d = 0; d < data.Length; d += 2)
                        {
                            data[d]     = colorIcons[d].Color[r].Data[d + 1];
                            data[d + 1] = colorIcons[d].Color[r].Data[d];
                        }

                        colorIcons[i].Color[r].Data = data;
                    }

                    resourceStream.Read(colorIcons[i].Color[r].Mask, 0, isize);

                    // Because the mask is stored as words, they get reversed on PC GEM (Little-endian)
                    if (!bigEndian)
                    {
                        mask = new byte[colorIcons[i].Color[r].Mask.Length];
                        for (int m = 0; m < mask.Length; m += 2)
                        {
                            mask[m]     = colorIcons[m].Color[r].Mask[m + 1];
                            mask[m + 1] = colorIcons[m].Color[r].Mask[m];
                        }

                        colorIcons[i].Color[r].Mask = mask;
                    }

                    if (cib.sel_data == 0)
                    {
                        continue;
                    }

                    colorIcons[i].Color[r].SelectedData = new byte[isize * cib.num_planes];
                    colorIcons[i].Color[r].SelectedMask = new byte[isize];

                    resourceStream.Read(colorIcons[i].Color[r].SelectedData, 0, isize * cib.num_planes);

                    // Because the image is stored as words, they get reversed on PC GEM (Little-endian)
                    if (!bigEndian)
                    {
                        data = new byte[colorIcons[i].Color[r].SelectedData.Length];
                        for (int d = 0; d < data.Length; d += 2)
                        {
                            data[d]     = colorIcons[d].Color[r].SelectedData[d + 1];
                            data[d + 1] =
                                colorIcons[d].Color[r].SelectedData[d];
                        }

                        colorIcons[i].Color[r].SelectedData = data;
                    }

                    resourceStream.Read(colorIcons[i].Color[r].SelectedMask, 0, isize);

                    // Because the mask is stored as words, they get reversed on PC GEM (Little-endian)
                    if (bigEndian)
                    {
                        continue;
                    }

                    mask = new byte[colorIcons[i].Color[r].SelectedMask.Length];
                    for (int m = 0; m < mask.Length; m += 2)
                    {
                        mask[m]     = colorIcons[m].Color[r].SelectedMask[m + 1];
                        mask[m + 1] = colorIcons[m].Color[r].SelectedMask[m];
                    }

                    colorIcons[i].Color[r].SelectedMask = mask;
                }
            }

            return(colorIcons);
        }
Ejemplo n.º 7
0
        static Icon GetIconBlock(Stream resourceStream, byte[] buffer, bool bigEndian, Encoding encoding)
        {
            long oldPosition = resourceStream.Position;

            IconBlock iconBlock = bigEndian
                                      ? BigEndianMarshal.ByteArrayToStructureBigEndian <IconBlock>(buffer)
                                      : BigEndianMarshal.ByteArrayToStructureLittleEndian <IconBlock>(buffer);

            Icon icon = new Icon
            {
                Width           = iconBlock.ib_wicon,
                Height          = iconBlock.ib_hicon,
                X               = iconBlock.ib_xicon,
                Y               = iconBlock.ib_yicon,
                ForegroundColor = (ObjectColors)((iconBlock.ib_char >> 12) & 0x000F),
                BackgroundColor = (ObjectColors)((iconBlock.ib_char >> 8) & 0x000F),
                Character       = encoding.GetString(new[] { (byte)(iconBlock.ib_char & 0xFF) })[0],
                CharX           = iconBlock.ib_xchar,
                CharY           = iconBlock.ib_ychar,
                TextX           = iconBlock.ib_xtext,
                TextY           = iconBlock.ib_ytext,
                TextWidth       = iconBlock.ib_wtext,
                TextHeight      = iconBlock.ib_htext
            };

            if (iconBlock.ib_ptext > 0 && iconBlock.ib_ptext < resourceStream.Length)
            {
                resourceStream.Position = iconBlock.ib_ptext;
                List <byte> chars = new List <byte>();
                while (true)
                {
                    int character = resourceStream.ReadByte();

                    if (character <= 0)
                    {
                        break;
                    }

                    chars.Add((byte)character);
                }

                icon.Text = StringHandlers.CToString(chars.ToArray(), encoding);
            }

            if (iconBlock.ib_pdata > 0 && iconBlock.ib_pdata < resourceStream.Length)
            {
                resourceStream.Position = iconBlock.ib_pdata;
                icon.Data = new byte[icon.Width * icon.Height / 8];
                resourceStream.Read(icon.Data, 0, icon.Data.Length);

                // Because the image is stored as words, they get reversed on PC GEM (Little-endian)
                if (!bigEndian)
                {
                    byte[] data = new byte[icon.Data.Length];
                    for (int i = 0; i < data.Length; i += 2)
                    {
                        data[i]     = icon.Data[i + 1];
                        data[i + 1] = icon.Data[i];
                    }

                    icon.Data = data;
                }
            }

            if (iconBlock.ib_pmask > 0 && iconBlock.ib_pmask < resourceStream.Length)
            {
                resourceStream.Position = iconBlock.ib_pmask;
                icon.Mask = new byte[icon.Width * icon.Height / 8];
                resourceStream.Read(icon.Mask, 0, icon.Mask.Length);

                // Because the mask is stored as words, they get reversed on PC GEM (Little-endian)
                if (!bigEndian)
                {
                    byte[] mask = new byte[icon.Mask.Length];
                    for (int i = 0; i < mask.Length; i += 2)
                    {
                        mask[i]     = icon.Mask[i + 1];
                        mask[i + 1] = icon.Mask[i];
                    }

                    icon.Mask = mask;
                }
            }

            resourceStream.Position = oldPosition;
            return(icon);
        }