COM: Cannot register a COM DLL using ATL::CComModule::RegisterServer()

Issue: Cannot register a COM DLL using ATL::CComModule::RegisterServer()

If you are using a COM DLL or building one that uses ATL’s CComModule::RegisterServer() and building the code in Visual Studio 2013, you are mostly failing to register it. Say if you are using RegSvr32.exe to register your DLL, the call stack might show you the following calls.

0:000> kL
Child-SP          RetAddr           Call Site
00000000`0012e490 00000001`800217a2 YOURDLL!ATL::CComModule::UpdateRegistryFromResourceD+0x19 [c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlbase.h @ 4729]
00000000`0012e4a0 00000001`80038471 YOURDLL!CODADataSource::UpdateRegistry+0xe2
00000000`0012e560 00000001`800218f6 YOURDLL!ATL::CComModule::RegisterServer+0x91
00000000`0012e5a0 00000000`ffe21326 YOURDLL!DllRegisterServer+0x26
00000000`0012e5d0 00000000`ffe21028 regsvr32!wWinMain+0x8e2
00000000`0012fac0 00000000`7799652d regsvr32!__wmainCRTStartup+0x1aa
00000000`0012fb80 00000000`77acc521 kernel32!BaseThreadInitThunk+0xd
00000000`0012fbb0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

A quick workaround is to replace UpdateRegistryFromResourceD() in atlbase.h (VS2013) with the one from VS2012. However this is not a preferable solution. Here is the root cause:
In atlbase.h (VS 2013), UpdateRegistryFromResourceD() is defined as follows:

virtual HRESULT WINAPI UpdateRegistryFromResourceD(
              _In_ UINT nResID,
              _In_ BOOL bRegister,
              _In_opt_ struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
       {
              (nResID);
              (bRegister);
              (pMapEntries);
              return E_FAIL;
       }

The same function in atlbase.h (VS2012) is defined as:

virtual HRESULT WINAPI UpdateRegistryFromResourceD(
              _In_ UINT nResID,
              _In_ BOOL bRegister,
              _In_opt_ struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
       {
#if defined(_ATL_STATIC_REGISTRY)
              (nResID);
              (bRegister);
              (pMapEntries);
              return E_FAIL;
#else
              return CAtlModuleT<CComModule>::UpdateRegistryFromResource(nResID, bRegister, pMapEntries);
#endif
       }

As a result the code when built with VS2013 fails to register a COM DLL. It returns E_FAIL from UpdateRegistryFromResourceD().
The actual reason behind this is: Usage of ATL::CComModule has been deprecated since ATL 7.0 (i.e. VS2003) and it has been completely removed since VS2013. You should use “CAtlComModule::RegisterServer()”, not CComModule::RegisterServer().

More Information
As of ATL 7.0, CComModule is deprecated. Please see msdn.microsoft.com/en-us/library/vstudio/79kd7a00.aspx for the CComModule Replacement Classes
Earlier versions of ATL used CComModule. In ATL 7.0, CComModule functionality is replaced by several classes as shown below:
•         CAtlBaseModule   Contains information required by most applications that use ATL. Contains the HINSTANCE of the module and the resource instance.
•         CAtlComModule    Contains information required by the COM classes in ATL.
•         CAtlWinModule    Contains information required by the windowing classes in ATL.
•         CAtlDebugInterfacesModule   Contains support for interface debugging.
•         CAtlModule   The following CAtlModule-derived classes are customized to contain information required in a particular application type. Most members in these classes can be overridden:
o    CAtlDllModuleT       Used in DLL applications. Provides code for the standard exports.
o    CAtlExeModuleT       Used in EXE applications. Provides code required in an EXE.
o    CAtlServiceModuleT   Provides support to create Windows NT and Windows 2000 Services.

 

 

Created by

Shamik Misra (MSFT)