// CAtlModule模块基类
__declspec(selectany) CAtlModule* _pAtlModule = NULL; // 全局变量, 代表一个模块

struct _ATL_MODULE70
{
 UINT cbSize;
 LONG m_nLockCnt;
 _ATL_TERMFUNC_ELEM* m_pTermFuncs;
 CComCriticalSection m_csStaticDataInitAndTypeInfo;
};
typedef _ATL_MODULE70 _ATL_MODULE;

class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE
{
 CAtlModule() throw()
 {
  // Should have only one instance of a class
  // derived from CAtlModule in a project.
  // 一个工程中仅有一个CAtlModule子类的实例
  // 其一般也是一个全局变量, 因为它会被赋值给_pAtlModule
  ATLASSERT(_pAtlModule == NULL);
  // _ATL_MODULE中的变量初始化
  cbSize = 0;
  m_nLockCnt = 0;
  m_pTermFuncs = NULL;
  
  _pAtlModule = this; // 赋值给_pAtlModule
  
  m_pGIT = NULL;

  if (FAILED(m_csStaticDataInitAndTypeInfo.Init()))
  {
   // 注意此if块中返回时, _pAtlModule已被赋值一个失败初始化的对象
   ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to initialize critical section in CAtlModule\n"));
   ATLASSERT(0);
   CAtlBaseModule::m_bInitFailed = true;
   return;
  }

  // Set cbSize on success.
  cbSize = sizeof(_ATL_MODULE);
 }
};

// CAtlBaseModule的定义和实现分别在VC\atlmfc\include\atlcore.h和VC\atlmfc\src\atl\atls\atlbase.cpp中
// atlbase.cpp定义了其一个全局变量_AtlBaseModule
#pragma init_seg( lib )
CAtlBaseModule _AtlBaseModule;
extern CAtlWinModule _AtlWinModule = CAtlWinModule();

struct _ATL_BASE_MODULE70
{
 UINT cbSize;
 HINSTANCE m_hInst;
 HINSTANCE m_hInstResource;
 bool m_bNT5orWin98;
 DWORD dwAtlBuildVer;
 const GUID* pguidVer;
 CComCriticalSection m_csResource;
 CSimpleArray<HINSTANCE> m_rgResourceInstance;
};
typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE;

class CAtlBaseModule : public _ATL_BASE_MODULE
{
 CAtlBaseModule::CAtlBaseModule() throw()
 {
  cbSize = sizeof(_ATL_BASE_MODULE);

  m_hInst = m_hInstResource = reinterpret_cast<HINSTANCE>(&__ImageBase);

  m_bNT5orWin98 = false;
  OSVERSIONINFO version;
  memset(&version, 0, sizeof(version));
  version.dwOSVersionInfoSize = sizeof(version);
  ::GetVersionEx(&version);
  if(version.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
   if(version.dwMajorVersion >= 5)
   {
    m_bNT5orWin98 = true;
   }
  }
  else if(version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  {
   if((version.dwMajorVersion > 4) || ((version.dwMajorVersion == 4) &&
    (version.dwMinorVersion > 0)))
   {
    m_bNT5orWin98 = true;
   }
  }

  dwAtlBuildVer = _ATL_VER;
  pguidVer = &GUID_ATLVer70;

  if (FAILED(m_csResource.Init()))
  {
   ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to initialize critical section in CAtlBaseModule\n"));
   ATLASSERT(0);
   CAtlBaseModule::m_bInitFailed = true;
  }
 }
}