use core::ffi::c_void;
use std::str::Utf8Error;
use windows::core::PSTR;
use windows::Win32::Foundation::{LocalFree, HLOCAL, PSID};
use windows::Win32::Security::Authorization::ConvertSidToStringSidA;
#[derive(Debug)]
pub enum SddlNativeError {
SidParseError(Utf8Error),
IoError(std::io::Error),
}
impl From<Utf8Error> for SddlNativeError {
fn from(err: Utf8Error) -> Self {
SddlNativeError::SidParseError(err)
}
}
impl std::fmt::Display for SddlNativeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SidParseError(e) => write!(f, "sid parse error {}", e),
Self::IoError(e) => write!(f, "i/o error {}", e),
}
}
}
pub(crate) type SddlResult<T> = Result<T, SddlNativeError>;
pub fn convert_sid_to_string(sid: *const c_void) -> SddlResult<String> {
let mut tmp = PSTR::null();
unsafe {
let not_really_mut_sid = sid.cast_mut(); if ConvertSidToStringSidA(PSID(not_really_mut_sid), &mut tmp).is_err() {
return Err(SddlNativeError::IoError(std::io::Error::last_os_error()));
}
let sid_string = std::ffi::CStr::from_ptr(tmp.0.cast()).to_str()?.to_owned();
if LocalFree(HLOCAL(tmp.0.cast())) != HLOCAL(std::ptr::null_mut()) {
return Err(SddlNativeError::IoError(std::io::Error::last_os_error()));
}
Ok(sid_string)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_convert_string_to_sid() {
let sid: Vec<u8> = vec![1, 2, 0, 0, 0, 0, 0, 5, 0x20, 0, 0, 0, 0x20, 2, 0, 0];
if let Ok(string_sid) = convert_sid_to_string(sid.as_ptr() as *const c_void) {
assert_eq!(string_sid, "S-1-5-32-544");
}
}
}