Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to register a COM class in memory?

Tags:

com

winapi

I have a COM class (e.g., CLSID_WidgetFactory) that I want to make available to anyone in my process who calls:

CoCreateInstance(CLSID_Widget, ...);

But i want to make it available without having to register it, or include it in a registration-free COM assembly manifest.

Core question

I have:

  • a clsid (CLSID_Widget)
  • an IClassFactory implementation

How can i register the these with the COM infrastructure so that anyone in my process can create the COM object?

Obviously I want to accomplish this:

  • without registering the COM object in the HKLM\Software\Classes registry hive
  • without registering the COM object in the HKCU\Software\Classes hive
  • without create a registration-free COM assembly manifest

Conceptually i would have my 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 class factory:

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 a COM Class in-memory:

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

Search terms

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

Note: I know the answer. But i can't figure out the correct set of search terms that would trigger a hit.

Bonus Reading

  • Can I create and use a COM class without registering it in the registry?
  • Old New Thing: Registration-free COM the old-fashioned way: The car mp3 player
  • Old New Thing: How do I accept files to be opened via IDropTarget instead of on the command line?
like image 593
Ian Boyd Avatar asked Jul 27 '17 15:07

Ian Boyd


People also ask

How to register a class in windows?

A window class is supported by a window procedure. Your application can register a window class by using either RegisterClassA or RegisterClassW. New applications should typically use RegisterClassW.

What does it mean to register a class in C++?

In the context of pure C++, without respect to any specific platoform or library, "register a class" has no meaning. This is not a language concept, nor is it any design pattern I am aware of. It does however have at least two meanings the Windows world.

How do I register my Clsid?

Start > run > regedit (Opens the registry editor). Look for the corresponding file name ocx/dll under this CLSID. Re-register that ocx/dll using regsvr32. Close the Project andopen again to verify if the issue persists.


1 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 anyone in your process can create this arbitrary COM object (even though it isn't registered in the registry, and was not included in an assembly manifest):

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

If you're registering several classes, you can combine the REGCLS_SUSPENDED flag (e.g. with the or operator |):

Suspends registration and activation requests for the specified CLSID until there is a call to CoResumeClassObjects. This is used typically to register the 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 call to the SCM, no matter how many CLSIDs are registered for the server.

Note This flag prevents COM activation errors from a possible race condition between an application shutting down and that application attempting to register a COM class.

and then call CoResumeClassObjects once to register the classes atomically.

If you intend to perform this from a DLL, you should make sure the DLL provides an entry point for registration at the start of the application. Or just don't use the resume and suspend class objects functions.

like image 60
acelent Avatar answered Nov 15 '22 11:11

acelent