Managing Windows Services
Once a service has been written, the next task is to put the service under the control of the SCM so that it can be started, stopped, and otherwise controlled.Several steps are required to open the SCM, create a service under SCM control, and then start the service. These steps do not directly control the service; they are directives to the SCM, which in turn controls the specified service.
Opening the SCM
A separate process, running as "Administrator," is required to create the service, much as JobShell was used in Chapter 6 to start jobs. The first step is to open the SCM, obtaining a handle that then allows the service to be created.
SC_HANDLE OpenSCManager (
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAccess)
Parameters
lpMachineName is NULL if the SCM is on the local system, but you can also access the SCM on networked machines.lpDatabaseName is also normally NULL.dwDesiredAccess is normally SC_MANAGER_ALL_ACCESS, but you can specify more limited access rights, as described in the on-line documentation.
Creating and Deleting a Service
Call CreateService to register a service.
SC_HANDLE CreateService (
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCTSTR lpDependencies,
LPCTSTR lpServiceStartName,
LPCTSTR lpPassword);
New services are entered into the registry under:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
Parameters
hSCManager is the SC_HANDLE obtained from OpenSCManager.Table 13-1.dwStartType specifies how the service is started. SERVICE_DEMAND_START is used in our examples, but other values (SERVICE_BOOT_START and SERVICE_SYSTEM_START) allow device driver services to be started during bootup or at system start time, and SERVICE_AUTO_START specifies that a service is to be started at system start-up.lpBinaryPathName gives the service's executable; the .exe extension is not required.Other parameters specify account name and password, groups for combining services, and dependencies when there are several interdependent services.Service configuration parameters of an existing service can be changed with ChangeServiceConfig and, for NT5, ChangeServiceConfig2. The service is identified by its handle, and you can specify new values for most of the parameters. For example, you can provide a new dwServiceType or dwStartType value, but not a new value for dwAccess.There is also an OpenService function to obtain a handle to a named service. Use DeleteService to remove a service from the registry and CloseServiceHandle to close SC_HANDLEs.
Starting a Service
A service, once created, is not running. Start the ServiceMain() function by specifying the handle obtained from CreateService along with the argc, argv command line parameters expected by the service's main function (that is, the function specified in the dispatch table).
BOOL StartService (
SC_HANDLE hService,
DWORD argc,
LPTSTR argv [])
Controlling a Service
Control a service by telling the SCM to invoke the service's control handler with the specified control.
BOOL ControlService (
SC_HANDLE hService,
DWORD dwControlCode,
LPSERVICE_STATUS lpServStat)
dw ControlCode, if access permits, is one of the following:
SERVICE_CONTROL_STOPSERVICE_CONTROL_PAUSESERVICE_CONTROL_CONTINUESERVICE_CONTROL_INTERROGATESERVICE_CONTROL_SHUTDOWN
or a user-specified value in the range 128255. These are the same values as those used with the dwControl flag in the ServerCtrlHandler function.lpServStat points to a SERVICE_STATUS structure that receives the current status. This is the same structure as that used by the SetServiceStatus function.
Querying Service Status
Obtain a service's current status in a SERVICE_STATUS structure with the following:
BOOL QueryServiceStatus (
SC_HANDLE hService,
LPSERVICE_STATUS lpServiceStatus)