<!-- Add the rest of your HTML here -->
The ClassFactory is the one of the major concepts in COM. COM provides various ways to control the creation process of the component. Proper understanding of the class factory will help programmers design COM components (i.e. coclass) and their corresponding class objects (i.e. class factories) in a better way. This article will cover the importance of class factories and an example which implements a single class object for multiple COM classes.
A class factory is a component whose main purpose is to create other components. A class object is also known as a class factory (class object and class factory are interchangeable) whose main purpose is to create the other components by implementing the standard interface called
IClassFactory. Don’t get confused with the techy terms as different authors use different terminologies for explanation.
COM provides a generic way of creating the components. All the components are created in a similar manner.
CoCreateInstance doesn’t provide the control on the creation process of the component. When
CoCreateInstance returns, the component has already been created in memory and hence you have no control over the creation process of the component.
IClassFactory provides much more control over the creation process of the component, however it is much more confusing than
CoCreateInstance. This can be considered as the price a programmer has to pay to get better control over the creation process.
CoCreateInstance provides a wrapper over the
CreateInstance methods of the
CoCreateInstance internally creates a class factory for the specified
CLSID, gets the
IClassFactory interface pointer and then creates the component by calling
CreateInstance on the
IClassFactory interface pointer. It then returns the requested interface pointer to the client by calling the
QueryInterface method in the
CreateInstance method of
Object Creation Process
, which provides an interface pointer on a class object associated with a CLSID, needs an entry point in the DLL to create the component’s class factory. In most cases the class factory is implemented along with the component in the same DLL. The entry point is called
, which creates the class factory. The client initiates the creation process by calling the
looks for a component in the system registry. If it finds the component, it loads the COM server, i.e. DLL, into a memory and then calls
. The purpose of
is to create the class object by calling the new operator for a class object.
queries the class object for the
interface, which is returned to the client.
The client, after receiving the
IClassFactory interface pointer, calls the
CreateInstance method. The
IClassFactory::CreateInstance method calls the new operator to create the component. In addition to calling the new operator it also calls
QueryInterface on the component for the
As soon as the component is created and the interface (requested) pointer is returned to the client, the purpose of the class object (i.e. to create a component) is achieved and the client can release the class factory for that specific component (CLSID). The client can use the returned pointer on the component to call methods of that component.
Every COM DLL server should implement and export a function called
DllGetClassObject. If a COM DLL doesn’t provides
DllGetClassObject, then the call to
CoCreateInstance returns an error "Class Not Registered".
DllGetClassObject is an entry point which basically creates the class factory for the specific class (CLSID).
CoGetClassObject looks for a component in the registry and, if found, the component’s CLSID is passed as an argument to
CoGetClassObject. If it finds the server, then it loads the COM DLL server (calls
DllMain of the COM Server) that encapsulates that specific component. After loading the DLL,
CoGetClassObject tries to get the address of
DllGetClassObject (exported by the COM DLL) by calling the
GetProcAddress function. If that fails then the COM SCM returns an error called "Class Not Registered" because there is no way to create a class factory for the requested component.
Sample code explanation
In the sample code, a single class object has been implemented for multiple COM classes (COM components). There could be a one-to-one mapping between class object and COM component supported. In that case, the
should create a class object corresponding to the requested CLSID. This case is easy as we can have a multiple
cases in the
and can call a
operator for the class object corresponding to a requested CLSID.
The purpose of the class object is to create another object (COM component), so the different class factory for different classes will cause the unnecessary duplication of code and makes code less readable. The COM server can be designed in such a way that the single class object should be able to support multiple COM components. This is what has been implemented in the sample code.
This has been achieved by the use of the helper function (creator function), which every COM class must support for its creation. There is a structure called
FactoryInfo, which maps the creation function with the corresponding CLSID for all the COM classes that are exposed by the COM server.
const CLSID *pCLSID;
When the client calls
function is called with the requested CLSID as an argument. The
function looks into the global array of
structures and traverses the array to fetch the address of the creator function, which is mapped to the requested CLSID. The class factory class stores this address in one of its data members, called
type. This stored address of the creation function in the
class is used in the
method of the
interface. The address of the creator function is passed to the
at the time of its creation by passing an argument of
type in the constructor of
for (int iCount = 0; iCount < 2; iCount++)
if (*gFactoryData[iCount].pCLSID == clsid)
CFactory *pFactory = new CFactory(gFactoryData[iCount].pFunc);
The above code is a part of the
function. This function traverses the global array of
structures and looks for the creation functions address corresponding to the requested CLSID. Once it gets the address of the creator function, it stops traversing the array and passes that address to the constructor of the CFactory class.
CFactory stores this address of the creator function for further use. Once the
IClassFactory interface on the class object is returned to the client the client can call the
CreateInstance method of the
IClassFactory to create an instance of the COM class. The
CreateInstance call is the place where the COM component is created and the requested interface is returned on that newly created COM components instance. The creator function, whose address has been stored in
CFactory’s (class object) data member, is called in the
CreateInstance method and the requested interface is returned to the client.
typedef HRESULT (*FPCOMPCREATOR) (const IID&, void**);
class CFactory : public IClassFactory
This is a call to the creator function in the
method of the
hResult = (*pCreator)(iid,ppv);
is a synonym for a "pointer to a function which takes const IID & and void** as an argument and returns an HRESULT".
The code has been commented properly to make it self-explanatory. The single class object for multiple COM classes will help you grasp the Class Factory concept in COM.