Skip to content

Commit

Permalink
fix(windows): add a fallback for fetching sid, which use powershell
Browse files Browse the repository at this point in the history
… while `wmic` command execution failed (#25)

* Add fallback `powershell` for `wmic` command execution fails

* chore: use const instead

---------

Co-authored-by: Jonson Petard <41122242+greenhat616@users.noreply.github.com>
  • Loading branch information
MNDIA and greenhat616 authored Oct 25, 2024
1 parent ea4f917 commit f1b93fe
Showing 1 changed file with 53 additions and 9 deletions.
62 changes: 53 additions & 9 deletions nyanpasu-utils/src/os/os_impl/windows.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult};
use tokio::process::Command;

pub async fn get_current_user_sid() -> IoResult<String> {
let output = Command::new("cmd")
.args(["/C", "wmic useraccount where name='%username%' get sid"])
async fn execute_command(command: &str, args: &[&str]) -> IoResult<String> {
let output = Command::new(command)
.args(args)
.creation_flags(0x0800_0000) // CREATE_NO_WINDOW
.output()
.await
Expand All @@ -15,16 +15,60 @@ pub async fn get_current_user_sid() -> IoResult<String> {
})?;

if !output.status.success() {
return Err(IoError::new(IoErrorKind::Other, "Command failed"));
return Err(IoError::new(
IoErrorKind::Other,
format!("Command execution failed: '{} {}'", command, args.join(" ")),
));
}

let output_str = String::from_utf8_lossy(&output.stdout);
Ok(output_str.trim().to_string())
}

pub async fn get_current_user_sid() -> IoResult<String> {
const CMD_BINARY: &str = "cmd";
const WMIC_ARGS: [&str; 2] = ["/C", "wmic useraccount where name='%username%' get sid"];
const POWERSHELL_BINARY: &str = "powershell";
const POWERSHELL_ARGS: [&str; 2] = [
"-Command",
"[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value",
];
const FALLBACK_POWERSHELL_ARGS: [&str; 2] = ["-Command", "Get-WmiObject Win32_UserAccount -Filter \"Name='$env:USERNAME'\" | Select-Object -ExpandProperty SID"];

let lines: Vec<&str> = output_str.lines().collect();
if lines.len() < 2 {
return Err(IoError::new(IoErrorKind::Other, "Unexpected output format"));
match execute_command(CMD_BINARY, &WMIC_ARGS).await {
Ok(output_str) => {
let lines: Vec<&str> = output_str.lines().collect();
if lines.len() < 2 {
return Err(IoError::new(IoErrorKind::Other, "Unexpected output format"));
}
Ok(lines[1].trim().to_string())
}
Err(_) => {
// Fallback to PowerShell if wmic fails
match execute_command(POWERSHELL_BINARY, &POWERSHELL_ARGS).await {
Ok(sid) => Ok(sid),
Err(_) => execute_command(POWERSHELL_BINARY, &FALLBACK_POWERSHELL_ARGS).await,
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use tokio::runtime::Runtime;

let sid = lines[1].trim().to_string();
Ok(sid)
#[tokio::test]
#[cfg(windows)]
async fn test_get_current_user_sid() {
match get_current_user_sid().await {
Ok(sid) => {
println!("[{}]", sid);
assert!(!sid.is_empty(), "SID should not be empty");
}
Err(e) => {
panic!("Failed to get current user SID: {}", e);
}
}
}
}

0 comments on commit f1b93fe

Please sign in to comment.