/************************************************************************* * 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 /***************************************************************************** * * * 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()