编写Control Handler函数
当接收到暂停请求,MyServiceCtrlHandler将SERVICE_STATUS结构中的dwCurrentState设置为SERVICE_PAUSED。同样的,当接收到继续请求时,状态被设置为SERVICE_RUNNING。所以,对于处理暂停和继续请求,MyServiceCtrlHandler函数并不是一个好例子。因为,MyServiceCtrlHandler函数是一个Handler函数的模版,暂停和继续控制的代码并不完整。支持暂停和继续控制的服务应该用一个有意义的方法来处理这些控制。很多服务都不支持暂停或者继续控制。如果服务利用dwControlsAccepted参数来指明它不支持暂停或继续,那么,SCM(服务控制管理器)就不会向服务的Handler函数发送暂停或继续控制信息。
为了输出调试信息,MyServiceCtrlHandler调用SvcDebugOut。SvcDebugOut的代码已经在“编写main函数”中列出。并且,注意一下,MyServiceStatus变量是一个全局变量,应该像在“编写ServiceMain函数”中描述的那样进行初始化。
#include <windows.h>
SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;
VOID SvcDebugOut(LPSTR String, DWORD Status);
VOID WINAPI MyServiceCtrlHandler (DWORD Opcode)
{
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
// Do whatever it takes to pause here.
MyServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
// Do whatever it takes to continue here.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here.
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (MyServiceStatusHandle,
&MyServiceStatus))
{
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld ",
status);
}
SvcDebugOut(" [MY_SERVICE] Leaving MyService ",0);
return;
case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;
default:
SvcDebugOut(" [MY_SERVICE] Unrecognized opcode %ld ",
Opcode);
}
// Send current status.
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld ",
status);
}
return;
}