diff --git a/Cargo.lock b/Cargo.lock index f7d2172..6fda347 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "W11Boost" -version = "1.4.1" +version = "1.4.2" dependencies = [ "chrono", "curl", @@ -67,9 +67,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "fltk" -version = "1.4.36" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3425eb42cd32d91ecacb9a51abce5eadb95805bc2a5bd0865af296d9c567e55" +checksum = "f182aa7eccef8015c19cd8d1f85da528ca32d2eb3effaccd7c8d4ff22e244174" dependencies = [ "bitflags", "crossbeam-channel", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "fltk-sys" -version = "1.4.36" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6064d919361d236997a98584263cb645d17beff0dd15b151f9bbfd19ddc4d37" +checksum = "02fe436baa9112e5b7f6fcce5274d6b3d9ba9108b29efd02f36f53e436da28da" dependencies = [ "cmake", "cmk", diff --git a/Cargo.toml b/Cargo.toml index 865dfe8..6a251b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "W11Boost" -version = "1.4.1" +version = "1.4.2" edition = "2024" build = "build.rs" authors = ["felikcat"] @@ -8,11 +8,11 @@ authors = ["felikcat"] [package.metadata.winres] CompanyName = "felikcat" FileDescription = "https://github.com/felikcat/W11Boost" -FileVersion = "1.4.1.0" +FileVersion = "1.4.2.0" LegalCopyright = "© 2024 felikcat, AGPL3 License" OriginalFilename = "W11Boost.exe" ProductName = "W11Boost" -ProductVersion = "1.4.1.0" +ProductVersion = "1.4.2.0" # Optimize for size. [profile.release] @@ -24,7 +24,7 @@ codegen-units = 1 [dependencies] fltk-theme = "0.7.3" curl = "0.4.47" -chrono = "0.4.38" +chrono = "0.4.39" widestring = "1.1.0" [dependencies.winsafe] @@ -55,7 +55,7 @@ features = [ ] [dependencies.fltk] -version = "^1.4.36" +version = "^1.5" features = [ "use-ninja" ] diff --git a/Images/W11Boost_GUI.png b/Images/W11Boost_GUI.png index b7388b2..f430274 100644 Binary files a/Images/W11Boost_GUI.png and b/Images/W11Boost_GUI.png differ diff --git a/src/common.rs b/src/common.rs index 97bbe27..2e30fcc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,11 +1,20 @@ use chrono::{Datelike, Timelike, Utc}; use fltk::app; +use windows_sys::Win32::System::SystemServices::MAXIMUM_ALLOWED; +use windows_sys::Win32::System::Threading::{OpenProcess, OpenProcessToken}; use std::error::Error; +use std::os::raw::c_void; use std::fs::{self, OpenOptions}; use std::io::Write; use std::path::PathBuf; +use std::ptr::null_mut; use windows::Win32::Foundation::ERROR_SUCCESS; use windows::Win32::System::Registry::{REG_DWORD, REG_SZ, RegCreateKeyW, RegSetValueExW}; +use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE; +use windows_sys::Win32::Security::{ + DuplicateTokenEx, SECURITY_ATTRIBUTES, SecurityImpersonation, + TOKEN_ALL_ACCESS, TOKEN_DUPLICATE, TokenImpersonation, +}; use windows::core::PCWSTR; use windows::{ Win32::System::{ @@ -345,3 +354,31 @@ pub fn save_registry_gpo( Ok(()) } + +pub fn create_access_token_from_pid(process_id: u32) -> Result<*mut c_void, Box> { + let mut dup_token = INVALID_HANDLE_VALUE; + unsafe { + let process = OpenProcess(MAXIMUM_ALLOWED, 0, process_id); + if !process.is_null() { + let mut token = INVALID_HANDLE_VALUE; + OpenProcessToken(process, TOKEN_DUPLICATE, &mut token); + + let attributes = SECURITY_ATTRIBUTES { + nLength: size_of::() as u32, + lpSecurityDescriptor: null_mut(), + bInheritHandle: 0, + }; + + DuplicateTokenEx( + token, + TOKEN_ALL_ACCESS, + &attributes, + SecurityImpersonation, + TokenImpersonation, + &mut dup_token, + ); + } + } + + Ok(dup_token) +} diff --git a/src/gui.rs b/src/gui.rs index 134ce44..d095fff 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -2,23 +2,31 @@ mod appx_support; mod create_system_restore_point; mod defaults; mod disable_defender_and_smartscreen; +mod disable_recall; mod disable_sleep; mod disable_vbs; mod reduce_forensics; mod reduce_online_data_collection; mod remove_w11boost; -mod disable_recall; +use crate::common::center; use fltk::{ - app::{self, Screen}, button::{Button, CheckButton}, dialog, draw::{self}, enums::{self, Color}, frame::{self}, prelude::*, widget::Widget, window::Window + app::{self, Screen}, + button::{Button, CheckButton}, + dialog, + draw::{self}, + enums::{self, Color}, + frame::{self}, + prelude::*, + widget::Widget, + window::Window, }; use fltk_theme::{ColorTheme, color_themes}; use std::{ - borrow::BorrowMut, cell::RefCell, error::Error, mem, - process::{exit, Command}, + process::{Command, exit}, rc::Rc, }; use windows::Win32::{ @@ -27,7 +35,6 @@ use windows::Win32::{ HWND_TOPMOST, SWP_FRAMECHANGED, SWP_NOMOVE, SWP_NOSIZE, SWP_SHOWWINDOW, SetWindowPos, }, }; -use crate::common::center; type MyCheckboxes = Vec>; @@ -54,13 +61,16 @@ pub fn draw_gui() -> Result<(), Box> { titlebar_close.set_frame(enums::FrameType::NoBox); titlebar_close.set_callback(move |_| exit(0)); - let apply = Rc::new(RefCell::new(Button::new( - 0, - 0, - (wind.width() - 6) / 2, - (wind.height() * 14) / 100, - "Apply W11Boost", - ).center_of(&wind))); + let apply = Rc::new(RefCell::new( + Button::new( + 0, + 0, + (wind.width() - 6) / 2, + (wind.height() * 14) / 100, + "Apply W11Boost", + ) + .center_of(&wind), + )); let remove = Rc::new(RefCell::new(Button::new( wind.width() / 2, @@ -70,29 +80,26 @@ pub fn draw_gui() -> Result<(), Box> { "Remove W11Boost", ))); - let apply = Rc::clone(&apply); - let mut apply_mut = (*apply).borrow_mut(); - - let apply_height = apply_mut.clone().height(); - apply_mut.set_pos(2, wind.height() - apply_height - 2); // Put the apply button at the bottom; wow! - - let remove = Rc::clone(&remove); - let mut remove_mut = (*remove).borrow_mut(); - - remove_mut.clone().center_of(&wind); - - let remove_width = remove_mut.width(); - let remove_height = remove_mut.height(); - remove_mut.set_pos( - wind.width() - remove_width - 2, - wind.height() - remove_height - 2, - ); - - remove_mut.set_label_font(enums::Font::by_name(&font)); - remove_mut.set_label_size(16); + { + let mut apply_mut = apply.borrow_mut(); + let apply_height = apply_mut.height(); + apply_mut.set_pos(2, wind.height() - apply_height - 2); + apply_mut.set_label_font(enums::Font::by_name(&font)); + apply_mut.set_label_size(16); + } - apply_mut.set_label_font(enums::Font::by_name(&font)); - apply_mut.set_label_size(16); + { + let mut remove_mut = remove.borrow_mut(); + remove_mut.clone().center_of(&wind); + let remove_width = remove_mut.width(); + let remove_height = remove_mut.height(); + remove_mut.set_pos( + wind.width() - remove_width - 2, + wind.height() - remove_height - 2, + ); + remove_mut.set_label_font(enums::Font::by_name(&font)); + remove_mut.set_label_size(16); + } let checkbox_height = wind.height() / 12; @@ -167,14 +174,8 @@ pub fn draw_gui() -> Result<(), Box> { checkbox_height, "Disable Windows Recall", )), - RefCell::new(CheckButton::new( - wind.width() / 2, - titlebar.height() + checkbox_height, - wind.width() / 2, - checkbox_height, - "Disable Windows Copilot", - )), - ].to_vec(); + ] + .to_vec(); for checkbox in &my_checkboxes { let mut checkbox = checkbox.borrow_mut(); @@ -185,36 +186,36 @@ pub fn draw_gui() -> Result<(), Box> { my_checkboxes[2].borrow_mut().set_value(true); // "Create a system restore point" my_checkboxes[8].borrow_mut().set_value(true); // "Add in non-intrusive tweaks" - let frame0 = RefCell::new( + let frame0 = Rc::new(RefCell::new( Widget::default() .with_size(wind.width(), wind.height() - titlebar.height()) .with_pos(0, titlebar.height()), - ); - - let frame0 = frame0.clone(); - - frame0 - .borrow_mut() - .set_frame(enums::FrameType::BorderBox); - frame0.borrow_mut().draw(move |f| { - let label = f.label(); - let txt = label.split(" ").nth(0).unwrap(); - let x = f.x(); - let y = f.y(); - let w = f.w(); - let h = f.h(); - - draw::push_clip(x, y, w, h); - draw::draw_box(f.frame(), x, y, w, h, f.color()); - draw::set_draw_color(f.label_color()); - draw::set_font(enums::Font::by_name(&font), 16); - draw::draw_text2(txt, x, y - 16, w, h, f.align()); - draw::pop_clip(); - }); - frame0 - .borrow_mut() - .set_label("Applying W11Boost, please wait..."); - frame0.borrow_mut().hide(); + )); + + { + let frame0 = Rc::clone(&frame0); + frame0.borrow_mut().set_frame(enums::FrameType::BorderBox); + let font = font.clone(); + frame0.borrow_mut().draw(move |f| { + let label = f.label(); + let txt = label.split(" ").nth(0).unwrap(); + let x = f.x(); + let y = f.y(); + let w = f.w(); + let h = f.h(); + + draw::push_clip(x, y, w, h); + draw::draw_box(f.frame(), x, y, w, h, f.color()); + draw::set_draw_color(f.label_color()); + draw::set_font(enums::Font::by_name(&font), 16); + draw::draw_text2(txt, x, y - 16, w, h, f.align()); + draw::pop_clip(); + }); + frame0 + .borrow_mut() + .set_label("Applying W11Boost, please wait..."); + frame0.borrow_mut().hide(); + } wind.end(); wind.show(); @@ -263,17 +264,17 @@ pub fn draw_gui() -> Result<(), Box> { }); fn hide_elements( - frame0: &mut impl WidgetExt, - apply: &mut impl ButtonExt, - remove: &mut impl ButtonExt, + frame0: &Rc>, + apply: &Rc>, + remove: &Rc>, my_checkboxes: &[RefCell], ) { - frame0.show(); - frame0.top_window(); + frame0.borrow_mut().show(); + frame0.borrow_mut().top_window(); // So these aren't accidentally clicked. - apply.hide(); - remove.hide(); + apply.borrow_mut().hide(); + remove.borrow_mut().hide(); for checkbox in my_checkboxes { checkbox.borrow_mut().hide(); } @@ -284,26 +285,26 @@ pub fn draw_gui() -> Result<(), Box> { } fn show_elements( - frame0: &mut impl WidgetExt, - apply: &mut impl ButtonExt, - remove: &mut impl ButtonExt, + frame0: &Rc>, + apply: &Rc>, + remove: &Rc>, my_checkboxes: &[RefCell], ) { // Does not require a manual redraw. - frame0.hide(); - apply.show(); - remove.show(); + frame0.borrow_mut().hide(); + apply.borrow_mut().show(); + remove.borrow_mut().show(); for checkbox in my_checkboxes { checkbox.borrow_mut().show(); } } - - (*apply_mut).set_callback({ - let frame0 = frame0.clone(); - let apply = apply.clone(); - let remove = remove.clone(); - let my_checkboxes = my_checkboxes.clone(); - move |_| { + + { + let frame0 = Rc::clone(&frame0); + let apply_cloned = Rc::clone(&apply); + let remove_cloned = Rc::clone(&remove); + let my_checkboxes_cloned = my_checkboxes.clone(); + apply.borrow_mut().set_callback(move |_| { let choice = dialog::choice2( center().0, center().1, @@ -314,75 +315,81 @@ pub fn draw_gui() -> Result<(), Box> { ); if choice == Some(0) { hide_elements( - &mut *frame0.borrow_mut(), - &mut *(*apply).borrow_mut(), - &mut *(*remove).borrow_mut(), - &my_checkboxes, + &frame0, + &apply_cloned, + &remove_cloned, + &my_checkboxes_cloned, ); // Has to be first! - if let Ok(checkbox) = my_checkboxes[2].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[2].try_borrow() { if checkbox.is_checked() { create_system_restore_point::run() .expect("create_system_restore_point::run failed"); } } - if let Ok(checkbox) = my_checkboxes[0].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[0].try_borrow() { if checkbox.is_checked() { reduce_forensics::run().expect("reduce_forensics::run failed"); } } - if let Ok(checkbox) = my_checkboxes[1].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[1].try_borrow() { if checkbox.is_checked() { reduce_online_data_collection::run() .expect("reduce_online_data_collection::run failed"); } } - if let Ok(checkbox) = my_checkboxes[3].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[3].try_borrow() { if checkbox.is_checked() { - Command::new("wsreset.exe") - .output() + let mut child = Command::new("wsreset.exe") + .args(&["-i"]) + .spawn() .expect("wsreset.exe failed to execute"); + + child.wait().expect("wsreset.exe -> failed to wait for the child process"); } } - if let Ok(checkbox) = my_checkboxes[4].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[4].try_borrow() { if checkbox.is_checked() { appx_support::install().expect("appx_support::install failed"); } } - if let Ok(checkbox) = my_checkboxes[5].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[5].try_borrow() { if checkbox.is_checked() { disable_defender_and_smartscreen::run() .expect("disable_defender_and_smartscreen::run failed"); } } - if let Ok(checkbox) = my_checkboxes[6].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[6].try_borrow() { if checkbox.is_checked() { disable_sleep::run().expect("disable_sleep::run failed"); } } - if let Ok(checkbox) = my_checkboxes[7].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[7].try_borrow() { if checkbox.is_checked() { disable_vbs::run().expect("disable_vbs::run failed"); } } - if let Ok(checkbox) = my_checkboxes[8].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[8].try_borrow() { if checkbox.is_checked() { defaults::run().expect("defaults::run failed"); } } - if let Ok(checkbox) = my_checkboxes[9].try_borrow_mut() { + if let Ok(checkbox) = my_checkboxes_cloned[9].try_borrow() { if checkbox.is_checked() { disable_recall::run().expect("disable_recall::run failed"); } } - if my_checkboxes.iter().all(|checkbox| checkbox.try_borrow_mut().map_or(false, | cb| !cb.is_checked())) { + if my_checkboxes_cloned + .iter() + .all(|checkbox| checkbox.borrow().value() == false) + { dialog::message( center().0, center().1, @@ -397,21 +404,21 @@ pub fn draw_gui() -> Result<(), Box> { } show_elements( - &mut *frame0.borrow_mut(), - &mut *(*apply).borrow_mut(), - &mut *(*remove).borrow_mut(), - &my_checkboxes, + &frame0, + &apply_cloned, + &remove_cloned, + &my_checkboxes_cloned, ); } - } - }); + }); + } - (*remove_mut).borrow_mut().set_callback({ - let frame0 = frame0.clone(); - let apply = apply.clone(); - let remove = remove.clone(); - let my_checkboxes = my_checkboxes.clone(); - move |_| { + { + let frame0 = Rc::clone(&frame0); + let apply_cloned = Rc::clone(&apply); + let remove_cloned = Rc::clone(&remove); + let my_checkboxes_cloned = my_checkboxes.clone(); + remove.borrow_mut().set_callback(move |_| { let choice = dialog::choice2( center().0, center().1, @@ -422,32 +429,32 @@ pub fn draw_gui() -> Result<(), Box> { ); if choice == Some(0) { hide_elements( - &mut *frame0.borrow_mut(), - &mut *(*apply).borrow_mut(), - &mut *(*remove).borrow_mut(), - &my_checkboxes, + &frame0, + &apply_cloned, + &remove_cloned, + &my_checkboxes_cloned, ); if let Ok(_) = remove_w11boost::run() { dialog::message( center().0, center().1, - "W11Boost applied your preferences successfully, please reboot.", + "W11Boost has been removed successfully, please reboot.", ); } else { eprintln!("remove_w11boost::run failed"); } show_elements( - &mut *frame0.borrow_mut(), - &mut *(*apply).borrow_mut(), - &mut *(*remove).borrow_mut(), - &my_checkboxes, + &frame0, + &apply_cloned, + &remove_cloned, + &my_checkboxes_cloned, ); } - } - }); + }); + } app.run().unwrap(); - + Ok(()) } diff --git a/src/gui/appx_support.rs b/src/gui/appx_support.rs index a8c78bd..cc8beec 100644 --- a/src/gui/appx_support.rs +++ b/src/gui/appx_support.rs @@ -34,13 +34,14 @@ pub fn install() -> Result<(), Box> { easy.perform() .expect("appx_support::install -> Failed to curl perform"); - Command::new("powershell.exe") + let mut child = Command::new("powershell.exe") .args([ "-Command", - r#"Add-AppxPackage ([Environment]::GetFolderPath("CommonDesktopDirectory") + "\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle""# + r#"Add-AppxPackage ([Environment]::GetFolderPath("CommonDesktopDirectory") + "\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle")"# ]) - .output() + .spawn() .expect("appx_support::install -> Failed to install the msixbundle"); + child.wait().expect("appx_support::install -> Failed to wait for the child process"); Ok(()) } diff --git a/src/main.rs b/src/main.rs index f0651d0..c3142f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,30 +1,26 @@ pub mod common; mod gui; -use common::center; +use common::{center, create_access_token_from_pid}; use fltk::dialog; use gui::draw_gui; +use windows_sys::Win32::Security::ImpersonateLoggedOnUser; use std::error::Error; -use std::os::raw::c_void; use std::ptr::null_mut; use std::time::Duration; use std::{mem, thread}; +use windows_sys::Win32::Foundation::CloseHandle; use windows::Win32::System::Services::{ CloseServiceHandle, OpenSCManagerW, OpenServiceW, QueryServiceStatusEx, SC_MANAGER_CONNECT, SC_STATUS_PROCESS_INFO, SERVICE_QUERY_STATUS, SERVICE_RUNNING, SERVICE_START, SERVICE_STATUS_PROCESS, SERVICE_STOPPED, StartServiceW, }; use windows::core::w; -use windows_sys::Win32::Foundation::{CloseHandle, INVALID_HANDLE_VALUE}; -use windows_sys::Win32::Security::{ - DuplicateTokenEx, ImpersonateLoggedOnUser, SECURITY_ATTRIBUTES, SecurityImpersonation, - TOKEN_ALL_ACCESS, TOKEN_DUPLICATE, TokenImpersonation, -}; use windows_sys::Win32::System::SystemServices::MAXIMUM_ALLOWED; use windows_sys::Win32::System::Threading::{ CREATE_UNICODE_ENVIRONMENT, CreateProcessWithTokenW, LOGON_WITH_PROFILE, OpenProcessToken, PROCESS_INFORMATION, STARTUPINFOW, }; -use windows_sys::Win32::System::Threading::{GetCurrentProcess, OpenProcess}; +use windows_sys::Win32::System::Threading::GetCurrentProcess; use winsafe::{self as ws, co, prelude::*}; fn get_pid_from_process_name(process_name: &str) -> Result> { @@ -63,34 +59,6 @@ fn impersonate_as_system() -> Result> { Ok(success) } -fn create_access_token_from_pid(process_id: u32) -> Result<*mut c_void, Box> { - let mut dup_token = INVALID_HANDLE_VALUE; - unsafe { - let process = OpenProcess(MAXIMUM_ALLOWED, 0, process_id); - if !process.is_null() { - let mut token = INVALID_HANDLE_VALUE; - OpenProcessToken(process, TOKEN_DUPLICATE, &mut token); - - let attributes = SECURITY_ATTRIBUTES { - nLength: size_of::() as u32, - lpSecurityDescriptor: null_mut(), - bInheritHandle: 0, - }; - - DuplicateTokenEx( - token, - TOKEN_ALL_ACCESS, - &attributes, - SecurityImpersonation, - TokenImpersonation, - &mut dup_token, - ); - } - } - - Ok(dup_token) -} - fn start_trusted_installer_service() -> Result> { const SLEEP_INTERVAL: u64 = 100; const MAX_ATTEMPTS: u32 = 50; // 50 * 100ms = 5 seconds