Skip to content

Instantly share code, notes, and snippets.

@leiless
Last active August 25, 2023 09:00
Show Gist options
  • Save leiless/231c9382bfcb30af281805502a902d1f to your computer and use it in GitHub Desktop.
Save leiless/231c9382bfcb30af281805502a902d1f to your computer and use it in GitHub Desktop.
Rust + windows-rs: Get current logged-in users
const WTS_CONNECT_STATE_ACTIVE: i32 = 0;
// https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_connectstate_class#syntax
fn wts_state_to_string(state: windows::Win32::System::RemoteDesktop::WTS_CONNECTSTATE_CLASS) -> String {
match state.0 {
0 => "Active".to_string(),
1 => "Connected".to_string(),
2 => "ConnectQuery".to_string(),
3 => "Shadow".to_string(),
4 => "Disconnected".to_string(),
5 => "Idle".to_string(),
6 => "Listen".to_string(),
7 => "Reset".to_string(),
8 => "Down".to_string(),
9 => "Init".to_string(),
_ => format!("Unknown({})", state.0),
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let active_console_session_id = unsafe { windows::Win32::System::RemoteDesktop::WTSGetActiveConsoleSessionId() };
println!("Active console session id: {}", active_console_session_id);
let handle = windows::Win32::System::RemoteDesktop::WTS_CURRENT_SERVER_HANDLE;
let mut session_info_ptr: *mut windows::Win32::System::RemoteDesktop::WTS_SESSION_INFOW = std::ptr::null_mut();
let mut session_count = 0u32;
unsafe {
windows::Win32::System::RemoteDesktop::WTSEnumerateSessionsW(
handle,
0,
1,
&mut session_info_ptr,
&mut session_count,
)?;
}
for i in 0..session_count {
let session_info = &unsafe { *session_info_ptr.add(i as usize) };
let win_station_name = unsafe { session_info.pWinStationName.to_string()? };
println!("> session_id: {} win_station_name: {} state: {}",
session_info.SessionId,
win_station_name,
wts_state_to_string(session_info.State),
);
if session_info.State.0 == WTS_CONNECT_STATE_ACTIVE {
let mut username_buf = windows::core::PWSTR::null();
let mut bytes_returned = 0u32;
unsafe {
windows::Win32::System::RemoteDesktop::WTSQuerySessionInformationW(
handle,
session_info.SessionId,
windows::Win32::System::RemoteDesktop::WTSUserName,
&mut username_buf,
&mut bytes_returned,
)?;
}
assert!(!username_buf.is_null());
let username = unsafe { username_buf.to_string()? };
println!("\t username: {} bytes_returned: {}", username, bytes_returned);
}
}
Ok(())
}
@leiless
Copy link
Author

leiless commented Aug 25, 2023

@leiless
Copy link
Author

leiless commented Aug 25, 2023

$ ./rust-test.exe
Active console session id: 1
> session_id: 0 win_station_name: Services state: Disconnected
> session_id: 1 win_station_name: Console state: Connected
> session_id: 2 win_station_name: RDP-Tcp#12 state: Active
         username: foobar bytes_returned: 14
> session_id: 65536 win_station_name: RDP-Tcp state: Listen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment