#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![allow(
warnings,
unused,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]
pub mod ffi {
#[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
#[cfg(all(not(feature = "regenerate"), target_arch = "x86"))]
include!("ffi/x86_bindgen.rs");
#[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
#[cfg(all(not(feature = "regenerate"), target_arch = "x86_64"))]
include!("ffi/x86_64_bindgen.rs");
#[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
#[cfg(all(not(feature = "regenerate"), target_arch = "aarch64"))]
include!("ffi/aarch64_bindgen.rs");
#[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
#[cfg(all(feature = "regenerate", target_arch = "x86"))]
include!(concat!(env!("OUT_DIR"), "/x86_bindgen.rs"));
#[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
#[cfg(all(feature = "regenerate", target_arch = "x86_64"))]
include!(concat!(env!("OUT_DIR"), "/x86_64_bindgen.rs"));
#[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
#[cfg(all(feature = "regenerate", target_arch = "aarch64"))]
include!(concat!(env!("OUT_DIR"), "/aarch64_bindgen.rs"));
}
pub mod ext {
use crate::ffi::*;
use core::{arch::asm, mem, ptr};
#[inline]
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
pub unsafe fn __readfsdword(offset: u32) -> usize {
let out: usize;
asm!(
"mov {}, fs:[{}]",
lateout(reg) out, in(reg) offset,
options(nostack, pure, readonly),
);
out
}
#[inline]
#[cfg(target_arch = "aarch64")]
pub unsafe fn __readfsdword(offset: u32) -> usize {
unimplemented!("not implemented on this arch")
}
#[inline]
#[cfg(target_arch = "x86_64")]
pub unsafe fn __readgsqword(offset: u32) -> usize {
let out: usize;
asm!(
"mov {}, gs:[{}]",
lateout(reg) out, in(reg) offset,
options(nostack, pure, readonly),
);
out
}
#[inline]
#[cfg(any(target_arch = "aarch64", target_arch = "x86"))]
pub unsafe fn __readgsqword(offset: u32) -> usize {
unimplemented!("not implemented on this arch")
}
#[inline]
#[cfg(target_arch = "aarch64")]
pub unsafe fn read_x18() -> usize {
let out: usize;
asm!(
"mov {}, x18",
lateout(reg) out,
options(nostack, pure, readonly),
);
out
}
#[inline]
#[cfg(not(target_arch = "aarch64"))]
pub unsafe fn read_x18() -> usize {
unimplemented!("not implemented on this arch")
}
#[inline]
pub unsafe fn NtCurrentTeb() -> *mut TEB {
const TEB_OFFSET: u32 = mem::offset_of!(NT_TIB, Self_) as u32;
if cfg!(target_arch = "x86_64") {
__readgsqword(TEB_OFFSET) as *mut TEB
} else if cfg!(target_arch = "x86") {
__readfsdword(TEB_OFFSET) as *mut TEB
} else if cfg!(target_arch = "aarch64") {
((read_x18().wrapping_add(TEB_OFFSET as usize)) as *mut *mut TEB).read()
} else {
unimplemented!("target architecture not implemented yet")
}
}
#[cfg(test)]
mod tests {
use super::*;
use windows_sys::Win32::System::Threading::GetCurrentThreadId;
#[test]
fn test_teb() {
let cur_thread = unsafe { (*NtCurrentTeb()).ClientId.UniqueThread as isize };
let cur_thread_sys = unsafe { GetCurrentThreadId() as isize };
assert_eq!(cur_thread, cur_thread_sys);
}
}
}