1
0
mirror of https://gitlab.com/marcandre.lureau/qemu-display.git synced 2025-03-07 15:25:04 +00:00

Add basic windows support

This commit is contained in:
Marc-André Lureau 2022-10-20 12:10:10 +04:00
parent 817d44e17a
commit 91a8549b70
6 changed files with 62 additions and 20 deletions

View File

@ -72,6 +72,8 @@ pub struct Audio {
pub proxy: AudioProxy<'static>, pub proxy: AudioProxy<'static>,
out_listener: Option<Connection>, out_listener: Option<Connection>,
in_listener: Option<Connection>, in_listener: Option<Connection>,
#[cfg(windows)]
peer_pid: u32,
} }
#[async_trait::async_trait] #[async_trait::async_trait]
@ -233,12 +235,14 @@ impl<H: AudioInHandler> AudioInListener<H> {
} }
impl Audio { impl Audio {
pub async fn new(conn: &zbus::Connection) -> Result<Self> { pub async fn new(conn: &zbus::Connection, #[cfg(windows)] peer_pid: u32) -> Result<Self> {
let proxy = AudioProxy::new(conn).await?; let proxy = AudioProxy::new(conn).await?;
Ok(Self { Ok(Self {
proxy, proxy,
in_listener: None, in_listener: None,
out_listener: None, out_listener: None,
#[cfg(windows)]
peer_pid,
}) })
} }
@ -246,7 +250,7 @@ impl Audio {
let (p0, p1) = UnixStream::pair()?; let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass( let p0 = util::prepare_uds_pass(
#[cfg(windows)] #[cfg(windows)]
self.proxy.inner().connection(), self.peer_pid,
&p0, &p0,
)?; )?;
self.proxy.register_out_listener(p0).await?; self.proxy.register_out_listener(p0).await?;
@ -266,7 +270,7 @@ impl Audio {
let (p0, p1) = UnixStream::pair()?; let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass( let p0 = util::prepare_uds_pass(
#[cfg(windows)] #[cfg(windows)]
self.proxy.inner().connection(), self.peer_pid,
&p0, &p0,
)?; )?;
self.proxy.register_in_listener(p0).await?; self.proxy.register_in_listener(p0).await?;

View File

@ -54,10 +54,12 @@ pub struct Console {
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
pub mouse: MouseProxy<'static>, pub mouse: MouseProxy<'static>,
listener: RefCell<Option<Connection>>, listener: RefCell<Option<Connection>>,
#[cfg(windows)]
peer_pid: u32,
} }
impl Console { impl Console {
pub async fn new(conn: &Connection, idx: u32) -> Result<Self> { pub async fn new(conn: &Connection, idx: u32, #[cfg(windows)] peer_pid: u32) -> Result<Self> {
let obj_path = ObjectPath::try_from(format!("/org/qemu/Display1/Console_{}", idx))?; let obj_path = ObjectPath::try_from(format!("/org/qemu/Display1/Console_{}", idx))?;
let proxy = ConsoleProxy::builder(conn).path(&obj_path)?.build().await?; let proxy = ConsoleProxy::builder(conn).path(&obj_path)?.build().await?;
let keyboard = KeyboardProxy::builder(conn) let keyboard = KeyboardProxy::builder(conn)
@ -70,6 +72,8 @@ impl Console {
keyboard, keyboard,
mouse, mouse,
listener: RefCell::new(None), listener: RefCell::new(None),
#[cfg(windows)]
peer_pid,
}) })
} }
@ -89,7 +93,7 @@ impl Console {
let (p0, p1) = UnixStream::pair()?; let (p0, p1) = UnixStream::pair()?;
let p0 = util::prepare_uds_pass( let p0 = util::prepare_uds_pass(
#[cfg(windows)] #[cfg(windows)]
self.proxy.inner().connection(), self.peer_pid,
&p0, &p0,
)?; )?;
self.proxy.register_listener(p0).await?; self.proxy.register_listener(p0).await?;

View File

@ -25,6 +25,8 @@ struct Inner<'d> {
proxy: fdo::ObjectManagerProxy<'d>, proxy: fdo::ObjectManagerProxy<'d>,
conn: Connection, conn: Connection,
objects: ManagedObjects, objects: ManagedObjects,
#[cfg(windows)]
peer_pid: u32,
} }
#[derive(Clone)] #[derive(Clone)]
@ -82,7 +84,11 @@ impl<'d> Display<'d> {
Ok(hm) Ok(hm)
} }
pub async fn new<D>(conn: &Connection, dest: Option<D>) -> Result<Display<'d>> pub async fn new<D>(
conn: &Connection,
dest: Option<D>,
#[cfg(windows)] peer_pid: u32,
) -> Result<Display<'d>>
where where
D: TryInto<BusName<'d>>, D: TryInto<BusName<'d>>,
D::Error: Into<Error>, D::Error: Into<Error>,
@ -102,6 +108,8 @@ impl<'d> Display<'d> {
proxy, proxy,
conn: conn.clone(), conn: conn.clone(),
objects, objects,
#[cfg(windows)]
peer_pid,
}; };
Ok(Self { Ok(Self {
@ -113,6 +121,11 @@ impl<'d> Display<'d> {
&self.inner.conn &self.inner.conn
} }
#[cfg(windows)]
pub fn peer_pid(&self) -> u32 {
self.inner.peer_pid
}
#[cfg(all(windows, feature = "qmp"))] #[cfg(all(windows, feature = "qmp"))]
pub async fn new_qmp<P: AsRef<std::path::Path>>(path: P) -> Result<Display<'d>> { pub async fn new_qmp<P: AsRef<std::path::Path>>(path: P) -> Result<Display<'d>> {
#![allow(non_snake_case, non_camel_case_types)] #![allow(non_snake_case, non_camel_case_types)]
@ -163,7 +176,7 @@ impl<'d> Display<'d> {
.build() .build()
.await?; .await?;
Self::new(&conn, Option::<String>::None).await Self::new(&conn, Option::<String>::None, pid).await
} }
pub async fn receive_owner_changed(&self) -> Result<OwnerChangedStream<'_>> { pub async fn receive_owner_changed(&self) -> Result<OwnerChangedStream<'_>> {
@ -179,7 +192,14 @@ impl<'d> Display<'d> {
return Ok(None); return Ok(None);
} }
Ok(Some(Audio::new(&self.inner.conn).await?)) Ok(Some(
Audio::new(
&self.inner.conn,
#[cfg(windows)]
self.peer_pid(),
)
.await?,
))
} }
pub async fn clipboard(&self) -> Result<Option<Clipboard>> { pub async fn clipboard(&self) -> Result<Option<Clipboard>> {

View File

@ -18,7 +18,7 @@ use windows::Win32::Networking::WinSock::SOCKET;
#[cfg(windows)] #[cfg(windows)]
use windows::Win32::System::Threading::PROCESS_DUP_HANDLE; use windows::Win32::System::Threading::PROCESS_DUP_HANDLE;
pub fn prepare_uds_pass(#[cfg(windows)] conn: &zbus::Connection, us: &UnixStream) -> Result<Fd> { pub fn prepare_uds_pass(#[cfg(windows)] peer_pid: u32, us: &UnixStream) -> Result<Fd> {
#[cfg(unix)] #[cfg(unix)]
{ {
Ok(us.as_raw_fd().into()) Ok(us.as_raw_fd().into())
@ -26,9 +26,7 @@ pub fn prepare_uds_pass(#[cfg(windows)] conn: &zbus::Connection, us: &UnixStream
#[cfg(windows)] #[cfg(windows)]
{ {
// FIXME: we should use GetConnectionCredentials to work with a bus let p = win32::ProcessHandle::open(Some(peer_pid as _), PROCESS_DUP_HANDLE)?;
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 _)) p.duplicate_socket(SOCKET(us.as_raw_socket() as _))
} }
} }

View File

@ -38,7 +38,9 @@ impl ProcessHandle {
process_id: Option<u32>, process_id: Option<u32>,
desired_access: PROCESS_ACCESS_RIGHTS, desired_access: PROCESS_ACCESS_RIGHTS,
) -> Result<Self, io::Error> { ) -> Result<Self, io::Error> {
use windows::Win32::System::Threading::{GetCurrentProcess, OpenProcess, PROCESS_QUERY_INFORMATION}; use windows::Win32::System::Threading::{
GetCurrentProcess, OpenProcess, PROCESS_QUERY_INFORMATION,
};
let process = if let Some(process_id) = process_id { let process = if let Some(process_id) = process_id {
let desired_access = desired_access | PROCESS_QUERY_INFORMATION; let desired_access = desired_access | PROCESS_QUERY_INFORMATION;
@ -51,8 +53,8 @@ impl ProcessHandle {
} }
pub fn process_id(&self) -> crate::Result<u32> { pub fn process_id(&self) -> crate::Result<u32> {
use windows::Win32::System::Threading::GetProcessId;
use windows::Win32::Foundation::GetLastError; use windows::Win32::Foundation::GetLastError;
use windows::Win32::System::Threading::GetProcessId;
unsafe { unsafe {
let pid = GetProcessId(self.0); let pid = GetProcessId(self.0);

View File

@ -73,7 +73,16 @@ async fn display_from_opt(opt: Arc<RefCell<AppOptions>>) -> Option<Display<'stat
Display::lookup(&conn, wait, name.as_deref()).await.unwrap() Display::lookup(&conn, wait, name.as_deref()).await.unwrap()
}; };
Some(Display::new(&conn, dest).await.unwrap()) Some(
Display::new(
&conn,
dest,
#[cfg(windows)]
unimplemented!(),
)
.await
.unwrap(),
)
} }
impl App { impl App {
@ -195,7 +204,12 @@ impl App {
} }
}); });
let console = Console::new(display.connection(), 0) let console = Console::new(
display.connection(),
0,
#[cfg(windows)]
display.peer_pid(),
)
.await .await
.expect("Failed to get the QEMU console"); .expect("Failed to get the QEMU console");
let rdw = display::Display::new(console); let rdw = display::Display::new(console);
@ -237,7 +251,7 @@ impl App {
let (p0, p1) = UnixStream::pair().unwrap(); let (p0, p1) = UnixStream::pair().unwrap();
let fd = util::prepare_uds_pass( let fd = util::prepare_uds_pass(
#[cfg(windows)] #[cfg(windows)]
c.proxy.inner().connection(), display.peer_pid(),
&p1, &p1,
) )
.unwrap(); .unwrap();