提交 1e48b522 编写于 作者: J jp9000

win-capture: Fix getting proper UWP window handles

The "main" windows detected for UWP programs are basically to help
sandbox the programs -- they run in the ApplicationFrameHost process and
help reduce the possibility of other programs trying to access the
actual process window, which is a child window.

To bypass this, go through the list of child windows for the
ApplicationFrameHost window, and then find the one that's attached to
a different process; that different process will always be the target,
and will allows us to open the actual process of the UWP program.
上级 4ec10337
......@@ -1443,6 +1443,9 @@ static void game_capture_tick(void *data, float seconds)
if (activate_now) {
HWND hwnd = (HWND)os_atomic_load_long(&gc->hotkey_window);
if (is_uwp_window(hwnd))
hwnd = get_uwp_actual_window(hwnd);
if (get_window_exe(&gc->executable, hwnd)) {
get_window_title(&gc->title, hwnd);
get_window_class(&gc->class, hwnd);
......
......@@ -192,33 +192,92 @@ static bool check_window_valid(HWND window, enum window_search_mode mode)
return true;
}
static inline HWND next_window(HWND window, enum window_search_mode mode)
bool is_uwp_window(HWND hwnd)
{
wchar_t name[256];
name[0] = 0;
if (!GetClassNameW(hwnd, name, sizeof(name) / sizeof(wchar_t)))
return false;
return wcscmp(name, L"ApplicationFrameWindow") == 0;
}
HWND get_uwp_actual_window(HWND parent)
{
DWORD parent_id = 0;
HWND child;
GetWindowThreadProcessId(parent, &parent_id);
child = GetWindow(parent, GW_CHILD);
while (child) {
DWORD child_id = 0;
GetWindowThreadProcessId(child, &child_id);
if (child_id != parent_id)
return child;
child = GetNextWindow(child, GW_HWNDNEXT);
}
return NULL;
}
static inline HWND next_window(HWND window, enum window_search_mode mode,
HWND *parent)
{
if (*parent) {
window = *parent;
*parent = NULL;
}
while (true) {
window = GetNextWindow(window, GW_HWNDNEXT);
if (!window || check_window_valid(window, mode))
break;
}
if (is_uwp_window(window)) {
HWND child = get_uwp_actual_window(window);
if (child) {
*parent = window;
return child;
}
}
return window;
}
static inline HWND first_window(enum window_search_mode mode)
static inline HWND first_window(enum window_search_mode mode, HWND *parent)
{
HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
*parent = NULL;
if (!check_window_valid(window, mode))
window = next_window(window, mode);
window = next_window(window, mode, parent);
if (is_uwp_window(window)) {
HWND child = get_uwp_actual_window(window);
if (child) {
*parent = window;
return child;
}
}
return window;
}
void fill_window_list(obs_property_t *p, enum window_search_mode mode,
add_window_cb callback)
{
HWND window = first_window(mode);
HWND parent;
HWND window = first_window(mode, &parent);
while (window) {
add_window(p, window, callback);
window = next_window(window, mode);
window = next_window(window, mode, &parent);
}
}
......@@ -268,7 +327,8 @@ HWND find_window(enum window_search_mode mode,
const char *title,
const char *exe)
{
HWND window = first_window(mode);
HWND parent;
HWND window = first_window(mode, &parent);
HWND best_window = NULL;
int best_rating = 0;
......@@ -279,7 +339,7 @@ HWND find_window(enum window_search_mode mode,
best_window = window;
}
window = next_window(window, mode);
window = next_window(window, mode, &parent);
}
return best_window;
......
......@@ -16,6 +16,8 @@ enum window_search_mode {
extern bool get_window_exe(struct dstr *name, HWND window);
extern void get_window_title(struct dstr *name, HWND hwnd);
extern void get_window_class(struct dstr *class, HWND hwnd);
extern bool is_uwp_window(HWND hwnd);
extern HWND get_uwp_actual_window(HWND parent);
typedef bool (*add_window_cb)(const char *title, const char *class,
const char *exe);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册