Now that we understand interfaces and the various mechanisms through which they work, we're ready to begin exploring all the other OLE services and technologies. Some of the 80 or so OLE-defined interfaces known at the time of writing are used internally within OLE, others are often used in writing components and clients, and others are less common. Most of OLE is, in fact, described, expressed, and accessed through interfaces of one kind or another, and some interfaces do no more than provide a base interface for others related to them. For most components, you'll need to implement only a few interfaces yourself, and as a client, you'll generally work with only a handful. OLE looks like a lot of technology—and it is—but you don't have to chew it all at the same time. Don't be scared of the myth that OLE is "complicated, complex, and difficult" simply because there's a lot of technology in there. Win32 as a whole is more complicated, but few people complain about that because they understand how to look at little pieces, one at a time, as each piece becomes necessary in programming. You can approach OLE the same way, and this book is structured to help you on that journey.
Part of what makes OLE so exciting is this idea of an extensible service architecture that allows you to arbitrarily extend what OLE does with custom components as well as with custom interfaces. You can implement a service that OLE does not for whatever reason you want. (For example, a group named the Open Market Data Council created a specification called WOSA/XRT for real-time market data exchange, using OLE technology to create a higher integration standard.) If OLE doesn't define an interface you need, you can define custom interfaces yourself. In this chapter, we've already seen six custom interfaces: IAnimal, IRabbit, IKoala, ISampleOne, ISampleTwo, and IEnumRECT. Granted, these are pretty useless interfaces for any real components, but they show you how easily you can create them, and GUIDs mean that you don't need to worry about conflicts. Remember that all these interfaces work only in-process because there is no marshaling support for them. We'll look at that topic in Chapter 6.
Besides the interfaces, OLE is also made up of more than 120 API functions. These generally fall into three categories: creation functions for components of different types such as CoCreateInstance and CoGetMalloc that access OLE-implemented components or custom components; helper functions such as CoTaskMemAlloc that wrap commonly used sequences of interface calls; and functions such as CoInitialize, StringFromCLSID, and IsEqualGUID that completely implement some useful or even vital functionality that does not create a component and is not a simple wrapper. We will see many examples of all of these functions in the chapters ahead, and as with interfaces, you'll generally use only a subset of them. Again, there's no reason to be terrified of all this technology. Each function and each interface has a specific purpose in life, and your paths need cross only when you share a common purpose.