mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-07-21 06:18:44 +08:00
[fix] fix Windows UAC prompt input by routing Consent UI through secure input helper
This commit is contained in:
@@ -46,6 +46,7 @@ struct SecureDesktopServiceStatus {
|
|||||||
DWORD active_session_id = 0xFFFFFFFF;
|
DWORD active_session_id = 0xFFFFFFFF;
|
||||||
DWORD error_code = 0;
|
DWORD error_code = 0;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
std::string error;
|
std::string error;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,12 +135,16 @@ class WgcPluginCapturer final : public ScreenCapturer {
|
|||||||
|
|
||||||
std::string BuildSecureCaptureCommand(int left, int top, int width, int height,
|
std::string BuildSecureCaptureCommand(int left, int top, int width, int height,
|
||||||
bool show_cursor,
|
bool show_cursor,
|
||||||
const std::string& stage) {
|
const std::string& stage,
|
||||||
|
const std::string& desktop) {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << kCrossDeskSecureInputCaptureCommandPrefix << left << ":" << top
|
stream << kCrossDeskSecureInputCaptureCommandPrefix << left << ":" << top
|
||||||
<< ":" << width << ":" << height << ":" << (show_cursor ? 1 : 0);
|
<< ":" << width << ":" << height << ":" << (show_cursor ? 1 : 0);
|
||||||
if (!stage.empty()) {
|
if (!stage.empty()) {
|
||||||
stream << ":" << stage;
|
stream << ":" << stage;
|
||||||
|
if (!desktop.empty()) {
|
||||||
|
stream << ":" << desktop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
@@ -147,13 +152,17 @@ std::string BuildSecureCaptureCommand(int left, int top, int width, int height,
|
|||||||
std::string BuildSecureCaptureStartCommand(int left, int top, int width,
|
std::string BuildSecureCaptureStartCommand(int left, int top, int width,
|
||||||
int height, bool show_cursor,
|
int height, bool show_cursor,
|
||||||
int fps,
|
int fps,
|
||||||
const std::string& stage) {
|
const std::string& stage,
|
||||||
|
const std::string& desktop) {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << kCrossDeskSecureInputCaptureStartCommandPrefix << left << ":" << top
|
stream << kCrossDeskSecureInputCaptureStartCommandPrefix << left << ":" << top
|
||||||
<< ":" << width << ":" << height << ":" << (show_cursor ? 1 : 0)
|
<< ":" << width << ":" << height << ":" << (show_cursor ? 1 : 0)
|
||||||
<< ":" << fps;
|
<< ":" << fps;
|
||||||
if (!stage.empty()) {
|
if (!stage.empty()) {
|
||||||
stream << ":" << stage;
|
stream << ":" << stage;
|
||||||
|
if (!desktop.empty()) {
|
||||||
|
stream << ":" << desktop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
@@ -284,6 +293,7 @@ bool QuerySecureDesktopServiceStatus(SecureDesktopServiceStatus* status) {
|
|||||||
json.value("last_session_event", std::string()))) {
|
json.value("last_session_event", std::string()))) {
|
||||||
status->active_session_id = json.value("active_session_id", 0xFFFFFFFFu);
|
status->active_session_id = json.value("active_session_id", 0xFFFFFFFFu);
|
||||||
status->interactive_stage = "user-desktop";
|
status->interactive_stage = "user-desktop";
|
||||||
|
status->interactive_desktop.clear();
|
||||||
status->capture_active = false;
|
status->capture_active = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -291,6 +301,8 @@ bool QuerySecureDesktopServiceStatus(SecureDesktopServiceStatus* status) {
|
|||||||
status->active_session_id = json.value("active_session_id", 0xFFFFFFFFu);
|
status->active_session_id = json.value("active_session_id", 0xFFFFFFFFu);
|
||||||
status->helper_running = json.value("secure_input_helper_running", false);
|
status->helper_running = json.value("secure_input_helper_running", false);
|
||||||
status->interactive_stage = json.value("interactive_stage", std::string());
|
status->interactive_stage = json.value("interactive_stage", std::string());
|
||||||
|
status->interactive_desktop =
|
||||||
|
json.value("interactive_input_desktop", std::string());
|
||||||
const bool secure_desktop_active =
|
const bool secure_desktop_active =
|
||||||
json.value("interactive_secure_desktop_active",
|
json.value("interactive_secure_desktop_active",
|
||||||
json.value("secure_desktop_active", false));
|
json.value("secure_desktop_active", false));
|
||||||
@@ -358,6 +370,7 @@ bool QuerySecureDesktopHelperCommand(DWORD session_id,
|
|||||||
bool QuerySecureDesktopHelperFrame(DWORD session_id, int left, int top,
|
bool QuerySecureDesktopHelperFrame(DWORD session_id, int left, int top,
|
||||||
int width, int height, bool show_cursor,
|
int width, int height, bool show_cursor,
|
||||||
const std::string& stage,
|
const std::string& stage,
|
||||||
|
const std::string& desktop,
|
||||||
std::vector<uint8_t>* nv12_frame_out,
|
std::vector<uint8_t>* nv12_frame_out,
|
||||||
int* captured_width_out,
|
int* captured_width_out,
|
||||||
int* captured_height_out,
|
int* captured_height_out,
|
||||||
@@ -368,7 +381,8 @@ bool QuerySecureDesktopHelperFrame(DWORD session_id, int left, int top,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::string command =
|
const std::string command =
|
||||||
BuildSecureCaptureCommand(left, top, width, height, show_cursor, stage);
|
BuildSecureCaptureCommand(left, top, width, height, show_cursor, stage,
|
||||||
|
desktop);
|
||||||
std::vector<uint8_t> response;
|
std::vector<uint8_t> response;
|
||||||
if (!QuerySecureDesktopHelperCommand(session_id, command, &response,
|
if (!QuerySecureDesktopHelperCommand(session_id, command, &response,
|
||||||
error_out)) {
|
error_out)) {
|
||||||
@@ -823,6 +837,7 @@ void ScreenCapturerWin::StopSecureDesktopSharedCapture(DWORD session_id) {
|
|||||||
secure_shared_fps_ = 0;
|
secure_shared_fps_ = 0;
|
||||||
secure_shared_show_cursor_ = true;
|
secure_shared_show_cursor_ = true;
|
||||||
secure_shared_stage_.clear();
|
secure_shared_stage_.clear();
|
||||||
|
secure_shared_desktop_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenCapturerWin::OpenSecureDesktopSharedFrame(DWORD session_id,
|
bool ScreenCapturerWin::OpenSecureDesktopSharedFrame(DWORD session_id,
|
||||||
@@ -952,7 +967,8 @@ bool ScreenCapturerWin::ReadSecureDesktopSharedFrame(
|
|||||||
|
|
||||||
bool ScreenCapturerWin::StartSecureDesktopSharedCapture(
|
bool ScreenCapturerWin::StartSecureDesktopSharedCapture(
|
||||||
DWORD session_id, int left, int top, int width, int height,
|
DWORD session_id, int left, int top, int width, int height,
|
||||||
const std::string& stage, bool show_cursor, int fps,
|
const std::string& stage, const std::string& desktop, bool show_cursor,
|
||||||
|
int fps,
|
||||||
std::string* error_out) {
|
std::string* error_out) {
|
||||||
const size_t payload_size = static_cast<size_t>(width) * height * 3 / 2;
|
const size_t payload_size = static_cast<size_t>(width) * height * 3 / 2;
|
||||||
const size_t mapping_size =
|
const size_t mapping_size =
|
||||||
@@ -968,7 +984,7 @@ bool ScreenCapturerWin::StartSecureDesktopSharedCapture(
|
|||||||
secure_shared_session_id_ == session_id &&
|
secure_shared_session_id_ == session_id &&
|
||||||
secure_shared_left_ == left && secure_shared_top_ == top &&
|
secure_shared_left_ == left && secure_shared_top_ == top &&
|
||||||
secure_shared_width_ == width && secure_shared_height_ == height &&
|
secure_shared_width_ == width && secure_shared_height_ == height &&
|
||||||
secure_shared_stage_ == stage &&
|
secure_shared_stage_ == stage && secure_shared_desktop_ == desktop &&
|
||||||
secure_shared_show_cursor_ == show_cursor && secure_shared_fps_ == fps &&
|
secure_shared_show_cursor_ == show_cursor && secure_shared_fps_ == fps &&
|
||||||
OpenSecureDesktopSharedFrame(session_id, mapping_size, error_out)) {
|
OpenSecureDesktopSharedFrame(session_id, mapping_size, error_out)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -978,7 +994,7 @@ bool ScreenCapturerWin::StartSecureDesktopSharedCapture(
|
|||||||
|
|
||||||
const std::string command =
|
const std::string command =
|
||||||
BuildSecureCaptureStartCommand(left, top, width, height, show_cursor, fps,
|
BuildSecureCaptureStartCommand(left, top, width, height, show_cursor, fps,
|
||||||
stage);
|
stage, desktop);
|
||||||
std::vector<uint8_t> response;
|
std::vector<uint8_t> response;
|
||||||
if (!QuerySecureDesktopHelperCommand(session_id, command, &response,
|
if (!QuerySecureDesktopHelperCommand(session_id, command, &response,
|
||||||
error_out)) {
|
error_out)) {
|
||||||
@@ -1002,6 +1018,7 @@ bool ScreenCapturerWin::StartSecureDesktopSharedCapture(
|
|||||||
secure_shared_show_cursor_ = show_cursor;
|
secure_shared_show_cursor_ = show_cursor;
|
||||||
secure_shared_fps_ = fps;
|
secure_shared_fps_ = fps;
|
||||||
secure_shared_stage_ = stage;
|
secure_shared_stage_ = stage;
|
||||||
|
secure_shared_desktop_ = desktop;
|
||||||
|
|
||||||
if (!OpenSecureDesktopSharedFrame(session_id, mapping_size, error_out)) {
|
if (!OpenSecureDesktopSharedFrame(session_id, mapping_size, error_out)) {
|
||||||
StopSecureDesktopSharedCapture(session_id);
|
StopSecureDesktopSharedCapture(session_id);
|
||||||
@@ -1161,8 +1178,10 @@ void ScreenCapturerWin::SecureDesktopCaptureLoop() {
|
|||||||
|
|
||||||
if (StartSecureDesktopSharedCapture(status.active_session_id, left, top,
|
if (StartSecureDesktopSharedCapture(status.active_session_id, left, top,
|
||||||
width, height,
|
width, height,
|
||||||
status.interactive_stage, show_cursor,
|
status.interactive_stage,
|
||||||
shared_fps, &error_message) &&
|
status.interactive_desktop,
|
||||||
|
show_cursor, shared_fps,
|
||||||
|
&error_message) &&
|
||||||
ReadSecureDesktopSharedFrame(
|
ReadSecureDesktopSharedFrame(
|
||||||
static_cast<DWORD>(frame_interval_ms + 20), &secure_frame,
|
static_cast<DWORD>(frame_interval_ms + 20), &secure_frame,
|
||||||
&captured_width, &captured_height, &error_message)) {
|
&captured_width, &captured_height, &error_message)) {
|
||||||
@@ -1177,6 +1196,7 @@ void ScreenCapturerWin::SecureDesktopCaptureLoop() {
|
|||||||
QuerySecureDesktopHelperFrame(status.active_session_id, left, top,
|
QuerySecureDesktopHelperFrame(status.active_session_id, left, top,
|
||||||
width, height, show_cursor,
|
width, height, show_cursor,
|
||||||
status.interactive_stage,
|
status.interactive_stage,
|
||||||
|
status.interactive_desktop,
|
||||||
&secure_frame, &captured_width,
|
&secure_frame, &captured_width,
|
||||||
&captured_height, &error_message)) {
|
&captured_height, &error_message)) {
|
||||||
if (cb_orig_ && !secure_frame.empty()) {
|
if (cb_orig_ && !secure_frame.empty()) {
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class ScreenCapturerWin : public ScreenCapturer {
|
|||||||
int secure_shared_fps_ = 0;
|
int secure_shared_fps_ = 0;
|
||||||
bool secure_shared_show_cursor_ = true;
|
bool secure_shared_show_cursor_ = true;
|
||||||
std::string secure_shared_stage_;
|
std::string secure_shared_stage_;
|
||||||
|
std::string secure_shared_desktop_;
|
||||||
bool secure_shared_capture_started_ = false;
|
bool secure_shared_capture_started_ = false;
|
||||||
|
|
||||||
void BuildCanonicalFromImpl();
|
void BuildCanonicalFromImpl();
|
||||||
@@ -87,6 +88,7 @@ class ScreenCapturerWin : public ScreenCapturer {
|
|||||||
bool StartSecureDesktopSharedCapture(DWORD session_id, int left, int top,
|
bool StartSecureDesktopSharedCapture(DWORD session_id, int left, int top,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
const std::string& stage,
|
const std::string& stage,
|
||||||
|
const std::string& desktop,
|
||||||
bool show_cursor, int fps,
|
bool show_cursor, int fps,
|
||||||
std::string* error_out);
|
std::string* error_out);
|
||||||
void StopSecureDesktopSharedCapture(DWORD session_id);
|
void StopSecureDesktopSharedCapture(DWORD session_id);
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ struct ScopedEnvironmentBlock {
|
|||||||
LPVOID environment = nullptr;
|
LPVOID environment = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::wstring Utf8ToWide(const std::string& value);
|
||||||
std::string WideToUtf8(const std::wstring& value);
|
std::string WideToUtf8(const std::wstring& value);
|
||||||
|
|
||||||
std::wstring GetCurrentExecutablePathW() {
|
std::wstring GetCurrentExecutablePathW() {
|
||||||
@@ -358,24 +359,32 @@ std::string BuildSecureDesktopMouseIpcCommand(int x, int y, int wheel,
|
|||||||
|
|
||||||
std::string BuildSecureInputHelperKeyboardCommand(
|
std::string BuildSecureInputHelperKeyboardCommand(
|
||||||
int key_code, bool is_down, uint32_t scan_code, bool extended,
|
int key_code, bool is_down, uint32_t scan_code, bool extended,
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << kCrossDeskSecureInputKeyboardCommandPrefix << key_code << ":"
|
stream << kCrossDeskSecureInputKeyboardCommandPrefix << key_code << ":"
|
||||||
<< (is_down ? 1 : 0) << ":" << scan_code << ":" << (extended ? 1 : 0);
|
<< (is_down ? 1 : 0) << ":" << scan_code << ":" << (extended ? 1 : 0);
|
||||||
if (!interactive_stage.empty()) {
|
if (!interactive_stage.empty()) {
|
||||||
stream << ":" << interactive_stage;
|
stream << ":" << interactive_stage;
|
||||||
|
if (!interactive_desktop.empty()) {
|
||||||
|
stream << ":" << interactive_desktop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BuildSecureInputHelperMouseCommand(
|
std::string BuildSecureInputHelperMouseCommand(
|
||||||
int x, int y, int wheel, int flag,
|
int x, int y, int wheel, int flag,
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << kCrossDeskSecureInputMouseCommandPrefix << x << ":" << y << ":"
|
stream << kCrossDeskSecureInputMouseCommandPrefix << x << ":" << y << ":"
|
||||||
<< wheel << ":" << flag;
|
<< wheel << ":" << flag;
|
||||||
if (!interactive_stage.empty()) {
|
if (!interactive_stage.empty()) {
|
||||||
stream << ":" << interactive_stage;
|
stream << ":" << interactive_stage;
|
||||||
|
if (!interactive_desktop.empty()) {
|
||||||
|
stream << ":" << interactive_desktop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
@@ -592,15 +601,23 @@ const char* DetermineInteractiveStage(bool lock_app_visible,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsCredentialUiVisible(bool prelogin, bool session_locked,
|
bool IsCredentialUiVisible(bool prelogin, bool session_locked,
|
||||||
bool logon_ui_running,
|
bool logon_ui_running, bool consent_ui_visible,
|
||||||
bool input_desktop_available,
|
bool input_desktop_available,
|
||||||
bool secure_desktop_active) {
|
bool secure_desktop_active) {
|
||||||
return (prelogin || session_locked || secure_desktop_active) &&
|
return consent_ui_visible ||
|
||||||
(logon_ui_running || !input_desktop_available);
|
((prelogin || session_locked || secure_desktop_active) &&
|
||||||
|
(logon_ui_running || !input_desktop_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring SecureInputHelperDesktopForStage(
|
std::wstring SecureInputHelperDesktopForStage(
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
|
if (!interactive_desktop.empty()) {
|
||||||
|
std::wstring interactive_desktop_w = Utf8ToWide(interactive_desktop);
|
||||||
|
if (!interactive_desktop_w.empty()) {
|
||||||
|
return L"winsta0\\" + interactive_desktop_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (interactive_stage == "credential-ui" ||
|
if (interactive_stage == "credential-ui" ||
|
||||||
interactive_stage == "secure-desktop") {
|
interactive_stage == "secure-desktop") {
|
||||||
return L"winsta0\\Winlogon";
|
return L"winsta0\\Winlogon";
|
||||||
@@ -663,7 +680,12 @@ bool QuerySessionLockState(DWORD session_id, bool* session_locked_out) {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLogonUiRunningInSession(DWORD session_id) {
|
bool IsProcessRunningInSession(const wchar_t* executable_name,
|
||||||
|
DWORD session_id) {
|
||||||
|
if (executable_name == nullptr || executable_name[0] == L'\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
if (snapshot == INVALID_HANDLE_VALUE) {
|
if (snapshot == INVALID_HANDLE_VALUE) {
|
||||||
return false;
|
return false;
|
||||||
@@ -674,7 +696,7 @@ bool IsLogonUiRunningInSession(DWORD session_id) {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
if (Process32FirstW(snapshot, &entry)) {
|
if (Process32FirstW(snapshot, &entry)) {
|
||||||
do {
|
do {
|
||||||
if (_wcsicmp(entry.szExeFile, L"LogonUI.exe") != 0) {
|
if (_wcsicmp(entry.szExeFile, executable_name) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,6 +713,14 @@ bool IsLogonUiRunningInSession(DWORD session_id) {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsLogonUiRunningInSession(DWORD session_id) {
|
||||||
|
return IsProcessRunningInSession(L"LogonUI.exe", session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsConsentUiRunningInSession(DWORD session_id) {
|
||||||
|
return IsProcessRunningInSession(L"Consent.exe", session_id);
|
||||||
|
}
|
||||||
|
|
||||||
InputDesktopInfo GetInputDesktopInfo() {
|
InputDesktopInfo GetInputDesktopInfo() {
|
||||||
InputDesktopInfo info;
|
InputDesktopInfo info;
|
||||||
HDESK desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
HDESK desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
||||||
@@ -724,6 +754,24 @@ InputDesktopInfo GetInputDesktopInfo() {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring Utf8ToWide(const std::string& value) {
|
||||||
|
if (value.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int size_needed =
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, nullptr, 0);
|
||||||
|
if (size_needed <= 1) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring result(static_cast<size_t>(size_needed), L'\0');
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, result.data(),
|
||||||
|
size_needed);
|
||||||
|
result.pop_back();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string WideToUtf8(const std::wstring& value) {
|
std::string WideToUtf8(const std::wstring& value) {
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
return {};
|
return {};
|
||||||
@@ -1024,6 +1072,7 @@ int CrossDeskServiceHost::InitializeRuntime() {
|
|||||||
secure_input_helper_last_error_code_ = 0;
|
secure_input_helper_last_error_code_ = 0;
|
||||||
session_locked_ = false;
|
session_locked_ = false;
|
||||||
logon_ui_visible_ = false;
|
logon_ui_visible_ = false;
|
||||||
|
consent_ui_visible_ = false;
|
||||||
prelogin_ = false;
|
prelogin_ = false;
|
||||||
secure_desktop_active_ = false;
|
secure_desktop_active_ = false;
|
||||||
input_desktop_available_ = false;
|
input_desktop_available_ = false;
|
||||||
@@ -1032,6 +1081,7 @@ int CrossDeskServiceHost::InitializeRuntime() {
|
|||||||
session_helper_report_input_desktop_available_ = false;
|
session_helper_report_input_desktop_available_ = false;
|
||||||
session_helper_report_lock_app_visible_ = false;
|
session_helper_report_lock_app_visible_ = false;
|
||||||
session_helper_report_logon_ui_visible_ = false;
|
session_helper_report_logon_ui_visible_ = false;
|
||||||
|
session_helper_report_consent_ui_visible_ = false;
|
||||||
session_helper_report_secure_desktop_active_ = false;
|
session_helper_report_secure_desktop_active_ = false;
|
||||||
session_helper_report_credential_ui_visible_ = false;
|
session_helper_report_credential_ui_visible_ = false;
|
||||||
session_helper_report_unlock_ui_visible_ = false;
|
session_helper_report_unlock_ui_visible_ = false;
|
||||||
@@ -1056,6 +1106,7 @@ int CrossDeskServiceHost::InitializeRuntime() {
|
|||||||
session_helper_report_interactive_stage_.clear();
|
session_helper_report_interactive_stage_.clear();
|
||||||
secure_input_helper_last_error_.clear();
|
secure_input_helper_last_error_.clear();
|
||||||
secure_input_helper_interactive_stage_.clear();
|
secure_input_helper_interactive_stage_.clear();
|
||||||
|
secure_input_helper_interactive_desktop_.clear();
|
||||||
last_session_event_type_ = 0;
|
last_session_event_type_ = 0;
|
||||||
last_session_event_session_id_ = active_session_id_;
|
last_session_event_session_id_ = active_session_id_;
|
||||||
RefreshSessionState();
|
RefreshSessionState();
|
||||||
@@ -1283,6 +1334,7 @@ void CrossDeskServiceHost::RefreshSessionState() {
|
|||||||
process_session_id_ = process_session_id;
|
process_session_id_ = process_session_id;
|
||||||
}
|
}
|
||||||
logon_ui_visible_ = IsLogonUiRunningInSession(active_session_id_);
|
logon_ui_visible_ = IsLogonUiRunningInSession(active_session_id_);
|
||||||
|
consent_ui_visible_ = IsConsentUiRunningInSession(active_session_id_);
|
||||||
InputDesktopInfo desktop_info = GetInputDesktopInfo();
|
InputDesktopInfo desktop_info = GetInputDesktopInfo();
|
||||||
input_desktop_available_ = desktop_info.available;
|
input_desktop_available_ = desktop_info.available;
|
||||||
input_desktop_error_code_ = desktop_info.error_code;
|
input_desktop_error_code_ = desktop_info.error_code;
|
||||||
@@ -1312,6 +1364,7 @@ void CrossDeskServiceHost::ResetSessionHelperReportedStateLocked(
|
|||||||
session_helper_report_input_desktop_.clear();
|
session_helper_report_input_desktop_.clear();
|
||||||
session_helper_report_lock_app_visible_ = false;
|
session_helper_report_lock_app_visible_ = false;
|
||||||
session_helper_report_logon_ui_visible_ = false;
|
session_helper_report_logon_ui_visible_ = false;
|
||||||
|
session_helper_report_consent_ui_visible_ = false;
|
||||||
session_helper_report_secure_desktop_active_ = false;
|
session_helper_report_secure_desktop_active_ = false;
|
||||||
session_helper_report_credential_ui_visible_ = false;
|
session_helper_report_credential_ui_visible_ = false;
|
||||||
session_helper_report_unlock_ui_visible_ = false;
|
session_helper_report_unlock_ui_visible_ = false;
|
||||||
@@ -1334,10 +1387,12 @@ bool CrossDeskServiceHost::HasSecureInputUiLocked() const {
|
|||||||
const bool service_host_credential_ui_visible =
|
const bool service_host_credential_ui_visible =
|
||||||
!session_helper_status_ok_ &&
|
!session_helper_status_ok_ &&
|
||||||
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
||||||
|
consent_ui_visible_,
|
||||||
input_desktop_available_,
|
input_desktop_available_,
|
||||||
secure_desktop_active_);
|
secure_desktop_active_);
|
||||||
return IsSasSecureDesktopGraceActiveLocked() || prelogin_ ||
|
return IsSasSecureDesktopGraceActiveLocked() || prelogin_ ||
|
||||||
secure_desktop_active_ || service_host_credential_ui_visible ||
|
secure_desktop_active_ || service_host_credential_ui_visible ||
|
||||||
|
session_helper_report_consent_ui_visible_ ||
|
||||||
session_helper_report_credential_ui_visible_ ||
|
session_helper_report_credential_ui_visible_ ||
|
||||||
session_helper_report_secure_desktop_active_ ||
|
session_helper_report_secure_desktop_active_ ||
|
||||||
session_helper_report_unlock_ui_visible_ ||
|
session_helper_report_unlock_ui_visible_ ||
|
||||||
@@ -1392,6 +1447,7 @@ std::string CrossDeskServiceHost::ResolveInteractiveStageLocked() const {
|
|||||||
|
|
||||||
const bool service_host_credential_ui_visible =
|
const bool service_host_credential_ui_visible =
|
||||||
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
||||||
|
consent_ui_visible_,
|
||||||
input_desktop_available_,
|
input_desktop_available_,
|
||||||
secure_desktop_active_);
|
secure_desktop_active_);
|
||||||
return DetermineInteractiveStage(
|
return DetermineInteractiveStage(
|
||||||
@@ -1401,6 +1457,33 @@ std::string CrossDeskServiceHost::ResolveInteractiveStageLocked() const {
|
|||||||
session_helper_report_secure_desktop_active_ || secure_desktop_active_);
|
session_helper_report_secure_desktop_active_ || secure_desktop_active_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CrossDeskServiceHost::ResolveInteractiveDesktopLocked(
|
||||||
|
const std::string& interactive_stage) const {
|
||||||
|
if (interactive_stage == "lock-screen") {
|
||||||
|
return "Default";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session_helper_status_ok_ &&
|
||||||
|
session_helper_report_input_desktop_available_ &&
|
||||||
|
!session_helper_report_input_desktop_.empty() &&
|
||||||
|
(interactive_stage == "credential-ui" ||
|
||||||
|
session_helper_report_consent_ui_visible_)) {
|
||||||
|
return session_helper_report_input_desktop_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_desktop_available_ && !input_desktop_name_.empty() &&
|
||||||
|
(interactive_stage == "credential-ui" || consent_ui_visible_)) {
|
||||||
|
return input_desktop_name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactive_stage == "credential-ui" ||
|
||||||
|
interactive_stage == "secure-desktop") {
|
||||||
|
return "Winlogon";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring CrossDeskServiceHost::GetSessionHelperPath() const {
|
std::wstring CrossDeskServiceHost::GetSessionHelperPath() const {
|
||||||
std::wstring current_executable = GetCurrentExecutablePathW();
|
std::wstring current_executable = GetCurrentExecutablePathW();
|
||||||
if (current_executable.empty()) {
|
if (current_executable.empty()) {
|
||||||
@@ -1491,6 +1574,7 @@ void CrossDeskServiceHost::ReapSecureInputHelper() {
|
|||||||
secure_input_helper_exit_code_ = exit_code;
|
secure_input_helper_exit_code_ = exit_code;
|
||||||
secure_input_helper_started_at_tick_ = 0;
|
secure_input_helper_started_at_tick_ = 0;
|
||||||
secure_input_helper_interactive_stage_.clear();
|
secure_input_helper_interactive_stage_.clear();
|
||||||
|
secure_input_helper_interactive_desktop_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_handle != nullptr) {
|
if (process_handle != nullptr) {
|
||||||
@@ -1550,6 +1634,7 @@ void CrossDeskServiceHost::StopSecureInputHelper() {
|
|||||||
secure_input_helper_process_id_ = 0;
|
secure_input_helper_process_id_ = 0;
|
||||||
secure_input_helper_started_at_tick_ = 0;
|
secure_input_helper_started_at_tick_ = 0;
|
||||||
secure_input_helper_interactive_stage_.clear();
|
secure_input_helper_interactive_stage_.clear();
|
||||||
|
secure_input_helper_interactive_desktop_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop_event_handle != nullptr) {
|
if (stop_event_handle != nullptr) {
|
||||||
@@ -1678,7 +1763,8 @@ bool CrossDeskServiceHost::LaunchSessionHelper(DWORD session_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CrossDeskServiceHost::LaunchSecureInputHelper(
|
bool CrossDeskServiceHost::LaunchSecureInputHelper(
|
||||||
DWORD session_id, const std::string& interactive_stage) {
|
DWORD session_id, const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
std::wstring helper_path = GetSecureInputHelperPath();
|
std::wstring helper_path = GetSecureInputHelperPath();
|
||||||
if (helper_path.empty() || !std::filesystem::exists(helper_path)) {
|
if (helper_path.empty() || !std::filesystem::exists(helper_path)) {
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
@@ -1713,7 +1799,7 @@ bool CrossDeskServiceHost::LaunchSecureInputHelper(
|
|||||||
STARTUPINFOW startup_info{};
|
STARTUPINFOW startup_info{};
|
||||||
startup_info.cb = sizeof(startup_info);
|
startup_info.cb = sizeof(startup_info);
|
||||||
std::wstring secure_input_helper_desktop =
|
std::wstring secure_input_helper_desktop =
|
||||||
SecureInputHelperDesktopForStage(interactive_stage);
|
SecureInputHelperDesktopForStage(interactive_stage, interactive_desktop);
|
||||||
startup_info.lpDesktop =
|
startup_info.lpDesktop =
|
||||||
const_cast<LPWSTR>(secure_input_helper_desktop.c_str());
|
const_cast<LPWSTR>(secure_input_helper_desktop.c_str());
|
||||||
PROCESS_INFORMATION process_info{};
|
PROCESS_INFORMATION process_info{};
|
||||||
@@ -1765,13 +1851,14 @@ bool CrossDeskServiceHost::LaunchSecureInputHelper(
|
|||||||
secure_input_helper_running_ = true;
|
secure_input_helper_running_ = true;
|
||||||
secure_input_helper_started_at_tick_ = GetTickCount64();
|
secure_input_helper_started_at_tick_ = GetTickCount64();
|
||||||
secure_input_helper_interactive_stage_ = interactive_stage;
|
secure_input_helper_interactive_stage_ = interactive_stage;
|
||||||
|
secure_input_helper_interactive_desktop_ = interactive_desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(
|
LOG_INFO(
|
||||||
"Secure input helper started: session_id={}, pid={}, stage='{}', "
|
"Secure input helper started: session_id={}, pid={}, stage='{}', "
|
||||||
"desktop='{}'",
|
"interactive_desktop='{}', desktop='{}'",
|
||||||
session_id, process_info.dwProcessId, interactive_stage,
|
session_id, process_info.dwProcessId, interactive_stage,
|
||||||
WideToUtf8(secure_input_helper_desktop));
|
interactive_desktop, WideToUtf8(secure_input_helper_desktop));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1860,6 +1947,8 @@ void CrossDeskServiceHost::RefreshSessionHelperReportedState() {
|
|||||||
json.value("lock_app_visible", false);
|
json.value("lock_app_visible", false);
|
||||||
session_helper_report_logon_ui_visible_ =
|
session_helper_report_logon_ui_visible_ =
|
||||||
json.value("logon_ui_visible", false);
|
json.value("logon_ui_visible", false);
|
||||||
|
session_helper_report_consent_ui_visible_ =
|
||||||
|
json.value("consent_ui_visible", false);
|
||||||
session_helper_report_secure_desktop_active_ =
|
session_helper_report_secure_desktop_active_ =
|
||||||
json.value("secure_desktop_active", false);
|
json.value("secure_desktop_active", false);
|
||||||
session_helper_report_credential_ui_visible_ =
|
session_helper_report_credential_ui_visible_ =
|
||||||
@@ -1885,6 +1974,7 @@ void CrossDeskServiceHost::RecordSessionEvent(DWORD event_type,
|
|||||||
process_session_id_ = process_session_id;
|
process_session_id_ = process_session_id;
|
||||||
}
|
}
|
||||||
logon_ui_visible_ = IsLogonUiRunningInSession(active_session_id_);
|
logon_ui_visible_ = IsLogonUiRunningInSession(active_session_id_);
|
||||||
|
consent_ui_visible_ = IsConsentUiRunningInSession(active_session_id_);
|
||||||
InputDesktopInfo desktop_info = GetInputDesktopInfo();
|
InputDesktopInfo desktop_info = GetInputDesktopInfo();
|
||||||
input_desktop_available_ = desktop_info.available;
|
input_desktop_available_ = desktop_info.available;
|
||||||
input_desktop_error_code_ = desktop_info.error_code;
|
input_desktop_error_code_ = desktop_info.error_code;
|
||||||
@@ -1911,7 +2001,7 @@ void CrossDeskServiceHost::RecordSessionEvent(DWORD event_type,
|
|||||||
LOG_INFO("Session event: type={}, session_id={}, active_session_id={}",
|
LOG_INFO("Session event: type={}, session_id={}, active_session_id={}",
|
||||||
SessionEventToString(event_type), session_id, active_session_id_);
|
SessionEventToString(event_type), session_id, active_session_id_);
|
||||||
EnsureSessionHelper();
|
EnsureSessionHelper();
|
||||||
if (!secure_desktop_active_ && !logon_ui_visible_) {
|
if (!secure_desktop_active_ && !logon_ui_visible_ && !consent_ui_visible_) {
|
||||||
StopSecureInputHelper();
|
StopSecureInputHelper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1955,10 +2045,13 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
bool launch_secure_input_helper = false;
|
bool launch_secure_input_helper = false;
|
||||||
DWORD secure_input_target_session_id = 0xFFFFFFFF;
|
DWORD secure_input_target_session_id = 0xFFFFFFFF;
|
||||||
std::string secure_input_interactive_stage;
|
std::string secure_input_interactive_stage;
|
||||||
|
std::string secure_input_interactive_desktop;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
secure_input_target_session_id = active_session_id_;
|
secure_input_target_session_id = active_session_id_;
|
||||||
secure_input_interactive_stage = ResolveInteractiveStageLocked();
|
secure_input_interactive_stage = ResolveInteractiveStageLocked();
|
||||||
|
secure_input_interactive_desktop =
|
||||||
|
ResolveInteractiveDesktopLocked(secure_input_interactive_stage);
|
||||||
keep_secure_input_helper =
|
keep_secure_input_helper =
|
||||||
ShouldKeepSecureInputHelperLocked(secure_input_target_session_id);
|
ShouldKeepSecureInputHelperLocked(secure_input_target_session_id);
|
||||||
launch_secure_input_helper =
|
launch_secure_input_helper =
|
||||||
@@ -1966,14 +2059,17 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
(!secure_input_helper_running_ ||
|
(!secure_input_helper_running_ ||
|
||||||
secure_input_helper_session_id_ != secure_input_target_session_id ||
|
secure_input_helper_session_id_ != secure_input_target_session_id ||
|
||||||
secure_input_helper_interactive_stage_ !=
|
secure_input_helper_interactive_stage_ !=
|
||||||
secure_input_interactive_stage);
|
secure_input_interactive_stage ||
|
||||||
|
secure_input_helper_interactive_desktop_ !=
|
||||||
|
secure_input_interactive_desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep_secure_input_helper) {
|
if (keep_secure_input_helper) {
|
||||||
if (launch_secure_input_helper) {
|
if (launch_secure_input_helper) {
|
||||||
StopSecureInputHelper();
|
StopSecureInputHelper();
|
||||||
LaunchSecureInputHelper(secure_input_target_session_id,
|
LaunchSecureInputHelper(secure_input_target_session_id,
|
||||||
secure_input_interactive_stage);
|
secure_input_interactive_stage,
|
||||||
|
secure_input_interactive_desktop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StopSecureInputHelper();
|
StopSecureInputHelper();
|
||||||
@@ -1999,6 +2095,8 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
EscapeJsonString(secure_input_helper_last_error_);
|
EscapeJsonString(secure_input_helper_last_error_);
|
||||||
std::string secure_input_helper_interactive_stage =
|
std::string secure_input_helper_interactive_stage =
|
||||||
EscapeJsonString(secure_input_helper_interactive_stage_);
|
EscapeJsonString(secure_input_helper_interactive_stage_);
|
||||||
|
std::string secure_input_helper_interactive_desktop =
|
||||||
|
EscapeJsonString(secure_input_helper_interactive_desktop_);
|
||||||
bool interactive_state_ready = session_helper_status_ok_;
|
bool interactive_state_ready = session_helper_status_ok_;
|
||||||
const bool sas_secure_desktop_grace_active =
|
const bool sas_secure_desktop_grace_active =
|
||||||
IsSasSecureDesktopGraceActiveLocked();
|
IsSasSecureDesktopGraceActiveLocked();
|
||||||
@@ -2011,6 +2109,7 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
: false;
|
: false;
|
||||||
const bool service_host_credential_ui_visible =
|
const bool service_host_credential_ui_visible =
|
||||||
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
IsCredentialUiVisible(prelogin_, session_locked_, logon_ui_visible_,
|
||||||
|
consent_ui_visible_,
|
||||||
input_desktop_available_,
|
input_desktop_available_,
|
||||||
secure_desktop_active_);
|
secure_desktop_active_);
|
||||||
bool credential_ui_visible =
|
bool credential_ui_visible =
|
||||||
@@ -2062,6 +2161,8 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
<< ",\"unlock_ui_visible\":" << (unlock_ui_visible ? "true" : "false")
|
<< ",\"unlock_ui_visible\":" << (unlock_ui_visible ? "true" : "false")
|
||||||
<< ",\"credential_ui_visible\":"
|
<< ",\"credential_ui_visible\":"
|
||||||
<< (credential_ui_visible ? "true" : "false")
|
<< (credential_ui_visible ? "true" : "false")
|
||||||
|
<< ",\"consent_ui_visible\":"
|
||||||
|
<< (consent_ui_visible_ ? "true" : "false")
|
||||||
<< ",\"password_box_visible\":"
|
<< ",\"password_box_visible\":"
|
||||||
<< (credential_ui_visible ? "true" : "false")
|
<< (credential_ui_visible ? "true" : "false")
|
||||||
<< ",\"logon_ui_visible\":" << (logon_ui_visible_ ? "true" : "false")
|
<< ",\"logon_ui_visible\":" << (logon_ui_visible_ ? "true" : "false")
|
||||||
@@ -2104,6 +2205,8 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
<< (session_helper_report_lock_app_visible_ ? "true" : "false")
|
<< (session_helper_report_lock_app_visible_ ? "true" : "false")
|
||||||
<< ",\"session_helper_report_logon_ui_visible\":"
|
<< ",\"session_helper_report_logon_ui_visible\":"
|
||||||
<< (session_helper_report_logon_ui_visible_ ? "true" : "false")
|
<< (session_helper_report_logon_ui_visible_ ? "true" : "false")
|
||||||
|
<< ",\"session_helper_report_consent_ui_visible\":"
|
||||||
|
<< (session_helper_report_consent_ui_visible_ ? "true" : "false")
|
||||||
<< ",\"session_helper_report_secure_desktop_active\":"
|
<< ",\"session_helper_report_secure_desktop_active\":"
|
||||||
<< (session_helper_report_secure_desktop_active_ ? "true" : "false")
|
<< (session_helper_report_secure_desktop_active_ ? "true" : "false")
|
||||||
<< ",\"session_helper_report_credential_ui_visible\":"
|
<< ",\"session_helper_report_credential_ui_visible\":"
|
||||||
@@ -2134,6 +2237,8 @@ std::string CrossDeskServiceHost::BuildStatusResponse() {
|
|||||||
<< secure_input_helper_last_error_code_
|
<< secure_input_helper_last_error_code_
|
||||||
<< ",\"secure_input_helper_stage\":\""
|
<< ",\"secure_input_helper_stage\":\""
|
||||||
<< secure_input_helper_interactive_stage << "\""
|
<< secure_input_helper_interactive_stage << "\""
|
||||||
|
<< ",\"secure_input_helper_desktop\":\""
|
||||||
|
<< secure_input_helper_interactive_desktop << "\""
|
||||||
<< ",\"secure_input_helper_uptime_ms\":"
|
<< ",\"secure_input_helper_uptime_ms\":"
|
||||||
<< (secure_input_helper_started_at_tick_ >= started_at_tick_
|
<< (secure_input_helper_started_at_tick_ >= started_at_tick_
|
||||||
? (GetTickCount64() - secure_input_helper_started_at_tick_)
|
? (GetTickCount64() - secure_input_helper_started_at_tick_)
|
||||||
@@ -2190,12 +2295,15 @@ std::string CrossDeskServiceHost::SendSecureDesktopKeyboardInput(
|
|||||||
bool helper_running = false;
|
bool helper_running = false;
|
||||||
bool can_inject = false;
|
bool can_inject = false;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
target_session_id = active_session_id_;
|
target_session_id = active_session_id_;
|
||||||
interactive_stage = ResolveInteractiveStageLocked();
|
interactive_stage = ResolveInteractiveStageLocked();
|
||||||
|
interactive_desktop = ResolveInteractiveDesktopLocked(interactive_stage);
|
||||||
const bool helper_stage_matches =
|
const bool helper_stage_matches =
|
||||||
secure_input_helper_interactive_stage_ == interactive_stage;
|
secure_input_helper_interactive_stage_ == interactive_stage &&
|
||||||
|
secure_input_helper_interactive_desktop_ == interactive_desktop;
|
||||||
helper_running = secure_input_helper_running_ &&
|
helper_running = secure_input_helper_running_ &&
|
||||||
secure_input_helper_session_id_ == target_session_id &&
|
secure_input_helper_session_id_ == target_session_id &&
|
||||||
helper_stage_matches;
|
helper_stage_matches;
|
||||||
@@ -2211,7 +2319,8 @@ std::string CrossDeskServiceHost::SendSecureDesktopKeyboardInput(
|
|||||||
|
|
||||||
if (!helper_running) {
|
if (!helper_running) {
|
||||||
StopSecureInputHelper();
|
StopSecureInputHelper();
|
||||||
if (!LaunchSecureInputHelper(target_session_id, interactive_stage)) {
|
if (!LaunchSecureInputHelper(target_session_id, interactive_stage,
|
||||||
|
interactive_desktop)) {
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
return BuildErrorJson(secure_input_helper_last_error_.c_str(),
|
return BuildErrorJson(secure_input_helper_last_error_.c_str(),
|
||||||
secure_input_helper_last_error_code_);
|
secure_input_helper_last_error_code_);
|
||||||
@@ -2221,7 +2330,8 @@ std::string CrossDeskServiceHost::SendSecureDesktopKeyboardInput(
|
|||||||
return QueryNamedPipeMessage(
|
return QueryNamedPipeMessage(
|
||||||
GetCrossDeskSecureInputHelperPipeName(target_session_id),
|
GetCrossDeskSecureInputHelperPipeName(target_session_id),
|
||||||
BuildSecureInputHelperKeyboardCommand(key_code, is_down, scan_code,
|
BuildSecureInputHelperKeyboardCommand(key_code, is_down, scan_code,
|
||||||
extended, interactive_stage),
|
extended, interactive_stage,
|
||||||
|
interactive_desktop),
|
||||||
1000);
|
1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2237,12 +2347,15 @@ std::string CrossDeskServiceHost::SendSecureDesktopMouseInput(int x, int y,
|
|||||||
bool helper_running = false;
|
bool helper_running = false;
|
||||||
bool can_inject = false;
|
bool can_inject = false;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
target_session_id = active_session_id_;
|
target_session_id = active_session_id_;
|
||||||
interactive_stage = ResolveInteractiveStageLocked();
|
interactive_stage = ResolveInteractiveStageLocked();
|
||||||
|
interactive_desktop = ResolveInteractiveDesktopLocked(interactive_stage);
|
||||||
const bool helper_stage_matches =
|
const bool helper_stage_matches =
|
||||||
secure_input_helper_interactive_stage_ == interactive_stage;
|
secure_input_helper_interactive_stage_ == interactive_stage &&
|
||||||
|
secure_input_helper_interactive_desktop_ == interactive_desktop;
|
||||||
helper_running = secure_input_helper_running_ &&
|
helper_running = secure_input_helper_running_ &&
|
||||||
secure_input_helper_session_id_ == target_session_id &&
|
secure_input_helper_session_id_ == target_session_id &&
|
||||||
helper_stage_matches;
|
helper_stage_matches;
|
||||||
@@ -2258,7 +2371,8 @@ std::string CrossDeskServiceHost::SendSecureDesktopMouseInput(int x, int y,
|
|||||||
|
|
||||||
if (!helper_running) {
|
if (!helper_running) {
|
||||||
StopSecureInputHelper();
|
StopSecureInputHelper();
|
||||||
if (!LaunchSecureInputHelper(target_session_id, interactive_stage)) {
|
if (!LaunchSecureInputHelper(target_session_id, interactive_stage,
|
||||||
|
interactive_desktop)) {
|
||||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||||
return BuildErrorJson(secure_input_helper_last_error_.c_str(),
|
return BuildErrorJson(secure_input_helper_last_error_.c_str(),
|
||||||
secure_input_helper_last_error_code_);
|
secure_input_helper_last_error_code_);
|
||||||
@@ -2267,7 +2381,8 @@ std::string CrossDeskServiceHost::SendSecureDesktopMouseInput(int x, int y,
|
|||||||
|
|
||||||
return QueryNamedPipeMessage(
|
return QueryNamedPipeMessage(
|
||||||
GetCrossDeskSecureInputHelperPipeName(target_session_id),
|
GetCrossDeskSecureInputHelperPipeName(target_session_id),
|
||||||
BuildSecureInputHelperMouseCommand(x, y, wheel, flag, interactive_stage),
|
BuildSecureInputHelperMouseCommand(x, y, wheel, flag, interactive_stage,
|
||||||
|
interactive_desktop),
|
||||||
1000);
|
1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ class CrossDeskServiceHost {
|
|||||||
void ReapSecureInputHelper();
|
void ReapSecureInputHelper();
|
||||||
void StopSecureInputHelper();
|
void StopSecureInputHelper();
|
||||||
bool LaunchSecureInputHelper(DWORD session_id,
|
bool LaunchSecureInputHelper(DWORD session_id,
|
||||||
const std::string& interactive_stage);
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop);
|
||||||
std::wstring GetSessionHelperPath() const;
|
std::wstring GetSessionHelperPath() const;
|
||||||
std::wstring GetSessionHelperStopEventName(DWORD session_id) const;
|
std::wstring GetSessionHelperStopEventName(DWORD session_id) const;
|
||||||
std::wstring GetSecureInputHelperPath() const;
|
std::wstring GetSecureInputHelperPath() const;
|
||||||
@@ -60,6 +61,8 @@ class CrossDeskServiceHost {
|
|||||||
bool IsSasSecureDesktopGraceActiveLocked() const;
|
bool IsSasSecureDesktopGraceActiveLocked() const;
|
||||||
bool ShouldKeepSecureInputHelperLocked(DWORD target_session_id) const;
|
bool ShouldKeepSecureInputHelperLocked(DWORD target_session_id) const;
|
||||||
std::string ResolveInteractiveStageLocked() const;
|
std::string ResolveInteractiveStageLocked() const;
|
||||||
|
std::string ResolveInteractiveDesktopLocked(
|
||||||
|
const std::string& interactive_stage) const;
|
||||||
void RefreshSessionHelperReportedState();
|
void RefreshSessionHelperReportedState();
|
||||||
void RecordSessionEvent(DWORD event_type, DWORD session_id);
|
void RecordSessionEvent(DWORD event_type, DWORD session_id);
|
||||||
std::string HandleIpcCommand(const std::string& command);
|
std::string HandleIpcCommand(const std::string& command);
|
||||||
@@ -108,6 +111,7 @@ class CrossDeskServiceHost {
|
|||||||
ULONGLONG sas_secure_desktop_until_tick_ = 0;
|
ULONGLONG sas_secure_desktop_until_tick_ = 0;
|
||||||
bool session_locked_ = false;
|
bool session_locked_ = false;
|
||||||
bool logon_ui_visible_ = false;
|
bool logon_ui_visible_ = false;
|
||||||
|
bool consent_ui_visible_ = false;
|
||||||
bool prelogin_ = false;
|
bool prelogin_ = false;
|
||||||
bool secure_desktop_active_ = false;
|
bool secure_desktop_active_ = false;
|
||||||
bool input_desktop_available_ = false;
|
bool input_desktop_available_ = false;
|
||||||
@@ -117,6 +121,7 @@ class CrossDeskServiceHost {
|
|||||||
bool session_helper_report_input_desktop_available_ = false;
|
bool session_helper_report_input_desktop_available_ = false;
|
||||||
bool session_helper_report_lock_app_visible_ = false;
|
bool session_helper_report_lock_app_visible_ = false;
|
||||||
bool session_helper_report_logon_ui_visible_ = false;
|
bool session_helper_report_logon_ui_visible_ = false;
|
||||||
|
bool session_helper_report_consent_ui_visible_ = false;
|
||||||
bool session_helper_report_secure_desktop_active_ = false;
|
bool session_helper_report_secure_desktop_active_ = false;
|
||||||
bool session_helper_report_credential_ui_visible_ = false;
|
bool session_helper_report_credential_ui_visible_ = false;
|
||||||
bool session_helper_report_unlock_ui_visible_ = false;
|
bool session_helper_report_unlock_ui_visible_ = false;
|
||||||
@@ -137,6 +142,7 @@ class CrossDeskServiceHost {
|
|||||||
std::string session_helper_report_interactive_stage_;
|
std::string session_helper_report_interactive_stage_;
|
||||||
std::string secure_input_helper_last_error_;
|
std::string secure_input_helper_last_error_;
|
||||||
std::string secure_input_helper_interactive_stage_;
|
std::string secure_input_helper_interactive_stage_;
|
||||||
|
std::string secure_input_helper_interactive_desktop_;
|
||||||
|
|
||||||
static CrossDeskServiceHost* instance_;
|
static CrossDeskServiceHost* instance_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ struct HelperState {
|
|||||||
std::string input_desktop_name;
|
std::string input_desktop_name;
|
||||||
bool lock_app_visible = false;
|
bool lock_app_visible = false;
|
||||||
bool logon_ui_visible = false;
|
bool logon_ui_visible = false;
|
||||||
|
bool consent_ui_visible = false;
|
||||||
bool secure_desktop_active = false;
|
bool secure_desktop_active = false;
|
||||||
ULONGLONG started_at_tick = 0;
|
ULONGLONG started_at_tick = 0;
|
||||||
ULONGLONG last_update_tick = 0;
|
ULONGLONG last_update_tick = 0;
|
||||||
@@ -64,6 +65,7 @@ struct SecureCaptureRequest {
|
|||||||
bool show_cursor = true;
|
bool show_cursor = true;
|
||||||
int fps = 30;
|
int fps = 30;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SecureMouseRequest {
|
struct SecureMouseRequest {
|
||||||
@@ -72,6 +74,7 @@ struct SecureMouseRequest {
|
|||||||
int wheel = 0;
|
int wheel = 0;
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SecureCaptureBuffers {
|
struct SecureCaptureBuffers {
|
||||||
@@ -288,6 +291,10 @@ bool IsLogonUiRunningInCurrentSession(DWORD session_id) {
|
|||||||
return IsProcessRunningInCurrentSession(L"LogonUI.exe", session_id);
|
return IsProcessRunningInCurrentSession(L"LogonUI.exe", session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsConsentUiRunningInCurrentSession(DWORD session_id) {
|
||||||
|
return IsProcessRunningInCurrentSession(L"Consent.exe", session_id);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsLockAppRunningInCurrentSession(DWORD session_id) {
|
bool IsLockAppRunningInCurrentSession(DWORD session_id) {
|
||||||
return IsProcessRunningInCurrentSession(L"LockApp.exe", session_id);
|
return IsProcessRunningInCurrentSession(L"LockApp.exe", session_id);
|
||||||
}
|
}
|
||||||
@@ -341,10 +348,12 @@ const char* DetermineInteractiveStage(bool lock_app_visible,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsCredentialUiVisible(bool session_locked, bool logon_ui_running,
|
bool IsCredentialUiVisible(bool session_locked, bool logon_ui_running,
|
||||||
|
bool consent_ui_visible,
|
||||||
bool input_desktop_available,
|
bool input_desktop_available,
|
||||||
bool secure_desktop_active) {
|
bool secure_desktop_active) {
|
||||||
return (session_locked || secure_desktop_active) &&
|
return consent_ui_visible ||
|
||||||
(logon_ui_running || !input_desktop_available);
|
((session_locked || secure_desktop_active) &&
|
||||||
|
(logon_ui_running || !input_desktop_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BuildErrorJson(const char* error, DWORD error_code = 0) {
|
std::string BuildErrorJson(const char* error, DWORD error_code = 0) {
|
||||||
@@ -367,6 +376,10 @@ void UpdateHelperState(HelperState* helper_state) {
|
|||||||
IsLockAppRunningInCurrentSession(helper_state->session_id);
|
IsLockAppRunningInCurrentSession(helper_state->session_id);
|
||||||
bool logon_ui_visible =
|
bool logon_ui_visible =
|
||||||
IsLogonUiRunningInCurrentSession(helper_state->session_id);
|
IsLogonUiRunningInCurrentSession(helper_state->session_id);
|
||||||
|
bool consent_ui_visible =
|
||||||
|
IsConsentUiRunningInCurrentSession(helper_state->session_id);
|
||||||
|
const bool consent_on_input_desktop =
|
||||||
|
desktop_info.available && consent_ui_visible;
|
||||||
const bool input_desktop_is_winlogon =
|
const bool input_desktop_is_winlogon =
|
||||||
_stricmp(desktop_info.name.c_str(), "Winlogon") == 0;
|
_stricmp(desktop_info.name.c_str(), "Winlogon") == 0;
|
||||||
const bool inaccessible_secure_input_desktop =
|
const bool inaccessible_secure_input_desktop =
|
||||||
@@ -388,6 +401,8 @@ void UpdateHelperState(HelperState* helper_state) {
|
|||||||
helper_state->input_desktop_name = desktop_info.name;
|
helper_state->input_desktop_name = desktop_info.name;
|
||||||
helper_state->lock_app_visible = lock_app_visible;
|
helper_state->lock_app_visible = lock_app_visible;
|
||||||
helper_state->logon_ui_visible = logon_ui_visible;
|
helper_state->logon_ui_visible = logon_ui_visible;
|
||||||
|
helper_state->consent_ui_visible =
|
||||||
|
consent_on_input_desktop || consent_ui_visible;
|
||||||
helper_state->secure_desktop_active = secure_desktop_active;
|
helper_state->secure_desktop_active = secure_desktop_active;
|
||||||
helper_state->last_update_tick = GetTickCount64();
|
helper_state->last_update_tick = GetTickCount64();
|
||||||
}
|
}
|
||||||
@@ -401,6 +416,7 @@ std::string BuildHelperStatusResponse(HelperState* helper_state) {
|
|||||||
std::lock_guard<std::mutex> lock(helper_state->mutex);
|
std::lock_guard<std::mutex> lock(helper_state->mutex);
|
||||||
const bool credential_ui_visible = IsCredentialUiVisible(
|
const bool credential_ui_visible = IsCredentialUiVisible(
|
||||||
helper_state->session_locked, helper_state->logon_ui_visible,
|
helper_state->session_locked, helper_state->logon_ui_visible,
|
||||||
|
helper_state->consent_ui_visible,
|
||||||
helper_state->input_desktop_available,
|
helper_state->input_desktop_available,
|
||||||
helper_state->secure_desktop_active);
|
helper_state->secure_desktop_active);
|
||||||
const bool unlock_ui_visible =
|
const bool unlock_ui_visible =
|
||||||
@@ -414,6 +430,7 @@ std::string BuildHelperStatusResponse(HelperState* helper_state) {
|
|||||||
json["input_desktop"] = helper_state->input_desktop_name;
|
json["input_desktop"] = helper_state->input_desktop_name;
|
||||||
json["lock_app_visible"] = helper_state->lock_app_visible;
|
json["lock_app_visible"] = helper_state->lock_app_visible;
|
||||||
json["logon_ui_visible"] = helper_state->logon_ui_visible;
|
json["logon_ui_visible"] = helper_state->logon_ui_visible;
|
||||||
|
json["consent_ui_visible"] = helper_state->consent_ui_visible;
|
||||||
json["secure_desktop_active"] = helper_state->secure_desktop_active;
|
json["secure_desktop_active"] = helper_state->secure_desktop_active;
|
||||||
json["credential_ui_visible"] = credential_ui_visible;
|
json["credential_ui_visible"] = credential_ui_visible;
|
||||||
json["unlock_ui_visible"] = unlock_ui_visible;
|
json["unlock_ui_visible"] = unlock_ui_visible;
|
||||||
@@ -639,8 +656,12 @@ bool EnsureThreadInteractiveDesktop(HDESK* opened_desktop_out = nullptr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t* DesktopNameForInteractiveStage(
|
std::wstring DesktopNameForInteractiveStage(
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
|
if (!interactive_desktop.empty()) {
|
||||||
|
return Utf8ToWide(interactive_desktop);
|
||||||
|
}
|
||||||
if (interactive_stage == "credential-ui" ||
|
if (interactive_stage == "credential-ui" ||
|
||||||
interactive_stage == "secure-desktop") {
|
interactive_stage == "secure-desktop") {
|
||||||
return L"Winlogon";
|
return L"Winlogon";
|
||||||
@@ -648,7 +669,7 @@ const wchar_t* DesktopNameForInteractiveStage(
|
|||||||
if (interactive_stage == "lock-screen") {
|
if (interactive_stage == "lock-screen") {
|
||||||
return L"Default";
|
return L"Default";
|
||||||
}
|
}
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DesktopSwitchDetails {
|
struct DesktopSwitchDetails {
|
||||||
@@ -666,14 +687,14 @@ struct InputInjectionResult {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DesktopSwitchDetails BuildDesktopSwitchDetails(
|
DesktopSwitchDetails BuildDesktopSwitchDetails(
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
DesktopSwitchDetails details;
|
DesktopSwitchDetails details;
|
||||||
details.stage = interactive_stage;
|
details.stage = interactive_stage;
|
||||||
const wchar_t* desktop_name =
|
const std::wstring desktop_name =
|
||||||
DesktopNameForInteractiveStage(interactive_stage);
|
DesktopNameForInteractiveStage(interactive_stage, interactive_desktop);
|
||||||
details.target_desktop =
|
details.target_desktop =
|
||||||
desktop_name != nullptr ? WideToUtf8(std::wstring(desktop_name))
|
!desktop_name.empty() ? WideToUtf8(desktop_name) : "input-or-Winlogon";
|
||||||
: "input-or-Winlogon";
|
|
||||||
details.current_desktop = WideToUtf8(GetCurrentThreadDesktopNameW());
|
details.current_desktop = WideToUtf8(GetCurrentThreadDesktopNameW());
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
@@ -709,6 +730,7 @@ Json BuildInputFailureJson(const InputInjectionResult& result) {
|
|||||||
|
|
||||||
bool EnsureThreadInteractiveDesktopForStage(
|
bool EnsureThreadInteractiveDesktopForStage(
|
||||||
const std::string& interactive_stage,
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop,
|
||||||
HDESK* opened_desktop_out = nullptr,
|
HDESK* opened_desktop_out = nullptr,
|
||||||
DesktopSwitchDetails* switch_details = nullptr) {
|
DesktopSwitchDetails* switch_details = nullptr) {
|
||||||
if (opened_desktop_out != nullptr) {
|
if (opened_desktop_out != nullptr) {
|
||||||
@@ -716,15 +738,15 @@ bool EnsureThreadInteractiveDesktopForStage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DesktopSwitchDetails local_details =
|
DesktopSwitchDetails local_details =
|
||||||
BuildDesktopSwitchDetails(interactive_stage);
|
BuildDesktopSwitchDetails(interactive_stage, interactive_desktop);
|
||||||
if (switch_details != nullptr) {
|
if (switch_details != nullptr) {
|
||||||
*switch_details = local_details;
|
*switch_details = local_details;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t* desktop_name =
|
const std::wstring desktop_name =
|
||||||
DesktopNameForInteractiveStage(interactive_stage);
|
DesktopNameForInteractiveStage(interactive_stage, interactive_desktop);
|
||||||
if (desktop_name != nullptr) {
|
if (!desktop_name.empty()) {
|
||||||
if (EnsureThreadDesktop(desktop_name, opened_desktop_out)) {
|
if (EnsureThreadDesktop(desktop_name.c_str(), opened_desktop_out)) {
|
||||||
if (switch_details != nullptr) {
|
if (switch_details != nullptr) {
|
||||||
switch_details->current_desktop =
|
switch_details->current_desktop =
|
||||||
WideToUtf8(GetCurrentThreadDesktopNameW());
|
WideToUtf8(GetCurrentThreadDesktopNameW());
|
||||||
@@ -741,7 +763,7 @@ bool EnsureThreadInteractiveDesktopForStage(
|
|||||||
LOG_WARN(
|
LOG_WARN(
|
||||||
"Failed to switch secure input helper to stage desktop, stage='{}', "
|
"Failed to switch secure input helper to stage desktop, stage='{}', "
|
||||||
"desktop='{}', error={}, current='{}'",
|
"desktop='{}', error={}, current='{}'",
|
||||||
interactive_stage, WideToUtf8(std::wstring(desktop_name)),
|
interactive_stage, WideToUtf8(desktop_name),
|
||||||
error,
|
error,
|
||||||
WideToUtf8(GetCurrentThreadDesktopNameW()));
|
WideToUtf8(GetCurrentThreadDesktopNameW()));
|
||||||
SetLastError(error);
|
SetLastError(error);
|
||||||
@@ -790,10 +812,12 @@ bool PreferSideSpecificVkInjection(int key_code) {
|
|||||||
|
|
||||||
InputInjectionResult InjectKeyboardInput(
|
InputInjectionResult InjectKeyboardInput(
|
||||||
int key_code, bool is_down, uint32_t scan_code, bool extended,
|
int key_code, bool is_down, uint32_t scan_code, bool extended,
|
||||||
const std::string& interactive_stage) {
|
const std::string& interactive_stage,
|
||||||
|
const std::string& interactive_desktop) {
|
||||||
ScopedDesktopHandle desktop;
|
ScopedDesktopHandle desktop;
|
||||||
DesktopSwitchDetails desktop_switch;
|
DesktopSwitchDetails desktop_switch;
|
||||||
if (!EnsureThreadInteractiveDesktopForStage(interactive_stage,
|
if (!EnsureThreadInteractiveDesktopForStage(interactive_stage,
|
||||||
|
interactive_desktop,
|
||||||
&desktop.handle,
|
&desktop.handle,
|
||||||
&desktop_switch)) {
|
&desktop_switch)) {
|
||||||
const DWORD error = GetLastError();
|
const DWORD error = GetLastError();
|
||||||
@@ -851,11 +875,37 @@ InputInjectionResult InjectKeyboardInput(
|
|||||||
return BuildInputSuccess();
|
return BuildInputSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParseInteractionTail(const std::string& tail,
|
||||||
|
std::string* interactive_stage_out,
|
||||||
|
std::string* interactive_desktop_out) {
|
||||||
|
if (interactive_stage_out != nullptr) {
|
||||||
|
interactive_stage_out->clear();
|
||||||
|
}
|
||||||
|
if (interactive_desktop_out != nullptr) {
|
||||||
|
interactive_desktop_out->clear();
|
||||||
|
}
|
||||||
|
if (tail.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t separator = tail.find(':');
|
||||||
|
if (interactive_stage_out != nullptr) {
|
||||||
|
*interactive_stage_out = separator == std::string::npos
|
||||||
|
? tail
|
||||||
|
: tail.substr(0, separator);
|
||||||
|
}
|
||||||
|
if (separator != std::string::npos && interactive_desktop_out != nullptr) {
|
||||||
|
*interactive_desktop_out = tail.substr(separator + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ParseSecureInputKeyboardCommand(const std::string& command,
|
bool ParseSecureInputKeyboardCommand(const std::string& command,
|
||||||
int* key_code_out, bool* is_down_out,
|
int* key_code_out, bool* is_down_out,
|
||||||
uint32_t* scan_code_out,
|
uint32_t* scan_code_out,
|
||||||
bool* extended_out,
|
bool* extended_out,
|
||||||
std::string* interactive_stage_out =
|
std::string* interactive_stage_out =
|
||||||
|
nullptr,
|
||||||
|
std::string* interactive_desktop_out =
|
||||||
nullptr) {
|
nullptr) {
|
||||||
if (key_code_out == nullptr || is_down_out == nullptr ||
|
if (key_code_out == nullptr || is_down_out == nullptr ||
|
||||||
scan_code_out == nullptr || extended_out == nullptr) {
|
scan_code_out == nullptr || extended_out == nullptr) {
|
||||||
@@ -867,6 +917,9 @@ bool ParseSecureInputKeyboardCommand(const std::string& command,
|
|||||||
if (interactive_stage_out != nullptr) {
|
if (interactive_stage_out != nullptr) {
|
||||||
interactive_stage_out->clear();
|
interactive_stage_out->clear();
|
||||||
}
|
}
|
||||||
|
if (interactive_desktop_out != nullptr) {
|
||||||
|
interactive_desktop_out->clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (command.rfind(crossdesk::kCrossDeskSecureInputKeyboardCommandPrefix, 0) !=
|
if (command.rfind(crossdesk::kCrossDeskSecureInputKeyboardCommandPrefix, 0) !=
|
||||||
0) {
|
0) {
|
||||||
@@ -926,8 +979,9 @@ bool ParseSecureInputKeyboardCommand(const std::string& command,
|
|||||||
: command.substr(extended_separator + 1,
|
: command.substr(extended_separator + 1,
|
||||||
stage_separator - extended_separator - 1);
|
stage_separator - extended_separator - 1);
|
||||||
if (stage_separator != std::string::npos &&
|
if (stage_separator != std::string::npos &&
|
||||||
interactive_stage_out != nullptr) {
|
(interactive_stage_out != nullptr || interactive_desktop_out != nullptr)) {
|
||||||
*interactive_stage_out = command.substr(stage_separator + 1);
|
ParseInteractionTail(command.substr(stage_separator + 1),
|
||||||
|
interactive_stage_out, interactive_desktop_out);
|
||||||
}
|
}
|
||||||
if (extended_str == "1" || extended_str == "true") {
|
if (extended_str == "1" || extended_str == "true") {
|
||||||
*extended_out = true;
|
*extended_out = true;
|
||||||
@@ -951,6 +1005,7 @@ bool ParseSecureInputMouseCommand(const std::string& command,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
request_out->interactive_stage.clear();
|
request_out->interactive_stage.clear();
|
||||||
|
request_out->interactive_desktop.clear();
|
||||||
|
|
||||||
const size_t x_begin =
|
const size_t x_begin =
|
||||||
std::strlen(crossdesk::kCrossDeskSecureInputMouseCommandPrefix);
|
std::strlen(crossdesk::kCrossDeskSecureInputMouseCommandPrefix);
|
||||||
@@ -993,7 +1048,9 @@ bool ParseSecureInputMouseCommand(const std::string& command,
|
|||||||
? command.substr(flag_begin)
|
? command.substr(flag_begin)
|
||||||
: command.substr(flag_begin, stage_separator - flag_begin));
|
: command.substr(flag_begin, stage_separator - flag_begin));
|
||||||
if (stage_separator != std::string::npos) {
|
if (stage_separator != std::string::npos) {
|
||||||
request_out->interactive_stage = command.substr(stage_separator + 1);
|
ParseInteractionTail(command.substr(stage_separator + 1),
|
||||||
|
&request_out->interactive_stage,
|
||||||
|
&request_out->interactive_desktop);
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1013,6 +1070,7 @@ bool ParseSecureInputCaptureCommand(const std::string& command,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
request_out->interactive_stage.clear();
|
request_out->interactive_stage.clear();
|
||||||
|
request_out->interactive_desktop.clear();
|
||||||
|
|
||||||
const size_t values_begin =
|
const size_t values_begin =
|
||||||
std::strlen(crossdesk::kCrossDeskSecureInputCaptureCommandPrefix);
|
std::strlen(crossdesk::kCrossDeskSecureInputCaptureCommandPrefix);
|
||||||
@@ -1042,9 +1100,11 @@ bool ParseSecureInputCaptureCommand(const std::string& command,
|
|||||||
request_out->width = parsed_values[2] & ~1;
|
request_out->width = parsed_values[2] & ~1;
|
||||||
request_out->height = parsed_values[3] & ~1;
|
request_out->height = parsed_values[3] & ~1;
|
||||||
request_out->show_cursor = parsed_values[4] != 0;
|
request_out->show_cursor = parsed_values[4] != 0;
|
||||||
request_out->interactive_stage =
|
if (separator != std::string::npos) {
|
||||||
separator == std::string::npos ? std::string()
|
ParseInteractionTail(command.substr(token_begin),
|
||||||
: command.substr(token_begin);
|
&request_out->interactive_stage,
|
||||||
|
&request_out->interactive_desktop);
|
||||||
|
}
|
||||||
return request_out->width > 0 && request_out->height > 0;
|
return request_out->width > 0 && request_out->height > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,6 +1119,7 @@ bool ParseSecureInputCaptureStartCommand(const std::string& command,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
request_out->interactive_stage.clear();
|
request_out->interactive_stage.clear();
|
||||||
|
request_out->interactive_desktop.clear();
|
||||||
|
|
||||||
const size_t values_begin = std::strlen(
|
const size_t values_begin = std::strlen(
|
||||||
crossdesk::kCrossDeskSecureInputCaptureStartCommandPrefix);
|
crossdesk::kCrossDeskSecureInputCaptureStartCommandPrefix);
|
||||||
@@ -1089,9 +1150,11 @@ bool ParseSecureInputCaptureStartCommand(const std::string& command,
|
|||||||
request_out->height = parsed_values[3] & ~1;
|
request_out->height = parsed_values[3] & ~1;
|
||||||
request_out->show_cursor = parsed_values[4] != 0;
|
request_out->show_cursor = parsed_values[4] != 0;
|
||||||
request_out->fps = parsed_values[5] > 0 ? parsed_values[5] : 30;
|
request_out->fps = parsed_values[5] > 0 ? parsed_values[5] : 30;
|
||||||
request_out->interactive_stage =
|
if (separator != std::string::npos) {
|
||||||
separator == std::string::npos ? std::string()
|
ParseInteractionTail(command.substr(token_begin),
|
||||||
: command.substr(token_begin);
|
&request_out->interactive_stage,
|
||||||
|
&request_out->interactive_desktop);
|
||||||
|
}
|
||||||
return request_out->width > 0 && request_out->height > 0;
|
return request_out->width > 0 && request_out->height > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,6 +1192,7 @@ InputInjectionResult InjectMouseInput(const SecureMouseRequest& request) {
|
|||||||
ScopedDesktopHandle desktop;
|
ScopedDesktopHandle desktop;
|
||||||
DesktopSwitchDetails desktop_switch;
|
DesktopSwitchDetails desktop_switch;
|
||||||
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
||||||
|
request.interactive_desktop,
|
||||||
&desktop.handle,
|
&desktop.handle,
|
||||||
&desktop_switch)) {
|
&desktop_switch)) {
|
||||||
const DWORD error = GetLastError();
|
const DWORD error = GetLastError();
|
||||||
@@ -1205,6 +1269,7 @@ std::vector<uint8_t> CaptureSecureDesktopFrame(
|
|||||||
|
|
||||||
ScopedDesktopHandle desktop;
|
ScopedDesktopHandle desktop;
|
||||||
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
||||||
|
request.interactive_desktop,
|
||||||
&desktop.handle)) {
|
&desktop.handle)) {
|
||||||
const DWORD error = GetLastError();
|
const DWORD error = GetLastError();
|
||||||
return BuildTextResponseBytes(BuildErrorJson(
|
return BuildTextResponseBytes(BuildErrorJson(
|
||||||
@@ -1355,6 +1420,7 @@ void SecureDesktopSharedCaptureThread(
|
|||||||
|
|
||||||
ScopedDesktopHandle desktop;
|
ScopedDesktopHandle desktop;
|
||||||
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
if (!EnsureThreadInteractiveDesktopForStage(request.interactive_stage,
|
||||||
|
request.interactive_desktop,
|
||||||
&desktop.handle)) {
|
&desktop.handle)) {
|
||||||
LOG_ERROR("Secure shared capture desktop switch failed, error={}",
|
LOG_ERROR("Secure shared capture desktop switch failed, error={}",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
@@ -1607,11 +1673,13 @@ std::vector<uint8_t> HandleSecureInputHelperCommand(
|
|||||||
uint32_t scan_code = 0;
|
uint32_t scan_code = 0;
|
||||||
bool extended = false;
|
bool extended = false;
|
||||||
std::string interactive_stage;
|
std::string interactive_stage;
|
||||||
|
std::string interactive_desktop;
|
||||||
if (ParseSecureInputKeyboardCommand(command, &key_code, &is_down, &scan_code,
|
if (ParseSecureInputKeyboardCommand(command, &key_code, &is_down, &scan_code,
|
||||||
&extended, &interactive_stage)) {
|
&extended, &interactive_stage,
|
||||||
|
&interactive_desktop)) {
|
||||||
const InputInjectionResult inject_result =
|
const InputInjectionResult inject_result =
|
||||||
InjectKeyboardInput(key_code, is_down, scan_code, extended,
|
InjectKeyboardInput(key_code, is_down, scan_code, extended,
|
||||||
interactive_stage);
|
interactive_stage, interactive_desktop);
|
||||||
if (!inject_result.ok) {
|
if (!inject_result.ok) {
|
||||||
LOG_WARN(
|
LOG_WARN(
|
||||||
"Secure input helper input failed for key_code={}, is_down={}, "
|
"Secure input helper input failed for key_code={}, is_down={}, "
|
||||||
@@ -1631,6 +1699,7 @@ std::vector<uint8_t> HandleSecureInputHelperCommand(
|
|||||||
json["scan_code"] = scan_code;
|
json["scan_code"] = scan_code;
|
||||||
json["extended"] = extended;
|
json["extended"] = extended;
|
||||||
json["stage"] = interactive_stage;
|
json["stage"] = interactive_stage;
|
||||||
|
json["interactive_desktop"] = interactive_desktop;
|
||||||
json["desktop"] = WideToUtf8(GetCurrentThreadDesktopNameW());
|
json["desktop"] = WideToUtf8(GetCurrentThreadDesktopNameW());
|
||||||
return BuildTextResponseBytes(json.dump());
|
return BuildTextResponseBytes(json.dump());
|
||||||
}
|
}
|
||||||
@@ -1658,6 +1727,7 @@ std::vector<uint8_t> HandleSecureInputHelperCommand(
|
|||||||
json["wheel"] = mouse_request.wheel;
|
json["wheel"] = mouse_request.wheel;
|
||||||
json["flag"] = mouse_request.flag;
|
json["flag"] = mouse_request.flag;
|
||||||
json["stage"] = mouse_request.interactive_stage;
|
json["stage"] = mouse_request.interactive_stage;
|
||||||
|
json["interactive_desktop"] = mouse_request.interactive_desktop;
|
||||||
json["desktop"] = WideToUtf8(GetCurrentThreadDesktopNameW());
|
json["desktop"] = WideToUtf8(GetCurrentThreadDesktopNameW());
|
||||||
return BuildTextResponseBytes(json.dump());
|
return BuildTextResponseBytes(json.dump());
|
||||||
}
|
}
|
||||||
@@ -1887,6 +1957,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::string last_desktop_name;
|
std::string last_desktop_name;
|
||||||
bool last_lock_app = false;
|
bool last_lock_app = false;
|
||||||
bool last_logon_ui = false;
|
bool last_logon_ui = false;
|
||||||
|
bool last_consent_ui = false;
|
||||||
bool last_secure_desktop = false;
|
bool last_secure_desktop = false;
|
||||||
bool last_session_locked = false;
|
bool last_session_locked = false;
|
||||||
std::string last_stage;
|
std::string last_stage;
|
||||||
@@ -1898,6 +1969,7 @@ int main(int argc, char* argv[]) {
|
|||||||
bool input_desktop_available = false;
|
bool input_desktop_available = false;
|
||||||
bool lock_app_visible = false;
|
bool lock_app_visible = false;
|
||||||
bool logon_ui_running = false;
|
bool logon_ui_running = false;
|
||||||
|
bool consent_ui_visible = false;
|
||||||
bool secure_desktop_active = false;
|
bool secure_desktop_active = false;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(helper_state.mutex);
|
std::lock_guard<std::mutex> lock(helper_state.mutex);
|
||||||
@@ -1906,10 +1978,12 @@ int main(int argc, char* argv[]) {
|
|||||||
input_desktop_available = helper_state.input_desktop_available;
|
input_desktop_available = helper_state.input_desktop_available;
|
||||||
lock_app_visible = helper_state.lock_app_visible;
|
lock_app_visible = helper_state.lock_app_visible;
|
||||||
logon_ui_running = helper_state.logon_ui_visible;
|
logon_ui_running = helper_state.logon_ui_visible;
|
||||||
|
consent_ui_visible = helper_state.consent_ui_visible;
|
||||||
secure_desktop_active = helper_state.secure_desktop_active;
|
secure_desktop_active = helper_state.secure_desktop_active;
|
||||||
}
|
}
|
||||||
const bool credential_ui_visible =
|
const bool credential_ui_visible =
|
||||||
IsCredentialUiVisible(session_locked, logon_ui_running,
|
IsCredentialUiVisible(session_locked, logon_ui_running,
|
||||||
|
consent_ui_visible,
|
||||||
input_desktop_available,
|
input_desktop_available,
|
||||||
secure_desktop_active);
|
secure_desktop_active);
|
||||||
std::string stage = DetermineInteractiveStage(
|
std::string stage = DetermineInteractiveStage(
|
||||||
@@ -1919,17 +1993,19 @@ int main(int argc, char* argv[]) {
|
|||||||
session_locked != last_session_locked ||
|
session_locked != last_session_locked ||
|
||||||
lock_app_visible != last_lock_app ||
|
lock_app_visible != last_lock_app ||
|
||||||
logon_ui_running != last_logon_ui ||
|
logon_ui_running != last_logon_ui ||
|
||||||
|
consent_ui_visible != last_consent_ui ||
|
||||||
secure_desktop_active != last_secure_desktop || stage != last_stage) {
|
secure_desktop_active != last_secure_desktop || stage != last_stage) {
|
||||||
LOG_INFO(
|
LOG_INFO(
|
||||||
"Session helper state: session_id={}, input_desktop='{}', "
|
"Session helper state: session_id={}, input_desktop='{}', "
|
||||||
"session_locked={}, lock_app_visible={}, logon_ui_running={}, "
|
"session_locked={}, lock_app_visible={}, logon_ui_running={}, "
|
||||||
"secure_desktop_active={}, stage={}",
|
"consent_ui_visible={}, secure_desktop_active={}, stage={}",
|
||||||
current_session_id, desktop_name, session_locked, lock_app_visible,
|
current_session_id, desktop_name, session_locked, lock_app_visible,
|
||||||
logon_ui_running, secure_desktop_active, stage);
|
logon_ui_running, consent_ui_visible, secure_desktop_active, stage);
|
||||||
last_desktop_name = desktop_name;
|
last_desktop_name = desktop_name;
|
||||||
last_session_locked = session_locked;
|
last_session_locked = session_locked;
|
||||||
last_lock_app = lock_app_visible;
|
last_lock_app = lock_app_visible;
|
||||||
last_logon_ui = logon_ui_running;
|
last_logon_ui = logon_ui_running;
|
||||||
|
last_consent_ui = consent_ui_visible;
|
||||||
last_secure_desktop = secure_desktop_active;
|
last_secure_desktop = secure_desktop_active;
|
||||||
last_stage = stage;
|
last_stage = stage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ int main() {
|
|||||||
ok &= ExpectContains("targets.lua", targets,
|
ok &= ExpectContains("targets.lua", targets,
|
||||||
"target(\"crossdesk_session_helper\")");
|
"target(\"crossdesk_session_helper\")");
|
||||||
ok &= ExpectContains("targets.lua", targets,
|
ok &= ExpectContains("targets.lua", targets,
|
||||||
"add_files(\"scripts/windows/crossdesk.rc\")");
|
"add_files(crossdesk_windows_resource)");
|
||||||
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
"EnablePerMonitorDpiAwareness");
|
"EnablePerMonitorDpiAwareness");
|
||||||
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
@@ -105,11 +105,33 @@ int main() {
|
|||||||
"const std::string& interactive_stage");
|
"const std::string& interactive_stage");
|
||||||
ok &= ExpectContains("service_host.h", service_host_h,
|
ok &= ExpectContains("service_host.h", service_host_h,
|
||||||
"bool LaunchSecureInputHelper(DWORD session_id,\n"
|
"bool LaunchSecureInputHelper(DWORD session_id,\n"
|
||||||
" const std::string& interactive_stage)");
|
" const std::string& interactive_stage,\n"
|
||||||
|
" const std::string& interactive_desktop)");
|
||||||
ok &= ExpectContains("service_host.h", service_host_h,
|
ok &= ExpectContains("service_host.h", service_host_h,
|
||||||
"std::string secure_input_helper_interactive_stage_");
|
"std::string secure_input_helper_interactive_stage_");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
"SecureInputHelperDesktopForStage");
|
"SecureInputHelperDesktopForStage");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"IsConsentUiRunningInSession");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"L\"Consent.exe\"");
|
||||||
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
|
"IsConsentUiRunningInCurrentSession");
|
||||||
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
|
"L\"Consent.exe\"");
|
||||||
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
|
"desktop_info.available && consent_ui_visible");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"session_helper_report_input_desktop_available_ &&");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"session_helper_report_consent_ui_visible_");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"secure_input_helper_interactive_desktop_");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"SecureInputHelperDesktopForStage("
|
||||||
|
"interactive_stage, interactive_desktop)");
|
||||||
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
|
"return L\"winsta0\\\\\" + interactive_desktop_w");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
"return L\"winsta0\\\\Winlogon\"");
|
"return L\"winsta0\\\\Winlogon\"");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
@@ -121,7 +143,8 @@ int main() {
|
|||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
"secure_input_helper_interactive_stage_.clear()");
|
"secure_input_helper_interactive_stage_.clear()");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
"LaunchSecureInputHelper(target_session_id, interactive_stage)");
|
"LaunchSecureInputHelper(target_session_id, interactive_stage,\n"
|
||||||
|
" interactive_desktop)");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
"\\\"secure_input_helper_stage\\\":\\\"");
|
"\\\"secure_input_helper_stage\\\":\\\"");
|
||||||
ok &= ExpectContains("service_host.cpp", service_host,
|
ok &= ExpectContains("service_host.cpp", service_host,
|
||||||
@@ -189,10 +212,11 @@ int main() {
|
|||||||
"json[\"stage\"]");
|
"json[\"stage\"]");
|
||||||
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
"ParseSecureInputKeyboardCommand(command, &key_code, &is_down, &scan_code,\n"
|
"ParseSecureInputKeyboardCommand(command, &key_code, &is_down, &scan_code,\n"
|
||||||
" &extended, &interactive_stage)");
|
" &extended, &interactive_stage,\n"
|
||||||
|
" &interactive_desktop)");
|
||||||
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
"InjectKeyboardInput(key_code, is_down, scan_code, extended,\n"
|
"InjectKeyboardInput(key_code, is_down, scan_code, extended,\n"
|
||||||
" interactive_stage)");
|
" interactive_stage, interactive_desktop)");
|
||||||
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectContains("session_helper_main.cpp", session_helper,
|
||||||
"InjectMouseInput(mouse_request)");
|
"InjectMouseInput(mouse_request)");
|
||||||
ok &= ExpectNotContains("session_helper_main.cpp", session_helper,
|
ok &= ExpectNotContains("session_helper_main.cpp", session_helper,
|
||||||
|
|||||||
Reference in New Issue
Block a user