windows-permissions 0.2.4

Safe Rust bindings to Windows permissions APIs
Documentation
use crate::utilities::os_from_buf;
use crate::Sid;
use std::ffi::OsString;
use std::io;
use std::ptr::null;

const BUFFER_SIZE: u32 = 256;

/// Wraps [`LookupAccountSidW`](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupaccountsidw).
///
/// Returns (name, domain).
///
/// ```
/// use windows_permissions::{Sid, LocalBox, wrappers::LookupAccountSid};
/// use winapi::um::winnt::WinBuiltinAdministratorsSid;
///
/// let sid = Sid::well_known_sid(WinBuiltinAdministratorsSid).unwrap();
/// let (name, domain) = LookupAccountSid(&sid).unwrap();
///
/// assert_eq!(name, "Administrators");
/// assert_eq!(domain, "BUILTIN");
/// ```
#[allow(non_snake_case)]
pub fn LookupAccountSid(sid: &Sid) -> Result<(OsString, OsString), io::Error> {
    let mut name_size = BUFFER_SIZE;
    let mut dom_size = BUFFER_SIZE;

    loop {
        let old_name_size = name_size;
        let old_dom_size = dom_size;

        let mut name: Vec<u16> = vec![0; name_size as usize];
        let mut dom: Vec<u16> = vec![0; dom_size as usize];

        let mut name_use: u32 = 0;

        let result = unsafe {
            winapi::um::winbase::LookupAccountSidW(
                null(),
                sid as *const Sid as *mut _,
                name.as_mut_ptr(),
                &mut name_size,
                dom.as_mut_ptr(),
                &mut dom_size,
                &mut name_use,
            )
        };

        if result != 0 {
            // Success: Return the filled buffers as OsStrings
            return Ok((os_from_buf(&name), os_from_buf(&dom)));
        } else if name_size != old_name_size || dom_size != old_dom_size {
            // Failed, but requests new allocation: try again
            continue;
        } else {
            // Failed, with no new allocation request
            return Err(io::Error::last_os_error());
        }
    }
}