106 lines
3.6 KiB
Rust
106 lines
3.6 KiB
Rust
|
|
|
|
#[cfg(target_os = "windows")]
|
|
fn main() {
|
|
println!("Starting Win32 clipboard listener isolation test");
|
|
|
|
let (_tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<()>();
|
|
|
|
std::thread::Builder::new()
|
|
.name("win32-clipboard-listener-isolation".to_string())
|
|
.spawn(move || {
|
|
use windows_sys::Win32::Foundation::*;
|
|
use windows_sys::Win32::System::DataExchange::*;
|
|
use windows_sys::Win32::UI::WindowsAndMessaging::*;
|
|
|
|
unsafe extern "system" fn wnd_proc(
|
|
hwnd: HWND,
|
|
msg: u32,
|
|
wparam: WPARAM,
|
|
lparam: LPARAM,
|
|
) -> LRESULT {
|
|
if msg == WM_CLIPBOARDUPDATE {
|
|
println!("WM_CLIPBOARDUPDATE received");
|
|
return 0;
|
|
}
|
|
unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) }
|
|
}
|
|
|
|
unsafe {
|
|
let class_name: Vec<u16> =
|
|
"McpMemoryClipboardWatcherClassIsolation\0".encode_utf16().collect();
|
|
let wnd_class = WNDCLASSEXW {
|
|
cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32,
|
|
style: 0,
|
|
lpfnWndProc: Some(wnd_proc),
|
|
cbClsExtra: 0,
|
|
cbWndExtra: 0,
|
|
hInstance: 0 as _,
|
|
hIcon: 0 as _,
|
|
hCursor: 0 as _,
|
|
hbrBackground: 0 as _,
|
|
lpszMenuName: std::ptr::null(),
|
|
lpszClassName: class_name.as_ptr(),
|
|
hIconSm: 0 as _,
|
|
};
|
|
let class_atom = RegisterClassExW(&wnd_class);
|
|
if class_atom == 0 {
|
|
println!("Failed to RegisterClassExW");
|
|
}
|
|
|
|
let hwnd = CreateWindowExW(
|
|
0,
|
|
class_name.as_ptr(),
|
|
std::ptr::null(),
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
HWND_MESSAGE,
|
|
0 as _,
|
|
0 as _,
|
|
std::ptr::null(),
|
|
);
|
|
if hwnd == 0 as _ {
|
|
println!("Failed to create Win32 clipboard message window");
|
|
return;
|
|
}
|
|
|
|
if AddClipboardFormatListener(hwnd) == 0 {
|
|
println!("Failed to AddClipboardFormatListener");
|
|
DestroyWindow(hwnd);
|
|
return;
|
|
}
|
|
println!("Win32 clipboard listener registered successfully on HWND_MESSAGE.");
|
|
|
|
let mut msg: MSG = std::mem::zeroed();
|
|
while GetMessageW(&mut msg, 0 as _, 0, 0) > 0 {
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
}
|
|
|
|
RemoveClipboardFormatListener(hwnd);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
})
|
|
.expect("Failed to spawn thread");
|
|
|
|
// Run a basic tokio runtime to keep the main thread alive for a bit
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
rt.block_on(async {
|
|
let _ = tokio::time::timeout(tokio::time::Duration::from_secs(3), async {
|
|
while let Some(()) = rx.recv().await {
|
|
println!("Got message from channel");
|
|
}
|
|
}).await;
|
|
});
|
|
|
|
println!("Isolation test completed without crash.");
|
|
}
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
fn main() {
|
|
println!("Not on windows, skipping isolation test");
|
|
}
|