I'm trying to use windows-rs to use GetNamedSecurityInfoW microsoft api docs to read file permission information, but I keep getting error code 87 corresponds to ERROR_INVALID_PARAMETER. What have I done wrong? (I'm not experienced with rust or the windows api)
#[cfg(windows)]
pub unsafe fn get_file_perms(file: String) -> Result<()> {
use windows_sys::core::PCWSTR;
use windows_sys::Win32::Security::Authorization::GetNamedSecurityInfoW;
let file_u16 = file.encode_utf16().collect::<Vec<u16>>();
let lpfile: PCWSTR = file_u16.as_ptr() as PCWSTR;
let acl: *mut *mut windows_sys::Win32::Security::ACL = std::ptr::null_mut();
let security_descriptor: *mut windows_sys::Win32::Security::PSECURITY_DESCRIPTOR = std::ptr::null_mut();
let err = GetNamedSecurityInfoW(
lpfile,
windows_sys::Win32::Security::Authorization::SE_FILE_OBJECT,
windows_sys::Win32::Security::DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
acl,
std::ptr::null_mut(),
security_descriptor,
);
if err != 0
{
println!("{}", err);
return Err(anyhow!("Failed to get file permissions"));
}
Ok(())
}`
GetNamedSecurityInfoWis an API call with somewhat complex semantics. Besides a description of the object, there'sSecurityInfo) describing the requested informationppsidOwner,ppsidGroup,ppDacl,ppSacl) that provide access to structured datappSecurityDescriptor).On successful return, the system allocates memory, and transfers ownership to the caller through the final parameter. Depending on the requested information (
DACL_SECURITY_INFORMATION) you will have to pass the addresses of pointers to the structured data (ppDaclin this case).With that fixed, there are two more issues left: Making sure that the object name (
pObjectName) is zero-terminated, and cleaning up the buffer the system allocated for us with a call toLocalFree. Note that any one ofppsidOwner,ppsidGroup,ppDacl, andppSaclare valid only for as long asppSecurityDescriptoris valid.The following code fixes the immediate issue:
As far as the interface goes, you should consider taking a
Path/PathBufinstead. Since you are dealing with path names, aStringwill unduly restrict the input to the point of not being able to encode all potential paths.Adding zero-termination, the function can be rewritten to this: