Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

641 lines
11 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
Main.c
Abstract:
This module contains the main startup code for the RNR Sample Service.
Author:
Charles K. Moore (keithmo) 24-July-1994
Revision History:
--*/
#include "rnrsvcp.h"
#pragma hdrstop
//
// Private constants.
//
#define NULL_SERVICE_STATUS_HANDLE ((SERVICE_STATUS_HANDLE)NULL)
#define RNR_START_WAIT_HINT 10000 // ms
#define RNR_STOP_WAIT_HINT 10000 // ms
//
// Private globals.
//
SERVICE_STATUS_HANDLE RnrpStatusHandle = NULL_SERVICE_STATUS_HANDLE;
//
// Private prototypes.
//
VOID
RnrpServiceMain(
DWORD cArgs,
LPTSTR * pArgs
);
APIERR
RnrpUpdateServiceStatus(
DWORD State,
DWORD Win32ExitCode,
DWORD CheckPoint,
DWORD WaitHint
);
APIERR
RnrpReportServiceStatus(
VOID
);
VOID
RnrpServiceCtrlHandler(
DWORD OpCode
);
APIERR
RnrpInitializeService(
VOID
);
VOID
RnrpTerminateService(
VOID
);
VOID
RnrpInterrogateService(
VOID
);
VOID
RnrpStopService(
VOID
);
VOID
RnrpPauseService(
VOID
);
VOID
RnrpContinueService(
VOID
);
//
// Public functions.
//
VOID
_CRTAPI1
main(
VOID
)
/*++
Routine Description:
Entrypoint for the RNR Sample Service.
Notes:
Rather than return from this function, it is more appropriate to
call ExitProcess().
--*/
{
#if defined(BUILD_STANDALONE_EXE)
RnrpServiceMain( 0, NULL );
#else // !BUILD_STANDALONE_EXE
//
// The dispatch table for all services contained in this
// process. For this sample, there is only a single service
// in the process.
//
SERVICE_TABLE_ENTRY Dispatch[] =
{
{ RNR_SERVICE_NAME, RnrpServiceMain },
{ NULL, NULL }
};
//
// Connect to the service controller. This will block until
// the service terminates.
//
if( !StartServiceCtrlDispatcher( Dispatch ) ) {
//
// If StartServiceCtrlDispatcher fails, there's not much
// we can do.
//
}
#endif // BUILD_STANDALONE_EXE
//
// Cleanup & exit.
//
ExitProcess( 0 );
} // main
//
// Private functions.
//
APIERR
RnrpUpdateServiceStatus(
DWORD State,
DWORD Win32ExitCode,
DWORD CheckPoint,
DWORD WaitHint
)
/*++
Routine Description:
Updates the local copy of the service's status, then reports
the status to the Service Controller.
Arguments:
State - The new service state.
Win32ExitCode - The service's exit code.
CheckPoint - The current checkpoint for lengthy state transitions.
WaitHint - Wait hint for lengthy state transitions.
Returns:
APIERR - NO_ERROR if successful, Win32 error code if not.
--*/
{
//
// Update the service status structure.
//
RnrServiceStatus.dwCurrentState = State;
RnrServiceStatus.dwWin32ExitCode = Win32ExitCode;
RnrServiceStatus.dwCheckPoint = CheckPoint;
RnrServiceStatus.dwWaitHint = WaitHint;
//
// Let RnrpReportServiceStatus do the dirty work.
//
return RnrpReportServiceStatus();
} // RnrpUpdateServiceStatus
APIERR
RnrpReportServiceStatus(
VOID
)
/*++
Routine Description:
Basically just a wrapper around SetServiceStatus.
Returns:
APIERR - NO_ERROR if successful, Win32 error code if not.
--*/
{
#if !defined(BUILD_STANDALONE_EXE)
//
// Report the status to the Service Controller.
//
if( !SetServiceStatus( RnrpStatusHandle, &RnrServiceStatus ) ) {
return GetLastError();
}
#endif // !BUILD_STANDALONE_EXE
//
// Success!
//
return NO_ERROR;
} // RnrpReportServiceStatus
VOID
RnrpServiceMain(
DWORD cArgs,
LPTSTR * pArgs
)
/*++
Routine Description:
This is the "real" entrypoint for the service. When the Service
Controller dispatcher is requested to start a service, it creates
a thread that will begin executing this routine.
Arguments:
cArgs - Number of command-line arguments to this service.
pArgs - Pointers to the command-line arguments.
Notes:
Rather than return from this function, it is more appropriate
to call ExitThread();
--*/
{
APIERR err = NO_ERROR;
//
// Initialize the service status structure.
//
RnrServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
RnrServiceStatus.dwCurrentState = SERVICE_STOPPED;
RnrServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_PAUSE_CONTINUE;
RnrServiceStatus.dwWin32ExitCode = NO_ERROR;
RnrServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
RnrServiceStatus.dwCheckPoint = 0;
RnrServiceStatus.dwWaitHint = 0;
#if !defined(BUILD_STANDALONE_EXE)
//
// Register the Control Handler routine.
//
RnrpStatusHandle = RegisterServiceCtrlHandler( RNR_SERVICE_NAME,
RnrpServiceCtrlHandler );
if( RnrpStatusHandle == NULL_SERVICE_STATUS_HANDLE ) {
err = GetLastError();
goto Cleanup;
}
#endif // !BUILD_STANDALONE_EXE
//
// Update the service status.
//
err = RnrpUpdateServiceStatus( SERVICE_START_PENDING,
NO_ERROR,
1,
RNR_START_WAIT_HINT );
if( err != NO_ERROR ) {
goto Cleanup;
}
//
// Initialize the various service components.
//
err = RnrpInitializeService();
if( err != NO_ERROR ) {
goto Cleanup;
}
//
// Update the service status.
//
err = RnrpUpdateServiceStatus( SERVICE_RUNNING,
NO_ERROR,
0,
0 );
if( err != NO_ERROR ) {
RNR_LOG0( RNR_EVENT_SYSTEM_CALL_FAILED,
err );
goto Cleanup;
}
//
// Wait for the shutdown event.
//
WaitForSingleObject( RnrShutdownEvent,
INFINITE );
//
// Stop time. Tell the Service Controller that we're stopping,
// then terminate the various service components.
//
RnrpUpdateServiceStatus( SERVICE_STOP_PENDING,
0,
0,
RNR_STOP_WAIT_HINT );
RnrpTerminateService();
Cleanup:
//
// If we managed to actually connect to the Service Controller,
// then tell it that we're stopped.
//
if( RnrpStatusHandle != NULL_SERVICE_STATUS_HANDLE ) {
RnrpUpdateServiceStatus( SERVICE_STOPPED,
err,
0,
0 );
}
ExitThread( 0 );
} // RnrpServiceMain
VOID
RnrpServiceCtrlHandler (
DWORD OpCode
)
/*++
Routine Description:
This function receives control requests from the Service
Controller.
Arguments:
OpCode - Indicates the requested control operation. This
will be one of the SERVICE_CONTROL_* manifests.
Notes:
If an operation (especially SERVICE_CONTROL_STOP) is particularly
lengthy, then this routine should report a STOP_PENDING status
and create a worker thread to do the dirty work. The worker thread
would then be responsible for reporting timely wait hints and the
final SERVICE_STOPPED status.
--*/
{
//
// Interpret the opcode.
//
switch( OpCode )
{
case SERVICE_CONTROL_INTERROGATE :
RnrpInterrogateService();
break;
case SERVICE_CONTROL_STOP :
RnrpStopService();
break;
case SERVICE_CONTROL_PAUSE :
RnrpPauseService();
break;
case SERVICE_CONTROL_CONTINUE :
RnrpContinueService();
break;
default :
break;
}
//
// Report the current service status back to the Service
// Controller. The workers called to implement the OpCodes
// should set the RnrServiceStatus.dwCurrentState field if
// the service status changed.
//
RnrpReportServiceStatus();
} // RnrpServiceCtrlHandler
APIERR
RnrpInitializeService(
VOID
)
/*++
Routine Description:
Initializes the various RNR Sample Service components.
Returns:
APIERR - NO_ERROR if successful, Win32 error code if not.
--*/
{
APIERR err;
//
// Initialize various components.
//
if( ( err = RnrGlobalsInitialize() ) ||
( err = RnrLogInitialize() ) ||
( err = RnrClientInitialize() ) ||
( err = RnrConnectInitialize() ) ) {
return err;
}
//
// Success!
//
return NO_ERROR;
} // InitializeService
VOID
RnrpTerminateService(
VOID
)
/*++
Routine Description:
Terminates the various RNR Sample Service components.
--*/
{
//
// Indicate that we're shutting down.
//
RnrShutdownInProgress = TRUE;
//
// Terminate the various components.
//
RnrClientTerminate();
RnrConnectTerminate();
RnrLogTerminate();
RnrGlobalsTerminate();
} // TerminateService
VOID
RnrpInterrogateService(
VOID
)
/*++
Routine Description:
This function interrogates the service status. Actually,
nothing needs to be done here; the status is always updated
after a service control operation.
--*/
{
//
// This space intentionally left blank.
//
} // RnrpInterrogateService
VOID
RnrpStopService(
VOID
)
/*++
Routine Description:
This function stops the service. If the stop cannot be performed
in a timely manner, a worker thread must be created to do the
actual dirty work.
Notes:
The final action of this function should be to signal the
shutdown event. This will release the main thread.
--*/
{
//
// Remember that we're stopping.
//
RnrServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
//
// Release the main thread.
//
SetEvent( RnrShutdownEvent );
} // RnrpStopService
VOID
RnrpPauseService(
VOID
)
/*++
Routine Description:
This function pauses the service. When the service is paused,
no new client connections will be accepted, but existing
connections are not affected.
--*/
{
//
// Remember that we're in the paused state.
//
RnrServiceStatus.dwCurrentState = SERVICE_PAUSED;
} // RnrpPauseService
VOID
RnrpContinueService(
VOID
)
/*++
Routine Description:
This function continues the paused service. This will return
the service to the running state.
--*/
{
//
// Remember that we're in the running state.
//
RnrServiceStatus.dwCurrentState = SERVICE_RUNNING;
} // RnrpContinueService