mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 10:23:10 +08:00
181 lines
7.4 KiB
C++
181 lines
7.4 KiB
C++
/*
|
|
* @Author: DI JUNKUN
|
|
* @Date: 2026-04-21
|
|
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
|
*/
|
|
|
|
#ifndef _SERVICE_HOST_H_
|
|
#define _SERVICE_HOST_H_
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <cstdint>
|
|
#include <atomic>
|
|
#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 ClientProcessMonitorLoop();
|
|
bool LaunchUnattendedHost(DWORD session_id);
|
|
void StopUnattendedHost();
|
|
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,
|
|
const std::string& interactive_stage,
|
|
const std::string& interactive_desktop);
|
|
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;
|
|
void UpdateSasSecureDesktopGraceLocked(const std::string& observed_stage);
|
|
bool IsSasSecureDesktopGraceActiveLocked() const;
|
|
bool ShouldKeepSecureInputHelperLocked(DWORD target_session_id) const;
|
|
std::string ResolveInteractiveStageLocked() const;
|
|
std::string ResolveInteractiveDesktopLocked(
|
|
const std::string& interactive_stage) const;
|
|
void RefreshSessionHelperReportedState();
|
|
void RecordSessionEvent(DWORD event_type, DWORD session_id);
|
|
std::string HandleIpcCommand(const std::string& command,
|
|
DWORD client_session_id);
|
|
std::string BuildStatusResponse(DWORD client_session_id);
|
|
std::string SendSecureAttentionSequence(DWORD client_session_id);
|
|
std::string SendSecureDesktopKeyboardInput(DWORD client_session_id,
|
|
int key_code, bool is_down,
|
|
uint32_t scan_code = 0,
|
|
bool extended = false);
|
|
std::string SendSecureDesktopMouseInput(DWORD client_session_id,
|
|
int x, int y, int wheel, int flag);
|
|
|
|
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::thread client_process_monitor_thread_;
|
|
// Owned exclusively by the monitor, then drained after it joins.
|
|
HANDLE unattended_process_ = nullptr;
|
|
HANDLE unattended_stop_event_ = nullptr;
|
|
DWORD unattended_session_ = 0xFFFFFFFF;
|
|
std::atomic<uint64_t> unattended_logoff_generation_{0};
|
|
std::mutex state_mutex_;
|
|
HANDLE lifetime_mutex_ = nullptr;
|
|
std::wstring lifetime_mutex_name_;
|
|
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;
|
|
ULONGLONG sas_secure_desktop_until_tick_ = 0;
|
|
bool session_locked_ = false;
|
|
bool logon_ui_visible_ = false;
|
|
bool consent_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_consent_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;
|
|
bool sas_secure_desktop_seen_ = 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_;
|
|
std::string secure_input_helper_interactive_stage_;
|
|
std::string secure_input_helper_interactive_desktop_;
|
|
|
|
static CrossDeskServiceHost* instance_;
|
|
};
|
|
|
|
bool IsCrossDeskServiceInstalled();
|
|
bool InstallCrossDeskService(const std::wstring& binary_path);
|
|
bool UninstallCrossDeskService();
|
|
bool StartCrossDeskService();
|
|
bool StopCrossDeskService(DWORD timeout_ms = 20000);
|
|
std::string QueryCrossDeskService(const std::string& command,
|
|
DWORD timeout_ms = 1000);
|
|
std::string SendCrossDeskSecureDesktopKeyInput(int key_code, bool is_down,
|
|
uint32_t scan_code = 0,
|
|
bool extended = false,
|
|
DWORD timeout_ms = 1000);
|
|
std::string SendCrossDeskSecureDesktopMouseInput(int x, int y, int wheel,
|
|
int flag,
|
|
DWORD timeout_ms = 1000);
|
|
|
|
} // namespace crossdesk
|
|
|
|
#endif
|