'windows-rs GetNamedSecurityInfoW error 87
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(())
}`
							
						Solution 1:[1]
GetNamedSecurityInfoW is an API call with somewhat complex semantics. Besides a description of the object, there's
- a bitmask (
SecurityInfo) describing the requested information - a set of output parameters (
ppsidOwner,ppsidGroup,ppDacl,ppSacl) that provide access to structured data - the actual buffer holding the data (
ppSecurityDescriptor). 
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 to LocalFree. Note that any one of ppsidOwner, ppsidGroup, ppDacl, and ppSacl are valid only for as long as ppSecurityDescriptor is valid.
The following code fixes the immediate issue:
pub unsafe fn get_file_perms(file: String) -> Result<()> {
    use windows_sys::Win32::Security::Authorization::GetNamedSecurityInfoW;
    let file_u16 = file.encode_utf16().collect::<Vec<u16>>();
    // Pointers that receive the output arguments
    let mut acl = std::ptr::null_mut();
    let mut security_descriptor = std::ptr::null_mut();
    let err = GetNamedSecurityInfoW(
        file_u16.as_ptr(),
        windows_sys::Win32::Security::Authorization::SE_FILE_OBJECT,
        windows_sys::Win32::Security::DACL_SECURITY_INFORMATION,
        std::ptr::null_mut(),
        std::ptr::null_mut(),
        // Pass the *address* of the pointer
        std::ptr::addr_of_mut!(acl),
        std::ptr::null_mut(),
        // Same here
        std::ptr::addr_of_mut!(security_descriptor),
    );
    if err != 0 {
        println!("{}", err);
        return Err("Failed to get file permissions".into());
    }
    // At this point `acl` points into an access control list
    // Cleanup up resources (should really be bound to a struct with a `Drop` impl)
    windows_sys::Win32::System::Memory::LocalFree(security_descriptor as _);
    Ok(())
}
As far as the interface goes, you should consider taking a Path/PathBuf instead. Since you are dealing with path names, a String 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:
pub unsafe fn get_file_perms(file: impl AsRef<Path>) -> Result<()> {
    let file_u16 = file
        .as_ref()
        .as_os_str()
        .encode_wide()
        .chain(once(0))
        .collect::<Vec<_>>();
    // ...
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | IInspectable | 
