Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32: Registry entries required to register an ActiveX control?

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.

like image 919
Ian Boyd Avatar asked Nov 12 '08 17:11

Ian Boyd


4 Answers

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?

like image 107
Ian Boyd Avatar answered Sep 29 '22 23:09

Ian Boyd


Larry Osterman provides a good jumping-off point:

A large part of the "cargo cult" nature of this is the fact that there are a bewildering set of registry settings that can be set for COM objects, and it's not clear which, if any apply. So I'm attempting to lay out a series of articles that can help people determine what they need to set.

-- What registry entries are needed to register a COM object.

Summary: it depends on what scenarios you need your object to be used in. The most basic, absolutely-necessary settings are the default value and ThreadingModel in HKEY_CLASSES_ROOT\CLSID\<clsid>\, but most of the time you'll want ProgIDs and AppIDs as well.

like image 44
Shog9 Avatar answered Sep 29 '22 23:09

Shog9


Find/borrow/steal a copy of Inside OLE 2, by Kraig Brockenschmidt. It's old like the world (and dates me as well :-))

Here's also a high-level overview of the registry entries mentioned above.

Read Larry Osterman's blog post for more pointers.

Look at the MSDN ActiveX samples.

Also, you are missing entries under the HKCR\Interfaces for all custom interfaces and event interfaces your control implements.

like image 41
Franci Penov Avatar answered Sep 29 '22 23:09

Franci Penov


It's not exhaustive, but try this MS knowledge base article.

Also, Larry Osterman has a useful blog post here.


It occurs to me that another approach would be to use a tool like RegMon and directly monitor what registry changes are made when your DllRegisterServer method is called.

like image 21
Stu Mackellar Avatar answered Sep 29 '22 22:09

Stu Mackellar