CoGetClassObject

HRESULT CoGetClassObject(clsid, grfContext, pServerInfo, iid, ppv)

Locate and connect to the class factory object associated with the class identifier clsid. If necessary, the COM Library dynamically loads executable code in order to accomplish this. The interface by which the caller wishes to talk to the class factory object is indicated by iid; this is usually IID_IClassFactory but can, of course, be any other object-creation interface.2. The class factory's interface is returned in ppv with one reference count on it on behalf of the caller, that is, the caller is responsible for calling Release after it has finished using the class factory object.

Different pieces of code can be associated with one CLSID for use in different execution contexts such as in-process, local, or object handler. The context in which the caller is interested is indicated by the grfContext parameter, a group of flags taken from the enumeration CLSCTX:


typedef enum tagCLSCTX {
.....CLSCTX_INPROC_SERVER..........= 1,
.....CLSCTX_INPROC_HANDLER.....= 2,
.....CLSCTX_LOCAL_SERVER..........= 4,
.....CLSCTX_REMOTE_SERVER..........= 16.
.....} CLSCTX;

The several contexts are tried in the sequence in which they are listed here. Multiple values may be combined (using bitwise OR) indicating that multiple contexts are acceptable to the caller:


#define CLSCTX_INPROC .....(CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER)
#define CLSCTX_SERVER .....(CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
#define CLSCTX_ALL..........(CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)

These context values have the following meanings which apply to all remote servers as well:

Value

Action Taken by the COM Library

CLSCTX_INPROC_SERVER

Load the in-process code (.DLL) which creates and completely manages the objects of this class. If the .DLL is on a remote computer, invoke a surrogate server as well to load the .DLL.

CLSCTX_INPROC_HANDLER

Load the in-process code (.DLL) which implements client-side structures of this class when instances of it are accessed remotely. An object handler generally implements object functionality which can only be implemented from an in-process module, relying on a local server for the remainder of the implementation.3.

CLSCTX_LOCAL_SERVER

Launch the separate-process code (.EXE) which creates and manages the objects of this class. 4..

CLSCTX_REMOTE_SERVER

Launch the separate-process code (.EXE) on another computer which creates and manages objects of this class.


The COM Library should attempt to load in-process servers first, then in-process handlers, then local servers, then remote servers. This order helps to minimize the frequency with which the library has to launch separate server applications which is generally a much more time-consuming operation than loading a .DLL, especially across the network.

When specifying CLSCTX_REMOTE_SERVER, the caller may pass a COMSERVERINFO structure to indicate the computer on which to run the server module, which is defined as follows:


typedef struct tagCOMSERVERINFO {
.....OLECHAR.....*szRemoteSCMBindingHandle;
.....} COMSERVERINFO;5.

The COM Library implementation of this CoGetClassObject relies on the system registry to map the CLSID to the server module to load or launch, but this process is opaque to the client application. If, however, COM cannot make any association then the function fails with the code REGDB_E_CLASSNOTREG. If this function launches a server application it must wait until that server registers its class factory or until a time-out occurs (duration determined by COM, something on the order of a minute of processing time). See the CoRegisterClassObject function in Chapter 6 under "Exposing the Class Factory from Local Servers."

The arguments to this function are as follows:

Argument

Type

Description

clsid

REFCLSID

The class of the class factory to obtain.

grfContext

DWORD

The context in which the executable code is to run.

pServerInfo

COMSERVERINFO*

Identifies the computer on which to activate the executable code. Must be NULL when grfContext does not contain CLSCTX_REMOTE_SERVER. When NULL and grfContext contains CLSCTX_REMOTE_SERVER, COM uses the default computer location for this class.

iid

REFIID

The interface on the class factory object desired by the caller.

ppv

void **

The place in which to put the requested interface.


Return Value

Meaning

S_OK

Success.

REGDB_E_CLASSNOTREG

An implementation of the requested class could not be located.

E_OUTOFMEMORY

Memory could not be allocated to service the request.

E_UNEXPECTED

An unknown error occurred.


The following code fragment demonstrates how a client would call CoGetClassObject and create an in-process instance of the TextRender object with CLSID_TextRender using the class factory to request an IUnknown pointer for the object. In this example the client is explicitly limiting COM to use only in-process servers:


IClassFactory *.....pCF;
IUnknown *      .....pUnkObj;
HRESULT        .....hr;

hr=CoGetClassObject(CLSID_TextRender, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void *)pCF);
if (FAILED(hr))
.....//Could not obtain class factory, creation fails completely.

/*
 * Create the object. If this call succeeds the pUnkObj will 
 * be valid and have a reference count on it on behalf of the caller
 * which the caller must Release.
 */
hr=pCF->CreateInstance(NULL, IID_IUnknown, (void *)pUnkObj);

//Caller must call Release regardless of CreateInstance result
pCF->Release();

if (FAILED(hr))
.....//Object creation failed: interface may not be supported

/*
 * Now use the object in whatever capacity the caller desires.
 * The first step will be initialization.
 */

//Release the object when finished with it.
pUnkObj->Release();

Since the process of calling CoGetClassObject, IClassFactory::CreateInstance, and IClassFactory::Release is so common in practice, the COM Library provides a wrapper API function for this sequence called CoCreateInstance. This allows the client to avoid the whole issue of class factory objects entirely. However, CoCreateInstance only creates one object at a time; if the client wants to create multiple objects of the same class at once, it is more efficient to obtain the class factory directly and call IClassFactory::CreateInstance multiple times, avoiding excess calls to CoGetClassObject and IClassFactory::Release.