Developing a COM server involves myriad issues, including creating class objects for your COM classes, registering your COM classes in the Registry, providing a way for external clients to get to your class objects, and taking care of the server lifetime issues. For example, if you're creating a COM DLL, you need to write several functions that the COM run time expects to see, including DllGetClassObject, DllRegisterServer, and DllUnregisterServer. You must provide your COM class with a reference count so that it can track the number of outstanding objects it's still serving. You also need to export DllCanUnloadNow. If you're creating a COM-based EXE server, you must register your class objects at run time using CoRegisterClassObject and check the command line for the /RegServer or /UnRegServer switches. An EXE server also needs to maintain a reference count and notify itself when the object reference count drops to 0.
All this requires the developer to pump out a lot of code. As it turns out, much of the code necessary for writing COM code is boilerplate. Of course, that's why there's ATL. ATL takes a load off developers who are creating new COM-based servers by implementing most of the boilerplate code required to develop COM classes and servers.
In addition to supporting basic COM classes, ATL also serves as a lightweight alternative to MFC for writing Microsoft ActiveX controls (which are just COM classes with a bunch of interfaces hanging off of them). Although MFC continues to be the most convenient way to write ActiveX controls using C++ (using Microsoft Visual Basic is probably the most convenient means overall), MFC has a downside. The most difficult-to-swallow aspect of MFC is its run-time DLL, which must accompany an ActiveX control wherever it goes. An ActiveX control usually doesn't need all the functionality available in the MFC DLL. However, the control has to carry around the entire enchilada just to work. For example, ActiveX controls require support for programming concerns such as IDispatch and window messaging, but they don't necessarily require everything else MFC provides, such as dialogs.
Because ATL is a template library, the chunks of code absolutely necessary for COM classes to work are brought in via template inheritance rather than normal C++ implementation inheritance. Templates actually copy bits of code into your class. You can customize templates by using template parameters. As a result, code compiled using templates tends to be a bit larger but more self-contained than normal C++ code (so the huge run-time DLL isn't necessary).
Creating a COM-based server in ATL is a simple matter of exercising the ATL COM AppWizard. Just select New from the File menu and choose ATL COM AppWizard. Figure 9-1 illustrates the ATL COM AppWizard.
Figure 9-1. The ATL COM AppWizard.
Once you're confronted with this dialog box, you've got several options to choose from. For starters, you can select a COM-based DLL, a COM-based EXE, or a COM-based service. Each of these options produces the correct code for the given context. Let's start by taking a look at what you get with an ATL-based DLL, which is a special type of COM-based DLL.