1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use windows::Win32::NetworkManagement::NetManagement::{
NetApiBufferFree, NetUserEnum, USER_INFO_3,
};
use crate::{User, UserManager, error::WindowsUsersError, utils::net_api_result};
pub use self::user_filter_flag::UserFilterFlags;
mod user_filter_flag;
impl UserManager {
/// Counts the number of user accounts on the local machine.
///
/// This function enumerates local normal accounts via `NetUserEnum`
/// and returns the number of entries read in the current enumeration call.
///
/// # Arguments
///
/// * `filter` - A combination of [`UserFilterFlags`] that determines which
/// accounts are included (e.g. normal accounts, disabled accounts, etc.).
///
/// # Returns
///
/// Returns the number of normal user accounts found by the enumeration call.
///
/// # Errors
///
/// Returns a [`WindowsUsersError`] if `NetUserEnum` fails.
pub fn count_users(&self, filter: UserFilterFlags) -> Result<u32, WindowsUsersError> {
let server_name = self.server;
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,
1,
filter.into(),
&raw mut buffer,
u32::MAX,
&raw mut entries_read,
&raw mut total_entries,
Some(&raw 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)
}
/// Lists users on the local machine.
///
/// This function enumerates local normal accounts via `NetUserEnum` level 3
/// and converts each entry into a [`User`].
///
/// # Arguments
///
/// * `filter` - A combination of [`UserFilterFlags`] that determines which
/// accounts are included (e.g. normal accounts, disabled accounts, etc.).
///
/// # Returns
///
/// Returns a vector containing all users returned by the enumeration call.
///
/// # Errors
///
/// Returns a [`WindowsUsersError`] if:
/// - The enumeration API call fails (`NetUserEnum`)
/// - Any entry cannot be converted into [`User`]
pub fn list_users(&self, filter: UserFilterFlags) -> Result<Vec<User>, WindowsUsersError> {
let server_name = self.server;
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(),
&raw mut buffer,
u32::MAX,
&raw mut entries_read,
&raw mut total_entries,
Some(&raw 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)
}
}