diff --git a/Cargo.toml b/Cargo.toml index e9f3e2c..74b0ec4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,12 +28,10 @@ serde_json = "1.0.143" strum = { version = "0.27.2", features = ["derive"] } windows = { version = "0.62.0", features = [ "Win32_NetworkManagement_WindowsFirewall", - "Win32_Security", "Win32_System_Com", "Win32_System_Diagnostics_ToolHelp", "Win32_System_Threading", "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", ] } winreg = "0.55.0" diff --git a/build.rs b/build.rs index 9a5b47c..bfd6aac 100644 --- a/build.rs +++ b/build.rs @@ -6,6 +6,17 @@ fn main() { .set("LegalCopyright", "futile ") .set_language(0x0009) .set_icon("assets/icon.ico") + .set_manifest( + r#" + + + + + + + + "#, + ) .compile() .unwrap(); embed_latest_git_hash(); diff --git a/src/gui/app.rs b/src/gui/app.rs index ff21c02..2be0d04 100644 --- a/src/gui/app.rs +++ b/src/gui/app.rs @@ -29,7 +29,6 @@ enum Stage { #[derive(Debug)] pub struct Flags { - pub elevated: bool, pub debug: bool, closing: bool, } @@ -37,7 +36,6 @@ pub struct Flags { impl Default for Flags { fn default() -> Self { Self { - elevated: win::is_elevated(), debug: false, closing: false, } @@ -67,15 +65,6 @@ impl eframe::App for App { .show(ctx, |ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| { ui.build_menu(&mut self.stage); - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - let button = ui - .add_enabled(!self.flags.elevated, egui::Button::new("Elevate")) - .on_hover_text("Relaunch ourselves as administrator.") - .on_disabled_hover_text("We are already running elevated."); - if button.clicked() { - win::elevate(win::ElevationExitMethod::Gentle(&mut self.flags.closing)); - } - }); }); }); egui::CentralPanel::default().show(ctx, |ui| { @@ -120,7 +109,7 @@ impl App { fn show_session_section(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) { ui.header("Session"); - ui.add_enabled_ui(self.flags.elevated && !self.empty_session.disabled, |ui| { + ui.add_enabled_ui(!self.empty_session.disabled, |ui| { ui.horizontal(|ui| { if ui.button("Empty current session").clicked() && features::empty_session::activate(&mut self.system_info, &self.firewall) @@ -156,77 +145,70 @@ impl App { egui::Frame::new() .outer_margin(egui::vec2(0.0, -2.0)) .show(ui, |ui| { - ui.add_enabled_ui(self.flags.elevated, |ui| { - let label = ui.horizontal(|ui| { - let label = match self.settings.block_method { - BlockMethod::EntireGame => ui.label("Game's network access"), - BlockMethod::SaveServer => ui.label("Rockstar save server access"), - }; - ui.add_space(1.0); - ui.create_indicator_dot(match self.game_networking.blocked { - BlockedStatus::Executable - if self.settings.block_method == BlockMethod::EntireGame => - { - colours::RED - } - BlockedStatus::Server - if self.settings.block_method == BlockMethod::SaveServer => - { - colours::RED - } - _ => colours::GREEN, - }); - label + let label = ui.horizontal(|ui| { + let label = match self.settings.block_method { + BlockMethod::EntireGame => ui.label("Game's network access"), + BlockMethod::SaveServer => ui.label("Rockstar save server access"), + }; + ui.add_space(1.0); + ui.create_indicator_dot(match self.game_networking.blocked { + BlockedStatus::Executable + if self.settings.block_method == BlockMethod::EntireGame => + { + colours::RED + } + BlockedStatus::Server + if self.settings.block_method == BlockMethod::SaveServer => + { + colours::RED + } + _ => colours::GREEN, }); - ui.allocate_ui_with_layout( - egui::vec2(label.inner.rect.width(), 0.0), - egui::Layout::top_down(egui::Align::Min), - |ui| { - ui.columns(2, |columns| { - columns[0].vertical_centered_justified(|ui| { - if ui.button("Block").clicked() { - match self.settings.block_method { - BlockMethod::EntireGame => { - self.game_networking - .block_exe( - &mut self.system_info, - &self.firewall, - ) - .unwrap(); - } - BlockMethod::SaveServer => { - self.game_networking - .block_save_server( - &self.settings.save_server_ip, - &self.firewall, - ) - .unwrap(); - } + label + }); + ui.allocate_ui_with_layout( + egui::vec2(label.inner.rect.width(), 0.0), + egui::Layout::top_down(egui::Align::Min), + |ui| { + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + if ui.button("Block").clicked() { + match self.settings.block_method { + BlockMethod::EntireGame => { + self.game_networking + .block_exe(&mut self.system_info, &self.firewall) + .unwrap(); + } + BlockMethod::SaveServer => { + self.game_networking + .block_save_server( + &self.settings.save_server_ip, + &self.firewall, + ) + .unwrap(); } } - }); - columns[1].vertical_centered_justified(|ui| { - if ui.button("Unblock").clicked() { - match self.settings.block_method { - BlockMethod::EntireGame => { - self.game_networking - .unblock_exe(&self.firewall) - .unwrap(); - } - BlockMethod::SaveServer => { - self.game_networking - .unblock_save_server(&self.firewall) - .unwrap(); - } - } - } - }); + } }); - }, - ); - }) - .response - .on_disabled_hover_text("This requires administrator.\nUse the Elevate button."); + columns[1].vertical_centered_justified(|ui| { + if ui.button("Unblock").clicked() { + match self.settings.block_method { + BlockMethod::EntireGame => { + self.game_networking + .unblock_exe(&self.firewall) + .unwrap(); + } + BlockMethod::SaveServer => { + self.game_networking + .unblock_save_server(&self.firewall) + .unwrap(); + } + } + } + }); + }); + }, + ); }); } @@ -238,7 +220,6 @@ impl App { fn show_settings_stage(&mut self, ctx: &egui::Context, ui: &mut egui::Ui) { ui.collapsing("General", |ui| { - ui.checkbox(&mut self.settings.start_elevated, "Always start elevated"); ui.horizontal(|ui| { let selection = self.settings.theme; egui::ComboBox::from_id_salt("Theme") @@ -263,39 +244,35 @@ impl App { }); }); ui.collapsing("Network", |ui| { - ui.add_enabled_ui(self.flags.elevated, |ui| { + ui.horizontal(|ui| { + egui::ComboBox::from_id_salt("Block method") + .selected_text(self.settings.block_method.to_string()) + .show_ui(ui, |ui| { + ui.build_menu(&mut self.settings.block_method); + }); + ui.label("Block method"); + if let Err(why) = self + .game_networking + .ensure_block_exclusivity(self.settings.block_method, &self.firewall) + { + log::warn!("Couldn't ensure block exclusivity: {why}"); + } + }); + if self.settings.block_method == BlockMethod::SaveServer { ui.horizontal(|ui| { - egui::ComboBox::from_id_salt("Block method") - .selected_text(self.settings.block_method.to_string()) - .show_ui(ui, |ui| { - ui.build_menu(&mut self.settings.block_method); - }); - ui.label("Block method"); - if let Err(why) = self - .game_networking - .ensure_block_exclusivity(self.settings.block_method, &self.firewall) - { - log::warn!("Couldn't ensure block exclusivity: {why}"); + ui.add( + egui::TextEdit::singleline(&mut self.settings.save_server_ip) + .char_limit(15) + .desired_width(92.0), + ); + ui.label("Save server IP"); + if self.settings.save_server_ip != Settings::default().save_server_ip { + if ui.button("↺").clicked() { + self.settings.save_server_ip = String::from(ROCKSTAR_SAVE_SERVER); + } } }); - if self.settings.block_method == BlockMethod::SaveServer { - ui.horizontal(|ui| { - ui.add( - egui::TextEdit::singleline(&mut self.settings.save_server_ip) - .char_limit(15) - .desired_width(92.0), - ); - ui.label("Save server IP"); - if self.settings.save_server_ip != Settings::default().save_server_ip { - if ui.button("↺").clicked() { - self.settings.save_server_ip = String::from(ROCKSTAR_SAVE_SERVER); - } - } - }); - } - }) - .response - .on_disabled_hover_text("This requires administrator.\nUse the Elevate button."); + }; }); ui.collapsing("Miscellaneous", |ui| { if ui.button("Open storage path").clicked() { diff --git a/src/gui/run.rs b/src/gui/run.rs index ba612fe..317dacb 100644 --- a/src/gui/run.rs +++ b/src/gui/run.rs @@ -3,7 +3,7 @@ use crate::{ app::{App, WINDOW_SIZE}, tools, }, - util::{persistent_state::PersistentState, win}, + util::persistent_state::PersistentState, }; use eframe::egui; use windows::Win32::System::Com::{COINIT_APARTMENTTHREADED, CoInitializeEx}; @@ -21,10 +21,6 @@ fn app_creator( if let Some(persistent_state) = PersistentState::get() { persistent_state.apply_to(&mut app); } - // check if we're elevated. if not, and the user wants an elevated launch - relaunch elevated - if !app.flags.elevated && app.settings.start_elevated { - win::elevate(win::ElevationExitMethod::Forced); - } // refresh system info because it initializes with nothing app.system_info.refresh(); // enable image loading support in egui diff --git a/src/gui/settings.rs b/src/gui/settings.rs index 79958b1..dd3db4a 100644 --- a/src/gui/settings.rs +++ b/src/gui/settings.rs @@ -55,7 +55,6 @@ pub enum BlockMethod { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Settings { - pub start_elevated: bool, pub theme: Theme, pub launch_version: LaunchVersion, pub save_server_ip: String, @@ -65,7 +64,6 @@ pub struct Settings { impl Default for Settings { fn default() -> Self { Self { - start_elevated: false, theme: Theme::default(), launch_version: LaunchVersion::default(), block_method: BlockMethod::default(), diff --git a/src/util/win.rs b/src/util/win.rs index 7826d36..3b4d619 100644 --- a/src/util/win.rs +++ b/src/util/win.rs @@ -1,25 +1,10 @@ -use windows::{ - Win32::{ - Foundation::{CloseHandle, HANDLE}, - Security::{GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation}, - System::Threading::{GetCurrentProcess, OpenProcessToken}, - UI::{ - Input::KeyboardAndMouse::{GetAsyncKeyState, VIRTUAL_KEY}, - Shell::ShellExecuteW, - WindowsAndMessaging::{ - CURSOR_SHOWING, CURSORINFO, GetCursorInfo, GetForegroundWindow, GetWindowTextW, - SW_NORMAL, - }, - }, +use windows::Win32::UI::{ + Input::KeyboardAndMouse::{GetAsyncKeyState, VIRTUAL_KEY}, + WindowsAndMessaging::{ + CURSOR_SHOWING, CURSORINFO, GetCursorInfo, GetForegroundWindow, GetWindowTextW, }, - core::{HSTRING, PCWSTR}, }; -pub enum ElevationExitMethod<'a> { - Gentle(&'a mut bool), - Forced, -} - pub fn is_cursor_visible() -> bool { let mut ci = CURSORINFO { cbSize: u32::try_from(std::mem::size_of::()).unwrap(), @@ -42,44 +27,6 @@ pub fn is_any_key_pressed(keys: &[VIRTUAL_KEY]) -> bool { .any(|&key| unsafe { GetAsyncKeyState(i32::from(key.0)) } & i16::MIN != 0) } -pub fn elevate(closing: ElevationExitMethod) { - let exe = std::env::current_exe().unwrap(); - unsafe { - ShellExecuteW( - None, - &HSTRING::from("runas"), - &HSTRING::from(exe.as_path()), - PCWSTR::null(), - PCWSTR::null(), - SW_NORMAL, - ); - } - match closing { - ElevationExitMethod::Gentle(closing) => *closing = true, - ElevationExitMethod::Forced => std::process::exit(0), - } -} - -pub fn is_elevated() -> bool { - let mut token: HANDLE = HANDLE::default(); - if unsafe { OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &raw mut token) }.is_err() { - return false; - } - let mut elevation = TOKEN_ELEVATION::default(); - let mut size = u32::try_from(std::mem::size_of::()).unwrap(); - let result = unsafe { - GetTokenInformation( - token, - TokenElevation, - Some((&raw mut elevation).cast()), - size, - &raw mut size, - ) - }; - unsafe { CloseHandle(token) }.unwrap(); - result.is_ok() && elevation.TokenIsElevated != 0 -} - pub fn is_system_theme_light() -> bool { use winreg::RegKey; let hkcu = RegKey::predef(winreg::enums::HKEY_CURRENT_USER);