1use std::{
4 ffi::{CStr, OsStr},
5 iter,
6 os::{raw::c_char, windows::prelude::OsStrExt},
7 slice, str,
8};
9use windows::{
10 core::PCSTR,
11 Win32::{
12 Foundation::{FARPROC, HMODULE},
13 System::LibraryLoader::GetProcAddress,
14 },
15};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[repr(transparent)]
19pub struct Share<T>(pub T);
20
21unsafe impl<T> Sync for Share<T> {}
22
23unsafe impl<T> Send for Share<T> {}
24
25#[inline]
27pub unsafe fn str_from_cstr<'a>(ptr: *const c_char) -> Option<&'a str> {
28 if ptr.is_null() {
29 None
30 } else {
31 CStr::from_ptr(ptr).to_str().ok()
32 }
33}
34
35#[inline]
39#[allow(dead_code)]
40pub unsafe fn str_from_cstr_len<'a>(ptr: *const c_char, len: u64) -> &'a str {
41 let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
42 str::from_utf8(slice).expect("cstr with invalid utf8")
43}
44
45#[inline]
47pub fn strip_account_prefix(account_name: &str) -> &str {
48 account_name.strip_prefix(':').unwrap_or(account_name)
49}
50
51#[inline]
54pub unsafe fn exported_proc(handle: HMODULE, name: &'static str) -> FARPROC {
55 GetProcAddress(handle, PCSTR(name.as_ptr()))
56}
57
58#[inline]
60pub unsafe fn str_to_wide(string: impl AsRef<str>) -> Vec<u16> {
61 OsStr::new(string.as_ref())
62 .encode_wide()
63 .chain(iter::once(0))
64 .collect()
65}
66
67macro_rules! abi {
69 ( $( $vis:vis type $name:ident = unsafe extern fn( $( $args:tt )* ) $( -> $ret:ty )? ; )* ) => {
70 $(
71 #[cfg(feature = "unwind")]
72 $vis type $name = unsafe extern "C-unwind" fn( $( $args )* ) $( -> $ret )?;
73
74 #[cfg(not(feature = "unwind"))]
75 $vis type $name = unsafe extern "C" fn( $( $args )* ) $( -> $ret )?;
76 )*
77 };
78}
79
80pub(crate) use abi;