COM registration if you need a typelib

The problem with the previous examples I posted on minimal COM object registration is that they don't always work.  As I mentioned, if you follow the rules specified, while your COM object will work just fine from Win32 applications, you'll have problems if you attempt to access it from a managed environment (either an app running under the CLR or another management environment such as the VB6 runtime or the scripting host).

For those environments, you need to have a typelib.  Since typelib's were designed primarily for interoperating with visual basic, they don't provide full access to the functionality that's available via MIDL (for instance, unnamed unions get turned into named unions, the MIDL boolean type isn't supported, etc), but if you gotta interoperate, you gotta interoperate.

So you've followed the examples listed here and you've registered your COM object, now how do you hook it up to the system?

First, you could call the RegisterTypeLib function, which will perform the registration, but that would be cheating :)  More importantly, there are lots of situations where it's inappropriate to use RegisterTypeLib - for instance, if you're building an app that needs to be installed, you need to enumerate all the registry manipulations done by your application so they can be undone.

So if you want to register a typelib, it's a smidge more complicated than registering a COM component or interface.

To register a typelib, you need (from here):

Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\   
    Default Value: <friendly name for the library> Again, not really required, but nice for oleview
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\HELPDIR   
    Default Value: <Directory that contains the help file for the type library>
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\FLAGS   
    Default Value: Flags for the ICreateTypeLib::SetLibFlags call (typically 0)
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\<LCID for library>
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\<LCID>\<Platform>
    Default Value: <File name that contains the typelib>

Notes:

If your typelib isn't locale-specific, you can specify 0 for the LCID.  Looking at my system, that's typically what most apps do.

<Platform> can be win32, win64 or win16 depending on the platform of the binary.
 

But this isn't quite enough to get the typelib hooked up  - the system still doesn't know how to get access to the type library.  To do that, you need to enhance your CLSID registration to let COM know that there's a typelib available.  With the typelib, a managed environment can synthesize all the interfaces associated with a class.  To do that, you enhance the class registration:

Key: HKEY_CLASSES_ROOT\CLSID\<CLSID>\TypeLib = <LibID>

But we're still not quite done.  For each of the interfaces in the typelib, you can let the system do the marshaling of the interface for you without having to specify a proxy library.  To do this, you can let the standard proxy marshaler do the work.  The universal marshaler has a clsid of {00020424-0000-0000-C000-000000000046}, so instead of using the interface registration mentioned in the last article, you can replace it with:

Key: HKEY_CLASSES_ROOT\Interface\<IID>\
    Default Value: <friendly name for the interface> Again, not really required, but nice for oleview
Key: HKEY_CLASSES_ROOT\Interface\<IID>\ProxyStubClsid32\
    Default Value: {00020424-0000-0000-C000-000000000046}
Key: HKEY_CLASSES_ROOT\Interface\<IID>\TypeLib\
    Default Value: <LibID>

Now instead of using the proxy code in a proxy DLL, the system will do the marshaling for you.

Next: Ok, but what if I don't want to deal with all those ugly GUID thingies?