Introduction

This article explains about different parts of an NT service and inter-process communication using Mailslots.

Different Aspects of an NT Service

Major aspects that need to be covered when writing an NT service are detailed out below. Following are the major aspects that are covered in this article:

Creating/Registering a service

Removing a service

Registering ServiceMain()

ServiceHandler()

Setting Service status

1) Creating/Registering a Service

Service can be created by opening the SCM. This is generally done in the WinMain() or main() function based on a command line parameter that is passed. OpenSCManager() will give the SCM handle. With this handle, CreateService() will have to be called to get the service created.

Once the service EXE is ready, to create the service, go to command prompt and move to the directory where the service binary is present and type the following: SigmaSrv /register. Calls within the binary to create the service are shown below:

2) Removing a Service

Similar to creating a service, removing a service is also initiated based on the command line argument. In this case also SCM will have to be opened using OpenSCManager(), followed by opening the service with all rights using OpenService(). Then DeleveService() will have to be called to delete the service.

To remove the service, go to command prompt and move to the directory where the service binary is present and type the following: SigmaSrv /unregister. Calls within the binary to get this done are shown below:

3) Registering ServiceMain()

ServiceMain() is a callback function and the starting point for a service. Reference to ServiceMain() is given via a call to StartServiceCtrlDispatcher()in WinMain(). SERVICE_TABLE_ENTRY structure is used to pass the service name and its associated starting point (ServiceMain() in this case) through the StartServiceCtrlDispatcher() call.

There could be multiple services housed in the same service via this structure. {NULL, NULL} is required to mark the end of this array. ServiceMain() function can have any name you wish, it need not be ServiceMain() always. Calls to register ServiceMain() are shown below. This is done in WinMain():

4) SeviceHandler()

ServiceHandler is another callback function which is registered in ServiceMain() by calling RegisterServiceCtrlHandler(). This is done within the ServiceMain() function. This function calls the user defined service functions based on the control requests received (Example: control request to stop the service, pause the service, etc.). Arguments for RegisterServiceCtrlHandler() are the service name and the ServiceHandler() proc name. Here also ServiceHandler() can be given any name. Call to register the ServiceHandler() is shown below:

5) Setting Service Status

SetServiceStatus() should be called to set the status of the service. This is required for the SCM to correctly understand the status of the service. In this article's source, SetServiceStatus() is encased in the function SetSigmaServiceStatus().

Mailslot

To show that the service is running, mailslots had been made use of in this sample. Mailslot is an interprocess communication mechanism. Service will periodically update its status into the status bar of a client application. This client application is available on CodeProject at the following location: Sigma.aspx. (Please bear with me till the client application is updated.)

Client will have the mailslot open and this service will keep updating its status into the mailslot. It is up to the client to read this on a periodic basis and display/convey the information to the user.

Service opens the mailslot using CreateFile() and keeps writing its status message into mailslot using WriteFile(). In the sample, WriteFile() is encased in the function PostToMailSlot(). Following is the code snippet that the service uses: