1#![no_std]
24#![cfg_attr(docsrs, feature(doc_cfg))]
25#![doc = include_str!("../README.md")]
26#![allow(
27 warnings,
28 unused,
29 non_snake_case,
30 non_camel_case_types,
31 non_upper_case_globals
32)]
33
34pub mod ffi {
36 #[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
38 #[cfg(all(not(feature = "regenerate"), target_arch = "x86"))]
39 include!("ffi/x86_bindgen.rs");
40 #[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
41 #[cfg(all(not(feature = "regenerate"), target_arch = "x86_64"))]
42 include!("ffi/x86_64_bindgen.rs");
43 #[cfg_attr(docsrs, doc(cfg(not(feature = "regenerate"))))]
44 #[cfg(all(not(feature = "regenerate"), target_arch = "aarch64"))]
45 include!("ffi/aarch64_bindgen.rs");
46
47 #[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
49 #[cfg(all(feature = "regenerate", target_arch = "x86"))]
50 include!(concat!(env!("OUT_DIR"), "/x86_bindgen.rs"));
51 #[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
52 #[cfg(all(feature = "regenerate", target_arch = "x86_64"))]
53 include!(concat!(env!("OUT_DIR"), "/x86_64_bindgen.rs"));
54 #[cfg_attr(docsrs, doc(cfg(feature = "regenerate")))]
55 #[cfg(all(feature = "regenerate", target_arch = "aarch64"))]
56 include!(concat!(env!("OUT_DIR"), "/aarch64_bindgen.rs"));
57}
58
59pub mod ext {
61 use crate::ffi::*;
62 use core::{arch::asm, mem, ptr};
63
64 #[inline]
65 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
66 pub unsafe fn __readfsdword(offset: u32) -> usize {
67 let out: usize;
68 asm!(
69 "mov {}, fs:[{}]",
70 lateout(reg) out, in(reg) offset,
71 options(nostack, pure, readonly),
72 );
73 out
74 }
75
76 #[inline]
77 #[cfg(target_arch = "aarch64")]
78 pub unsafe fn __readfsdword(offset: u32) -> usize {
79 unimplemented!("not implemented on this arch")
80 }
81
82 #[inline]
83 #[cfg(target_arch = "x86_64")]
84 pub unsafe fn __readgsqword(offset: u32) -> usize {
85 let out: usize;
86 asm!(
87 "mov {}, gs:[{}]",
88 lateout(reg) out, in(reg) offset,
89 options(nostack, pure, readonly),
90 );
91 out
92 }
93
94 #[inline]
95 #[cfg(any(target_arch = "aarch64", target_arch = "x86"))]
96 pub unsafe fn __readgsqword(offset: u32) -> usize {
97 unimplemented!("not implemented on this arch")
98 }
99
100 #[inline]
101 #[cfg(target_arch = "aarch64")]
102 pub unsafe fn read_x18() -> usize {
103 let out: usize;
104 asm!(
105 "mov {}, x18",
106 lateout(reg) out,
107 options(nostack, pure, readonly),
108 );
109 out
110 }
111
112 #[inline]
113 #[cfg(not(target_arch = "aarch64"))]
114 pub unsafe fn read_x18() -> usize {
115 unimplemented!("not implemented on this arch")
116 }
117
118 #[inline]
119 pub unsafe fn NtCurrentTeb() -> *mut TEB {
120 const TEB_OFFSET: u32 = mem::offset_of!(NT_TIB, Self_) as u32;
121 if cfg!(target_arch = "x86_64") {
122 __readgsqword(TEB_OFFSET) as *mut TEB
123 } else if cfg!(target_arch = "x86") {
124 __readfsdword(TEB_OFFSET) as *mut TEB
125 } else if cfg!(target_arch = "aarch64") {
126 ((read_x18().wrapping_add(TEB_OFFSET as usize)) as *mut *mut TEB).read()
127 } else {
128 unimplemented!("target architecture not implemented yet")
129 }
130 }
131
132 #[cfg(test)]
133 mod tests {
134 use super::*;
135 use windows_sys::Win32::System::Threading::GetCurrentThreadId;
136
137 #[test]
138 fn test_teb() {
139 let cur_thread = unsafe { (*NtCurrentTeb()).ClientId.UniqueThread as isize };
140 let cur_thread_sys = unsafe { GetCurrentThreadId() as isize };
141 assert_eq!(cur_thread, cur_thread_sys);
142 }
143 }
144}