use std::{ptr::null_mut, time::Duration}; use winapi::{ shared::minwindef::DWORD, um::{ errhandlingapi::GetLastError, winsvc::{ CloseServiceHandle, ControlService, OpenSCManagerW, OpenServiceW, QueryServiceStatus, StartServiceW, SC_HANDLE__, SC_MANAGER_CONNECT, SERVICE_CONTROL_STOP, SERVICE_QUERY_STATUS, SERVICE_START, SERVICE_STOP }, }, }; use widestring::U16CString; const SERVICE_STATUS_RUNNING: u32 = 0x00000004; const SERVICE_STATUS_STOPPED: u32 = 0x00000001; fn open_sc_manager(desired_access: DWORD) -> Result<*mut SC_HANDLE__, DWORD> { let sc_manager_handle = unsafe { OpenSCManagerW(null_mut(), null_mut(), desired_access) }; if sc_manager_handle.is_null() { Err(unsafe { GetLastError() }) } else { Ok(sc_manager_handle) } } fn open_service( sc_manager_handle: *mut SC_HANDLE__, service_name: &str, desired_access: DWORD, ) -> Result<*mut SC_HANDLE__, DWORD> { let service_name_wstr = U16CString::from_str(service_name).unwrap(); let service_handle = unsafe { OpenServiceW( sc_manager_handle, service_name_wstr.as_ptr(), desired_access, ) }; if service_handle.is_null() { Err(unsafe { GetLastError() }) } else { Ok(service_handle) } } fn start_service(service_handle: *mut SC_HANDLE__) -> Result<(), DWORD> { let result = unsafe { StartServiceW(service_handle, 0, null_mut()) }; if result == 0 { Err(unsafe { GetLastError() }) } else { Ok(()) } } fn stop_service(service_handle: *mut SC_HANDLE__) -> Result<(), DWORD> { let mut service_status = unsafe { std::mem::zeroed() }; let result = unsafe { ControlService( service_handle, SERVICE_CONTROL_STOP, &mut service_status, ) }; if result == 0 { Err(unsafe { GetLastError() }) } else { Ok(()) } } fn query_service_status(service_handle: *mut SC_HANDLE__) -> Result { let mut service_status = unsafe { std::mem::zeroed() }; let result = unsafe { QueryServiceStatus(service_handle, &mut service_status) }; if result == 0 { Err(unsafe { GetLastError() }) } else { Ok(service_status.dwCurrentState) } } pub fn restart_service(service_name: String) { let sc_manager_handle = open_sc_manager(SC_MANAGER_CONNECT).unwrap(); let service_handle = open_service( sc_manager_handle, service_name.as_str(), SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP, ) .unwrap(); let service_status_res = query_service_status(service_handle); if let Err(e) = service_status_res { error!("Failed to query service status. Error code: {e}"); return; } let service_status = service_status_res.unwrap(); if service_status == SERVICE_STATUS_RUNNING { // Stop the service match stop_service(service_handle) { Ok(_) => info!("Service stopped successfully."), Err(error) => info!("Failed to stop service. Error: {}", error), } info!("Waiting for service being stopped successfully"); std::thread::sleep(Duration::from_secs(10)); // Start the service match start_service(service_handle) { Ok(_) => info!("Service started successfully."), Err(error) => info!("Failed to start service. Error: {}", error), } } if service_status == SERVICE_STATUS_STOPPED { // Start the service match start_service(service_handle) { Ok(_) => info!("Service started successfully."), Err(error) => info!("Failed to start service. Error: {}", error), } } // Close the service and SCM handles unsafe { CloseServiceHandle(service_handle); CloseServiceHandle(sc_manager_handle); } }