After you create one or more COM classes, you need to package the classes and install them on a system. The package is called a COM Server, which is a dynamically activated collection of the implementations of one or more COM classes. Modern Win32 versions of COM enable you to create a COM server as an in-process (inproc) server (a dynamic link library), an out-of-process server (an executable), or, on the Windows NT/2000/XP/2003 operating system, a system service executable.
A COM server has three jobs, in addition to hosting the implementations of its classes:
Technically, the first and third items are optional, but all COM servers should implement this functionality. Exactly how a server does this depends on the type of server.
An inproc server is a dynamic link library (DLL) that contains five well-known entry points, one for the Win32 operating systems and the other four for COM:
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved); STDAPI DllRegisterServer(void); STDAPI DllUnregisterServer(void); STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv); STDAPI DllCanUnloadNow(void);
Each of the Win32 operating systems calls a DLL's DllMain function when it loads a DLL into a process and removes a DLL from a process. The operating system also calls DllMain each time the current process creates a new thread and when a thread terminates cleanly. This function is optional but present in all ATL inproc servers.
The DllRegisterServer and DllUnregisterServer functions create and remove, respectively, in the Windows Registry all entries necessary for the correct operation of the server and its classes. When you use the REGSVR32 utility to register or unregister an inproc server, the utility loads the DLL and calls the appropriate one of these function in the DLL. Technically, both of these functions are optional, but, in practice, you want to have them in your server.
The COM SCM calls a server's DllGetClassObject function when it requires a class object exposed by the server. The server should return the requested interface, riid, on the specified class object, rclsid.
When you call the CoFreeUnusedLibraries API, COM asks each inproc server in your process whether COM should unload the DLL by calling the DllCanUnloadNow function. An S_OK return value means that the server permits COM to unload the server. An S_FALSE return value indicates that the server is busy and COM cannot unload it.
Local Servers and Service-Based Servers
A local server or Windows service is an executable image (EXE) server that contains one well-known entry point:
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd);
Executables cannot provide multiple specialized entry points as DLLs can, so a local server must use a different technique to implement the three requirements of a COM server: registration, exposed class objects, and lifetime management.
A local server registers and unregisters itself, and then immediately terminates when the server parses its command line and finds the well-known (noncase-sensitive) command-line switches Regserver and UnregServer, respectively.
A local server exposes its class objects by calling the CoRegisterClassObject API and handing an IUnknown interface pointer to each of the server's class objects to the SCM. A local server must call this API after the SCM starts the server process. When the server is ready to shut down, it must first call CoRevokeClassObject to notify the SCM that each of the server's class objects is no longer available for use.
A local server manages its own lifetime. When a server detects that there are no references to any of the objects managed by the server, the server can shut downor not, as desired. As you'll see later in this chapter, detecting that there are no references is a little trickier than you might think.
COM Createable and Noncreateable Classes
A COM createable class is a COM object class that supports using the CoCreateInstance API to create instances. This implies that the class must provide a class object and that the class object implements the IClassFactory interface.
A noncreateable class typically provides no class object, so calling CoCreateInstance using the class's CLSID fails. In many designs, far more noncreateable classes exist than createable ones. For example, one version of Microsoft Excel had approximately 130 classes, only 3 of which were createable. You typically access interfaces on noncreateable classes through properties or methods on createable classes or on classes that have already been created by other means.