Chapter 6: COM Servers
As described in earlier chapters, a COM Server is some module of code, a .DLL or an .EXE, that implements one or more object classes (each with their own CLSID). A COM server structures the object implementations such that COM clients can create an use objects from the server using the CLSID to identify the object through the processes described in Chapter 5.
In addition, COM servers themselves may be clients of other objects, usually when the server is using those other objects to help implement part of its own objects. This chapter will cover the various methods of using an object as part of another through the mechanisms of containment and aggregation.
Another feature that servers might support is the ability to emulate a different server of a different CLSID. The COM Library provides a few API functions to support this capability that are covered at the end of this chapter.
If the server is an application, that is, an executable program, then it must follow all the requirements for a COM Application as detailed in Chapter 4. If the server is a .DLL, that is, an in-process server or an object handler, it must at least verify the library version and may, if desired, insure that the COM Library is initialized. That aside, all servers generally perform the following operations in order to expose their object implementations:
- Allocate a class identifier—a CLSID—for each supported class and provide the system with a mapping between the CLSID and the server module.
- Implement a class factory object with the IClassFactory interface for each supported CLSID.
- Expose the class factory such that the COM Library can locate it after loading (.DLL) or launching (.EXE) the server.
- Provide for unloading the server when there are no objects being served and no locks on the server (IClassFactory::LockServer).
Of course, there must be some object to serve, so the first section of this chapter discusses the basic structure of an object and some considerations for design. The sections that follow then cover the functions involved in each of these steps for the different styles of servers—.DLL and .EXE—which apply regardless of whether the server is running on a remote computer. Also included is a discussion of object handlers (special-case in-process objects) before the discussion of aggregation. Note that no new interfaces are introduced in this chapter as the fundamental ones, IUnknown and IClassFactory, have already been covered.
As far as the server is concerned, the COM Library exists to drive the server's class factory to create objects and to handle remote method calls from clients in other processes or on other computers and to marshal the object's return values back to the client. Whereas client applications are unaware of the object's execution context once the object is created, the server is, of course, always aware of that context. An in-process object is always loaded into the client's process space. A local or remote object always runs in a process other than the client, or on a different computer. However, the actual object itself can be written such that it does not need to care about the execution context, leaving the specifics to the structure of the server module instead. This chapter will cover one such strategy.
Finally, recall from the beginning of Chapter 5 that a client always makes a call into some in-process object whenever it calls any interface member function. If the actual object in the server is local or remote, that object is merely a proxy that generates the appropriate remote method call to the true object. This does not mean a server has to understand RPC, however, as the server always sees these calls as direct calls from a piece of code in the server process. The mechanism that achieves this, described in Chapter 7, "Communicating via Interfaces: Remoting," is that the RPC call is picked up in the server process by an stub object which translate the RPC information into the direct call to the server's object. From the server's point of view, the client called it directly.
You can read through this chapter, or you can choose a topic of interest from this list:
- Identifying and Registering an Object Class
- Implementing the Class Factory
- Exposing the Class Factory
- Providing for Server Unloading
- Object Handlers
- Object Reusability
- Emulating Other Servers