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)]
19#[repr(transparent)]
20pub struct Share<T>(T);
21
22impl<T> Share<T> {
23 pub unsafe fn new(value: T) -> Self {
25 Self(value)
26 }
27
28 pub unsafe fn get(&self) -> &T {
32 &self.0
33 }
34}
35
36unsafe impl<T> Sync for Share<T> {}
37
38unsafe impl<T> Send for Share<T> {}
39
40#[inline]
42pub unsafe fn str_from_cstr<'a>(ptr: *const c_char) -> Option<&'a str> {
43 if ptr.is_null() {
44 None
45 } else {
46 CStr::from_ptr(ptr).to_str().ok()
47 }
48}
49
50#[inline]
54#[allow(dead_code)]
55pub unsafe fn str_from_cstr_len<'a>(ptr: *const c_char, len: u64) -> &'a str {
56 let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
57 str::from_utf8(slice).expect("cstr with invalid utf8")
58}
59
60#[inline]
62pub fn strip_account_prefix(account_name: &str) -> &str {
63 account_name.strip_prefix(':').unwrap_or(account_name)
64}
65
66#[inline]
69pub unsafe fn exported_proc(handle: HMODULE, name: &'static str) -> FARPROC {
70 GetProcAddress(handle, PCSTR(name.as_ptr()))
71}
72
73#[inline]
75pub unsafe fn str_to_wide(string: impl AsRef<str>) -> Vec<u16> {
76 OsStr::new(string.as_ref())
77 .encode_wide()
78 .chain(iter::once(0))
79 .collect()
80}
81
82macro_rules! abi {
84 ( $( $vis:vis type $name:ident = unsafe extern fn( $( $args:tt )* ) $( -> $ret:ty )? ; )* ) => {
85 $(
86 #[cfg(feature = "unwind")]
87 $vis type $name = unsafe extern "C-unwind" fn( $( $args )* ) $( -> $ret )?;
88
89 #[cfg(not(feature = "unwind"))]
90 $vis type $name = unsafe extern "C" fn( $( $args )* ) $( -> $ret )?;
91 )*
92 };
93}
94
95pub(crate) use abi;