COM is easily one of the most commonly used technologies in Microsoft Windows Platform. Many of Microsoft Windows’ capabilities are only exposed in COM.

I do not claim to be a COM expert. But my work in Microsoft in the past and now do affect how people use COM in some way. In this article, I want to briefly discuss COM and its evolutions. I only intend to discuss in-proc COM here.

Traditional COM Activation

In traditional COM, the COM server is responsible to register its COM activation information. The information is typically recorded in the registry. The following is an example:

G:\Temp>more COM_example1.reg
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{0725C3CB-FEFB-11D0-99F9-00C04FC2F8EC}]
@="WDM Event Provider"

[HKEY_CLASSES_ROOT\CLSID\{0725C3CB-FEFB-11D0-99F9-00C04FC2F8EC}\InprocServer32]
@="C:\\WINDOWS\\System32\\wbem\\wmiprov.dll"
"ThreadingModel"="Both"

A COM client can call API CoCreateInstance to activation a COM object. Internally COM maps the CLSID to the COM server dll using the COM activation information registered by the COM server, then calls the appropriate API to activate the COM object.

Sxs and Registration Free COM activation

In Windows XP, our team introduced the Sxs technology. One of the benefits of Sxs technology is non-impact install. For example, it enables application to activate COM objects without registering the COM server in the registry.

To use registration free COM, the COM Server needs to have a Sxs manifest describing its COM server information in the manifest file. Here is an example:

G:\temp >more COMExample.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

    <assemblyIdentity type="win32" name="MyExample" version="1.0.0.0"
 processorArchitecture="x86" />

    <file name="foo.dll" hash="80e5fb356b5f5cfe6f765a9ffe1eb749642a2e0f" hash
alg="SHA1">

        <typelib tlbid="{f5078f18-c551-11d3-89b9-0000f81fe221}" version="4.0" he
lpdir=""/>
        <comClass description="MyCOMType " clsid="{88d969c
0-f192-11d4-a65f-0040963251e5}" threadingModel="Apartment" progid="MSXML2.DOMDoc
ument.4.0" tlbid="{f5078f18-c551-11d3-89b9-0000f81fe221}"/>
    </file>
</assembly>

The COM client application also needs a Sxs manifest, in which it declares it depends on the COM Server. For example:

G:\Temp>more CientExample1.manifest
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="CoCreate" type="win32" />
<dependency>
<dependentAssembly>
    <assemblyIdentity type="win32" name="MyExample" version="1.0.0.0"
 processorArchitecture="x86" />
</dependentAssembly>
</dependency>
</assembly>

Now the client can call CoCreateInstance to activate the COM object. Internally COM queries Sxs for the COM activation information before searches it in registry.

COM/.Net Interop

.Net framework natively supports COM. Every .Net framework assembly is automatically a COM server.

To allow a COM client to activate a .Net type, first you need to register the .Net assembly for COM, by running regasm.exe on the assembly. Here is a snippet of what is registered by regasm.exe:

G:\Temp>more COM_example2.reg
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}]
@="System.Security.Cryptography.HMACSHA1"

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}\Implemented Cate
gories]

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}\Implemented Cate
gories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
@=""

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="System.Security.Cryptography.HMACSHA1"
"Assembly"="mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c
561934e089"
"RuntimeVersion"="v1.1.4322"

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}\InprocServer32\1
.0.5000.0]
"Class"="System.Security.Cryptography.HMACSHA1"
"Assembly"="mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c
561934e089"
"RuntimeVersion"="v1.1.4322"

[HKEY_CLASSES_ROOT\CLSID\{00B01B2E-B1FE-33A6-AD40-57DE8358DC7D}\ProgId]
@="System.Security.Cryptography.HMACSHA1"

Regasm.exe always registers mscoree.dll as the COM Server dll. In addition, it registers the assembly information, as well as the type information. On CoCreateInstance, COM will try to activate the COM object by calling mscoree.dll. Mscoree.dll then reads the assembly and type information from the registry, and activates the .Net type as appropriate.

Registration Free COM/.Net Interop

Recognizing the value of registration free COM/.Net interop, both CLR team and Windows team did some work to make this scenario possible.

Just like registration free COM, you will need to generate a Sxs manifest for the .Net framework assembly.  Here is an example:

G:\temp>more CLRExample.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
       <assemblyIdentity
                    name="myOrganization.myDivision.myManagedComp"
                    version="1.2.3.4"  />
       <clrClass
                    clsid="{65722BE6-3449-4628-ABD3-74B6864F9739}"
                    progid="myManagedComp.testClass1"
                    threadingModel="Both"
                    name="myManagedComp.testClass1"
                    runtimeVersion="v1.0.3705">
       </clrClass>
       <clrClass
                    clsid="{367221D6-3559-3328-ABD3-45B6825F9732}"
                    progid="myManagedComp.testClass2"
                    threadingModel="Both"
                    name="myManagedComp.testClass2"
                    runtimeVersion="v1.0.3705">
       </clrClass>
       <file name="MyManagedComp.dll">
       </file>
</assembly>

The client will also need to have a manifest, and declare the managed assembly as its dependencies.

G:\Temp>more CientExample2.manifest
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="CoCreate" type="win32" />
<dependency>
<dependentAssembly>
       <assemblyIdentity
                    name="myOrganization.myDivision.myManagedComp"
                    version="1.2.3.4"  />
</dependentAssembly>
</dependency>
</assembly>

Now the client can use CoCreateInstance to activate the .Net type. Just like the registration free COM case, internally COM will query Sxs for the COM activation information. Instead of returning the real file, Sxs will return mscoree.dll as the COM Server dll. COM then calls mscoree.dll. Mscoree.dll in turn queries Sxs for the assembly and type information, before query them in the registry.

Summary

This article briefly discusses COM activation and its evolution, and the details how various information is used to activation the COM type.

Next time, I’ll discuss some of the nitty-gritty of registration free COM/.Net interop.