dinvk/syscall/dll.rs
1#![cfg(any(target_arch = "x86_64", target_arch = "x86"))]
2
3use core::sync::atomic::{Ordering, AtomicUsize};
4
5/// The global variable that stores the currently selected DLL for system calls.
6///
7/// # Default
8///
9/// By default, this is set to `Dll::Ntdll`, meaning that system calls will be
10/// resolved from `ntdll.dll` unless explicitly changed using [`Dll::use_dll`].
11static DEFAULT_DLL: AtomicUsize = AtomicUsize::new(Dll::Ntdll as usize);
12
13/// Represents different dynamic link libraries (DLLs) that contain system call functions.
14#[derive(Clone, Copy, PartialEq)]
15pub enum Dll {
16 #[cfg(target_arch = "x86_64")]
17 /// `iumdll.dll`
18 Iumdll,
19
20 #[cfg(target_arch = "x86_64")]
21 /// `vertdll.dll`
22 Vertdll,
23
24 /// `win32u.dll`
25 Win32u,
26
27 /// `ntdll.dll`
28 Ntdll,
29}
30
31impl Dll {
32 /// Sets the default DLL to be used for system calls.
33 ///
34 /// # Arguments
35 ///
36 /// * `dll` - The [`Dll`] variant to use as the new default.
37 ///
38 /// # Example
39 ///
40 /// ```rust,ignore
41 /// use dinvk::Dll;
42 ///
43 /// // Switch to win32u.dll for GUI-related syscalls
44 /// Dll::use_dll(Dll::Win32u);
45 /// ```
46 pub fn use_dll(dll: Dll) {
47 DEFAULT_DLL.store(dll as usize, Ordering::Relaxed);
48 }
49
50 /// Retrieves the currently selected DLL for system calls.
51 ///
52 /// # Returns
53 ///
54 /// * The currently set DLL as a [`Dll`] enum variant.
55 ///
56 /// # Example
57 ///
58 /// ```rust,ignore
59 /// use dinvk::Dll;
60 ///
61 /// // Retrieve the currently selected DLL
62 /// let dll = Dll::current();
63 ///
64 /// println!("Current DLL: {}", dll);
65 /// ```
66 pub fn current() -> Dll {
67 match DEFAULT_DLL.load(Ordering::Relaxed) {
68 #[cfg(target_arch = "x86_64")]
69 x if x == Dll::Iumdll as usize => Dll::Iumdll,
70 #[cfg(target_arch = "x86_64")]
71 x if x == Dll::Vertdll as usize => Dll::Vertdll,
72 x if x == Dll::Win32u as usize => Dll::Win32u,
73 _ => Dll::Ntdll,
74 }
75 }
76
77 /// Returns the function name associated with the selected DLL, if applicable.
78 ///
79 /// # Returns
80 ///
81 /// * A static string slice (`&str`) containing the function name or an empty string.
82 ///
83 /// # Example
84 ///
85 /// ```rust,ignore
86 /// use dinvk::Dll;
87 ///
88 /// let dll = Dll::Win32u;
89 /// println!("Function: {}", dll.function_hash());
90 /// ```
91 pub fn function_hash(&self) -> u32 {
92 match self {
93 Dll::Ntdll => 0,
94 Dll::Win32u => 2604093150u32,
95 #[cfg(target_arch = "x86_64")]
96 Dll::Iumdll => 75139374u32,
97 #[cfg(target_arch = "x86_64")]
98 Dll::Vertdll => 2237456582u32,
99 }
100 }
101}
102
103impl core::fmt::Display for Dll {
104 /// Formats the `Dll` variant as its corresponding DLL file name.
105 ///
106 /// # Example
107 ///
108 /// ```rust,ignore
109 /// use dinvk::Dll;
110 ///
111 /// let dll = Dll::Win32u;
112 /// println!("DLL: {}", dll);
113 /// ```
114 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
115 let name: &[u8] = match self {
116 Dll::Ntdll => &[0x4E, 0x54, 0x44, 0x4C, 0x4C, 0x0E, 0x44, 0x4C, 0x4C],
117 Dll::Win32u => &[0x57, 0x49, 0x4E, 0x13, 0x12, 0x55, 0x0E, 0x44, 0x4C, 0x4C],
118 #[cfg(target_arch = "x86_64")]
119 Dll::Iumdll => &[0x49, 0x55, 0x4D, 0x44, 0x4C, 0x4C, 0x0E, 0x44, 0x4C, 0x4C],
120 #[cfg(target_arch = "x86_64")]
121 Dll::Vertdll => &[0x56, 0x45, 0x52, 0x54, 0x44, 0x4C, 0x4C, 0x0E, 0x44, 0x4C, 0x4C],
122 };
123 write!(f, "{}", name.iter().map(|&c| (c ^ 0x20) as char).collect::<alloc::string::String>())
124 }
125}