Win32: Registry entries required to register an ActiveX control?

Ian Boyd picture Ian Boyd · Nov 12, 2008 · Viewed 6.9k times · Source

i need write the code that runs when DllRegisterServer is called. i.e. when someone calls:

regsvr32 myActiveX.ocx

i'm trying to find the definitive list of required registry entries (rather than just what i can cobble together by spellunking through the registry).

So far my expeditions have found:

HKEY_CLASSES_ROOT
   \MyCoolLibrary.MyCoolControl
      \Clsid
         (default) = "{myClassId}"
   \CLSID
      \{myClassId}
         \Control
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \MiscStatus
            \1
               (default) = 205201
         \ProgID
            (default) = "MyCoolLibrary.MyCoolControl"
         \ToolboxBitmap32
            (default) = "c:\foo\myActiveX.ocx,1"
         \TypeLib
            (default) = "{myTypeLibraryGuid}"
         \Verb
            \0
               (default) = "Properties,0,2"
         \Version
            (default) = "1.0"
   \TypeLib
      \{myTypeLibraryGuid}
         \1.0
            (default) = "MyCoolLibrary.MyCoolControl"

Now, the concerns: - what does the Control folder contain? Is it's presence indicate a control? - what's a MiscStatus of 205201 do? What would 205202 do instead? - What's the verb "Properties,0,2"? Where's "Properties,0,0" and "Properties,0,1"?

In other words, i'm looking for the docs.

Answer

Ian Boyd picture Ian Boyd · Nov 12, 2008

What i know so far. COM creates an object based on it's clsid. This is a guid that uniquely identifies that class.

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}

That class is then used to create objects. COM now needs to know where the DLL is that holds that COM Object. In my particular case, the "server" that exposes the COM object is a DLL, and will be "in process". We then point COM to that "in-process" dll by adding:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"

COM also needs to know the threading model that the COM server object supports. The simplest, most common, and the one used in this example is the "Apartment" threading model:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"

Next is the ProgID. This is similar to how DNS is used to turn a friendly name into an IP. Here we turn a friendly name "MyCoolLibrary.MyCoolControl" into the ugly clsid "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

Now someone can ask for

MyCoolLibrary.MyCoolControl

and COM can turn that into the ClassID

{AE8530CF-D204-4877-9CAB-F052BF1F661F}

Once COM has the clasid, it can then look in the registry under HKCR\Clsid\{AE8530CF-D204-4877-9CAB-F052BF1F661F} to find the real information.

For fun, the ProgID is added to the Clsid section, just so people can have some idea what this class is:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

Next is the type library. This is mostly unimportant for anything in-process, but if the COM object is in another "apartment", then function parameters need to be marshalled. COM does this automatically for you if it has a type library that defines all the classes methods.

The clsid section is pointed to the appropriate type library with the addition of a TypeLib key:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
         \TypeLib            
             (default) = "{17A5A3D4-439C-4C2A-8AB4-749B7771CDE1}"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

Information about this type library is also stored in the registry, but adding these keys is done for us with a call to RegisterTypeLib. But it will add keys for us similar to:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
         \TypeLib            
             (default) = "{17A5A3D4-439C-4C2A-8AB4-749B7771CDE1}"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"
HKEY_CLASSES_ROOT
    \TypeLib
        \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
           \1.0
              (default) = "My Cool ActiveX Library"
           ...

Now we get into the tricky stuff, stuff that is needed to hopefully make an ActiveX control work.

An MSDN article states that you must add a dummy Programmable key to indicate that it is an ActiveX control:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \Programmable

But this MSDN Library page says the keyword is Control, and not Programmable - and there is no Programmable key.

But that doesn't stop some ActiveX's from using Control, some using Programmable, and some using both.

i cannot find anything mentioning anything else being required.

So, can anyone find some definitive documentation?