October 1997 [Microsoft Systems Journal Homepage] -------------------------------------- Design a Windows NT Service to Exploit Special Operating System Facilities Jeffrey Richter A Windows NT service is a Win32-based executable. If you want to write a service and you are already familiar with DLLs, structured exception handling, memory-mapped files, virtual memory, and all the other staple facilities offered by the Win32 API, you will not have to learn much more. This article assumes you're familiar with Win32, Windows NT Jeffrey Richter wrote Advanced Windows, Third Edition (Microsoft Press, 1997) and Windows 95: A Developer's Guide (M&T Books, 1995). Jeff is a consultant and teaches Win32 programming courses (www.solsem.com). Have you ever wanted to write an application that could perform work for various clients, both local and remote? Suppose this app needs the ability to set the permission necessary to handle that work based on the client's authorization level. And say that this app has to execute whether or not a user is physically touching the computer on which it is running. What you need to create, then, is a Windows NT® service. [Image]In Windows NT, a service is a type of executable that gets special treatment from the operating system. This article describes what Windows NT service applications are, how to design them, and what additional facilities the operating system offers to services. [Image] First and foremost, a Windows NT service is a Win32® executable. If you want to write a service and you are already familiar with DLLs, structured exception handling, memory-mapped files, virtual memory, device I/O, thread-local storage, thread synchronization, Unicode, and all the other staple facilities offered by the Win32 API, you will not have to learn much more. All of these facilities are available to Windows NT services, and it should be relatively easy and straightforward for you to convert an existing application into a service. (The Windows NT Resource Kit contains a utility called SRVANY.EXE that allows you to run any Win32 application as a service, but it will not be able to take advantage of the special operating system features available to services.) [Image] The second thing you need to know when writing a service is that it should have absolutely no user interface. Most services will be running on a Windows NT Server machine locked away in a closet somewhere. If your service presents any user interface elements like message boxes, it's unlikely that a user will be in front of the machine to see the message box and dismiss it. Since you shouldn't have a user interface, it doesn't matter whether you choose to implement your service as a GUI application (with WinMain as its entry point) or as a console application (with main as its entry point). [Image] If a service doesn't present a user interface, how do you configure it? How do you start and stop a service? How does the service issue warnings or error messages, or report statistical data about its performance? The answer to all of these questions is that services can be remotely administered. Windows NT offers a number of administrative tools that allow a service to be managed from other machines connected on the network so you don't have to physically check the computer running the service. You are probably already familiar with many of these tools: the Services Control Panel applet, the Registry Editor (RegEdit.exe), the Event Viewer (EventVwr.exe), and the Performance Monitor (PerfMon.exe). [Image] Windows NT includes a number of services right out of the box. Figure 1 shows all of the services installed on my Windows NT Workstation machine and the name of the corresponding Win32 executable file that contains the code for the service. A Word about Security [Image] Depending on the service you are writing, you may have to be familiar with the Windows NT security architecture. I'll just go over the basics. On Windows NT, all security is user-based. In other words, all objects—processes, threads, files, registry keys, mutexes, semaphores, events, and so on—have a user as an owner. When a process is invoked, that process is usually executing in the context of a user who has an account on the machine/network or in the context of a special account called the System Account. [Image] If the process is executing under a user account, the threads in the process are allowed to touch any resources that the user has been granted access to. For example, users can read and write to a file on the local machine if they have been granted access to that file and they can also access a file on a networked machine if they are validated by the domain. [Image] The System Account identifies the operating system itself, and any process running under this account has full access to anything on the machine. For example, threads running in a System Account process can read from and write to any file on the machine. However, the System Account is never validated by the domain, so it has no access to network resources. [Image] There is an application called WinLogon.exe that the operating system starts as part of the boot process. WinLogon.exe runs under the System Account and is responsible for displaying the familiar Windows NT Logon dialog box. When a user enters her username and password, WinLogon.exe passes this information to the security database to validate the user. If the user is validated, WinLogon.exe runs the Explorer.exe application under the context of the logged-on user account. Any applications spawned from Explorer.exe will also run under the logged-on user account. A user who logs onto the system using the WinLogon dialog box is called an interactive user because she is physically accessing the machine using its keyboard and mouse. [Image] It is also possible for users to access a machine via the network. When a request comes to a machine via the network, the request can indirectly contain a username and password that can be checked against the security database to validate the user. If the user is validated, the thread that executed the security check can now impersonate the user. Impersonation means that the thread acts as if it is executing in a process that was run by the networked user. This thread is allowed to touch any resources that the networked user has been granted access to. A user that connects to a machine this way is called noninteractive because she isn't physically touching the computer's keyboard or mouse. [Image] Requests more often come from client software (usually running on Windows® 95 or Windows NT Workstation) into the server machine, and the user logged onto these machines becomes one of the many noninteractive users. [Image] The Three Service Components [Image] There are three types of components involved in making Windows NT services work. The first component is called the Service Control Manager (SCM, pronounced "scum"). Each Windows NT system ships with a SCM that lives in the Services.exe file. It is automatically invoked when the operating system boots, and terminates when the system is shut down. This process runs with system privileges and provides a unified and secure means of controlling Win32 services. The SCM is responsible for communicating with the various services, telling them to start, stop, pause, continue, and so on. [Image] The second component is the service itself. A service is simply a Win32 executable that contains the additional code necessary to receive information and commands from the SCM. A service also calls special functions that communicate its status back to the SCM. [Image] The third and last component is a service control program (SCP), a Win32 application that presents a user interface allowing the user to start, stop, pause, continue, and otherwise control all the services installed on a machine. The SCP calls special Win32 functions that let it talk to the SCM. The Services Control Panel applet (see Figure 2) is an SCP that Microsoft ships with Windows NT. [Figure 2 The Services Control Panel applet] [Image]Figure 2 The Services Control Panel applet [Image] In Figure 2, the Service column identifies the service's name, the Status column indicates whether the service is started, paused, or stopped (blank), and the Startup column indicates when the service is to be invoked. Using this window, you can command the SCM to start a stopped service, stop a started service, pause a started service, or continue a paused service. If you are manually starting a service, you can pass command-line arguments to the service by filling in the Startup Parameters edit box (but most services should not require command-line arguments). [Image] Of these three components, you are most likely to write the services themselves. It is also likely that you will have to write a companion client-side application that will talk to the SCM as an SCP. The bulk of this article describes how to design and implement a service. A future article will describe how to implement an SCP. [Image] You will never write the SCM itself; Microsoft has done this for you. Because the SCM is an RPC server, an SCP can communicate with it over a network to administer services remotely. An administrator using an SCP on machine A can have the SCM on machine B start, stop, and control a Win32 service running on machine B. [Image] In addition to the Services Control Panel applet, Windows NT also ships with a command-line SCP tool called NET.EXE. This tool is limited to controlling services residing on the local machine. Using NET.EXE, you can start, pause, continue, and stop services using the following syntax: NET START servicename NET PAUSE servicename NET CONTINUE servicename NET STOP servicename You can also use NET.EXE to display a list of services running on the local machine by simply typing NET START without specifying a servicename. [Image] If you want an SCP that allows you to administer services remotely, you can use the Server Manager (SrvMgr.exe) that ships with both Windows NT Server and the Windows NT Workstation Resource Kit. When you invoke the Server Manager, it displays a list of networked computers (see Figure 3). Selecting a machine and choosing the Services option from the Computer menu item causes SrvMgr.exe to display a window that looks just like the Services Control Panel applet's window. However, the content of the window reflects the status of the services installed on the selected machine. If you press the Start button, you will cause a service to start on the remote machine. [Figure 3 Windows NT Server Manager] [Image]Figure 3 Windows NT Server Manager [Image] Microsoft also offers a command-line SCP (SC.EXE) that comes with all versions of Windows NT Resource Kits. Running this tool without passing it any parameters displays its usage syntax, as shown in Figure 4. How a Service Starts [Image] In order for the SCM to start a service, information about the service must be added to the SCM's database. The SCM's database lives inside the registry under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services subkey. An application should not manipulate this registry subkey directly using the various registry functions. Instead, an SCP should call Win32 functions that tell the SCM to manipulate this database. When you purchase and install a product that includes a Win32 service, the Setup program for that product is an SCP that tells the SCM to add the information for that service to the SCM's database. [Image] Once the service is in the SCM's database, an SCP like the Services Control Panel applet will be able to enumerate the installed services and show you each service's current status. The Services Control Panel applet also lets you select when the service should start. Pressing the applet's Startup button displays a dialog box (shown in Figure 5) that allows you to configure how the service should start. This dialog box shows the name of the selected service at the top and allows you to adjust the startup type of the service. [Figure 5 Service Startup] [Image]Figure 5 Service Startup [Image] One of the benefits of writing a service versus a regular Win32 application is that the operating system can automatically start a service for you. In the SCM database, a service can be marked as an automatic service, which means that the operating system should automatically try to start the service when it boots. It's important to note that automatic services run before any user logs onto the machine interactively. In fact, many machines running Windows NT Server are set up to run services only, and no one ever logs onto the machine interactively. The Server service allows a client to access subdirectories, files, and printers on a networked machine. When Windows NT boots, the Server service starts automatically, and can therefore service requests from networked clients without anyone having to log onto the machine interactively. [Image] A service can also be marked as manual, which means that the operating system will not automatically start it, but a user can explicitly start the service. A manual service will also start if another service is started that depends on the manual service. (I'll go into more detail about service dependencies later.) Finally, a service can be marked as disabled, which means that it cannot start at all. For example, you would disable the DHCP Client service if you manually assigned an IP address to your machine rather than having it dynamically obtain an IP address from a machine running the DHCP Server service. [Image] In addition to the startup type, you are able to specify under which user account the service should execute. Most services run under the System Account (sometimes referred to as the Local System Account), which basically means that the service can do just about anything on the computer. If the service is running under the System Account, you can optionally check the Allow Service to Interact with Desktop option. This option is disabled for most services. [Image] Remember when I said that a service should not have a user interface because no one will be in front of the machine? A few special services do display a user interface. On my system, the Remote Access Connection Manager service and the Spooler service are the only two services that interact with the desktop. These two services are probably running on a machine controlled by a user. The Spooler service is responsible for sending data out of the machine to a printer. When the print job completes or if the printer is out of paper, the Spooler service notifies the user with a message box. For the user to see this message box, the Allow Service to Interact with Desktop option must be checked. [Image] When a service is running under the System Account, there is no user running the process... Continued in the October 1997 issue of Microsoft Systems Journal. Get it at your local newsstand, or better yet, subscribe. -------------------------------------- © 1997 Microsoft Corporation. All rights reserved. Terms of Use.