Last active
September 19, 2017 23:51
-
-
Save fliedonion/382f2691592af48cb8535463667a75e2 to your computer and use it in GitHub Desktop.
Load Icon Data From File. Sideline of my other program using UpdateResource.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
// https://stackoverflow.com/a/36795367 | |
// http://schima.hatenablog.com/entry/20090512/1242139542 | |
// https://blogs.msdn.microsoft.com/oldnewthing/20120720-00/?p=7083 | |
namespace IconLoadToStruct { | |
class IconLoader { | |
List<IconStore> LoadIcons(string iconFilename) { | |
var icons = new List<IconStore>(); | |
var stream = File.OpenRead(iconFilename); | |
using (var br = new BinaryReader(stream)) { | |
var header = LoadToValueClass<IconFileHeader>(br); | |
if (header.Type != 1) { | |
throw new Exception($"Invalid type. expected 1 but {header.Type}"); | |
} | |
for (var i = 0; i < header.NumOfImages; i++) { | |
var dest = LoadToValueClass<IconBasicInfo>(br); | |
Console.WriteLine("bps = {0}, w:{1} h:{2}, offset:{3}", dest.BitsPerPixel, dest.Width == 0 ? 256 : dest.Width, dest.Height == 0 ? 256 : dest.Height, dest.Offset); | |
icons.Add(new IconStore { | |
Info = dest, | |
}); | |
} | |
foreach (var icon in icons) { | |
if (br.BaseStream.Position < icon.Info.Offset) { | |
// skip to offset pos | |
br.ReadBytes((int)(icon.Info.Offset - br.BaseStream.Position)); | |
} | |
icon.ImageData = br.ReadBytes((int)icon.Info.DataSize); | |
} | |
} | |
return icons; | |
} | |
T LoadToValueClass<T>(BinaryReader br) where T : new() { | |
var dest = new T(); | |
var size = Marshal.SizeOf(dest); | |
IntPtr pBytes = Marshal.AllocHGlobal(size); | |
Marshal.Copy(br.ReadBytes(size), 0, pBytes, size); | |
Marshal.PtrToStructure<T>(pBytes, dest); | |
Marshal.FreeHGlobal(pBytes); | |
return dest; | |
} | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public class IconFileHeader { | |
public ushort Reserved0; | |
public ushort Type; // .ico 0, .cur 2 | |
public ushort NumOfImages; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public class IconBasicInfo { | |
public byte Width; | |
public byte Height; | |
public byte Colors; | |
public byte Reserved0; | |
public ushort ColorPlanes; | |
public ushort BitsPerPixel; | |
public uint DataSize; | |
public uint Offset; | |
} | |
public class IconStore { | |
public IconBasicInfo Info; | |
public byte[] ImageData; | |
} | |
public static class IconStoreListExt { | |
public static byte[] ToGroupData(this List<IconStore> list, int startNId = 1) { | |
using (var ms = new MemoryStream()) | |
using (var writer = new BinaryWriter(ms)) { | |
var i = 0; | |
writer.Write((ushort)0); // reserved | |
writer.Write((ushort)1); // icon | |
writer.Write((ushort)list.Count); // number of icons | |
foreach (var icon in list) { | |
writer.Write(icon.Info.Width); | |
writer.Write(icon.Info.Height); | |
writer.Write(icon.Info.Colors); | |
writer.Write((byte)0); // reserved, must be 0 | |
writer.Write(icon.Info.ColorPlanes); | |
writer.Write(icon.Info.BitsPerPixel); | |
writer.Write(icon.Info.DataSize); | |
writer.Write((ushort)(startNId + i)); // nId | |
i++; | |
} | |
return ms.ToArray(); | |
} | |
//typedef struct GRPICONDIR { | |
// WORD idReserved; | |
// WORD idType; | |
// WORD idCount; | |
// GRPICONDIRENTRY idEntries[]; | |
//} GRPICONDIR; | |
//typedef struct GRPICONDIRENTRY { | |
// BYTE bWidth; | |
// BYTE bHeight; | |
// BYTE bColorCount; | |
// BYTE bReserved; | |
// WORD wPlanes; | |
// WORD wBitCount; | |
// DWORD dwBytesInRes; | |
// WORD nId; | |
//} GRPICONDIRENTRY; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace IconResource { | |
public class Native { | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern int UpdateResource(IntPtr hUpdate, uint lpType, ushort lpName, ushort wLanguage, byte[] lpData, uint cbData); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard); | |
public const uint RT_ICON = 3; | |
public const uint RT_GROUP_ICON = 14; | |
public const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002; | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern bool FreeLibrary(IntPtr hModule); | |
[DllImport("kernel32.dll")] | |
static extern bool EnumResourceNames(IntPtr hModule, string lpszType, EnumResNameProcDelegate lpEnumFunc, IntPtr lParam); | |
[DllImport("kernel32.dll")] | |
static extern bool EnumResourceNames(IntPtr hModule, int dwID, EnumResNameProcDelegate lpEnumFunc, IntPtr lParam); | |
delegate bool EnumResNameProcDelegate(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam); | |
enum ResType { | |
CURSOR = 1, | |
BITMAP = 2, | |
ICON = 3, | |
MENU = 4, | |
DIALOG = 5, | |
STRING = 6, | |
FONTDIR = 7, | |
FONT = 8, | |
ACCELERATOR = 9, | |
RCDATA = 10, | |
MESSAGETABLE = 11, | |
GROUP_CURSOR = 12, | |
GROUP_ICON = 14, | |
VERSION = 16, | |
DLGINCLUDE = 17, | |
PLUGPLAY = 19, | |
VXD = 20, | |
ANICURSOR = 21, | |
ANIICON = 22, | |
HTML = 23, | |
MANIFEST = 24 | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
// https://stackoverflow.com/a/36795367 | |
// http://schima.hatenablog.com/entry/20090512/1242139542 | |
// https://blogs.msdn.microsoft.com/oldnewthing/20120720-00/?p=7083 | |
namespace IconLoadToStruct { | |
class Program { | |
static void Main(string[] args) { | |
var icons = new Program().Load("app.ico"); | |
Console.ReadKey(); | |
} | |
List<IconStore> Load(string iconFilename) { | |
var icons = new List<IconStore>(); | |
var stream = File.OpenRead(iconFilename); | |
using (var br = new BinaryReader(stream)) { | |
var header = LoadToValueClass<IconFileHeader>(br); | |
if(header.Type != 1) { | |
throw new Exception($"Invalid type. expected 1 but {header.Type}"); | |
} | |
for (var i = 0; i < header.NumOfImages; i++) { | |
var dest = LoadToValueClass<IconBasicInfo>(br); | |
Console.WriteLine("bps = {0}, w:{1} h:{2}, offset:{3}", dest.BitsPerPixel, dest.Width == 0 ? 256 : dest.Width, dest.Height == 0 ? 256 : dest.Height, dest.Offset); | |
icons.Add(new IconStore { | |
Info = dest, | |
}); | |
} | |
foreach (var icon in icons) { | |
if (br.BaseStream.Position < icon.Info.Offset) { | |
// skip to offset pos | |
br.ReadBytes((int)(icon.Info.Offset - br.BaseStream.Position)); | |
} | |
icon.ImageData = br.ReadBytes((int)icon.Info.DataSize); | |
} | |
} | |
return icons; | |
} | |
T LoadToValueClass<T>(BinaryReader br) where T : new(){ | |
var dest = new T(); | |
var size = Marshal.SizeOf(dest); | |
IntPtr pBytes = Marshal.AllocHGlobal(size); | |
Marshal.Copy(br.ReadBytes(size), 0, pBytes, size); | |
Marshal.PtrToStructure<T>(pBytes, dest); | |
Marshal.FreeHGlobal(pBytes); | |
return dest; | |
} | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public class IconFileHeader { | |
public ushort Reserved0; | |
public ushort Type; // .ico 0, .cur 2 | |
public ushort NumOfImages; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public class IconBasicInfo { | |
public byte Width; | |
public byte Height; | |
public byte Colors; | |
public byte Reserved0; | |
public ushort ColorPlanes; | |
public ushort BitsPerPixel; | |
public uint DataSize; | |
public uint Offset; | |
} | |
public class IconStore { | |
public IconBasicInfo Info; | |
public byte[] ImageData; | |
} | |
public static class IconStoreListExt { | |
public static byte[] ToGroupData(this List<IconStore> list, int startNId = 1) { | |
using (var ms = new MemoryStream()) | |
using (var writer = new BinaryWriter(ms)) { | |
var i = 0; | |
writer.Write((ushort)0); // reserved | |
writer.Write((ushort)1); // icon | |
writer.Write((ushort)list.Count); // number of icons | |
foreach (var icon in list) { | |
writer.Write(icon.Info.Width); | |
writer.Write(icon.Info.Height); | |
writer.Write(icon.Info.Colors); | |
writer.Write((byte)0); // reserved, must be 0 | |
writer.Write(icon.Info.ColorPlanes); | |
writer.Write(icon.Info.BitsPerPixel); | |
writer.Write(icon.Info.DataSize); | |
writer.Write((ushort)(startNId + i)); // nId | |
i++; | |
} | |
return ms.ToArray(); | |
} | |
//typedef struct GRPICONDIR { | |
// WORD idReserved; | |
// WORD idType; | |
// WORD idCount; | |
// GRPICONDIRENTRY idEntries[]; | |
//} GRPICONDIR; | |
//typedef struct GRPICONDIRENTRY { | |
// BYTE bWidth; | |
// BYTE bHeight; | |
// BYTE bColorCount; | |
// BYTE bReserved; | |
// WORD wPlanes; | |
// WORD wBitCount; | |
// DWORD dwBytesInRes; | |
// WORD nId; | |
//} GRPICONDIRENTRY; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace IconResource { | |
class Program { | |
static void Main(string[] args) { | |
IntPtr hModule = Native.LoadLibraryEx("app.exe", IntPtr.Zero, Native.LOAD_LIBRARY_AS_DATAFILE); | |
if(hModule != IntPtr.Zero) { | |
try { | |
Native. | |
} finally { | |
Native.FreeLibrary(hModule); | |
} | |
} | |
} | |
public enum ICResult { | |
Success, | |
FailBegin, | |
FailUpdate, | |
FailEnd | |
} | |
//public ICResult ChangeIcon(string exeFilePath, string iconFilePath) { | |
// using (FileStream fs = new FileStream(iconFilePath, FileMode.Open, FileAccess.Read)) { | |
// var reader = new IconReader(fs); | |
// var iconChanger = new IconChanger(); | |
// return iconChanger.ChangeIcon(exeFilePath, reader.Icons); | |
// } | |
//} | |
//public ICResult ChangeIcon(string exeFilePath, Icons icons) { | |
// // Load executable | |
// IntPtr handleExe = Native.BeginUpdateResource(exeFilePath, false); | |
// if (handleExe == null) return ICResult.FailBegin; | |
// ushort startindex = 1; | |
// ushort index = startindex; | |
// ICResult result = ICResult.Success; | |
// var ret = 1; | |
// foreach (var icon in icons) { | |
// // Replace the icon | |
// // todo :Improve the return value handling of UpdateResource | |
// ret = Native.UpdateResource(handleExe, Native.RT_ICON, index, 0, icon.Data, icon.Size); | |
// index++; | |
// } | |
// var groupdata = icons.ToGroupData(); | |
// // todo :Improve the return value handling of UpdateResource | |
// ret = Native.UpdateResource(handleExe, Native.RT_GROUP_ICON, startindex, 0, groupdata, (uint)groupdata.Length); | |
// if (ret == 1) { | |
// if (EndUpdateResource(handleExe, false)) | |
// result = ICResult.Success; | |
// else | |
// result = ICResult.FailEnd; | |
// } else | |
// result = ICResult.FailUpdate; | |
// return result; | |
//} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment