Add SAS Service for Ctrl+Alt+Del support

- New guruconnect-sas-service binary (runs as SYSTEM)
- Named pipe IPC for agent-to-service communication
- Multi-tier SAS approach: service > sas.dll > fallback
- Service auto-install/uninstall helpers in startup.rs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 20:34:41 -07:00
parent f6bf0cfd26
commit 68eab236bf
6 changed files with 822 additions and 8 deletions

View File

@@ -177,6 +177,93 @@ pub fn uninstall() -> Result<()> {
Ok(())
}
/// Install the SAS service if the binary is available
/// This allows the agent to send Ctrl+Alt+Del even without SYSTEM privileges
#[cfg(windows)]
pub fn install_sas_service() -> Result<()> {
info!("Attempting to install SAS service...");
// Check if the SAS service binary exists alongside the agent
let exe_path = std::env::current_exe()?;
let exe_dir = exe_path.parent().ok_or_else(|| anyhow::anyhow!("No parent directory"))?;
let sas_binary = exe_dir.join("guruconnect-sas-service.exe");
if !sas_binary.exists() {
// Also check in Program Files
let program_files = std::path::PathBuf::from(r"C:\Program Files\GuruConnect\guruconnect-sas-service.exe");
if !program_files.exists() {
warn!("SAS service binary not found");
return Ok(());
}
}
// Run the install command
let sas_path = if sas_binary.exists() {
sas_binary
} else {
std::path::PathBuf::from(r"C:\Program Files\GuruConnect\guruconnect-sas-service.exe")
};
let output = std::process::Command::new(&sas_path)
.arg("install")
.output();
match output {
Ok(result) => {
if result.status.success() {
info!("SAS service installed successfully");
} else {
let stderr = String::from_utf8_lossy(&result.stderr);
warn!("SAS service install failed: {}", stderr);
}
}
Err(e) => {
warn!("Failed to run SAS service installer: {}", e);
}
}
Ok(())
}
/// Uninstall the SAS service
#[cfg(windows)]
pub fn uninstall_sas_service() -> Result<()> {
info!("Attempting to uninstall SAS service...");
// Try to find and run the uninstall command
let paths = [
std::env::current_exe().ok().and_then(|p| p.parent().map(|d| d.join("guruconnect-sas-service.exe"))),
Some(std::path::PathBuf::from(r"C:\Program Files\GuruConnect\guruconnect-sas-service.exe")),
];
for path_opt in paths.iter() {
if let Some(ref path) = path_opt {
if path.exists() {
let output = std::process::Command::new(path)
.arg("uninstall")
.output();
if let Ok(result) = output {
if result.status.success() {
info!("SAS service uninstalled successfully");
return Ok(());
}
}
}
}
}
warn!("SAS service binary not found for uninstall");
Ok(())
}
/// Check if the SAS service is installed and running
#[cfg(windows)]
pub fn check_sas_service() -> bool {
use crate::sas_client;
sas_client::is_service_available()
}
#[cfg(not(windows))]
pub fn add_to_startup() -> Result<()> {
warn!("Startup persistence not implemented for this platform");
@@ -193,3 +280,19 @@ pub fn uninstall() -> Result<()> {
warn!("Uninstall not implemented for this platform");
Ok(())
}
#[cfg(not(windows))]
pub fn install_sas_service() -> Result<()> {
warn!("SAS service only available on Windows");
Ok(())
}
#[cfg(not(windows))]
pub fn uninstall_sas_service() -> Result<()> {
Ok(())
}
#[cfg(not(windows))]
pub fn check_sas_service() -> bool {
false
}