scmanager_windows_rs/
common.rs

1use defer_lite::defer;
2use widestring::U16CString;
3use windows_sys::Win32::{
4    Foundation::{CloseHandle, GetLastError, LUID},
5    Security::{
6        AdjustTokenPrivileges, LookupPrivilegeValueW, SE_PRIVILEGE_ENABLED,
7        TOKEN_ADJUST_PRIVILEGES, TOKEN_PRIVILEGES, TOKEN_QUERY,
8    },
9    System::Threading::{GetCurrentProcess, OpenProcessToken},
10};
11
12#[inline(always)]
13pub fn get_last_error() -> u32 {
14    unsafe { GetLastError() }
15}
16pub fn set_privilege(name: String) -> Result<(), String> {
17    unsafe {
18        let mut token_handle = 0;
19
20        if OpenProcessToken(
21            GetCurrentProcess(),
22            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
23            &mut token_handle,
24        ) == 0
25        {
26            return Err("OpenProcessToken failed".to_string());
27        }
28
29        defer! {CloseHandle(token_handle);}
30
31        let mut lookup_id = std::mem::MaybeUninit::<LUID>::zeroed();
32
33        let name = U16CString::from_str(name).unwrap();
34
35        if LookupPrivilegeValueW(std::ptr::null(), name.as_ptr(), lookup_id.as_mut_ptr()) == 0 {
36            return Err("LookupPrivilegeValueA failed".to_string());
37        }
38
39        let mut token_priv = std::mem::MaybeUninit::<TOKEN_PRIVILEGES>::zeroed();
40        let token_priv_ptr = token_priv.as_mut_ptr();
41
42        (*token_priv_ptr).PrivilegeCount = 1;
43        (*token_priv_ptr).Privileges[0].Luid = lookup_id.assume_init();
44        (*token_priv_ptr).Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
45
46        if AdjustTokenPrivileges(
47            token_handle,
48            0,
49            token_priv.as_ptr(),
50            std::mem::size_of::<TOKEN_PRIVILEGES>() as u32,
51            std::ptr::null_mut(),
52            std::ptr::null_mut(),
53        ) == 0
54        {
55            return Err("AdjustTokenPrivileges failed".to_string());
56        }
57    }
58
59    Ok(())
60}