use std::{
ffi::{CStr, OsStr},
iter,
os::{raw::c_char, windows::prelude::OsStrExt},
slice, str,
};
use windows::{
core::PCSTR,
Win32::{
Foundation::{FARPROC, HMODULE},
System::LibraryLoader::GetProcAddress,
},
};
#[inline]
pub unsafe fn str_from_cstr<'a>(ptr: *const c_char) -> Option<&'a str> {
if ptr.is_null() {
None
} else {
CStr::from_ptr(ptr).to_str().ok()
}
}
#[inline]
#[allow(dead_code)]
pub unsafe fn str_from_cstr_len<'a>(ptr: *const c_char, len: u64) -> &'a str {
let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
str::from_utf8(slice).expect("cstr with invalid utf8")
}
#[inline]
pub fn strip_account_prefix(account_name: &str) -> &str {
account_name.strip_prefix(':').unwrap_or(account_name)
}
#[inline]
pub unsafe fn exported_proc(handle: HMODULE, name: &'static str) -> FARPROC {
GetProcAddress(handle, PCSTR(name.as_ptr()))
}
#[inline]
pub unsafe fn str_to_wide(string: impl AsRef<str>) -> Vec<u16> {
OsStr::new(string.as_ref())
.encode_wide()
.chain(iter::once(0))
.collect()
}
macro_rules! abi {
( $( $vis:vis type $name:ident = unsafe extern fn( $( $args:tt )* ) $( -> $ret:ty )? ; )* ) => {
$(
#[cfg(feature = "unwind")]
$vis type $name = unsafe extern "C-unwind" fn( $( $args )* ) $( -> $ret )?;
#[cfg(not(feature = "unwind"))]
$vis type $name = unsafe extern "C" fn( $( $args )* ) $( -> $ret )?;
)*
};
}
pub(crate) use abi;