windows-nt/Source/XPSP1/NT/admin/admt/common/commonlib/tservice.cpp
2020-09-26 16:20:57 +08:00

296 lines
7.8 KiB
C++

//#pragma title( "TService.cpp - SCM interface for MCS service" )
/*
Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
===============================================================================
Module - TService.cpp
System - Common
Author - Rich Denham
Created - 1997-08-17
Description - Service Control Manager interface for MCS service
Updates -
===============================================================================
*/
#include <windows.h>
#include <stdio.h>
#include "TService.hpp"
///////////////////////////////////////////////////////////////////////////////
// Private data declarations
///////////////////////////////////////////////////////////////////////////////
#define WAIT_HINT_SECONDS (10)
#define WAIT_HINT_MILLISECONDS (WAIT_HINT_SECONDS*1000)
static
TCHAR * gNameService;
static
SERVICE_STATUS gServiceStatus;
static
SERVICE_STATUS_HANDLE ghServiceStatus;
static
HANDLE ghServDoneEvent=INVALID_HANDLE_VALUE;
static
DWORD gArgc;
static
TCHAR ** gArgv;
static
TScmEpRc grcScmEp=TScmEpRc_Unknown; // TScmEp return code
///////////////////////////////////////////////////////////////////////////////
// Private function prototypes
///////////////////////////////////////////////////////////////////////////////
static
void
TScmServiceMain(
DWORD argc ,// in -number of arguments
TCHAR ** argv // in -string argument array
);
static
void
TScmServiceCtrl(
DWORD dwCtrlCode
);
static
DWORD WINAPI // ret-OS return code
TScmServiceWorker(
void * notUsed // i/o-not used
);
static
BOOL // ret-TRUE if successful
TScmReportStatusToSCMgr(
DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint
);
///////////////////////////////////////////////////////////////////////////////
// Entry point from caller's 'main' function
///////////////////////////////////////////////////////////////////////////////
TScmEpRc // TScmEp return code
TScmEp(
int argc ,// in -argument count
char const ** argv ,// in -argument array
TCHAR * nameService // in -name of service
)
{
int argn; // argument number
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ nameService, (LPSERVICE_MAIN_FUNCTION) TScmServiceMain },
{ NULL, NULL }
};
gNameService = nameService;
grcScmEp = TScmEpRc_Unknown;
for ( argn = 1;
argn < argc;
argn++ )
{
if ( !UScmCmdLineArgs( argv[argn] ) )
{
grcScmEp = TScmEpRc_InvArgCli;
}
}
if ( grcScmEp == TScmEpRc_Unknown )
{
if ( UScmForceCli() || !StartServiceCtrlDispatcher( dispatchTable ) )
{
// UScmEp( FALSE );
UScmEp();
grcScmEp = TScmEpRc_OkCli;
}
else
{
grcScmEp = TScmEpRc_OkSrv;
}
}
return grcScmEp;
}
///////////////////////////////////////////////////////////////////////////////
// Mainline for service
///////////////////////////////////////////////////////////////////////////////
static
void
TScmServiceMain(
DWORD argc ,// in -number of arguments
TCHAR ** argv // in -string argument array
)
{
DWORD dwWait;
DWORD idThread;
HANDLE hThread=INVALID_HANDLE_VALUE;
gArgc = argc;
gArgv = argv;
do // once or until break
{
ghServiceStatus = RegisterServiceCtrlHandler(
gNameService,
(LPHANDLER_FUNCTION) TScmServiceCtrl );
if ( !ghServiceStatus )
{
break;
}
gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gServiceStatus.dwServiceSpecificExitCode = 0;
if ( !TScmReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 1,
WAIT_HINT_MILLISECONDS ) )
{
break;
}
ghServDoneEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( ghServDoneEvent == INVALID_HANDLE_VALUE )
{
break;
}
if ( !TScmReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 2,
WAIT_HINT_MILLISECONDS ) )
{
break;
}
hThread = CreateThread( NULL, 0, TScmServiceWorker, NULL, 0, &idThread );
if ( hThread == INVALID_HANDLE_VALUE )
{
break;
}
if ( !TScmReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0, 0 ) )
{
break;
}
dwWait = WaitForSingleObject( ghServDoneEvent, INFINITE );
} while ( FALSE );
if ( hThread != INVALID_HANDLE_VALUE )
{
CloseHandle( hThread );
hThread = INVALID_HANDLE_VALUE;
}
if ( ghServDoneEvent != INVALID_HANDLE_VALUE )
{
CloseHandle( ghServDoneEvent );
ghServDoneEvent = INVALID_HANDLE_VALUE;
}
if ( ghServiceStatus )
{
TScmReportStatusToSCMgr( SERVICE_STOPPED, 0, 0, 0 );
}
}
///////////////////////////////////////////////////////////////////////////////
// Service control handler
///////////////////////////////////////////////////////////////////////////////
static
void
TScmServiceCtrl(
DWORD dwCtrlCode
)
{
DWORD dwState = SERVICE_RUNNING;
switch ( dwCtrlCode )
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
dwState = SERVICE_STOP_PENDING;
TScmReportStatusToSCMgr( SERVICE_STOP_PENDING, NO_ERROR, 1,
WAIT_HINT_MILLISECONDS );
SetEvent( ghServDoneEvent );
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
TScmReportStatusToSCMgr( dwState, NO_ERROR, 0, 0 );
}
///////////////////////////////////////////////////////////////////////////////
// Service worker thread
///////////////////////////////////////////////////////////////////////////////
static
DWORD WINAPI // ret-OS return code
TScmServiceWorker(
void * notUsed // i/o-not used
)
{
for ( DWORD i = 1;
i < gArgc;
i++ )
{
if ( !UScmCmdLineArgs( gArgv[i] ) )
{
grcScmEp = TScmEpRc_InvArgSrv;
}
}
if ( grcScmEp != TScmEpRc_InvArgSrv )
{
// UScmEp( TRUE );
UScmEp();
}
SetEvent( ghServDoneEvent );
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// Report status to Service Control Manager
///////////////////////////////////////////////////////////////////////////////
static
BOOL // ret-TRUE if successful
TScmReportStatusToSCMgr(
DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint
)
{
BOOL bRc; // boolean return code
if ( dwCurrentState == SERVICE_START_PENDING )
{
gServiceStatus.dwControlsAccepted = 0;
}
else
{
gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
gServiceStatus.dwCurrentState = dwCurrentState;
gServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
gServiceStatus.dwCheckPoint = dwCheckPoint;
gServiceStatus.dwWaitHint = dwWaitHint;
bRc = SetServiceStatus( ghServiceStatus, &gServiceStatus );
if ( !bRc )
{
SetEvent( ghServDoneEvent );
}
return bRc;
}
// TService.cpp - end of file