shroud
shroud copied to clipboard
get_process_window not working correctly / get_process_window returns arbitrary window handle instead of main window
I expect the get_process_window function to return the main window handle of the current process, not just any window handle belonging to the current process.
The current implementation of get_process_window does not work correctly if a process contains multiple windows or controls, as it may return a handle to a child control instead of the main application window.
pub(crate) fn get_process_window() -> Option<HWND> {
extern "system" fn enum_windows_callback(hwnd: HWND, l_param: LPARAM) -> BOOL {
let mut wnd_proc_id: u32 = 0;
unsafe {
GetWindowThreadProcessId(hwnd, Some(&mut wnd_proc_id));
if std::process::id() != wnd_proc_id {
return true.into();
}
// windows has an owner => not a main window
if GetWindow(hwnd, GW_OWNER).is_ok() {
return true.into();
}
*(l_param.0 as *mut HWND) = hwnd;
}
false.into()
}
let mut output: HWND = HWND::default();
unsafe {
let _ = EnumWindows(
Some(enum_windows_callback),
std::mem::transmute::<_, LPARAM>(&mut output as *mut HWND),
);
};
match output.is_invalid() {
true => None,
false => Some(output),
}
}
Thank you very much! I'm familiar with this issue. This will be a pain point for those who want to spawn a terminal on windows when injecting a DLL. Your suggested fix looks ideal, I can work on this during the weekend. If you'd like pull requests are welcome as well!