mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-24 13:48:51 +08:00
[fix] repair Windows privacy screen startup and capture recovery
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "../screen_capturer/dxgi_cursor_state.h"
|
#include "../screen_capturer/dxgi_cursor_state.h"
|
||||||
#include "privacy_cursor_api.h"
|
#include "privacy_cursor_api.h"
|
||||||
|
#include "privacy_cursor_process.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
@@ -85,15 +86,13 @@ bool PrivacyCursorGuard::Start(std::string& error) {
|
|||||||
startup.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
startup.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||||
inherited, sizeof(inherited), nullptr, nullptr) != FALSE;
|
inherited, sizeof(inherited), nullptr, nullptr) != FALSE;
|
||||||
PROCESS_INFORMATION child{};
|
PROCESS_INFORMATION child{};
|
||||||
|
bool used_job_fallback = false;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
std::wstring command = L"\"" + helper.wstring() + L"\"";
|
std::wstring command = L"\"" + helper.wstring() + L"\"";
|
||||||
for (HANDLE handle : inherited)
|
for (HANDLE handle : inherited)
|
||||||
command += L" " + std::to_wstring(reinterpret_cast<uintptr_t>(handle));
|
command += L" " + std::to_wstring(reinterpret_cast<uintptr_t>(handle));
|
||||||
ok =
|
ok = CreatePrivacyCursorProcess(helper.c_str(), command, startup, child,
|
||||||
CreateProcessW(helper.c_str(), command.data(), nullptr, nullptr, TRUE,
|
used_job_fallback);
|
||||||
CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT |
|
|
||||||
CREATE_BREAKAWAY_FROM_JOB,
|
|
||||||
nullptr, nullptr, &startup.StartupInfo, &child) != FALSE;
|
|
||||||
}
|
}
|
||||||
const DWORD start_error = GetLastError();
|
const DWORD start_error = GetLastError();
|
||||||
DeleteProcThreadAttributeList(startup.lpAttributeList);
|
DeleteProcThreadAttributeList(startup.lpAttributeList);
|
||||||
@@ -102,6 +101,11 @@ bool PrivacyCursorGuard::Start(std::string& error) {
|
|||||||
return Failed("Start crossdesk_privacy_cursor_helper.exe", error,
|
return Failed("Start crossdesk_privacy_cursor_helper.exe", error,
|
||||||
start_error);
|
start_error);
|
||||||
}
|
}
|
||||||
|
if (used_job_fallback) {
|
||||||
|
LOG_INFO("Privacy cursor: launcher denied job breakaway; helper process={} "
|
||||||
|
"started without breakaway flag with parent-exit monitoring",
|
||||||
|
child.dwProcessId);
|
||||||
|
}
|
||||||
CloseHandle(child.hThread);
|
CloseHandle(child.hThread);
|
||||||
process_ = child.hProcess;
|
process_ = child.hProcess;
|
||||||
stop_event_ = stop.value;
|
stop_event_ = stop.value;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* @Author: DI JUNKUN
|
||||||
|
* @Date: 2026-10-08
|
||||||
|
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PRIVACY_CURSOR_PROCESS_H_
|
||||||
|
#define _PRIVACY_CURSOR_PROCESS_H_
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
|
// Prefer an independent lifetime, so closing the launcher's job cannot kill
|
||||||
|
// the cursor helper before it restores the cursor. Some launchers (including
|
||||||
|
// scheduled tasks) forbid breakaway. In that case retain the inherited parent
|
||||||
|
// process handle/stop event and run in the job; parent-only exits still trigger
|
||||||
|
// cleanup, although terminating the entire job also terminates the helper.
|
||||||
|
inline bool CreatePrivacyCursorProcess(const wchar_t* executable,
|
||||||
|
const std::wstring& command,
|
||||||
|
STARTUPINFOEXW& startup,
|
||||||
|
PROCESS_INFORMATION& child,
|
||||||
|
bool& used_job_fallback) {
|
||||||
|
used_job_fallback = false;
|
||||||
|
const auto create = [&](DWORD flags) {
|
||||||
|
// CreateProcessW may modify its command line, including on failure.
|
||||||
|
auto mutable_command = command;
|
||||||
|
return CreateProcessW(executable, mutable_command.data(), nullptr, nullptr,
|
||||||
|
TRUE, CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT |
|
||||||
|
flags,
|
||||||
|
nullptr, nullptr, &startup.StartupInfo, &child) != FALSE;
|
||||||
|
};
|
||||||
|
if (create(CREATE_BREAKAWAY_FROM_JOB)) return true;
|
||||||
|
const DWORD error = GetLastError();
|
||||||
|
BOOL in_job = FALSE;
|
||||||
|
if (error != ERROR_ACCESS_DENIED ||
|
||||||
|
!IsProcessInJob(GetCurrentProcess(), nullptr, &in_job) || !in_job) {
|
||||||
|
SetLastError(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!create(0)) return false;
|
||||||
|
used_job_fallback = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crossdesk
|
||||||
|
|
||||||
|
#endif // _PRIVACY_CURSOR_PROCESS_H_
|
||||||
@@ -932,6 +932,9 @@ int ScreenCapturerWin::Stop() {
|
|||||||
// Drain management operations before stopping/replacing their backend.
|
// Drain management operations before stopping/replacing their backend.
|
||||||
virtual_display_.RequestCancel();
|
virtual_display_.RequestCancel();
|
||||||
StopSecureCaptureThread();
|
StopSecureCaptureThread();
|
||||||
|
// A recovery already in progress can publish "running" while Stop waits.
|
||||||
|
// Publish the final stopped state after that management thread has exited.
|
||||||
|
NotifyPrivacyCapture(false);
|
||||||
JoinVirtualDisplayThread();
|
JoinVirtualDisplayThread();
|
||||||
ResetPostSecureDesktopState();
|
ResetPostSecureDesktopState();
|
||||||
if (impl_) {
|
if (impl_) {
|
||||||
@@ -1238,6 +1241,7 @@ bool ScreenCapturerWin::RestartCaptureBackendAfterSecureDesktop() {
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
applied_show_cursor_ = show_cursor;
|
applied_show_cursor_ = show_cursor;
|
||||||
RestoreMonitor(current_monitor);
|
RestoreMonitor(current_monitor);
|
||||||
|
NotifyPrivacyCapture(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1253,11 +1257,13 @@ bool ScreenCapturerWin::RestartCaptureBackendAfterSecureDesktop() {
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
applied_show_cursor_ = show_cursor;
|
applied_show_cursor_ = show_cursor;
|
||||||
RestoreMonitor(current_monitor);
|
RestoreMonitor(current_monitor);
|
||||||
|
NotifyPrivacyCapture(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StartPreferredBackend(headless_compat_.load(std::memory_order_relaxed),
|
if (StartPreferredBackend(headless_compat_.load(std::memory_order_relaxed),
|
||||||
current_monitor, usbmmidd)) {
|
current_monitor, usbmmidd)) {
|
||||||
|
NotifyPrivacyCapture(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user