use crate::*;
use winapi::um::securitybaseapi::AdjustTokenPrivileges;
use core::convert::Infallible;
use core::ptr::null_mut;
pub fn adjust_token_privileges_enable_if(token: &token::OwnedHandle, mut cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> {
adjust_token_privileges_each(token, move |p| {
let prev = p.attributes & privilege::ENABLED;
p.attributes = if cond(p.luid) { privilege::ENABLED } else { privilege::Attributes::default() };
p.attributes != prev
})
}
pub fn adjust_token_privileges_disable_if(token: &token::OwnedHandle, mut cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> {
adjust_token_privileges_each(token, move |p| {
let prev = p.attributes & privilege::ENABLED;
p.attributes = if cond(p.luid) { privilege::Attributes::default() } else { privilege::ENABLED };
p.attributes != prev
})
}
pub fn adjust_token_privileges_retain_if(token: &token::OwnedHandle, mut cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> {
adjust_token_privileges_each(token, move |p| {
let prev = p.attributes & privilege::ENABLED;
p.attributes = if cond(p.luid) { prev } else { privilege::REMOVED };
p.attributes != prev
})
}
pub fn adjust_token_privileges_remove_if(token: &token::OwnedHandle, mut cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> {
adjust_token_privileges_each(token, move |p| {
let prev = p.attributes & privilege::ENABLED;
p.attributes = if cond(p.luid) { privilege::REMOVED } else { prev };
p.attributes != prev
})
}
fn adjust_token_privileges_each(token: &token::OwnedHandle, mut adjust_attributes: impl FnMut(&mut privilege::LuidAndAttributes) -> bool) -> Result<(), Error> {
let mut privileges = get_token_information::privileges(token)?;
let mut changes = false;
for privilege in privileges.privileges_mut() {
changes |= adjust_attributes(privilege);
}
if changes {
unsafe { adjust_token_privileges(token, false, Some(&mut privileges), None, None)? };
}
Ok(())
}
impl token::OwnedHandle {
pub fn privileges_enable_if(&self, cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> { adjust_token_privileges_enable_if(self, cond) }
pub fn privileges_disable_if(&self, cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> { adjust_token_privileges_disable_if(self, cond) }
pub fn privileges_retain_if(&self, cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> { adjust_token_privileges_retain_if(self, cond) }
pub fn privileges_remove_if(&self, cond: impl FnMut(privilege::Luid) -> bool) -> Result<(), Error> { adjust_token_privileges_remove_if(self, cond) }
}
fn _adjust_token_privileges_disable_all(token: &token::OwnedHandle) -> Result<(), Error> {
unsafe { adjust_token_privileges(token, true, None, None, None) }
}
unsafe fn adjust_token_privileges(token: &token::OwnedHandle, disable_all_privileges: bool, new_state: Option<&mut token::BoxTokenPrivileges>, _previous_state: Option<Infallible>, _return_length: Option<Infallible>) -> Result<(), Error> {
let new_state = new_state.map_or(null_mut(), |s| s.as_token_privileges_mut_ptr()).cast();
Error::get_last_if(0 == unsafe { AdjustTokenPrivileges(token.as_handle(), disable_all_privileges as _, new_state, 0, none2null(_previous_state), none2null(_return_length)) })
}
#[test] fn test() {
let t = open_process_token(get_current_process(), token::ALL_ACCESS).unwrap();
let t = duplicate_token_ex(&t, token::ALL_ACCESS, None, security::Delegation, token::Primary).unwrap();
t.privileges_disable_if(|_| true).unwrap();
t.privileges_remove_if(|_| true).unwrap();
}