windows-permissions 0.2.4

Safe Rust bindings to Windows permissions APIs
Documentation
use crate::{wrappers, LocalBox, Sid};
use std::io;
use std::ptr::null_mut;

/// Wraps [`CreateWellKnownSid`](https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-createwellknownsid).
///
/// `sid_type` may be any value in [`WELL_KNOWN_SID_TYPE`](https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-well_known_sid_type).
///
/// If `domain_sid` is omitted, this has the same behavior as the underlying
/// WinAPI function.
///
/// ```
/// use windows_permissions::{wrappers, Sid, LocalBox};
/// use winapi::um::winnt::WinWorldSid;
///
/// let win_world_sid = wrappers::CreateWellKnownSid(WinWorldSid, None).unwrap();
/// let another_sid = "S-1-1-0".parse().unwrap();
///
/// assert_eq!(win_world_sid, another_sid);
/// ```
#[allow(non_snake_case)]
pub fn CreateWellKnownSid(sid_type: u32, domain_sid: Option<&Sid>) -> io::Result<LocalBox<Sid>> {
    // Optimistically reserve enough space for a fairly large SID
    let mut sid_len = wrappers::GetSidLengthRequired(8) as u32;

    // Get the pointer to the domain SID
    let domain_sid_ptr = match domain_sid {
        None => null_mut(),
        Some(s) => s as *const _ as *mut _,
    };

    // Allocate space for the new SID
    let new_sid: LocalBox<Sid> = unsafe { LocalBox::try_allocate(true, sid_len as usize)? };

    let result = unsafe {
        winapi::um::securitybaseapi::CreateWellKnownSid(
            sid_type,
            domain_sid_ptr,
            new_sid.as_ptr() as *mut _,
            &mut sid_len,
        )
    };

    if result != 0 {
        // Success! The SID was initialized and should be returned
        Ok(new_sid)
    } else {
        Err(io::Error::last_os_error())
    }
}