Read the full configuration and status of an already-opened service handle. # Safety `service_handle` must be a valid, open service handle with `SERVICE_QUERY_CONFIG` and `SERVICE_QUERY_STATUS` access rights.
(
service_handle: SC_HANDLE,
service_name: &str,
)
| 84 | /// `service_handle` must be a valid, open service handle with `SERVICE_QUERY_CONFIG` |
| 85 | /// and `SERVICE_QUERY_STATUS` access rights. |
| 86 | unsafe fn read_service_state( |
| 87 | service_handle: SC_HANDLE, |
| 88 | service_name: &str, |
| 89 | ) -> Result<WindowsService, ServiceError> { |
| 90 | // Query basic configuration |
| 91 | let mut bytes_needed: u32 = 0; |
| 92 | let sizing_result = unsafe { |
| 93 | QueryServiceConfigW(service_handle, None, 0, &mut bytes_needed) |
| 94 | }; |
| 95 | if let Err(e) = sizing_result && e.code() != ERROR_INSUFFICIENT_BUFFER.to_hresult() { |
| 96 | return Err(t!("get.queryConfigFailed", error = e.to_string()).to_string().into()); |
| 97 | } |
| 98 | if bytes_needed == 0 { |
| 99 | return Err(t!("get.queryConfigFailed", error = "buffer size is 0").to_string().into()); |
| 100 | } |
| 101 | let mut config_buffer = vec![0u8; bytes_needed as usize]; |
| 102 | let config_ptr = config_buffer.as_mut_ptr().cast::<QUERY_SERVICE_CONFIGW>(); |
| 103 | unsafe { |
| 104 | QueryServiceConfigW( |
| 105 | service_handle, |
| 106 | Some(&mut *config_ptr), |
| 107 | bytes_needed, |
| 108 | &mut bytes_needed, |
| 109 | ) |
| 110 | .map_err(|e| ServiceError::from(t!("get.queryConfigFailed", error = e.to_string()).to_string()))?; |
| 111 | } |
| 112 | |
| 113 | let config = unsafe { &*config_ptr }; |
| 114 | let display_name = unsafe { pwstr_to_string(config.lpDisplayName) }; |
| 115 | |
| 116 | let start_type = match config.dwStartType { |
| 117 | SERVICE_AUTO_START => { |
| 118 | if unsafe { is_delayed_auto_start(service_handle) } { |
| 119 | Some(StartType::AutomaticDelayedStart) |
| 120 | } else { |
| 121 | Some(StartType::Automatic) |
| 122 | } |
| 123 | } |
| 124 | SERVICE_DEMAND_START => Some(StartType::Manual), |
| 125 | SERVICE_DISABLED => Some(StartType::Disabled), |
| 126 | _ => None, |
| 127 | }; |
| 128 | |
| 129 | let error_control = match config.dwErrorControl { |
| 130 | SERVICE_ERROR_IGNORE => Some(ErrorControl::Ignore), |
| 131 | SERVICE_ERROR_NORMAL => Some(ErrorControl::Normal), |
| 132 | SERVICE_ERROR_SEVERE => Some(ErrorControl::Severe), |
| 133 | SERVICE_ERROR_CRITICAL => Some(ErrorControl::Critical), |
| 134 | _ => None, |
| 135 | }; |
| 136 | |
| 137 | let executable_path = unsafe { pwstr_to_string(config.lpBinaryPathName) }; |
| 138 | let logon_account = unsafe { pwstr_to_string(config.lpServiceStartName) }; |
| 139 | let deps = unsafe { parse_multi_string(config.lpDependencies) }; |
| 140 | let dependencies = if deps.is_empty() { None } else { Some(deps) }; |
| 141 | |
| 142 | let description = unsafe { query_description(service_handle) }; |
| 143 | let status = unsafe { query_status(service_handle) }?; |
no test coverage detected