[feat] improve Windows secure desktop capture and input handling, refs #77

This commit is contained in:
dijunkun
2026-05-26 03:26:37 +08:00
parent 52b894fe0e
commit 665f4e684c
10 changed files with 776 additions and 139 deletions
+20 -3
View File
@@ -88,9 +88,14 @@ struct WindowsServiceInteractiveStatus {
};
constexpr uint32_t kWindowsServiceStatusIntervalMs = 1000;
constexpr DWORD kWindowsServiceQueryTimeoutMs = 100;
constexpr DWORD kWindowsServiceQueryTimeoutMs = 500;
constexpr DWORD kWindowsServiceSasTimeoutMs = 500;
bool IsTransientWindowsServiceStatusError(const std::string& error) {
return error == "pipe_unavailable" || error == "pipe_connect_failed" ||
error == "pipe_read_failed";
}
RemoteAction BuildWindowsServiceStatusAction(
const WindowsServiceInteractiveStatus& status) {
RemoteAction action{};
@@ -1938,9 +1943,16 @@ void Render::HandleWindowsServiceIntegration() {
WindowsServiceInteractiveStatus status;
const bool status_ok = QueryWindowsServiceInteractiveStatus(&status);
local_service_status_received_ = status_ok;
const bool previous_secure_desktop_interaction =
IsSecureDesktopInteractionRequired(local_interactive_stage_);
local_service_status_received_ =
status_ok || previous_secure_desktop_interaction;
local_service_available_ = status.available;
local_interactive_stage_ = status.available ? status.interactive_stage : "";
if (status.available) {
local_interactive_stage_ = status.interactive_stage;
} else if (!previous_secure_desktop_interaction) {
local_interactive_stage_.clear();
}
if (status_ok) {
const bool availability_changed =
@@ -1953,6 +1965,11 @@ void Render::HandleWindowsServiceIntegration() {
if (status.available) {
LOG_INFO(
"Local Windows service available for secure desktop integration");
} else if (IsTransientWindowsServiceStatusError(status.error)) {
LOG_INFO(
"Local Windows service temporarily unavailable, keeping last "
"secure desktop state: error={}, code={}",
status.error, status.error_code);
} else {
LOG_WARN(
"Local Windows service unavailable, secure desktop integration "
+25 -2
View File
@@ -317,6 +317,22 @@ void LogSecureDesktopInputBlocked(uint32_t* last_tick, const char* side,
"cannot drive the Windows password UI",
side != nullptr ? side : "unknown", stage != nullptr ? stage : "");
}
bool IsTransientSecureDesktopInputFailure(const nlohmann::json& response,
const RemoteAction& action) {
if (!response.is_object()) {
return false;
}
if (response.value("error", std::string()) != "send_input_failed") {
return false;
}
if (response.value("code", 0u) != ERROR_ACCESS_DENIED) {
return false;
}
return action.type == ControlType::keyboard &&
action.k.flag == KeyFlag::key_up;
}
#endif
} // namespace
@@ -492,7 +508,7 @@ int Render::ProcessKeyboardEvent(const SDL_Event& event) {
int Render::ProcessMouseEvent(const SDL_Event& event) {
controlled_remote_id_ = "";
RemoteAction remote_action;
RemoteAction remote_action{};
float cursor_x = last_mouse_event.motion.x;
float cursor_y = last_mouse_event.motion.y;
@@ -1104,7 +1120,6 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
// remote
#if _WIN32
if (render->local_service_status_received_ &&
render->local_service_available_ &&
IsSecureDesktopInteractionRequired(render->local_interactive_stage_)) {
if (remote_action.type == ControlType::mouse) {
int absolute_x = 0;
@@ -1145,6 +1160,14 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
remote_action.k.extended, 1000);
auto json = nlohmann::json::parse(response, nullptr, false);
if (json.is_discarded() || !json.value("ok", false)) {
if (!json.is_discarded() &&
IsTransientSecureDesktopInputFailure(json, remote_action)) {
LOG_INFO(
"Secure desktop keyboard injection transient failure, "
"key_code={}, is_down={}, response={}",
key_code, is_down, response);
return;
}
LogSecureDesktopInputBlocked(
&render->last_local_secure_input_block_log_tick_, "local",
render->local_interactive_stage_.c_str());