libobs_window_helper\util/
validators.rs1use std::os::raw::c_void;
2use windows::Win32::UI::WindowsAndMessaging::{
3 GetClientRect, GetWindowLongPtrW, IsIconic, IsWindowVisible, GWL_EXSTYLE, GWL_STYLE, WS_CHILD,
4 WS_EX_TOOLWINDOW,
5};
6use windows::{
7 core::Result,
8 Win32::{
9 Foundation::{HWND, RECT},
10 Graphics::Dwm::{DwmGetWindowAttribute, DWMWA_CLOAKED},
11 },
12};
13
14const INTERNAL_MICROSOFT_EXES_EXACT: &[&str] = &[
15 "startmenuexperiencehost.exe",
16 "applicationframehost.exe",
17 "peopleexperiencehost.exe",
18 "shellexperiencehost.exe",
19 "microsoft.notes.exe",
20 "systemsettings.exe",
21 "textinputhost.exe",
22 "searchapp.exe",
23 "video.ui.exe",
24 "searchui.exe",
25 "lockapp.exe",
26 "cortana.exe",
27 "gamebar.exe",
28 "tabtip.exe",
29 "time.exe",
30];
31
32const INTERNAL_MICROSOFT_EXES_PARTIAL: &[&str] = &["windowsinternal"];
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum WindowSearchMode {
36 ExcludeMinimized,
37 IncludeMinimized,
38}
39
40#[allow(clippy::upper_case_acronyms)]
41type DWORD = u32;
42
43pub(crate) fn is_window_cloaked(handle: HWND) -> bool {
44 let cloaked: DWORD = 0;
45 let res = unsafe {
46 DwmGetWindowAttribute(
49 handle,
50 DWMWA_CLOAKED,
51 cloaked as *mut c_void,
52 size_of::<DWORD>() as u32,
53 )
54 };
55
56 res.is_ok() && cloaked != 0
57}
58
59pub fn is_window_valid(handle: HWND, mode: WindowSearchMode) -> Result<bool> {
60 let is_visible = unsafe {
61 IsWindowVisible(handle)
64 };
65 if !is_visible.as_bool() {
66 return Ok(false);
67 }
68
69 if mode == WindowSearchMode::ExcludeMinimized {
70 let is_minimized = unsafe {
71 IsIconic(handle).as_bool()
73 } || is_window_cloaked(handle);
74 if is_minimized {
75 return Ok(false);
76 }
77 }
78
79 let mut rect = RECT::default();
80 let styles;
81 let ex_styles;
82
83 unsafe {
84 GetClientRect(handle, &mut rect)?;
87
88 styles = GetWindowLongPtrW(handle, GWL_STYLE) as DWORD;
90 ex_styles = GetWindowLongPtrW(handle, GWL_EXSTYLE) as DWORD;
91 }
92
93 if ex_styles & WS_EX_TOOLWINDOW.0 > 0 {
94 return Ok(false);
95 }
96 if styles & WS_CHILD.0 > 0 {
97 return Ok(false);
98 }
99
100 if mode == WindowSearchMode::ExcludeMinimized && (rect.bottom == 0 || rect.right == 0) {
101 return Ok(false);
102 }
103
104 Ok(true)
105}
106
107pub fn is_microsoft_internal_exe(exe: &str) -> bool {
108 let exact = INTERNAL_MICROSOFT_EXES_EXACT.contains(&exe);
109 let partial = INTERNAL_MICROSOFT_EXES_PARTIAL
110 .iter()
111 .any(|e| exe.contains(e));
112
113 exact || partial
114}