예제 #1
0
파일: NEFormat.cs 프로젝트: JGTM2016/bdhero
        public unsafe void Save(MultiIcon multiIcon, Stream stream)
        {
            //Lets prepare the complete file in memory, then we dump everything to a file
            IMAGE_DOS_HEADER    dos_header      = new IMAGE_DOS_HEADER();
            IMAGE_OS2_HEADER    os2_header      = new IMAGE_OS2_HEADER();
            RESOURCE_TABLE      resource_table  = new RESOURCE_TABLE();
            TYPEINFO            rscTypes_Group  = new TYPEINFO();
            TYPEINFO            rscTypes_Icon   = new TYPEINFO();
            TNAMEINFO[]         nameInfos_Group;
            TNAMEINFO[]         nameInfos_Icon;
            byte[]              resourceNames;
            List<GRPICONDIR>    groupIcons      = new List<GRPICONDIR>();
            Dictionary<ushort, IconImage> icons = new Dictionary<ushort,IconImage>();

            int offset = 0;

            // Lets set the MS DOS header
            dos_header.e_magic                  = (int) HeaderSignatures.IMAGE_DOS_SIGNATURE; // MZ
            dos_header.e_lfanew                 = 144; // NE Header location.
            dos_header.e_cblp                   = 80;
            dos_header.e_cp                     = 2;
            dos_header.e_cparhdr                = 4;
            dos_header.e_lfarlc                 = 64;
            dos_header.e_maxalloc               = 65535;
            dos_header.e_minalloc               = 15;
            dos_header.e_sp                     = 184;
            offset += (int) dos_header.e_lfanew;

            // Lets set the NE header
            os2_header.ne_magic                 = (int) HeaderSignatures.IMAGE_OS2_SIGNATURE; // NE
            os2_header.ne_ver                   = 71; 
            os2_header.ne_rev                   = 70; 
            os2_header.ne_enttab                = 178;
            os2_header.ne_cbenttab              = 10;
            os2_header.ne_crc                   = 0;
            os2_header.ne_flags                 = 33545;
            os2_header.ne_autodata              = 3;
            os2_header.ne_heap                  = 1024;
            os2_header.ne_stack                 = 0;
            os2_header.ne_csip                  = 65536;
            os2_header.ne_sssp                  = 0;
            os2_header.ne_cseg                  = 0;  // Entries in Segment Table
            os2_header.ne_cmod                  = 1;
            os2_header.ne_cbnrestab             = 26;
            os2_header.ne_segtab                = 64; // Offset to Segment Table
            os2_header.ne_rsrctab               = 64; // Offset to Resource Table
            os2_header.ne_restab                = 132;// Later will be overwriten
            os2_header.ne_modtab                = 168;
            os2_header.ne_imptab                = 170;
            os2_header.ne_nrestab               = 332;
            os2_header.ne_cmovent               = 1;
            os2_header.ne_align                 = SHIFT_FACTOR;
            os2_header.ne_cres                  = 0;
            os2_header.ne_exetyp                = 2; // OS target = Windows.
            os2_header.ne_flagsothers           = 0;
            os2_header.ne_pretthunks            = 0;
            os2_header.ne_psegrefbytes          = 0;
            os2_header.ne_swaparea              = 0;
            os2_header.ne_expver                = 768;  // OS version = 300
            offset += os2_header.ne_rsrctab;

            // Resoruce Table
            resource_table.rscAlignShift        = SHIFT_FACTOR; // 9 for now, lets split the entries every 512 bytes;
            offset += 2; // rscAlignShift

            // Type Info Groups
            rscTypes_Group.rtTypeID             = 0x8000 + (ushort) ResourceType.RT_GROUP_ICON;
            rscTypes_Group.rtResourceCount      = (ushort) multiIcon.Count;
            offset += 8; // rtTypeID + rtResourceCount + rtReserved
            nameInfos_Group                     = new TNAMEINFO[multiIcon.Count];
            offset += sizeof(TNAMEINFO) * multiIcon.Count;

            // Type Info Icons
            int iconCounter = 0;
            foreach(SingleIcon singleIcon in multiIcon)
                iconCounter += singleIcon.Count;
            rscTypes_Icon.rtTypeID              = 0x8000 + (ushort) ResourceType.RT_ICON;
            rscTypes_Icon.rtResourceCount       = (ushort) iconCounter;
            offset += 8; // rtTypeID + rtResourceCount + rtReserved
            nameInfos_Icon                      = new TNAMEINFO[iconCounter];
            offset += sizeof(TNAMEINFO) * iconCounter;

            resource_table.rscEndTypes = 0;
            offset += 2; // rscEndTypes

            // Resource Names
            os2_header.ne_restab = (ushort) (offset - dos_header.e_lfanew);
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write("ICL");
            foreach(SingleIcon singleIcon in multiIcon)
                bw.Write(singleIcon.Name);
            resourceNames = new byte[ms.Length];
            Array.Copy(ms.GetBuffer(), resourceNames, resourceNames.Length);
            ms.Dispose();
            offset += resourceNames.Length + 1; //resourceNames + rscEndNames

            // Here is the offset where we are going to start writting the directory
            int shiftOffset = (offset >> resource_table.rscAlignShift) + 1;

            // Name Infos Group
            int iconIndex = 0;
            for(int i=0; i<multiIcon.Count; i++)
            {
                SingleIcon singleIcon   = multiIcon[i];
                GRPICONDIR groupIconDir = new GRPICONDIR();
                groupIconDir.idCount    = (ushort) singleIcon.Count;
                groupIconDir.idType     = (ushort) ResourceType.RT_GROUP_ICON;

                // Name Infos Icons
                GRPICONDIRENTRY[] goupIconDirEntries = new GRPICONDIRENTRY[singleIcon.Count];
                for(int j=0; j<singleIcon.Count; j++)
                {
                    
                    nameInfos_Icon[iconIndex].rnFlags   = (ushort) (ResourceMemoryType.Moveable | ResourceMemoryType.Pure | ResourceMemoryType.Unknown);
                    nameInfos_Icon[iconIndex].rnHandle  = 0;
                    nameInfos_Icon[iconIndex].rnID      = (ushort) (0x8000 + iconIndex + 1);
                    nameInfos_Icon[iconIndex].rnUsage   = 0;
                    nameInfos_Icon[iconIndex].rnOffset  = (ushort) shiftOffset;
                    nameInfos_Icon[iconIndex].rnLength  = (ushort) Math.Ceiling(singleIcon[j].IconImageSize / (float) (1 << resource_table.rscAlignShift));
                    shiftOffset += nameInfos_Icon[iconIndex].rnLength;

                    goupIconDirEntries[j]       = singleIcon[j].GRPICONDIRENTRY;
                    goupIconDirEntries[j].nID   = (ushort) (iconIndex + 1);

                    icons.Add((ushort) (iconIndex + 1), singleIcon[j]);
                    iconIndex++;
                }

                nameInfos_Group[i].rnFlags   = (ushort) (ResourceMemoryType.Moveable | ResourceMemoryType.Pure | ResourceMemoryType.Unknown);
                nameInfos_Group[i].rnHandle  = 0;
                nameInfos_Group[i].rnID      = (ushort) (0x8000 + i + 1);
                nameInfos_Group[i].rnUsage   = 0;
                nameInfos_Group[i].rnOffset  = (ushort) shiftOffset;
                nameInfos_Group[i].rnLength  = (ushort) Math.Ceiling((6 + singleIcon.Count * sizeof(GRPICONDIRENTRY)) / (float) (1 << resource_table.rscAlignShift));
                groupIconDir.idEntries = goupIconDirEntries;
                groupIcons.Add(groupIconDir);

                shiftOffset += nameInfos_Group[i].rnLength;
            }

            resource_table.rscTypes                 = new TYPEINFO[2];
            resource_table.rscTypes[0]              = rscTypes_Group;
            resource_table.rscTypes[0].rtNameInfo   = nameInfos_Group;
            resource_table.rscTypes[1]              = rscTypes_Icon;
            resource_table.rscTypes[1].rtNameInfo   = nameInfos_Icon;
            resource_table.rscResourceNames = resourceNames;

            // HERE WE GO TO THE FS...

            // Lets write the MS DOS header
            dos_header.Write(stream);

            // Lets write first Bin segment
            stream.Write(MSDOS_STUB, 0, MSDOS_STUB.Length);

            // Lets position over where the "NE" header will be
            stream.Seek(dos_header.e_lfanew, SeekOrigin.Begin);

            // Lets write the NE header
            os2_header.Write(stream);

            // Lets position over the "Resource Table"
            stream.Seek(os2_header.ne_rsrctab + dos_header.e_lfanew, SeekOrigin.Begin);

            // Lets write the "Resource Table"
            resource_table.Write(stream);

            // Now write the Icons Directory
            resource_table.SetGroupIcons(stream, groupIcons);

            // And the Images...
            resource_table.SetIcons(stream, icons);
        }
예제 #2
0
        public unsafe void Save(MultiIcon multiIcon, Stream stream)
        {
            //Lets prepare the complete file in memory, then we dump everything to a file
            IMAGE_DOS_HEADER dos_header     = new IMAGE_DOS_HEADER();
            IMAGE_OS2_HEADER os2_header     = new IMAGE_OS2_HEADER();
            RESOURCE_TABLE   resource_table = new RESOURCE_TABLE();
            TYPEINFO         rscTypes_Group = new TYPEINFO();
            TYPEINFO         rscTypes_Icon  = new TYPEINFO();

            TNAMEINFO[]       nameInfos_Group;
            TNAMEINFO[]       nameInfos_Icon;
            byte[]            resourceNames;
            List <GRPICONDIR> groupIcons         = new List <GRPICONDIR>();
            Dictionary <ushort, IconImage> icons = new Dictionary <ushort, IconImage>();

            int offset = 0;

            // Lets set the MS DOS header
            dos_header.e_magic    = (int)HeaderSignatures.IMAGE_DOS_SIGNATURE; // MZ
            dos_header.e_lfanew   = 144;                                       // NE Header location.
            dos_header.e_cblp     = 80;
            dos_header.e_cp       = 2;
            dos_header.e_cparhdr  = 4;
            dos_header.e_lfarlc   = 64;
            dos_header.e_maxalloc = 65535;
            dos_header.e_minalloc = 15;
            dos_header.e_sp       = 184;
            offset += (int)dos_header.e_lfanew;

            // Lets set the NE header
            os2_header.ne_magic        = (int)HeaderSignatures.IMAGE_OS2_SIGNATURE;           // NE
            os2_header.ne_ver          = 71;
            os2_header.ne_rev          = 70;
            os2_header.ne_enttab       = 178;
            os2_header.ne_cbenttab     = 10;
            os2_header.ne_crc          = 0;
            os2_header.ne_flags        = 33545;
            os2_header.ne_autodata     = 3;
            os2_header.ne_heap         = 1024;
            os2_header.ne_stack        = 0;
            os2_header.ne_csip         = 65536;
            os2_header.ne_sssp         = 0;
            os2_header.ne_cseg         = 0;           // Entries in Segment Table
            os2_header.ne_cmod         = 1;
            os2_header.ne_cbnrestab    = 26;
            os2_header.ne_segtab       = 64;          // Offset to Segment Table
            os2_header.ne_rsrctab      = 64;          // Offset to Resource Table
            os2_header.ne_restab       = 132;         // Later will be overwriten
            os2_header.ne_modtab       = 168;
            os2_header.ne_imptab       = 170;
            os2_header.ne_nrestab      = 332;
            os2_header.ne_cmovent      = 1;
            os2_header.ne_align        = SHIFT_FACTOR;
            os2_header.ne_cres         = 0;
            os2_header.ne_exetyp       = 2;          // OS target = Windows.
            os2_header.ne_flagsothers  = 0;
            os2_header.ne_pretthunks   = 0;
            os2_header.ne_psegrefbytes = 0;
            os2_header.ne_swaparea     = 0;
            os2_header.ne_expver       = 768;           // OS version = 300
            offset += os2_header.ne_rsrctab;

            // Resoruce Table
            resource_table.rscAlignShift = SHIFT_FACTOR; // 9 for now, lets split the entries every 512 bytes;
            offset += 2;                                 // rscAlignShift

            // Type Info Groups
            rscTypes_Group.rtTypeID        = 0x8000 + (ushort)ResourceType.RT_GROUP_ICON;
            rscTypes_Group.rtResourceCount = (ushort)multiIcon.Count;
            offset         += 8; // rtTypeID + rtResourceCount + rtReserved
            nameInfos_Group = new TNAMEINFO[multiIcon.Count];
            offset         += sizeof(TNAMEINFO) * multiIcon.Count;

            // Type Info Icons
            int iconCounter = 0;

            foreach (SingleIcon singleIcon in multiIcon)
            {
                iconCounter += singleIcon.Count;
            }
            rscTypes_Icon.rtTypeID        = 0x8000 + (ushort)ResourceType.RT_ICON;
            rscTypes_Icon.rtResourceCount = (ushort)iconCounter;
            offset        += 8; // rtTypeID + rtResourceCount + rtReserved
            nameInfos_Icon = new TNAMEINFO[iconCounter];
            offset        += sizeof(TNAMEINFO) * iconCounter;

            resource_table.rscEndTypes = 0;
            offset += 2; // rscEndTypes

            // Resource Names
            os2_header.ne_restab = (ushort)(offset - dos_header.e_lfanew);
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);

            bw.Write("ICL");
            foreach (SingleIcon singleIcon in multiIcon)
            {
                bw.Write(singleIcon.Name);
            }
            resourceNames = new byte[ms.Length];
            Array.Copy(ms.GetBuffer(), resourceNames, resourceNames.Length);
            ms.Dispose();
            offset += resourceNames.Length + 1; //resourceNames + rscEndNames

            // Here is the offset where we are going to start writting the directory
            int shiftOffset = (offset >> resource_table.rscAlignShift) + 1;

            // Name Infos Group
            int iconIndex = 0;

            for (int i = 0; i < multiIcon.Count; i++)
            {
                SingleIcon singleIcon   = multiIcon[i];
                GRPICONDIR groupIconDir = new GRPICONDIR();
                groupIconDir.idCount = (ushort)singleIcon.Count;
                groupIconDir.idType  = (ushort)ResourceType.RT_GROUP_ICON;

                // Name Infos Icons
                GRPICONDIRENTRY[] goupIconDirEntries = new GRPICONDIRENTRY[singleIcon.Count];
                for (int j = 0; j < singleIcon.Count; j++)
                {
                    nameInfos_Icon[iconIndex].rnFlags  = (ushort)(ResourceMemoryType.Moveable | ResourceMemoryType.Pure | ResourceMemoryType.Unknown);
                    nameInfos_Icon[iconIndex].rnHandle = 0;
                    nameInfos_Icon[iconIndex].rnID     = (ushort)(0x8000 + iconIndex + 1);
                    nameInfos_Icon[iconIndex].rnUsage  = 0;
                    nameInfos_Icon[iconIndex].rnOffset = (ushort)shiftOffset;
                    nameInfos_Icon[iconIndex].rnLength = (ushort)Math.Ceiling(singleIcon[j].IconImageSize / (float)(1 << resource_table.rscAlignShift));
                    shiftOffset += nameInfos_Icon[iconIndex].rnLength;

                    goupIconDirEntries[j]     = singleIcon[j].GRPICONDIRENTRY;
                    goupIconDirEntries[j].nID = (ushort)(iconIndex + 1);

                    icons.Add((ushort)(iconIndex + 1), singleIcon[j]);
                    iconIndex++;
                }

                nameInfos_Group[i].rnFlags  = (ushort)(ResourceMemoryType.Moveable | ResourceMemoryType.Pure | ResourceMemoryType.Unknown);
                nameInfos_Group[i].rnHandle = 0;
                nameInfos_Group[i].rnID     = (ushort)(0x8000 + i + 1);
                nameInfos_Group[i].rnUsage  = 0;
                nameInfos_Group[i].rnOffset = (ushort)shiftOffset;
                nameInfos_Group[i].rnLength = (ushort)Math.Ceiling((6 + singleIcon.Count * sizeof(GRPICONDIRENTRY)) / (float)(1 << resource_table.rscAlignShift));
                groupIconDir.idEntries      = goupIconDirEntries;
                groupIcons.Add(groupIconDir);

                shiftOffset += nameInfos_Group[i].rnLength;
            }

            resource_table.rscTypes               = new TYPEINFO[2];
            resource_table.rscTypes[0]            = rscTypes_Group;
            resource_table.rscTypes[0].rtNameInfo = nameInfos_Group;
            resource_table.rscTypes[1]            = rscTypes_Icon;
            resource_table.rscTypes[1].rtNameInfo = nameInfos_Icon;
            resource_table.rscResourceNames       = resourceNames;

            // HERE WE GO TO THE FS...

            // Lets write the MS DOS header
            dos_header.Write(stream);

            // Lets write first Bin segment
            stream.Write(MSDOS_STUB, 0, MSDOS_STUB.Length);

            // Lets position over where the "NE" header will be
            stream.Seek(dos_header.e_lfanew, SeekOrigin.Begin);

            // Lets write the NE header
            os2_header.Write(stream);

            // Lets position over the "Resource Table"
            stream.Seek(os2_header.ne_rsrctab + dos_header.e_lfanew, SeekOrigin.Begin);

            // Lets write the "Resource Table"
            resource_table.Write(stream);

            // Now write the Icons Directory
            resource_table.SetGroupIcons(stream, groupIcons);

            // And the Images...
            resource_table.SetIcons(stream, icons);
        }