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