|
|
/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1995 **/ /**********************************************************************/
/*
main.cxx
This module contains the main startup code for a Gibraltar Service. Since gibraltar service startup is a common operation, this source code will be shared with all services.
To do this, you only need to set certain #defines to your specific service.
See %MSNROOT%\apps\mail\[pop3,smtp]\server\main.cxx for examples.
FILE HISTORY: KeithMo 07-Mar-1993 Created. rkamicar 20-Dec-1995 Modified for sharing */
//
// Private globals.
//
DEFINE_TSVC_INFO_INTERFACE(); DECLARE_DEBUG_PRINTS_OBJECT( ); DECLARE_DEBUG_VARIABLE( );
#define INITIALIZE_IPC 0x00000001
#define INITIALIZE_SOCKETS 0x00000002
#define INITIALIZE_ACCESS 0x00000004
#define INITIALIZE_SERVICE 0x00000008
#define INITIALIZE_CONNECTIONS 0x00000010
#define INITIALIZE_DISCOVERY 0x00000020
DWORD GlobalInitializeStatus = 0; BOOL ServiceBooted = FALSE;
//
// Global startup named event
//
HANDLE ghStartupEvent = INVALID_HANDLE_VALUE;
//
//
// Shared TCPSVCS.EXE data
//
PTCPSVCS_GLOBAL_DATA pTcpsvcsGlobalData;
//
// Private prototypes.
//
APIERR InitializeService( LPVOID pContext ); APIERR TerminateService( LPVOID pContext );
//+---------------------------------------------------------------------------
//
// Function:
//
// DllEntryPoint
//
// Synopsis:
// Arguments:
// Returns:
// See Win32 SDK
//
// History:
//
// Richard Kamicar (rkamicar) 5 January 1996
//
// Notes:
//
// If we find we need this per service, we can move it out of here..
//
//----------------------------------------------------------------------------
BOOL WINAPI DllEntryPoint(HINSTANCE hInst, DWORD dwReason, LPVOID lpvContext) { switch (dwReason) { case DLL_PROCESS_ATTACH:
//
// To help performance, cancel thread attach and detach notifications
//
DisableThreadLibraryCalls((HMODULE) hInst);
break;
case DLL_PROCESS_DETACH:
if( ghStartupEvent != INVALID_HANDLE_VALUE ) { _VERIFY( CloseHandle( ghStartupEvent ) ); }
break;
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break; } return TRUE; }
BOOL WINAPI DllMain (HANDLE hInst, ULONG dwReason, LPVOID lpvReserve) { return DllEntryPoint((HINSTANCE) hInst, dwReason, lpvReserve); }
//
// Public functions.
//
/*******************************************************************
NAME: ServiceEntry
SYNOPSIS: 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.
ENTRY: cArgs - Number of command line arguments to this service.
pArgs - Pointers to the command line arguments.
pGlobalData - Points to global data shared amongst all services that live in TCPSVCS.EXE.
EXIT: Does not return until service is stopped.
HISTORY: KeithMo 07-Mar-1993 Created. KeithMo 07-Jan-1994 Modified for use as a DLL.
********************************************************************/ VOID ServiceEntry( DWORD cArgs, LPWSTR pArgs[], PTCPSVCS_GLOBAL_DATA pGlobalData ) { APIERR err = NO_ERROR;
InitAsyncTrace(); TraceQuietEnter( "ServiceEntry");
//
// Save the global data pointer.
//
pTcpsvcsGlobalData = pGlobalData;
//
// Initialize the service status structure.
//
DebugTrace( 0, "new TSVC_INFO( %s)", XXX_SERVICE_NAME);
g_pTsvcInfo = new TSVC_INFO( XXX_SERVICE_NAME, XXX_MODULE_NAME, XXX_PARAMETERS_KEY_A, XXX_ANONYMOUS_SECRET_W, XXX_ROOT_SECRET_W, XXX_INET, InitializeService, TerminateService );
//
// If we couldn't allocate memory for the service info struct, then the
// machine is really hosed -- we can't even log..
//
if (!g_pTsvcInfo || !g_pTsvcInfo->IsValid()) { FatalTrace( 0, "new TSVC_INFO( %s) failed: %x", XXX_SERVICE_NAME, g_pTsvcInfo); if (g_pTsvcInfo != NULL) { delete g_pTsvcInfo; g_pTsvcInfo = NULL; } goto out; } //
// save the global pointer for rpc thread
//
g_pTsvcInfo->SetTcpsvcsGlobalData( pTcpsvcsGlobalData); //
// This blocks until the service is shutdown
//
err = g_pTsvcInfo->StartServiceOperation( SERVICE_CTRL_HANDLER() );
delete g_pTsvcInfo; g_pTsvcInfo = NULL;
out: TermAsyncTrace( );
} // ServiceEntry
//
// Private functions.
//
/*******************************************************************
NAME: InitializeService
SYNOPSIS: Initializes the various W3 Service components.
EXIT: If successful, then every component has been successfully initialized.
RETURNS: APIERR - NO_ERROR if successful, otherwise a Win32 status code.
HISTORY: KeithMo 07-Mar-1993 Created.
********************************************************************/ APIERR InitializeService( LPVOID pContext ) { APIERR err; LPTSVC_INFO ptsi = (LPTSVC_INFO ) pContext;
TraceFunctEnter("InitializeService");
//
// Create a startup named event. If this already exists, refuse to boot !
//
HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, XXX_NAMED_EVENT); if( !hEvent || GetLastError() != 0 ) {
if( hEvent) { _VERIFY( CloseHandle( hEvent ) ); }
g_pTsvcInfo->LogEvent( XXX_BOOT_ERROR, 0, (const CHAR **)NULL, ERROR_SERVICE_ALREADY_RUNNING );
return ERROR_SERVICE_ALREADY_RUNNING ; }
// set the global startup event. this is closed when our DLL_PROCESS_DETACH
ghStartupEvent = hEvent; ServiceBooted = TRUE;
g_pTsvcInfo->LogEvent( XXX_EVENT_SERVICE_STARTED, 0, (const CHAR **)NULL, 0 );
//
// Initialize various components. The ordering of the
// components is somewhat limited. Globals should be
// initialized first, then the event logger. After
// the event logger is initialized, the other components
// may be initialized in any order with one exception.
// InitializeSockets must be the last initialization
// routine called. It kicks off the main socket connection
// thread.
//
if(( err = InitializeGlobals())) { FatalTrace( 0, "InitializeGlobals failed, err=%d.", err); TraceFunctLeave(); return err; }
if( (err = ptsi->InitializeIpc( (UCHAR *) "ncacn_np", (UCHAR *) XXX_NAMED_PIPE, XXX_ServerIfHandle)) != NO_ERROR) { FatalTrace( 0, "InitializeIpc failed, err=%d.", err); TraceFunctLeave(); return err; }
GlobalInitializeStatus |= INITIALIZE_IPC;
if((err = g_pTsvcInfo->InitializeDiscovery( NULL))) { FatalTrace( 0, "InitializeDiscovery failed, err=%d.", err); TraceFunctLeave(); return err; }
GlobalInitializeStatus |= INITIALIZE_DISCOVERY;
if((err = InitializeSockets())) { FatalTrace( 0, "InitializeSockets failed, err=%d.", err); TraceFunctLeave(); return err; }
GlobalInitializeStatus |= INITIALIZE_SOCKETS; //
// InitializeConnection
//
if ( !g_pTsvcInfo->InitializeConnections( &XXX_OnConnect, &XXX_OnConnectEx, &XXX_Completion, XXX_SECURE_PORT, 0 )) {
err = GetLastError(); g_pTsvcInfo->LogEvent( XXX_EVENT_CANNOT_INITIALIZE_WINSOCK, 0, (const CHAR **)NULL, err );
ErrorTrace(0,"InitializeConnections failed, error %d",err ); return err; }
GlobalInitializeStatus |= INITIALIZE_CONNECTIONS;
//
// Success!
//
TraceFunctLeave(); return NO_ERROR;
} // InitializeService
/*******************************************************************
NAME: TerminateService
SYNOPSIS: Terminates the various W3 Service components.
EXIT: If successful, then every component has been successfully terminated.
HISTORY: KeithMo 07-Mar-1993 Created.
********************************************************************/ APIERR TerminateService( LPVOID pContext ) { LPTSVC_INFO ptsi = (LPTSVC_INFO ) pContext; DWORD err;
TraceFunctEnter("TerminateService");
if(!ServiceBooted) { return NO_ERROR; }
ServiceBooted = FALSE;
_ASSERT(ptsi == g_pTsvcInfo); //
// Components should be terminated in reverse
// initialization order.
//
//
// must happen after CleanupConnections so no new conns accepted
//
if ( GlobalInitializeStatus & INITIALIZE_CONNECTIONS) { g_pTsvcInfo->CleanupConnections(); }
if (XXX_g_Config != NULL) { XXX_g_Config->DisconnectAllConnections(); } if ( GlobalInitializeStatus & INITIALIZE_SOCKETS) { TerminateSockets(); }
if ( GlobalInitializeStatus & INITIALIZE_DISCOVERY) { if ( (err = ptsi->TerminateDiscovery()) != NO_ERROR) { ErrorTrace(0, "TerminateDiscovery() failed. Error = %u", err); } }
if ( GlobalInitializeStatus & INITIALIZE_IPC) { if ( (err = ptsi->CleanupIpc( XXX_ServerIfHandle)) != NO_ERROR) { ErrorTrace(0, "CleanupIpc() failed. Error = %u", err); } }
TerminateGlobals();
g_pTsvcInfo->LogEvent( XXX_EVENT_SERVICE_STOPPED, 0, (const CHAR **)NULL, 0 );
TraceFunctLeave(); return NO_ERROR;
} // TerminateService
|