mirror of
https://github.com/Devolutions/IronRDP.git
synced 2025-12-23 12:26:46 +00:00
fix(cliprdr): prevent window class registration error on multiple sessions (#1047)
Some checks are pending
CI / Check formatting (push) Waiting to run
CI / FFI (push) Blocked by required conditions
CI / Success (push) Blocked by required conditions
CI / Check typos (push) Waiting to run
CI / Checks [linux] (push) Blocked by required conditions
CI / Checks [macos] (push) Blocked by required conditions
CI / Checks [windows] (push) Blocked by required conditions
CI / Fuzzing (push) Blocked by required conditions
CI / Web Client (push) Blocked by required conditions
Coverage / Coverage Report (push) Waiting to run
Release crates / Open release PR (push) Waiting to run
Release crates / Release crates (push) Waiting to run
Some checks are pending
CI / Check formatting (push) Waiting to run
CI / FFI (push) Blocked by required conditions
CI / Success (push) Blocked by required conditions
CI / Check typos (push) Waiting to run
CI / Checks [linux] (push) Blocked by required conditions
CI / Checks [macos] (push) Blocked by required conditions
CI / Checks [windows] (push) Blocked by required conditions
CI / Fuzzing (push) Blocked by required conditions
CI / Web Client (push) Blocked by required conditions
Coverage / Coverage Report (push) Waiting to run
Release crates / Open release PR (push) Waiting to run
Release crates / Release crates (push) Waiting to run
When starting a second clipboard session, `RegisterClassA` would fail with `ERROR_CLASS_ALREADY_EXISTS` because window classes are global to the process. Now checks if the class is already registered before attempting registration, allowing multiple WinClipboard instances to coexist.
This commit is contained in:
parent
924330159a
commit
a2af587e60
1 changed files with 20 additions and 11 deletions
|
|
@ -19,7 +19,8 @@ use windows::Win32::System::DataExchange::{AddClipboardFormatListener, RemoveCli
|
|||
use windows::Win32::System::LibraryLoader::GetModuleHandleA;
|
||||
use windows::Win32::UI::Shell::{RemoveWindowSubclass, SetWindowSubclass};
|
||||
use windows::Win32::UI::WindowsAndMessaging::{
|
||||
CreateWindowExA, DefWindowProcA, RegisterClassA, CW_USEDEFAULT, WINDOW_EX_STYLE, WM_USER, WNDCLASSA, WS_POPUP,
|
||||
CreateWindowExA, DefWindowProcA, GetClassInfoA, RegisterClassA, CW_USEDEFAULT, WINDOW_EX_STYLE, WM_USER, WNDCLASSA,
|
||||
WS_POPUP,
|
||||
};
|
||||
|
||||
use self::clipboard_impl::{clipboard_subproc, WinClipboardImpl};
|
||||
|
|
@ -152,17 +153,25 @@ impl WinClipboard {
|
|||
// SAFETY: low-level WinAPI call
|
||||
let instance = unsafe { GetModuleHandleA(None)? };
|
||||
let window_class = s!("IronRDPClipboardMonitor");
|
||||
let wc = WNDCLASSA {
|
||||
hInstance: instance.into(),
|
||||
lpszClassName: window_class,
|
||||
lpfnWndProc: Some(wndproc),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// SAFETY: low-level WinAPI call
|
||||
let atom = unsafe { RegisterClassA(&wc) };
|
||||
if atom == 0 {
|
||||
return Err(WinCliprdrError::from(Error::from_thread()));
|
||||
let mut existing_wc = WNDCLASSA::default();
|
||||
// SAFETY: `instance` is a valid module handle, `window_class` is a valid null-terminated string,
|
||||
// and `existing_wc` is a valid mutable reference to a WNDCLASSA structure.
|
||||
let class_exists = unsafe { GetClassInfoA(Some(instance.into()), window_class, &mut existing_wc).is_ok() };
|
||||
|
||||
if !class_exists {
|
||||
let wc = WNDCLASSA {
|
||||
hInstance: instance.into(),
|
||||
lpszClassName: window_class,
|
||||
lpfnWndProc: Some(wndproc),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// SAFETY: low-level WinAPI call
|
||||
let atom = unsafe { RegisterClassA(&wc) };
|
||||
if atom == 0 {
|
||||
return Err(WinCliprdrError::from(Error::from_thread()));
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: low-level WinAPI call
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue