shroud icon indicating copy to clipboard operation
shroud copied to clipboard

get_process_window not working correctly / get_process_window returns arbitrary window handle instead of main window

Open phamtuan993 opened this issue 3 months ago • 1 comments

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),
    }
}

phamtuan993 avatar Sep 18 '25 17:09 phamtuan993

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!

ohchase avatar Oct 02 '25 12:10 ohchase