[Previous] [Contents] [Next]

Registering a Component Category

In contrast to component registration, where COM+ leaves it up to you to write the code that manually registers objects, component categories have a lot of built-in registration support. COM+ provides a coclass called the Component Categories Manager that implements the ICatRegister interface. Through this interface, a client application can create and manipulate component categories.

The ICatRegister Interface

You can use the six methods of the ICatRegister interface to define component categories and register coclasses that implement or require them. Remember that there is no reason to implement the ICatRegister interface; the Component Categories Manager already provides a satisfactory implementation. The following code shows the ICatRegister interface in IDL notation:

interface ICatRegister : IUnknown
{
// Register a new component category.
HRESULT RegisterCategories(
    [in] ULONG cCategories, 
    [in, size_is(cCategories)] CATEGORYINFO rgCategoryInfo[]);

// Remove an existing component category.
HRESULT UnRegisterCategories(
    [in] ULONG cCategories, 
    [in, size_is(cCategories)] CATID rgcatid[]);

// Register a CLSID as implementing a component category.
HRESULT RegisterClassImplCategories(
    [in] REFCLSID rclsid, 
    [in] ULONG cCategories, 
    [in, size_is(cCategories)] CATID rgcatid[]);

// Remove an implemented component category from the CLSID.
HRESULT UnRegisterClassImplCategories(
    [in] REFCLSID rclsid,
    [in] ULONG cCategories, 
    [in, size_is(cCategories)] CATID rgcatid[]);

// Register a CLSID as requiring a component category.
HRESULT RegisterClassReqCategories(
    [in] REFCLSID rclsid, 
    [in] ULONG cCategories, 
    [in, size_is(cCategories)] CATID rgcatid[]);

// Remove a required component category from the CLSID.
HRESULT UnRegisterClassReqCategories(
    [in] REFCLSID rclsid,
    [in] ULONG cCategories,  
    [in, size_is(cCategories)] CATID rgcatid[]);
}

To use the component category interfaces, you must include the comcat.h file in the source. The following code defines a new CATID, CATID_Math, which is implemented by the InsideCOM coclass:

#include <comcat.h> // For component category stuff

// CATID for the Arithmetic Objects category
CATID CATID_Math = 
    {0x10000010,0x0000,0x0000,
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

After making a call to CoInitializeEx, a client program can instantiate the Component Categories Manager object, which is identified as CLSID_StdComponentCategoriesMgr or with the GUID {0002E 005-0000-0000-C000-000000000046}. A quick scan of the registry reveals that this class is implemented by the in-process server ole32.dll, which is in the Windows\System folder. (In Microsoft Windows 2000, this file is in the WINNT\System32 folder.) COM+'s implementation of the component category interfaces is no different from an in-process component you might create. The following code retrieves a pointer to the ICatRegister interface:

// Instantiate COM+'s implementation of component categories.
ICatRegister* pCatRegister;
CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, 
    CLSCTX_INPROC_SERVER, IID_ICatRegister, 
    (void**)&pCatRegister);

To register the new component category, you build a CATEGORYINFO structure and then call the ICatRegister::RegisterCategories method. The CATEGORYINFO structure contains the CATID, a locale identifier (lcid) for localizing the descriptive string, and a string description of the new component category. This structure is shown below:

typedef struct tagCATEGORYINFO {
    CATID       catid;
    LCID        lcid;
    OLECHAR szDescription[CATDESC_MAX];
    } CATEGORYINFO, *LPCATEGORYINFO;

The Component Categories Manager in addition implements the IEnumCATEGORYINFO interface, which enumerates the CATIDs and description strings for the component categories registered on the current system.

After the new component category is registered, you can call the Release method to free the ICatRegister interface pointer. The following code is normally executed with other self-registration code in the component:

// Set up the CATEGORYINFO structure.
CATEGORYINFO catinfo;
catinfo.catid = CATID_Math;
catinfo.lcid = 0x0409; // English
wcsncpy(catinfo.szDescription, L"Arithmetic Objects", 128);

// Install the component category.
pCatRegister->RegisterCategories(1, &catinfo);

// Release COM+'s implementation of component categories.
pCatRegister->Release();

If it becomes necessary to unregister a component category, you can call the ICatRegister::UnRegisterCategories method, as shown here:

pCatRegister->UnRegisterCategories(1, &CATID_Math);

Under most circumstances, however, it is unnecessary to remove a component category from the registry; there are likely to be many components of any particular category.

Perhaps more common than registering or unregistering component categories is the task of declaring that a particular coclass implements or requires one or more component categories. The following code calls the ICatRegister::RegisterClassImplCategories method to declare that the InsideCOM coclass implements the Arithmetic Objects component category. This method adds the Implemented Categories key below the HKEY_CLASSES_ROOT\CLSID\{CLSID_InsideCOM} entry in the registry. The actual CATIDs supported are inserted below the Implemented Categories key. The following code would probably be executed as part of a component self-registration procedure:

CATID rgcatid[1];
rgcatid[0] = CATID_Math;
pCatRegister->RegisterClassImplCategories(CLSID_InsideCOM, 
    1, rgcatid);

Removing a particular CATID from the registration of a coclass, as shown in the following code, is less commonly performed. During the unregister procedure, most components simply delete all their registry settings, so removing implemented categories specifically is unnecessary. It does no harm, however.

CATID rgcatid[1];
rgcatid[0] = CATID_Math;
pCatRegister->UnRegisterClassImplCategories(CLSID_InsideCOM, 1, 
    rgcatid);