Archive Browser
Download Cyotek.ArcadeExplosionMaker.zip version 1.0.0.1, last updated 05/06/2012 (123.69 KB)
Download- md5: bd412009442f7923a555ba5b0f508fe0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
// http://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files
namespace TKageyu.Utils
{
internal class IconExtractor : IDisposable
{
#region Nested Classes
private class IconResInfo
{
#region Public Member Declarations
public List<ResourceName> IconNames = new List<ResourceName>();
#endregion Public Member Declarations
}
private class ResourceName
{
#region Private Member Declarations
private IntPtr _bufPtr = IntPtr.Zero;
#endregion Private Member Declarations
#region Public Constructors
public ResourceName(IntPtr lpName)
{
if (((uint)lpName >> 16) == 0) // #define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0)
{
this.Id = lpName;
this.Name = null;
}
else
{
this.Id = IntPtr.Zero;
this.Name = Marshal.PtrToStringAuto(lpName);
}
}
#endregion Public Constructors
#region Public Methods
public void Free()
{
if (this._bufPtr != IntPtr.Zero)
{
try { Marshal.FreeHGlobal(this._bufPtr); }
catch { }
this._bufPtr = IntPtr.Zero;
}
}
public IntPtr GetValue()
{
if (this.Name == null)
{
return this.Id;
}
else
{
this._bufPtr = Marshal.StringToHGlobalAuto(this.Name);
return this._bufPtr;
}
}
#endregion Public Methods
#region Public Properties
public IntPtr Id { get; private set; }
public string Name { get; private set; }
#endregion Public Properties
}
#endregion Nested Classes
#region Private Member Declarations
private string _filename = null;
private IntPtr _hModule = IntPtr.Zero;
private Icon[] _iconCache = null;
private IconResInfo _resInfo = null;
private const int ERROR_BAD_EXE_FORMAT = 193;
private const int ERROR_FILE_NOT_FOUND = 2;
private const int ERROR_RESOURCE_TYPE_NOT_FOUND = 1813;
private const int ERROR_SUCCESS = 0;
private const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private const int MAX_PATH = 260;
private const int RT_GROUP_ICON = 14;
private const int RT_ICON = 3;
// sizeof(ICONDIRENTRY)
private const int sGRPICONDIRENTRY = 14;
private const int sICONDIR = 6;
// sizeof(ICONDIR)
private const int sICONDIRENTRY = 16;
#endregion Private Member Declarations
#region Public Constructors
/// <summary>
/// Load the specified executable file or DLL, and get ready to extract the icons.
/// </summary>
/// <param name="filename">The name of a file from which icons will be extracted.</param>
public IconExtractor(string filename)
{
if (filename == null)
{
throw new ArgumentNullException("filename");
}
this._hModule = LoadLibrary(filename);
if (this._hModule == IntPtr.Zero)
{
this._hModule = LoadLibraryEx(filename, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
if (this._hModule == IntPtr.Zero)
{
switch (Marshal.GetLastWin32Error())
{
case ERROR_FILE_NOT_FOUND:
throw new FileNotFoundException("Specified file '" + filename + "' not found.");
case ERROR_BAD_EXE_FORMAT:
throw new ArgumentException("Specified file '" + filename + "' is not an executable file or DLL.");
default:
throw new Win32Exception();
}
}
}
StringBuilder buf = new StringBuilder(MAX_PATH);
int len = GetModuleFileName(this._hModule, buf, buf.Capacity + 1);
if (len != 0)
{
this._filename = buf.ToString();
}
else
{
switch (Marshal.GetLastWin32Error())
{
case ERROR_SUCCESS:
this._filename = filename;
break;
default:
throw new Win32Exception();
}
}
this._resInfo = new IconResInfo();
bool success = EnumResourceNames(this._hModule, RT_GROUP_ICON, EnumResNameCallBack, this._resInfo);
if (!success)
{
throw new Win32Exception();
}
this._iconCache = new Icon[this.IconCount];
}
#endregion Public Constructors
#region Private Constructors
~IconExtractor()
{
Dispose();
}
#endregion Private Constructors
#region Delegates
[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Auto)]
private delegate bool EnumResNameProc(IntPtr hModule, int lpszType, IntPtr lpszName, IconResInfo lParam);
#endregion Delegates
#region Public Class Methods
/// <summary>
/// Split an Icon consists of multiple icons into an array of Icon each consist of single icons.
/// </summary>
/// <param name="icon">The System.Drawing.Icon to be split.</param>
/// <returns>An array of System.Drawing.Icon each consist of single icons.</returns>
public static Icon[] SplitIcon(Icon icon)
{
if (icon == null)
{
throw new ArgumentNullException("icon");
}
// Get multiple .ico file image.
byte[] srcBuf = null;
using (MemoryStream stream = new MemoryStream())
{
icon.Save(stream);
srcBuf = stream.ToArray();
}
List<Icon> splitIcons = new List<Icon>();
{
int count = BitConverter.ToInt16(srcBuf, 4); // ICONDIR.idCount
for (int i = 0; i < count; i++)
{
using (MemoryStream destStream = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(destStream))
{
// Copy ICONDIR and ICONDIRENTRY.
writer.Write(srcBuf, 0, sICONDIR - 2);
writer.Write((short)1); // ICONDIR.idCount == 1;
writer.Write(srcBuf, sICONDIR + sICONDIRENTRY * i, sICONDIRENTRY - 4);
writer.Write(sICONDIR + sICONDIRENTRY); // ICONDIRENTRY.dwImageOffset = sizeof(ICONDIR) + sizeof(ICONDIRENTRY)
// Copy picture and mask data.
int imgSize = BitConverter.ToInt32(srcBuf, sICONDIR + sICONDIRENTRY * i + 8); // ICONDIRENTRY.dwBytesInRes
int imgOffset = BitConverter.ToInt32(srcBuf, sICONDIR + sICONDIRENTRY * i + 12); // ICONDIRENTRY.dwImageOffset
writer.Write(srcBuf, imgOffset, imgSize);
// Create new icon.
destStream.Seek(0, SeekOrigin.Begin);
splitIcons.Add(new Icon(destStream));
}
}
}
return splitIcons.ToArray();
}
#endregion Public Class Methods
#region Private Class Methods
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool EnumResourceNames(
IntPtr hModule, int lpszType, EnumResNameProc lpEnumFunc, IconResInfo lParam);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, int lpType);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetModuleFileName(IntPtr hModule, StringBuilder lpFilename, int nSize);
// sizeof(GRPICONDIRENTRY)
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, int dwFlags);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern int SizeofResource(IntPtr hModule, IntPtr hResInfo);
#endregion Private Class Methods
#region Public Overridden Methods
public override string ToString()
{
string text = String.Format("IconExtractor (Filename: '{0}', IconCount: {1})", this.Filename, this.IconCount);
return text;
}
#endregion Public Overridden Methods
#region Public Methods
public void Dispose()
{
if (this._hModule != IntPtr.Zero)
{
try { FreeLibrary(this._hModule); }
catch { }
this._hModule = IntPtr.Zero;
}
if (this._iconCache != null)
{
foreach (Icon i in this._iconCache)
{
if (i != null)
{
try { i.Dispose(); }
catch { }
}
}
this._iconCache = null;
}
}
/// <summary>
/// Extract an icon from the loaded executable file or DLL.
/// </summary>
/// <param name="iconIndex">The zero-based index of the icon to be extracted.</param>
/// <returns>A System.Drawing.Icon object which may consists of multiple icons.</returns>
/// <remarks>Always returns new copy of the Icon. It should be disposed by the user.</remarks>
public Icon GetIcon(int iconIndex)
{
if (this._hModule == IntPtr.Zero)
{
throw new ObjectDisposedException("IconExtractor");
}
if (iconIndex < 0 || this.IconCount <= iconIndex)
{
throw new ArgumentException(
"iconIndex is out of range. It should be between 0 and " + (this.IconCount - 1).ToString() + ".");
}
if (this._iconCache[iconIndex] == null)
{
this._iconCache[iconIndex] = CreateIcon(iconIndex);
}
return (Icon)this._iconCache[iconIndex].Clone();
}
#endregion Public Methods
#region Public Properties
// Full path
public string Filename
{
get { return this._filename; }
}
public int IconCount
{
get { return this._resInfo.IconNames.Count; }
}
#endregion Public Properties
#region Private Methods
private Icon CreateIcon(int iconIndex)
{
// Get group icon resource.
byte[] srcBuf = GetResourceData(this._hModule, this._resInfo.IconNames[iconIndex], RT_GROUP_ICON);
// Convert the resouce into an .ico file image.
using (MemoryStream destStream = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(destStream))
{
int count = BitConverter.ToUInt16(srcBuf, 4); // ICONDIR.idCount
int imgOffset = sICONDIR + sICONDIRENTRY * count;
// Copy ICONDIR.
writer.Write(srcBuf, 0, sICONDIR);
for (int i = 0; i < count; i++)
{
// Copy GRPICONDIRENTRY converting into ICONDIRENTRY.
writer.BaseStream.Seek(sICONDIR + sICONDIRENTRY * i, SeekOrigin.Begin);
writer.Write(srcBuf, sICONDIR + sGRPICONDIRENTRY * i, sICONDIRENTRY - 4); // Common fields of structures
writer.Write(imgOffset); // ICONDIRENTRY.dwImageOffset
// Get picture and mask data, then copy them.
IntPtr nID = (IntPtr)BitConverter.ToUInt16(srcBuf, sICONDIR + sGRPICONDIRENTRY * i + 12); // GRPICONDIRENTRY.nID
byte[] imgBuf = GetResourceData(this._hModule, nID, RT_ICON);
writer.BaseStream.Seek(imgOffset, SeekOrigin.Begin);
writer.Write(imgBuf, 0, imgBuf.Length);
imgOffset += imgBuf.Length;
}
destStream.Seek(0, SeekOrigin.Begin);
return new Icon(destStream);
}
}
private bool EnumResNameCallBack(IntPtr hModule, int lpszType, IntPtr lpszName, IconResInfo lParam)
{
// Callback function for EnumResourceNames().
if (lpszType == RT_GROUP_ICON)
{
lParam.IconNames.Add(new ResourceName(lpszName));
}
return true;
}
private byte[] GetResourceData(IntPtr hModule, IntPtr lpName, int lpType)
{
// Get binary image of the specified resource.
IntPtr hResInfo = FindResource(hModule, lpName, lpType);
if (hResInfo == IntPtr.Zero)
{
throw new Win32Exception();
}
IntPtr hResData = LoadResource(hModule, hResInfo);
if (hResData == IntPtr.Zero)
{
throw new Win32Exception();
}
IntPtr hGlobal = LockResource(hResData);
if (hGlobal == IntPtr.Zero)
{
throw new Win32Exception();
}
int resSize = SizeofResource(hModule, hResInfo);
if (resSize == 0)
{
throw new Win32Exception();
}
byte[] buf = new byte[resSize];
Marshal.Copy(hGlobal, buf, 0, buf.Length);
return buf;
}
private byte[] GetResourceData(IntPtr hModule, ResourceName name, int lpType)
{
try
{
IntPtr lpName = name.GetValue();
return GetResourceData(hModule, lpName, lpType);
}
finally
{
name.Free();
}
}
#endregion Private Methods
}
}
Donate
This software may be used free of charge, but as with all free software there are costs involved to develop and maintain.
If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.
Donate