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(())
}`
GetNamedSecurityInfoW
is 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 (ppDacl
in 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
, andppSacl
are valid only for as long asppSecurityDescriptor
is valid.The following code fixes the immediate issue:
As far as the interface goes, you should consider taking a
Path
/PathBuf
instead. Since you are dealing with path names, aString
will 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: