The API Dance

Services have some unique qualities that will require some maneuvering on your part to accommodate. First, the entry point you use in services—main or WinMain—doesn't matter. Because your service doesn't have any user interface, you can use console or graphical user interface (GUI) entry points interchangeably.

Inside your main or WinMain processing, the first call you have to make is to the StartServiceCtrlDispatcher API function. You pass a SERVICE_TABLE_ENTRY structure to StartServiceCtrlDispatcher in which you indicate your service name and the main entry point of your service. The Service Control Manager (SCM), which starts all services and is what StartServiceCtrlDispatcher eventually talks to in order to set up your service, is an operating system feature that, as its name implies, controls all services. If your service doesn't call StartServiceCtrlDispatcher within 30 seconds of starting, the SCM will terminate your service. As you'll see later in the chapter, this time limit can make debugging startup a little more interesting.

As soon as you call into the SCM, the SCM spawns a thread to call your service's entry point. Your service's entry point has one hard requirement: it must register a handler with RegisterServiceCtrlHandlerEx and call SetServiceStatus within 82 seconds of starting. If your service doesn't make the calls within that time, the SCM thinks your service has failed, though it doesn't terminate the service. If your service eventually does call RegisterServiceCtrlHandlerEx, your service will run normally. Although you'd expect that the SCM would terminate your service if it thought your service had failed, it doesn't. Odd as this behavior is, it does make debugging as your service continues to run much easier.

RegisterServiceCtrlHandlerEx takes yet another pointer to a function, called the handler function. The SCM calls into the handler function to control your service's performance on operations such as stopping, pausing, or continuing.

When your service is transitioning from the states of starting, stopping, and pausing, it communicates with the SCM through the SetServiceStatus API function. Most services just need to call SetServiceStatus and indicate the basic state to which they're changing—there's nothing fancy about this API function.

I've glossed over a few of the details involved with the API functions, but basically the calls to StartServiceCtrlDispatcher, RegisterServiceCtrlHandlerEx, and SetServiceStatus are all that the operating system requires of your service to get it up and running. Notice that I didn't mention anything about requirements concerning communications protocols your service uses to communicate between a controller user interface you write and your service. Fortunately, services have access to all the regular Windows API functions, so you can use memory-mapped files, mail slots, named pipes, and so on. With services, you really have all the same options as you do in normal cross-process communications. The most challenging issue with services, as I pointed out at the beginning of the chapter, is security.

+1 0

Post a comment