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:
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.
(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.
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:
A
BIND_OPTS
structure containing a set
of parameters that do not change during the binding operation.
When a composite
moniker is bound, each component uses the same bind context, so it acts as
a mechanism for passing the same parameters to each component of a composite
moniker.
A set of pointers to objects that the binding operation has activated. The bind context holds pointers to these bound objects, keeping them loaded and thus eliminating redundant activations if the objects are needed again during subsequent binding operations.
A pointer to the Running Object Table on the machine of the
process that started the bind operation.
Moniker implementations that need
to access the Running Object Table should use the
IBindCtx::GetRunningObjectTable()
method rather than using the
GetRunningObjectTable()
function.
This allows future enhancements to the system's
IBindCtx()
implementation to modify binding behavior.
A table of interface pointers, each associated with a string
key.
This capability enables moniker implementations to store interface pointers
under a well-known string so that they can later be retrieved from the bind
context.
For example, COM defines several string keys (e.g., ``ExceededDeadline'', ``ConnectManually'') that can be used to
store a pointer to the object that caused an error during a binding operation.
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.
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:
Call the
CreateBindCtx()
function to create
a bind context
and get a pointer to the
IBindCtx()
interface on the bind
context
object..
If desired (although this is rarely necessary), the moniker
client can call
IBindCtx::SetBindOptions()
to specify the bind options.
Pass the bind context as a parameter to the desired
IMoniker()
method (usually
IMoniker::BindToObject()).
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.
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
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. |
CreateBindCtx(),
IMoniker(),
IOleItemContainer(),
IParseDisplayName()
- Supplies a pointer to an
IBindCtx::EnumObjectParam()IEnumString()
interface
on an enumerator that can return the keys of the bind context's string-keyed
table of pointers.
HRESULT EnumObjectParam(
#include <objidl.h>
IEnumString ** ppenum
);
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().
[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().
This method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKAn enumerator was successfully created and the pointer supplied.
IBindCtx::RegisterObjectParam(),
IEnumString()
- Returns the binding options stored in this bind context.
IBindCtx::GetBindOptions()
HRESULT GetBindOptions(
#include <objidl.h>
BIND_OPTS * pbindopts
);
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.
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.
[in, out] Pointer to an initialized
BIND_OPTS
structure
on entry that receives the current binding parameters on return.
This method supports the standard return value
E_UNEXPECTED, as well as
the following:
S_OKThe stored binding options were successfully returned.
- Retrieves the pointer associated with the specified key in the
bind context's string-keyed table of pointers.
IBindCtx::GetObjectParam()
HRESULT GetObjectParam(
#include <objidl.h>
LPOLESTR pszKey,
IUnknown ** ppunk
);
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.
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).
[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.
[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.
This method supports the standard return value
E_FAIL,
as well as the
following:
S_OKThe pointer associated with the specified key was successfully returned.
IBindCtx::RegisterObjectParam(),
IBindCtx::EnumObjectParam()
- Provides an interface pointer to the Running Object Table (ROT)
for the machine on which this bind context is running.
IBindCtx::GetRunningObjectTable()
HRESULT GetRunningObjectTable((
#include <objidl.h>
IRunningObjectTable ** pprot
);
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.
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.
[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().
This method supports the standard return values
E_OUTOFMEMORY
and
E_UNEXPECTED, as well as the following:
S_OKA pointer to the ROT was returned successfully.
IMoniker(),
IRunningObjectTable()
- Calls
IBindCtx::RegisterObjectBound()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.
HRESULT RegisterObjectBound(
#include <objidl.h>
IUnknown * punk
);
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.
[in] Pointer to the
IUnknown()
interface
on the object
that is being registered as bound.
This method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKThe object was successfully registered.
IBindCtx::ReleaseBoundObjects(),
IBindCtx::RevokeObjectBound(),
IRunningObjectTable::GetObject()
- Stores an
IBindCtx::RegisterObjectParam()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.
HRESULT RegisterObjectParam(
#include <objidl.h>
LPOLESTR pszKey,
IUnknown * punk
);
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.
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:
It is replaced in the table by another object with the same key.
It is removed from the table by a call to
IBindCtx::RevokeObjectParam().
The bind context is released. All registered objects are released when the bind context is released.
[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.
[in] Pointer to the
IUnknown()
interface
on the object
that is to be registered.
This method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKThe pointer was successfully registered under the specified string.
IBindCtx::GetObjectParam(),
IBindCtx::RevokeObjectParam(),
IBindCtx::EnumObjectParam()
- Releases all pointers to all objects that were previously registered
by calls to
IBindCtx::ReleaseBoundObjects()IBindCtx::RegisterObjectBound().
HRESULT ReleaseBoundObjects(
#include <objidl.h>
void
);
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.
S_OKThe objects were released successfully.
IBindCtx::RegisterObjectBound()
- Releases the
IBindCtx::RevokeObjectBound()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.
HRESULT RevokeObjectBound(
#include <objidl.h>
IUnknown * punk
);
You rarely call this method. This method is included for completeness.
[in] Pointer to the
IUnknown()
interface
on the object
to be released.
S_OKThe object was released successfully.
MK_E_NOTBOUNDIndicates that
punk
was not previously
registered
with a call to
IBindCtx::RegisterObjectBound().
IBindCtx::RegisterObjectBound()
- 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::RevokeObjectParam()IBindCtx::RegisterObjectParam().
HRESULT RevokeObjectParam(
#include <objidl.h>
LPOLESTR pszKey
);
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.
[in] Pointer to a zero-terminated wide character string (two bytes per character) containing the key to remove. Key string comparison is case-sensitive.
S_OKThe specified key was successfully removed from the table.
S_FALSENo object has been registered with the specified key.
IBindCtx::RegisterObjectParam()
- Specifies new values for the binding parameters stored in the
bind context.
Subsequent binding operations can call
IBindCtx::SetBindOptions()IBindCtx::GetBindOptions()
to retrieve the parameters.
HRESULT SetBindOptions(
#include <objidl.h>
BIND_OPTS * pbindopts
);
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.
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.
[in] Pointer to a
BIND_OPTS2
or a
BIND_OPTS
structure containing the binding parameters.
This method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKThe parameters were stored successfully.
Bind_OPTS2,
IBindCtx::GetBindOptions()
IClassActivator()
Specifies a method that retrieves
a class object.
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().
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
Description
|
GetClassObject
|
Retrieves a class object. |
- Retrieves a class object.
Similar to
IClassActivator::GetClassObject()CoGetClassObject(),
HRESULT GetClassObject(
#include <objidl.h>
REFCLSID * pClassID,
DWORD dwClsContext,
LCID locale,
REFIID riid,
void ** ppv
);
This method returns the class identifier (CLSID) for an object, used in later operations to load object-specific code into the caller's context.
[in] Points to the CLSID that Identifies the class whose class object is to be retrieved.
[in] The context in which the class is expected to run; values
are taken
from the
CLSCTX
enumeration.
[in] Any LCID constant as defined in
WINNLS.H.
[in] IID of the interface on the object to which a pointer is desired.
[out] On successful return, an indirect pointer to the requested interface.
This method supports the standard return value
E_FAIL,
as well as the
following:
S_OK
The CLSID was successfully returned.
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().
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.
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
IMoniker::Enum()
method gets a pointer
to an
IEnumMoniker()
implementation that can enumerate forwards
or backwards
through the components of the moniker.
For a description of how two of the
system-supplied types of monikers enumerate their components, see
Section
Section 16.2.9
and Section
Section 16.2.10.
The
IRunningObjectTable::EnumRunning()
method returns a
pointer to an
IEnumMoniker()
implementation that can enumerate
the
monikers registered in a Running Object Table.
The prototypes of the methods are as follows:
HRESULT Next(
#include <objidl.h>
ULONG celt,
IMoniker * rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumMoniker ** ppenum
);
IEnumXXXX,
IMoniker::Enum(),
IRunningObjectTable::EnumRunning()
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().
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.
Call the methods of
IEnumString()
to enumerate through
a set of
strings.
The prototypes of the member functions are as follows:
HRESULT Next(
#include <objidl.h>
ULONG celt,
LPOLESTR * rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumString ** ppenum
);
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().
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.
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:
HRESULT Next(
#include <objidl.h>
ULONG celt,
IUnknown ** rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumUnknown ** ppenum
);
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 can be saved to a persistent storage. When a moniker is loaded back into memory, it still identifies the same object.
Monikers support an operation called ``binding,'' which is the process of locating the object named by the moniker, activating it (loading it into memory) if it is not already active, and returning a pointer to a requested interface on that object.
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.
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).
Two kinds of objects call the methods of
IMoniker:
A component that contains one or more objects to be identified with a moniker and must provide the moniker to other objects
A client object that must bind to the object identified by the moniker
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.
File monikers
-- based on a path in
the file system.
File
monikers can be used to identify objects that are saved as files.
The
associated creation function is
CreateFileMoniker.
Item monikers
-- based on a string
that identifies an object
in a container.
Item monikers can be used to identify objects smaller than
a
file, such as embedded objects in a compound document and pseudo-objects (like
a range of cells in a spreadsheet).
The associated creation function is
CreateItemMoniker().
Generic composite monikers
-- consists
of two or more
monikers of arbitrary type that have been composed together.
Generic composite
monikers allow monikers of different classes to be used in combination.
The
associated creation function is
CreateGenericComposite().
Anti-monikers
-- the inverse of file,
item, or pointer
monikers.
Anti-monikers are used primarily for constructing relative monikers,
which are analogous to relative path (such as ``..\backup\report.old''), and
which specify a location of an object
relative
to the
location of
another object).
The associated creation function is
CreateAntiMoniker().
Pointer monikers
-- a non-persistent
moniker that wraps an
interface pointer to an object loaded in memory.
Whereas most monikers identify
objects that can be saved to persistent storage, pointer monikers identify
objects that cannot.
The associated creation function is
CreatePointerMoniker().
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.
Class monikers
-- these represent
an object class.
Class
monikers bind to the class object of the class for which they are created.
The
associated creation function is
CreateClassComposite.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
IPersist Methods
|
Description
|
GetClassID()
|
Returns the object's CLSID. |
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. |
|
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. |
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
- 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.
IMoniker::BindToObject()
HRESULT BindToObject(
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
REFIID riidResult,
void ** ppvResult
);
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.
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:
Create a bind context object with a call to the
CreateBindCtx()
function.
Call
IMoniker::BindToObject()
using the
moniker, retrieving a pointer
to a desired interface on the identified object.
Release()
the bind context.
Through the acquired interface pointer, perform the desired operations on the object.
When finished with the object, release the object's interface pointer.
The following code fragment illustrates these steps:
// pMnk is anIMoniker()* 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.
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).
[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.
[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.
[in] IID of the interface the client wishes to use to communicate with the object that the moniker identifies.
[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.
The method supports the standard return values
E_UNEXPECTED
and
E_OUTOFMEMORY, as well as the following:
S_OKThe binding operation was successful.
MK_E_NOOBJECTThe 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_EXCEEDEDDEADLINEThe binding operation could not be completed within the time
limit specified
by the bind context's
BIND_OPTS
structure.
MK_E_CONNECTMANUALLYThe 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_INTERMEDIATEINTERFACENOTSUPPORTEDAn 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_ACCESSDENIEDUnable to access the storage object.
IOleItemContainer::GetObject()
errorsIf the moniker used to bind to an object contains an item moniker, errors associated with this method can be returned.
BindMoniker(),
IMoniker::BindToStorage()
- Retrieves an interface pointer to the storage that contains the
object identified by the moniker.
Unlike the
IMoniker::BindToStorage()IMoniker::BindToObject()
method, this method does not activate the object identified by
the moniker.
HRESULT BindToStorage(
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
REFIID riid,
void ** ppvObj
);
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.
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.
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).
[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().
[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.
[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().
[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.
The method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKThe binding operation was successful.
MK_E_NOSTORAGEThe object identified by this moniker does not have its own storage.
MK_E_EXCEEDEDDEADLINEThe operation could not be completed within the time limit
specified
by the bind context's
BIND_OPTS
structure.
MK_E_CONNECTMANUALLYThe 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_INTERMEDIATEINTERFACENOTSUPPORTEDAn 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_ACCESSDENIEDUnable to access the storage object.
IOleItemContainer::GetObject()
errorsBinding to a moniker containing an item moniker can return any of the errors associated with this function.
- 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.
IMoniker::CommonPrefixWith()
HRESULT CommonPrefixWith(
#include <objidl.h>
IMoniker * pmkOther,
IMoniker ** ppmkPrefix
);
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.''
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.
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.
[in] Pointer to the
IMoniker()
interface
on another
moniker to be compared with this one to determine whether there is a common
prefix.
[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.
The method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKA common prefix exists that is neither this moniker nor pmkOther.
MK_S_NOPREFIXNo common prefix exists.
MK_S_HIMThe entire pmkOther moniker is a prefix of this moniker.
MK_S_USThe two monikers are identical.
MK_S_METhis moniker is a prefix of the pmkOther moniker.
MK_E_NOTBINDABLEThis method was called on a relative moniker. It is not meaningful to take the common prefix on a relative moniker.
IMoniker::RelativePathTo(),
MonikerCommonPrefixWith()
- Combines the current moniker with another moniker, creating a
new composite moniker.
IMoniker::ComposeWith()
HRESULT ComposeWith(
#include <objidl.h>
IMoniker * pmkRight,
BOOL fOnlyIfNotGeneric,
IMoniker ** ppmkComposite
);
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 ) )
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:
Create an item moniker identifying an object.
Get a moniker that identifies the object's container.
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.
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.
[in] Pointer to the
IMoniker()
interface
on the moniker
to compose onto the end of this moniker.
[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.
[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.
The method supports the standard return values
E_OUTOFMEMORY
and
E_UNEXPECTED, as well as the following:
S_OKThe monikers were successfully combined.
MK_E_NEEDGENERICIndicates that
fOnlyIfNotGeneric
was
TRUE, but the monikers could not be composed together without creating
a generic composite moniker.
CreateGenericComposite(),
IMoniker::Inverse()
- Supplies a pointer to an enumerator that can enumerate the components of a
composite moniker.
IMoniker::Enum()
HRESULT Enum(
#include <objidl.h>
BOOL fForward,
IEnumMoniker ** ppenumMoniker
);
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.
Call this method to examine the components that make up a composite moniker.
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.
[in] If
TRUE, enumerates the monikers from
left to
right.
If
FALSE, enumerates from right to left.
[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.
The method supports the standard return values
E_OUTOFMEMORY
and
E_UNEXPECTED, as well as the following:
S_OKIndicates success.
This value is returned even if the moniker
does not
provide an enumerator (if
ppenumMoniker
equals
NULL).
- Gets the display name , which is a user-readable representation
of this moniker.
IMoniker::GetDisplayName()
HRESULT GetDisplayName(
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
LPOLESTR * ppszDisplayName
);
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.
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.
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.
[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().
[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.
[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.
The method supports the standard return value
E_OUTOFMEMORY,
as well as the following:
S_OKThe 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_NOTIMPLThere is no display name.
IMoniker::ParseDisplayName(),
MkParseDisplayName()
- 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.
IMoniker::GetTimeOfLastChange()
HRESULT GetTimeOfLastChange(
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
FILETIME * pFileTime
);
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.
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:
For many types of monikers, the
pmkToLeft
parameter identifies the
container of the object identified by this moniker.
If this is true of your
moniker class, you can simply call
IMoniker::GetTimeOfLastChange()
on the
pmkToLeft
parameter, since an object cannot have changed
at a date later
than its container.
You can get a pointer to the Running Object Table (ROT) by
calling
IBindCtx::GetRunningObjectTable()
on the
pbc
parameter, and
then calling
IRunningObjectTable::GetTimeOfLastChange(),
since the
ROT generally records the time of last change.
You can get the storage associated with this moniker (or the
pmkToLeft
moniker) and return the storage's last modification
time with
a call to
IStorage::Stat().
[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().
[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.
[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).
The method supports the standard return value
E_UNEXPECTED, as well as
the following:
S_OKThe method successfully returned a time.
MK_E_EXCEEDEDDEADLINEThe binding operation could not be completed within the time
limit specified
by the bind context's
BIND_OPTS
structure.
MK_E_CONNECTMANUALLYThe 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_UNAVAILABLEThe time of the change is unavailable, and will not be available no matter what deadline is used.
IBindCtx::GetRunningObjectTable(),
IRunningObjectTable::GetTimeOfLastChange()
- Calculates a 32-bit integer using the internal state of the moniker.
IMoniker::Hash()
HRESULT Hash(
#include <objidl.h>
DWORD * pdwHash
);
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().
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.
[out] Pointer to the hash value.
S_OKSuccessfully received a 32-bit integer hash value.
- 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).
IMoniker::Inverse()
HRESULT Inverse(
#include <objidl.h>
IMoniker ** ppmk
);
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 ) )
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.
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.
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().
[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.
The method supports the standard return value
E_OUTOFMEMORY, as well as
the following:
S_OKThe inverse moniker has been returned successfully.
MK_E_NOINVERSEThe moniker class does not have an inverse.
CreateAntiMoniker(),
IMoniker::ComposeWith(),
IMoniker::RelativePathTo()
- Compares this moniker with a specified moniker and indicates whether they
are identical.
IMoniker::IsEqual()
HRESULT IsEqual(
#include <objidl.h>
IMoniker * pmkOtherMoniker
);
Previous implementations of the Running Object Table (ROT) called this
method.
The current implementation of the ROT uses the
IROTData()
interface instead.
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.
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().
[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).
S_OKThe two monikers are identical.
S_FALSEThe two monikers are not identical.
IMoniker::Reduce(),
IMoniker::Hash(),
IROTData()
- Determines whether the object identified by this moniker is currently loaded
and running.
IMoniker::IsRunning()
HRESULT IsRunning((
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
IMoniker * pmkNewlyRunning
);
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.
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.
[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().
[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.
[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.
The method supports the standard return value
E_UNEXPECTED, as well as
the following:
S_OKThe moniker is running.
S_FALSEThe moniker is not running.
IBindCtx::GetRunningObjectTable(),
IRunningObjectTable::IsRunning()
- Indicates whether this moniker is of one of the system-supplied
moniker classes.
IMoniker::IsSystemMoniker()
HRESULT IsSystemMoniker(
#include <objidl.h>
DWORD * pdwMksys
);
New values of the
MKSYS
enumeration may be defined
in the
future; therefore you should explicitly test for each value you are interested
in.
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.
[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.
S_OKThe moniker is a system moniker.
S_FALSEThe moniker is not a system moniker.
- 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.
IMoniker::ParseDisplayName()
HRESULT ParseDisplayName(
#include <objidl.h>
IBindCtx * pbc,
IMoniker * pmkToLeft,
LPOLESTR pszDisplayName,
ULONG * pchEaten,
IMoniker ** ppmkOut
);
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.
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:
You can try to get the object's CLSID (by calling
IPersist::GetClassID()
on the object), and then call the
CoGetClassObject()
function, requesting the
IParseDisplayName()
interface on the class factory associated
with that
CLSID.
You can try to bind to the object itself to get an
IParseDisplayName()
pointer.
You can try binding to the object identified by
pmkToLeft
to get an
IOleItemContainer()
pointer, and then call
IOleItemContainer::GetObject()
to get an
IParseDisplayName()
pointer for the item.
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.
[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().
[in] Pointer to the
IMoniker()
interface
on the moniker
that has been built out of the display name up to this point.
[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.
[out] Pointer to the number of characters in pszDisplayName that were consumed in this step.
[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.
The method supports the standard return values
E_OUTOFMEMORY
and
E_UNEXPECTED, as well as the following:
S_OKThe parsing operation was completed successfully.
MK_E_SYNTAXAn 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()
errorsParsing display names may cause binding. Thus, any error associated with this function may be returned.
IParseDisplayName(),
MkParseDisplayName()
- 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.
IMoniker::Reduce()
HRESULT Reduce(
#include <objidl.h>
IBindCtx * pbc,
DWORD dwReduceHowFar,
IMoniker ** ppmkToLeft,
IMoniker ** ppmkReduced
);
IMoniker::Reduce()
is intended for the following
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 that tracks data as it moves about. When reduced, the moniker of the data in its current location is returned.
On file systems that support an identifier-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 identifiers.
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.
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.
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.
[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().
[in]
DWORD
that specifies how far this
moniker should
be reduced.
This parameter must be one of the values from the
MKRREDUCE
enumeration.
[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