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); }
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); }
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); }
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); }
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); } }
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; }