1
0
mirror of https://gitlab.com/marcandre.lureau/qemu-display.git synced 2025-04-14 08:44:46 +00:00

qemu-display: pass sockets with win32

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2022-08-31 12:48:11 +04:00
parent 5b428adace
commit 2ed1174df6
6 changed files with 43 additions and 63 deletions

View File

@ -10,7 +10,7 @@ edition = "2018"
cfg-if = "1.0"
log = "0.4"
derivative = "2.2.0"
zbus = { version = "3.0", features = ["xml"] }
zbus = { version = "3.2", features = ["xml"] }
zvariant = { version = "3.0", features = ["serde_bytes"] }
libc = "0.2.86"
enumflags2 = { version = "0.7", features = ["serde"] }

View File

@ -244,7 +244,11 @@ impl Audio {
pub async fn register_out_listener<H: AudioOutHandler>(&mut self, handler: H) -> Result<()> {
let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass(&p0)?;
let p0 = util::prepare_uds_pass(
#[cfg(windows)]
self.proxy.inner().connection(),
&p0,
)?;
self.proxy.register_out_listener(p0).await?;
let c = zbus::ConnectionBuilder::unix_stream(p1)
.p2p()
@ -260,7 +264,11 @@ impl Audio {
pub async fn register_in_listener<H: AudioInHandler>(&mut self, handler: H) -> Result<()> {
let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass(&p0)?;
let p0 = util::prepare_uds_pass(
#[cfg(windows)]
self.proxy.inner().connection(),
&p0,
)?;
self.proxy.register_in_listener(p0).await?;
let c = zbus::ConnectionBuilder::unix_stream(p1)
.p2p()

View File

@ -87,7 +87,11 @@ impl Console {
pub async fn register_listener<H: ConsoleListenerHandler>(&self, handler: H) -> Result<()> {
let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass(&p0)?;
let p0 = util::prepare_uds_pass(
#[cfg(windows)]
self.proxy.inner().connection(),
&p0,
)?;
self.proxy.register_listener(p0).await?;
let c = zbus::ConnectionBuilder::unix_stream(p1)
.p2p()

View File

@ -14,11 +14,11 @@ use std::os::windows::io::AsRawSocket;
#[cfg(windows)]
use uds_windows::UnixStream;
#[cfg(windows)]
use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW};
use windows::Win32::Networking::WinSock::SOCKET;
#[cfg(windows)]
use windows::Win32::System::Threading::PROCESS_DUP_HANDLE;
pub fn prepare_uds_pass(us: &UnixStream) -> Result<Fd> {
pub fn prepare_uds_pass(#[cfg(windows)] conn: &zbus::Connection, us: &UnixStream) -> Result<Fd> {
#[cfg(unix)]
{
Ok(us.as_raw_fd().into())
@ -26,21 +26,9 @@ pub fn prepare_uds_pass(us: &UnixStream) -> Result<Fd> {
#[cfg(windows)]
{
let pid = win32::unix_stream_get_peer_pid(us)?;
let p = win32::ProcessHandle::open(Some(pid), PROCESS_DUP_HANDLE)?;
let mut info = unsafe { std::mem::zeroed() };
if unsafe {
WSADuplicateSocketW(SOCKET(us.as_raw_socket() as _), p.process_id(), &mut info)
} != 0
{
return Err(crate::Error::Io(win32::wsa_last_err()));
}
let info = unsafe {
std::slice::from_raw_parts(
&info as *const _ as *const u8,
std::mem::size_of::<WSAPROTOCOL_INFOW>(),
)
};
Ok(info.to_vec())
// FIXME: we should use GetConnectionCredentials to work with a bus
let pid = conn.peer_pid()?.unwrap();
let p = win32::ProcessHandle::open(Some(pid as _), PROCESS_DUP_HANDLE)?;
p.duplicate_socket(SOCKET(us.as_raw_socket() as _))
}
}

View File

@ -1,6 +1,6 @@
use std::io;
use uds_windows::UnixStream;
use windows::Win32::Foundation::{CloseHandle, HANDLE};
use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW};
use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS;
pub type Fd = Vec<u8>;
@ -36,6 +36,20 @@ impl ProcessHandle {
unsafe { GetProcessId(self.0) }
}
pub fn duplicate_socket(&self, sock: SOCKET) -> crate::Result<Fd> {
let mut info = unsafe { std::mem::zeroed() };
if unsafe { WSADuplicateSocketW(sock, self.process_id(), &mut info) } != 0 {
return Err(crate::Error::Io(wsa_last_err()));
}
let info = unsafe {
std::slice::from_raw_parts(
&info as *const _ as *const u8,
std::mem::size_of::<WSAPROTOCOL_INFOW>(),
)
};
Ok(info.to_vec())
}
}
pub(crate) fn wsa_last_err() -> io::Error {
@ -44,42 +58,3 @@ pub(crate) fn wsa_last_err() -> io::Error {
let err = unsafe { WSAGetLastError() };
io::Error::from_raw_os_error(err.0)
}
// Get the process ID of the connected peer
pub fn unix_stream_get_peer_pid(stream: &UnixStream) -> Result<u32, io::Error> {
use std::os::windows::io::AsRawSocket;
use windows::Win32::Networking::WinSock::{
WSAIoctl, IOC_OUT, IOC_VENDOR, SOCKET, SOCKET_ERROR,
};
macro_rules! _WSAIOR {
($x:expr, $y:expr) => {
IOC_OUT | $x | $y
};
}
let socket = stream.as_raw_socket();
const SIO_AF_UNIX_GETPEERPID: u32 = _WSAIOR!(IOC_VENDOR, 256);
let mut ret = 0 as u32;
let mut bytes = 0;
let r = unsafe {
WSAIoctl(
SOCKET(socket as _),
SIO_AF_UNIX_GETPEERPID,
0 as *mut _,
0,
&mut ret as *mut _ as *mut _,
std::mem::size_of_val(&ret) as u32,
&mut bytes,
0 as *mut _,
None,
)
};
if r == SOCKET_ERROR {
return Err(wsa_last_err());
}
Ok(ret)
}

View File

@ -208,7 +208,12 @@ impl App {
use uds_windows::UnixStream;
let (p0, p1) = UnixStream::pair().unwrap();
let fd = util::prepare_uds_pass(&p1).unwrap();
let fd = util::prepare_uds_pass(
#[cfg(windows)]
c.proxy.inner().connection(),
&p1,
)
.unwrap();
if c.proxy.register(fd).await.is_ok() {
let mut reader = BufReader::new(p0.try_clone().unwrap());
let mut line = String::new();