Windows System Programming Third Edition


The ServiceMain() Functions



Download 3.41 Mb.
Page18/31
Date31.07.2017
Size3.41 Mb.
#24970
1   ...   14   15   16   17   18   19   20   21   ...   31

The ServiceMain() Functions


These functions are specified in the dispatch table, as shown in Program 13-1, and represent logical services. The functions are essentially enhanced versions of the base program that is being converted to a service, and each logical service will be invoked on its own thread by the SCM. A logical service may, in turn, start up additional threads, such as the server worker threads that were used in serverSK and serverNP. Frequently, there is just one logical service within a service. In Program 13-2, the logical service is adapted from the main server shown in Program 12-2. It would be possible, however, to run both socket and named pipe logical services under the same Windows service, in which case two service main functions would be supplied.

While the ServiceMain() function is an adaptation of a main() function with argument count and argument string parameters, there is one small change. The function should be declared void rather than having an int return value the way that a normal main() function would.

Extra code is required to register the service control handler, which is a function called by the SCM to control the services.

Registering the Service Control Handler


A service control handler, called by the SCM, must be able to control the associated logical service. The console control handler in serverSK, which sets a global shutdown flag, illustrates, in limited form, what is expected of a handler. First, however, each logical service must immediately register a handler using the RegisterServiceCtrlHandlerEx function. The function call should be at the beginning of ServiceMain() and not called again. The SCM, after receiving a control request for the service, calls the handler.

SERVICE_STATUS_HANDLE

RegisterServiceCtrlHandlerEx (

LPCTSTR lpServiceName,

LPHANDLER_FUNCTION_EX lpHandlerProc,

LPVOID lpContext)


Parameters

lpServiceName is the user-supplied service name provided in the service table entry for this logical service.

lpHandlerProc is the address of the extended handler function, which will be described in a later section. The extended handler form was added to NT5, with RegisterServiceCtrlHandlerEx superseding RegisterServiceCtrlHandler. The next parameter was also added to NT5.

lpContext is user-defined data passed to the control handler. This allows a single control handler to distinguish between multiple services using the same handler.

The return value, which is a SERVICE_STATUS_HANDLE object, is 0 if there is an error, and the usual methods can be used to analyze errors.


Setting the Service Status


Now that the handler is registered, the next immediate task is to set the service status to SERVICE_START_PENDING using SetServiceStatus. SetServiceStatus will also be used in several other places to set different values, informing the SCM of the service's current status. A later section and Table 13-3 describe the valid status values in addition to SERVICE_START_PENDING.
Table 13-3. Controls That a Service Accepts (Partial List)

Value

Meaning

SERVICE_ACCEPT_STOP

Enables the SERVICE_CONTROL_STOP.

SERVICE_ACCEPT_PAUSE_CONTINUE

Enables SERVICE_CONTROL_PAUSE and SERVICE_CONTROL_CONTINUE.

SERVICE_ACCEPT_SHUTDOWN (The ControlService function cannot send this control code.)

Notifies the service when system shutdown occurs. This enables the system to send a SERVICE_CONTROL_SHUTDOWN value to the service.

SERVICE_ACCEPT_PARAMCHANGE

Requires NT5. The startup parameters can change without restarting. The notification is SERVICE_CONTROL_PARAMCHANGE.

The service control handler must set the status every time it is called, even if there is no status change.

Furthermore, any of the service's threads can call SetServiceStatus at any time to report progress, errors, or other information, and services frequently have a thread dedicated to periodic status updates. The time period between status update calls is specified in a member field in a data structure parameter. The SCM can assume an error has occurred if a status update does not occur within this time period.

BOOL SetServiceStatus (

SERVICE_STATUS_HANDLE hServiceStatus,

LPSERVICE_STATUS lpServiceStatus)

Parameters

hServiceStatus is the SERVICE_STATUS_HANDLE returned by RegisterServiceCtrlHandlerEx. The RegisterServiceCtrlHandlerEx call must, therefore, precede the SetServiceStatus call.

lpServiceStatus, pointing to a SERVICE_STATUS structure, describes service properties, status, and capabilities.


The SERVICE_STATUS Structure


The SERVICE_STATUS structure is defined as follows:

typedef struct _SERVICE_STATUS {

DWORD dwServiceType;

DWORD dwCurrentState;

DWORD dwControlsAccepted;

DWORD dwWin32ExitCode;

DWORD dwServiceSpecificExitCode;

DWORD dwCheckPoint;

DWORD dwWaitHint;

} SERVICE_STATUS, *LPSERVICE_STATUS;


Parameters

dwWin32ExitCode is the normal thread exit code for the logical service. The service must set this to NO_ERROR while running and on normal termination.

dwServiceSpecificExitCode can be used to indicate an error while the service is starting or stopping, but this value will be ignored unless dwWin32ExitCode is set to ERROR_SERVICE_SPECIFIC_ERROR.

dwCheckPoint should be incremented periodically by the service to report its progress during all steps, including initialization and shutdown. This value is invalid and should be 0 if the service does not have a start, stop, pause, or continue operation pending.

dwWaitHint, in milliseconds, is the elapsed time between calls to SetServiceStatus with either an incremented value of dwCheckPoint value or a change in dwCurrentState. As mentioned previously, the SCM can assume that an error has occurred if this time period passes without such a SetServiceStatus call.



The remaining SERVICE_STATUS members are now described in individual sections.
Service Type

dwServiceType must be one of the values described in Table 13-1.
Table 13-1. Service Types

Value

Meaning

SERVICE_WIN32_OWN_PROCESS

Indicates that the Windows service runs in its own process with its own resources. Used in Program 13-2.

SERVICE_WIN32_SHARE_PROCESS

Indicates a Windows service that shares a process with other services so that several services can share resources, environment variables, and so on.

SERVICE_KERNEL_DRIVER

Indicates a Windows device driver.

SERVICE_FILE_SYSTEM_DRIVER

Specifies a Windows file system driver.

SERVICE_INTERACTIVE_PROCESS

Indicates a Windows Service process that can interact with the user through the desktop.

For our purposes, the type is almost always SERVICE_WIN32_OWN_PROCESS, but the different values indicate that services play many different roles.
Service State

dwCurrentState indicates the current service state. Table 13-2 shows the different possible values.
Table 13-2. Service State Values

Value

Meaning

SERVICE_STOPPED

The service is not running.

SERVICE_START_PENDING

The service is in the process of starting but is not yet ready to respond to requests. For example, the worker threads have not yet been started.

SERVICE_STOP_PENDING

The service is stopping but has not yet completed shutdown. For example, a global shutdown flag may have been set, but the worker threads have not yet responded.

SERVICE_RUNNING

The service is running.

SERVICE_CONTINUE_PENDING

The service continue is pending after a service has been in the pause state.

SERVICE_PAUSE_PENDING

The service pause is pending, but the service is not yet safely in the pause state.

SERVICE_PAUSED

The service is paused.


Controls Accepted

dwControlsAccepted specifies the control codes that the service will accept and process through its service control handler (see the next section). Table 13-3 enumerates four of the possible values, and the appropriate values should be combined by bit-wise "or" (|). The service version of serverSK, developed later, will accept only the first three values. Additional values are described in the MSDN entry for SERVICE_STATUS.

Service-Specific Code


Once the handler has been registered and the service status has been set to SERVICE_START_PENDING, the service can initialize itself and set its status again. In the case of converting serverSK, once the sockets are initialized and the server is ready to accept clients, the status should be set to SERVICE_RUNNING.

прямоугольник 1



Directory: bitstream -> NAU
bitstream -> A mathematical theory of communication
bitstream -> Images of Fairfax in Modern Literature and Film Andrew Hopper
bitstream -> Amphitheater High School’s Outdoor Classroom: a study in the Application of Design
bitstream -> Ethics of Climate Change: Adopting an Empirical Approach to Moral Concern
bitstream -> The Age of Revolution in the Indian Ocean, Bay of Bengal and South China Sea: a maritime Perspective
bitstream -> Methodism and Culture
bitstream -> Review of coastal ecosystem management to improve the health and resilience of the Great Barrier Reef World Heritage Area
bitstream -> Present state of the area
NAU -> International significance of icao alphabet for flight safety
NAU -> Performance comparison of android runtime and dalvik environments on an android device

Download 3.41 Mb.

Share with your friends:
1   ...   14   15   16   17   18   19   20   21   ...   31




The database is protected by copyright ©ininet.org 2024
send message

    Main page