COM API Functions for GUIDs

The basic COM and OLE system DLLs provide a number of API functions for dealing with GUIDs, CLSIDs, and IIDs, as illustrated in Table 2-1:

Function

Purpose

CoCreateGuid

Allocates a new GUID

IsEqualGUID

Compares two GUIDs for equivalence

IsEqualCLSID

Typesafe version of IsEqualGUID for CLSIDs

IsEqualIID

Typesafe version of IsEqualGUID for IIDs

StringFromCLSID

Typesafe conversion of a CLSID to a text string

StringFromIID

Typesafe version of StringFromCLSID for IIDs

StringFromGUID2

Converts a GUID to a text string, storing the string in a caller-allocated buffer

CLSIDFromString

Converts a text string to a typesafe CLSID

IIDFromString

Typesafe version of CLSIDFromString for IIDs


Table 2-1.

API functions for working with GUIDs, CLSIDs, and IIDs. Strings are always in Unicode on 32-bit platforms.

All of the string-related functions work with a GUID spelled out in hex digits as before, but they are wrapped in braces, as in {42754580-16b7-11ce-80eb-00aa003d7352}. This is the format of a GUID as it appears in the registry. The StringFromCLSID and StringFromIID functions allocate the returned string themselves, using what is called the task allocator, as we'll see in "Memory Management" later in this chapter.

In addition to the IsEqual functions, the OLE header files also include C++ overloaded == operators for GUIDs, CLSIDs, and IIDs, providing more convenient methods of comparison for C++ implementations. You'll see these operators used in most of this book's sample code.

One other note concerning C vs. C++: when passing any GUID as a function argument, you must pass an explicit pointer in C, whereas you can use a reference in C++. For example, in C++ you could pass something such as IID_ISampleOne as is, but in C you would have to pass &IID_ISampleOne.


#include <initguid.h> and Precompiled Headers

Any code that ever refers to any GUID, be it a CLSID or an IID, must include a standard OLE header file, INITGUID.H, once and only once in the entire compilation of a DLL or an EXE. All clients and components should have an #include <initguid.h> line in one and only one source file, which comes after the other OLE headers. INITGUID.H ensures that all GUIDs (yours and OLE's) get defined as constants in your data or code segment that holds constants. If you typically use a central include file for all files in your project, wrap an #ifdef statement around the #include. The samples in this book have such a statement based on a symbol INITGUIDS that you'll see in INC\BOOKGUID.H. One file in each project defines INITGUIDS. (INITGUIDS is a symbol used in the OLE headers themselves for the same sort of purpose, but I couldn't think of another name.)

Including INITGUID.H only once is tricky when you are using precompiled headers. Create the precompiled header in a file that does not include INITGUID.H—the samples using precompilation all use the file PRECOMP.CPP, which contains only one #include statement. You can then use the precompiled header from this step to compile with all files except the one in which you want to include INITGUID.H. You should compile that single file without using the precompiled header to pull in the extra file.