Up Close with the IMoniker Interface

In our discussion of OLE's naming and binding architecture, we've seen some of the member functions of IMoniker and the parts of the architecture that use those members. We're now in a position to look at the entirety of this rather large interface, which, again, is derived from IPersistStream:7


interface IMoniker : IPersistStream
{
HRESULT BindToObject(IBindContext *pbc, IMoniker *pmkToLeft
, REFIID riid, VOID **ppvResult);
HRESULT BindToStorage(IBindContext *pbc, IMoniker pmkToLeft
, REFIID riid, void **ppvObj);
HRESULT Reduce (IBindContext *pbc, DWORD dwReduceHowFar
, IMoniker **ppmkToLeft, IMoniker **ppmkReduced);
HRESULT ComposeWith(IMoniker **pmkRight, BOOL fOnlyIfNotGeneric
, IMoniker **ppmkComposite);
HRESULT Enum(BOOL fForward, IEnumMoniker **ppEnum);
HRESULT IsEqual(IMoniker *pmkOtherMoniker);
HRESULT Hash(DWORD *pdwHash);
HRESULT IsRunning(IBindContext *pbc, IMoniker *pmkToLeft
, IMoniker *pmkNewlyRunning);
HRESULT GetTimeOfLastChange(IBindContext *pbc, IMoniker *pmkToLeft
, FILETIME *pFileTime); HRESULT Inverse(IMoniker **ppmk);
HRESULT CommonPrefixWith(IMoniker *pmkOther, IMoniker **ppmkPrefix);
HRESULT RelativePathTo(IMoniker *pmkOther, IMoniker **ppmkRelPath);
HRESULT GetDisplayName(IBindContext *pbc, IMoniker *pmkToLeft
, LPOLESTR *ppszDisplayName);
HRESULT ParseDisplayName(IBindContext *pbc, IMoniker *pmkToLeft
, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut);
HRESULT IsSystemMoniker(DWORD pdwMksys);
};

Holy cow! IMoniker alone has 15 specific members and as many as 23 members if you count all the base interfaces. This makes IMoniker one of the largest interfaces in all of OLE. Fortunately, we can group the specific IMoniker members so that looking at them in detail isn't such a drag.

Group

Related Members

Binding

BindToObject, BindToStorage

Composite

Reduce, ComposeWith, Inverse, Enum, CommonPrefixWith, RelativePathTo, IsSystemMoniker

Table

IsEqual, Hash, IsRunning, GetTimeOfLastChange

Display Name

GetDisplayName, ParseDisplayName


We've already explored the members of the Binding group except to note that not all named objects have storage, so the function BindToStorage can easily fail with MK_E_NOSTORAGE. That said, the following sections look in more detail at the functions in the Table, Composite, and Display Name groups. Do note that understanding IMoniker is generally necessary only if you are developing custom monikers and sophisticated clients. If this is not what you plan to be doing, feel free to skip the rest of this detailed section.

7 The OLE architects admit that a moniker might benefit from a more flexible choice of per-sistence model, so they have at times regretted using IPersistStream as a base interface for IMoniker, chaining monikers to stream persistence. At the time they were designed, interfaces and monikers were so scary that trying to explain a multiple-interface component as complicated as a moniker was simply not acceptable. At that time, it was easier to understand objects with single interfaces, so that's what a moniker came out to be. Of course, in hindsight and with a better understanding of interfaces, this is not an optimal design.