(input: &WindowsService)
| 604 | } |
| 605 | |
| 606 | pub fn set_service(input: &WindowsService) -> Result<WindowsService, ServiceError> { |
| 607 | let name = input.name.as_deref() |
| 608 | .ok_or_else(|| t!("set.nameRequired").to_string())?; |
| 609 | |
| 610 | if let Some(ref account) = input.logon_account && !is_builtin_service_account(account) { |
| 611 | return Err(ServiceError::from( |
| 612 | t!("set.unsupportedLogonAccount", account = account).to_string(), |
| 613 | )); |
| 614 | } |
| 615 | |
| 616 | unsafe { |
| 617 | let scm = OpenSCManagerW(None, None, SC_MANAGER_CONNECT) |
| 618 | .map_err(|e| t!("set.openScmFailed", error = e.to_string()).to_string())?; |
| 619 | let scm = ScHandle(scm); |
| 620 | |
| 621 | let name_wide = to_wide(name); |
| 622 | let needs_config_change = input.start_type.is_some() |
| 623 | || input.executable_path.is_some() |
| 624 | || input.logon_account.is_some() |
| 625 | || input.error_control.is_some() |
| 626 | || input.display_name.is_some() |
| 627 | || input.dependencies.is_some() |
| 628 | || input.description.is_some(); |
| 629 | |
| 630 | let mut access = SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS; |
| 631 | if needs_config_change { |
| 632 | access |= SERVICE_CHANGE_CONFIG; |
| 633 | } |
| 634 | if let Some(ref status) = input.status { |
| 635 | match status { |
| 636 | ServiceStatus::Running => { |
| 637 | access |= SERVICE_START | SERVICE_PAUSE_CONTINUE; |
| 638 | } |
| 639 | ServiceStatus::Stopped => { |
| 640 | access |= SERVICE_STOP; |
| 641 | } |
| 642 | ServiceStatus::Paused => { |
| 643 | access |= SERVICE_PAUSE_CONTINUE; |
| 644 | } |
| 645 | _ => {} |
| 646 | } |
| 647 | } |
| 648 | |
| 649 | let service_handle = OpenServiceW(scm.0, PCWSTR(name_wide.as_ptr()), access) |
| 650 | .map_err(|e| t!("set.openServiceFailed", error = e.to_string()).to_string())?; |
| 651 | let service_handle = ScHandle(service_handle); |
| 652 | |
| 653 | // 1. Apply configuration changes via ChangeServiceConfigW |
| 654 | let has_config = input.start_type.is_some() |
| 655 | || input.executable_path.is_some() |
| 656 | || input.logon_account.is_some() |
| 657 | || input.error_control.is_some() |
| 658 | || input.display_name.is_some() |
| 659 | || input.dependencies.is_some(); |
| 660 | |
| 661 | if has_config { |
| 662 | let dw_start_type = match &input.start_type { |
| 663 | Some(StartType::Automatic | StartType::AutomaticDelayedStart) => SERVICE_AUTO_START, |
no test coverage detected