To expand a bit more. Our module is an ATL::CAtlMfcModule that looks like this:
//------------------------------------------------------------------------------
class OurModule : public ATL::CAtlMfcModule
//------------------------------------------------------------------------------
{
public:
DECLARE_LIBID(APPLIBID);
#if defined (_M_X64)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_A64_REG, "OUR ACAD 64bit CLSID");
#else
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_A32_REG, "OUR ACAD 32bit CLSID");
#endif
};
The IDRs are resource IDs for the RGS file in a "REGISTRY" section of the resources.
We also needed this in our app class:
// DllCanUnloadNow - Allows COM to unload DLL
#if !defined(_WIN32_WCE) && !defined(_AMD64_) && !defined(_IA64_)
#pragma comment(linker, "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow@0,PRIVATE")
#pragma comment(linker, "/EXPORT:DllGetClassObject=_DllGetClassObject@12,PRIVATE")
#pragma comment(linker, "/EXPORT:DllRegisterServer=_DllRegisterServer@0,PRIVATE")
#pragma comment(linker, "/EXPORT:DllUnregisterServer=_DllUnregisterServer@0,PRIVATE")
#else
#if defined(_X86_) || defined(_SHX_)
#pragma comment(linker, "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow,PRIVATE")
#pragma comment(linker, "/EXPORT:DllGetClassObject=_DllGetClassObject,PRIVATE")
#pragma comment(linker, "/EXPORT:DllRegisterServer=_DllRegisterServer,PRIVATE")
#pragma comment(linker, "/EXPORT:DllUnregisterServer=_DllUnregisterServer,PRIVATE")
#else
#pragma comment(linker, "/EXPORT:DllCanUnloadNow,PRIVATE")
#pragma comment(linker, "/EXPORT:DllGetClassObject,PRIVATE")
#pragma comment(linker, "/EXPORT:DllRegisterServer,PRIVATE")
#pragma comment(linker, "/EXPORT:DllUnregisterServer,PRIVATE")
#endif // (_X86_)||(_SHX_)
#endif // !_WIN32_WCE && !_AMD64_ && !_IA64_
And our registration functions look like this:
extern OurModule _AtlModule; // <-- extern this in the .h file
OurModule _AtlModule;
//------------------------------------------------------------------------------
STDAPI DllCanUnloadNow()
//------------------------------------------------------------------------------
{
if (_AtlModule.GetLockCount() > 0)
{
return S_FALSE;
}
return S_OK;
}
//------------------------------------------------------------------------------
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
//------------------------------------------------------------------------------
{
// DllGetClassObject - Returns class factory
if (S_OK == _AtlModule.GetClassObject(rclsid, riid, ppv))
{
return S_OK;
}
return AfxDllGetClassObject(rclsid, riid, ppv);
}
//typedef void (*OaEnablePerUserTLibRegistration)();
//------------------------------------------------------------------------------
STDAPI DllRegisterServer()
//------------------------------------------------------------------------------
{
// DllRegisterServer - Adds entries to the system registry
//HRESULT hr = ATL::AtlSetPerUserRegistration(true);
HRESULT hRes1 = _AtlModule.UpdateRegistryAppId(TRUE);
HINSTANCE hInstOle32 = NULL;
try
{
HRESULT hr = _AtlModule.RegisterServer(TRUE);
if (FAILED(hr))
{
hInstOle32 = LoadLibrary(_T("Oleaut32.dll"));
if (hInstOle32 != NULL)
{
//OaEnablePerUserTLibRegistration lr = (OaEnablePerUserTLibRegistration)GetProcAddress(hInstOle32, ("OaEnablePerUserTLibRegistration"));
ULONG (PASCAL *lr)();
(FARPROC&)lr = GetProcAddress(hInstOle32, ("OaEnablePerUserTLibRegistration"));
if (lr != NULL)
{
lr();
hr = _AtlModule.RegisterServer(TRUE);
if (SUCCEEDED(hr))
{
FreeLibrary(hInstOle32);
return hr;
}
}
HKEY hKCr;
hr = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Classes"), 0, KEY_READ, &hKCr);
if (hr != ERROR_SUCCESS)
{
return hr;
}
hr = RegOverridePredefKey(HKEY_CLASSES_ROOT, hKCr);
if (FAILED(hr))
{
RegCloseKey(hKCr);
return hr;
}
hr = _AtlModule.RegisterServer(TRUE);
RegCloseKey(hKCr);
RegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
hr = S_OK;
}
}
if (hInstOle32 != NULL)
{
FreeLibrary(hInstOle32);
}
return hr;
}
catch (...)
{
if (hInstOle32)
{
FreeLibrary(hInstOle32);
}
return E_FAIL;
}
}
//------------------------------------------------------------------------------
STDAPI DllUnregisterServer()
//------------------------------------------------------------------------------
{
// DllUnregisterServer - Removes entries from the system registry
_AtlModule.UpdateRegistryAppId(FALSE);
HRESULT hRes2 = _AtlModule.UnregisterServer(TRUE);
return hRes2;
}