Skip to content

Instantly share code, notes, and snippets.

@pigeonhands
Last active December 14, 2016 05:24
Show Gist options
  • Save pigeonhands/e30f7e45b7a2f3c91160 to your computer and use it in GitHub Desktop.
Save pigeonhands/e30f7e45b7a2f3c91160 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
using System.Text;
/// <summary>
/// Wrapper for reading/writing to native resources
/// Made by BahNahNah
/// </summary>
public static class NativeResource
{
#region " Writing "
/// /// <summary>
/// Writes a byte array to resource
/// </summary>
/// <param name="filename">File to write resource</param>
/// <param name="name">Name of resource</param>
/// <param name="data">Data to write</param>
public static void WriteResource(string filename, string name, byte[] data)
{
IntPtr handle = OpenFile(filename);
IntPtr dataPtr = CopyToNative(data);
if (!UpdateResource(handle, "RT_RCDATA", name, 0, dataPtr, Convert.ToUInt32(data.Length)))
{
FreeAlloc(dataPtr);
throw new AccessViolationException("Failed to update resource");
}
if (!EndUpdateResource(handle, false))
{
FreeAlloc(dataPtr);
throw new AccessViolationException("Failed to write resource");
}
}
/// <summary>
/// Writes a string to native resource
/// </summary>
/// <param name="filename">File to write resource</param>
/// <param name="name">Name of resouce</param>
/// <param name="data">String to write</param>
public static void WriteResource(string filename, string name, string data)
{
IntPtr handle = OpenFile(filename);
StringBuilder sb = new StringBuilder(data);
if (!UpdateResource(handle, "RT_STRING", name, 0, sb, Convert.ToUInt32(data.Length)))
throw new AccessViolationException("Failed to update resource");
if (!EndUpdateResource(handle, false))
throw new AccessViolationException("Failed to write resource");
}
/// <summary>
/// Deletes all native resources from a binary
/// </summary>
/// <param name="filename">File to delete resources from</param>
public static void ClearResources(string filename)
{
IntPtr handle = OpenFile(filename);
if (!EndUpdateResource(handle, true))
throw new AccessViolationException("Failed end update");
}
#endregion
#region " Reading "
private static byte[] ReadFromPointer(IntPtr mHandle, string resourceName, string type)
{
IntPtr rHandle = FindResource(mHandle, resourceName, type);
IntPtr dHandle = LoadResource(mHandle, rHandle);
uint size = SizeofResource(mHandle, rHandle);
return CopyToManaged(dHandle, size);
}
/// <summary>
/// Reads a byte array from the executing assembly
/// </summary>
/// <param name="resourceName">Name of resource to read</param>
/// <returns></returns>
public static byte[] ReadResource(string resourceName)
{
IntPtr mHandle = CurrentModuleHandle();
return ReadFromPointer(mHandle, resourceName, "RT_RCDATA");
}
/// <summary>
/// Reads a string from the executing assembly
/// </summary>
/// <param name="resourceName">>Name of resource to read</param>
/// <returns></returns>
public static string ReadResourceString(string resourceName)
{
IntPtr mHandle = CurrentModuleHandle();
byte[] data = ReadFromPointer(mHandle, resourceName, "RT_STRING");
return Encoding.UTF8.GetString(data);
}
/// <summary>
/// Reads byte array from specified file
/// </summary>
/// <param name="filename">File to read native resouce from</param>
/// <param name="resourcename">Name of resouce to read</param>
/// <returns></returns>
public static byte[] ReadResource(string filename, string resourcename)
{
IntPtr fHandle = OpenFile(filename);
return ReadFromPointer(fHandle, resourcename, "RT_RCDATA");
}
/// <summary>
/// Read string from specified file
/// </summary>
/// <param name="filename">File to read native resource from</param>
/// <param name="resourcename">Name of resouce to read</param>
/// <returns></returns>
public static string ReadResourceString(string filename, string resourcename)
{
IntPtr fHandle = OpenFile(filename);
byte[] data = ReadFromPointer(fHandle, resourcename, "RT_STRING");
return Encoding.UTF8.GetString(data);
}
#endregion
#region " Healpers "
private static IntPtr GetResourceHandle(IntPtr mHandle, string rname, string type)
{
IntPtr rHandle = FindResource(mHandle, rname, type);
if (rHandle == IntPtr.Zero)
throw new InvalidOperationException("Cant find resource");
return rHandle;
}
private static IntPtr CurrentModuleHandle()
{
IntPtr handle = GetModuleHandle(null);
if (handle == IntPtr.Zero)
throw new AccessViolationException("Failed to get current module handle");
return handle;
}
private static IntPtr OpenFile(string filename)
{
IntPtr handle = BeginUpdateResource(filename, false);
if (handle == IntPtr.Zero)
throw new AccessViolationException("Failed to open file");
return handle;
}
private static IntPtr CopyToNative(byte[] data)
{
IntPtr dataPtr = Marshal.AllocHGlobal(data.Length);
if (dataPtr == IntPtr.Zero)
throw new AccessViolationException("Failed to open resource handle");
Marshal.Copy(data, 0, dataPtr, data.Length);
return dataPtr;
}
private static byte[] CopyToManaged(IntPtr ptr, uint size)
{
if (ptr == IntPtr.Zero)
throw new ArgumentException("Pointer cant be zero");
byte[] b = new byte[size];
Marshal.Copy(ptr, b, 0, b.Length);
return b;
}
private static void FreeAlloc(IntPtr ptr)
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
#endregion
#region " WinApi "
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string module);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[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 BeginUpdateResource(string pFileName,
[MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, string lpType, string 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, StringBuilder lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment