notificationswindows-servicesresumepause

Automatically pausing/continuing a service when OS suspends


I made a Windows Service process that can be started/stopped/paused/continued.

The service is created with CreateService() and the service starts a service controller with RegisterServiceCtrlHandlerExA().

Even though the service can subscribe to power setting notifications using RegisterPowerSettingNotification() I find that these only represent events like battery/mains for laptops, and such. Not for suspend/sleep of the OS.

How can I tell the SCM to automatically pause my service before the OS suspends/sleeps? And continue my service after it wakes up again?


Solution

  • This requires calling the PowerRegisterSuspendResumeNotification() function.

    For this, you need to #include <powrprof.h> and link against powrprof.lib.

    The callback itself looks like:

    static ULONG DeviceNotifyCallbackRoutine
    (
        PVOID Context,
        ULONG Type,         // PBT_APMSUSPEND, PBT_APMRESUMESUSPEND, or PBT_APMRESUMEAUTOMATIC
        PVOID Setting       // Unused
    )
    {
        LOGI("DeviceNotifyCallbackRoutine");
        if (Type == PBT_APMSUSPEND)
        {
            turboledz_pause_all_devices();
            LOGI("Devices paused.");
        }
        if (Type == PBT_APMRESUMEAUTOMATIC)
        {
            turboledz_paused = 0;
            LOGI("Device unpaused.");
        }
        return 0;
    }
    
    static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS notifycb =
    {
        DeviceNotifyCallbackRoutine,
        NULL,
    };
    

    And then register it with:

        HPOWERNOTIFY registration;
        const DWORD registered = PowerRegisterSuspendResumeNotification
        (
            DEVICE_NOTIFY_CALLBACK,
            &notifycb,
            &registration
        );
        if (registered != ERROR_SUCCESS)
        {
            const DWORD err = GetLastError();
            LOGI("PowerRegisterSuspendResumeNotification failed with error 0x%lx", err);
        }