mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-15 00:09:39 +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 "privacy_cursor_api.h"
|
||||
#include "privacy_cursor_process.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
@@ -85,15 +86,13 @@ bool PrivacyCursorGuard::Start(std::string& error) {
|
||||
startup.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||
inherited, sizeof(inherited), nullptr, nullptr) != FALSE;
|
||||
PROCESS_INFORMATION child{};
|
||||
bool used_job_fallback = false;
|
||||
if (ok) {
|
||||
std::wstring command = L"\"" + helper.wstring() + L"\"";
|
||||
for (HANDLE handle : inherited)
|
||||
command += L" " + std::to_wstring(reinterpret_cast<uintptr_t>(handle));
|
||||
ok =
|
||||
CreateProcessW(helper.c_str(), command.data(), nullptr, nullptr, TRUE,
|
||||
CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT |
|
||||
CREATE_BREAKAWAY_FROM_JOB,
|
||||
nullptr, nullptr, &startup.StartupInfo, &child) != FALSE;
|
||||
ok = CreatePrivacyCursorProcess(helper.c_str(), command, startup, child,
|
||||
used_job_fallback);
|
||||
}
|
||||
const DWORD start_error = GetLastError();
|
||||
DeleteProcThreadAttributeList(startup.lpAttributeList);
|
||||
@@ -102,6 +101,11 @@ bool PrivacyCursorGuard::Start(std::string& error) {
|
||||
return Failed("Start crossdesk_privacy_cursor_helper.exe", 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);
|
||||
process_ = child.hProcess;
|
||||
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.
|
||||
virtual_display_.RequestCancel();
|
||||
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();
|
||||
ResetPostSecureDesktopState();
|
||||
if (impl_) {
|
||||
@@ -1238,6 +1241,7 @@ bool ScreenCapturerWin::RestartCaptureBackendAfterSecureDesktop() {
|
||||
if (ret == 0) {
|
||||
applied_show_cursor_ = show_cursor;
|
||||
RestoreMonitor(current_monitor);
|
||||
NotifyPrivacyCapture(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1253,11 +1257,13 @@ bool ScreenCapturerWin::RestartCaptureBackendAfterSecureDesktop() {
|
||||
if (ret == 0) {
|
||||
applied_show_cursor_ = show_cursor;
|
||||
RestoreMonitor(current_monitor);
|
||||
NotifyPrivacyCapture(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StartPreferredBackend(headless_compat_.load(std::memory_order_relaxed),
|
||||
current_monitor, usbmmidd)) {
|
||||
NotifyPrivacyCapture(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user