The "affixiate" way of managing application resources using WinAPI.
This class allows you to easily read/write to your own applications resource section as well as that of others.
Example usage:
If you use this code, it would be most excellent if you could maintain the credits. I'm not asking for cash or beer. This is the least you can do for such high quality work, no? ;)
Don't be a ripper.
/affixiate
P.S. All constructive criticism as well as questions and general comments are welcome.
This class allows you to easily read/write to your own applications resource section as well as that of others.
Code
using System;
using System.Globalization;
using System.Runtime.InteropServices;
/*
* Title: CResourceManager.cs
* Description: Class that wraps reading and writing to resource files using WinAPI.
*
* Developed by: affixiate
* Release date: December 14, 2010
* Released on: https://hackforums.net
*
* Comments: If you use this code, I require you to give me credits. Don't be a ripper! ;]
*/
public class CResourceManager
{
private readonly string _file;
private readonly ushort _currentCultureId;
/// <summary>
/// Initializes a new instance of the <see cref="CResourceManager"/> class.
/// </summary>
/// <param name="file">The full path of the file to manage resources of.</param>
public CResourceManager(string file)
{
_file = file;
_currentCultureId = MAKELANGID(PRIMARYLANGID((ushort) CultureInfo.CurrentCulture.LCID), SUBLANGID((ushort) CultureInfo.CurrentCulture.LCID));
}
/// <summary>
/// Writes to a specified resource.
/// </summary>
/// <param name="resourceType">Type of the resource.</param>
/// <param name="resourceName">Name of the resource.</param>
/// <param name="bufData">The data to write.</param>
/// <returns>
/// <c>true</c> if operation was successful; otherwise <c>false</c>.
/// </returns>
public bool Write<TA, TB>(TA resourceType, TB resourceName, byte[] bufData)
{
IntPtr hResource = IntPtr.Zero;
GCHandle gcResource = GCHandle.Alloc(bufData, GCHandleType.Pinned);
try
{
hResource = BeginUpdateResource(_file, false);
if (hResource == IntPtr.Zero)
throw new Exception();
bool ret = false;
if (typeof(TA) == typeof(int) && typeof(TB) == typeof(int))
ret = UpdateResource(hResource, (int)(object)resourceType, (int)(object)resourceName, _currentCultureId, gcResource.AddrOfPinnedObject(), (uint)bufData.Length);
else if (typeof(TA) == typeof(int) && typeof(TB) == typeof(string))
ret = UpdateResource(hResource, (int)(object)resourceType, (string)(object)resourceName, _currentCultureId, gcResource.AddrOfPinnedObject(), (uint)bufData.Length);
else if (typeof(TA) == typeof(string) && typeof(TB) == typeof(int))
ret = UpdateResource(hResource, (string)(object)resourceType, (int)(object)resourceName, _currentCultureId, gcResource.AddrOfPinnedObject(), (uint)bufData.Length);
else if (typeof(TA) == typeof(string) && typeof(TB) == typeof(string))
ret = UpdateResource(hResource, (string)(object)resourceType, (string)(object)resourceName, _currentCultureId, gcResource.AddrOfPinnedObject(), (uint)bufData.Length);
if (!ret)
throw new Exception();
}
catch
{
return false;
}
finally
{
if (hResource != IntPtr.Zero)
EndUpdateResource(hResource, false);
gcResource.Free();
}
return true;
}
/// <summary>
/// Reads the specified resource.
/// </summary>
/// <param name="resourceType">Type of the resource.</param>
/// <param name="resourceName">Name of the resource.</param>
/// <returns>The contents of that resource.</returns>
public byte[] Read<TA, TB>(TA resourceType, TB resourceName)
{
IntPtr hModule = IntPtr.Zero;
try
{
hModule = LoadLibraryEx(_file, IntPtr.Zero, 0x2 /* LoadLibraryAsDatafile */);
if (hModule == IntPtr.Zero)
throw new Exception();
IntPtr hResource = IntPtr.Zero;
if (typeof(TA) == typeof(int) && typeof(TB) == typeof(int))
hResource = FindResource(hModule, (int)(object)resourceName, (int)(object)resourceType);
else if (typeof(TA) == typeof(int) && typeof(TB) == typeof(string))
hResource = FindResource(hModule, (int)(object)resourceName, (string)(object)resourceType);
else if (typeof(TA) == typeof(string) && typeof(TB) == typeof(int))
hResource = FindResource(hModule, (string)(object)resourceName, (int)(object)resourceType);
else if (typeof(TA) == typeof(string) && typeof(TB) == typeof(string))
hResource = FindResource(hModule, (string)(object)resourceName, (string)(object)resourceType);
if (hResource == IntPtr.Zero)
throw new Exception();
uint dwResourceSize = SizeofResource(hModule, hResource);
if (dwResourceSize == 0)
throw new Exception();
IntPtr hGlobal = LoadResource(hModule, hResource);
if (hGlobal == IntPtr.Zero)
throw new Exception();
IntPtr hLock = LockResource(hGlobal);
if (hLock == IntPtr.Zero)
throw new Exception();
var buf = new byte[dwResourceSize];
Marshal.Copy(hLock, buf, 0, buf.Length);
return buf;
}
catch
{
return null;
}
finally
{
if (hModule != IntPtr.Zero)
FreeLibrary(hModule);
}
}
/// <summary>
/// Creates a language identifier from a primary language identifier and a sub-language identifier.
/// </summary>
/// <param name="primaryLanguage">The primary language.</param>
/// <param name="subLanguage">The sub language.</param>
/// <returns>The language identifier.</returns>
private static ushort MAKELANGID(byte primaryLanguage, byte subLanguage)
{
return (ushort)((subLanguage << 10) | primaryLanguage);
}
/// <summary>
/// Extracts a primary language identifier from a language identifier.
/// </summary>
/// <param name="languageId">The language id.</param>
/// <returns>The primary language identifier.</returns>
private static byte PRIMARYLANGID(ushort languageId)
{
return (byte)(languageId & 0x3ff);
}
/// <summary>
/// Extracts a sublanguage identifier from a language identifier.
/// </summary>
/// <param name="languageId">The language id.</param>
/// <returns>The secondary language identifier.</returns>
private static byte SUBLANGID(ushort languageId)
{
return (byte)(languageId >> 10);
}
#region WinNT Definitions
#region WinAPI
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
#region FindResource
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, int lpName, int lpType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, int lpName, string lpType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, string lpName, int lpType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
#endregion
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources);
#region UpdateResource
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, int lpType, int lpName, ushort wLanguage, IntPtr lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, int lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, string lpType, int lpName, ushort wLanguage, IntPtr lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
#endregion
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
#endregion
#endregion
}Example usage:
Code
CResourceManager resourceManager = new CResourceManager(Application.ExecutablePath);
byte[] buf = resourceManager.Read("BITMAP", "IDB_IMAGE");
//...
resourceManager.Write("BITMAP", "IDB_IMAGE", buf);If you use this code, it would be most excellent if you could maintain the credits. I'm not asking for cash or beer. This is the least you can do for such high quality work, no? ;)
Don't be a ripper.
/affixiate
P.S. All constructive criticism as well as questions and general comments are welcome.



