Win2k Services: Intercepting Shutdown Requests

Hello everyone,

I’m currently experiencing a problem with my service.
I’ve been trying to trap the shutdown command from
my service routine. I inserted a registry write
function to see if the shutdown message got
intercepted when the service was running during a
system shutdown but so far, nothing.

From MSDN, I found out that Win2K Pro needed a SP
update in order for the SERVICE_CONTROL_SHUTDOWN
to work properly and have updated it to SP2.

I have set the appropriate flags for dwControlsAccepted
and the service still wouldn’t trap the message.

I would really appreciate it if someone can point out
any errors/omissions I may have missed out.

Thank you,
Tan Chee Hui

(PS:Note that in order to handle the SHUTDOWN message in
the control handler routine, I need to temporarily
issue a STOP_PENDING message -since Shutdown imposes
a strict time limitation - while I complete my own tasks first.)

Code follows:-

void main(int argc, char *argv)
{
SERVICE_TABLE_ENTRY DispatchTable =
{
{ SERVNAME, TestServiceStart },
{ NULL, NULL }
};


hSC = CreateService(
hSCMan, // SCManager database
SERVNAME, // name of service
SERVDISP, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
pathname, // service’s binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (hSC == NULL) {
// check if the service is already in the SCManager database
// if it is, we attempt to start the service
hSC = OpenService(
hSCMan, // handle to service control manager database
SERVNAME, // pointer to name of service to start
SERVICE_ALL_ACCESS // type of access to service
);
}
else {

StartService(hSC,0,NULL);

}
if (hSC) CloseServiceHandle(hSC);
if (hSCMan) CloseServiceHandle(hSCMan);

StartServiceCtrlDispatcher(DispatchTable));

}

void __stdcall TestServiceStart(DWORD argc, LPTSTR *argv)
{

ServStat.dwControlsAccepted = SERVICE_ACCEPT_STOP
|SERVICE_ACCEPT_SHUTDOWN
|SERVICE_ACCEPT_PAUSE_CONTINUE;

hServ = RegisterServiceCtrlHandler(SERVNAME,TestServiceCtrlHandler);

SetServiceStatus (hServ, &ServStat);
return;
}

void __stdcall TestServiceCtrlHandler (DWORD opcode)
{
ServStat.dwControlsAccepted = SERVICE_ACCEPT_STOP
|SERVICE_ACCEPT_SHUTDOWN
|SERVICE_ACCEPT_PAUSE_CONTINUE;
switch(opcode) {

case SERVICE_CONTROL_SHUTDOWN:
WriteToRegistry(); // function to write to registry
ServStat.dwCurrentState = SERVICE_STOP_PENDING;
if (!SetServiceStatus (hServ,&ServStat)) {
status = GetLastError();
SvcDbgOut(“SDSERVICE.C: hServ error %ld\n”,status);
}


ServStat.dwWin32ExitCode = 0;
ServStat.dwCurrentState = SERVICE_STOPPED;
ServStat.dwWaitHint = 5;
if (!SetServiceStatus (hServ, &ServStat)) {
status = GetLastError();
SvcDbgOut(“SDSERVICE.C: SetServiceStatus error %ld\n”,status);
}
break;
}
return;
}