Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

431 lines
11 KiB

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