Skip to content

Instantly share code, notes, and snippets.

@aosoft
Created April 24, 2020 23:45
Show Gist options
  • Save aosoft/485b3a3703f95bccac5d1503e55db8b4 to your computer and use it in GitHub Desktop.
Save aosoft/485b3a3703f95bccac5d1503e55db8b4 to your computer and use it in GitHub Desktop.
use std::ffi::c_void;
use std::ptr;
type Error = u32;
type FnMessageBox = extern "stdcall" fn(hWnd: *const c_void, lpText: *const u16, lpCaption: *const u16, uType: u32) -> i32;
#[link(name = "kernel32")]
#[no_mangle]
extern "stdcall" {
fn GetLastError() -> Error;
fn LoadLibraryExW(lpLibFileName: *const u16, hFile: *const c_void, dwFlags: u32) -> *const c_void;
fn FreeLibrary(hLibModule: *const c_void) -> i32;
fn GetProcAddress(hModule: *const c_void, lpProcName: *const u8) -> *const c_void;
}
fn main() {
unsafe {
let h = LoadLibraryExW("user32.dll".to_nullterminated_u16().as_ptr(),
ptr::null(),
0x800).to_result().unwrap();
let p = GetProcAddress(h, "MessageBoxW\0".as_ptr()).to_result().unwrap();
let fn_message_box = std::mem::transmute::<_, FnMessageBox>(p);
fn_message_box(ptr::null(),
"Hello, Rust!".to_nullterminated_u16().as_ptr(),
"MessageBox".to_nullterminated_u16().as_ptr(),
0);
FreeLibrary(h);
}
}
trait ToResult: Sized {
fn to_result(&self) -> Result<Self, Error>;
}
impl ToResult for *const c_void {
fn to_result(&self) -> Result<*const c_void, Error> {
if *self == ptr::null() {
unsafe {
Err(GetLastError())
}
} else {
Ok(*self)
}
}
}
trait IntoNullTerminatedU16 {
fn to_nullterminated_u16(&self) -> Vec<u16>;
}
impl IntoNullTerminatedU16 for str {
fn to_nullterminated_u16(&self) -> Vec<u16> {
self.encode_utf16().chain(Some(0)).collect()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment