[Previous] [Contents] [Next]

The Running Object Table

The Running Object Table (ROT) is a machine-wide table in which objects can register themselves. The ROT enables a moniker to check whether an object is already running when the client application calls the IMoniker::BindToObject method to bind to the object. Thus, the ROT acts mainly as a binding optimization to help you avoid unnecessarily instantiating a new object when binding. You access the ROT through the IRunningObjectTable interface. The GetRunningObjectTable function provides access to the system implementation of this interface. The IRunningObjectTable interface is defined here in IDL notation:

interface IRunningObjectTable : IUnknown
{
    // Add an object to the ROT.
    HRESULT Register(
        [in] DWORD grfFlags,
        [in, unique] IUnknown *punkObject,
        [in, unique] IMoniker *pmkObjectName,
        [out] DWORD *pdwRegister);

    // Remove an object from the ROT.
    HRESULT Revoke(
        [in] DWORD dwRegister);

    // Check whether the object named by a moniker is 
    // in the ROT.
    HRESULT IsRunning(
        [in, unique] IMoniker *pmkObjectName);
    // Get a pointer to the object named by a moniker from 
    // the ROT.
    HRESULT GetObject(
        [in, unique] IMoniker *pmkObjectName,
        [out] IUnknown **ppunkObject);

    // Specify the time an object in the ROT was last modified.
    HRESULT NoteChangeTime(
        [in] DWORD dwRegister,
        [in] FILETIME *pfiletime);

    // Get the time an object in the ROT was last modified.
    HRESULT GetTimeOfLastChange(
        [in, unique] IMoniker *pmkObjectName,
        [out] FILETIME *pfiletime);

    // Get an enumerator for all objects in the ROT.
    HRESULT EnumRunning(
        [out] IEnumMoniker **ppenumMoniker);
}

You can get a feel for the information stored in the ROT by examining its contents. You can do this using the IRunningObjectTable::EnumRunning method, which simply enumerates all the objects currently registered in the ROT. The IEnumMoniker interface returned by the EnumRunning method enumerates the registered objects by their monikers. To turn this data into easily browsable information, you can call the IMoniker::GetDisplayName method on each moniker in the ROT. The following code snippet is from the Running Object Table.cpp sample on the companion CD:

// Open the ROT.
IRunningObjectTable* pRunningObjectTable;
GetRunningObjectTable(NULL, &pRunningObjectTable);

// Get an enumerator.
IEnumMoniker* pEnumMoniker;
pRunningObjectTable->EnumRunning(&pEnumMoniker);

IMoniker* pMoniker;
IBindCtx* pBindCtx;
OLECHAR* moniker_name;

// Loop until there are no more monikers.
while(pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK)
{
    // Create a silly bind context.
    CreateBindCtx(0, &pBindCtx);

    // Get the display name, print it, and free the buffer.
    pMoniker->GetDisplayName(pBindCtx, NULL, &moniker_name);
    wprintf(L"DisplayName is %s\n", moniker_name);
    CoTaskMemFree(moniker_name);

    // Code omitted here that determines the moniker type...

    // Release the moniker and the silly bind context.
    pMoniker->Release();
    pBindCtx->Release();
}

// Free the enumerator and close the ROT.
pEnumMoniker->Release();
pRunningObjectTable->Release();

When you register an object in the ROT, the IRunningObjectTable::Register method requires a flag specifying the type of registration that should occur. This value should be 0, indicating a weak registration, or ROTFLAGS_REGISTRATIONKEEPSALIVE, which holds the object in memory even if no other references to the object exist. When an object is registered, the ROT calls IUnknown::AddRef on the object. For a weak registration, the ROT releases the object when the last reference to the object is released. For a strong registration (ROTFLAGS_REGISTRATIONKEEPSALIVE), the ROT prevents the object from being destroyed until the object's registration is explicitly revoked via the IRunningObjectTable::Revoke method. You can also use the ROTFLAGS_ALLOWANYCLIENT flag when an object registered in the ROT needs to be accessed by clients running from different security contexts. Without this flag, the moniker is registered with a security descriptor that allows only clients from the same security context to access it.