Look up a service by `name` and/or `display_name` and return the full service info. - If only `name` is provided, the service is looked up by name. - If only `display_name` is provided, the service key name is resolved first. - If both are provided, the service is looked up by name and the display name is verified. If the service does not exist, returns a `WindowsService` with `_exist: false`.
(input: &WindowsService)
| 164 | /// |
| 165 | /// If the service does not exist, returns a `WindowsService` with `_exist: false`. |
| 166 | pub fn get_service(input: &WindowsService) -> Result<WindowsService, ServiceError> { |
| 167 | if input.name.is_none() && input.display_name.is_none() { |
| 168 | return Err(t!("get.nameOrDisplayNameRequired").to_string().into()); |
| 169 | } |
| 170 | |
| 171 | // Open Service Control Manager |
| 172 | let scm = unsafe { OpenSCManagerW(None, None, SC_MANAGER_CONNECT) } |
| 173 | .map_err(|e| ServiceError::from(t!("get.openScmFailed", error = e.to_string()).to_string()))?; |
| 174 | let scm = ScHandle(scm); |
| 175 | |
| 176 | // Resolve the service key name |
| 177 | let service_key_name = match &input.name { |
| 178 | Some(name) => Some(name.clone()), |
| 179 | None => { |
| 180 | let display_name = input.display_name.as_ref().unwrap(); |
| 181 | unsafe { resolve_key_name_from_display_name(scm.0, display_name) }? |
| 182 | } |
| 183 | }; |
| 184 | |
| 185 | // If we couldn't resolve a key name, the service doesn't exist |
| 186 | let service_key_name = match service_key_name { |
| 187 | Some(n) => n, |
| 188 | None => { |
| 189 | return Ok(WindowsService { |
| 190 | name: input.name.clone(), |
| 191 | display_name: input.display_name.clone(), |
| 192 | exist: Some(false), |
| 193 | ..Default::default() |
| 194 | }); |
| 195 | } |
| 196 | }; |
| 197 | |
| 198 | // Open the service |
| 199 | let name_wide = to_wide(&service_key_name); |
| 200 | let service_handle = match unsafe { |
| 201 | OpenServiceW( |
| 202 | scm.0, |
| 203 | PCWSTR(name_wide.as_ptr()), |
| 204 | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS, |
| 205 | ) |
| 206 | } { |
| 207 | Ok(h) => ScHandle(h), |
| 208 | Err(e) if e.code() == ERROR_SERVICE_DOES_NOT_EXIST.to_hresult() => { |
| 209 | return Ok(WindowsService { |
| 210 | name: input.name.clone(), |
| 211 | display_name: input.display_name.clone(), |
| 212 | exist: Some(false), |
| 213 | ..Default::default() |
| 214 | }); |
| 215 | } |
| 216 | Err(e) => { |
| 217 | return Err(ServiceError::from(t!("get.openServiceFailed", error = e.to_string()).to_string())); |
| 218 | } |
| 219 | }; |
| 220 | |
| 221 | let svc = unsafe { read_service_state(service_handle.0, &service_key_name) }?; |
| 222 | |
| 223 | // If both name and display_name were provided, verify they match |
no test coverage detected