djin 0.1.1

DLL injector with support for 32-bit and 64-bit targets.
Documentation
macro_rules! ptr {
    ($e:expr) => {
        $e.as_ptr().cast()
    };
}

macro_rules! bail_if_null {
    ($e:expr) => {
        if $e.is_null() {
            return Err(
                #[allow(unused_unsafe)]
                unsafe {
                    winapi::um::errhandlingapi::GetLastError()
                },
            );
        }
    };
}

macro_rules! bail_if_nonzero {
    ($e:expr) => {
        if $e != 0 {
            return Err(
                #[allow(unused_unsafe)]
                unsafe {
                    winapi::um::errhandlingapi::GetLastError()
                },
            );
        }
    };
}

macro_rules! bail_if_zero {
    ($e:expr) => {
        if $e == 0 {
            return Err(
                #[allow(unused_unsafe)]
                unsafe {
                    winapi::um::errhandlingapi::GetLastError()
                },
            );
        }
    };
}

#[repr(C)]
#[derive(Debug)]
pub struct Pointers {
    llw: *mut (),
    gpa: *mut (),
    gle: *mut (),
    err: u32,
}

use crate::windows_prelude::*;

pub fn get_fn_pointers() -> Pointers {
    unsafe {
        let k32 = GetModuleHandleA(ptr!(b"Kernel32.dll\0"));
        let llw = GetProcAddress(k32, ptr!(b"LoadLibraryW\0")).cast();
        let gpa = GetProcAddress(k32, ptr!(b"GetProcAddress\0")).cast();
        let gle = GetProcAddress(k32, ptr!(b"GetLastError\0")).cast();
        let err = 0;

        // In theory, these should never ever be NULL, as kernel32.dll is always loaded.
        debug_assert!(k32 != NULL as _ && llw != NULL as _ && gpa != NULL as _ && gle != NULL as _);

        Pointers { llw, gpa, gle, err }
    }
}

pub fn alloc(process: HANDLE, size: usize) -> LPVOID {
    unsafe {
        VirtualAllocEx(
            process,
            NULL,
            size,
            MEM_COMMIT | MEM_RESERVE,
            PAGE_EXECUTE_READWRITE,
        )
    }
}