|
|
////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2000-2002, Microsoft Corporation.
//
// All rights reserved.
//
// Module Name:
//
// WMIAdapter_Service.cpp
//
// Abstract:
//
// module for service
//
// History:
//
// initial a-marius
//
////////////////////////////////////////////////////////////////////////////////////
#include "PreComp.h"
// debuging features
#ifndef _INC_CRTDBG
#include <crtdbg.h>
#endif _INC_CRTDBG
// new stores file/line info
#ifdef _DEBUG
#ifndef NEW
#define NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
#define new NEW
#endif NEW
#endif _DEBUG
// messaging
#include "WMIAdapterMessages.h"
// application
#include "WMIAdapter_App.h"
extern WmiAdapterApp _App;
// service module
#include "WMIAdapter_Service.h"
extern WmiAdapterService _Service;
extern LONG g_lRefLib; // refcount of libarries attached into process
extern CStaticCritSec g_csInit; // synch object used to protect above globals
/////////////////////////////////////////////////////////////////////////////////////////
// destruction
/////////////////////////////////////////////////////////////////////////////////////////
WmiAdapterService::~WmiAdapterService() { ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService destruction\n" L"*************************************************************\n" );
if ( m_hServiceStatus ) { // service status handle doesn't have to be closed
// ::CloseHandle ( m_hServiceStatus );
m_hServiceStatus = NULL; }
::DeleteCriticalSection ( &m_cs ); }
///////////////////////////////////////////////////////////////////////////////////////////////
// service status
///////////////////////////////////////////////////////////////////////////////////////////////
BOOL WmiAdapterService::SetServiceStatus ( DWORD dwState ) { ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService set status\n" L"*************************************************************\n" );
////////////////////////////////////////////////////////////////////////
// smart locking/unlocking
////////////////////////////////////////////////////////////////////////
__Smart_CRITICAL_SECTION scs ( const_cast<LPCRITICAL_SECTION> ( &m_cs ) );
m_ServiceStatus.dwCurrentState = dwState;
try { return ::SetServiceStatus ( m_hServiceStatus, &m_ServiceStatus ); } catch ( ... ) { }
return FALSE; }
SERVICE_STATUS* WmiAdapterService::GetServiceStatus ( void ) const { ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService get status\n" L"*************************************************************\n" );
////////////////////////////////////////////////////////////////////////
// smart locking/unlocking
////////////////////////////////////////////////////////////////////////
__Smart_CRITICAL_SECTION scs ( const_cast<LPCRITICAL_SECTION> ( &m_cs ) );
return const_cast < SERVICE_STATUS* > ( &m_ServiceStatus ); }
/////////////////////////////////////////////////////////////////////////////////////////
// run body :))
/////////////////////////////////////////////////////////////////////////////////////////
extern "C" int WINAPI WinRun ( );
/////////////////////////////////////////////////////////////////////////////////////////
// functions
/////////////////////////////////////////////////////////////////////////////////////////
void WINAPI WmiAdapterService::_ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv) { _Service.ServiceMain(dwArgc, lpszArgv); } void WINAPI WmiAdapterService::_ServiceHandler(DWORD dwOpcode) { _Service.ServiceHandler(dwOpcode); }
/////////////////////////////////////////////////////////////////////////////////////////
// routine
/////////////////////////////////////////////////////////////////////////////////////////
inline void WmiAdapterService::ServiceMain( DWORD, LPWSTR* ) { // Register the control request handler
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
if ( ( m_hServiceStatus = RegisterServiceCtrlHandlerW(g_szAppName, _ServiceHandler) ) == NULL ) { #ifdef __SUPPORT_EVENTVWR
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_OPEN_SCM_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
return; }
SetServiceStatus(SERVICE_START_PENDING);
m_ServiceStatus.dwWin32ExitCode = S_OK; m_ServiceStatus.dwCheckPoint = 0; m_ServiceStatus.dwWaitHint = 0;
try { m_ServiceStatus.dwWin32ExitCode = WinRun ( ); } catch ( ... ) { m_ServiceStatus.dwWin32ExitCode = static_cast < ULONG > ( E_UNEXPECTED ); }
SetServiceStatus ( SERVICE_STOPPED ); }
/////////////////////////////////////////////////////////////////////////////////////////
// handler
/////////////////////////////////////////////////////////////////////////////////////////
inline void WmiAdapterService::ServiceHandler(DWORD dwOpcode) { // auto lock/unlock
__Smart_CRITICAL_SECTION scs ( const_cast<LPCRITICAL_SECTION> ( &m_cs ) );
switch (dwOpcode) { case SERVICE_CONTROL_STOP: { BOOL bStop = FALSE;
if ( ::TryEnterCriticalSection ( &g_csInit ) ) { if ( ( ::InterlockedCompareExchange ( &g_lRefLib, 0, 0 ) == 0 ) && ! _App.InUseGet() ) { bStop = TRUE; }
::LeaveCriticalSection ( &g_csInit ); }
if ( bStop ) { if ( SetServiceStatus ( SERVICE_STOP_PENDING ) ) { if ( _App.m_hKill.GetHANDLE() ) { // kill application
::SetEvent ( _App.m_hKill ); } } } } break; case SERVICE_CONTROL_CONTINUE: { m_ServiceStatus.dwCurrentState = SERVICE_RUNNING; } break; case SERVICE_CONTROL_PAUSE: break; case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: break;
default: { // bad service status :))
} } }
BOOL WmiAdapterService::StartService ( void ) { SERVICE_TABLE_ENTRY st[] = { { const_cast < LPWSTR > ( g_szAppName ), _ServiceMain }, { NULL, NULL } };
if ( ! ::StartServiceCtrlDispatcher ( st ) ) { return FALSE; }
return TRUE; }
/////////////////////////////////////////////////////////////////////////////////////////
// initialization
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT WmiAdapterService::Init ( void ) { ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService initialization\n" L"*************************************************************\n" );
////////////////////////////////////////////////////////////////////////
// smart locking/unlocking
////////////////////////////////////////////////////////////////////////
__Smart_CRITICAL_SECTION scs ( const_cast<LPCRITICAL_SECTION> ( &m_cs ) );
m_hServiceStatus = NULL;
m_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; m_ServiceStatus.dwCurrentState = SERVICE_STOPPED; m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; m_ServiceStatus.dwWin32ExitCode = 0; m_ServiceStatus.dwServiceSpecificExitCode = 0; m_ServiceStatus.dwCheckPoint = 0; m_ServiceStatus.dwWaitHint = 0;
return S_OK; }
/////////////////////////////////////////////////////////////////////////////////////////
// helper if installed
/////////////////////////////////////////////////////////////////////////////////////////
int WmiAdapterService::IsInstalled ( SC_HANDLE hSC ) { int iResult = -1;
if ( hSC ) { __SmartServiceHANDLE hService;
if ( ( hService = ::OpenServiceW ( hSC, g_szAppName, SERVICE_QUERY_CONFIG ) ) != NULL ) { iResult = 1; } else { iResult = 0; } }
return iResult; }
/////////////////////////////////////////////////////////////////////////////////////////
// register service
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT WmiAdapterService::RegisterService ( void ) { HRESULT hr = S_FALSE;
// Unregister service ( could have bad variables )
hr = UnregisterService ( false );
ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService registration\n" L"*************************************************************\n" );
if SUCCEEDED ( hr ) { // SCM has suggested wait a while if we were deleting
if ( hr == S_OK ) { // I do not like it either, but there is no way
// to waitforsingleobject on some kernel object ...
::Sleep ( 3000 ); }
__SmartServiceHANDLE hSC; if ( ( hSC = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ) != NULL ) { // Get the executable file path
WCHAR wszFilePath[_MAX_PATH] = { L'\0' }; ::GetModuleFileNameW(NULL, wszFilePath, _MAX_PATH-1);
__SmartServiceHANDLE hService;
// create service description
LPWSTR wszServiceName = NULL;
try { wszServiceName = LoadStringSystem ( ::GetModuleHandle( NULL ), IDS_NAME ); } catch ( ... ) { if ( wszServiceName ) { delete [] wszServiceName; wszServiceName = NULL; } }
if ( ( hService = ::CreateServiceW ( hSC, g_szAppName,
( wszServiceName != NULL ) ? wszServiceName : L"WMI Performance Adapter",
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, wszFilePath, 0, 0, L"RPCSS\0", 0, 0 ) ) != NULL ) { hr = E_OUTOFMEMORY;
// create service description
LPWSTR wszDescription = NULL;
try { if ( ( wszDescription = LoadStringSystem ( ::GetModuleHandle( NULL ), IDS_DESCRIPTION ) ) != NULL ) { hr = S_OK;
SERVICE_DESCRIPTION sd; sd.lpDescription = wszDescription;
if ( ! ChangeServiceConfig2 ( hService, SERVICE_CONFIG_DESCRIPTION, reinterpret_cast < LPVOID > ( &sd ) ) ) { hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; } } } catch ( ... ) { hr = E_FAIL; }
if ( wszDescription ) { delete [] wszDescription; wszDescription = NULL; } } else { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_CREATE_SC_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_CREATE_SC_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
if ( wszServiceName ) { delete [] wszServiceName; wszServiceName = NULL; }
// unable to create service
hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; }
if ( wszServiceName ) { delete [] wszServiceName; wszServiceName = NULL; } } else { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_OPEN_SCM_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_OPEN_SCM_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
// unable to open service manager
hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; } }
return hr; }
/////////////////////////////////////////////////////////////////////////////////////////
// unregister service
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT WmiAdapterService::UnregisterService ( bool bStatus ) { HRESULT hr = S_FALSE;
ATLTRACE ( L"*************************************************************\n" L"WmiAdapterService unregistartion\n" L"*************************************************************\n" );
__SmartServiceHANDLE hSCM; if ( ( hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ) != NULL ) { if ( IsInstalled ( hSCM ) != 0 ) { BOOL bContinue = TRUE; BOOL bSucceeded= FALSE;
DWORD dwTry = 5; while ( bContinue && dwTry-- ) { __SmartServiceHANDLE hService; if ( ( hService = ::OpenServiceW( hSCM, g_szAppName, SERVICE_QUERY_STATUS | SERVICE_STOP ) ) != NULL) { SERVICE_STATUS s; QueryServiceStatus ( hService, &s );
// we are service what's our status
if( s.dwCurrentState != SERVICE_STOPPED ) { if ( ! ::ControlService( hService, SERVICE_CONTROL_STOP, &s ) ) { DWORD dwError = ERROR_SUCCESS; dwError = ::GetLastError ();
switch ( dwError ) { case ERROR_SERVICE_NOT_ACTIVE: { bContinue = FALSE; bSucceeded= TRUE; } break;
case ERROR_SERVICE_CANNOT_ACCEPT_CTRL: { if ( s.dwCurrentState == SERVICE_STOPPED ) { bContinue = FALSE; bSucceeded= TRUE; } } break;
default: { bContinue = FALSE; hr = HRESULT_FROM_WIN32 ( dwError ); } break; } } else { bSucceeded = TRUE; } } else { bContinue = FALSE; bSucceeded= TRUE; } } else { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_OPEN_SC_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_OPEN_SC_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
// unable to open service
hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; bContinue = FALSE; } }
if ( bSucceeded ) { __SmartServiceHANDLE hService; if ( ( hService = ::OpenServiceW( hSCM, g_szAppName, DELETE ) ) != NULL) { BOOL bDelete = FALSE; if ( ( bDelete = ::DeleteService( hService ) ) == FALSE ) { hr = S_FALSE; } else { hr = S_OK; }
if ( bStatus ) { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_DELETE_SC_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_DELETE_SC_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
} } else { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_OPEN_SC_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_OPEN_SC_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
// unable to open service
hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; bContinue = FALSE; } } } } else { #ifdef __SUPPORT_EVENTVWR
LPWSTR wszError = NULL;
wszError = GetErrorMessageModule ( WMI_ADAPTER_OPEN_SCM_FAIL, _App.m_hResources ); ::MessageBoxW ( ::GetActiveWindow(), ( wszError ) ? wszError : L"error", g_szAppName, MB_OK | MB_ICONERROR );
delete wszError;
try { ((CPerformanceEventLogBase*)_App)->ReportEvent ( EVENTLOG_ERROR_TYPE, 0, WMI_ADAPTER_OPEN_SCM_FAIL, 0, 0, 0, 0 ); } catch ( ... ) { } #endif __SUPPORT_EVENTVWR
// unable to open service manager
hr = FAILED ( HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ? HRESULT_FROM_WIN32 ( ::GetLastError () ) : E_FAIL; }
return hr; }
|