use windows::{
Win32::NetworkManagement::NetManagement::{NetApiBufferFree, NetUserEnum, USER_INFO_3},
core::PCWSTR,
};
use crate::{
User,
error::WindowsUsersError,
utils::{net_api_result, to_wide},
};
pub use self::user_filter_flag::UserFilterFlags;
mod user_filter_flag;
pub fn count_users(
server_name: Option<&str>,
filter: UserFilterFlags,
) -> Result<u32, WindowsUsersError> {
let server_name = server_name
.map(|s| PCWSTR(to_wide(s).as_ptr()))
.unwrap_or_default();
let mut buffer = std::ptr::null_mut();
let mut entries_read = 0;
let mut total_entries = 0;
let mut resume_handle = 0;
let status = unsafe {
NetUserEnum(
server_name,
3,
filter.into(),
&mut buffer,
u32::MAX,
&mut entries_read,
&mut total_entries,
Some(&mut resume_handle),
)
};
let _guard = scopeguard::guard(buffer, |buf| {
if !buf.is_null() {
unsafe { NetApiBufferFree(Some(buf.cast())) };
}
});
net_api_result(status)?;
Ok(entries_read)
}
pub fn list_users(
server_name: Option<&str>,
filter: UserFilterFlags,
) -> Result<Vec<User>, WindowsUsersError> {
let server_name = server_name
.map(|s| PCWSTR(to_wide(s).as_ptr()))
.unwrap_or_default();
let mut buffer = std::ptr::null_mut();
let mut entries_read = 0;
let mut total_entries = 0;
let mut resume_handle = 0;
let status = unsafe {
NetUserEnum(
server_name,
3,
filter.into(),
&mut buffer,
u32::MAX,
&mut entries_read,
&mut total_entries,
Some(&mut resume_handle),
)
};
let _guard = scopeguard::guard(buffer, |buf| {
if !buf.is_null() {
unsafe { NetApiBufferFree(Some(buf.cast())) };
}
});
net_api_result(status)?;
let users = unsafe {
std::slice::from_raw_parts(buffer as *const USER_INFO_3, entries_read as usize)
.iter()
.map(User::try_from)
.collect::<Result<Vec<_>, _>>()
}?;
Ok(users)
}