16    Persistent Intelligent Names: Monikers

16.1    Overview

A moniker is simply an object that supports the IMoniker() interface. IMoniker() interface includes the IPersistStream() interface; thus, monikers can be saved to and loaded from streams. The persistent form of a moniker contains the class identifier (CLSID) of its implementation which is used during the loading process, and so new kinds of monikers can be created transparently to clients.

[Footnote 64] The most basic operation in IMoniker() interface is that of binding to the object to which it points, which is supported by IMoniker::BindToObject. This function takes as a parameter the interface identifier by which the caller wishes to talk to the object, runs whatever algorithm is necessary in order to locate the object, then returns a pointer of that interface type to the caller. [Footnote 64] Each moniker class can store arbitrary data its persistent representation, and can run arbitrary code at binding time.

If there is an identifiable piece of persistent storage in which the object referenced by the moniker is stored, then IMoniker::BindToStorage can be used to gain access to it. Many objects have such identifiable storage, but some, such as the objects which are the ranges on a Microsoft Excel spreadsheet do not. (These ranges exist only as a part of Excel's data structures; they are in effect a figment of Excel's imagination and are only reified on demand for clients.)

In most cases, a particular moniker class is designed to be one step along the path to the information source in question. These pieces can be composed together to form a moniker which represents the complete path. For example, the moniker stored inside a chart that refers to its underlying data in a spreadsheet might be a composite moniker formed from three pieces:

Figure 16-1:  A Moniker Referring to a Spreadsheet

This composite is itself a moniker; it just happens to be a moniker which is a sequenced collection of other monikers. The composition here is generic in that it has no knowledge of the pieces involved other than that they are monikers.

Most monikers have a textual representation which is meaningful to the user; this can be retrieved with IMoniker::GetDisplayName. The API function MkParseDisplayName() goes the other direction: it can turn a textual display name into the appropriate moniker, though beware that in general this operation is as expensive as actually binding to the object.

Monikers can compare themselves to other monikers using IMoniker::IsEqual. A hash value useful for storing monikers in lookup tables is available through IMoniker::Hash(). Monikers are not a total order or even a partial order; therefore, monikers cannot be stored in tables that rely on sorting for retrieval; use hashing instead (it is inappropriate to use the display name of a moniker for sorting, since the display name may not reflect the totality of internal state of the moniker).

The earliest time after which the object to which the moniker points is known not to have changed can be obtained with IMoniker::GetTimeOfLastChange. This is not necessarily the time of last change of the object; rather, it is the best cheaply available approximation thereto.

A moniker can be asked to re-write itself into another equivalent moniker by calling IMoniker::Reduce(). This function returns a new moniker that will bind to the same object, but does so in a more efficient way. This capability has several uses:

It enables the construction of user-defined macros or aliases as new kinds of moniker classes. When reduced, the moniker to which the macro evaluates is returned.

It enables the construction of a kind of moniker which tracks data as it moves about. When reduced, the moniker of the data in its current location is returned.

On file systems such as Macintosh System 7 which support an ID-based method of accessing files which is independent of file names, a File Moniker could be reduced to a moniker which contains one of these IDs.

Figure 16-2 shows a (somewhat contrived) example of moniker reduction. It illustrates the reduction of a moniker which names the net income entry for this year's report in the ``Projects'' directory of the current user's home directory.

Figure 16-2:  Reduction of a Moniker

(Note that the particular classes of monikers used here are for illustrative purposes only.) As we can see, many monikers in this example are reduced to something completely different, and some bind to something during their reduction, but some do not. For example, to reduce the alias ``Home'', the reduction must access the information that ``Home'' was an alias for ``\\server\share\fred''.

The process of moniker reduction may also be tied to a global table called the Running Object Table. The Running Object Table serves as the place where monikers in the process of binding look to see if they are already running or not.

Pointers to instances of IMoniker() interface can be marshaled to other processes, just as any other interface pointer can. Many monikers are of the nature that they are immutable once created and that they maintain no object state outside themselves. Item Monikers are an example of a class of such monikers. These monikers, which can be replicated at will, will usually want to support custom marshaling (see IMarshal() interface) so as to simply serialize themselves and de-serialize themselves in the destination context (see IPersistStream() regarding serialization). This is referred to as marshaling an object by value.

16.2    Moniker Interface Descriptions

16.2.1    IBindCtx

The IBindCtx() interface provides access to a bind context, which is an object that stores information about a particular moniker binding operation. You pass a bind context as a parameter when calling many methods of IMoniker() and in certain functions related to monikers.

A bind context includes the following information:

When to Implement

You do not need to implement this interface. The system provides an IBindCtx() implementation, accessible though a call to the CreateBindCtx() function, that is suitable for all situations.

When to Use

Anyone writing a new moniker class by implementing the IMoniker() interface must call IBindCtx() methods in the implementation of several IMoniker() methods. Moniker providers (servers that hand out monikers to identify their objects) may also need to call IBindCtx() methods from their implementations of the IOleItemContainer or IParseDisplayName() interfaces.

Moniker clients (objects that use monikers to acquire interface pointers to other objects) typically don't call many IBindCtx() methods. Instead, they simply pass a bind context as a parameter in a call to an IMoniker() method. To acquire an interface pointer and activate the indicated object (called binding to an object), moniker clients typically do the following:

  1. Call the CreateBindCtx() function to create a bind context and get a pointer to the IBindCtx() interface on the bind context object..

  2. If desired (although this is rarely necessary), the moniker client can call IBindCtx::SetBindOptions() to specify the bind options.

  3. Pass the bind context as a parameter to the desired IMoniker() method (usually IMoniker::BindToObject()).

  4. Call IUnknown::Release() on the bind context to release it.

Although applications that act as link containers (container applications that allow their documents to contain linked objects) are moniker clients, they rarely call IMoniker() methods directly.

Table 16-1:  IBindCtx Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 16-2:  IBindCtx Methods

IBindCtx() Methods Description
RegisterObjectBound Registers an object with the bind context.
RevokeObjectBound Revokes an object's registration.
ReleaseBoundObjects Releases all registered objects.
SetBindOptions Sets the binding options.
GetBindOptions Retrieves the binding options.
GetRunningObjectTable() Retrieves a pointer to the Running Object Table.
RegisterObjectParam Associates an object with a string key.
GetObjectParam Returns the object associated with a given string key.
EnumObjectParam Enumerates all the string keys in the table.
RevokeObjectParam Revokes association between an object and a string key.

See Also

CreateBindCtx(), IMoniker(), IOleItemContainer(), IParseDisplayName()  

IBindCtx::EnumObjectParam()

NAME

IBindCtx::EnumObjectParam() - Supplies a pointer to an IEnumString() interface on an enumerator that can return the keys of the bind context's string-keyed table of pointers.

Synopsis

#include <objidl.h>

HRESULT EnumObjectParam(
        IEnumString ** ppenum );

Description

This method provides an IEnumString() pointer to an enumerator that can return the keys of the bind context's string-keyed table of pointers. The keys returned are the ones previously specified in calls to IBindCtx::RegisterObjectParam().

Parameters

ppenum

[out] Indirect pointer to the IEnumString() interface on the enumerator. If an error occurs, *ppenum is set to NULL. If *ppenum is non-NULL, the implementation calls IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release().

Return Values

This method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

An enumerator was successfully created and the pointer supplied.

See Also

IBindCtx::RegisterObjectParam(), IEnumString()  

IBindCtx::GetBindOptions()

NAME

IBindCtx::GetBindOptions() - Returns the binding options stored in this bind context.

Synopsis

#include <objidl.h>

HRESULT GetBindOptions(
        BIND_OPTS * pbindopts );

Description

A bind context contains a block of parameters, stored in a BIND_OPTS structure, that are common to most IMoniker() operations and that do not change as the operation moves from piece to piece of a composite moniker.

Notes to Callers

You typically call this method if you are writing your own moniker class (this requires that you implement the IMoniker() interface). You call this method to retrieve the parameters specified by the moniker client.

You must initialize the BIND_OPTS structure that is filled in by this method. Before calling this method, you must initialize the cbStruct field of the structure to the size of the BIND_OPTS structure.

Parameters

pbindopts

[in, out] Pointer to an initialized BIND_OPTS structure on entry that receives the current binding parameters on return.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The stored binding options were successfully returned.

See Also

IBindCtx::SetBindOptions()  

IBindCtx::GetObjectParam()

NAME

IBindCtx::GetObjectParam() - Retrieves the pointer associated with the specified key in the bind context's string-keyed table of pointers.

Synopsis

#include <objidl.h>

HRESULT GetObjectParam(
        LPOLESTR pszKey,
        IUnknown ** ppunk );

Description

A bind context maintains a table of interface pointers, each associated with a string key. This enables communication between a moniker implementation and the caller that initiated the binding operation. One party can store an interface pointer under a string known to both parties so that the other party can later retrieve it from the bind context.

The pointer this method retrieves must have previously been inserted into the table using the IBindCtx::RegisterObjectParam() method.

Notes to Callers

Those writing a new moniker class (through an implementation of IMoniker()) and some moniker clients (objects using a moniker to bind to an object) can call IBindCtx::GetObjectParam().

Objects using monikers to locate other objects can call this method when a binding operation fails to get specific information about the error that occurred. Depending on the error, it may be possible to correct the situation and retry the binding operation. See IBindCtx::RegisterObjectParam() for more information.

Moniker implementations can call this method to deal with situations where a caller initates a binding operation and requests specific information. By convention, the implementer should use key names that begin with the string form of the CLSID of a moniker class (see the StringFromCLSID() function).

Parameters

pszKey

[in] Pointer to a zero-terminated wide character string (two bytes per character) containing the key to search for. Key string comparison is case-sensitive.

ppunk

[out] When successful, indirect pointer to the IUnknown() interface on the object associated with pszKey. In this case, the implementation calls IUnknown::AddRef() on the parameter. It is the caller's responsibility to call IUnknown::Release(). If an error occurs, ppunk is set to NULL.

Return Values

This method supports the standard return value E_FAIL, as well as the following:

S_OK

The pointer associated with the specified key was successfully returned.

See Also

IBindCtx::RegisterObjectParam(), IBindCtx::EnumObjectParam()  

IBindCtx::GetRunningObjectTable()

NAME

IBindCtx::GetRunningObjectTable() - Provides an interface pointer to the Running Object Table (ROT) for the machine on which this bind context is running.

Synopsis

#include <objidl.h>

HRESULT GetRunningObjectTable((
        IRunningObjectTable ** pprot );

Description

The Running Object Table is a globally accessible table on each machine. It keeps track of all the objects that are currently running on the machine.

Notes to Callers

Typically, those implementing a new moniker class (through an implementation of IMoniker() interface) call IBindCtx::GetRunningObjectTable(). It is useful to call this method in an implementation of IMoniker::BindToObject() or IMoniker::IsRunning() to check whether a given object is currently running. You can also call this method in the implementation of IMoniker::GetTimeOfLastChange() to learn when a running object was last modified.

Moniker implementations should call this method instead of using the GetRunningObjectTable() function. This makes it possible for future implementations of IBindCtx() to modify binding behavior.

Parameters

pprot

[out] When successful, indirect pointer to the IRunningObjectTable() interface on the Running Object Table. If an error occurs, *pprot is set to NULL. If *pprot is non-NULL, the implementation calls IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release().

Return Values

This method supports the standard return values E_OUTOFMEMORY and E_UNEXPECTED, as well as the following:

S_OK

A pointer to the ROT was returned successfully.

See Also

IMoniker(), IRunningObjectTable()  

IBindCtx::RegisterObjectBound()

NAME

IBindCtx::RegisterObjectBound() - Calls IUnknown::AddRef() on the specified object to ensure that the object remains active until the bind context is released. The method stores a pointer to the object in the bind context's internal list of pointers.

Synopsis

#include <objidl.h>

HRESULT RegisterObjectBound(
        IUnknown * punk );

Description

Notes to Callers

Those writing a new moniker class (through an implementation of the IMoniker() interface), should call this method whenever the implementation activates an object. This happens most often in the course of binding a moniker, but it can also happen while retrieving a moniker's display name, parsing a display name into a moniker, or retrieving the time that an object was last modified.

IBindCtx::RegisterObjectBound() calls IUnknown::AddRef() to create an additional reference to the object. You must, however, still release your own copy of the pointer. Note that calling this method twice for the same object creates two references to that object. You can release a reference obtained through a call to this method by calling IBindCtx::RevokeObjectBound(). All references held by the bind context are released when the bind context itself is released.

Calling IBindCtx::RegisterObjectBound() to register an object with a bind context keeps the object active until the bind context is released. Reusing a bind context in a subsequent binding operation (either for another piece of the same composite moniker, or for a different moniker) can make the subsequent binding operation more efficient because it doesn't have to reload that object. This, however, improves performance only if the subsequent binding operation requires some of the same objects as the original one, so you need to balance the possible performance improvement of reusing a bind context against the costs of keeping objects activated unnecessarily.

IBindCtx() does not provide a method to retrieve a pointer to an object registered using IBindCtx::RegisterObjectBound(). Assuming the object has registered itself with the Running Object Table, moniker implementations can call IRunningObjectTable::GetObject() to retrieve a pointer to the object.

Parameters

punk

[in] Pointer to the IUnknown() interface on the object that is being registered as bound.

Return Values

This method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The object was successfully registered.

See Also

IBindCtx::ReleaseBoundObjects(), IBindCtx::RevokeObjectBound(), IRunningObjectTable::GetObject()  

IBindCtx::RegisterObjectParam()

NAME

IBindCtx::RegisterObjectParam() - Stores an IUnknown() pointer on the specified object under the specified key in the bind context's string-keyed table of pointers. The method must call IUnknown::AddRef() on the stored pointer.

Synopsis

#include <objidl.h>

HRESULT RegisterObjectParam(
        LPOLESTR pszKey,
        IUnknown * punk );

Description

A bind context maintains a table of interface pointers, each associated with a string key. This enables communication between a moniker implementation and the caller that initiated the binding operation. One party can store an interface pointer under a string known to both parties so that the other party can later retrieve it from the bind context.

Binding operations subsequent to the use of this method can use IBindCtx::GetObjectParam() to retrieve the stored pointer.

Notes to Callers

IBindCtx::RegisterObjectParam() is useful to those implementing a new moniker class (through an implementation of IMoniker()) and to moniker clients (those who use monikers to bind to objects).

In implementing a new moniker class, you call this method when an error occurs during moniker binding to inform the caller of the cause of the error. The key that you would obtain with a call to this method would depend on the error condition. The following lists common moniker binding errors, describing for each the keys that would be appropriate:

MK_E_EXCEEDEDDEADLINE

If a binding operation exceeds its deadline because a given object is not running, you should register the object's moniker using the first unused key from the list: "ExceededDeadline", "ExceededDeadline1", "ExceededDeadline2", etc. If the caller later finds the moniker in the Running Object Table, the caller can retry the binding operation.

MK_E_CONNECTMANUALLY

The ``ConnectManually'' key indicates a moniker whose binding requires assistance from the end user. The caller can retry the binding operation after showing the moniker's display name to request that the end user manually connect to the object. Common reasons for this error are that a password is needed or that a floppy needs to be mounted.

E_CLASSNOTFOUND

The ``ClassNotFound'' key indicates a moniker whose class could not be found (the server for the object identified by this moniker could not be located). If this key is used for a COM compound-document object, the caller can use IMoniker::BindToStorage() to bind to the object, and then try to carry out a Treat As... or Convert To... operation to associate the object with a different server. If this is successful, the caller can retry the binding operation.

If you're a moniker client with detailed knowledge of the implementation of the moniker you're using, you can also call this method to pass private information to that implementation.

You can define new strings as keys for storing pointers. By convention, you should use key names that begin with the string form of the CLSID of the moniker class (see the StringFromCLSID() function).

If the pszKey parameter matches the name of an existing key in the bind context's table, the new object replaces the existing object in the table.

When you register an object using this method, the object is not released until one of the following occurs:

Parameters

pszKey

[in] Pointer to a zero-terminated wide character string (two bytes per character) containing the key under which the object is being registered. Key string comparison is case-sensitive.

punk

[in] Pointer to the IUnknown() interface on the object that is to be registered.

Return Values

This method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The pointer was successfully registered under the specified string.

See Also

IBindCtx::GetObjectParam(), IBindCtx::RevokeObjectParam(), IBindCtx::EnumObjectParam()  

IBindCtx::ReleaseBoundObjects()

NAME

IBindCtx::ReleaseBoundObjects() - Releases all pointers to all objects that were previously registered by calls to IBindCtx::RegisterObjectBound().

Synopsis

#include <objidl.h>

HRESULT ReleaseBoundObjects(
        void );

Description

You rarely call this method directly. The system's IBindCtx() implementation calls this method when the pointer to the IBindCtx() interface on the bind context is released (the bind context is released). If a bind context is not released, all of the registered objects remain active.

If the same object has been registered more than once, this method calls the IUnknown::Release() method on the object the number of times it was registered.

Return Values

S_OK

The objects were released successfully.

See Also

IBindCtx::RegisterObjectBound()  

IBindCtx::RevokeObjectBound()

NAME

IBindCtx::RevokeObjectBound() - Releases the IUnknown() pointer to the specified object and removes that pointer from the bind context's internal list of pointers. This undoes a previous call to IBindCtx::RegisterObjectBound() for the same object.

Synopsis

#include <objidl.h>

HRESULT RevokeObjectBound(
        IUnknown * punk );

Description

You rarely call this method. This method is included for completeness.

Parameters

punk

[in] Pointer to the IUnknown() interface on the object to be released.

Return Values

S_OK

The object was released successfully.

MK_E_NOTBOUND

Indicates that punk was not previously registered with a call to IBindCtx::RegisterObjectBound().

See Also

IBindCtx::RegisterObjectBound()  

IBindCtx::RevokeObjectParam()

NAME

IBindCtx::RevokeObjectParam() - Removes the specified key and its associated pointer from the bind context's string-keyed table of objects. The key must have previously been inserted into the table with a call to IBindCtx::RegisterObjectParam().

Synopsis

#include <objidl.h>

HRESULT RevokeObjectParam(
        LPOLESTR pszKey );

Description

A bind context maintains a table of interface pointers, each associated with a string key. This enables communication between a moniker implementation and the caller that initiated the binding operation. One party can store an interface pointer under a string known to both parties so that the other party can later retrieve it from the bind context.

This method is used to remove an entry from the table. If the specified key is found, the bind context also releases its reference to the object.

Parameters

pszKey

[in] Pointer to a zero-terminated wide character string (two bytes per character) containing the key to remove. Key string comparison is case-sensitive.

Return Values

S_OK

The specified key was successfully removed from the table.

S_FALSE

No object has been registered with the specified key.

See Also

IBindCtx::RegisterObjectParam()  

IBindCtx::SetBindOptions()

NAME

IBindCtx::SetBindOptions() - Specifies new values for the binding parameters stored in the bind context. Subsequent binding operations can call IBindCtx::GetBindOptions() to retrieve the parameters.

Synopsis

#include <objidl.h>

HRESULT SetBindOptions(
        BIND_OPTS * pbindopts );

Description

A bind context contains a block of parameters, stored in a BIND_OPTS2 or a BIND_OPTS structure, that are common to most IMoniker() operations. These parameters do not change as the operation moves from piece to piece of a composite moniker.

Notes to Callers

This method can be called by moniker clients (those who use monikers to acquire interface pointers to objects).

When you first create a bind context using the CreateBindCtx() function, the fields of the BIND_OPTS structure are initialized to the following values:

cbStruct = sizeof(BINDOPTS); 
grfFlags = 0; 
grfMode = STGM_READWRITE; 
dwTickCountDeadline = 0;

You can use the IBindCtx::SetBindOptions() method to modify these values before using the bind context, if you want values other than the defaults. See BIND_OPTS for more information.

SetBindOptions only copies the struct members of BIND_OPTS2, but not the COSERVERINFO structure and the pointers it contains. Callers may not free any of these pointers until the bind context is released.

Parameters

pbindopts

[in] Pointer to a BIND_OPTS2 or a BIND_OPTS structure containing the binding parameters.

Return Values

This method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The parameters were stored successfully.

See Also

Bind_OPTS2, IBindCtx::GetBindOptions()

16.2.2    IClassActivator

IClassActivator() Specifies a method that retrieves a class object.

When to Implement

No implementation of a moniker or an object supporting IClassActivator() currently exists within the system, however future versions of the operating system may contain such implementations. Implement the IClassActivator() interface if you are writing a custom moniker type which you want to be able to compose to the left of a class moniker or any other moniker that supports binding to IClassActivator().

When to Use

Use IClassActivator() if you write a custom moniker class that should behave similarly to class monikers when composed to the right of other monikers. File monikers also use this interface.

Table 16-3:  IClassActivator Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 16-4:  IClassActivator Methods

IClassActivator() Method Description
GetClassObject Retrieves a class object.

 

IClassActivator::GetClassObject()

NAME

IClassActivator::GetClassObject() - Retrieves a class object. Similar to CoGetClassObject(),

Synopsis

#include <objidl.h>

HRESULT GetClassObject(
        REFCLSID * pClassID,
        DWORD dwClsContext,
        LCID locale,
        REFIID riid,
        void ** ppv );

Description

This method returns the class identifier (CLSID) for an object, used in later operations to load object-specific code into the caller's context.

Parameters

pClassID

[in] Points to the CLSID that Identifies the class whose class object is to be retrieved.

dwClsContext

[in] The context in which the class is expected to run; values are taken from the CLSCTX enumeration.

locale

[in] Any LCID constant as defined in WINNLS.H.

riid

[in] IID of the interface on the object to which a pointer is desired.

ppv

[out] On successful return, an indirect pointer to the requested interface.

Return Values

This method supports the standard return value E_FAIL, as well as the following:

S_OK

The CLSID was successfully returned.

See Also

CoGetClassObject()

16.2.3    IEnumMoniker

The IEnumMoniker() interface is used to enumerate the components of a moniker or to enumerate the monikers in a table of monikers. IEnumMoniker() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

When to Implement

You need to implement IEnumMoniker() if you are writing a new type of moniker and your monikers have an internal structure that can be enumerated. Your implementation of IMoniker::Enum() must return an enumerator that implements IEnumMoniker() and can enumerate your moniker's components. If your moniker has no structure that can be enumerated, your IMoniker::Enum() method can simply return a NULL pointer.

When to Use

Call the methods of the IEnumMoniker() interface if you need to enumerate the components of a composite moniker, or to enumerate the monikers in a table.

COM defines two interfaces that supply an IEnumMoniker() interface pointer:

The prototypes of the methods are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        IMoniker * rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumMoniker ** ppenum );

See Also

IEnumXXXX, IMoniker::Enum(), IRunningObjectTable::EnumRunning()

16.2.4    IEnumString

IEnumString() is defined to enumerate strings. LPWSTR is the type that indicates a pointer to a zero-terminated string of wide, i.e., Unicode, characters. IEnumString() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

When to Implement

It is usually not necessary to implement this interface unless you have use for a custom string enumerator. A system implementation in the bind context object on which is the IBindCtx() interface also contains an implementation of IEnumString(). IBindCtx::EnumObjectParam() returns a pointer to this IEnumString() interface on an enumerator that can return the keys of the bind context's string-keyed table of pointers.

When to Use

Call the methods of IEnumString() to enumerate through a set of strings.

The prototypes of the member functions are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        LPOLESTR * rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumString ** ppenum );

16.2.5    IEnumUnknown

This enumerator enumerates objects with the IUnknown() interface. It can be used to enumerate through the objects in a component containing multiple objects. IEnumUnknown() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

When to Implement

You can implement this whenever you want a caller to be able to enumerate the objects contained in another object. You get a pointer to IEnumUnknown() through a call to IOleContainer::EnumObjects.

When to Implement

Call the methods of IEnumUnknown() to enumerate the objects in a compound document, when you get a pointer to the interface on the enumerator through a call to IOleContainer::EnumObjects.

The prototypes of the methods are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        IUnknown ** rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumUnknown ** ppenum );

16.2.6    IMoniker

The IMoniker() interface contains methods that allow you to use a moniker object, which contains information that uniquely identifies a COM object. An object that has a pointer to the moniker object's IMoniker() interface can locate, activate, and get access to the identified object without having any other specific information on where the object is actually located in a distributed system.

Like a path to a file in a file system, a moniker contains information that allows a COM object to be located and activated. Monikers can identify any type of COM object, from a document object stored in a file to a selection within an embedded object. COM provides a set of moniker classes that allow you to create moniker objects identifying the objects most commonly found in the system. For example, there might be an object representing a range of cells in a spreadsheet which is itself embedded in a text document stored in a file. In a distributed system, this object's moniker would identify the location of the object's system, the file's physical location on that system, the storage of the embedded object within that file, and, finally, the location of the range of cells within the embedded object.

A moniker object supports the IMoniker() interface, which is derived from the IPersistStream() interface, and uniquely identifies a single object in the system. Once an object providing a moniker has created the moniker object, this information cannot be changed within that object. If the moniker provider changes the information, it can only do so by creating a new moniker object, which would then uniquely identify the object in question.

Monikers have two important capabilites:

Monikers are used as the basis for linking in COM. A linked object contains a moniker that identifies its source. When the user activates the linked object to edit it, the moniker is bound; this loads the link source into memory.

When to Implement

Implement IMoniker() only if you are writing a new moniker class. This is necessary only if you need to identify objects that cannot be identified using one of the COM-supplied moniker classes described below.

The COM-supplied moniker classes are sufficient for most situations. Before considering writing your own moniker class, you should make sure that your requirements cannot be satisified by these classes.

If you decide you need to write your own implementation of IMoniker(), you must also implement the IROTData() interface on your moniker class. This interface allows your monikers to be registered with the Running Object Table (ROT).

When to Use

Two kinds of objects call the methods of IMoniker:

The component providing a moniker makes it accessible to other objects. It is important to understand the differences between the various system-supplied moniker classes to know which are appropriate for a given object. COM also provides functions for creating monikers using the COM-supplied moniker classes.

A moniker provider must also implement other interfaces to allow the monikers it hands out to be bound. COM objects that commonly provide monikers are link sources. These include server applications that support linking and container applications that support linking to their embedded objects.

Binding to an object means that a client uses a moniker to locate the object, activate it when necessary, and get a pointer to one of the active object's interfaces. The client of the moniker does not need to be aware of the class of the moniker--it must just get a pointer to the correct moniker's IMoniker() interface. Monikers are used most often in this way by container applications that allow their documents to contain linked objects. However, link containers rarely call IMoniker() methods directly.

Table 16-5:  IMoniker Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 16-6:  IPersist Methods

IPersist Methods Description
GetClassID() Returns the object's CLSID.

Table 16-7:  IPersistStream Methods

IPersistStream Methods Description
IsDirty Checks whether object has been modified.
Load Loads the object from a stream.
Save Saves the object to a stream.
GetSizeMax Returns the buffer size needed to save the object.

Table 16-8:  IMoniker Methods

IMoniker() Methods Description
BindToObject Binds to the object named by the moniker.
BindToStorage Binds to the object's storage.
Reduce Reduces the moniker to simplest form.
ComposeWith Composes with another moniker.
Enum Enumerates component monikers.
IsEqual Compares with another moniker.
Hash Returns a hash value.
IsRunning() Checks whether object is running.
GetTimeOfLastChange Returns time the object was last changed.
Inverse Returns the inverse of the moniker.
CommonPrefixWith Finds the prefix that the moniker has in common with another moniker.
RelativePathTo Constructs a relative moniker between the moniker and another.
GetDisplayName Returns the display name.
ParseDisplayName Converts a display name into a moniker.
IsSystemMoniker Checks whether moniker is one of the system-supplied types.

See Also

BindMoniker(), CreateBindCtx(), CreateGenericComposite(), CreateFileMoniker, CreateItemMoniker(), CreateAntiMoniker(), CreatePointerMoniker(), IPersistStream(), IROTData(), IMoniker--AntiMoniker Implementation, IMoniker--File Moniker Implementation, IMoniker--Item Moniker Implementation, IMoniker--Generic Composite Moniker Implementation, IMoniker--Pointer Moniker Implementation  

IMoniker::BindToObject()

NAME

IMoniker::BindToObject() - Uses the moniker to bind to the object it identifies. The binding process involves finding the object, putting it into the running state if necessary, and supplying the caller with a pointer to a specified interface on the identified object.

Synopsis

#include <objidl.h>

HRESULT BindToObject(
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        REFIID riidResult,
        void ** ppvResult );

Description

IMoniker::BindToObject() implements the primary function of a moniker, which is to locate the object identified by the moniker and return a pointer to one of its interfaces.

Notes to Callers

If you are using a moniker as a persistent connection between two objects, you activate the connection by calling IMoniker::BindToObject().

You typically call IMoniker::BindToObject() during the following process:

  1. Create a bind context object with a call to the CreateBindCtx() function.

  2. Call IMoniker::BindToObject() using the moniker, retrieving a pointer to a desired interface on the identified object.

  3. Release() the bind context.

  4. Through the acquired interface pointer, perform the desired operations on the object.

  5. When finished with the object, release the object's interface pointer.

The following code fragment illustrates these steps:

// pMnk is an IMoniker() * that points to a previously acquired moniker 
// ICellRange is a custom interface designed for an object that is a
//            range of spreadsheet cells 
ICellRange *pCellRange; 
IBindCtx() *pbc; 
CreateBindCtx( 0, &pbc ); 
pMnk->BindToObject( pbc, NULL, IID_ICellRange, &pCellRange );
pbc->Release(); 
// pCellRange now points to the object; safe to use pCellRange 
pCellRange->Release();

You can also use the BindMoniker() function when you only intend one binding operation and don't need to retain the bind context object. This helper function encapsulates the creation of the bind context, calling IMoniker::BindToObject(), and releasing the bind context.

COM containers that support links to objects use monikers to locate and get access to the linked object, but typically do not call IMoniker::BindToObject() directly.

Notes to Implementors

What your implementation does depends on whether you expect your moniker to have a prefix, that is, whether you expect the pmkToLeft parameter to be NULL or not. For example, an item moniker, which identifies an object within a container, expects that pmkToLeft identifies the container. An item moniker consequently uses pmkToLeft to request services from that container. If you expect your moniker to have a prefix, you should use the pmkToLeft parameter (for instance, calling IMoniker::BindToObject() on it) to request services from the object it identifies.

If you expect your moniker to have no prefix, your IMoniker::BindToObject() implementation should first check the Running Object Table (ROT) to see if the object is already running. To acquire a pointer to the ROT, your implementation should call IBindCtx::GetRunningObjectTable() on the pbc parameter. You can then call the IRunningObjectTable::GetObject() method to see if the current moniker has been registered in the ROT. If so, you can immediately call IUnknown::QueryInterface() to get a pointer to the interface requested by the caller.

When your IMoniker::BindToObject() implementation binds to some object, it should use the pbc parameter to call IBindCtx::RegisterObjectBound() to store a reference to the bound object in the bind context. This ensures that the bound object remains running until the bind context is released, which can avoid the expense of having a subsequent binding operation load it again later.

If the bind context's BIND_OPTS structure specifies the BINDFLAGS_JUSTTESTEXISTENCE flag, your implementation has the option of returning NULL in ppvResult (although you can also ignore the flag and perform the complete binding operation).

Parameters

pbc

[in] Pointer to the IBindCtx() interface on the bind context object, which is used in this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment.

pmkToLeft

[in] If the moniker is part of a composite moniker, pointer to the moniker to the left of this moniker. This parameter is primarily used by moniker implementers to enable cooperation between the various components of a composite moniker. Moniker clients should pass NULL.

riidResult

[in] IID of the interface the client wishes to use to communicate with the object that the moniker identifies.

ppvResult

[out] When successful, indirect pointer to the interface specified in riidResult on the object the moniker identifies. In this case, the implementation must call IUnknown::AddRef() on this pointer. It is the caller's responsibility to release the object with a call to IUnknown::Release(). If an error occurs, ppvResult should return NULL.

Return Values

The method supports the standard return values E_UNEXPECTED and E_OUTOFMEMORY, as well as the following:

S_OK

The binding operation was successful.

MK_E_NOOBJECT

The object identified by this moniker, or some object identified by the composite moniker of which this moniker is a part, could not be found.

MK_E_EXCEEDEDDEADLINE

The binding operation could not be completed within the time limit specified by the bind context's BIND_OPTS structure.

MK_E_CONNECTMANUALLY

The binding operation requires assistance from the end user. The most common reasons for returning this value are that a password is needed or that a floppy needs to be mounted. When this value is returned, retrieve the moniker that caused the error with a call to IBindCtx::GetObjectParam() with the key ``ConnectManually''. You can then call IMoniker::GetDisplayName() to get the display name, display a dialog box that communicates the desired information, such as instructions to mount a floppy or a request for a password, and then retry the binding operation.

MK_E_INTERMEDIATEINTERFACENOTSUPPORTED

An intermediate object was found but it did not support an interface required to complete the binding operation. For example, an item moniker returns this value if its container does not support the IOleItemContainer() interface.

STG_E_ACCESSDENIED

Unable to access the storage object.

IOleItemContainer::GetObject() errors

If the moniker used to bind to an object contains an item moniker, errors associated with this method can be returned.

See Also

BindMoniker(), IMoniker::BindToStorage()  

IMoniker::BindToStorage()

NAME

IMoniker::BindToStorage() - Retrieves an interface pointer to the storage that contains the object identified by the moniker. Unlike the IMoniker::BindToObject() method, this method does not activate the object identified by the moniker.

Synopsis

#include <objidl.h>

HRESULT BindToStorage(
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        REFIID riid,
        void ** ppvObj );

Description

There is an important difference between the IMoniker::BindToObject() and IMoniker::BindToStorage() methods. If, for example, you have a moniker that identifies a spreadsheet object, calling IMoniker::BindToObject() provides access to the spreadsheet object itself, while calling IMoniker::BindToStorage() provides access to the storage object in which the spreadsheet resides.

Notes to Callers

Although none of the COM moniker classes call this method in their binding operations, it might be appropriate to call it in the implementation of a new moniker class. You could call this method in an implementation of IMoniker::BindToObject() that requires information from the object identified by the pmkToLeft parameter and can get it from the persistent storage of the object without activation. For example, if your monikers are used to identify objects that can be activated without activating their containers, you may find this method useful.

A client that can read the storage of the object its moniker identifies could also call this method.

Notes to Implementors

Your implementation should locate the persistent storage for the object identified by the current moniker and return the desired interface pointer. Some types of monikers represent pseudo-objects, which are objects that do not have their own persistent storage. Such objects comprise some portion of the internal state of its container; as, for example, a range of cells in a spreadsheet. If your moniker class identifies this type of object, your implementation of IMoniker::BindToStorage() should return the error MK_E_NOSTORAGE.

If the bind context's BIND_OPTS structure specifies the BINDFLAGS_JUSTTESTEXISTENCE flag, your implementation has the option of returning NULL in ppvObj (although it can also ignore the flag and perform the complete binding operation).

Parameters

pbc

[in] Pointer to the IBindCtx() interface on the bind context object to be used during this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

pmkToLeft

[in] If the moniker is part of a composite moniker, pointer to the moniker to the left of this moniker. This parameter is primarily used by moniker implementers to enable cooperation between the various components of a composite moniker. Moniker clients should pass NULL.

riid

[in] Reference to the identifier of the storage interface requested, whose pointer will be returned in ppvObj. Storage interfaces commonly requested include IStorage(), IStream(), and ILockBytes().

ppvObj

[out] Pointer to the interface identified by riid on the storage of the object identified by the moniker. If ppvObj is non-NULL, the implementation must call IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release(). If an error occurs, ppvObj is set to NULL.

Return Values

The method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The binding operation was successful.

MK_E_NOSTORAGE

The object identified by this moniker does not have its own storage.

MK_E_EXCEEDEDDEADLINE

The operation could not be completed within the time limit specified by the bind context's BIND_OPTS structure.

MK_E_CONNECTMANUALLY

The operation was unable to connect to the storage, possibly because a network device could not be connected to. For more information, see IMoniker::BindToObject().

MK_E_INTERMEDIATEINTERFACENOTSUPPORTED

An intermediate object was found but it did not support an interface required for an operation. For example, an item moniker returns this value if its container does not support the IOleItemContainer() interface.

STG_E_ACCESSDENIED

Unable to access the storage object.

IOleItemContainer::GetObject() errors

Binding to a moniker containing an item moniker can return any of the errors associated with this function.

See Also

IMoniker::BindToObject()  

IMoniker::CommonPrefixWith()

NAME

IMoniker::CommonPrefixWith() - Creates a new moniker based on the common prefix that this moniker (the one comprising the data of this moniker object) shares with another moniker.

Synopsis

#include <objidl.h>

HRESULT CommonPrefixWith(
        IMoniker * pmkOther,
        IMoniker ** ppmkPrefix );

Description

IMoniker::CommonPrefixWith() creates a new moniker that consists of the common prefixes of the moniker on this moniker object and another moniker. If, for example, one moniker represents the path ``c:\projects\secret\art\pict1.bmp'' and another moniker represents the path ``c:\projects\secret\docs\chap1.txt,'' the common prefix of these two monikers would be a moniker representing the path ``c:\projects\secret.''

Notes to Callers

The IMoniker::CommonPrefixWith() method is primarily called in the implementation of the IMoniker::RelativePathTo() method. Clients using a moniker to locate an object rarely need to call this method.

Call this method only if pmkOther and this moniker are both absolute monikers. An absolute moniker is either a file moniker or a generic composite whose leftmost component is a file moniker that represents an absolute path. Do not call this method on relative monikers, because it would not produce meaningful results.

Notes to Implementors

Your implementation should first determine whether pmkOther is a moniker of a class that you recognize and for which you can provide special handling (for example, if it is of the same class as this moniker). If so, your implementation should determine the common prefix of the two monikers. Otherwise, it should pass both monikers in a call to the MonikerCommonPrefixWith() function, which correctly handles the generic case.

Parameters

pmkOther

[in] Pointer to the IMoniker() interface on another moniker to be compared with this one to determine whether there is a common prefix.

ppmkPrefix

[out] When successful, points to the IMoniker() pointer to the moniker that is the common prefix of this moniker and pmkOther. In this case, the implementation must call IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release(). If an error occurs or if there is no common prefix, the implementation should set ppmkPrefix to NULL.

Return Values

The method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

A common prefix exists that is neither this moniker nor pmkOther.

MK_S_NOPREFIX

No common prefix exists.

MK_S_HIM

The entire pmkOther moniker is a prefix of this moniker.

MK_S_US

The two monikers are identical.

MK_S_ME

This moniker is a prefix of the pmkOther moniker.

MK_E_NOTBINDABLE

This method was called on a relative moniker. It is not meaningful to take the common prefix on a relative moniker.

See Also

IMoniker::RelativePathTo(), MonikerCommonPrefixWith()  

IMoniker::ComposeWith()

NAME

IMoniker::ComposeWith() - Combines the current moniker with another moniker, creating a new composite moniker.

Synopsis

#include <objidl.h>

HRESULT ComposeWith(
        IMoniker * pmkRight,
        BOOL fOnlyIfNotGeneric,
        IMoniker ** ppmkComposite );

Description

Joining two monikers together is called composition. Sometimes two monikers of the same class can be combined in what is called non-generic composition. For example, a file moniker representing an incomplete path and another file moniker representing a relative path can be combined to form a single file moniker representing the complete path. Non-generic composition for a given moniker class can be handled only in the implementation of IMoniker::ComposeWith() for that moniker class.

Combining two monikers of any class is called generic composition, which can be accomplished through a call to the CreateGenericComposite() function.

Composition of monikers is an associative operation. That is, if A, B, and C are monikers, then:

Comp( Comp( A, B ), C )

(where Comp() represents the composition operation) is always equal to:

Comp( A, Comp( B, C ) )

Notes to Callers

To combine two monikers, you should call IMoniker::ComposeWith() rather than calling the CreateGenericComposite() function to give the first moniker a chance to perform a non-generic composition.

An object that provides item monkers to identify its objects would call IMoniker::ComposeWith() to provide a moniker that completely identifies the location of the object. This would apply, for example, to a server that supports linking to portions of a document, or a container that supports linking to embedded objects within its documents. In such a situation, you would do the following:

  1. Create an item moniker identifying an object.

  2. Get a moniker that identifies the object's container.

  3. Call IMoniker::ComposeWith() on the moniker identifying the container, passing the item moniker as the pmkRight parameter.

Most callers of IMoniker::ComposeWith() should set the fOnlyIfNotGeneric parameter to FALSE.

Notes to Implementors

You can use either non-generic or generic composition to compose the current moniker with the moniker that pmkRight points to. If the class of the moniker indicated by pmkRight is the same as that of the current moniker, it is possible to use the contents of pmkRight to perform a more intelligent non-generic composition.

In writing a new moniker class, you must decide if there are any kinds of monikers, whether of your own class or another class, to which you want to give special treatment. If so, implement IMoniker::ComposeWith() to check whether pmkRight is a moniker of the type that should have this treatment. To do this, you can call the moniker's GetClassID() method (derived from the IPersist() Interface), or, if you have defined a moniker object that supports a custom interface, you can call IUnknown::QueryInterface() on the moniker for that interface. An example of special treatment would be the non-generic composition of an absolute file moniker with a relative file moniker. The most common case of a special moniker is the inverse for your moniker class (whatever you return from your implementation of IMoniker::Inverse()).

If pmkRight completely negates the receiver so the resulting composite is empty, you should pass back NULL in ppmkComposite and return the status code S_OK.

If the pmkRight parameter is not of a class to which you give special treatment, examine fOnlyIfNotGeneric to determine what to do next. If fOnlyIfNotGeneric is TRUE, pass back NULL through ppmkComposite and return the status code MK_E_NEEDGENERIC. If fOnlyIfNotGeneric is FALSE, call the CreateGenericComposite() function to perform the composition generically.

Parameters

pmkRight

[in] Pointer to the IMoniker() interface on the moniker to compose onto the end of this moniker.

fOnlyIfNotGeneric

[in] If TRUE, the caller requires a non-generic composition, so the operation should proceed only if pmkRight is a moniker class that this moniker can compose with in some way other than forming a generic composite. If FALSE, the method can create a generic composite if necessary.

ppmkComposite

[out] When the call is successful, indirect pointer to the location of the resulting composite moniker pointer. In this case, the implementation must call IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release(). If an error occurs or if the monikers compose to nothing (e.g., composing an anti-moniker with an item moniker or a file moniker), ppmkComposite should be set to NULL.

Return Values

The method supports the standard return values E_OUTOFMEMORY and E_UNEXPECTED, as well as the following:

S_OK

The monikers were successfully combined.

MK_E_NEEDGENERIC

Indicates that fOnlyIfNotGeneric was TRUE, but the monikers could not be composed together without creating a generic composite moniker.

See Also

CreateGenericComposite(), IMoniker::Inverse()  

IMoniker::Enum()

NAME

IMoniker::Enum() - Supplies a pointer to an enumerator that can enumerate the components of a composite moniker.

Synopsis

#include <objidl.h>

HRESULT Enum(
        BOOL fForward,
        IEnumMoniker ** ppenumMoniker );

Description

IMoniker::Enum() must supply an IEnumMoniker() pointer to an enumerator that can enumerate the components of a moniker. For example, the implementation of the IMoniker::Enum() method for a generic composite moniker creates an enumerator that can determine the individual monikers that make up the composite, while the IMoniker::Enum() method for a file moniker creates an enumerator that returns monikers representing each of the components in the path.

Notes to Callers

Call this method to examine the components that make up a composite moniker.

Notes to Implementors

If the new moniker class has no discernible internal structure, your implementation of this method can simply return S_OK and set ppenumMoniker to NULL.

Parameters

fForward

[in] If TRUE, enumerates the monikers from left to right. If FALSE, enumerates from right to left.

ppenumMoniker

[out] When successful, indirect pointer to an IEnumMoniker() enumerator on this moniker. In this case, the implementation must call IUnknown::AddRef() on the parameter. It is the caller's responsibility to call IUnknown::Release(). If an error occurs or if the moniker has no enumerable components, the implementation sets ppenumMoniker to NULL.

Return Values

The method supports the standard return values E_OUTOFMEMORY and E_UNEXPECTED, as well as the following:

S_OK

Indicates success. This value is returned even if the moniker does not provide an enumerator (if ppenumMoniker equals NULL).

See Also

IEnumXXXX  

IMoniker::GetDisplayName()

NAME

IMoniker::GetDisplayName() - Gets the display name , which is a user-readable representation of this moniker.

Synopsis

#include <objidl.h>

HRESULT GetDisplayName(
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        LPOLESTR * ppszDisplayName );

Description

IMoniker::GetDisplayName() provides a string that is a displayable representation of the moniker. A display name is not a complete representation of a moniker's internal state; it is simply a form that can be read by users. As a result, it is possible (though rare) for two different monikers to have the same display name. While there is no guarantee that the display name of a moniker can be parsed back into that moniker when calling the MkParseDisplayName() function with it, failure to do so is rare.

As examples, the file moniker implementation of this method supplies the path the moniker represents, and an item moniker's display name is the string identifying the item that is contained in the moniker.

Notes to Callers

It is possible that retrieving a moniker's display name may be an expensive operation. For efficiency, you may want to cache the results of the first successful call to IMoniker::GetDisplayName(), rather than making repeated calls.

Notes to Implementors

If you are writing a moniker class in which the display name does not change, simply cache the display name and supply the cached name when requested. If the display name can change over time, getting the current display name might mean that the moniker has to access the object's storage or bind to the object, either of which can be expensive operations. If this is the case, your implementation of IMoniker::GetDisplayName() should return MK_E_EXCEEDEDDEADLINE if the name cannot be retrieved by the time specified in the bind context's BIND_OPTS structure.

A moniker that is intended to be part of a generic composite moniker should include any preceding delimiter (such as ``\'') as part of its display name. For example, the display name returned by an item moniker includes the delimiter specified when it was created with the CreateItemMoniker() function. The display name for a file moniker does not include a delimiter because file monikers are always expected to be the leftmost component of a composite.

Parameters

pbc

[in] Pointer to the IBindCtx() interface on the bind context to be used in this operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

pmkToLeft

[in] If the moniker is part of a composite moniker, pointer to the moniker to the left of this moniker. This parameter is primarily used by moniker implementers to enable cooperation between the various components of a composite moniker. Moniker clients should pass NULL.

ppszDisplayName

[out] When successful, indirect pointer to a zero-terminated wide character string (two bytes per character) containing the display name of this moniker. The implementation must use IMalloc::Alloc() to allocate the string returned in ppszDisplayName, and the caller is responsible for calling IMalloc::Free() to free it. Both the caller and and the one called use the COM task allocator returned by CoGetMalloc(). If an error occurs, ppszDisplayName should be set to NULL.

Return Values

The method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The display name was successfully supplied.

MK_E_EXCEEDEDDEADLINE

The binding operation could not be completed within the time limit specified by the bind context's BIND_OPTS structure.

E_NOTIMPL

There is no display name.

See Also

IMoniker::ParseDisplayName(), MkParseDisplayName()  

IMoniker::GetTimeOfLastChange()

NAME

IMoniker::GetTimeOfLastChange() - Provides a number representing the time the object identified by this moniker was last changed. To be precise, the time returned is the earliest time COM can identify after which no change has occurred, so this time may be later than the time of the last change to the object.

Synopsis

#include <objidl.h>

HRESULT GetTimeOfLastChange(
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        FILETIME * pFileTime );

Description

Notes to Callers

If you're caching information returned by the object identified by the moniker, you may want to ensure that your information is up-to-date. To do so, you would call IMoniker::GetTimeOfLastChange() and compare the time returned with the time you last retrieved information from the object.

For the monikers stored within linked objects, IMoniker::GetTimeOfLastChange() is primarily called by the default handler's implementation of IOleObject::IsUpToDate. Container applications call IOleObject::IsUpToDate to determine if a linked object (or an embedded object containing linked objects) is up-to-date without actually binding to the object. This enables an application to determine quickly which linked objects require updating when the end user opens a document. The application can then bind only those linked objects that need updating (after prompting the end user to determine whether they should be updated), instead of binding every linked object in the document.

Notes to Implementors

It is important to perform this operation quickly because, for linked objects, this method is called when a user first opens a compound document. Consequently, your IMoniker::GetTimeOfLastChange() implementation should not bind to any objects. In addition, your implementation should check the deadline parameter in the bind context and return MK_E_EXCEEDEDDEADLINE if the operation cannot be completed by the specified time.

There are a number of strategies you can use in your implementations:

Parameters

pbc

[in] Pointer to the bind context to be used in this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

pmkToLeft

[in] If the moniker is part of a composite moniker, pointer to the moniker to the left of this moniker. This parameter is primarily used by moniker Implementers to enable cooperation between the various components of a composite moniker. Moniker clients should pass NULL.

pFileTime

[out] Pointer to the FILETIME structure receiving the time of last change. A value of {0xFFFFFFFF,0x7FFFFFFF} indicates an error (for example, exceeded time limit, information not available).

Return Values

The method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The method successfully returned a time.

MK_E_EXCEEDEDDEADLINE

The binding operation could not be completed within the time limit specified by the bind context's BIND_OPTS structure.

MK_E_CONNECTMANUALLY

The operation was unable to connect to the storage for this object, possibly because a network device could not be connected to. For more information, see IMoniker::BindToObject().

MK_E_UNAVAILABLE

The time of the change is unavailable, and will not be available no matter what deadline is used.

See Also

IBindCtx::GetRunningObjectTable(), IRunningObjectTable::GetTimeOfLastChange()  

IMoniker::Hash()

NAME

IMoniker::Hash() - Calculates a 32-bit integer using the internal state of the moniker.

Synopsis

#include <objidl.h>

HRESULT Hash(
        DWORD * pdwHash );

Description

Notes to Callers

You can use the value returned by this method to maintain a hash table of monikers. The hash value determines a hash bucket in the table. To search such a table for a specified moniker, calculate its hash value and then compare it to the monikers in that hash bucket using IMoniker::IsEqual().

Notes to Implementors

The hash value must be constant for the lifetime of the moniker. Two monikers that compare as equal using IMoniker::IsEqual() must hash to the same value.

Marshaling and then unmarshaling a moniker should have no effect on its hash value. Consequently, your implementation of IMoniker::Hash() should rely only on the internal state of the moniker, not on its memory address.

Parameters

pdwHash

[out] Pointer to the hash value.

Return Values

S_OK

Successfully received a 32-bit integer hash value.

See Also

IMoniker::IsEqual()  

IMoniker::Inverse()

NAME

IMoniker::Inverse() - Provides a moniker that, when composed to the right of this moniker or one of similar structure, will destroy it (the moniker will compose to nothing).

Synopsis

#include <objidl.h>

HRESULT Inverse(
        IMoniker ** ppmk );

Description

The inverse of a moniker is analogous to the ``..'' directory in MS-DOS file systems; the ``..'' directory acts as the inverse to any other directory name, because appending ``..'' to a directory name results in an empty path. In the same way, the inverse of a moniker typically is also the inverse of all monikers in the same class. However, it is not necessarily the inverse of a moniker of a different class.

The inverse of a composite moniker is a composite consisting of the inverses of the components of the original moniker, arranged in reverse order. For example, if the inverse of A is Inv( A ) and the composite of A, B, and C is Comp( A, B, C ), then:

Inv( Comp( A, B, C ) )

is equal to:

Comp( Inv( C ), Inv( B ), Inv( A ) ).

Not all monikers have inverses. Most monikers that are themselves inverses, such as anti-monikers, do not have inverses. Monikers that have no inverse cannot have relative monikers formed from inside the objects they identify to other objects outside.

Notes to Callers

An object that is using a moniker to locate another object usually does not know the class of the moniker it is using. To get the inverse of a moniker, you should always call IMoniker::Inverse() rather than the CreateAntiMoniker() function, because you cannot be certain that the moniker you're using considers an anti-moniker to be its inverse.

The IMoniker::Inverse() method is also called by the implementation of the IMoniker::RelativePathTo() method, to assist in constructing a relative moniker.

Notes to Implementors

If your monikers have no internal structure, you can call the CreateAntiMoniker() function in to get an anti-moniker in your implementation of IMoniker::Inverse(). In your implementation of IMoniker::ComposeWith(), you need to check for the inverse you supply in the implementation of IMoniker::Inverse().

Parameters

ppmk

[out] When successful, indirect pointer to the IMoniker() interface on a moniker that is the inverse of this moniker. In this case, the implementation must call IUnknown::AddRef() on the parameter. It is the caller's responsibility to call IUnknown::Release(). If an error occurs, the implementation should set ppmk to NULL.

Return Values

The method supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The inverse moniker has been returned successfully.

MK_E_NOINVERSE

The moniker class does not have an inverse.

See Also

CreateAntiMoniker(), IMoniker::ComposeWith(), IMoniker::RelativePathTo()  

IMoniker::IsEqual()

NAME

IMoniker::IsEqual() - Compares this moniker with a specified moniker and indicates whether they are identical.

Synopsis

#include <objidl.h>

HRESULT IsEqual(
        IMoniker * pmkOtherMoniker );

Description

Previous implementations of the Running Object Table (ROT) called this method. The current implementation of the ROT uses the IROTData() interface instead.

Notes to Callers

Call this method to determine if two monikers are identical or not. Note that the reduced form of a moniker is considered different from the unreduced form. You should call the IMoniker::Reduce() method before calling IMoniker::IsEqual(), because a reduced moniker is in its most specific form. IMoniker::IsEqual() may return S_FALSE on two monikers before they are reduced, and S_OK after they are reduced.

Notes to Implementors

Your implementation should not reduce the current moniker before performing the comparison. It is the caller's responsibility to call IMoniker::Reduce() in order to compare reduced monikers.

Note that two monikers that compare as equal must hash to the same value using IMoniker::Hash().

Parameters

pmkOtherMoniker

[in] Pointer to the IMoniker() interface on the moniker to be used for comparison with this one (the one from which this method is called).

Return Values

S_OK

The two monikers are identical.

S_FALSE

The two monikers are not identical.

See Also

IMoniker::Reduce(), IMoniker::Hash(), IROTData()  

IMoniker::IsRunning()

NAME

IMoniker::IsRunning() - Determines whether the object identified by this moniker is currently loaded and running.

Synopsis

#include <objidl.h>

HRESULT IsRunning((
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        IMoniker * pmkNewlyRunning );

Description

Notes to Callers

If speed is important when you're requesting services from the object identified by the moniker, you may want those services only if the object is already running (because loading an object into the running state may be time-consuming). In such a situation, you'd call IMoniker::IsRunning() to determine if the object is running.

For the monikers stored within linked objects, IMoniker::IsRunning() is primarily called by the default handler's implementation of IOleLink::BindIfRunning.

Notes to Implementors

To get a pointer to the Running Object Table (ROT), your implementation should call IBindCtx::GetRunningObjectTable() on the pbc parameter. Your implementation can then call IRunningObjectTable::IsRunning() to determine whether the object identified by the moniker is running. Note that the object identified by the moniker must have registered itself with the ROT when it first began running.

Parameters

pbc

[in] Pointer to the IBindCtx interface on the bind context to be used in this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

pmkToLeft

[in] Pointer to the IMoniker interface on the moniker to the left of this moniker if this moniker is part of a composite. This parameter is primarily used by moniker Implementers to enable cooperation between the various components of a composite moniker; moniker clients can usually pass NULL.

pmkNewlyRunning

[in] Pointer to the IMoniker interface on the moniker most recently added to the Running Object Table (ROT). This can be NULL. If non-NULL, the implementation can return the results of calling IMoniker::IsEqual() on the pmkNewlyRunning parameter, passing the current moniker. This parameter is intended to enable IMoniker::IsRunning() implementations that are more efficient than just searching the ROT, but the implementation can choose to ignore pmkNewlyRunning without causing any harm.

Return Values

The method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The moniker is running.

S_FALSE

The moniker is not running.

See Also

IBindCtx::GetRunningObjectTable(), IRunningObjectTable::IsRunning()  

IMoniker::IsSystemMoniker()

NAME

IMoniker::IsSystemMoniker() - Indicates whether this moniker is of one of the system-supplied moniker classes.

Synopsis

#include <objidl.h>

HRESULT IsSystemMoniker(
        DWORD * pdwMksys );

Description

Notes to Callers

New values of the MKSYS enumeration may be defined in the future; therefore you should explicitly test for each value you are interested in.

Notes to Implementors

Your implementation of this method must return MKSYS_NONE. You cannot use this function to identify your own monikers (for example, in your implementation of IMoniker::ComposeWith()). Instead, you should use your moniker's implementation of IPersist::GetClassID() or use IUnknown::QueryInterface() to test for your own private interface.

Parameters

pdwMksys

[out] Pointer to an integer that is one of the values from the MKSYS enumeration, and refers to one of the COM moniker classes. This parameter cannot be NULL.

Return Values

S_OK

The moniker is a system moniker.

S_FALSE

The moniker is not a system moniker.

See Also

IPersist::GetClassID(), MKSYS  

IMoniker::ParseDisplayName()

NAME

IMoniker::ParseDisplayName() - Reads as many characters of the specified display name as it understands and builds a moniker corresponding to the portion read; this procedure is known as "parsing" the display name.

Synopsis

#include <objidl.h>

HRESULT ParseDisplayName(
        IBindCtx * pbc,
        IMoniker * pmkToLeft,
        LPOLESTR pszDisplayName,
        ULONG * pchEaten,
        IMoniker ** ppmkOut );

Description

Notes to Callers

Moniker clients do not typically call IMoniker::ParseDisplayName() directly. Instead, they call the MkParseDisplayName() function when they want to convert a display name into a moniker (for example, in implementing the Links dialog box for a container application, or for implementing a macro language that supports references to objects outside the document). That function first parses the initial portion of the display name itself.

It then calls IMoniker::ParseDisplayName() on the moniker it has just created, passing the remainder of the display name and getting a new moniker in return; this step is repeated until the entire display name has been parsed.

Notes to Implementors

Your implementation may be able to perform this parsing by itself if your moniker class is designed to designate only certain kinds of objects. Otherwise, you must get an IParseDisplayName() interface pointer for the object identified by the moniker-so-far (i.e., the composition of pmkToLeft and this moniker) and then return the results of calling IParseDisplayName::ParseDisplayName().

There are different strategies for getting an IParseDisplayName() pointer:

Any objects that are bound should be registered with the bind context (see IBindCtx::RegisterObjectBound()) to ensure that they remain running for the duration of the parsing operation.

Parameters

pbc

[in] Pointer to the IBindCtx() interface on the bind context to be used in this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

pmkToLeft

[in] Pointer to the IMoniker() interface on the moniker that has been built out of the display name up to this point.

pszDisplayName

[in] Pointer to a zero-terminated string containing the remaining display name to be parsed. For Win32 applications, the LPOLESTR type indicates a wide character string (two bytes per character); otherwise, the string has one byte per character.

pchEaten

[out] Pointer to the number of characters in pszDisplayName that were consumed in this step.

ppmkOut

[out] When successful, indirect pointer to the IMoniker() interface on the moniker that was built from pszDisplayName. In this case, the implementation must call IUnknown::AddRef() on the parameter; it is the caller's responsibility to call IUnknown::Release(). If an error occurs, the implementation sets ppmkOut to NULL.

Return Values

The method supports the standard return values E_OUTOFMEMORY and E_UNEXPECTED, as well as the following:

S_OK

The parsing operation was completed successfully.

MK_E_SYNTAX

An error in the syntax of the input components (pmkToLeft, this moniker, and pszDisplayName). For example, a file moniker returns this error if pmkToLeft is non-NULL, and an item moniker returns it if pmkToLeft is NULL.

IMoniker::BindToObject() errors

Parsing display names may cause binding. Thus, any error associated with this function may be returned.

See Also

IParseDisplayName(), MkParseDisplayName()  

IMoniker::Reduce()

NAME

IMoniker::Reduce() - Returns a reduced moniker; that is, another moniker that refers to the same object as this moniker but can be bound with equal or greater efficiency.

Synopsis

#include <objidl.h>

HRESULT Reduce(
        IBindCtx * pbc,
        DWORD dwReduceHowFar,
        IMoniker ** ppmkToLeft,
        IMoniker ** ppmkReduced );

Description

IMoniker::Reduce() is intended for the following uses:

The intent of the MKRREDUCE flags passed in the dwReduceHowFar parameter is to provide the ability to programmatically reduce a moniker to a form whose display name is recognizable to the user. For example, paths in the file system, bookmarks in word-processing documents, and range names in spreadsheets are all recognizable to users. In contrast, a macro or an alias encapsulated in a moniker are not recognizable to users.

Notes to Callers

The scenarios described above are not currently implemented by the system-supplied moniker classes.

You should call IMoniker::Reduce() before comparing two monikers using the IMoniker::IsEqual() method, because a reduced moniker is in its most specific form. IMoniker::IsEqual() may return S_FALSE on two monikers before they are reduced and return S_OK after they are reduced.

Notes to Implementors

If the current moniker can be reduced, your implementation must not reduce the moniker in-place. Instead, it must return a new moniker that represents the reduced state of the current one. This way, the caller still has the option of using the non-reduced moniker (for example, enumerating its components). Your implementation should reduce the moniker at least as far as is requested.

Parameters

pbc

[in] Pointer to the IBindCtx() interface on the bind context to be used in this binding operation. The bind context caches objects bound during the binding process, contains parameters that apply to all operations using the bind context, and provides the means by which the moniker implementation should retrieve information about its environment. For more information, see IBindCtx().

dwReduceHowFar

[in] DWORD that specifies how far this moniker should be reduced. This parameter must be one of the values from the MKRREDUCE enumeration.

ppmkToLeft

[in, out] On entry, indirect pointer to the moniker to the left of this moniker, if this moniker is part of a composite. This parameter is primarily used by moniker Implementers to enable cooperation between the various components of a composite moniker; moniker clients can usually pass NULL.

On return, ppmkToLeft is usually set to NULL, indicating no change in the original moniker to the left. In rare