How do I register a COM class in memory?

I have a COM class (for example CLSID_WidgetFactory

) that I want to make available to everyone in my process that calls:

CoCreateInstance(CLSID_Widget, ...);

      

But I want to make it available unregistered, or include it in the unregistered COM assembly manifest.

The main question

I have:

  • a clsid

    ( CLSID_Widget

    )
  • a IClassFactory

    implementation

How can I register them with the COM infrastructure so that each of my processes can create a COM object?

Obviously I want to do this:

  • without registering a COM object in a piece of registry HKLM\Software\Classes

  • without registering COM object in HKCU\Software\Classes

    hive
  • do not create unregistered COM assembly manifest

It is clear that I would have a classID and my factory object:

class WidgetFactory : ComObject, IClassFactory
{
   //IClassFactory methods
   HRESULT CreateInstance(IUnknown unkOuter, Guid iid, out obj)
   {
      Widget widget = new Widget();

      HRESULT hr = widget.QueryInterface(iid, out obj);
      return hr;
   }
}

      

Then I want to register my factory class:

Guid CLSID_Widget = "{0677445E-EA9B-447A-AF2E-CCD86E49CED0}";
IClassFactory factory = new WidgetFactory();

RegisterClassFactory(CLSID_Widget, factory);

      

All that's left is to figure out how to register the COM class in memory:

void RegisterClassFactory(Guid clsid, IClassFactory classfactory)
{
   //...
}

      

Search queries

  • How to register a COM object in memory
  • How to register a COM class in my process
  • How to register CLSID in memory
  • How to register IClassFactory in my application

Note . I know the answer. But I can't figure out the right set of search terms that can trigger hits.

Bonus reading

+3


source to share


2 answers


You can use CoRegisterClassObject

with CLSCTX_INPROC_SERVER

and REGCLS_MULTIPLEUSE

.

DWORD RegisterClassFactory(Guid clsid, IClassFactory factory)
{
   /*
      Register a COM class in-memory. 
      Any requests by COM to create object clsid will use the 
      class factory given by factory.
      This means that a COM object does not have to be registered
      in the registry in order to use it. Nor does it have
      to be included in an application manifest.

      Public domain: No attribution required.
   */
   DWORD dwCookie; //returned cookie can be later used to delete the registration

   HRESULT hr = CoRegisterClassObject(
         clsid,                // the CLSID to register
         factory,              // the factory that can construct the object
         CLSCTX_INPROC_SERVER, // can only be used inside our process
         REGCLS_MULTIPLEUSE,   // it can be created multiple times
         out dwCookie          // cookie we can later use to delete the registration
   );
   OleCheck(hr);

   return dwCookie;
}

      

And now any of your processes can create this arbitrary COM object (although it is not registered in the registry and has not been included in the assembly manifest):

CoCreateInstance(CLSID_Widget, null, CLSCTX_INPROC_SERVER, IID_IUnknown, out unk);

      



If you are registering multiple classes, you can combine the flag REGCLS_SUSPENDED

(for example with or operator |

):

Suspends registration and activation requests for the specified CLSID until a call to CoResumeClassObjects is made . This is typically used to register CLSIDs for servers that can register multiple class objects to reduce the overall registration time and thus the server application startup time by making a single SCM call, regardless of how many CLSIDs are registered for the server.

Note This flag prevents COM activation errors from a possible race condition between the application shutdown and the application trying to register the COM class.

and then call CoResumeClassObjects

once to register the classes atomically.

If you intend to do this from a DLL, you must ensure that the DLL provides an entry point for registration at the beginning of the application. Or just don't use resume and pause the functions of the class objects.

+3


source


CoRegisterClassObject

will register a factory class for the given one CLSID

and make it available to the callers of your process, however just in the registration apartment (you could probably register in multiple apartments though).

CoCreateInstance

elsewhere in the apartment will be successful, as if CLSID

registered through the registry in the usual way.



AFAIR you're interested in Delphi, but anyway this ATL C ++ class is a sample snippet that shows the use of CoRegisterClassObject

temporarily register CLSID

for a third party CoCreateInstance

in the scope of a local variable:

{
        BEGIN_OBJECT_MAP(g_pObjectMap)
            OBJECT_ENTRY(__uuidof(CSplitterMediaObject), CSplitterMediaObject)
            // ...
        END_OBJECT_MAP()
        CLocalObjectMap ObjectMap(g_pObjectMap, TRUE);
        // ...
        // Someone calls CoCreateInstance(__uuidof(CSplitterMediaObject), ...
        // here and the call succeeds as if the class is registered
}

      

+2


source







All Articles