mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-13 21:52:37 +00:00
move winapi to windows
This commit is contained in:
parent
f014138a0c
commit
c1c8958fd0
4 changed files with 142 additions and 81 deletions
69
Cargo.lock
generated
69
Cargo.lock
generated
|
@ -441,7 +441,7 @@ dependencies = [
|
|||
"users",
|
||||
"version_check",
|
||||
"wild",
|
||||
"winapi",
|
||||
"windows",
|
||||
"xattr",
|
||||
"xdg",
|
||||
"yaml-rust",
|
||||
|
@ -1037,49 +1037,106 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "0.2.2"
|
||||
|
|
|
@ -45,7 +45,7 @@ users = "0.11.*"
|
|||
xattr = "0.2.*"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = {version = "0.3.*", features = ["aclapi", "accctrl", "winnt", "winerror", "securitybaseapi", "winbase"]}
|
||||
windows = { version = "0.43.0", features = ["Win32_Foundation", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_Memory"] }
|
||||
|
||||
[dependencies.clap]
|
||||
features = ["suggestions", "color", "wrap_help"]
|
||||
|
|
|
@ -25,7 +25,7 @@ extern crate yaml_rust;
|
|||
extern crate users;
|
||||
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
extern crate windows;
|
||||
|
||||
mod app;
|
||||
mod color;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use std::ffi::{OsStr, OsString};
|
||||
use std::io;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
use std::path::Path;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use winapi::ctypes::c_void;
|
||||
use winapi::shared::winerror;
|
||||
use winapi::um::accctrl::TRUSTEE_W;
|
||||
use winapi::um::winnt;
|
||||
use windows::Win32::Foundation::PSID;
|
||||
use windows::Win32::Security::{self, Authorization::TRUSTEE_W, ACL};
|
||||
|
||||
use super::{Owner, Permissions};
|
||||
|
||||
|
@ -30,10 +28,10 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
// These pointers will be populated by GetNamedSecurityInfoW
|
||||
// sd_ptr points at a new buffer that must be freed
|
||||
// The others point at (opaque) things inside that buffer
|
||||
let mut owner_sid_ptr = null_mut();
|
||||
let mut group_sid_ptr = null_mut();
|
||||
let mut dacl_ptr = null_mut();
|
||||
let mut sd_ptr = null_mut();
|
||||
let mut owner_sid_ptr = MaybeUninit::uninit();
|
||||
let mut group_sid_ptr = MaybeUninit::uninit();
|
||||
let mut dacl_ptr = MaybeUninit::uninit();
|
||||
let mut sd_ptr = MaybeUninit::uninit();
|
||||
|
||||
// Assumptions:
|
||||
// - windows_path is a null-terminated WTF-16-encoded string
|
||||
|
@ -43,28 +41,32 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
// flags are set
|
||||
// - sd_ptr must be freed with LocalFree
|
||||
let error_code = unsafe {
|
||||
winapi::um::aclapi::GetNamedSecurityInfoW(
|
||||
windows_path.as_ptr(),
|
||||
winapi::um::accctrl::SE_FILE_OBJECT,
|
||||
winnt::OWNER_SECURITY_INFORMATION
|
||||
| winnt::GROUP_SECURITY_INFORMATION
|
||||
| winnt::DACL_SECURITY_INFORMATION,
|
||||
&mut owner_sid_ptr,
|
||||
&mut group_sid_ptr,
|
||||
&mut dacl_ptr,
|
||||
null_mut(),
|
||||
&mut sd_ptr,
|
||||
Security::Authorization::GetNamedSecurityInfoW(
|
||||
windows::core::PCWSTR::from_raw(windows_path.as_ptr()),
|
||||
Security::Authorization::SE_FILE_OBJECT,
|
||||
Security::OWNER_SECURITY_INFORMATION
|
||||
| Security::GROUP_SECURITY_INFORMATION
|
||||
| Security::DACL_SECURITY_INFORMATION,
|
||||
Some(owner_sid_ptr.as_mut_ptr()),
|
||||
Some(group_sid_ptr.as_mut_ptr()),
|
||||
Some(dacl_ptr.as_mut_ptr()),
|
||||
None,
|
||||
sd_ptr.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
|
||||
if error_code != winerror::ERROR_SUCCESS {
|
||||
return Err(std::io::Error::from_raw_os_error(error_code as i32));
|
||||
if error_code.is_err() {
|
||||
return Err(std::io::Error::from_raw_os_error(error_code.0 as i32));
|
||||
}
|
||||
|
||||
// Assumptions:
|
||||
// - owner_sid_ptr is valid
|
||||
// - group_sid_ptr is valid
|
||||
// (both OK because GetNamedSecurityInfoW returned success)
|
||||
let owner_sid_ptr = unsafe { owner_sid_ptr.assume_init() };
|
||||
let group_sid_ptr = unsafe { group_sid_ptr.assume_init() };
|
||||
let dacl_ptr = unsafe { dacl_ptr.assume_init() };
|
||||
let sd_ptr = unsafe { sd_ptr.assume_init() };
|
||||
|
||||
let owner = match unsafe { lookup_account_sid(owner_sid_ptr) } {
|
||||
Ok((n, d)) => {
|
||||
|
@ -104,8 +106,9 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
// Assumptions: None
|
||||
// "This function cannot fail"
|
||||
// -- Windows Dev Center docs
|
||||
let mut world_sid_len: u32 = unsafe { winapi::um::securitybaseapi::GetSidLengthRequired(1) };
|
||||
let mut world_sid_len: u32 = unsafe { Security::GetSidLengthRequired(1) };
|
||||
let mut world_sid = vec![0u8; world_sid_len as usize];
|
||||
let world_sid_ptr = PSID(world_sid.as_mut_ptr() as *mut _);
|
||||
|
||||
// Assumptions:
|
||||
// - world_sid_len is no larger than the number of bytes available at
|
||||
|
@ -113,61 +116,65 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
// - world_sid is appropriately aligned (if there are strange crashes this
|
||||
// might be why)
|
||||
let result = unsafe {
|
||||
winapi::um::securitybaseapi::CreateWellKnownSid(
|
||||
winnt::WinWorldSid,
|
||||
null_mut(),
|
||||
world_sid.as_mut_ptr() as *mut _,
|
||||
Security::CreateWellKnownSid(
|
||||
Security::WinWorldSid,
|
||||
PSID::default(),
|
||||
world_sid_ptr,
|
||||
&mut world_sid_len,
|
||||
)
|
||||
};
|
||||
|
||||
if result == 0 {
|
||||
if result.ok().is_err() {
|
||||
// Failed to create the SID
|
||||
// Assumptions: Same as the other identical calls
|
||||
unsafe {
|
||||
winapi::um::winbase::LocalFree(sd_ptr);
|
||||
windows::Win32::System::Memory::LocalFree(sd_ptr.0 as _);
|
||||
}
|
||||
|
||||
// Assumptions: None (GetLastError shouldn't ever fail)
|
||||
return Err(io::Error::from_raw_os_error(unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
windows::Win32::Foundation::GetLastError().0
|
||||
} as i32));
|
||||
}
|
||||
|
||||
// Assumptions:
|
||||
// - xxxxx_sid_ptr are valid pointers to SIDs
|
||||
// - xxxxx_trustee is only valid as long as its SID pointer is
|
||||
let mut owner_trustee = unsafe { trustee_from_sid(owner_sid_ptr) };
|
||||
let mut group_trustee = unsafe { trustee_from_sid(group_sid_ptr) };
|
||||
let mut world_trustee = unsafe { trustee_from_sid(world_sid.as_mut_ptr() as *mut _) };
|
||||
let owner_trustee = unsafe { trustee_from_sid(owner_sid_ptr) };
|
||||
let group_trustee = unsafe { trustee_from_sid(group_sid_ptr) };
|
||||
let world_trustee = unsafe { trustee_from_sid(world_sid_ptr) };
|
||||
|
||||
// Assumptions:
|
||||
// - xxxxx_trustee are still valid (including underlying SID)
|
||||
// - dacl_ptr is still valid
|
||||
let owner_access_mask = unsafe { get_acl_access_mask(dacl_ptr as *mut _, &mut owner_trustee) }?;
|
||||
let owner_access_mask = unsafe { get_acl_access_mask(dacl_ptr, &owner_trustee) }?;
|
||||
|
||||
let group_access_mask = unsafe { get_acl_access_mask(dacl_ptr as *mut _, &mut group_trustee) }?;
|
||||
let group_access_mask = unsafe { get_acl_access_mask(dacl_ptr, &group_trustee) }?;
|
||||
|
||||
let world_access_mask = unsafe { get_acl_access_mask(dacl_ptr as *mut _, &mut world_trustee) }?;
|
||||
let world_access_mask = unsafe { get_acl_access_mask(dacl_ptr, &world_trustee) }?;
|
||||
|
||||
let has_bit = |field: u32, bit: u32| field & bit != 0;
|
||||
let permissions = {
|
||||
use windows::Win32::Storage::FileSystem::{
|
||||
FILE_ACCESS_FLAGS, FILE_GENERIC_EXECUTE, FILE_GENERIC_READ, FILE_GENERIC_WRITE,
|
||||
};
|
||||
let has_bit = |field: u32, bit: FILE_ACCESS_FLAGS| field & bit.0 != 0;
|
||||
Permissions {
|
||||
user_read: has_bit(owner_access_mask, FILE_GENERIC_READ),
|
||||
user_write: has_bit(owner_access_mask, FILE_GENERIC_WRITE),
|
||||
user_execute: has_bit(owner_access_mask, FILE_GENERIC_EXECUTE),
|
||||
|
||||
let permissions = Permissions {
|
||||
user_read: has_bit(owner_access_mask, winnt::FILE_GENERIC_READ),
|
||||
user_write: has_bit(owner_access_mask, winnt::FILE_GENERIC_WRITE),
|
||||
user_execute: has_bit(owner_access_mask, winnt::FILE_GENERIC_EXECUTE),
|
||||
group_read: has_bit(group_access_mask, FILE_GENERIC_READ),
|
||||
group_write: has_bit(group_access_mask, FILE_GENERIC_WRITE),
|
||||
group_execute: has_bit(group_access_mask, FILE_GENERIC_EXECUTE),
|
||||
|
||||
group_read: has_bit(group_access_mask, winnt::FILE_GENERIC_READ),
|
||||
group_write: has_bit(group_access_mask, winnt::FILE_GENERIC_WRITE),
|
||||
group_execute: has_bit(group_access_mask, winnt::FILE_GENERIC_EXECUTE),
|
||||
other_read: has_bit(world_access_mask, FILE_GENERIC_READ),
|
||||
other_write: has_bit(world_access_mask, FILE_GENERIC_WRITE),
|
||||
other_execute: has_bit(world_access_mask, FILE_GENERIC_EXECUTE),
|
||||
|
||||
other_read: has_bit(world_access_mask, winnt::FILE_GENERIC_READ),
|
||||
other_write: has_bit(world_access_mask, winnt::FILE_GENERIC_WRITE),
|
||||
other_execute: has_bit(world_access_mask, winnt::FILE_GENERIC_EXECUTE),
|
||||
|
||||
sticky: false,
|
||||
setuid: false,
|
||||
setgid: false,
|
||||
sticky: false,
|
||||
setuid: false,
|
||||
setgid: false,
|
||||
}
|
||||
};
|
||||
|
||||
// Assumptions:
|
||||
|
@ -177,7 +184,7 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
// options. It's not much memory, so leaking it on failure is
|
||||
// *probably* fine)
|
||||
unsafe {
|
||||
winapi::um::winbase::LocalFree(sd_ptr);
|
||||
windows::Win32::System::Memory::LocalFree(sd_ptr.0 as _);
|
||||
}
|
||||
|
||||
Ok((owner, permissions))
|
||||
|
@ -190,24 +197,21 @@ pub fn get_file_data(path: &Path) -> Result<(Owner, Permissions), io::Error> {
|
|||
/// - trustee_ptr points to a valid trustee data structure
|
||||
/// - Both remain valid through the function call (no long-term requirement)
|
||||
unsafe fn get_acl_access_mask(
|
||||
acl_ptr: *mut c_void,
|
||||
trustee_ptr: *mut TRUSTEE_W,
|
||||
acl_ptr: *const ACL,
|
||||
trustee_ptr: *const TRUSTEE_W,
|
||||
) -> Result<u32, io::Error> {
|
||||
let mut access_mask = 0;
|
||||
|
||||
// Assumptions:
|
||||
// - All function assumptions
|
||||
// - Result is not valid until return value is checked
|
||||
let err_code = winapi::um::aclapi::GetEffectiveRightsFromAclW(
|
||||
acl_ptr as *mut _,
|
||||
trustee_ptr,
|
||||
&mut access_mask,
|
||||
);
|
||||
let err_code =
|
||||
Security::Authorization::GetEffectiveRightsFromAclW(acl_ptr, trustee_ptr, &mut access_mask);
|
||||
|
||||
if err_code == winerror::ERROR_SUCCESS {
|
||||
if err_code.is_ok() {
|
||||
Ok(access_mask)
|
||||
} else {
|
||||
Err(io::Error::from_raw_os_error(err_code as i32))
|
||||
Err(io::Error::from_raw_os_error(err_code.0 as i32))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,10 +223,10 @@ unsafe fn get_acl_access_mask(
|
|||
/// Note: winapi's TRUSTEE_W looks different from the one in the MS docs because
|
||||
/// of some unusual pre-processor macros in the original .h file. The winapi
|
||||
/// version is correct (MS's doc generator messed up)
|
||||
unsafe fn trustee_from_sid(sid_ptr: *mut c_void) -> TRUSTEE_W {
|
||||
let mut trustee: TRUSTEE_W = std::mem::zeroed();
|
||||
unsafe fn trustee_from_sid<P: Into<PSID>>(sid_ptr: P) -> TRUSTEE_W {
|
||||
let mut trustee = TRUSTEE_W::default();
|
||||
|
||||
winapi::um::aclapi::BuildTrusteeWithSidW(&mut trustee, sid_ptr);
|
||||
Security::Authorization::BuildTrusteeWithSidW(&mut trustee, sid_ptr);
|
||||
|
||||
trustee
|
||||
}
|
||||
|
@ -233,7 +237,7 @@ unsafe fn trustee_from_sid(sid_ptr: *mut c_void) -> TRUSTEE_W {
|
|||
/// function execution
|
||||
///
|
||||
/// Returns null-terminated Vec's, one for the name and one for the domain.
|
||||
unsafe fn lookup_account_sid(sid: *mut c_void) -> Result<(Vec<u16>, Vec<u16>), std::io::Error> {
|
||||
unsafe fn lookup_account_sid(sid: PSID) -> Result<(Vec<u16>, Vec<u16>), std::io::Error> {
|
||||
let mut name_size: u32 = BUF_SIZE;
|
||||
let mut domain_size: u32 = BUF_SIZE;
|
||||
|
||||
|
@ -244,22 +248,22 @@ unsafe fn lookup_account_sid(sid: *mut c_void) -> Result<(Vec<u16>, Vec<u16>), s
|
|||
let old_name_size = name_size;
|
||||
let old_domain_size = domain_size;
|
||||
|
||||
let mut sid_name_use = 0;
|
||||
let mut sid_name_use = MaybeUninit::uninit();
|
||||
|
||||
// Assumptions:
|
||||
// - sid is a valid pointer to a SID data structure
|
||||
// - name_size and domain_size accurately reflect the sizes
|
||||
let result = winapi::um::winbase::LookupAccountSidW(
|
||||
null_mut(),
|
||||
let result = Security::LookupAccountSidW(
|
||||
None,
|
||||
sid,
|
||||
name.as_mut_ptr(),
|
||||
windows::core::PWSTR(name.as_mut_ptr()),
|
||||
&mut name_size,
|
||||
domain.as_mut_ptr(),
|
||||
windows::core::PWSTR(domain.as_mut_ptr()),
|
||||
&mut domain_size,
|
||||
&mut sid_name_use,
|
||||
sid_name_use.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if result != 0 {
|
||||
if result.ok().is_ok() {
|
||||
// Success!
|
||||
return Ok((name, domain));
|
||||
} else if name_size != old_name_size || domain_size != old_domain_size {
|
||||
|
@ -271,7 +275,7 @@ unsafe fn lookup_account_sid(sid: *mut c_void) -> Result<(Vec<u16>, Vec<u16>), s
|
|||
// Possibly foreign item originating from another machine
|
||||
// TODO: Calculate permissions since it has to be possible if Explorer knows.
|
||||
return Err(io::Error::from_raw_os_error(
|
||||
winapi::um::errhandlingapi::GetLastError() as i32,
|
||||
windows::Win32::Foundation::GetLastError().0 as i32,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue