(ii) an in-depth discussion of services
The last chapter is actually a general introduction, the following is the real details. In the entry function to complete the initialization of the ServiceMain, the more accurate is to initialize a service_table_entry structure array, this structure records all the services contained in the name of the service and the entry point function, below is a service_ Examples of table_entry:
SERVICE_TABLE_ENTRY service_table_entry[] =
{
{ "MyFTPd" , FtpdMain },
{ "MyHttpd", Httpserv},
{ NULL, NULL },
};
The first member represents the name of the service, and the second member is the address of the ServiceMain callback function, which has three service_table_entry elements because it has two services, and the first two are used for the service, and the last null indicates the end of the array.
The address of this array is then passed to the StartServiceCtrlDispatcher function:
BOOL StartServiceCtrlDispatcher(
LPSERVICE_TABLE_ENTRY lpServiceStartTable
)
This Win32 function shows how the executable process notifies the SCM of the services included in the process. As is said in the previous chapter, StartServiceCtrlDispatcher produces a new thread for every non-empty element in the array that is passed to it. Each process begins executing the ServiceMain function specified by lpservicestarttable in the array element.
After the SCM starts a service program, it waits for the main thread of the program to tune the StartServiceCtrlDispatcher. If the function is not invoked within two minutes, SCM will consider the service problematic and invoke terminateprocess to kill the process. This requires your main thread to call StartServiceCtrlDispatcher as fast as possible.
The StartServiceCtrlDispatcher function does not return immediately, instead it resides in a loop. When inside the loop, StartServiceCtrlDispatcher hangs himself, waiting for one of the following two events to occur. First, the thread activates if the SCM is going to send a control notification to a service running within the process. When the control notification arrives, the thread activates and invokes the Ctrlhandler function of the corresponding service. The Ctrlhandler function handles this service control notification and returns to StartServiceCtrlDispatcher. StartServiceCtrlDispatcher cycle back and hang yourself once again.