Skip to content

Instantly share code, notes, and snippets.

@Kittoes0124
Last active July 6, 2019 10:55
Show Gist options
  • Save Kittoes0124/0e936d97a0bc57c8d8a0ce16406231cb to your computer and use it in GitHub Desktop.
Save Kittoes0124/0e936d97a0bc57c8d8a0ce16406231cb to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace ByteTerrace.Windows.Api
{
static class BitwiseHelpers
{
public static uint ConcatBits(ushort highPart, ushort lowPart) => ((((uint)highPart) << 16) | lowPart);
}
public static class Constants
{
public const string Kernel32Dll = "Kernel32.dll";
}
[Flags]
public enum VirtualMemoryAllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
}
[Flags]
public enum VirtualMemoryFreeType : uint
{
RELEASE = 0x8000,
}
[Flags]
public enum VirtualMemoryProtectionType : uint
{
EXECUTE = 0x10,
READWRITE = 0x04,
}
public enum WindowShowType : int
{
HIDE = 0,
SHOW = 5,
}
[Flags]
public enum WindowStyleBasic : uint
{
OVERLAPPED = 0x00,
}
[Flags]
public enum WindowStyleExtended : uint
{
EX_LEFT = 0x00,
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct Atom
{
public static Atom Null => New(0);
public static Atom New(ushort value) => new Atom(value);
public static bool operator ==(Atom left, Atom right) => (left.m_value == right.m_value);
public static bool operator !=(Atom left, Atom right) => (left.m_value != right.m_value);
private readonly ushort m_value;
private Atom(ushort value) {
m_value = value;
}
public bool Equals(Atom other) => (this == other);
public override bool Equals(object other) => ((other != null) && ((other is Atom) && Equals(other)));
public override int GetHashCode() => m_value.GetHashCode();
public ushort ToUInt16() => m_value;
}
public abstract class SafeHandleZeroIsInvalid : SafeHandle
{
protected SafeHandleZeroIsInvalid(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) { }
public override bool IsInvalid {
[PrePrepareMethod]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
get => (IntPtr.Zero == handle);
}
}
public static class Library
{
[Flags]
public enum LoadLibraryType : uint
{
NONE = 0x00000000,
}
[Flags]
public enum ModuleHandleType : uint
{
NONE = 0x00000000,
}
public sealed class LoadLibrarySafeHandle : SafeHandleZeroIsInvalid
{
[SuppressUnmanagedCodeSecurity]
private static class UnsafeNativeMethods
{
[DllImport(Constants.Kernel32Dll, BestFitMapping = false, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true, ThrowOnUnmappableChar = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecurityCritical]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr libraryHandle);
[DllImport(Constants.Kernel32Dll, BestFitMapping = false, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, ThrowOnUnmappableChar = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecurityCritical]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetModuleHandleExW(ModuleHandleType moduleHandleType, [MarshalAs(UnmanagedType.LPWStr)] string libraryName, out IntPtr libraryHandle);
[DllImport(Constants.Kernel32Dll, BestFitMapping = false, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true, ThrowOnUnmappableChar = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecurityCritical]
public static extern IntPtr GetProcAddress(IntPtr libraryHandle, IntPtr procedureName);
[DllImport(Constants.Kernel32Dll, BestFitMapping = false, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, ThrowOnUnmappableChar = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecurityCritical]
public static extern IntPtr LoadLibraryExW([MarshalAs(UnmanagedType.LPWStr)] string libraryName, IntPtr fileHandle, LoadLibraryType loadLibraryType);
}
public static LoadLibrarySafeHandle New(IntPtr address) => new LoadLibrarySafeHandle(address);
public static LoadLibrarySafeHandle New(string name, IntPtr fileHandle, LoadLibraryType loadLibraryType) {
if (UnsafeNativeMethods.GetModuleHandleExW(ModuleHandleType.NONE, name, out IntPtr libraryHandle)) {
return New(libraryHandle);
}
else {
libraryHandle = UnsafeNativeMethods.LoadLibraryExW(name, fileHandle, loadLibraryType);
if (IntPtr.Zero == libraryHandle) {
throw new DllNotFoundException(message: $"unable to find a library named {name}", inner: Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
}
return New(libraryHandle);
}
}
public static LoadLibrarySafeHandle New(string name) => New(name, IntPtr.Zero, LoadLibraryType.NONE);
private LoadLibrarySafeHandle(IntPtr address) : base(true) {
SetHandle(address);
}
[PrePrepareMethod]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override bool ReleaseHandle() => UnsafeNativeMethods.FreeLibrary(handle);
public TDelegate GetDelegateForProcedure<TDelegate>(string name) {
var nameHandle = Marshal.StringToHGlobalAnsi(name);
try {
var functionHandle = UnsafeNativeMethods.GetProcAddress(handle, nameHandle);
if (IntPtr.Zero == functionHandle) {
throw new EntryPointNotFoundException(message: $"unable to find a procedure named {name}", inner: Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
}
else {
return Marshal.GetDelegateForFunctionPointer<TDelegate>(functionHandle);
}
}
finally {
Marshal.FreeHGlobal(nameHandle);
}
}
}
}
public static class Memory
{
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr VirtualAllocEx(IntPtr handle, IntPtr address, UIntPtr length, VirtualMemoryAllocationType allocationType, VirtualMemoryProtectionType protectionType);
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern bool VirtualFreeEx(IntPtr handle, IntPtr address, UIntPtr length, VirtualMemoryFreeType freeType);
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern bool VirtualProtectEx(IntPtr handle, IntPtr address, UIntPtr length, VirtualMemoryProtectionType newProtectionType, out VirtualMemoryProtectionType oldProtectionType);
}
public static class Process
{
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = false)]
public static extern IntPtr GetCurrentProcess();
}
public static class Window
{
public delegate IntPtr WindowProcWDelegate(IntPtr windowHandle, uint message, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public readonly struct WndClassExW
{
public static WndClassExW New(WindowProcWDelegate lpfnWndProc, IntPtr hInstance, string lpszClassName) => new WndClassExW(lpfnWndProc, hInstance, lpszClassName);
public static WndClassExW New(IntPtr hInstance, string lpszClassName) => new WndClassExW(DefWindowProcW, hInstance, lpszClassName);
public static WndClassExW New() => new WndClassExW(null, IntPtr.Zero, null);
private readonly uint m_cbSize;
private readonly uint m_style;
private readonly IntPtr m_lpfnWndProc;
private readonly int m_cbClsExtra;
private readonly int m_cbWndExtra;
private readonly IntPtr m_hInstance;
private readonly IntPtr m_hIcon;
private readonly IntPtr m_hCursor;
private readonly IntPtr m_hbrBackground;
[MarshalAs(UnmanagedType.LPWStr)] private readonly string m_lpszMenuName;
[MarshalAs(UnmanagedType.LPWStr)] private readonly string m_lpszClassName;
private readonly IntPtr m_hIconSm;
private WndClassExW(WindowProcWDelegate lpfnWndProc, IntPtr hInstance, string lpszClassName) {
m_cbSize = ((uint)Marshal.SizeOf(typeof(WndClassExW)));
m_style = 0U;
m_lpfnWndProc = ((lpfnWndProc != null) ? Marshal.GetFunctionPointerForDelegate(lpfnWndProc) : IntPtr.Zero);
m_cbClsExtra = 0;
m_cbWndExtra = 0;
m_hInstance = hInstance;
m_hIcon = IntPtr.Zero;
m_hCursor = IntPtr.Zero;
m_hbrBackground = IntPtr.Zero;
m_lpszMenuName = string.Empty;
m_lpszClassName = lpszClassName;
m_hIconSm = IntPtr.Zero;
}
}
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateWindowExW(WindowStyleExtended extendedWindowStyle, [MarshalAs(UnmanagedType.LPWStr)] string className, [MarshalAs(UnmanagedType.LPWStr)] string windowName, WindowStyleBasic baseWindowStyle, int x, int y, int width, int height, IntPtr parentHandle, IntPtr menuHandle, IntPtr moduleHandle, IntPtr createParameters);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr DefWindowProcW(IntPtr windowHandle, uint message, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern bool DestroyWindow(IntPtr windowHandle);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool GetClassInfoExW(IntPtr instanceHandle, IntPtr className, ref WndClassExW windowClass);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern Atom RegisterClassExW(ref WndClassExW windowClass);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern bool ShowWindow(IntPtr windowHandle, WindowShowType windowShowType);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool UnregisterClassW(IntPtr classAtom, IntPtr instanceHandle);
public static bool UnregisterClassW(Atom classAtom, IntPtr instanceHandle) => UnregisterClassW(new IntPtr(BitwiseHelpers.ConcatBits(0, classAtom.ToUInt16())), instanceHandle);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment