diff --git a/Cargo.lock b/Cargo.lock index ab3c6696..1572ca04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1612,7 +1612,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.51.1", ] [[package]] @@ -2887,7 +2887,7 @@ dependencies = [ "urlencoding", "versions", "which", - "windows 0.48.0", + "windows 0.52.0", "winres", "yaml-rust", ] @@ -3483,21 +3483,22 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ + "windows-core 0.51.1", "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", - "windows-targets 0.48.5", + "windows-core 0.52.0", + "windows-targets 0.52.0", ] [[package]] @@ -3509,6 +3510,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 1a9f2a44..a637aa03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,7 +104,7 @@ features = ["preserve_order", "indexmap2"] deelevate = "0.2.0" [target.'cfg(windows)'.dependencies.windows] -version = "0.48.0" +version = "0.52.0" features = [ "Win32_Foundation", "Win32_UI_Shell", diff --git a/src/modules/utils/directory_win.rs b/src/modules/utils/directory_win.rs index 61760c8a..b34c570d 100644 --- a/src/modules/utils/directory_win.rs +++ b/src/modules/utils/directory_win.rs @@ -3,7 +3,7 @@ use std::{mem, os::windows::ffi::OsStrExt, path::Path}; use windows::{ core::PCWSTR, Win32::{ - Foundation::{CloseHandle, ERROR_INSUFFICIENT_BUFFER, HANDLE}, + Foundation::{CloseHandle, BOOL, ERROR_INSUFFICIENT_BUFFER, HANDLE}, Security::{ AccessCheck, DuplicateToken, GetFileSecurityW, MapGenericMask, SecurityImpersonation, DACL_SECURITY_INFORMATION, GENERIC_MAPPING, GROUP_SECURITY_INFORMATION, @@ -17,6 +17,17 @@ use windows::{ UI::Shell::PathIsNetworkPathW, }, }; + +struct Handle(HANDLE); + +impl Drop for Handle { + fn drop(&mut self) { + if let Err(e) = unsafe { CloseHandle(self.0) } { + log::debug!("CloseHandle failed: {e:?}"); + } + } +} + /// Checks if the current user has write access right to the `folder_path` /// /// First, the function extracts DACL from the given directory and then calls `AccessCheck` against @@ -71,27 +82,35 @@ pub fn is_write_allowed(folder_path: &Path) -> std::result::Result )); } - let mut token = HANDLE::default(); - let rc = unsafe { - OpenProcessToken( - GetCurrentProcess(), - TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_READ_CONTROL, - &mut token, - ) + let token = { + let mut token = HANDLE::default(); + + let rc = unsafe { + OpenProcessToken( + GetCurrentProcess(), + TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_READ_CONTROL, + &mut token, + ) + }; + if let Err(e) = rc { + return Err(format!( + "OpenProcessToken failed to retrieve current process' security token: {e:?}" + )); + } + + Handle(token) }; - if let Err(e) = rc.ok() { - return Err(format!( - "OpenProcessToken failed to retrieve current process' security token: {e:?}" - )); - } - let mut impersonated_token = HANDLE::default(); - let rc = unsafe { DuplicateToken(token, SecurityImpersonation, &mut impersonated_token) }; + let impersonated_token = { + let mut impersonated_token = HANDLE::default(); + let rc = unsafe { DuplicateToken(token.0, SecurityImpersonation, &mut impersonated_token) }; - if let Err(e) = rc.ok() { - unsafe { CloseHandle(token) }; - return Err(format!("DuplicateToken failed: {e:?}")); - } + if let Err(e) = rc { + return Err(format!("DuplicateToken failed: {e:?}")); + } + + Handle(impersonated_token) + }; let mapping = GENERIC_MAPPING { GenericRead: FILE_GENERIC_READ.0, @@ -104,12 +123,12 @@ pub fn is_write_allowed(folder_path: &Path) -> std::result::Result let mut priv_size = mem::size_of::() as _; let mut granted_access = 0; let mut access_rights = FILE_GENERIC_WRITE; - let mut result = 0; + let mut result = BOOL::default(); unsafe { MapGenericMask(&mut access_rights.0, &mapping) }; let rc = unsafe { AccessCheck( psecurity_descriptor, - impersonated_token, + impersonated_token.0, access_rights.0, &mapping, Some(&mut privileges), @@ -118,14 +137,10 @@ pub fn is_write_allowed(folder_path: &Path) -> std::result::Result &mut result, ) }; - unsafe { - CloseHandle(impersonated_token); - CloseHandle(token); - } - if let Err(e) = rc.ok() { + if let Err(e) = rc { return Err(format!("AccessCheck failed: {e:?}")); } - Ok(result != 0) + Ok(result.as_bool()) }