Export (enumerate) all services, optionally filtering by the provided criteria. Returns a list of matching services.
(filter: Option<&WindowsService>)
| 398 | /// Export (enumerate) all services, optionally filtering by the provided criteria. |
| 399 | /// Returns a list of matching services. |
| 400 | pub fn export_services(filter: Option<&WindowsService>) -> Result<Vec<WindowsService>, ServiceError> { |
| 401 | let scm = unsafe { OpenSCManagerW(None, None, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE) } |
| 402 | .map_err(|e| ServiceError::from(t!("get.openScmFailed", error = e.to_string()).to_string()))?; |
| 403 | let scm = ScHandle(scm); |
| 404 | |
| 405 | let services = unsafe { enumerate_services(scm.0) }?; |
| 406 | let mut results = Vec::new(); |
| 407 | |
| 408 | // Pre-compute the status filter value for early rejection before expensive per-service queries |
| 409 | let status_filter_dw = filter.and_then(|f| f.status.as_ref()).map(status_to_current_state); |
| 410 | |
| 411 | for (service_name, current_state) in &services { |
| 412 | // Quick reject based on status before opening the service handle |
| 413 | if let Some(expected_state) = status_filter_dw && *current_state != expected_state { |
| 414 | continue; |
| 415 | } |
| 416 | |
| 417 | let svc = match unsafe { get_service_details(scm.0, service_name) } { |
| 418 | Ok(s) => s, |
| 419 | Err(_) => continue, // skip services we can't query |
| 420 | }; |
| 421 | |
| 422 | if let Some(f) = filter && !matches_filter(&svc, f) { |
| 423 | continue; |
| 424 | } |
| 425 | |
| 426 | results.push(svc); |
| 427 | } |
| 428 | |
| 429 | Ok(results) |
| 430 | } |
| 431 | |
| 432 | /// Enumerate all Win32 services using `EnumServicesStatusExW`, handling pagination. |
| 433 | /// Returns a list of `(service_name, current_state)` tuples. |
no test coverage detected