|
|
/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name: module.cpp
Abstract: This file contains the implementation of the CServiceModule class, which is used to handling COM server-related routines.
Revision History: Davide Massarenti (Dmassare) 03/27/2000 created
******************************************************************************/
#include "stdafx.h"
/////////////////////////////////////////////////////////////////////////////
DWORD dwTimeOut = 10*1000; // time for EXE to be idle before shutting down
const DWORD dwPause = 1000; // time to wait for threads to finish up
CServiceModule _Module; MPC::NTEvent g_NTEvents;
/////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG
#define DEBUG_REGKEY HC_REGISTRY_HELPHOST L"\\Debug"
#define DEBUG_BREAKONSTART L"BREAKONSTART"
#define DEBUG_TIMEOUT L"TIMEOUT"
void CServiceModule::ReadDebugSettings() { __HCP_FUNC_ENTRY( "CServiceModule::ReadDebugSettings" );
HRESULT hr; MPC::RegKey rkBase; bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE )); __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( DEBUG_REGKEY )); __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Exists ( fFound ));
if(fFound) { CComVariant vValue; __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_BREAKONSTART )); if(fFound && vValue.vt == VT_I4) { if(vValue.lVal) DebugBreak(); }
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_TIMEOUT )); if(fFound && vValue.vt == VT_I4) { dwTimeOut = 1000 * vValue.lVal; } }
__HCP_FUNC_CLEANUP; } #endif
/////////////////////////////////////////////////////////////////////////////
CServiceModule::CServiceModule() { m_hEventShutdown = NULL; // HANDLE m_hEventShutdown;
m_dwThreadID = 0; // DWORD m_dwThreadID;
m_hMonitor = NULL; // HANDLE m_hMonitor;
m_bActivity = FALSE; // BOOL m_bActivity;
//
m_szServiceName = NULL; // LPCWSTR m_szServiceName;
m_iDisplayName = 0; // UINT m_iDisplayName;
m_iDescription = 0; // UINT m_iDescription;
m_hServiceStatus = NULL; // SERVICE_STATUS_HANDLE m_hServiceStatus;
// SERVICE_STATUS m_status;
m_bService = FALSE; // BOOL m_bService;
::ZeroMemory( &m_status, sizeof( m_status ) ); }
CServiceModule::~CServiceModule() { if(m_hEventShutdown) ::CloseHandle( m_hEventShutdown ); if(m_hMonitor ) ::CloseHandle( m_hMonitor ); }
/////////////////////////////////////////////////////////////////////////////
LONG CServiceModule::Lock() { LONG lCount = CComModule::Lock();
return lCount; }
LONG CServiceModule::Unlock() { LONG lCount = CComModule::Unlock();
if(lCount == 0) { m_bActivity = TRUE;
if(m_hEventShutdown) ::SetEvent( m_hEventShutdown ); // tell monitor that we transitioned to zero
}
return lCount; }
void CServiceModule::MonitorShutdown() { while(1) { DWORD dwWait;
m_bActivity = FALSE; dwWait = ::WaitForSingleObject( m_hEventShutdown, dwTimeOut );
if(dwWait == WAIT_OBJECT_0) continue; // We are alive...
//
// If no activity let's really bail.
//
if(m_bActivity == FALSE && m_nLockCnt <= 0) { ::CoSuspendClassObjects();
if(m_bActivity == FALSE && m_nLockCnt <= 0) break; } }
ForceShutdown(); }
void CServiceModule::ForceShutdown() {
//
// Tell process to exit.
//
::PostThreadMessage( m_dwThreadID, WM_QUIT, 0, 0 ); }
BOOL CServiceModule::StartMonitor() { DWORD dwThreadID;
m_hMonitor = ::CreateThread( NULL, 0, _Monitor, this, 0, &dwThreadID ); if(m_hMonitor == NULL) return FALSE;
return TRUE; }
/////////////////////////////////////////////////////////////////////////////
HRESULT CServiceModule::RegisterServer( BOOL bRegTypeLib, BOOL bService, LPCWSTR szSvcHostGroup ) { HRESULT hr;
// Add object entries
if(FAILED(hr = CComModule::RegisterServer( FALSE ))) return hr;
return S_OK; }
HRESULT CServiceModule::UnregisterServer( LPCWSTR szSvcHostGroup ) { HRESULT hr;
// Remove object entries
if(FAILED(hr = CComModule::UnregisterServer( FALSE ))) return hr;
return S_OK; }
void CServiceModule::Init( _ATL_OBJMAP_ENTRY* p, HINSTANCE h, LPCWSTR szServiceName, UINT iDisplayName, UINT iDescription, const GUID* plibid ) { CComModule::Init( p, h, plibid ); }
BOOL CServiceModule::IsInstalled() { return FALSE; // Not implemented for a COM server.
}
BOOL CServiceModule::Install( LPCWSTR szSvcHostGroup ) { return FALSE; // Not implemented for a COM server.
}
BOOL CServiceModule::Uninstall( LPCWSTR szSvcHostGroup ) { return FALSE; // Not implemented for a COM server.
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Service startup and registration
BOOL CServiceModule::Start( BOOL bService ) { m_hEventShutdown = ::CreateEvent( NULL, FALSE, FALSE, NULL ); if(m_hEventShutdown == NULL) return FALSE;
if(StartMonitor() == FALSE) return FALSE;
if(FAILED(Run())) return FALSE;
return TRUE; }
void CServiceModule::ServiceMain( DWORD dwArgc, LPWSTR lpszArgv[] ) { // Not implemented.
}
void CServiceModule::Handler( DWORD dwOpcode ) { // Not implemented.
}
HRESULT CServiceModule::Run() { __HCP_FUNC_ENTRY( "CServiceModule::Run" );
HRESULT hr; MSG msg;
m_dwThreadID = ::GetCurrentThreadId();
while(::GetMessage( &msg, 0, 0, 0 )) { ::DispatchMessage( &msg ); }
hr = S_OK;
_Module.RevokeClassObjects(); ::Sleep( dwPause ); //wait for any threads to finish
__HCP_FUNC_EXIT(hr); }
void CServiceModule::SetServiceStatus( DWORD dwState ) { // Not implemented.
}
////////////////////////////////////////////////////////////////////////////////
void WINAPI CServiceModule::_ServiceMain( DWORD dwArgc, LPWSTR* lpszArgv ) { // Not implemented.
}
void WINAPI CServiceModule::_Handler( DWORD dwOpcode ) { // Not implemented.
}
DWORD WINAPI CServiceModule::_Monitor( void* pv ) { ((CServiceModule*)pv)->MonitorShutdown();
return 0; }
|