use windows::Win32::System::Services::{ENUM_SERVICE_STATUS_PROCESSW, SERVICE_STATUS_PROCESS};
use super::types::ServiceState;
#[derive(Debug, Clone)]
pub struct ServiceStatus {
pub name: String,
pub display_name: Option<String>,
pub state: ServiceState,
pub process_id: u32,
pub service_type: u32,
pub controls_accepted: u32,
pub exit_code: u32,
pub service_specific_exit_code: u32,
pub checkpoint: u32,
pub wait_hint_ms: u32,
pub service_flags: u32,
}
impl ServiceStatus {
pub(crate) fn from_status_process(
name: String,
display_name: Option<String>,
status: &SERVICE_STATUS_PROCESS,
) -> Self {
ServiceStatus {
name,
display_name,
state: ServiceState::from_windows(status.dwCurrentState),
process_id: status.dwProcessId,
service_type: status.dwServiceType.0,
controls_accepted: status.dwControlsAccepted,
exit_code: status.dwWin32ExitCode,
service_specific_exit_code: status.dwServiceSpecificExitCode,
checkpoint: status.dwCheckPoint,
wait_hint_ms: status.dwWaitHint,
service_flags: status.dwServiceFlags.0,
}
}
pub(crate) fn from_enum_status(raw: &ENUM_SERVICE_STATUS_PROCESSW) -> Self {
ServiceStatus {
name: unsafe { read_pwstr(raw.lpServiceName.0) },
display_name: Some(unsafe { read_pwstr(raw.lpDisplayName.0) }),
state: ServiceState::from_windows(raw.ServiceStatusProcess.dwCurrentState),
process_id: raw.ServiceStatusProcess.dwProcessId,
service_type: raw.ServiceStatusProcess.dwServiceType.0,
controls_accepted: raw.ServiceStatusProcess.dwControlsAccepted,
exit_code: raw.ServiceStatusProcess.dwWin32ExitCode,
service_specific_exit_code: raw.ServiceStatusProcess.dwServiceSpecificExitCode,
checkpoint: raw.ServiceStatusProcess.dwCheckPoint,
wait_hint_ms: raw.ServiceStatusProcess.dwWaitHint,
service_flags: raw.ServiceStatusProcess.dwServiceFlags.0,
}
}
}
unsafe fn read_pwstr(ptr: *const u16) -> String {
if ptr.is_null() {
return String::new();
}
let mut len = 0usize;
while unsafe { *ptr.add(len) } != 0 {
len += 1;
}
let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
String::from_utf16_lossy(slice)
}