Beispiel #1
0
            public byte[] CreateIconGroupData(uint iconBaseID)
            {
                // This will store the memory version of the icon.
                int sizeOfIconGroupData = Marshal.SizeOf(typeof(ICONDIR)) +
                                          Marshal.SizeOf(typeof(GRPICONDIRENTRY)) * ImageCount;

                byte[] data       = new byte[sizeOfIconGroupData];
                var    pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);

                Marshal.StructureToPtr(iconDir, pinnedData.AddrOfPinnedObject(), false);
                var offset = Marshal.SizeOf(iconDir);

                for (int i = 0; i <= ImageCount - 1; i++)
                {
                    GRPICONDIRENTRY  grpEntry     = new GRPICONDIRENTRY();
                    BITMAPINFOHEADER bitmapheader = new BITMAPINFOHEADER();
                    var pinnedBitmapInfoHeader    = GCHandle.Alloc(bitmapheader, GCHandleType.Pinned);
                    Marshal.Copy(ImageData(i), 0, pinnedBitmapInfoHeader.AddrOfPinnedObject(),
                                 Marshal.SizeOf(typeof(BITMAPINFOHEADER)));
                    pinnedBitmapInfoHeader.Free();
                    grpEntry.Width      = iconEntry[i].Width;
                    grpEntry.Height     = iconEntry[i].Height;
                    grpEntry.ColorCount = iconEntry[i].ColorCount;
                    grpEntry.Reserved   = iconEntry[i].Reserved;
                    grpEntry.Planes     = bitmapheader.Planes;
                    grpEntry.BitCount   = bitmapheader.BitCount;
                    grpEntry.BytesInRes = iconEntry[i].BytesInRes;
                    grpEntry.ID         = Convert.ToUInt16(iconBaseID + i);
                    Marshal.StructureToPtr(grpEntry, new IntPtr(pinnedData.AddrOfPinnedObject().ToInt64() + offset),
                                           false);
                    offset += Marshal.SizeOf(typeof(GRPICONDIRENTRY));
                }
                pinnedData.Free();
                return(data);
            }
Beispiel #2
0
        public byte[] CreateIconGroupData(uint iconBaseID)
        {
            int sizeOfIconGroupData = Marshal.SizeOf(typeof(ICONDIR)) + Marshal.SizeOf(typeof(GRPICONDIRENTRY)) * IconCount;

            byte[] data = new byte[sizeOfIconGroupData];

            GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);

            Marshal.StructureToPtr(_iconDir, pinnedData.AddrOfPinnedObject(), false);

            int offset = Marshal.SizeOf(_iconDir);
            int size   = Marshal.SizeOf(typeof(GRPICONDIRENTRY));

            for (int i = 0; i < IconCount; i++)
            {
                GRPICONDIRENTRY  grpEntry     = new GRPICONDIRENTRY();
                BITMAPINFOHEADER bitmapHeader = new BITMAPINFOHEADER();

                GCHandle pinnedBitmapInfoHeader = GCHandle.Alloc(bitmapHeader, GCHandleType.Pinned);
                Marshal.Copy(_iconImage[i], 0, pinnedBitmapInfoHeader.AddrOfPinnedObject(), Marshal.SizeOf(typeof(BITMAPINFOHEADER)));

                pinnedBitmapInfoHeader.Free();

                grpEntry.Width      = _iconDirEntry[i].Width;
                grpEntry.Height     = _iconDirEntry[i].Height;
                grpEntry.ColorCount = _iconDirEntry[i].ColorCount;
                grpEntry.Reserved   = _iconDirEntry[i].Reserved;
                grpEntry.Planes     = bitmapHeader.Planes;
                grpEntry.BitCount   = bitmapHeader.BitCount;
                grpEntry.BytesInRes = _iconDirEntry[i].BytesInRes;
                grpEntry.ID         = Convert.ToUInt16(iconBaseID + i);

                Marshal.StructureToPtr(grpEntry, new IntPtr(pinnedData.AddrOfPinnedObject().ToInt64() + offset), false);

                offset += size;
            }

            pinnedData.Free();
            return(data);
        }
Beispiel #3
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);
        }
Beispiel #4
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);
        }
Beispiel #5
0
        public static void ChangeIcon(string exeFilePath, string icoFilePath)
        {
            int len = Marshal.SizeOf(typeof(GRPICONDIR));

            using (FileStream fs = new FileStream(icoFilePath, FileMode.Open, FileAccess.Read))
            {
                // 读取图标目录
                ICONDIR iconDir = fs.Read <ICONDIR>();
                // 读取图标头列表
                List <ICONDIRENTRY> iconDirEntrys = new List <ICONDIRENTRY>();
                for (int i = 0; i < iconDir.idCount; i++)
                {
                    ICONDIRENTRY iconDirEntry = fs.Read <ICONDIRENTRY>();
                    iconDirEntrys.Add(iconDirEntry);
                }
                // 读取图标数据列表
                List <byte[]> iconDatas = new List <byte[]>();
                for (int i = 0; i < iconDir.idCount; i++)
                {
                    byte[] iconData = new byte[iconDirEntrys[i].dwBytesInRes];
                    fs.Seek(iconDirEntrys[i].dwImageOffset, SeekOrigin.Begin);
                    fs.Read(iconData, 0, iconData.Length);
                    iconDatas.Add(iconData);
                }

                // 生成GRPICONDIR
                GRPICONDIR grpIconDir = new GRPICONDIR();
                grpIconDir.idCount    = iconDir.idCount;
                grpIconDir.idReserved = 0;
                grpIconDir.idType     = 1; // 1代表图标

                // 生成List<GRPICONDIRENTRY>
                List <GRPICONDIRENTRY> grpIconDirEntrys = new List <GRPICONDIRENTRY>();
                for (int i = 0; i < iconDirEntrys.Count; i++)
                {
                    GRPICONDIRENTRY grpIconDirEntry = new GRPICONDIRENTRY();
                    grpIconDirEntry.CopyFrom(iconDirEntrys[i]);
                    grpIconDirEntry.nID = (short)(i + 1);
                    grpIconDirEntrys.Add(grpIconDirEntry);
                }
                List <byte> grpData = new List <byte>();
                grpData.AddRange(grpIconDir.ToByteArray());
                for (int i = 0; i < grpIconDirEntrys.Count; i++)
                {
                    grpData.AddRange(grpIconDirEntrys[i].ToByteArray());
                }
                IntPtr grpDataPtr = grpData.ToArray().ToPtr();

                bool   ret        = false;
                IntPtr pUpdateRes = BeginUpdateResource(exeFilePath, false);
                for (int i = 0; i < grpIconDirEntrys.Count; i++)
                {
                    // 更新图标数据
                    int id = grpIconDirEntrys[i].nID;
                    ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_ICON), new IntPtr(id), 0, iconDatas[i].ToPtr(), iconDatas[i].Length);
                }
                // 更新图标目录和图标头
                // 32512为当前exe中Icon Group下id号
                ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_GROUP_ICON), new IntPtr(32512), 0, grpDataPtr, grpData.Count);
                ret = EndUpdateResource(pUpdateRes, false);
            }
        }
Beispiel #6
0
 public byte[] CreateIconGroupData(uint iconBaseID)
 {
     // This will store the memory version of the icon.
     int sizeOfIconGroupData = Marshal.SizeOf(typeof(ICONDIR)) + Marshal.SizeOf(typeof(GRPICONDIRENTRY)) * ImageCount;
     byte[] data = new byte[sizeOfIconGroupData];
     var pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
     Marshal.StructureToPtr(iconDir, pinnedData.AddrOfPinnedObject(), false);
     var offset = Marshal.SizeOf(iconDir);
     for (int i = 0; i <= ImageCount - 1; i++)
     {
         GRPICONDIRENTRY grpEntry = new GRPICONDIRENTRY();
         BITMAPINFOHEADER bitmapheader = new BITMAPINFOHEADER();
         var pinnedBitmapInfoHeader = GCHandle.Alloc(bitmapheader, GCHandleType.Pinned);
         Marshal.Copy(ImageData(i), 0, pinnedBitmapInfoHeader.AddrOfPinnedObject(), Marshal.SizeOf(typeof(BITMAPINFOHEADER)));
         pinnedBitmapInfoHeader.Free();
         grpEntry.Width = iconEntry[i].Width;
         grpEntry.Height = iconEntry[i].Height;
         grpEntry.ColorCount = iconEntry[i].ColorCount;
         grpEntry.Reserved = iconEntry[i].Reserved;
         grpEntry.Planes = bitmapheader.Planes;
         grpEntry.BitCount = bitmapheader.BitCount;
         grpEntry.BytesInRes = iconEntry[i].BytesInRes;
         grpEntry.ID = Convert.ToUInt16(iconBaseID + i);
         Marshal.StructureToPtr(grpEntry, new IntPtr(pinnedData.AddrOfPinnedObject().ToInt64() + offset), false);
         offset += Marshal.SizeOf(typeof(GRPICONDIRENTRY));
     }
     pinnedData.Free();
     return data;
 }