diff --git a/crates/win-api-wrappers/src/process.rs b/crates/win-api-wrappers/src/process.rs index 6d190551..0a8b83bc 100644 --- a/crates/win-api-wrappers/src/process.rs +++ b/crates/win-api-wrappers/src/process.rs @@ -563,7 +563,9 @@ impl ProcessEntry32Iterator { // SAFETY: It is safe to zero out the structure as it is a simple POD type. let mut process_entry: PROCESSENTRY32W = unsafe { mem::zeroed() }; - process_entry.dwSize = mem::size_of::().try_into().unwrap(); + process_entry.dwSize = mem::size_of::() + .try_into() + .expect("BUG: PROCESSENTRY32W size always fits in u32"); Ok(ProcessEntry32Iterator { snapshot_handle, @@ -616,7 +618,7 @@ impl ProcessEntry { .szExeFile .iter() .position(|&c| c == 0) - .ok_or(anyhow!("Executable name null terminator not found"))?; + .ok_or_else(|| anyhow!("Executable name null terminator not found"))?; let name = String::from_utf16(&self.0.szExeFile[..exe_name_length]) .map_err(|_| anyhow!("Invalid executable name UTF16 encoding"))?; @@ -641,18 +643,15 @@ impl ProcessEnvironment { impl Drop for ProcessEnvironment { fn drop(&mut self) { - match self { - ProcessEnvironment::OsDefined(block) => { - // SAFETY: `block` is checked to be valid before free. - unsafe { - if !block.is_null() { - if let Err(err) = DestroyEnvironmentBlock(*block) { - warn!(%err, "Failed to destroy environment block"); - } + if let ProcessEnvironment::OsDefined(block) = self { + // SAFETY: `block` is checked to be valid before free. + unsafe { + if !block.is_null() { + if let Err(err) = DestroyEnvironmentBlock(*block) { + warn!(%err, "Failed to destroy environment block"); } - }; - } - _ => {} + } + }; } } } @@ -680,10 +679,11 @@ pub fn create_process_as_user( let mut environment: *mut c_void = ptr::null_mut(); if let Some(token) = token { + // SAFETY: Allocated memory will be freed by `ProcessEnvironment` destructor. unsafe { CreateEnvironmentBlock(&mut environment, token.handle().raw(), false) }?; } - ProcessEnvironment::OsDefined(environment as *const _) + ProcessEnvironment::OsDefined(environment.cast_const()) }; let mut command_line = command_line @@ -728,6 +728,7 @@ pub fn create_process_as_user( /// Starts new process in the specified session. Note that this function requires the current /// process to have `SYSTEM`-level permissions. Use with caution. +#[allow(clippy::too_many_arguments)] pub fn create_process_in_session( session_id: u32, application_name: Option<&Path>, @@ -826,6 +827,7 @@ fn terminate_process_by_name_impl(process_name: &str, session_id: Option) - match process { Ok(process) => { + // SAFETY: `OpenProcess` ensures that the handle is valid. unsafe { if let Err(err) = TerminateProcess(process, 1) { warn!(process_name, session_id, %err, "TerminateProcess failed"); diff --git a/crates/win-api-wrappers/src/security/privilege.rs b/crates/win-api-wrappers/src/security/privilege.rs index 1a97163b..af39efcb 100644 --- a/crates/win-api-wrappers/src/security/privilege.rs +++ b/crates/win-api-wrappers/src/security/privilege.rs @@ -146,11 +146,11 @@ impl<'a> ScopedPrivileges<'a> { } pub fn token(&self) -> &Token { - &self.token + self.token } pub fn token_mut(&mut self) -> &mut Token { - &mut self.token + self.token } } diff --git a/devolutions-agent/build.rs b/devolutions-agent/build.rs index 8c8bcedf..a98c06e2 100644 --- a/devolutions-agent/build.rs +++ b/devolutions-agent/build.rs @@ -8,10 +8,10 @@ mod win { use std::{env, fs}; pub(super) fn embed_version_rc() { - let out_dir = env::var("OUT_DIR").unwrap(); + let out_dir = env::var("OUT_DIR").expect("BUG: failed to get OUT_DIR"); let version_rc_file = format!("{}/version.rc", out_dir); let version_rc_data = generate_version_rc(); - fs::write(&version_rc_file, version_rc_data).unwrap(); + fs::write(&version_rc_file, version_rc_data).expect("BUG: failed to write version.rc"); embed_resource::compile(&version_rc_file, embed_resource::NONE); embed_resource::compile("resources.rc", embed_resource::NONE); @@ -23,7 +23,8 @@ mod win { let company_name = "Devolutions Inc."; let legal_copyright = format!("Copyright 2020-2024 {}", company_name); - let version_number = env::var("CARGO_PKG_VERSION").unwrap() + ".0"; + let mut version_number = env::var("CARGO_PKG_VERSION").expect("BUG: failed to get CARGO_PKG_VERSION"); + version_number.push_str(".0"); let version_commas = version_number.replace('.', ","); let file_description = output_name; let file_version = version_number.clone(); diff --git a/devolutions-agent/src/config.rs b/devolutions-agent/src/config.rs index 6695df93..0385bd78 100644 --- a/devolutions-agent/src/config.rs +++ b/devolutions-agent/src/config.rs @@ -262,6 +262,7 @@ pub mod dto { pub enabled: bool, } + #[allow(clippy::derivable_impls)] // Just to be explicit about the default values of the config. impl Default for SessionHostConf { fn default() -> Self { Self { enabled: false } diff --git a/devolutions-agent/src/session_manager/mod.rs b/devolutions-agent/src/session_manager/mod.rs index 88d82577..d5e0a816 100644 --- a/devolutions-agent/src/session_manager/mod.rs +++ b/devolutions-agent/src/session_manager/mod.rs @@ -199,13 +199,13 @@ impl Task for SessionManager { } AgentServiceEvent::SessionLogoff(id) => { info!(%id, "Session logged off"); - ctx.write().await.get_session_mut(&id).map(|session| { + if let Some(mut session) = ctx.write().await.get_session_mut(&id) { // When a user logs off, host process will be stopped by the system; // Console sessions could be reused for different users, therefore // we should not remove the session from the list, but mark it as // not yet ready (host will be started as soon as new user logs in). session.set_host_ready(false); - }); + } } _ => { continue; @@ -225,16 +225,16 @@ impl Task for SessionManager { /// Starts Devolutions Host process in the target session. fn try_start_host_process(ctx: &mut SessionManagerCtx, session: &Session) -> anyhow::Result<()> { - match ctx.get_session_mut(&session) { + match ctx.get_session_mut(session) { Some(gw_session) => { - if is_host_running_in_session(&session)? { + if is_host_running_in_session(session)? { gw_session.set_host_ready(true); return Ok(()); } info!(%session, "Starting host process in session"); - match start_host_process(&session) { + match start_host_process(session) { Ok(()) => { info!(%session, "Host process started in session"); gw_session.set_host_ready(true); @@ -285,7 +285,11 @@ fn start_host_process(session: &Session) -> anyhow::Result<()> { let mut startup_info = StartupInfo::default(); // Run with GUI access - startup_info.show_window = SW_SHOW.0 as u16; + // NOTE: silent clippy warning, just to be more explicit about `show_window` value + #[allow(clippy::field_reassign_with_default)] + { + startup_info.show_window = u16::try_from(SW_SHOW.0).expect("BUG: SW_SHOW always fit u16"); + } startup_info.flags = STARTF_USESHOWWINDOW; startup_info.desktop = WideString::from("WinSta0\\Default"); diff --git a/devolutions-host/build.rs b/devolutions-host/build.rs index 83911597..0b96bd32 100644 --- a/devolutions-host/build.rs +++ b/devolutions-host/build.rs @@ -8,10 +8,10 @@ mod win { use std::{env, fs}; pub(super) fn embed_version_rc() { - let out_dir = env::var("OUT_DIR").unwrap(); + let out_dir = env::var("OUT_DIR").expect("BUG: failed to get OUT_DIR"); let version_rc_file = format!("{}/version.rc", out_dir); let version_rc_data = generate_version_rc(); - fs::write(&version_rc_file, version_rc_data).unwrap(); + fs::write(&version_rc_file, version_rc_data).expect("BUG: failed to write version.rc"); embed_resource::compile(&version_rc_file, embed_resource::NONE); } @@ -22,7 +22,8 @@ mod win { let company_name = "Devolutions Inc."; let legal_copyright = format!("Copyright 2020-2024 {}", company_name); - let version_number = env::var("CARGO_PKG_VERSION").unwrap() + ".0"; + let mut version_number = env::var("CARGO_PKG_VERSION").expect("BUG: failed to get CARGO_PKG_VERSION"); + version_number.push_str(".0"); let version_commas = version_number.replace('.', ","); let file_description = output_name; let file_version = version_number.clone(); diff --git a/devolutions-host/src/dvc.rs b/devolutions-host/src/dvc.rs index 240e2c20..695a7082 100644 --- a/devolutions-host/src/dvc.rs +++ b/devolutions-host/src/dvc.rs @@ -41,6 +41,8 @@ pub fn loop_dvc(config: ConfHandle) { info!("DVC loop finished"); } +#[allow(clippy::multiple_unsafe_ops_per_block)] +#[allow(clippy::undocumented_unsafe_blocks)] fn open_virtual_channel(channel_name: &str) -> windows::core::Result { unsafe { let channel_name_wide = PCSTR::from_raw(channel_name.as_ptr()); @@ -76,6 +78,8 @@ fn open_virtual_channel(channel_name: &str) -> windows::core::Result { } } +#[allow(clippy::multiple_unsafe_ops_per_block)] +#[allow(clippy::undocumented_unsafe_blocks)] fn write_virtual_channel_message(h_file: HANDLE, cb_size: u32, buffer: *const u8) -> windows::core::Result<()> { unsafe { let buffer_slice = std::slice::from_raw_parts(buffer, cb_size as usize); @@ -86,6 +90,10 @@ fn write_virtual_channel_message(h_file: HANDLE, cb_size: u32, buffer: *const u8 #[allow(clippy::cast_possible_wrap)] #[allow(clippy::cast_ptr_alignment)] +#[allow(clippy::ptr_offset_with_cast)] +#[allow(clippy::cast_possible_truncation)] +#[allow(clippy::multiple_unsafe_ops_per_block)] +#[allow(clippy::undocumented_unsafe_blocks)] fn handle_virtual_channel(h_file: HANDLE) -> windows::core::Result<()> { unsafe { let mut read_buffer = [0u8; CHANNEL_PDU_LENGTH]; @@ -111,7 +119,7 @@ fn handle_virtual_channel(h_file: HANDLE) -> windows::core::Result<()> { if let Err(e) = result { if GetLastError() == WIN32_ERROR(ERROR_IO_PENDING.0) { let _dw_status = WaitForSingleObject(h_event, INFINITE); - if !GetOverlappedResult(h_file, &mut overlapped, &mut dw_read, false).is_ok() { + if GetOverlappedResult(h_file, &overlapped, &mut dw_read, false).is_err() { return Err(windows::core::Error::from_win32()); } } else { @@ -119,14 +127,14 @@ fn handle_virtual_channel(h_file: HANDLE) -> windows::core::Result<()> { } } - println!("read {} bytes", dw_read); + info!("read {} bytes", dw_read); let packet_size = dw_read as usize - std::mem::size_of::(); let p_data = read_buffer .as_ptr() - .offset(std::mem::size_of::() as isize) as *const u8; + .offset(std::mem::size_of::() as isize); - println!( + info!( ">> {}", std::str::from_utf8(std::slice::from_raw_parts(p_data, packet_size)).unwrap_or("Invalid UTF-8") ); diff --git a/devolutions-host/src/main.rs b/devolutions-host/src/main.rs index b94f7a7a..648394b3 100644 --- a/devolutions-host/src/main.rs +++ b/devolutions-host/src/main.rs @@ -1,6 +1,6 @@ // Start the program without a console window. // It has no effect on platforms other than Windows. -#![windows_subsystem = "windows"] +#![cfg_attr(windows, windows_subsystem = "windows")] #[macro_use] extern crate tracing;