Skip to main content

windows_erg/service/
status.rs

1use windows::Win32::System::Services::{ENUM_SERVICE_STATUS_PROCESSW, SERVICE_STATUS_PROCESS};
2
3use super::types::ServiceState;
4
5/// Runtime status for a Windows service.
6#[derive(Debug, Clone)]
7pub struct ServiceStatus {
8    /// Service key name.
9    pub name: String,
10    /// Optional display name when available.
11    pub display_name: Option<String>,
12    /// Current service state.
13    pub state: ServiceState,
14    /// Process ID owning the service instance (0 for some stopped/shared services).
15    pub process_id: u32,
16    /// Service type flags.
17    pub service_type: u32,
18    /// Accepted control flags.
19    pub controls_accepted: u32,
20    /// Win32 exit code.
21    pub exit_code: u32,
22    /// Service-specific exit code.
23    pub service_specific_exit_code: u32,
24    /// Checkpoint value for pending states.
25    pub checkpoint: u32,
26    /// Wait hint in milliseconds.
27    pub wait_hint_ms: u32,
28    /// Service flags.
29    pub service_flags: u32,
30}
31
32impl ServiceStatus {
33    pub(crate) fn from_status_process(
34        name: String,
35        display_name: Option<String>,
36        status: &SERVICE_STATUS_PROCESS,
37    ) -> Self {
38        ServiceStatus {
39            name,
40            display_name,
41            state: ServiceState::from_windows(status.dwCurrentState),
42            process_id: status.dwProcessId,
43            service_type: status.dwServiceType.0,
44            controls_accepted: status.dwControlsAccepted,
45            exit_code: status.dwWin32ExitCode,
46            service_specific_exit_code: status.dwServiceSpecificExitCode,
47            checkpoint: status.dwCheckPoint,
48            wait_hint_ms: status.dwWaitHint,
49            service_flags: status.dwServiceFlags.0,
50        }
51    }
52
53    pub(crate) fn from_enum_status(raw: &ENUM_SERVICE_STATUS_PROCESSW) -> Self {
54        ServiceStatus {
55            name: unsafe { read_pwstr(raw.lpServiceName.0) },
56            display_name: Some(unsafe { read_pwstr(raw.lpDisplayName.0) }),
57            state: ServiceState::from_windows(raw.ServiceStatusProcess.dwCurrentState),
58            process_id: raw.ServiceStatusProcess.dwProcessId,
59            service_type: raw.ServiceStatusProcess.dwServiceType.0,
60            controls_accepted: raw.ServiceStatusProcess.dwControlsAccepted,
61            exit_code: raw.ServiceStatusProcess.dwWin32ExitCode,
62            service_specific_exit_code: raw.ServiceStatusProcess.dwServiceSpecificExitCode,
63            checkpoint: raw.ServiceStatusProcess.dwCheckPoint,
64            wait_hint_ms: raw.ServiceStatusProcess.dwWaitHint,
65            service_flags: raw.ServiceStatusProcess.dwServiceFlags.0,
66        }
67    }
68}
69
70unsafe fn read_pwstr(ptr: *const u16) -> String {
71    if ptr.is_null() {
72        return String::new();
73    }
74
75    let mut len = 0usize;
76    while unsafe { *ptr.add(len) } != 0 {
77        len += 1;
78    }
79
80    let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
81    String::from_utf16_lossy(slice)
82}