windows-rs GetNamedSecurityInfoW 错误 87
windows-rs GetNamedSecurityInfoW error 87
我正在尝试使用 windows-rs to use GetNamedSecurityInfoW microsoft api docs 读取文件权限信息,但我一直收到错误代码 87
对应于 ERROR_INVALID_PARAMETER
。我做错了什么? (我对生锈或 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
是一个 API 调用,语义有些复杂。除了对象的描述,还有
- 描述请求信息的位掩码 (
SecurityInfo
)
- 一组提供对结构化数据的访问的输出参数(
ppsidOwner
、ppsidGroup
、ppDacl
、ppSacl
)
- 保存数据的实际缓冲区 (
ppSecurityDescriptor
)。
成功后return,系统分配内存,并通过最终参数将所有权转移给调用者。根据请求的信息 (DACL_SECURITY_INFORMATION
),您必须将指针的地址传递给结构化数据(在本例中为 ppDacl
)。
修复后,还有两个问题:确保对象名称 (pObjectName
) 是 zero-terminated,以及清理系统通过调用为我们分配的缓冲区LocalFree
。请注意,ppsidOwner
、ppsidGroup
、ppDacl
和 ppSacl
中的任何一个仅在 ppSecurityDescriptor
有效期间有效。
以下代码解决了眼前的问题:
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(())
}
就界面而言,您应该考虑使用 Path
/PathBuf
。由于您正在处理路径名,因此 String
会将输入过度限制到无法对所有潜在路径进行编码的程度。
加上zero-termination,函数可以改写成这样:
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<_>>();
// ...
我正在尝试使用 windows-rs to use GetNamedSecurityInfoW microsoft api docs 读取文件权限信息,但我一直收到错误代码 87
对应于 ERROR_INVALID_PARAMETER
。我做错了什么? (我对生锈或 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
是一个 API 调用,语义有些复杂。除了对象的描述,还有
- 描述请求信息的位掩码 (
SecurityInfo
) - 一组提供对结构化数据的访问的输出参数(
ppsidOwner
、ppsidGroup
、ppDacl
、ppSacl
) - 保存数据的实际缓冲区 (
ppSecurityDescriptor
)。
成功后return,系统分配内存,并通过最终参数将所有权转移给调用者。根据请求的信息 (DACL_SECURITY_INFORMATION
),您必须将指针的地址传递给结构化数据(在本例中为 ppDacl
)。
修复后,还有两个问题:确保对象名称 (pObjectName
) 是 zero-terminated,以及清理系统通过调用为我们分配的缓冲区LocalFree
。请注意,ppsidOwner
、ppsidGroup
、ppDacl
和 ppSacl
中的任何一个仅在 ppSecurityDescriptor
有效期间有效。
以下代码解决了眼前的问题:
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(())
}
就界面而言,您应该考虑使用 Path
/PathBuf
。由于您正在处理路径名,因此 String
会将输入过度限制到无法对所有潜在路径进行编码的程度。
加上zero-termination,函数可以改写成这样:
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<_>>();
// ...