use crate::ThreadName;
use core::ptr;
pub type RawId = u32;
extern "system" {
fn GetCurrentThread() -> isize;
fn WideCharToMultiByte(codepage: u32, dwflags: u32, lpwidecharstr: *const u16, cchwidechar: i32, lpmultibytestr: *const u8, cbmultibyte: i32, lpdefaultchar: *const u8, lpuseddefaultchar: *mut i32) -> i32;
fn LocalFree(hmem: isize) -> isize;
fn GetCurrentThreadId() -> RawId;
fn GetModuleHandleA(lpmodulename: *const u8) -> isize;
fn GetProcAddress(hmodule: isize, lpprocname: *const u8) -> isize;
}
#[inline]
pub fn get_raw_id() -> RawId {
unsafe {
GetCurrentThreadId()
}
}
#[inline(always)]
pub fn raw_thread_eq(left: RawId, right: RawId) -> bool {
left == right
}
macro_rules! compat_fn {
($module:literal: $(
$(#[$meta:meta])*
pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block
)*) => ($(
$(#[$meta])*
pub mod $symbol {
#[allow(unused_imports)]
use super::*;
use core::mem;
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
static mut PTR: Option<F> = None;
#[used]
#[link_section = ".CRT$XCU"]
static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
unsafe extern "C" fn init() {
let module_name: *const u8 = concat!($module, "\0").as_ptr();
let symbol_name: *const u8 = concat!(stringify!($symbol), "\0").as_ptr();
let module_handle = GetModuleHandleA(module_name);
if module_handle != 0 {
match GetProcAddress(module_handle, symbol_name) as usize {
0 => {}
n => {
PTR = Some(mem::transmute::<usize, F>(n));
}
}
}
}
#[allow(dead_code)]
pub fn option() -> Option<F> {
unsafe { PTR }
}
#[allow(dead_code)]
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
if let Some(ptr) = PTR {
ptr($($argname),*)
} else {
$fallback_body
}
}
}
$(#[$meta])*
pub use $symbol::call as $symbol;
)*)
}
pub fn get_current_thread_name() -> ThreadName {
const CP_UTF8: u32 = 65001u32;
compat_fn! {
"kernel32":
#[allow(non_snake_case)]
pub fn GetThreadDescription(handle: isize, out: *mut *const u16) -> i32 {
return -1
}
}
let mut desc_ptr = ptr::null();
let code = unsafe {
GetThreadDescription(GetCurrentThread(), &mut desc_ptr)
};
if code < 0 {
return ThreadName::new();
}
let mut result = [0u8; 16];
unsafe {
WideCharToMultiByte(CP_UTF8, 0, desc_ptr as _, -1, result.as_mut_ptr() as _, result.len() as _, ptr::null(), ptr::null_mut());
LocalFree(desc_ptr as _);
};
ThreadName::name(result)
}