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}