IMoniker
A moniker is a system object that identifies a COM object. Win32 has several functions for creating them, see references.
A moniker is bound to its target in a binding context, an object that implements IBindCtx.
Basic Usage
Monikers usually work under the hood. CoGetObject is a convenience function that retrieves an object from its display name. It calls MkParseDisplayName to get the moniker, then IMoniker::BindToObject to get the underlying object. Here’s some pseudo code for that.
HRESULT __stdcall CoGetObject(LPCWSTR pszDisplayName,
BIND_OPTS* pBindOptions, REFIID riid, void** ppv)
{
HRESULT hr = 0;
// Create the bind context.
IBindCtx* pBindCtx = 0;
hr = CreateBindCtx(0, &pBindCtx);
// Call MkParseDisplayName with the user's string.
ULONG chEaten;
IMoniker* pMoniker = 0;
hr = MkParseDisplayName(pBindCtx, pszDisplayName,
&chEaten, &pMoniker);
// Set the bind options requested by the caller.
hr = pBindCtx->SetBindOptions(pBindOptions);
// Call IMoniker::BindToObject to get the user's object.
hr = pMoniker->BindToObject(pBindCtx, NULL, riid, ppv);
// Release stuff.
pMoniker->Release();
pBindCtx->Release();
return hr;
}
Class Moniker
One use case of monikers is when you want to create an object with ‘constructor’ arguments. Internally, CoCreateInstance is a thin wrapper that calls CoGetClassObject, passing in the IID of the default IClassFactory, which does not support arguments.
We can work around this in C++ by calling CoGetClassObject directly and passing in the IID of a custom class factory:
interface IPrimeFactory : IUnknown
{
HRESULT CreatePrime([in] int starting_prime, [out, retval]IPrime** ppPrime);
};
IPrimeFactory* pPrimeFactory;
CoGetClassObject(CLSID_Prime, CLSCTX_SERVER, NULL, IID_IPrimeFactory, (void**)&pPrimeFactory);
IPrime* pPrime;
pPrimeFactory->CreatePrime(7, &pPrime);
pPrimeFactory->Release();
But to get to the factory interface from a scripting language, a moniker is needed. First the C++:
// We always need a bind context.
IBindCtx* pBindCtx;
CreateBindCtx(0, &pBindCtx);
// Convert the string to a moniker.
ULONG eaten;
IMoniker* pMoniker;
OLECHAR string[] =
L"clsid:10000013-0000-0000-0000-000000000001";
MkParseDisplayName(pBindCtx, string, &eaten, &pMoniker);
// Bind the moniker to the named object.
IPrimeFactory* pPrimeFactory;
pMoniker->BindToObject(pBindCtx, NULL, IID_IPrimeFactory,
(void**)&pPrimeFactory);
// Use the custom class object to create a Prime object.
IPrime* pPrime;
pPrimeFactory->CreatePrime(7, &pPrime);
// Now we have a Prime object.
int next_prime;
pPrime->GetNextPrime(&next_prime);
cout << next_prime << endl; // Displays 11
// Release all.
pPrimeFactory->Release();
pPrime->Release();
pBindCtx->Release();
pMoniker->Release();
The corresponding script looks something like this:
Dim myPrimeFactory As IPrimeFactory
Dim myPrime As IPrime
' Call MkParseDisplayName and IMoniker::BindToObject.
Set myPrimeFactory = _
GetObject("clsid:10000013-0000-0000-0000-000000000001")
' Call IPrimeFactory::CreatePrime.
Set myPrime = myPrimeFactory.CreatePrime(7)
' Call IPrime::GetNextPrime.
Print myPrime.GetNextPrime ' Displays 11
References
- CreateFileMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- CreateItemMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- CreatePointerMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- CreateAntiMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- CreateGenericComposite function (objbase.h) - Win32 apps | Microsoft Learn
- CreateClassMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- URL Moniker Functions - Win32 apps | Microsoft Learn
- CreateObjrefMoniker function (objbase.h) - Win32 apps | Microsoft Learn
- MkParseDisplayName function (objbase.h) - Win32 apps | Microsoft Learn
- CoGetObject function (objbase.h) - Win32 apps | Microsoft Learn