Introduction
Let's ensure we understand the foundational concepts before delving further into the subjects. Here is a brief introduction if you are unfamiliar with the Active Template Library.

Active Template Library (ATL), a collection of C++ classes built using templates, makes programming Component Object Model (COM) objects easier. For building and consuming software components on Windows, COM is a binary specification. It is strongly advised to be familiar with COM to better use ATL.
This article explains the details of ATL Services, in which we will talk about The CAtlServiceModuleT::Start Function, The CAtlServiceModuleT::ServiceMain Function, The CAtlServiceModuleT::Run Function, and The CAtlServiceModuleT::Handler Function.
Without further ado, let's get started.
Also read about, Abstract Data Types in C++ and Application of Oops
ATL Services
Simply choose Service (EXE) from the list of server choices in the ATL Project Wizard to create your ATL COM object so that it operates as a service. To implement the service, the wizard will provide a class derived from CAtlServiceModuleT.
The ATL COM object will only be registered as a local server when constructed as a service, and it won't appear in the Control Panel's list of services. This is so that the service may be more easily debugged as a local server rather than a service. At the command prompt, enter the following commands to set it up as a service:
YourEXE .exe /Service
Run the following commands to uninstall it:
YourEXE .exe /UnregServer

The CAtlServiceModuleT::Start Function
To run the service, _tWinMain calls CAtlServiceModuleT::WinMain, which then calls CAtlServiceModuleT::Start.
CAtlServiceModuleT::Start sets up an array of SERVICE_TABLE_ENTRY structures to map each service to its startup function. After that, the Win32 API method StartServiceCtrlDispatcher receives this array as input. One EXE might theoretically manage numerous services, and the array may include numerous SERVICE_TABLE_ENTRY structures. However, an ATL-generated service currently only allows for one service per EXE. The service name and _ServiceMain, the launch method, are both contained in a single item of the array. ServiceMain is a non-static member function called by _ServiceMain, a static member function of CAtlServiceModuleT.
💻 When the service is started, CAtlServiceModuleT::WinMain is called.
HRESULT Start(int nShowCmd) throw();
☑️ Parameters
- nShowCmd: Specifies the display method for the window. One of the values mentioned in the WinMain section can apply to this parameter.
✅ Return Value
Returns an error HRESULT on failure and S_OK on success.
The CAtlServiceModuleT::ServiceMain Function
When you run the Services Control Panel program, choose the service, and click Start, the service control manager (SCM) calls ServiceMain.
A service must provide the SCM with a handler function once the SCM calls ServiceMain. The SCM can use this function to find out the status of the service and send commands (such as pausing or stopping). When the service calls the Win32 API function RegisterServiceCtrlHandler with the argument _Handler, the SCM receives this function.
The SCM should be informed of the service's current condition at starting. It accomplishes this by sending SERVICE START PENDING to the SetServiceStatus Win32 API method.
The Win32 API method CoInitializeEx is called by ServiceMain, which subsequently calls CAtlExeModuleT::InitializeCom. By default, the COINIT MULTITHREADED flag is passed to the function by InitializeCom. This flag designates the application as a free-threaded server.
The primary function of the service is now carried out by calling CAtlServiceModuleT::Run. Until the service is terminated, the Run keeps running.
💻 The Service Control Manager uses this mechanism.
void Service_Main(DWORD dwArgc, LPTSTR* lpszArgv) throw();
☑️ Parameters
- dwArgc: The argc argument.
- lpszArgv: The argv argument.
The CAtlServiceModuleT::Run Function
Run includes calls to PreMessageLoop, RunMessageLoop, and PostMessageLoop. PreMessageLoop first saves the service's thread ID after receiving a call. By sending a WM QUIT message via the Win32 API function PostThreadMessage, the service will use this ID to shut down on its own.
Next, InitializeSecurity is called by PreMessageLoop. Because CoInitializeSecurity, by default, calls InitializeSecurity with the security descriptor set to NULL, any user can access your object.
If you override PreMessageLoop and don't use InitializeSecurity, COM will determine the security settings from the registry if you do not want the service to define its security. The DCOMCNFG application, which is covered later in this section, is a straightforward way to configure registry settings.
The object is registered with COM when security is specified so new clients can connect to the programme. The application then enters a message loop and notifies the service control manager (SCM) that it is operating. When the service is turned down, the program keeps running until it posts a quit message.
💻 Execute the service.
HRESULT Run(int nShowCmd = SW_HIDE) throw();
☑️ Parameters
- nShowCmd: Specifies the display method for the window. One of the values mentioned in the WinMain section can apply to this parameter.
✅ Return Value
Returns an error HRESULT on failure and S_OK on success.
The CAtlServiceModuleT::Handler Function
The procedure that the service control manager (SCM) calls to get the service's status and issue various directives is CAtlServiceModuleT::Handler (such as stopping or pausing). The SCM sends an operation code to tell the handler what to do. ATL-generated services, by default, only respond to the stop instruction. The service notifies the SCM that the program is about to terminate if the SCM passes the stop instruction. To publish a quitting message to itself, the service then runs PostThreadMessage. As a result, the message loop is broken, and the service eventually shuts down.
The m_status data member, initialised in the CAtlServiceModuleT function Object(), needs to be changed to handle more instructions. When the service is chosen in the Services Control Panel app, this data item instructs the SCM which buttons to enable.
💻 The service's handler process.
void Handler(DWORD dwOpcode) throw();
☑️ Parameters
- dwOpcode: A switch that specifies how the handler will work.




