292 lines
11 KiB
C
292 lines
11 KiB
C
|
/*************************************************************************
|
||
|
* Microsoft Windows NT *
|
||
|
* *
|
||
|
* Copyright(c) Microsoft Corp., 1994 *
|
||
|
* *
|
||
|
* Revision History: *
|
||
|
* *
|
||
|
* Jan. 22,94 Koti Created *
|
||
|
* *
|
||
|
* Description: *
|
||
|
* *
|
||
|
* This file contains functions that enable LPD service to interact *
|
||
|
* with the Service Controller *
|
||
|
* *
|
||
|
*************************************************************************/
|
||
|
|
||
|
|
||
|
#include "lpd.h"
|
||
|
#include <tcpsvcs.h>
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* *
|
||
|
* Service Entry(): *
|
||
|
* Entry point called by the Service Controller. This function returns *
|
||
|
* only when the service is stopped. *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* Nothing *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* dwArgc (IN): number of arguments passed in *
|
||
|
* lpszArgv (IN): arguments to this function (array of null-terminated *
|
||
|
* strings). First arg is the name of the service and the *
|
||
|
* remaining are the ones passed by the calling process. *
|
||
|
* (e.g. net start lpd /p:xyz) *
|
||
|
* *
|
||
|
* History: *
|
||
|
* Jan.22, 94 Koti Created *
|
||
|
* *
|
||
|
*****************************************************************************/
|
||
|
|
||
|
VOID ServiceEntry( DWORD dwArgc, LPTSTR *lpszArgv,
|
||
|
PTCPSVCS_GLOBAL_DATA pGlobalData )
|
||
|
{
|
||
|
|
||
|
DWORD dwErrcode;
|
||
|
|
||
|
DBG_TRACEIN( "ServiceEntry" );
|
||
|
|
||
|
// Register our control handler
|
||
|
|
||
|
hSvcHandleGLB = RegisterServiceCtrlHandler( LPD_SERVICE_NAME,
|
||
|
LPDCntrlHandler );
|
||
|
|
||
|
if ( hSvcHandleGLB == 0 )
|
||
|
{
|
||
|
LOGIT(( "ServiceEntry: RegisterServiceCtrlHandler() failed %d\n",
|
||
|
GetLastError() ));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Initialize events, objects; event logging etc.
|
||
|
|
||
|
if ( !InitStuff() ){
|
||
|
LPD_DEBUG( "ServiceEntry: InitStuff() failed\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Tell the Service Controller that we are starting
|
||
|
|
||
|
if (!TellSrvcController( SERVICE_START_PENDING, NO_ERROR, 1, LPD_WAIT_HINT ))
|
||
|
{
|
||
|
LPD_DEBUG( "ServiceEntry: TellSrvcController(SERVICE_START_PENDING)"
|
||
|
" failed\n" );
|
||
|
EndLogging();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Ok, this is where we start the service (and keep it running)
|
||
|
|
||
|
dwErrcode = StartLPD( dwArgc, lpszArgv );
|
||
|
|
||
|
if ( dwErrcode != NO_ERROR )
|
||
|
{
|
||
|
LOGIT(( "ServiceEntry: StartLPD() failed %d\n", GetLastError() ));
|
||
|
LpdReportEvent( LPDLOG_LPD_DIDNT_START, 0, NULL, dwErrcode );
|
||
|
EndLogging();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Tell the Service Controller that we are up and running
|
||
|
// If we have trouble telling srv controller, stop LPD and return
|
||
|
|
||
|
if ( !TellSrvcController( SERVICE_RUNNING, NO_ERROR, 0, 0 ) )
|
||
|
{
|
||
|
LPD_DEBUG( "TellSrvcController(): stopping LPD and quitting!\n" );
|
||
|
StopLPD();
|
||
|
TellSrvcController( SERVICE_STOPPED, NO_ERROR, 0, 0 );
|
||
|
EndLogging();
|
||
|
DBG_TRACEOUT( "ServiceEntry" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LPD_DEBUG( "Started LpdSvc successfully\n" );
|
||
|
|
||
|
LpdReportEvent( LPDLOG_LPD_STARTED, 0, NULL, 0 );
|
||
|
|
||
|
|
||
|
// wait here until SetEvent is invoked (i.e. LPD is stopped or shutdown)
|
||
|
|
||
|
WaitForSingleObject( hEventShutdownGLB, INFINITE );
|
||
|
|
||
|
|
||
|
// Tell the Service Controller that we are going to stop now!
|
||
|
|
||
|
if ( !TellSrvcController( SERVICE_STOP_PENDING, NO_ERROR, 1, LPD_WAIT_HINT ) )
|
||
|
{
|
||
|
LPD_DEBUG( "TellSrvcController( SERVICE_STOP_PENDING, .. ) failed\n" );
|
||
|
}
|
||
|
|
||
|
// Stop the LPD service
|
||
|
|
||
|
StopLPD();
|
||
|
FreeStrings();
|
||
|
DBG_DUMPLEAKS();
|
||
|
LPD_DEBUG( "ServiceEntry: Stopped LpdSvc successfully\n" );
|
||
|
LpdReportEvent( LPDLOG_LPD_STOPPED, 0, NULL, 0 );
|
||
|
EndLogging();
|
||
|
DBG_UNINIT();
|
||
|
|
||
|
#ifdef DBG
|
||
|
if( LogFile ){
|
||
|
stoplogging( LogFile );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// if we can still connect, tell the Service Controller that we are gone!
|
||
|
|
||
|
if ( hSvcHandleGLB != 0 )
|
||
|
{
|
||
|
TellSrvcController( SERVICE_STOPPED, NO_ERROR, 0, 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
} // end ServiceEntry()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* *
|
||
|
* TellSrvcController(): *
|
||
|
* This function updates the status of our service (LPD) with the Service *
|
||
|
* Controller. *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* TRUE if everything went ok *
|
||
|
* FALSE if something went wrong *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* The four parameters correspond to the 2nd, 4th, 6th and 7th parameters *
|
||
|
* respectively of the SERVICE_STATUS structure passed to the *
|
||
|
* SetServiceStatus call. *
|
||
|
* *
|
||
|
* History: *
|
||
|
* Jan.22, 94 Koti Created *
|
||
|
* *
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL TellSrvcController( DWORD dwCurrentState, DWORD dwWin32ExitCode,
|
||
|
DWORD dwCheckPoint, DWORD dwWaitHint)
|
||
|
{
|
||
|
|
||
|
BOOL fResult;
|
||
|
|
||
|
LOGIT(( "Entering TellSrvcController %d\n", dwCurrentState ));
|
||
|
|
||
|
|
||
|
// initialize the service status structure
|
||
|
|
||
|
ssSvcStatusGLB.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||
|
ssSvcStatusGLB.dwCurrentState = dwCurrentState;
|
||
|
ssSvcStatusGLB.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
||
|
SERVICE_ACCEPT_PAUSE_CONTINUE |
|
||
|
SERVICE_ACCEPT_SHUTDOWN;
|
||
|
ssSvcStatusGLB.dwWin32ExitCode = dwWin32ExitCode;
|
||
|
ssSvcStatusGLB.dwServiceSpecificExitCode = NO_ERROR;
|
||
|
ssSvcStatusGLB.dwCheckPoint = dwCheckPoint;
|
||
|
ssSvcStatusGLB.dwWaitHint = dwWaitHint;
|
||
|
|
||
|
|
||
|
// Tell the Service Controller what our status is
|
||
|
|
||
|
fResult = SetServiceStatus( hSvcHandleGLB, &ssSvcStatusGLB );
|
||
|
|
||
|
|
||
|
DBG_TRACEOUT( "TellSrvcController" );
|
||
|
|
||
|
return (fResult);
|
||
|
|
||
|
} // end TellSrvcController()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* *
|
||
|
* LPDCntrlHandler(): *
|
||
|
* This function gets called (indirectly by the Service Controller) *
|
||
|
* whenever there is a control request for the LPD service. Depending on *
|
||
|
* the control request, this function takes appropriate action. *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* Nothing *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* dwControl (IN): The requested control code. *
|
||
|
* *
|
||
|
* History: *
|
||
|
* Jan.22, 94 Koti Created *
|
||
|
* *
|
||
|
*****************************************************************************/
|
||
|
|
||
|
VOID LPDCntrlHandler( DWORD dwControl )
|
||
|
{
|
||
|
|
||
|
BOOL fMustStopSrvc=FALSE;
|
||
|
time_t now;
|
||
|
|
||
|
time( &now );
|
||
|
LOGIT(("Entering LPDCntrlHandler %d at %s", dwControl, ctime(&now) ));
|
||
|
|
||
|
switch( dwControl )
|
||
|
{
|
||
|
// Treat _STOP and _SHUTDOWN in the same manner
|
||
|
case SERVICE_CONTROL_STOP:
|
||
|
LOGIT(("LPDCntrlHandler: SERVICE_CONTROL_STOP\n"));
|
||
|
|
||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||
|
LOGIT(("LPDCntrlHandler: SERVICE_CONTROL_SHUTDOWN\n"));
|
||
|
ssSvcStatusGLB.dwCurrentState = SERVICE_STOP_PENDING;
|
||
|
ssSvcStatusGLB.dwCheckPoint = 0;
|
||
|
|
||
|
fMustStopSrvc = TRUE;
|
||
|
break;
|
||
|
|
||
|
// don't accept any new connections: the service is now PAUSED
|
||
|
case SERVICE_CONTROL_PAUSE:
|
||
|
LOGIT(("LPDCntrlHandler: SERVICE_CONTROL_PAUSE\n"));
|
||
|
ssSvcStatusGLB.dwCurrentState = SERVICE_PAUSED;
|
||
|
break;
|
||
|
|
||
|
// the service was paused earlier: continue it now
|
||
|
case SERVICE_CONTROL_CONTINUE:
|
||
|
LOGIT(("LPDCntrlHandler: SERVICE_CONTROL_CONTINUE\n"));
|
||
|
ssSvcStatusGLB.dwCurrentState = SERVICE_RUNNING;
|
||
|
break;
|
||
|
|
||
|
// we don't do anything with this
|
||
|
case SERVICE_CONTROL_INTERROGATE:
|
||
|
LOGIT(("LPDCntrlHandler: SERVICE_CONTROL_INTERROGATE\n"));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
LOGIT(("Unknown control word received in LPDCntrlHandler\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Update the status (even if it didn't change!) with Service Controller
|
||
|
|
||
|
SetServiceStatus( hSvcHandleGLB, &ssSvcStatusGLB );
|
||
|
|
||
|
|
||
|
// If we must stop or shutdown the service, set our shutdown event
|
||
|
|
||
|
if ( fMustStopSrvc )
|
||
|
{
|
||
|
fShuttingDownGLB = 1;
|
||
|
SetEvent( hEventShutdownGLB );
|
||
|
LOGIT(("LPDCntrlHandler: fShuttingDownGLB=%d\n", fShuttingDownGLB ));
|
||
|
}
|
||
|
|
||
|
DBG_TRACEOUT( "LPDCntrlHandler" );
|
||
|
|
||
|
} // end LPDCntrlHandler()
|