Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to register for pre-shutdown notification from C++

I write a local service application using C++ and I can't find the correct way of registering for a pre-shut-down notification (for OS later than Windows XP). I believe that SERVICE_CONTROL_PRESHUTDOWN notification has been added since Vista, but when you call SetServiceStatus do we need to specify:

dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PRESHUTDOWN;

or

dwServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PRESHUTDOWN;
like image 339
ahmd0 Avatar asked Dec 12 '22 20:12

ahmd0


2 Answers

You cannot accept both a shutdown and a preshutdown if your service is correctly coded. The documentation explicitly states this.

From http://msdn.microsoft.com/en-us/library/windows/desktop/ms683241(v=vs.85).aspx:

Referring to SERVICE_CONTROL_PRESHUTDOWN:

A service that handles this notification blocks system shutdown until the service stops or the preshutdown time-out interval specified through SERVICE_PRESHUTDOWN_INFO expires.

In the same page, the section about SERVICE_CONTROL_SHUTDOWN adds:

Note that services that register for SERVICE_CONTROL_PRESHUTDOWN notifications cannot receive this notification because they have already stopped.

So, the correct way is to set the dwControlsAccepted to include either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN, depending on your needs, but not to both at the same time.

But do note that you probably want to accept more controls. You should always allow at least SERVICE_CONTROL_INTERROGATE, and almost certainly allow SERVICE_CONTROL_STOP, since without the latter the service cannot be stopped (e.g. in order to uninstall the software) and the process will have to be forcibly terminated (i.e. killed).

like image 98
Nik Bougalis Avatar answered Dec 31 '22 13:12

Nik Bougalis


As noted by the commenters above, you will need to choose from either SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PRESHUTDOWN (Vista or later). If you are using SERVICE_ACCEPT_PRESHUTDOWN, you will need to register your service with the SCM using RegisterServiceCtrlHandlerEx instead of RegisterServiceCtrlHandler else you will not be receiving the pre-shutdown notifications. The handler prototype also changes from Handler to HandlerEx.

Another point to note is that handling pure shutdown events is limited to 5 seconds in Windows Server 2012 (and presumably Windows 8), 12 seconds in Windows 7 and Windows Server 2008, 20 seconds in Windows XP before your service is killed while stopping. This is the reason why you may need the pre-shutdown notification. You may want to change this at \\HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout.

like image 27
JaLooNz Avatar answered Dec 31 '22 14:12

JaLooNz