From 6a59a5a43aded5da308d6b38518294ae652c8340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Jan 2025 14:45:19 +0400 Subject: [PATCH] qemu-display: replace hand-written win32 mmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- qemu-display/examples/list.rs | 16 ++++ qemu-display/src/console_listener.rs | 32 ++++---- qemu-display/src/win32.rs | 51 +----------- qemu-rdw/src/display.rs | 112 --------------------------- 4 files changed, 30 insertions(+), 181 deletions(-) create mode 100644 qemu-display/examples/list.rs diff --git a/qemu-display/examples/list.rs b/qemu-display/examples/list.rs new file mode 100644 index 0000000..375a8ba --- /dev/null +++ b/qemu-display/examples/list.rs @@ -0,0 +1,16 @@ +use std::error::Error; + +use futures::StreamExt; +use qemu_display::Display; +use zbus::Connection; + +#[async_std::main] +async fn main() -> Result<(), Box> { + tracing_subscriber::fmt::init(); + + let conn = Connection::session().await?; + let display = Display::new::<()>(&conn, None).await?; + let owner = display.receive_owner_changed().await?.next().await; + dbg!(owner); + Ok(()) +} diff --git a/qemu-display/src/console_listener.rs b/qemu-display/src/console_listener.rs index 22ffbd5..2ae2c19 100644 --- a/qemu-display/src/console_listener.rs +++ b/qemu-display/src/console_listener.rs @@ -1,9 +1,10 @@ #[cfg(windows)] -use crate::win32::{Fd, Mmap}; +use crate::win32::Fd; use derivative::Derivative; -#[cfg(unix)] use memmap2::Mmap; use std::ops::Drop; +#[cfg(windows)] +use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle}; #[cfg(unix)] use std::os::{ fd::{AsFd, OwnedFd}, @@ -41,7 +42,7 @@ pub struct ScanoutMap { #[cfg(unix)] pub fd: OwnedFd, #[cfg(windows)] - pub handle: u64, + pub handle: OwnedHandle, pub offset: u32, pub width: u32, pub height: u32, @@ -52,9 +53,6 @@ pub struct ScanoutMap { #[derive(Debug)] pub struct ScanoutMmap { scanout: ScanoutMap, - #[cfg(unix)] - mmap: Mmap, - #[cfg(windows)] mmap: Mmap, } @@ -64,20 +62,15 @@ impl ScanoutMap { let offset = self.offset; #[cfg(unix)] - let mmap = { - let fd = self.fd.as_raw_fd(); - unsafe { - memmap2::MmapOptions::new() - .len(len) - .offset(offset.into()) - .map(fd) - }? - }; - + let desc = self.fd.as_raw_fd(); #[cfg(windows)] - let mmap = { - let handle = windows::Win32::Foundation::HANDLE(self.handle as _); // taking ownership - Mmap::new(handle, offset.try_into().unwrap(), len)? + let desc = self.handle.as_raw_handle(); + + let mmap = unsafe { + memmap2::MmapOptions::new() + .len(len) + .offset(offset.into()) + .map(desc)? }; Ok(ScanoutMmap { @@ -426,6 +419,7 @@ impl ConsoleListenerMap { stride: u32, format: u32, ) -> zbus::fdo::Result<()> { + let handle = unsafe { OwnedHandle::from_raw_handle(handle as _) }; let map = ScanoutMap { handle, offset, diff --git a/qemu-display/src/win32.rs b/qemu-display/src/win32.rs index 405a90f..1692970 100644 --- a/qemu-display/src/win32.rs +++ b/qemu-display/src/win32.rs @@ -1,13 +1,9 @@ use std::io; -use tracing::warn; use windows::Win32::{ Foundation::{CloseHandle, HANDLE}, Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW}, - System::{ - Memory::{MapViewOfFile, UnmapViewOfFile, FILE_MAP_READ, MEMORY_MAPPED_VIEW_ADDRESS}, - Threading::PROCESS_ACCESS_RIGHTS, - }, + System::Threading::PROCESS_ACCESS_RIGHTS, }; #[cfg(feature = "qmp")] @@ -122,48 +118,3 @@ pub(crate) fn unix_stream_get_peer_pid(stream: &UnixStream) -> Result std::io::Result { - let ptr = unsafe { MapViewOfFile(handle, FILE_MAP_READ, 0, 0, offset + size) }; - if ptr.Value.is_null() { - return Err(io::Error::last_os_error()); - } - Ok(Self { - handle, - ptr, - offset: offset.try_into().unwrap(), - size, - }) - } - - pub(crate) fn as_ref(&self) -> &[u8] { - unsafe { - std::slice::from_raw_parts(self.ptr.Value.cast::().offset(self.offset), self.size) - } - } -} diff --git a/qemu-rdw/src/display.rs b/qemu-rdw/src/display.rs index 6f86bcd..be6dc59 100644 --- a/qemu-rdw/src/display.rs +++ b/qemu-rdw/src/display.rs @@ -18,10 +18,6 @@ mod imp { use qemu_display::ScanoutMmap; #[cfg(any(windows, unix))] use std::cell::RefCell; - #[cfg(windows)] - use std::ffi::c_void; - #[cfg(windows)] - use windows::Win32::Foundation::{CloseHandle, HANDLE}; #[repr(C)] pub struct RdwDisplayQemuClass { @@ -49,36 +45,6 @@ mod imp { type Type = Display; } - #[cfg(windows)] - #[derive(Debug)] - struct MemoryMap { - handle: HANDLE, - ptr: *const c_void, - offset: isize, - size: usize, - } - - #[cfg(windows)] - impl Drop for MemoryMap { - fn drop(&mut self) { - unsafe { - use windows::Win32::System::Memory::UnmapViewOfFile; - - UnmapViewOfFile(self.ptr); - CloseHandle(self.handle); - } - } - } - - #[cfg(windows)] - impl MemoryMap { - fn as_bytes(&self) -> &[u8] { - unsafe { - std::slice::from_raw_parts(self.ptr.cast::().offset(self.offset), self.size) - } - } - } - #[derive(Debug, Default)] pub struct Display { pub(crate) console: OnceCell, @@ -319,7 +285,6 @@ mod imp { Some(&u.data), ); } - #[cfg(unix)] ScanoutMap { scanout, wait_tx } => { log::debug!("{scanout:?}"); if scanout.format != 0x20020888 { @@ -343,7 +308,6 @@ mod imp { this.scanout_map.replace(map); let _ = wait_tx.send(()); } - #[cfg(unix)] UpdateMap(u) => { log::debug!("{u:?}"); let scanout_map = this.scanout_map.borrow(); @@ -365,82 +329,6 @@ mod imp { ); } #[cfg(windows)] - ScanoutMap { scanout, wait_tx } => { - use windows::Win32::System::Memory::{ - MapViewOfFile, FILE_MAP_READ, - }; - - log::debug!("{s:?}"); - if scanout.format != 0x20020888 { - log::warn!( - "Format not yet supported: {:X}", - scanout.format - ); - continue; - } - - let handle = HANDLE(scanout.handle as _); - let size = - scanout.height as usize * scanout.stride as usize; - let offset = scanout.offset as isize; - let ptr = unsafe { - MapViewOfFile( - handle, - FILE_MAP_READ, - 0, - 0, - scanout.offset as usize + size, - ) - }; - if ptr.is_null() { - log::warn!("Failed to map scanout!"); - continue; - } - - let map = MemoryMap { - ptr, - handle, - offset, - size, - }; - this.obj().set_display_size(Some(( - scanout.width as _, - scanout.height as _, - ))); - this.obj().update_area( - 0, - 0, - scanout.width as _, - scanout.height as _, - scanout.stride as _, - Some(map.as_bytes()), - ); - this.scanout_map.replace(Some((map, scanout.stride))); - let _ = wait_tx.send(()); - } - #[cfg(windows)] - UpdateMap(u) => { - log::debug!("{u:?}"); - let scanout_map = this.scanout_map.borrow(); - let Some((map, stride)) = scanout_map.as_ref() else { - log::warn!("No mapped scanout!"); - continue; - }; - let stride = *stride; - let bytes = map.as_bytes(); - this.obj().update_area( - u.x as _, - u.y as _, - u.w as _, - u.h as _, - stride as _, - Some( - &bytes[u.y as usize * stride as usize - + u.x as usize * 4..], - ), - ); - } - #[cfg(windows)] ScanoutD3dTexture2d(s) => { log::debug!("{s:?}"); this.obj().set_display_size(Some((s.w as _, s.h as _)));