#[allow(unused_imports)]
use std::ffi::c_void;
use std::path::Path;
#[allow(unused_imports)]
use windows_sys::Win32::Foundation::{
CloseHandle, LocalFree, ERROR_SUCCESS, HANDLE, INVALID_HANDLE_VALUE,
};
#[allow(unused_imports)]
use windows_sys::Win32::Security::Authorization::{
GetNamedSecurityInfoW, GetSecurityInfo, SetEntriesInAclW, SetNamedSecurityInfoW,
SetSecurityInfo, EXPLICIT_ACCESS_W, TRUSTEE_IS_SID, TRUSTEE_IS_UNKNOWN, TRUSTEE_W,
};
#[allow(unused_imports)]
use windows_sys::Win32::Security::{
MapGenericMask, ACCESS_ALLOWED_ACE, ACE_HEADER, ACL, DACL_SECURITY_INFORMATION, GENERIC_MAPPING,
};
#[allow(unused_imports)]
use windows_sys::Win32::Storage::FileSystem::{
CreateFileW, FILE_FLAG_BACKUP_SEMANTICS, FILE_GENERIC_EXECUTE, FILE_GENERIC_READ,
FILE_GENERIC_WRITE, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
READ_CONTROL,
};
#[allow(dead_code)]
const SE_FILE_OBJECT: i32 = 1;
#[allow(dead_code)]
const GENERIC_WRITE_MASK: u32 = 0x4000_0000;
#[allow(dead_code)]
const DENY_ACCESS: i32 = 3;
#[allow(dead_code)]
pub unsafe fn fetch_dacl_handle(path: &Path) -> Result<(*mut ACL, *mut c_void), String> {
let wpath: Vec<u16> = path
.to_string_lossy()
.encode_utf16()
.chain(std::iter::once(0))
.collect();
let h = CreateFileW(
wpath.as_ptr(),
READ_CONTROL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
std::ptr::null_mut(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
std::ptr::null_mut(),
);
if h == INVALID_HANDLE_VALUE {
return Err(format!("CreateFileW failed for {}", path.display()));
}
let mut p_sd: *mut c_void = std::ptr::null_mut();
let mut p_dacl: *mut ACL = std::ptr::null_mut();
let code = GetSecurityInfo(
h,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut p_dacl,
std::ptr::null_mut(),
&mut p_sd,
);
let _ = CloseHandle(h);
if code != ERROR_SUCCESS {
return Err(format!("GetSecurityInfo failed: {}", code));
}
Ok((p_dacl, p_sd))
}
#[allow(dead_code)]
pub unsafe fn add_allow_ace(path: &Path, psid: *mut c_void) -> Result<(), String> {
let (p_dacl, p_sd) = unsafe { fetch_dacl_handle(path)? };
let mut explicit: EXPLICIT_ACCESS_W = std::mem::zeroed();
let mut mapping: GENERIC_MAPPING = std::mem::zeroed();
mapping.GenericRead = FILE_GENERIC_READ;
mapping.GenericWrite = FILE_GENERIC_WRITE;
mapping.GenericExecute = FILE_GENERIC_EXECUTE;
mapping.GenericAll = 0x1000_0000;
let mut perms = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE;
MapGenericMask(&mut perms, &mapping);
explicit.grfAccessPermissions = perms;
explicit.grfAccessMode = 2; explicit.grfInheritance = 0x1 | 0x2; explicit.Trustee = TRUSTEE_W {
pMultipleTrustee: std::ptr::null_mut(),
MultipleTrusteeOperation: 0,
TrusteeForm: TRUSTEE_IS_SID,
TrusteeType: TRUSTEE_IS_UNKNOWN,
ptstrName: psid as *mut u16,
};
let mut p_new_dacl: *mut ACL = std::ptr::null_mut();
let code = SetEntriesInAclW(1, &explicit, p_dacl, &mut p_new_dacl);
if code != ERROR_SUCCESS {
if !p_sd.is_null() {
windows_sys::Win32::Foundation::LocalFree(
p_sd as windows_sys::Win32::Foundation::HLOCAL,
);
}
return Err(format!("SetEntriesInAclW failed: {}", code));
}
let wpath: Vec<u16> = path
.to_string_lossy()
.encode_utf16()
.chain(std::iter::once(0))
.collect();
let _ = SetNamedSecurityInfoW(
wpath.as_ptr() as *mut u16,
1, DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
p_new_dacl,
std::ptr::null_mut(),
);
if !p_new_dacl.is_null() {
windows_sys::Win32::Foundation::LocalFree(
p_new_dacl as windows_sys::Win32::Foundation::HLOCAL,
);
}
if !p_sd.is_null() {
windows_sys::Win32::Foundation::LocalFree(p_sd as windows_sys::Win32::Foundation::HLOCAL);
}
Ok(())
}
#[allow(dead_code)]
pub unsafe fn add_deny_write_ace(path: &Path, psid: *mut c_void) -> Result<(), String> {
let (p_dacl, p_sd) = unsafe { fetch_dacl_handle(path)? };
let mut explicit: EXPLICIT_ACCESS_W = std::mem::zeroed();
let mut mapping: GENERIC_MAPPING = std::mem::zeroed();
mapping.GenericRead = FILE_GENERIC_READ;
mapping.GenericWrite = FILE_GENERIC_WRITE;
mapping.GenericExecute = FILE_GENERIC_EXECUTE;
mapping.GenericAll = 0x1000_0000;
let mut perms = FILE_GENERIC_WRITE | 0x4000_0000; MapGenericMask(&mut perms, &mapping);
explicit.grfAccessPermissions = perms;
explicit.grfAccessMode = DENY_ACCESS;
explicit.grfInheritance = 0x1 | 0x2; explicit.Trustee = TRUSTEE_W {
pMultipleTrustee: std::ptr::null_mut(),
MultipleTrusteeOperation: 0,
TrusteeForm: TRUSTEE_IS_SID,
TrusteeType: TRUSTEE_IS_UNKNOWN,
ptstrName: psid as *mut u16,
};
let mut p_new_dacl: *mut ACL = std::ptr::null_mut();
let code = SetEntriesInAclW(1, &explicit, p_dacl, &mut p_new_dacl);
if code != ERROR_SUCCESS {
if !p_sd.is_null() {
windows_sys::Win32::Foundation::LocalFree(
p_sd as windows_sys::Win32::Foundation::HLOCAL,
);
}
return Err(format!("SetEntriesInAclW failed: {}", code));
}
let wpath: Vec<u16> = path
.to_string_lossy()
.encode_utf16()
.chain(std::iter::once(0))
.collect();
let _ = SetNamedSecurityInfoW(
wpath.as_ptr() as *mut u16,
1, DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
p_new_dacl,
std::ptr::null_mut(),
);
if !p_new_dacl.is_null() {
windows_sys::Win32::Foundation::LocalFree(
p_new_dacl as windows_sys::Win32::Foundation::HLOCAL,
);
}
if !p_sd.is_null() {
windows_sys::Win32::Foundation::LocalFree(p_sd as windows_sys::Win32::Foundation::HLOCAL);
}
Ok(())
}
#[allow(dead_code)]
pub unsafe fn allow_null_device(psid: *mut c_void) -> Result<(), String> {
let desired = 0x00020000 | 0x00040000; let wnull = r"\\.\NUL"
.encode_utf16()
.chain(std::iter::once(0))
.collect::<Vec<u16>>();
let h = CreateFileW(
wnull.as_ptr(),
desired,
FILE_SHARE_READ | FILE_SHARE_WRITE,
std::ptr::null_mut(),
OPEN_EXISTING,
0x80, std::ptr::null_mut(),
);
if h.is_null() || h == INVALID_HANDLE_VALUE {
return Ok(()); }
let mut p_sd: *mut c_void = std::ptr::null_mut();
let mut p_dacl: *mut ACL = std::ptr::null_mut();
let code = GetSecurityInfo(
h,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut p_dacl,
std::ptr::null_mut(),
&mut p_sd,
);
if code == ERROR_SUCCESS {
let trustee = TRUSTEE_W {
pMultipleTrustee: std::ptr::null_mut(),
MultipleTrusteeOperation: 0,
TrusteeForm: TRUSTEE_IS_SID,
TrusteeType: TRUSTEE_IS_UNKNOWN,
ptstrName: psid as *mut u16,
};
let mut explicit: EXPLICIT_ACCESS_W = std::mem::zeroed();
explicit.grfAccessPermissions =
FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE;
explicit.grfAccessMode = 2; explicit.grfInheritance = 0;
explicit.Trustee = trustee;
let mut p_new_dacl: *mut ACL = std::ptr::null_mut();
let code2 = SetEntriesInAclW(1, &explicit, p_dacl, &mut p_new_dacl);
if code2 == ERROR_SUCCESS {
let _ = SetSecurityInfo(
h,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
p_new_dacl,
std::ptr::null_mut(),
);
if !p_new_dacl.is_null() {
windows_sys::Win32::Foundation::LocalFree(
p_new_dacl as windows_sys::Win32::Foundation::HLOCAL,
);
}
}
}
if !p_sd.is_null() {
windows_sys::Win32::Foundation::LocalFree(p_sd as windows_sys::Win32::Foundation::HLOCAL);
}
let _ = CloseHandle(h);
Ok(())
}
#[allow(dead_code)]
pub fn ensure_allow_mask_aces(_path: &Path, _psid: *mut c_void) -> Result<(), String> {
Ok(())
}
#[allow(dead_code)]
pub fn ensure_allow_write_aces(_path: &Path, _psid: *mut c_void) -> Result<(), String> {
Ok(())
}
#[allow(dead_code)]
pub fn path_mask_allows(_path: &Path, _psid: *mut c_void, _access: u32) -> bool {
true
}
#[cfg(test)]
#[cfg(target_os = "windows")]
mod tests {
use super::*;
#[test]
fn test_allow_null_device() {
unsafe {
let result = allow_null_device(std::ptr::null_mut());
if result.is_ok() {
return;
}
let err = result.unwrap_err();
assert!(
err.contains("failed") || err.contains("CreateFileW"),
"Expected Ok or descriptive error, got: {}",
err
);
}
}
#[test]
fn test_fetch_dacl_handle_invalid_path() {
let invalid_path = std::path::Path::new("C:\\this\\path\\does\\not\\exist\\file.txt");
let result = unsafe { fetch_dacl_handle(invalid_path) };
assert!(result.is_err());
}
}