コード例 #1
0
        /// <summary>
        ///     Gets a string with human readable information for a given MZ header
        /// </summary>
        /// <returns>Human readable information for given MZ header.</returns>
        /// <param name="header">MZ executable header.</param>
        static string GetInfo(MZHeader header)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("DOS MZ executable:");
            sb.AppendFormat("\tBlocks in file: {0}", header.blocks_in_file).AppendLine();
            sb.AppendFormat("\t{0} bytes used in last block",
                            header.bytes_in_last_block == 0 ? 512 : header.bytes_in_last_block).AppendLine();
            sb.AppendFormat("\t{0} relocations present after the header", header.num_relocs).AppendLine();
            sb.AppendFormat("\t{0} paragraphs in header", header.header_paragraphs).AppendLine();
            sb.AppendFormat("\t{0} paragraphs of additional memory required", header.min_extra_paragraphs)
            .AppendLine();
            sb.AppendFormat("\t{0} paragraphs of additional memory requested", header.max_extra_paragraphs)
            .AppendLine();
            sb.AppendFormat("\tSegment address for SS: {0:X4}h", header.ss).AppendLine();
            sb.AppendFormat("\tInitial value of SP: {0:X4}h", header.sp).AppendLine();
            sb.AppendFormat("\tInitial value of IP: {0:X4}h", header.ip).AppendLine();
            sb.AppendFormat("\tInitial value of CS: {0:X4}h", header.cs).AppendLine();
            sb.AppendFormat("\tOffset to relocation table: {0}", header.reloc_table_offset).AppendLine();
            sb.AppendFormat("\tFile contains {0} overlays", header.overlay_number).AppendLine();
            sb.AppendFormat("\tFile checksum: 0x{0:X4}", header.checksum).AppendLine();
            sb.AppendFormat("\tOEM ID: {0}", header.oem_id).AppendLine();
            sb.AppendFormat("\tOEM information: 0x{0:X4}", header.oem_info).AppendLine();
            sb.AppendFormat("\tOffset to new header: {0}", header.new_offset).AppendLine();
            return(sb.ToString());
        }
コード例 #2
0
        public FarPtr StartingPointer = new FarPtr(1 + 0x10, 0); //PSP+10h for Segment

        public MZFile(string exeFile)
        {
            Segments          = new List <Segment>();
            RelocationRecords = new List <FarPtr>();

            _exeFile     = exeFile;
            _exeFileData = File.ReadAllBytes(_exeFile);

            _mzHeader = new MZHeader(_exeFileData);

            Load();
        }
コード例 #3
0
ファイル: MZ.cs プロジェクト: claunia/libexeinfo
        /// <summary>
        ///     Identifies if the specified executable is a DOS relocatable executable
        /// </summary>
        /// <returns><c>true</c> if the specified executable is a DOS relocatable executable, <c>false</c> otherwise.</returns>
        /// <param name="stream">Stream containing the executable.</param>
        public static bool Identify(FileStream stream)
        {
            byte[] buffer = new byte[Marshal.SizeOf(typeof(MZHeader))];

            stream.Position = 0;
            stream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            MZHeader mzHdr = (MZHeader)Marshal.PtrToStructure(hdrPtr, typeof(MZHeader));

            Marshal.FreeHGlobal(hdrPtr);

            return(mzHdr.signature == SIGNATURE);
        }
コード例 #4
0
ファイル: MZ.cs プロジェクト: claunia/libexeinfo
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            byte[] buffer = new byte[Marshal.SizeOf(typeof(MZHeader))];

            BaseStream.Position = 0;
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

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

            if (!Recognized)
            {
                return;
            }

            Type = "DOS Executable (MZ)";
            RequiredOperatingSystem = new OperatingSystem {
                Name = "DOS"
            };

            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.ByteArrayToStructureLittleEndian <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;
            }

            RequiredOperatingSystem = new OperatingSystem {
                Name = "PC-GEM"
            };

            if (gemResourceHeader.rsh_vrsn == 3)
            {
                buffer = new byte[Marshal.SizeOf(typeof(GEM.MagiCResourceHeader))];
                ResourceStream.Position = 0;
                ResourceStream.Read(buffer, 0, buffer.Length);
                ResourceHeader =
                    BigEndianMarshal.ByteArrayToStructureLittleEndian <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.ByteArrayToStructureLittleEndian <GEM.GemResourceExtension>(buffer);

                GemColorIcons =
                    GEM.GetColorIcons(ResourceStream, ResourceExtension.color_ic, false, Encoding.GemEncoding);
            }

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

            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, 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.ByteArrayToStructureLittleEndian <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, false,
                                                  Encoding.GemEncoding);
                }
            }
            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.ByteArrayToStructureLittleEndian <GEM.ObjectNode>(buffer);
                }

                List <short> knownNodes = new List <short>();
                ResourceObjectRoots = new GEM.TreeObjectNode[1];
                // TODO: Correct encoding?
                ResourceObjectRoots[0] =
                    GEM.ProcessResourceObject(nodes, ref knownNodes, 0, ResourceStream, strings, false,
                                              Encoding.GemEncoding);
            }

            if (strings.Count > 0)
            {
                strings.Sort();
                Strings = strings.Distinct();
            }
        }
コード例 #5
0
ファイル: NEFile.cs プロジェクト: synacktic/MBBSEmu
        private void Load()
        {
            var data = new Span <byte>(FileContent);

            DOSHeader = new MZHeader(FileContent);

            //Verify old DOS header is correct
            if (DOSHeader.Signature != 23117)
            {
                throw new Exception("Invalid Header");
            }

            //Locate Windows Header
            ushort windowsHeaderOffset;

            if (data[0x18] >= 0x40)
            {
                windowsHeaderOffset = BitConverter.ToUInt16(FileContent, 0x3C);
            }
            else
            {
                throw new Exception("Unable to locate Windows Header location");
            }

            //Load Windows Header
            WindowsHeader = new NEHeader(data.Slice(windowsHeaderOffset, 0x3F).ToArray())
            {
                FileOffset = windowsHeaderOffset
            };

            //Adjust Offsets According to Spec (Offset from beginning of Windows Header, not file)
            WindowsHeader.SegmentTableOffset        += windowsHeaderOffset;
            WindowsHeader.ResourceTableOffset       += windowsHeaderOffset;
            WindowsHeader.ResidentNameTableOffset   += windowsHeaderOffset;
            WindowsHeader.ModleReferenceTableOffset += windowsHeaderOffset;
            WindowsHeader.ImportedNamesTableOffset  += windowsHeaderOffset;
            WindowsHeader.EntryTableOffset          += windowsHeaderOffset;

            //Load Segment Table
            SegmentTable = new List <Segment>(WindowsHeader.SegmentTableEntries);
            for (var i = 0; i < WindowsHeader.SegmentTableEntries; i++)
            {
                //Load Segment Header (8 bytes per record)
                var segment =
                    new Segment(data.Slice(WindowsHeader.SegmentTableOffset + (i * 8), 8).ToArray())
                {
                    Ordinal = (ushort)(i + 1)
                };
                segment.Offset <<= WindowsHeader.LogicalSectorAlignmentShift;

                //Attach Segment Data
                segment.Data = data.Slice((int)segment.Offset, segment.Length).ToArray();

                //Attach Relocation Records
                if (segment.Flags.Contains(EnumSegmentFlags.HasRelocationInfo))
                {
                    var relocationInfoCursor    = (int)segment.Offset + segment.Length;
                    var relocationRecordEntries = BitConverter.ToUInt16(FileContent, relocationInfoCursor);
                    relocationInfoCursor += 2;
                    var records = new Dictionary <ushort, RelocationRecord>();
                    for (var j = 0; j < relocationRecordEntries; j++)
                    {
                        var relocationRecord = new RelocationRecord(_logger)
                        {
                            Data = data.Slice(relocationInfoCursor + j * 8, 8).ToArray()
                        };

                        records.Add(relocationRecord.Offset, relocationRecord);
                    }
                    segment.RelocationRecords = records;
                }
                SegmentTable.Add(segment);
            }

            //Load Resource Table
            //ResourceTable = new List<ResourceRecord>();
            //TODO -- Resource Table isn't used by MBBS modules so we'll skip loading this for now
            //TODO -- Implement this in a future version

            //Load Resident Name Table
            ResidentNameTable = new List <ResidentName>();
            for (var i = 0; i < WindowsHeader.ModleReferenceTableOffset; i += 2)
            {
                var residentName       = new ResidentName();
                var residentNameLength = data[WindowsHeader.ResidentNameTableOffset + i];

                //End of Names
                if (residentNameLength == 0)
                {
                    break;
                }

                i++;
                residentName.Name =
                    Encoding.Default.GetString(data.Slice(WindowsHeader.ResidentNameTableOffset + i, residentNameLength)
                                               .ToArray());
                i += residentNameLength;
                residentName.IndexIntoEntryTable = BitConverter.ToUInt16(FileContent, WindowsHeader.ResidentNameTableOffset + i);
                ResidentNameTable.Add(residentName);
            }

            //Load Module & Imported Name Reference Tables
            ModuleReferenceTable = new List <ModuleReference>(WindowsHeader.ModuleReferenceTableEntries);
            ImportedNameTable    = new Dictionary <ushort, ImportedName>();
            for (var i = 0; i < WindowsHeader.ModuleReferenceTableEntries; i++)
            {
                var nameOffset =
                    BitConverter.ToUInt16(FileContent, WindowsHeader.ModleReferenceTableOffset + i * 2);

                var fileOffset   = (ushort)(nameOffset + WindowsHeader.ImportedNamesTableOffset);
                var module       = new ModuleReference();
                var importedName = new ImportedName()
                {
                    Offset = nameOffset, FileOffset = fileOffset
                };

                var name = Encoding.Default.GetString(data.Slice(fileOffset + 1, data[fileOffset]).ToArray());

                module.Name          = name;
                importedName.Name    = name;
                importedName.Ordinal = (ushort)(i + 1); //Ordinal Index in Resource Tables start with 1

                ModuleReferenceTable.Add(module);
                ImportedNameTable.Add(importedName.Ordinal, importedName);
            }

            //Load Entry Table
            EntryTable = new List <Entry>(data[WindowsHeader.EntryTableOffset]);

            //Value of 0 denotes no segment data
            if (data[WindowsHeader.EntryTableOffset] > 0)
            {
                var    entryByteOffset = 0;
                ushort entryOrdinal    = 1;
                while (WindowsHeader.EntryTableOffset + entryByteOffset < WindowsHeader.NonResidentNameTableOffset)
                {
                    //0xFF is moveable (6 bytes), anything else is fixed as it becomes the segment number
                    var entryCount   = data[WindowsHeader.EntryTableOffset + entryByteOffset];
                    var entrySegment = data[WindowsHeader.EntryTableOffset + entryByteOffset + 1];

                    if (entryCount == 1 && entrySegment == 0)
                    {
                        entryByteOffset += 2;
                        entryOrdinal    += 1;
                        continue;
                    }

                    var entrySize = entrySegment == 0xFF ? 6 : 3;

                    for (var i = 0; i < entryCount; i++)
                    {
                        var entry = new Entry {
                            SegmentNumber = entrySegment
                        };
                        if (entrySize == 3)
                        {
                            entry.Flag   = data[WindowsHeader.EntryTableOffset + entryByteOffset + 2 + entrySize * i];
                            entry.Offset = BitConverter.ToUInt16(FileContent,
                                                                 WindowsHeader.EntryTableOffset + entryByteOffset + 3 + entrySize * i);
                            entry.SegmentNumber = entrySegment;
                            entry.Ordinal       = entryOrdinal; //First Entry is the Resident Name table is the module name, so we shift the ordinals by 1 to line up
                        }
                        else
                        {
                            entry.Flag          = data[WindowsHeader.EntryTableOffset + entryByteOffset + 2 + entrySize * i];
                            entry.SegmentNumber = data[WindowsHeader.EntryTableOffset + entryByteOffset + 5 + (entrySize * i)];
                            entry.Offset        =
                                BitConverter.ToUInt16(FileContent,
                                                      WindowsHeader.EntryTableOffset + entryByteOffset + 6 + entrySize * i);
                        }
                        entryOrdinal++;
                        EntryTable.Add(entry);
                    }

                    entryByteOffset += (entryCount * entrySize) + 2;
                }
            }

            //Load Non-Resident Name Table
            NonResidentNameTable = new List <NonResidentName>();
            for (var i = (int)WindowsHeader.NonResidentNameTableOffset; i < (WindowsHeader.NonResidentNameTableOffset + WindowsHeader.NonResidentNameTableLength); i += 2)
            {
                var nameLength = data[i];
                i++;
                var name = Encoding.Default.GetString(data.Slice(i, nameLength).ToArray());
                i += nameLength;
                var indexIntoEntryTable = BitConverter.ToUInt16(FileContent, i);
                NonResidentNameTable.Add(new NonResidentName()
                {
                    Name = name, IndexIntoEntryTable = indexIntoEntryTable
                });
            }
        }
コード例 #6
0
 public MZResult(MZHeader header)
 {
     RawData         = StructConverter.GetBytes(header);
     NewHeaderOffset = header.NewHeaderRVA;
 }
コード例 #7
0
 public unsafe IMZResult Package(IMZInfo param) => new MZResult(MZHeader.CreateWithDefaultStub((uint)sizeof(MZHeader)));