Remote Desktop
A Microsoft app that connects remotely to computers and to virtual apps and desktops.
4,617 questions
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I'm developing an open-source screen capture application in Rust that needs to capture screen content from Remote Desktop sessions on Windows Server 2022. Our setup:
xcap
crate for screen captureThis works for local screens but fails to capture RDP session content.
Questions:
I've been diving into windows-rs
lib to do so. This is my current WIP code:
pub async fn capture_rdp_session(session_id: &str) -> Result<DynamicImage> {
#[cfg(target_os = "windows")]
{
use windows::Win32::System::RemoteDesktop::{
WTSQuerySessionInformationW, WTSVirtualChannelQuery, WTS_CURRENT_SERVER_HANDLE,
WTS_VIRTUAL_CLASS, WTSEnumerateSessionsW, WTS_SESSION_INFOW,
};
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
// First find the correct session ID
let mut session_count: u32 = 0;
let mut sessions_ptr = std::ptr::null_mut();
unsafe {
WTSEnumerateSessionsW(
WTS_CURRENT_SERVER_HANDLE,
0,
1,
&mut sessions_ptr,
&mut session_count,
)?;
let sessions = std::slice::from_raw_parts(
sessions_ptr as *const WTS_SESSION_INFOW,
session_count as usize,
);
println!("Sessions: {:?}", sessions);
// Find matching session
// let target_session = sessions.iter().find(|s| {
// let session_name = unsafe {
// let slice = s.pWinStationName.as_wide();
// String::from_utf16_lossy(slice)
// };
// session_name == session_id
// }).ok_or_else(|| anyhow!("Session not found"))?;
let target_session = sessions[0];
// Query session buffer
let mut buffer_size: u32 = 0;
let mut buffer_ptr = std::ptr::null_mut();
WTSVirtualChannelQuery(
WTS_CURRENT_SERVER_HANDLE,
WTS_VIRTUAL_CLASS(target_session.SessionId as i32),
&mut buffer_ptr,
&mut buffer_size,
)?;
if buffer_ptr.is_null() {
return Err(anyhow!("Failed to get session buffer"));
}
// Convert buffer to image
let buffer_slice = std::slice::from_raw_parts(
buffer_ptr as *const u8,
buffer_size as usize
);
let buffer_vec = buffer_slice.to_vec();
// Free WTS memory
WTSFreeMemory(buffer_ptr);
WTSFreeMemory(sessions_ptr as *mut _);
// Create image from buffer
let width = (buffer_size as f64).sqrt() as u32;
let image = DynamicImage::ImageRgb8(
ImageBuffer::from_raw(width, width, buffer_vec)
.ok_or_else(|| anyhow!("Failed to create image buffer"))?
);
Ok(image)
}
}
#[cfg(not(target_os = "windows"))]
{
Err(anyhow!("RDP capture only supported on Windows"))
}
}
Any guidance on the correct Windows APIs or Rust crates for this specific use case would be greatly appreciated.