To contact the authors with suggestions or comments, use csells@sellsbrothers.com, tewald@obelisk-llc.com and dbox@develop.com.
Monikers, on the other hand, provide a general-purpose way for a client to separate itself from the object binding policy. These object binding polices can be composed and stored in strings. These strings contain a string description of the binding policy and policy parameters. By building a custom moniker that takes a string-ized interface reference as a parameter, a client can use the standard moniker-based binding algorithm and bind to a running object via an interface reference. The MeowMoniker is an implementation of a moniker that can compose display names out of interface pointers and bind to objects via its display names.
To create a MeowMoniker from an interface pointer, MeowMoniker.dll exposes the CreateMeowMoniker() function:
STDAPI CreateMeowMoniker(
IUnknown* punk, // Pointer to the interface to be marshaled
REFIID riid, // Reference to the identifier of the interface
DWORD dwDestContext, // Destination context
DWORD mshlflags, // Reason for marshaling
IMoniker** ppmk); // Indirect pointer to the moniker
e.g.
IMoniker* pmk;
hr = CreateMeowMoniker(punkObject,
IID_IUnknown,
MSHCTX_DIFFERENTMACHINE,
MSHLFLAGS_NORMAL,
&pmk);
To obtain the MeowMoniker's display name, use the GetDisplayName() member function of the IMoniker interface:
HRESULT GetDisplayName(
IBindCtx *pbc, // Pointer to bind context to be used
IMoniker *pmkToLeft, // Pointer to moniker to the left in the composite
LPOLESTR *ppszDisplayName); //Indirect pointer to the display name
e.g.
IBindCtx* pbc;
hr = CreateBindCtx(0, &pbc);
wchar_t* pwszDisplayName;
hr = pmk->GetDisplayName(pbc, 0, &pwszDisplayName);
To parse a display name composed by the MeowMoniker, OLE32.dll exposes the MkParseDisplayName() function:
WINOLEAPI MkParseDisplayName(
LPBC pbc, // Pointer to the bind context object
LPCOLESTR szUserName, // Pointer to display name
ULONG FAR *pchEaten, // Pointer to the number of characters consumed
LPMONIKER FAR *ppmk); // Indirect pointer to the moniker
e.g.
IBindCtx* pbc;
hr = CreateBindCtx(0, &pbc);
IMoniker* pmk;
ULONG cchEaten;
hr = MkParseDisplayName(pbc,
pwszDisplayName,
&cchEaten,
&pmk);
To bind to a object, use the BindToObject() member function of the IMoniker interface:
HRESULT BindToObject(
IBindCtx *pbc, // Pointer to bind context object to be used
IMoniker *pmkToLeft,// Pointer to moniker that precedes this one in the composite
REFIID riidResult, // IID of interface pointer requested
void **ppvResult); // Indirect pointer to the specified interface on the object
e.g.
IUnknown* punk;
hr = pmk->BindToObject(pbc, 0, IID_IUnknown, (void**)&punk);
Note: The MeowMoniker does not current supportly composition or the IMoniker interface
member function BindToStorage().
[
object,
uuid(CB18CB8E-C7CC-11D0-9A44-00008600A105),
dual,
helpstring("DIFeline Interface"),
pointer_default(unique)
]
interface DIFeline : IDispatch
{
[id(1), helpstring("Returns the Meow Moniker name of an interface pointer")]
HRESULT GetDisplayName([in] IDispatch* pdisp, [out, retval] BSTR* pbstrName);
[id(2), helpstring("Returns an interface pointer given any moniker display name")]
HRESULT ParseDisplayName([in] BSTR bstrName, [out, retval] IDispatch** ppdisp);
};
The following is an example Active Server Page that creates an object on the server,
creates a display name using the object's interface pointer and uses the display
name to create a client-side script. The client-side script uses its own instance
of a feline object to parse the display name and bind to the object created on the
server-side.
<HEAD>
<TITLE>feline.asp</TITLE>
</HEAD>
<BODY>
<object classid="clsid:CB18CB8F-C7CC-11D0-9A44-00008600A105"
runat=server
id=feline>
</object>
<object classid="clsid:7CF322E0-29A9-11D0-B367-0080C7BC7884"
runat=server
id=pt>
</object>
<object classid="clsid:CB18CB8F-C7CC-11D0-9A44-00008600A105"
id=feline>
</object>
<script language=vbscript>
dim pt
set pt = feline.ParseDisplayName("<%= feline.GetDisplayName(pt) %>")
pt.x = 100
pt.y = 200
document.write pt.x & ", " & pt.y
</script>
</BODY>
</HTML>
STDMETHODIMP BindToObject(
IBindCtx* pbc,
IMoniker* pmkToLeft,
REFIID riidResult,
void** ppvResult);
STDMETHODIMP GetDisplayName(
IBindCtx* pbc,
IMoniker* pmkToLeft,
LPOLESTR* ppszDisplayName);
STDMETHODIMP ParseDisplayName(
IBindCtx* pbc,
IMoniker* pmkToLeft,
LPOLESTR pszDisplayName,
ULONG* pchEaten,
IMoniker** ppmkOut);
As a aid in parsing display names, the CComMoniker class provides the following
helper function:
bool MatchesProgID(
const wchar_t* pwszDisplayName, // Display name being parsed
const wchar_t** ppwszDisplayParam); // Pointer to character past :
This function checks the display name for a leading ProgID or VersionIndependentProgID
followed by a colon and returns a pointer to the first character of the display
name parameter(s), i.e. one character past the colon. The implementation of this
function requires the derived class to implement the following member functions:
virtual const wchar_t* ProgID() =0;
virtual const wchar_t* VersionIndependentProgID() =0;
e.g.
const wchar_t* ProgID() { return L"dm.meow.1"; }
const wchar_t* VersionIndependentProgID() { return L"dm.meow"; }