mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-08-01 14:30:26 +08:00
[feat] add Windows secure desktop remote unlock support for locked sessions, refs #77
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
#ifndef _CROSSDESK_INTERACTIVE_STATE_H_
|
||||
#define _CROSSDESK_INTERACTIVE_STATE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline bool IsSecureDesktopInteractionRequired(
|
||||
const std::string& interactive_stage) {
|
||||
return interactive_stage == "credential-ui" ||
|
||||
interactive_stage == "secure-desktop";
|
||||
}
|
||||
|
||||
inline bool ShouldNormalizeUnlockToUserDesktop(
|
||||
bool interactive_lock_screen_visible,
|
||||
const std::string& interactive_stage, bool session_locked,
|
||||
bool interactive_logon_ui_visible, bool interactive_secure_desktop_active,
|
||||
bool credential_ui_visible, bool password_box_visible,
|
||||
bool unlock_ui_visible, const std::string& last_session_event) {
|
||||
if (!interactive_lock_screen_visible && interactive_stage != "lock-screen") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (session_locked || interactive_logon_ui_visible ||
|
||||
interactive_secure_desktop_active || credential_ui_visible ||
|
||||
password_box_visible || unlock_ui_visible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return last_session_event != "session-lock";
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "service_host.h"
|
||||
|
||||
namespace {
|
||||
|
||||
std::wstring GetExecutablePath() {
|
||||
wchar_t path[MAX_PATH] = {0};
|
||||
DWORD length = GetModuleFileNameW(nullptr, path, MAX_PATH);
|
||||
if (length == 0 || length >= MAX_PATH) {
|
||||
return L"";
|
||||
}
|
||||
return std::wstring(path, length);
|
||||
}
|
||||
|
||||
void PrintUsage() {
|
||||
std::cout << "CrossDesk Windows service skeleton\n"
|
||||
<< " --service Run under the Windows Service Control Manager\n"
|
||||
<< " --console Run the service loop in console mode\n"
|
||||
<< " --install Install the service for the current executable\n"
|
||||
<< " --uninstall Remove the installed service\n"
|
||||
<< " --start Start the installed service\n"
|
||||
<< " --stop Stop the installed service\n"
|
||||
<< " --sas Ask the service to send Secure Attention Sequence\n"
|
||||
<< " --ping Ping the running service over named pipe IPC\n"
|
||||
<< " --status Query runtime status over named pipe IPC\n";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
crossdesk::CrossDeskServiceHost host;
|
||||
|
||||
if (argc <= 1) {
|
||||
PrintUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string command = argv[1];
|
||||
if (command == "--service") {
|
||||
return host.RunAsService();
|
||||
}
|
||||
if (command == "--console") {
|
||||
return host.RunInConsole();
|
||||
}
|
||||
if (command == "--install") {
|
||||
std::wstring executable_path = GetExecutablePath();
|
||||
bool success = !executable_path.empty() &&
|
||||
crossdesk::InstallCrossDeskService(executable_path);
|
||||
std::cout << (success ? "install ok" : "install failed") << std::endl;
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
if (command == "--uninstall") {
|
||||
bool success = crossdesk::UninstallCrossDeskService();
|
||||
std::cout << (success ? "uninstall ok" : "uninstall failed")
|
||||
<< std::endl;
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
if (command == "--start") {
|
||||
bool success = crossdesk::StartCrossDeskService();
|
||||
std::cout << (success ? "start ok" : "start failed") << std::endl;
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
if (command == "--stop") {
|
||||
bool success = crossdesk::StopCrossDeskService();
|
||||
std::cout << (success ? "stop ok" : "stop failed") << std::endl;
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
if (command == "--sas") {
|
||||
std::cout << crossdesk::QueryCrossDeskService("sas") << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (command == "--ping") {
|
||||
std::cout << crossdesk::QueryCrossDeskService("ping") << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (command == "--status") {
|
||||
std::cout << crossdesk::QueryCrossDeskService("status") << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintUsage();
|
||||
return 1;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
#ifndef _CROSSDESK_SERVICE_HOST_H_
|
||||
#define _CROSSDESK_SERVICE_HOST_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline constexpr wchar_t kCrossDeskServiceName[] = L"CrossDeskService";
|
||||
inline constexpr wchar_t kCrossDeskServiceDisplayName[] =
|
||||
L"CrossDesk Service";
|
||||
inline constexpr wchar_t kCrossDeskServicePipeName[] =
|
||||
L"\\\\.\\pipe\\CrossDeskService";
|
||||
|
||||
class CrossDeskServiceHost {
|
||||
public:
|
||||
CrossDeskServiceHost();
|
||||
~CrossDeskServiceHost();
|
||||
|
||||
int RunAsService();
|
||||
int RunInConsole();
|
||||
|
||||
private:
|
||||
int RunServiceLoop(bool as_service);
|
||||
int InitializeRuntime();
|
||||
void ShutdownRuntime();
|
||||
void RequestStop();
|
||||
void ReportServiceStatus(DWORD current_state, DWORD win32_exit_code,
|
||||
DWORD wait_hint);
|
||||
void IpcServerLoop();
|
||||
void RefreshSessionState();
|
||||
void EnsureSessionHelper();
|
||||
void ReapSessionHelper();
|
||||
void StopSessionHelper();
|
||||
bool LaunchSessionHelper(DWORD session_id);
|
||||
void ReapSecureInputHelper();
|
||||
void StopSecureInputHelper();
|
||||
bool LaunchSecureInputHelper(DWORD session_id);
|
||||
std::wstring GetSessionHelperPath() const;
|
||||
std::wstring GetSessionHelperStopEventName(DWORD session_id) const;
|
||||
std::wstring GetSecureInputHelperPath() const;
|
||||
std::wstring GetSecureInputHelperStopEventName(DWORD session_id) const;
|
||||
void ResetSessionHelperReportedStateLocked(const char* error,
|
||||
DWORD error_code);
|
||||
bool GetEffectiveSessionLockedLocked() const;
|
||||
bool IsHelperReportingLockScreenLocked() const;
|
||||
bool HasSecureInputUiLocked() const;
|
||||
bool ShouldKeepSecureInputHelperLocked(DWORD target_session_id) const;
|
||||
void RefreshSessionHelperReportedState();
|
||||
void RecordSessionEvent(DWORD event_type, DWORD session_id);
|
||||
std::string HandleIpcCommand(const std::string& command);
|
||||
std::string BuildStatusResponse();
|
||||
std::string SendSecureAttentionSequence();
|
||||
std::string SendSecureDesktopKeyboardInput(int key_code, bool is_down);
|
||||
|
||||
static void WINAPI ServiceMain(DWORD argc, LPWSTR* argv);
|
||||
static BOOL WINAPI ConsoleControlHandler(DWORD control_type);
|
||||
static DWORD WINAPI ServiceControlHandler(DWORD control, DWORD event_type,
|
||||
LPVOID event_data,
|
||||
LPVOID context);
|
||||
|
||||
private:
|
||||
SERVICE_STATUS_HANDLE status_handle_ = nullptr;
|
||||
SERVICE_STATUS service_status_{};
|
||||
HANDLE stop_event_ = nullptr;
|
||||
std::thread ipc_thread_;
|
||||
std::mutex state_mutex_;
|
||||
DWORD active_session_id_ = 0xFFFFFFFF;
|
||||
DWORD process_session_id_ = 0xFFFFFFFF;
|
||||
DWORD input_desktop_error_code_ = 0;
|
||||
DWORD session_helper_process_id_ = 0;
|
||||
DWORD session_helper_session_id_ = 0xFFFFFFFF;
|
||||
DWORD session_helper_exit_code_ = 0;
|
||||
DWORD session_helper_last_error_code_ = 0;
|
||||
DWORD session_helper_status_error_code_ = 0;
|
||||
DWORD session_helper_report_session_id_ = 0xFFFFFFFF;
|
||||
DWORD session_helper_report_process_id_ = 0;
|
||||
DWORD session_helper_report_input_desktop_error_code_ = 0;
|
||||
DWORD secure_input_helper_process_id_ = 0;
|
||||
DWORD secure_input_helper_session_id_ = 0xFFFFFFFF;
|
||||
DWORD secure_input_helper_exit_code_ = 0;
|
||||
DWORD secure_input_helper_last_error_code_ = 0;
|
||||
DWORD last_session_event_type_ = 0;
|
||||
DWORD last_session_event_session_id_ = 0xFFFFFFFF;
|
||||
ULONGLONG started_at_tick_ = 0;
|
||||
ULONGLONG last_sas_tick_ = 0;
|
||||
ULONGLONG session_helper_started_at_tick_ = 0;
|
||||
ULONGLONG session_helper_report_state_age_ms_ = 0;
|
||||
ULONGLONG session_helper_report_uptime_ms_ = 0;
|
||||
ULONGLONG secure_input_helper_started_at_tick_ = 0;
|
||||
bool session_locked_ = false;
|
||||
bool logon_ui_visible_ = false;
|
||||
bool prelogin_ = false;
|
||||
bool secure_desktop_active_ = false;
|
||||
bool input_desktop_available_ = false;
|
||||
bool session_helper_running_ = false;
|
||||
bool session_helper_status_ok_ = false;
|
||||
bool session_helper_report_session_locked_ = false;
|
||||
bool session_helper_report_input_desktop_available_ = false;
|
||||
bool session_helper_report_lock_app_visible_ = false;
|
||||
bool session_helper_report_logon_ui_visible_ = false;
|
||||
bool session_helper_report_secure_desktop_active_ = false;
|
||||
bool session_helper_report_credential_ui_visible_ = false;
|
||||
bool session_helper_report_unlock_ui_visible_ = false;
|
||||
bool secure_input_helper_running_ = false;
|
||||
bool console_mode_ = false;
|
||||
DWORD last_sas_error_code_ = 0;
|
||||
bool last_sas_success_ = false;
|
||||
HANDLE session_helper_process_handle_ = nullptr;
|
||||
HANDLE session_helper_stop_event_ = nullptr;
|
||||
HANDLE secure_input_helper_process_handle_ = nullptr;
|
||||
HANDLE secure_input_helper_stop_event_ = nullptr;
|
||||
std::string input_desktop_name_;
|
||||
std::string last_sas_error_;
|
||||
std::string session_helper_last_error_;
|
||||
std::string session_helper_status_error_;
|
||||
std::string session_helper_report_input_desktop_;
|
||||
std::string session_helper_report_interactive_stage_;
|
||||
std::string secure_input_helper_last_error_;
|
||||
|
||||
static CrossDeskServiceHost* instance_;
|
||||
};
|
||||
|
||||
bool InstallCrossDeskService(const std::wstring& binary_path);
|
||||
bool UninstallCrossDeskService();
|
||||
bool StartCrossDeskService();
|
||||
bool StopCrossDeskService(DWORD timeout_ms = 5000);
|
||||
std::string QueryCrossDeskService(const std::string& command,
|
||||
DWORD timeout_ms = 1000);
|
||||
std::string SendCrossDeskSecureDesktopKeyInput(int key_code, bool is_down,
|
||||
DWORD timeout_ms = 1000);
|
||||
std::string SendCrossDeskSecureDesktopMouseInput(int x, int y, int wheel,
|
||||
int flag,
|
||||
DWORD timeout_ms = 1000);
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
#ifndef _CROSSDESK_SESSION_HELPER_SHARED_H_
|
||||
#define _CROSSDESK_SESSION_HELPER_SHARED_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline constexpr wchar_t kCrossDeskSessionHelperPipePrefix[] =
|
||||
L"\\\\.\\pipe\\CrossDeskSessionHelper-";
|
||||
inline constexpr wchar_t kCrossDeskSecureInputHelperPipePrefix[] =
|
||||
L"\\\\.\\pipe\\CrossDeskSecureInputHelper-";
|
||||
inline constexpr char kCrossDeskSessionHelperStatusCommand[] = "status";
|
||||
inline constexpr char kCrossDeskSecureInputKeyboardCommandPrefix[] =
|
||||
"keyboard:";
|
||||
inline constexpr char kCrossDeskSecureInputMouseCommandPrefix[] =
|
||||
"mouse:";
|
||||
inline constexpr char kCrossDeskSecureInputCaptureCommandPrefix[] =
|
||||
"capture:";
|
||||
inline constexpr DWORD kCrossDeskSecureInputPipeBufferBytes =
|
||||
16 * 1024 * 1024;
|
||||
inline constexpr uint32_t kCrossDeskSecureDesktopFrameMagic = 0x50444358;
|
||||
inline constexpr uint32_t kCrossDeskSecureDesktopFrameVersion = 1;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct CrossDeskSecureDesktopFrameHeader {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
int32_t left;
|
||||
int32_t top;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t payload_size;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
inline std::wstring GetCrossDeskSessionHelperPipeName(DWORD session_id) {
|
||||
return std::wstring(kCrossDeskSessionHelperPipePrefix) +
|
||||
std::to_wstring(session_id);
|
||||
}
|
||||
|
||||
inline std::wstring GetCrossDeskSecureInputHelperPipeName(DWORD session_id) {
|
||||
return std::wstring(kCrossDeskSecureInputHelperPipePrefix) +
|
||||
std::to_wstring(session_id);
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user