Skip to content

Windows service improvements for hosting, testing, fallback, and extended commands #3662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 21, 2025

Conversation

kennykerr
Copy link
Collaborator

@kennykerr kennykerr commented Jul 14, 2025

This update provides a major overhaul of the windows-services crate and addresses a number of issues to support more scenarios and features while retaining the simplicity of the Service builder by default.

  • Provides the foundation for supporting extended controls by switching from RegisterServiceCtrlHandlerW to RegisterServiceCtrlHandlerExW internally.
  • Provides a new Extended variant for the Command enum to allow services to receive extended control information.
  • Provides a new can_accept builder method to specify other specific commands to accept.
  • Provides a new can_fallback builder method to allow the service to provide specific handling when the service is not started by the Service Control Manager.
  • The run method is no longer fatal so that a caller may decide to gracefully handle and detect when the service is not started by the Service Control Manager.
  • Provides a new handle method to retrieve the handle representing the service. This may be used to call other service-related functions like RegisterPowerSettingNotification.

Additional samples and tests are now provided thanks to the greater flexibility afforded by the new implementation.

Fixes: #3610
Fixes: #3641

@edvard-pettersen-elas-ai

@kennykerr, the API looks good, but there are some additional steps that are required to support SERVICE_CONTROL_POWEREVENT. After having specified can_accept(SERVICE_ACCEPT_POWEREVENT), the application also needs to specify which power events to register for notification by calling RegisterPowerSettingNotification. This requires access to the handle returned by RegisterServiceCtrlHandlerExW, which doesn't seem accessible in the current proposal.

@kennykerr
Copy link
Collaborator Author

kennykerr commented Jul 15, 2025

37c0d93 adds a handle method that you can use to retrieve the service handle. You might for example use it when responding to Command::Start to call RegisterPowerSettingNotification. Something like this:

let mut power_handle = 0;

Service::new()
    .can_stop()
    .can_accept(SERVICE_ACCEPT_POWEREVENT)
    .run(|service, command| {
        if command == Command::Start {
            power_handle = unsafe {
                RegisterPowerSettingNotification(
                    service.handle(),
                    &GUID_GLOBAL_USER_PRESENCE,
                    DEVICE_NOTIFY_SERVICE_HANDLE,
                )
            };
        }

        if let Command::Extended(command) = command {
            if command.control == SERVICE_CONTROL_POWEREVENT {
                debug_assert!(command.ty == PBT_POWERSETTINGCHANGE);
                let data = unsafe { &*(command.data as *const POWERBROADCAST_SETTING) };
                debug_assert!(&data.PowerSetting == &GUID_GLOBAL_USER_PRESENCE);
                debug_assert!(data.DataLength == 4);

                let data = unsafe {
                    std::slice::from_raw_parts(data.Data.as_ptr(), data.DataLength as usize)
                };

                let data = u32::from_le_bytes(data.try_into().unwrap());
                writeln!(log, "Present: {data}").unwrap();
            }
        }
    })
    .unwrap();

@kennykerr

This comment was marked as resolved.

@kennykerr kennykerr merged commit 0dfbc25 into master Jul 21, 2025
29 checks passed
@kennykerr kennykerr deleted the service-state branch July 21, 2025 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for running a service exe as a console app. Support extended control codes with windows-services
2 participants