mod safe_windows_bindings;
use crate::safe_windows_bindings::high_level::{
add_admin_privileges_to_token, create_process_with_token, get_current_user_token,
get_process_pid, get_process_token,
};
#[derive(Default)]
pub enum Elevation {
#[default]
User,
Admin,
LocalSystem,
}
#[derive(Default)]
pub enum Desktop {
#[default]
Default,
Secure,
}
pub fn win(path: impl AsRef<str>) -> ProcessBuilder {
ProcessBuilder::new(path)
}
pub struct ProcessBuilder {
pub(crate) path: String,
pub(crate) args: String,
pub(crate) directory: String,
pub(crate) desktop: Desktop,
pub(crate) elevation: Elevation,
}
impl ProcessBuilder {
pub fn new(path: impl AsRef<str>) -> Self {
let path = path.as_ref().to_string();
let args = "".to_owned();
let directory = std::env::current_exe()
.expect("Could not get path to the current executable")
.parent()
.expect("Could not get path to the directory of the current executable")
.to_str()
.expect("Could not get the current directory path as utf-8")
.to_string();
let desktop = Desktop::default();
let elevation = Elevation::default();
Self {
path,
args,
directory,
desktop,
elevation,
}
}
pub fn args(mut self, args: impl AsRef<str>) -> Self {
self.args = args.as_ref().to_string();
self
}
pub fn directory(mut self, directory: impl AsRef<str>) -> Self {
self.directory = directory.as_ref().to_string();
self
}
pub fn desktop(mut self, desktop: Desktop) -> Self {
self.desktop = desktop;
self
}
pub fn elevation(mut self, elevation: Elevation) -> Self {
self.elevation = elevation;
self
}
pub fn run(&self) -> Result<(), String> {
let application_name = &self.path;
let command_line = format!("{} {}", self.path, self.args);
let current_directory = &self.directory;
let desktop = match self.desktop {
Desktop::Default => "",
Desktop::Secure => "WinSta0\\Winlogon",
};
let token = match self.elevation {
Elevation::User => get_current_user_token()?,
Elevation::Admin => {
let mut current_user_token = get_current_user_token()?;
current_user_token = add_admin_privileges_to_token(current_user_token)?;
current_user_token
}
Elevation::LocalSystem => {
let process_pid = get_process_pid("winlogon")?;
get_process_token(process_pid)?
}
};
create_process_with_token(
token,
application_name,
&command_line,
current_directory,
desktop,
)
}
}