In the earlier material about QueryInterface, you might have thought of some very common questions. How can a client obtain just a list of all of an object's interfaces short of calling QueryInterface for every known interface under the sun? How could an object browser accomplish this without even instantiating objects in the first place? How can a client learn about the names of interface member functions as well as the names and types of the arguments to those functions? One answer to this last question is a header file that contains the function signatures for the interface in question. Header files, however, contain compile-time information. How can you obtain the same information at run time?
The answer to these questions is known as Type Information—literally, a collection of information about data types, interfaces, member functions (return types and arguments), object classes, and even DLL modules. Type information is really just a complex set of nested data structures: one structure describes an object and its interfaces, the interfaces have data structures describing the individual member functions, the functions have structures to describe the individual arguments, and these in turn have structures to describe their various attributes and data types. In reality, this is as much, if not more, information than you could hope to glean from any header file.
To deal with this complexity, OLE provides native services to navigate through type information as well as to create it in the first place. In other words, all creation and manipulation of type information happens through OLE-implemented objects and their interfaces, so you rarely have to deal with these complex data structures directly. These OLE components are the topic of Chapter 3.
All type information is stored in an entity called a type library, which can contain information for any number of objects, interfaces, data types, and modules. Creating a type library happens through an object that implements ICreateTypeLib and creating elements in the library happens through an object with ICreateTypeInfo. The implementation of these objects is provided as a standard OLE service, so you will never implement these yourself. In fact, you will generally never have occasion to even use them as a client because the OLE SDK includes a tool called MKTYPLIB.EXE (Make Type Library), which takes a text file you write in an Object Description Language (ODL), parses it, and makes all the appropriate calls to ICreateTypeLib and ICreateTypeInfo, generating a file that contains all the binary data structures for your type library.
Accessing the information contained in a type library is accomplished through two similar OLE-provided objects. The library exposes ITypeLib, and the elements in it expose ITypeInfo. OLE offers a number of means through which you can load a type library into memory and obtain the ITypeLib pointer for it, as we'll see in Chapter 3. After you have an ITypeLib pointer, you can easily obtain the ITypeInfo for an object class (given a unique class identifier for the object), and through this interface you can obtain a list of the interfaces the object supports. All of this can be done without ever instantiating an object, but it does require a little information in the system registry to associate an object class with a type library.
If a client wants to retrieve the same information from an object that is already running, it can query for an interface named IProvideClassInfo. The presence of this interface means that the object can directly provide the client with the ITypeInfo that describes the object as a whole, without the bother of having to go out and find a type library.
I should point out that at the time of writing, type information is available for only a few objects outside of OLE Automation or OLE Controls (where it is required). However, type information is universal—it can describe any object and any interface, so as time passes I expect to see type information become available for most objects. Any type-related information about anything in OLE can be stored in a type library, so such a library is the repository for information about objects and interfaces.