276 lines
6.3 KiB
C++
276 lines
6.3 KiB
C++
/******************************************************************************
|
|
|
|
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;
|
|
}
|