windows: Fix some weird IME window panic (#15286)
Previously, we used messages greater than `WM_USER` to pass information between `WindowsPlatform` and `WindowsWindow`. For example, to close a window, we handled it as follows: 1. The window sends a message with `WM_USER + 2` to `WindowsPlatform`. 2. `WindowsPlatform`, upon receiving this message, casts the `lparam` to `HWND` and closes the window. According to Microsoft's documentation, it is safe to use values between `WM_USER` and `0xBFFF` as messages. However, certain versions of Microsoft's IME use `WM_USER + 2` for UNKNOWN purposes. This causes step 2 to be erroneously triggered. The IME window's `lparam` value could be arbitrary, leading to an attempt to close an arbitrary `HWND` and resulting in errors. It is quite surprising that Microsoft indicates using `WM_USER + 2` is safe, yet Microsoft itself breaks this convention. I mean, well done Microsoft! This PR addresses the issue by using the `wparam` with a specific random value for validation purpose when sending the aforementioned message. Before `WindowsPlatform` attempts to close the window, it will first verify the `wparam` value. Special thanks to @shenjackyuanjie for helping me on this. Co-authored-by: shenjackyuanjie <3695888@qq.com> Release Notes: - Fixed weird panic when IME window is closing(#15185, #12563). --------- Co-authored-by: shenjack <3695888@qq.com>
This commit is contained in:
parent
e6cd1cf22b
commit
6af385c09e
3 changed files with 31 additions and 3 deletions
|
@ -217,7 +217,13 @@ fn handle_destroy_msg(handle: HWND, state_ptr: Rc<WindowsWindowStatePtr>) -> Opt
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
PostMessageW(None, CLOSE_ONE_WINDOW, None, LPARAM(handle.0 as isize)).log_err();
|
PostMessageW(
|
||||||
|
None,
|
||||||
|
CLOSE_ONE_WINDOW,
|
||||||
|
WPARAM(state_ptr.validation_number),
|
||||||
|
LPARAM(handle.0 as isize),
|
||||||
|
)
|
||||||
|
.log_err();
|
||||||
}
|
}
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ pub(crate) struct WindowsPlatform {
|
||||||
clipboard_metadata_format: u32,
|
clipboard_metadata_format: u32,
|
||||||
windows_version: WindowsVersion,
|
windows_version: WindowsVersion,
|
||||||
bitmap_factory: ManuallyDrop<IWICImagingFactory>,
|
bitmap_factory: ManuallyDrop<IWICImagingFactory>,
|
||||||
|
validation_number: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct WindowsPlatformState {
|
pub(crate) struct WindowsPlatformState {
|
||||||
|
@ -111,6 +112,7 @@ impl WindowsPlatform {
|
||||||
let clipboard_metadata_format =
|
let clipboard_metadata_format =
|
||||||
register_clipboard_format(CLIPBOARD_METADATA_FORMAT).unwrap();
|
register_clipboard_format(CLIPBOARD_METADATA_FORMAT).unwrap();
|
||||||
let windows_version = WindowsVersion::new().expect("Error retrieve windows version");
|
let windows_version = WindowsVersion::new().expect("Error retrieve windows version");
|
||||||
|
let validation_number = rand::random::<usize>();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
state,
|
state,
|
||||||
|
@ -123,6 +125,7 @@ impl WindowsPlatform {
|
||||||
clipboard_metadata_format,
|
clipboard_metadata_format,
|
||||||
windows_version,
|
windows_version,
|
||||||
bitmap_factory,
|
bitmap_factory,
|
||||||
|
validation_number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +162,16 @@ impl WindowsPlatform {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_one_window(&self, target_window: HWND) -> bool {
|
fn close_one_window(
|
||||||
|
&self,
|
||||||
|
target_window: HWND,
|
||||||
|
validation_number: usize,
|
||||||
|
msg: *const MSG,
|
||||||
|
) -> bool {
|
||||||
|
if validation_number != self.validation_number {
|
||||||
|
unsafe { DispatchMessageW(msg) };
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let mut lock = self.raw_window_handles.write();
|
let mut lock = self.raw_window_handles.write();
|
||||||
let index = lock
|
let index = lock
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -206,7 +218,11 @@ impl Platform for WindowsPlatform {
|
||||||
match msg.message {
|
match msg.message {
|
||||||
WM_QUIT => break 'a,
|
WM_QUIT => break 'a,
|
||||||
CLOSE_ONE_WINDOW => {
|
CLOSE_ONE_WINDOW => {
|
||||||
if self.close_one_window(HWND(msg.lParam.0 as _)) {
|
if self.close_one_window(
|
||||||
|
HWND(msg.lParam.0 as _),
|
||||||
|
msg.wParam.0,
|
||||||
|
&msg,
|
||||||
|
) {
|
||||||
break 'a;
|
break 'a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,6 +332,7 @@ impl Platform for WindowsPlatform {
|
||||||
self.foreground_executor.clone(),
|
self.foreground_executor.clone(),
|
||||||
lock.current_cursor,
|
lock.current_cursor,
|
||||||
self.windows_version,
|
self.windows_version,
|
||||||
|
self.validation_number,
|
||||||
)?;
|
)?;
|
||||||
drop(lock);
|
drop(lock);
|
||||||
let handle = window.get_raw_handle();
|
let handle = window.get_raw_handle();
|
||||||
|
|
|
@ -62,6 +62,7 @@ pub(crate) struct WindowsWindowStatePtr {
|
||||||
pub(crate) is_movable: bool,
|
pub(crate) is_movable: bool,
|
||||||
pub(crate) executor: ForegroundExecutor,
|
pub(crate) executor: ForegroundExecutor,
|
||||||
pub(crate) windows_version: WindowsVersion,
|
pub(crate) windows_version: WindowsVersion,
|
||||||
|
pub(crate) validation_number: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowsWindowState {
|
impl WindowsWindowState {
|
||||||
|
@ -224,6 +225,7 @@ impl WindowsWindowStatePtr {
|
||||||
is_movable: context.is_movable,
|
is_movable: context.is_movable,
|
||||||
executor: context.executor.clone(),
|
executor: context.executor.clone(),
|
||||||
windows_version: context.windows_version,
|
windows_version: context.windows_version,
|
||||||
|
validation_number: context.validation_number,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,6 +252,7 @@ struct WindowCreateContext {
|
||||||
executor: ForegroundExecutor,
|
executor: ForegroundExecutor,
|
||||||
current_cursor: HCURSOR,
|
current_cursor: HCURSOR,
|
||||||
windows_version: WindowsVersion,
|
windows_version: WindowsVersion,
|
||||||
|
validation_number: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowsWindow {
|
impl WindowsWindow {
|
||||||
|
@ -260,6 +263,7 @@ impl WindowsWindow {
|
||||||
executor: ForegroundExecutor,
|
executor: ForegroundExecutor,
|
||||||
current_cursor: HCURSOR,
|
current_cursor: HCURSOR,
|
||||||
windows_version: WindowsVersion,
|
windows_version: WindowsVersion,
|
||||||
|
validation_number: usize,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let classname = register_wnd_class(icon);
|
let classname = register_wnd_class(icon);
|
||||||
let hide_title_bar = params
|
let hide_title_bar = params
|
||||||
|
@ -300,6 +304,7 @@ impl WindowsWindow {
|
||||||
executor,
|
executor,
|
||||||
current_cursor,
|
current_cursor,
|
||||||
windows_version,
|
windows_version,
|
||||||
|
validation_number,
|
||||||
};
|
};
|
||||||
let lpparam = Some(&context as *const _ as *const _);
|
let lpparam = Some(&context as *const _ as *const _);
|
||||||
let creation_result = unsafe {
|
let creation_result = unsafe {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue