CAtlModule类的实现:
======================= dll =======================
template <class T>
class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT <T>
{
public :
.....
}
======================= exe =======================
template <class T>
class ATL_NO_VTABLE CAtlExeModuleT : public CAtlModuleT <T>
{
public :
.....
}
======================= service =======================
template <class T, UINT nServiceNameID>
class ATL_NO_VTABLE CAtlServiceModuleT : public CAtlExeModuleT <T>
{
public :
.....
}
======================= others =======================
template <class T>
class ATL_NO_VTABLE CAtlExeModuleT : public CAtlModuleT <T>
{
public :
.....
}
template <class T>
class ATL_NO_VTABLE CAtlModuleT : public CAtlModule
{
public :
.....
}
class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE
{
public :
.....
}
typedef _ATL_MODULE70 _ATL_MODULE;
struct _ATL_MODULE70
{
UINT cbSize;
LONG m_nLockCnt;
_ATL_TERMFUNC_ELEM* m_pTermFuncs;
CComCriticalSection m_csStaticDataInitAndTypeInfo;
};
类继承关系图:
_ATL_MODULE
¦
¦
CAtlModule
¦
¦
CAtlModuleT ------> CAtlDllModuleT
¦
¦
CAtlExeModuleT -----> CAtlServiceModuleT
CAtlModule类的函数分布:
在CAtlModule 中出现了熟悉的Lock和Unlock,都为虚函数。
virtual LONG Lock() throw()
{
return CComGlobalsThreadModel::Increment(&m_nLockCnt);
}
virtual LONG Unlock() throw()
{
return CComGlobalsThreadModel::Decrement(&m_nLockCnt);
}
在CAtlModuleT中实现了RegisterServer,UnregisterServer, RegisterAppId, UpdateRegistryAppId ,UnregisterAppId
HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw()
{
pCLSID;
bRegTypeLib;
HRESULT hr = S_OK;
#ifndef _ATL_NO_COM_SUPPORT
hr = _AtlComModule.RegisterServer(bRegTypeLib, pCLSID);
#endif // _ATL_NO_COM_SUPPORT
#ifndef _ATL_NO_PERF_SUPPORT
if (SUCCEEDED(hr) && _pPerfRegFunc != NULL)
hr = (*_pPerfRegFunc)(_AtlBaseModule.m_hInst);
#endif
return hr;
}
HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw()
{
bUnRegTypeLib;
pCLSID;
HRESULT hr = S_OK;
#ifndef _ATL_NO_PERF_SUPPORT
if (_pPerfUnRegFunc != NULL)
hr = (*_pPerfUnRegFunc)();
#endif
#ifndef _ATL_NO_COM_SUPPORT
if (SUCCEEDED(hr))
hr = _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID);
#endif // _ATL_NO_COM_SUPPORT
return hr;
}
static HRESULT WINAPI UpdateRegistryAppId(BOOL /*bRegister*/) throw()
{
return S_OK;
}
HRESULT RegisterAppId() throw()
{
return T::UpdateRegistryAppId(TRUE);
}
HRESULT UnregisterAppId() throw()
{
return T::UpdateRegistryAppId(FALSE);
}
它们会在CAtlDllModuleT,CAtlExeModuleT和CAtlServiceModuleT中使用:
======================= CAtlDllModuleT=======================
HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw()
{
// registers object, typelib and all interfaces in typelib
T* pT = static_cast <T*> (this);
HRESULT hr = pT-> RegisterAppId();
if (SUCCEEDED(hr))
hr = pT-> RegisterServer(bRegTypeLib);
return hr;
}
HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw()
{
T* pT = static_cast <T*> (this);
HRESULT hr = pT-> UnregisterServer(bUnRegTypeLib);
if (SUCCEEDED(hr))
hr = pT-> UnregisterAppId();
return hr;
}
======================= CAtlExeModuleT =======================
// Parses the command line and registers/unregisters the rgs file if necessary
bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw()
{
*pnRetCode = S_OK;
TCHAR szTokens[] = _T( "-/ ");
T* pT = static_cast <T*> (this);
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (WordCmpI(lpszToken, _T( "UnregServer "))==0)
{
*pnRetCode = pT-> UnregisterServer(TRUE);
if (SUCCEEDED(*pnRetCode))
*pnRetCode = pT-> UnregisterAppId();
return false;
}
// Register as Local Server
if (WordCmpI(lpszToken, _T( "RegServer "))==0)
{
*pnRetCode = pT-> RegisterAppId();
if (SUCCEEDED(*pnRetCode))
*pnRetCode = pT-> RegisterServer(TRUE);
return false;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
return true;
}
======================= CAtlServiceModuleT =======================
// Parses the command line and registers/unregisters the rgs file if necessary
bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw()
{
if (!CAtlExeModuleT <T> ::ParseCommandLine(lpCmdLine, pnRetCode))
return false;
TCHAR szTokens[] = _T( "-/ ");
*pnRetCode = S_OK;
T* pT = static_cast <T*> (this);
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (WordCmpI(lpszToken, _T( "Service "))==0)
{
*pnRetCode = pT-> RegisterAppId(true);
if (SUCCEEDED(*pnRetCode))
*pnRetCode = pT-> RegisterServer(TRUE);
return false;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
return true;
}
CAtlDllModuleT 在中实现了更加熟悉的DllMain,DllCanUnloadNow, DllGetClassObject, DllRegisterServer, DllUnregisterServer和 GetClassObject
BOOL WINAPI DllMain(DWORD dwReason, LPVOID /* lpReserved */) throw()
{
if (dwReason == DLL_PROCESS_ATTACH)
{
if (CAtlBaseModule::m_bInitFailed)
{
ATLASSERT(0);
return FALSE;
}
_AtlBaseModule.m_eDllInitializationStage = Dll_Process_attached;
#ifdef _ATL_MIN_CRT
DisableThreadLibraryCalls(_AtlBaseModule.GetModuleInstance());
#endif
}
else if (dwReason == DLL_PROCESS_DETACH)
{
_AtlBaseModule.m_eDllInitializationStage = Dll_Process_detached;
#ifdef _DEBUG
// Prevent false memory leak reporting. ~CAtlWinModule may be too late.
_AtlWinModule.Term();
#endif // _DEBUG
}
return TRUE; // ok
}
HRESULT DllCanUnloadNow() throw()
{
T* pT = static_cast <T*> (this);
return (pT-> GetLockCount()==0) ? S_OK : S_FALSE;
}
HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw()
{
T* pT = static_cast <T*> (this);
return pT-> GetClassObject(rclsid, riid, ppv);
}
HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw()
{
// registers object, typelib and all interfaces in typelib
T* pT = static_cast <T*> (this);
HRESULT hr = pT-> RegisterAppId();
if (SUCCEEDED(hr))
hr = pT-> RegisterServer(bRegTypeLib);
return hr;
}
HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw()
{
T* pT = static_cast <T*> (this);
HRESULT hr = pT-> UnregisterServer(bUnRegTypeLib);
if (SUCCEEDED(hr))
hr = pT-> UnregisterAppId();
return hr;
}
// Obtain a Class Factory
HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw()
{
#ifndef _ATL_OLEDB_CONFORMANCE_TESTS
ATLASSERT(ppv != NULL);
#endif
return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv);
}
CAtlExeModuleT重新实现了自己的Unlock
LONG Unlock() throw()
{
LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt);
#ifndef _ATL_NO_COM_SUPPORT
if (lRet == 0)
{
if (m_bDelayShutdown)
{
m_bActivity = true;
::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
}
else
{
::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
}
}
#endif // _ATL_NO_COM_SUPPORT
return lRet;
}
CAtlServiceModuleT也重新实现了自己的Unlock
LONG Unlock() throw()
{
LONG lRet;
if (m_bService)
{
// We are running as a service, therefore transition to zero does not
// unload the process
lRet = CAtlModuleT <T> ::Unlock();
}
else
{
// We are running as EXE, use MonitorShutdown logic provided by CExeModule
lRet = CAtlExeModuleT <T> ::Unlock();
}
return lRet;
}
在CAtlServiceModuleT中实现了InitializeSecurity, LogEventEx和SetServiceStatus
// This function provides the default security settings for your service,
// you should overide this in your specific service module class to change
// as appropriate. By default, this will allow any caller and calls will be
// on the callers security token (impersonated).
HRESULT InitializeSecurity() throw()
{
return CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
}
void LogEventEx(int id, LPCTSTR pszMessage=NULL, WORD type = EVENTLOG_INFORMATION_TYPE) throw()
{
HANDLE hEventSource;
if (m_szServiceName)
{
/* Get a handle to use with ReportEvent(). */
hEventSource = RegisterEventSource(NULL, m_szServiceName);
if (hEventSource != NULL)
{
/* Write to event log. */
ReportEvent(hEventSource,
type,
(WORD)0,
id,
NULL,
(WORD)(pszMessage != NULL ? 1 : 0),
0,
pszMessage != NULL ? &pszMessage : NULL,
NULL);
DeregisterEventSource(hEventSource);
}
}
}
void __cdecl LogEvent(LPCTSTR pszFormat, ...) throw()
{
TCHAR chMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[1];
va_list pArg;
va_start(pArg, pszFormat);
_vstprintf(chMsg, pszFormat, pArg);
va_end(pArg);
lpszStrings[0] = chMsg;
if (!m_bService)
{
// Not running as a service, so print out the error message
// to the console if possible
_putts(chMsg);
}
/* Get a handle to use with ReportEvent(). */
hEventSource = RegisterEventSource(NULL, m_szServiceName);
if (hEventSource != NULL)
{
/* Write to event log. */
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
void SetServiceStatus(DWORD dwState) throw()
{
m_status.dwCurrentState = dwState;
::SetServiceStatus(m_hServiceStatus, &m_status);
}